Files
pvaClient/src/pv/pvaClientMultiChannel.h

618 lines
20 KiB
C++

/* pvaClientMultiChannel.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2015.02
*/
#ifndef PVACLIENTMULTICHANNEL_H
#define PVACLIENTMULTICHANNEL_H
#ifdef epicsExportSharedSymbols
# define pvaClientMultiChannelEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/ntmultiChannel.h>
#include <pv/createRequest.h>
#ifdef pvaClientMultiChannelEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef pvaClientMultiChannelEpicsExportSharedSymbols
#endif
#include <pv/pvaClient.h>
namespace epics { namespace pvaClient {
class PvaClientMultiChannel;
typedef std::tr1::shared_ptr<PvaClientMultiChannel> PvaClientMultiChannelPtr;
class PvaClientMultiGetDouble;
typedef std::tr1::shared_ptr<PvaClientMultiGetDouble> PvaClientMultiGetDoublePtr;
class PvaClientMultiPutDouble;
typedef std::tr1::shared_ptr<PvaClientMultiPutDouble> PvaClientMultiPutDoublePtr;
class PvaClientMultiMonitorDouble;
typedef std::tr1::shared_ptr<PvaClientMultiMonitorDouble> PvaClientMultiMonitorDoublePtr;
class PvaClientNTMultiGet;
typedef std::tr1::shared_ptr<PvaClientNTMultiGet> PvaClientNTMultiGetPtr;
class PvaClientNTMultiPut;
typedef std::tr1::shared_ptr<PvaClientNTMultiPut> PvaClientNTMultiPutPtr;
class PvaClientNTMultiMonitor;
typedef std::tr1::shared_ptr<PvaClientNTMultiMonitor> PvaClientNTMultiMonitorPtr;
class PvaClientNTMultiData;
typedef std::tr1::shared_ptr<PvaClientNTMultiData> PvaClientNTMultiDataPtr;
typedef epics::pvData::shared_vector<PvaClientChannelPtr> PvaClientChannelArray;
/**
* @brief PvaMultiChannel is a synchronous interface for accessing multiple channels.
*
* @author mrk
*/
class epicsShareClass PvaClientMultiChannel :
public std::tr1::enable_shared_from_this<PvaClientMultiChannel>
{
public:
POINTER_DEFINITIONS(PvaClientMultiChannel);
/** @brief Create a PvaClientMultiChannel.
* @param pvaClient The interface to pvaClient.
* @param channelNames The names of the channel..
* @param providerName The name of the provider.
* @param maxNotConnected The maximum number of channels that can be disconnected.
* @return The interface to the PvaClientMultiChannel
*/
static PvaClientMultiChannelPtr create(
PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const std::string> const & channelNames,
std::string const & providerName = "pva",
size_t maxNotConnected=0
);
/**
* @brief Destructor
*/
~PvaClientMultiChannel();
/** @brief Get the channelNames.
* @return The names.
*/
epics::pvData::shared_vector<const std::string> getChannelNames();
/** @brief Connect to the channels.
*
* This calls issueConnect and waitConnect.
* An exception is thrown if connect fails.
* @param timeout The time to wait for connecting to the channel.
* @return status of request
*/
epics::pvData::Status connect(double timeout=5);
/** @brief Are all channels connected?
* @return if all are connected.
*/
bool allConnected();
/** @brief Has a connection state change occured?
* @return (true, false) if (at least one, no) channel has changed state.
*/
bool connectionChange();
/** @brief Get the connection state of each channel.
* @return The state of each channel.
*/
epics::pvData::shared_vector<epics::pvData::boolean> getIsConnected();
/** @brief Get the pvaClientChannelArray.
* @return The shared pointer.
*/
PvaClientChannelArray getPvaClientChannelArray();
/** @brief Get pvaClient.
* @return The shared pointer.
*/
PvaClientPtr getPvaClient();
/**
* @brief create a pvaClientMultiGetDouble
* @return The interface.
*/
PvaClientMultiGetDoublePtr createGet();
/**
* @brief Create a pvaClientMultiPutDouble.
* @return The interface.
*/
PvaClientMultiPutDoublePtr createPut();
/**
* @brief Create a pvaClientMultiMonitorDouble.
* @return The interface.
*/
PvaClientMultiMonitorDoublePtr createMonitor();
/**
* @brief Create a pvaClientNTMultiPut.
* @return The interface.
*/
PvaClientNTMultiPutPtr createNTPut();
/**
* @brief Create a pvaClientNTMultiGet;
* @param request The request for each channel.
* @return The interface.
*/
PvaClientNTMultiGetPtr createNTGet(
std::string const &request = "field(value,alarm,timeStamp)");
/**
* @brief Create a pvaClientNTMultiPut.
* @param request The request for each channel.
* @return The interface.
*/
PvaClientNTMultiMonitorPtr createNTMonitor(
std::string const &request= "field(value,alarm,timeStamp)");
private:
PvaClientMultiChannel(
PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const std::string> const & channelName,
std::string const & providerName,
size_t maxNotConnected);
void checkConnected();
PvaClientPtr pvaClient;
epics::pvData::shared_vector<const std::string> channelName;
std::string providerName;
size_t maxNotConnected;
size_t numChannel;
epics::pvData::Mutex mutex;
size_t numConnected;
PvaClientChannelArray pvaClientChannelArray;
epics::pvData::shared_vector<epics::pvData::boolean> isConnected;
epics::pvData::CreateRequest::shared_pointer createRequest;
};
/**
* @brief Provides channelGet to multiple channels where each channel has a numeric scalar value field.
*/
class epicsShareClass PvaClientMultiGetDouble :
public std::tr1::enable_shared_from_this<PvaClientMultiGetDouble>
{
public:
POINTER_DEFINITIONS(PvaClientMultiGetDouble);
/**
* @brief Create a PvaClientMultiGetDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
static PvaClientMultiGetDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
~PvaClientMultiGetDouble();
/**
* @brief Create a channelGet for each channel.
*/
void connect();
/**
* @brief Get the data.
* @return The double[] where each element is the value field of the corresponding channel.
*/
epics::pvData::shared_vector<double> get();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientMultiGetDoublePtr getPtrSelf()
{
return shared_from_this();
}
private:
PvaClientMultiGetDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
PvaClientMultiChannelPtr pvaClientMultiChannel;
PvaClientChannelArray pvaClientChannelArray;
size_t nchannel;
epics::pvData::Mutex mutex;
epics::pvData::shared_vector<double> doubleValue;
std::vector<PvaClientGetPtr> pvaClientGet;
bool isGetConnected;
};
/**
* @brief Provides channelPut to multiple channels where each channel has a numeric scalar value field.
*/
class epicsShareClass PvaClientMultiPutDouble :
public std::tr1::enable_shared_from_this<PvaClientMultiPutDouble>
{
public:
POINTER_DEFINITIONS(PvaClientMultiPutDouble);
/** @brief Create a PvaClientMultiPutDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
static PvaClientMultiPutDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
~PvaClientMultiPutDouble();
/**
* @brief Create a channelPut for each channel.
*/
void connect();
/** @brief put data to each channel as a double
* @param data The array of data for each channel.
*/
void put(epics::pvData::shared_vector<double> const &data);
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientMultiPutDoublePtr getPtrSelf()
{
return shared_from_this();
}
private:
PvaClientMultiPutDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
PvaClientMultiChannelPtr pvaClientMultiChannel;
PvaClientChannelArray pvaClientChannelArray;
size_t nchannel;
epics::pvData::Mutex mutex;
std::vector<PvaClientPutPtr> pvaClientPut;
bool isPutConnected;
};
/**
* @brief Provides a monitor to multiple channels where each channel has a numeric scalar value field.
*/
class epicsShareClass PvaClientMultiMonitorDouble :
public std::tr1::enable_shared_from_this<PvaClientMultiMonitorDouble>
{
public:
POINTER_DEFINITIONS(PvaClientMultiMonitorDouble);
/** @brief Create a PvaClientMultiMonitorDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
static PvaClientMultiMonitorDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
~PvaClientMultiMonitorDouble();
/**
* @brief Connect a channel monitor for each channel.
*/
void connect();
/**
* @brief Poll each channel.
*
* If any has new data it is used to update the double[].
* @return (false,true) if (no, at least one) value was updated.
*/
bool poll();
/**
* @brief Wait until poll returns true.
* @param secondsToWait The time to keep trying.
* A thread sleep of .1 seconds occurs between each call to poll.
* @return (false,true) if (timeOut, poll returned true).
*/
bool waitEvent(double secondsToWait);
/**
* get the data.
* @return The double[] where each element is the value field of the corresponding channel.
*/
epics::pvData::shared_vector<double> get();
/** @brief Monitor the shared pointer to self.
* @return The shared pointer.
*/
PvaClientMultiMonitorDoublePtr getPtrSelf()
{
return shared_from_this();
}
private:
PvaClientMultiMonitorDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
PvaClientMultiChannelPtr pvaClientMultiChannel;
PvaClientChannelArray pvaClientChannelArray;
size_t nchannel;
epics::pvData::Mutex mutex;
epics::pvData::shared_vector<double> doubleValue;
std::vector<PvaClientMonitorPtr> pvaClientMonitor;
bool isMonitorConnected;
};
/**
* @brief Provides channelGet to multiple channels where the value field of each channel is presented as a union.
*/
class epicsShareClass PvaClientNTMultiGet :
public std::tr1::enable_shared_from_this<PvaClientNTMultiGet>
{
public:
POINTER_DEFINITIONS(PvaClientNTMultiGet);
/**
* @brief Create a PvaClientNTMultiGet.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @param pvRequest The pvRequest for each channel.
* @return The interface.
*/
static PvaClientNTMultiGetPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
~PvaClientNTMultiGet();
/**
* @brief Connect a channelGet for each channel.
*/
void connect();
/**
* @brief Get each channel.
*
* @param valueOnly use only value for union.
*/
void get(bool valueOnly = true);
/**
* @brief Get the data from the last get.
* @return the pvaClientNTMultiData.
*/
PvaClientNTMultiDataPtr getData();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientNTMultiGetPtr getPtrSelf()
{
return shared_from_this();
}
private:
PvaClientNTMultiGet(
epics::pvData::UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
PvaClientMultiChannelPtr pvaClientMultiChannel;
PvaClientChannelArray pvaClientChannelArray;
epics::pvData::PVStructurePtr pvRequest;
size_t nchannel;
epics::pvData::Mutex mutex;
PvaClientNTMultiDataPtr pvaClientNTMultiData;
std::vector<PvaClientGetPtr> pvaClientGet;
bool isConnected;
};
/**
* @brief Provides channelPut to multiple channels where the value field of each channel is presented as a union.
*/
class epicsShareClass PvaClientNTMultiPut :
public std::tr1::enable_shared_from_this<PvaClientNTMultiPut>
{
public:
POINTER_DEFINITIONS(PvaClientNTMultiPut);
/**
* @brief Create a PvaClientNTMultiPut.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
static PvaClientNTMultiPutPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
~PvaClientNTMultiPut();
/**
* @brief Connect a channelPut for each channel.
*/
void connect();
/**
* @brief Get the value field of each channel as a union.
* @return A shared vector of union.
*/
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> getValues();
/**
* @brief Issue a put for each channel.
' */
void put();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientNTMultiPutPtr getPtrSelf()
{
return shared_from_this();
}
private:
PvaClientNTMultiPut(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
PvaClientMultiChannelPtr pvaClientMultiChannel;
PvaClientChannelArray pvaClientChannelArray;
size_t nchannel;
epics::pvData::Mutex mutex;
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> unionValue;
epics::pvData::shared_vector<epics::pvData::PVFieldPtr> value;
std::vector<PvaClientPutPtr> pvaClientPut;
bool isConnected;
};
/**
* @brief Provides channel monitor to multiple channels where the value field of each channel is presented as a union.
*/
class epicsShareClass PvaClientNTMultiMonitor :
public std::tr1::enable_shared_from_this<PvaClientNTMultiMonitor>
{
public:
POINTER_DEFINITIONS(PvaClientNTMultiMonitor);
/** @brief Create a PvaClientNTMultiMonitor.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @param pvRequest The pvRequest for each channel.
* @return The interface.
*/
static PvaClientNTMultiMonitorPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
~PvaClientNTMultiMonitor();
/**
* @brief Connect to a channel monitor for each channel.
*/
void connect();
/**
* @brief Poll each channel.
*
* @param valueOnly use only value for union.
* If any has new data it is used to update the double[].
* @return (false,true) if (no, at least one) value was updated.
*/
bool poll(bool valueOnly = true);
/**
* @brief Wait until poll returns true.
* @param secondsToWait The time to keep trying.
* A thread sleep of .1 seconds occurs between each call to poll.
* @return (false,true) if (timeOut, poll returned true).
*/
bool waitEvent(double secondsToWait);
/**
* @brief Get the data for the last successfull poll.
* @return the pvaClientNTMultiData.
*/
PvaClientNTMultiDataPtr getData();
/** Monitor the shared pointer to self.
* @return The shared pointer.
*/
PvaClientNTMultiMonitorPtr getPtrSelf()
{
return shared_from_this();
}
private:
PvaClientNTMultiMonitor(
epics::pvData::UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
PvaClientMultiChannelPtr pvaClientMultiChannel;
PvaClientChannelArray pvaClientChannelArray;
epics::pvData::PVStructurePtr pvRequest;
size_t nchannel;
epics::pvData::Mutex mutex;
PvaClientNTMultiDataPtr pvaClientNTMultiData;
std::vector<PvaClientMonitorPtr> pvaClientMonitor;
bool isConnected;
};
/**
* @brief Provides NTMultiChannel data for both PvaClientNTMultiGet and PvaClientNTMultiMonitor.
*/
class epicsShareClass PvaClientNTMultiData :
public std::tr1::enable_shared_from_this<PvaClientNTMultiData>
{
public:
POINTER_DEFINITIONS(PvaClientNTMultiData);
/**
* @brief Create a PvaClientNTMultiData.
*
* Normally only called by PvaClientNTMultiGet and PvaClientNTMultiMonitor.
* @param u The union interface for the value field of each channel.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @param pvRequest The pvRequest for each channel.
*/
static PvaClientNTMultiDataPtr create(
epics::pvData::UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
~PvaClientNTMultiData();
/**
* @brief Get the number of channels.
* @return The number of channels.
*/
size_t getNumber();
/**
* @brief Set the timeStamp base for computing deltaTimes.
*/
void startDeltaTime();
/**
* @brief Update NTMultiChannel fields.
*
* @param valueOnly use only value for union.
*/
void endDeltaTime(bool valueOnly = true);
/**
* @brief Get the time when the last get was made.
* @return The timeStamp.
*/
epics::pvData::TimeStamp getTimeStamp();
/**
* @brief Get the NTMultiChannel.
* @return The value.
*/
epics::nt::NTMultiChannelPtr getNTMultiChannel();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientNTMultiDataPtr getPtrSelf()
{
return shared_from_this();
}
private:
PvaClientNTMultiData(
epics::pvData::UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaNTMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
void setPVStructure(
epics::pvData::PVStructurePtr const &pvStructure,size_t index);
PvaClientMultiChannelPtr pvaClientMultiChannel;
PvaClientChannelArray pvaClientChannelArray;
size_t nchannel;
epics::pvData::Mutex mutex;
std::vector<epics::pvData::PVStructurePtr> topPVStructure;
bool gotAlarm;
bool gotTimeStamp;
epics::pvData::StructureConstPtr ntMultiChannelStructure;
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> unionValue;
epics::pvData::shared_vector<epics::pvData::int32> severity;
epics::pvData::shared_vector<epics::pvData::int32> status;
epics::pvData::shared_vector<std::string> message;
epics::pvData::shared_vector<epics::pvData::int64> secondsPastEpoch;
epics::pvData::shared_vector<epics::pvData::int32> nanoseconds;
epics::pvData::shared_vector<epics::pvData::int32> userTag;
epics::pvData::Alarm alarm;
epics::pvData::TimeStamp timeStamp;;
epics::pvData::PVTimeStamp pvTimeStamp;
friend class PvaClientNTMultiGet;
friend class PvaClientNTMultiPut;
friend class PvaClientNTMultiMonitor;
};
}}
#endif /* PVACLIENTMULTICHANNEL_H */