/* 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 #include #ifdef pvaClientMultiChannelEpicsExportSharedSymbols # define epicsExportSharedSymbols # undef pvaClientMultiChannelEpicsExportSharedSymbols #endif #include namespace epics { namespace pvaClient { class PvaClientMultiChannel; typedef std::tr1::shared_ptr PvaClientMultiChannelPtr; class PvaClientMultiGetDouble; typedef std::tr1::shared_ptr PvaClientMultiGetDoublePtr; class PvaClientMultiPutDouble; typedef std::tr1::shared_ptr PvaClientMultiPutDoublePtr; class PvaClientMultiMonitorDouble; typedef std::tr1::shared_ptr PvaClientMultiMonitorDoublePtr; class PvaClientNTMultiGet; typedef std::tr1::shared_ptr PvaClientNTMultiGetPtr; class PvaClientNTMultiPut; typedef std::tr1::shared_ptr PvaClientNTMultiPutPtr; class PvaClientNTMultiMonitor; typedef std::tr1::shared_ptr PvaClientNTMultiMonitorPtr; class PvaClientNTMultiData; typedef std::tr1::shared_ptr PvaClientNTMultiDataPtr; typedef epics::pvData::shared_vector PvaClientChannelArray; /** * @brief PvaMultiChannel is a synchronous interface for accessing multiple channels. * * @author mrk */ class epicsShareClass PvaClientMultiChannel : public std::tr1::enable_shared_from_this { 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 & channelNames, std::string const & providerName = "pva", size_t maxNotConnected=0 ); /** * @brief Destructor */ ~PvaClientMultiChannel(); /** @brief Get the channelNames. * @return The names. */ epics::pvData::shared_vector 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 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 & channelName, std::string const & providerName, size_t maxNotConnected); void checkConnected(); PvaClientPtr pvaClient; epics::pvData::shared_vector channelName; std::string providerName; size_t maxNotConnected; size_t numChannel; epics::pvData::Mutex mutex; size_t numConnected; PvaClientChannelArray pvaClientChannelArray; epics::pvData::shared_vector 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 { 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 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 doubleValue; std::vector 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 { 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 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 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 { 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 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 doubleValue; std::vector 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 { 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 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 { 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 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 unionValue; epics::pvData::shared_vector value; std::vector 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 { 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 pvaClientMonitor; bool isConnected; }; /** * @brief Provides NTMultiChannel data for both PvaClientNTMultiGet and PvaClientNTMultiMonitor. */ class epicsShareClass PvaClientNTMultiData : public std::tr1::enable_shared_from_this { 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 topPVStructure; bool gotAlarm; bool gotTimeStamp; epics::pvData::StructureConstPtr ntMultiChannelStructure; epics::pvData::shared_vector unionValue; epics::pvData::shared_vector severity; epics::pvData::shared_vector status; epics::pvData::shared_vector message; epics::pvData::shared_vector secondsPastEpoch; epics::pvData::shared_vector nanoseconds; epics::pvData::shared_vector 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 */