NTMultiChannel support now available.
This commit is contained in:
@@ -22,6 +22,10 @@ LIBSRCS += pvaClientMultiChannel.cpp
|
||||
LIBSRCS += pvaClientMultiGetDouble.cpp
|
||||
LIBSRCS += pvaClientMultiPutDouble.cpp
|
||||
LIBSRCS += pvaClientMultiMonitorDouble.cpp
|
||||
LIBSRCS += pvaClientNTMultiPut.cpp
|
||||
LIBSRCS += pvaClientNTMultiData.cpp
|
||||
LIBSRCS += pvaClientNTMultiGet.cpp
|
||||
LIBSRCS += pvaClientNTMultiMonitor.cpp
|
||||
|
||||
pvaClient_LIBS += pvAccess pvData nt Com
|
||||
pvaClient_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
|
||||
203
src/PvaClientNTMultiData.cpp
Normal file
203
src/PvaClientNTMultiData.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
/* pvaClientNTMultiData.cpp */
|
||||
/**
|
||||
* 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.03
|
||||
*/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/convert.h>
|
||||
#include <epicsMath.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
static ConvertPtr convert = getConvert();
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static StandardFieldPtr standardField = getStandardField();
|
||||
|
||||
|
||||
PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
|
||||
epics::pvData::UnionConstPtr const & u,
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
PVStructurePtr const & pvRequest)
|
||||
{
|
||||
PvaClientNTMultiDataPtr pvaClientNTMultiData(
|
||||
new PvaClientNTMultiData(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
|
||||
return pvaClientNTMultiData;
|
||||
}
|
||||
|
||||
PvaClientNTMultiData::PvaClientNTMultiData(
|
||||
epics::pvData::UnionConstPtr const & u,
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest)
|
||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||
pvaClientChannelArray(pvaClientChannelArray),
|
||||
pvRequest(pvRequest),
|
||||
u(u),
|
||||
nchannel(pvaClientChannelArray.size()),
|
||||
gotAlarm(false),
|
||||
gotTimeStamp(false),
|
||||
isDestroyed(false)
|
||||
{
|
||||
PVFieldPtr pvValue = pvRequest->getSubField("field.value");
|
||||
if(!pvValue) {
|
||||
throw std::runtime_error("pvRequest did not specify value");
|
||||
}
|
||||
topPVStructure.resize(nchannel);
|
||||
for(size_t i=0; i< nchannel; ++i) topPVStructure[i] = PVStructurePtr();
|
||||
NTMultiChannelBuilderPtr builder = NTMultiChannel::createBuilder();
|
||||
builder->value(u);
|
||||
if(pvRequest->getSubField("field.alarm"))
|
||||
{
|
||||
gotAlarm = true;
|
||||
builder->addAlarm();
|
||||
severity.resize(nchannel);
|
||||
status.resize(nchannel);
|
||||
message.resize(nchannel);
|
||||
|
||||
}
|
||||
if(pvRequest->getSubField("field.timeStamp")) {
|
||||
gotTimeStamp = true;
|
||||
builder->addTimeStamp();
|
||||
secondsPastEpoch.resize(nchannel);
|
||||
nanoseconds.resize(nchannel);
|
||||
userTag.resize(nchannel);
|
||||
}
|
||||
ntMultiChannel = builder->create();
|
||||
}
|
||||
|
||||
|
||||
PvaClientNTMultiData::~PvaClientNTMultiData()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PvaClientNTMultiData::destroy()
|
||||
{
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
}
|
||||
pvaClientChannelArray.clear();
|
||||
}
|
||||
|
||||
void PvaClientNTMultiData::setStructure(StructureConstPtr const & structure,size_t index)
|
||||
{
|
||||
FieldConstPtr field = structure->getField("value");
|
||||
if(!field) {
|
||||
string message = "channel "
|
||||
+ pvaClientChannelArray[index]->getChannel()->getChannelName()
|
||||
+ " does not have top level value field";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
}
|
||||
|
||||
void PvaClientNTMultiData::setPVStructure(
|
||||
PVStructurePtr const &pvStructure,size_t index)
|
||||
{
|
||||
topPVStructure[index] = pvStructure;
|
||||
}
|
||||
|
||||
|
||||
size_t PvaClientNTMultiData::getNumber()
|
||||
{
|
||||
return nchannel;
|
||||
}
|
||||
|
||||
void PvaClientNTMultiData::startDeltaTime()
|
||||
{
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
topPVStructure[i] = PVStructurePtr();
|
||||
if(gotAlarm)
|
||||
{
|
||||
alarm.setSeverity(noAlarm);
|
||||
alarm.setStatus(noStatus);
|
||||
alarm.setMessage("");
|
||||
severity[i] = invalidAlarm;
|
||||
status[i] = undefinedStatus;
|
||||
message[i] = "not connected";
|
||||
}
|
||||
if(gotTimeStamp)
|
||||
{
|
||||
timeStamp.getCurrent();
|
||||
secondsPastEpoch[i] = 0;
|
||||
nanoseconds[i] = 0;
|
||||
userTag[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PvaClientNTMultiData::endDeltaTime()
|
||||
{
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
PVStructurePtr pvst = topPVStructure[i];
|
||||
if(!pvst) {
|
||||
unionValue[i] = PVUnionPtr();
|
||||
} else {
|
||||
unionValue[i]->set(pvst->getSubField("value"));
|
||||
}
|
||||
if(gotAlarm)
|
||||
{
|
||||
severity[i] = pvst->getSubField<PVInt>("alarm.severity")->get();
|
||||
status[i] = pvst->getSubField<PVInt>("alarm.status")->get();
|
||||
message[i] = pvst->getSubField<PVString>("alarm.message")->get();
|
||||
}
|
||||
if(gotTimeStamp)
|
||||
{
|
||||
secondsPastEpoch[i] = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch")->get();
|
||||
nanoseconds[i] = pvst->getSubField<PVInt>("timeStamp.nanoseconds")->get();
|
||||
userTag[i] = pvst->getSubField<PVInt>("timeStamp.userTag")->get();
|
||||
}
|
||||
|
||||
}
|
||||
ntMultiChannel->getValue()->replace(freeze(unionValue));
|
||||
if(gotAlarm)
|
||||
{
|
||||
ntMultiChannel->getSeverity()->replace(freeze(severity));
|
||||
ntMultiChannel->getStatus()->replace(freeze(status));
|
||||
ntMultiChannel->getMessage()->replace(freeze(message));
|
||||
}
|
||||
if(gotTimeStamp)
|
||||
{
|
||||
ntMultiChannel->getSecondsPastEpoch()->replace(freeze(secondsPastEpoch));
|
||||
ntMultiChannel->getNanoseconds()->replace(freeze(nanoseconds));
|
||||
ntMultiChannel->getUserTag()->replace(freeze(userTag));
|
||||
}
|
||||
}
|
||||
|
||||
TimeStamp PvaClientNTMultiData::getTimeStamp()
|
||||
{
|
||||
pvTimeStamp.get(timeStamp);
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
NTMultiChannelPtr PvaClientNTMultiData::getNTMultiChannel()
|
||||
{
|
||||
return ntMultiChannel;
|
||||
}
|
||||
|
||||
PVStructurePtr PvaClientNTMultiData::getPVTop()
|
||||
{
|
||||
return ntMultiChannel->getPVStructure();
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <pv/event.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/createRequest.h>
|
||||
|
||||
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
@@ -52,7 +52,8 @@ PvaClientMultiChannel::PvaClientMultiChannel(
|
||||
numChannel(channelName.size()),
|
||||
numConnected(0),
|
||||
pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())),
|
||||
isConnected(shared_vector<bool>(numChannel,false)),
|
||||
isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)),
|
||||
createRequest(CreateRequest::create()),
|
||||
isDestroyed(false)
|
||||
{
|
||||
}
|
||||
@@ -131,7 +132,7 @@ bool PvaClientMultiChannel::connectionChange()
|
||||
return false;
|
||||
}
|
||||
|
||||
epics::pvData::shared_vector<bool> PvaClientMultiChannel::getIsConnected()
|
||||
epics::pvData::shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected()
|
||||
{
|
||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
||||
for(size_t i=0; i<numChannel; ++i) {
|
||||
@@ -181,5 +182,47 @@ PvaClientMultiMonitorDoublePtr PvaClientMultiChannel::createMonitor()
|
||||
return PvaClientMultiMonitorDouble::create(getPtrSelf(), pvaClientChannelArray);
|
||||
}
|
||||
|
||||
PvaClientNTMultiPutPtr PvaClientMultiChannel::createNTPut()
|
||||
{
|
||||
checkConnected();
|
||||
return PvaClientNTMultiPut::create(getPtrSelf(), pvaClientChannelArray);
|
||||
}
|
||||
|
||||
|
||||
PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet()
|
||||
{
|
||||
return createNTGet("value,alarm,timeStamp");
|
||||
}
|
||||
|
||||
PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet(std::string const &request)
|
||||
{
|
||||
checkConnected();
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
if(!pvRequest) {
|
||||
stringstream ss;
|
||||
ss << " PvaClientMultiChannel::createNTGet invalid pvRequest: " + createRequest->getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
return PvaClientNTMultiGet::create(getPtrSelf(), pvaClientChannelArray,pvRequest);
|
||||
}
|
||||
|
||||
|
||||
PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor()
|
||||
{
|
||||
return createNTMonitor("value,alarm,timeStamp");
|
||||
}
|
||||
|
||||
PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor(std::string const &request)
|
||||
{
|
||||
checkConnected();
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
if(!pvRequest) {
|
||||
stringstream ss;
|
||||
ss << " PvaClientMultiChannel::createNTMonitor invalid pvRequest: " + createRequest->getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
return PvaClientNTMultiMonitor::create(getPtrSelf(), pvaClientChannelArray,pvRequest);
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* pvaClient.h */
|
||||
/* pvaClientMultiChannel.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
#include <pv/ntmultiChannel.h>
|
||||
#include <pv/createRequest.h>
|
||||
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
@@ -32,11 +33,20 @@ 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;
|
||||
|
||||
/**
|
||||
* Provides access to multiple channels.
|
||||
* @brief PvaMultiChannel is a synchronous interface for accessing multiple channels.
|
||||
*
|
||||
* @author mrk
|
||||
*/
|
||||
@@ -58,9 +68,11 @@ public:
|
||||
std::string const & providerName = "pva",
|
||||
size_t maxNotConnected=0
|
||||
);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~PvaClientMultiChannel();
|
||||
/** Destroy the pvAccess connection.
|
||||
/** Destroy the pvAccess connections.
|
||||
*/
|
||||
void destroy();
|
||||
/** Get the channelNames.
|
||||
@@ -85,7 +97,7 @@ public:
|
||||
/** Get the connection state of each channel.
|
||||
* @return The state of each channel.
|
||||
*/
|
||||
epics::pvData::shared_vector<bool> getIsConnected();
|
||||
epics::pvData::shared_vector<epics::pvData::boolean> getIsConnected();
|
||||
/** Get the pvaClientChannelArray.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
@@ -109,6 +121,35 @@ public:
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientMultiMonitorDoublePtr createMonitor();
|
||||
/**
|
||||
* Create a pvaClientNTMultiPut.
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientNTMultiPutPtr createNTPut();
|
||||
/**
|
||||
* Create a pvaClientNTMultiGet.
|
||||
* This calls the next method with request = "value,alarm,timeStamp"
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientNTMultiGetPtr createNTGet();
|
||||
/**
|
||||
* Create a pvaClientNTMultiGet;
|
||||
* @param request The request for each channel.
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientNTMultiGetPtr createNTGet(std::string const &request);
|
||||
/**
|
||||
* Create a pvaClientNTMultiMonitor.
|
||||
* This calls the next method with request = "value,alarm,timeStamp"
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientNTMultiMonitorPtr createNTMonitor();
|
||||
/**
|
||||
* Create a pvaClientNTMultiPut.
|
||||
* @param request The request for each channel.
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientNTMultiMonitorPtr createNTMonitor(std::string const &request);
|
||||
/** Get the shared pointer to self.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
@@ -135,8 +176,10 @@ private:
|
||||
|
||||
size_t numConnected;
|
||||
PvaClientChannelArray pvaClientChannelArray;
|
||||
epics::pvData::shared_vector<bool> isConnected;
|
||||
epics::pvData::shared_vector<epics::pvData::boolean> isConnected;
|
||||
epics::pvData::CreateRequest::shared_pointer createRequest;
|
||||
bool isDestroyed;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -319,6 +362,312 @@ private:
|
||||
bool isDestroyed;
|
||||
};
|
||||
|
||||
/**
|
||||
* This 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);
|
||||
/**
|
||||
* Factory method that creates 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();
|
||||
|
||||
/** Destroy the pvAccess connection.
|
||||
*/
|
||||
void destroy();
|
||||
/**
|
||||
* Create a channelGet for each channel.
|
||||
*/
|
||||
void connect();
|
||||
/**
|
||||
* get data for each channel.
|
||||
*/
|
||||
void get();
|
||||
/**
|
||||
* get the data.
|
||||
* @return the pvaClientNTMultiData.
|
||||
*/
|
||||
PvaClientNTMultiDataPtr getData();
|
||||
/** 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;
|
||||
size_t nchannel;
|
||||
epics::pvData::Mutex mutex;
|
||||
|
||||
epics::pvData::PVStructurePtr pvRequest;
|
||||
PvaClientNTMultiDataPtr pvaClientNTMultiData;
|
||||
std::vector<PvaClientGetPtr> pvaClientGet;
|
||||
bool isConnected;
|
||||
bool isDestroyed;
|
||||
};
|
||||
|
||||
/**
|
||||
* This 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);
|
||||
/**
|
||||
* Factory method that creates 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();
|
||||
|
||||
/** Destroy the pvAccess connection.
|
||||
*/
|
||||
void destroy();
|
||||
/**
|
||||
* Create a channelPut for each channel.
|
||||
*/
|
||||
void connect();
|
||||
/**
|
||||
* get the value field of each channel as a union.
|
||||
* @return A shared vector of union.
|
||||
*/
|
||||
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> getValues();
|
||||
/**
|
||||
* put the data to each channel.
|
||||
' */
|
||||
void put();
|
||||
/** 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;
|
||||
bool isDestroyed;
|
||||
};
|
||||
|
||||
/**
|
||||
* This 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);
|
||||
/**
|
||||
* Factory method that creates 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 &pvaNTMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest);
|
||||
~PvaClientNTMultiMonitor();
|
||||
|
||||
/** Destroy the pvAccess connection.
|
||||
*/
|
||||
void destroy();
|
||||
/**
|
||||
* Create a channel monitor for each channel.
|
||||
*/
|
||||
void connect();
|
||||
/**
|
||||
* 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();
|
||||
/**
|
||||
* Wait until poll returns true.
|
||||
* @param waitForEvent 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 waitForEvent);
|
||||
/**
|
||||
* get the data.
|
||||
* @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;
|
||||
size_t nchannel;
|
||||
epics::pvData::Mutex mutex;
|
||||
|
||||
epics::pvData::PVStructurePtr pvRequest;
|
||||
PvaClientNTMultiDataPtr pvaClientNTMultiData;
|
||||
std::vector<PvaClientMonitorPtr> pvaClientMonitor;
|
||||
bool isConnected;
|
||||
bool isDestroyed;
|
||||
};
|
||||
|
||||
/**
|
||||
* This provides NTMultiChannel data for both PvaClientNTMultiGet and PvaClientNTMultiMonitor.
|
||||
*/
|
||||
class epicsShareClass PvaClientNTMultiData :
|
||||
public std::tr1::enable_shared_from_this<PvaClientNTMultiData>
|
||||
{
|
||||
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientNTMultiData);
|
||||
/**
|
||||
* Factory method that creates 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 &pvaNTMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest);
|
||||
~PvaClientNTMultiData();
|
||||
/** Destroy the pvAccess connection.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* Get the number of channels.
|
||||
* @return The number of channels.
|
||||
*/
|
||||
size_t getNumber();
|
||||
|
||||
/**
|
||||
* Set the timeStamp base for computing deltaTimes.
|
||||
*/
|
||||
void startDeltaTime();
|
||||
|
||||
/**
|
||||
* Update NTMultiChannel fields.
|
||||
*/
|
||||
void endDeltaTime();
|
||||
/**
|
||||
* Get the time when the last get was made.
|
||||
* @return The timeStamp.
|
||||
*/
|
||||
epics::pvData::TimeStamp getTimeStamp();
|
||||
/**
|
||||
* Get the NTMultiChannel.
|
||||
* @return The value.
|
||||
*/
|
||||
epics::nt::NTMultiChannelPtr getNTMultiChannel();
|
||||
|
||||
/**
|
||||
* Get the top level structure.
|
||||
* @return The top level structure.
|
||||
*/
|
||||
epics::pvData::PVStructurePtr getPVTop();
|
||||
/** 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);
|
||||
static epics::pvData::PVStructurePtr createRequest(std::string const & request);
|
||||
void setStructure(epics::pvData::StructureConstPtr const & structure,size_t index);
|
||||
void setPVStructure(
|
||||
epics::pvData::PVStructurePtr const &pvStructure,size_t index);
|
||||
|
||||
PvaClientMultiChannelPtr pvaClientMultiChannel;
|
||||
PvaClientChannelArray pvaClientChannelArray;
|
||||
epics::pvData::PVStructurePtr pvRequest;
|
||||
epics::pvData::UnionConstPtr u;
|
||||
size_t nchannel;
|
||||
epics::pvData::Mutex mutex;
|
||||
|
||||
std::vector<epics::pvData::PVStructurePtr> topPVStructure;
|
||||
bool gotAlarm;
|
||||
bool gotTimeStamp;
|
||||
bool isDestroyed;
|
||||
|
||||
epics::nt::NTMultiChannelPtr ntMultiChannel;
|
||||
epics::pvData::PVStructurePtr pvTop;
|
||||
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::PVAlarm pvAlarm;
|
||||
epics::pvData::TimeStamp timeStamp;;
|
||||
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||
friend class PvaClientNTMultiGet;
|
||||
friend class PvaClientNTMultiPut;
|
||||
friend class PvaClientNTMultiMonitor;
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVACLIENTMULTICHANNEL_H */
|
||||
|
||||
@@ -68,7 +68,7 @@ void PvaClientMultiGetDouble::destroy()
|
||||
|
||||
void PvaClientMultiGetDouble::connect()
|
||||
{
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
string request = "value";
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
@@ -94,7 +94,7 @@ void PvaClientMultiGetDouble::connect()
|
||||
epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
|
||||
{
|
||||
if(!isGetConnected) connect();
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
|
||||
@@ -69,7 +69,7 @@ void PvaClientMultiMonitorDouble::destroy()
|
||||
|
||||
void PvaClientMultiMonitorDouble::connect()
|
||||
{
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
string request = "value";
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
@@ -103,7 +103,7 @@ bool PvaClientMultiMonitorDouble::poll()
|
||||
epicsThreadSleep(.01);
|
||||
}
|
||||
bool result = false;
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
|
||||
@@ -70,7 +70,7 @@ void PvaClientMultiPutDouble::destroy()
|
||||
|
||||
void PvaClientMultiPutDouble::connect()
|
||||
{
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
@@ -98,13 +98,13 @@ void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &da
|
||||
if(data.size()!=nchannel) {
|
||||
throw std::runtime_error("data has wrong size");
|
||||
}
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure();
|
||||
PVDoublePtr pvValue = pvTop->getSubField<PVDouble>("value");
|
||||
pvValue->put(data[i]);
|
||||
PVScalarPtr pvValue = pvTop->getSubField<PVScalar>("value");
|
||||
convert->fromDouble(pvValue,data[i]);
|
||||
pvaClientPut[i]->issuePut();
|
||||
}
|
||||
if(isConnected[i]) {
|
||||
|
||||
232
src/pvaClientNTMultiData.cpp
Normal file
232
src/pvaClientNTMultiData.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
/* pvaClientNTMultiData.cpp */
|
||||
/**
|
||||
* 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.03
|
||||
*/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/convert.h>
|
||||
#include <epicsMath.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
static ConvertPtr convert = getConvert();
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static StandardFieldPtr standardField = getStandardField();
|
||||
|
||||
|
||||
PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
|
||||
epics::pvData::UnionConstPtr const & u,
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
PVStructurePtr const & pvRequest)
|
||||
{
|
||||
PvaClientNTMultiDataPtr pvaClientNTMultiData(
|
||||
new PvaClientNTMultiData(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
|
||||
return pvaClientNTMultiData;
|
||||
}
|
||||
|
||||
PvaClientNTMultiData::PvaClientNTMultiData(
|
||||
epics::pvData::UnionConstPtr const & u,
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest)
|
||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||
pvaClientChannelArray(pvaClientChannelArray),
|
||||
pvRequest(pvRequest),
|
||||
u(u),
|
||||
nchannel(pvaClientChannelArray.size()),
|
||||
gotAlarm(false),
|
||||
gotTimeStamp(false),
|
||||
isDestroyed(false)
|
||||
{
|
||||
PVFieldPtr pvValue = pvRequest->getSubField("field.value");
|
||||
if(!pvValue) {
|
||||
throw std::runtime_error("pvRequest did not specify value");
|
||||
}
|
||||
topPVStructure.resize(nchannel);
|
||||
unionValue.resize(nchannel);
|
||||
for(size_t i=0; i< nchannel; ++i) {
|
||||
topPVStructure[i] = PVStructurePtr();
|
||||
unionValue[i] = pvDataCreate->createPVUnion(u);
|
||||
}
|
||||
NTMultiChannelBuilderPtr builder = NTMultiChannel::createBuilder();
|
||||
builder->value(u);
|
||||
if(pvRequest->getSubField("field.alarm"))
|
||||
{
|
||||
gotAlarm = true;
|
||||
builder->addAlarm();
|
||||
builder->addSeverity();
|
||||
builder->addStatus();
|
||||
builder->addMessage();
|
||||
severity.resize(nchannel);
|
||||
status.resize(nchannel);
|
||||
message.resize(nchannel);
|
||||
|
||||
}
|
||||
if(pvRequest->getSubField("field.timeStamp")) {
|
||||
gotTimeStamp = true;
|
||||
builder->addTimeStamp();
|
||||
builder->addSecondsPastEpoch();
|
||||
builder->addNanoseconds();
|
||||
builder->addUserTag();
|
||||
secondsPastEpoch.resize(nchannel);
|
||||
nanoseconds.resize(nchannel);
|
||||
userTag.resize(nchannel);
|
||||
}
|
||||
ntMultiChannel = builder->create();
|
||||
ntMultiChannel->getChannelName()->replace(pvaClientMultiChannel->getChannelNames());
|
||||
}
|
||||
|
||||
|
||||
PvaClientNTMultiData::~PvaClientNTMultiData()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PvaClientNTMultiData::destroy()
|
||||
{
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
}
|
||||
pvaClientChannelArray.clear();
|
||||
}
|
||||
|
||||
void PvaClientNTMultiData::setStructure(StructureConstPtr const & structure,size_t index)
|
||||
{
|
||||
FieldConstPtr field = structure->getField("value");
|
||||
if(!field) {
|
||||
string message = "channel "
|
||||
+ pvaClientChannelArray[index]->getChannel()->getChannelName()
|
||||
+ " does not have top level value field";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
}
|
||||
|
||||
void PvaClientNTMultiData::setPVStructure(
|
||||
PVStructurePtr const &pvStructure,size_t index)
|
||||
{
|
||||
topPVStructure[index] = pvStructure;
|
||||
}
|
||||
|
||||
|
||||
size_t PvaClientNTMultiData::getNumber()
|
||||
{
|
||||
return nchannel;
|
||||
}
|
||||
|
||||
void PvaClientNTMultiData::startDeltaTime()
|
||||
{
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
topPVStructure[i] = PVStructurePtr();
|
||||
if(gotAlarm)
|
||||
{
|
||||
alarm.setSeverity(noAlarm);
|
||||
alarm.setStatus(noStatus);
|
||||
alarm.setMessage("");
|
||||
severity[i] = invalidAlarm;
|
||||
status[i] = undefinedStatus;
|
||||
message[i] = "not connected";
|
||||
}
|
||||
if(gotTimeStamp)
|
||||
{
|
||||
timeStamp.getCurrent();
|
||||
secondsPastEpoch[i] = 0;
|
||||
nanoseconds[i] = 0;
|
||||
userTag[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PvaClientNTMultiData::endDeltaTime()
|
||||
{
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
PVStructurePtr pvst = topPVStructure[i];
|
||||
if(!pvst) {
|
||||
unionValue[i] = PVUnionPtr();
|
||||
} else {
|
||||
unionValue[i]->set(pvst->getSubField("value"));
|
||||
}
|
||||
if(gotAlarm)
|
||||
{
|
||||
severity[i] = pvst->getSubField<PVInt>("alarm.severity")->get();
|
||||
status[i] = pvst->getSubField<PVInt>("alarm.status")->get();
|
||||
message[i] = pvst->getSubField<PVString>("alarm.message")->get();
|
||||
}
|
||||
if(gotTimeStamp)
|
||||
{
|
||||
secondsPastEpoch[i] = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch")->get();
|
||||
nanoseconds[i] = pvst->getSubField<PVInt>("timeStamp.nanoseconds")->get();
|
||||
userTag[i] = pvst->getSubField<PVInt>("timeStamp.userTag")->get();
|
||||
}
|
||||
|
||||
}
|
||||
shared_vector<epics::pvData::PVUnionPtr> val(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) val[i] = unionValue[i];
|
||||
ntMultiChannel->getValue()->replace(freeze(val));
|
||||
shared_vector<epics::pvData::boolean> connected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) isConnected[i] = connected[i];
|
||||
ntMultiChannel->getIsConnected()->replace(freeze(isConnected));
|
||||
if(gotAlarm)
|
||||
{
|
||||
shared_vector<int32> sev(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) sev[i] = severity[i];
|
||||
ntMultiChannel->getSeverity()->replace(freeze(sev));
|
||||
shared_vector<int32> sta(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) sta[i] = status[i];
|
||||
ntMultiChannel->getStatus()->replace(freeze(sta));
|
||||
shared_vector<string> mes(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) mes[i] = message[i];
|
||||
ntMultiChannel->getMessage()->replace(freeze(mes));
|
||||
}
|
||||
if(gotTimeStamp)
|
||||
{
|
||||
shared_vector<int64> sec(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) sec[i] = secondsPastEpoch[i];
|
||||
ntMultiChannel->getSecondsPastEpoch()->replace(freeze(sec));
|
||||
shared_vector<int32> nano(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) nano[i] = nanoseconds[i];
|
||||
ntMultiChannel->getNanoseconds()->replace(freeze(nano));
|
||||
shared_vector<int32> tag(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) tag[i] = userTag[i];
|
||||
ntMultiChannel->getUserTag()->replace(freeze(tag));
|
||||
}
|
||||
}
|
||||
|
||||
TimeStamp PvaClientNTMultiData::getTimeStamp()
|
||||
{
|
||||
pvTimeStamp.get(timeStamp);
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
NTMultiChannelPtr PvaClientNTMultiData::getNTMultiChannel()
|
||||
{
|
||||
return ntMultiChannel;
|
||||
}
|
||||
|
||||
PVStructurePtr PvaClientNTMultiData::getPVTop()
|
||||
{
|
||||
return ntMultiChannel->getPVStructure();
|
||||
}
|
||||
|
||||
}}
|
||||
143
src/pvaClientNTMultiGet.cpp
Normal file
143
src/pvaClientNTMultiGet.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/* pvaClientNTMultiGet.cpp */
|
||||
/**
|
||||
* 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.03
|
||||
*/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/convert.h>
|
||||
#include <epicsMath.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
static ConvertPtr convert = getConvert();
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static StandardFieldPtr standardField = getStandardField();
|
||||
|
||||
|
||||
PvaClientNTMultiGetPtr PvaClientNTMultiGet::create(
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
PVStructurePtr const & pvRequest)
|
||||
{
|
||||
UnionConstPtr u = fieldCreate->createVariantUnion();
|
||||
PvaClientNTMultiGetPtr pvaClientNTMultiGet(
|
||||
new PvaClientNTMultiGet(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
|
||||
return pvaClientNTMultiGet;
|
||||
}
|
||||
|
||||
PvaClientNTMultiGet::PvaClientNTMultiGet(
|
||||
UnionConstPtr const & u,
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest)
|
||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||
pvaClientChannelArray(pvaClientChannelArray),
|
||||
nchannel(pvaClientChannelArray.size()),
|
||||
pvRequest(pvRequest),
|
||||
pvaClientNTMultiData(
|
||||
PvaClientNTMultiData::create(
|
||||
u,
|
||||
pvaClientMultiChannel,
|
||||
pvaClientChannelArray,
|
||||
pvRequest)),
|
||||
isConnected(false),
|
||||
isDestroyed(false)
|
||||
{
|
||||
}
|
||||
|
||||
PvaClientNTMultiGet::~PvaClientNTMultiGet()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PvaClientNTMultiGet::destroy()
|
||||
{
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
}
|
||||
pvaClientChannelArray.clear();
|
||||
}
|
||||
|
||||
void PvaClientNTMultiGet::connect()
|
||||
{
|
||||
pvaClientGet.resize(nchannel);
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
string request = "value";
|
||||
if(pvRequest->getSubField("field.alarm")) request += ",alarm";
|
||||
if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(request);
|
||||
pvaClientGet[i]->issueConnect();
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientGet[i]->waitConnect();
|
||||
if(status.isOK()) continue;
|
||||
stringstream ss;
|
||||
string channelName = pvaClientChannelArray[i]->getChannelName();
|
||||
ss << "channel " << channelName << " PvaChannelGet::waitConnect " << status.getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
this->isConnected = true;
|
||||
}
|
||||
|
||||
void PvaClientNTMultiGet::get()
|
||||
{
|
||||
if(!isConnected) connect();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientGet[i]->issueGet();
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientGet[i]->waitGet();
|
||||
if(status.isOK()) continue;
|
||||
stringstream ss;
|
||||
string channelName = pvaClientChannelArray[i]->getChannelName();
|
||||
ss << "channel " << channelName << " PvaChannelGet::waitConnect " << status.getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
pvaClientNTMultiData->startDeltaTime();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientNTMultiData->setPVStructure(pvaClientGet[i]->getData()->getPVStructure(),i);
|
||||
}
|
||||
}
|
||||
pvaClientNTMultiData->endDeltaTime();
|
||||
}
|
||||
|
||||
PvaClientNTMultiDataPtr PvaClientNTMultiGet::getData()
|
||||
{
|
||||
return pvaClientNTMultiData;
|
||||
}
|
||||
|
||||
}}
|
||||
155
src/pvaClientNTMultiMonitor.cpp
Normal file
155
src/pvaClientNTMultiMonitor.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/* pvaClientNTMultiMonitor.cpp */
|
||||
/**
|
||||
* 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.03
|
||||
*/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <epicsThread.h>
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/convert.h>
|
||||
#include <epicsMath.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
static ConvertPtr convert = getConvert();
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static StandardFieldPtr standardField = getStandardField();
|
||||
|
||||
|
||||
PvaClientNTMultiMonitorPtr PvaClientNTMultiMonitor::create(
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest)
|
||||
{
|
||||
UnionConstPtr u = fieldCreate->createVariantUnion();
|
||||
PvaClientNTMultiMonitorPtr pvaClientNTMultiMonitor(
|
||||
new PvaClientNTMultiMonitor(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
|
||||
return pvaClientNTMultiMonitor;
|
||||
}
|
||||
|
||||
PvaClientNTMultiMonitor::PvaClientNTMultiMonitor(
|
||||
UnionConstPtr const & u,
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
PVStructurePtr const & pvRequest)
|
||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||
pvaClientChannelArray(pvaClientChannelArray),
|
||||
nchannel(pvaClientChannelArray.size()),
|
||||
pvRequest(pvRequest),
|
||||
pvaClientNTMultiData(
|
||||
PvaClientNTMultiData::create(
|
||||
u,
|
||||
pvaClientMultiChannel,
|
||||
pvaClientChannelArray,
|
||||
pvRequest)),
|
||||
isConnected(false),
|
||||
isDestroyed(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PvaClientNTMultiMonitor::~PvaClientNTMultiMonitor()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PvaClientNTMultiMonitor::destroy()
|
||||
{
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
}
|
||||
pvaClientChannelArray.clear();
|
||||
}
|
||||
|
||||
|
||||
void PvaClientNTMultiMonitor::connect()
|
||||
{
|
||||
pvaClientMonitor.resize(nchannel);
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
string request = "value";
|
||||
if(pvRequest->getSubField("field.alarm")) request += ",alarm";
|
||||
if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(request);
|
||||
pvaClientMonitor[i]->issueConnect();
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientMonitor[i]->waitConnect();
|
||||
if(status.isOK()) continue;
|
||||
stringstream ss;
|
||||
string channelName = pvaClientChannelArray[i]->getChannelName();
|
||||
ss << "channel " << channelName << " PvaChannelMonitor::waitConnect " << status.getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) pvaClientMonitor[i]->start();
|
||||
}
|
||||
this->isConnected = true;
|
||||
}
|
||||
|
||||
bool PvaClientNTMultiMonitor::poll()
|
||||
{
|
||||
if(!isConnected) connect();
|
||||
bool result = false;
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
pvaClientNTMultiData->startDeltaTime();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
if(pvaClientMonitor[i]->poll()) {
|
||||
pvaClientNTMultiData->setPVStructure(
|
||||
pvaClientMonitor[i]->getData()->getPVStructure(),i);
|
||||
pvaClientMonitor[i]->releaseEvent();
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(result) pvaClientNTMultiData->endDeltaTime();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PvaClientNTMultiMonitor::waitEvent(double waitForEvent)
|
||||
{
|
||||
if(poll()) return true;
|
||||
TimeStamp start;
|
||||
start.getCurrent();
|
||||
TimeStamp now;
|
||||
while(true) {
|
||||
epicsThreadSleep(.1);
|
||||
if(poll()) return true;
|
||||
now.getCurrent();
|
||||
double diff = TimeStamp::diff(now,start);
|
||||
if(diff>=waitForEvent) break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PvaClientNTMultiDataPtr PvaClientNTMultiMonitor::getData()
|
||||
{
|
||||
return pvaClientNTMultiData;
|
||||
}
|
||||
|
||||
}}
|
||||
149
src/pvaClientNTMultiPut.cpp
Normal file
149
src/pvaClientNTMultiPut.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
/* PvaClientNTMultiPut.cpp */
|
||||
/**
|
||||
* 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.03
|
||||
*/
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/convert.h>
|
||||
#include <epicsMath.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
static ConvertPtr convert = getConvert();
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static StandardFieldPtr standardField = getStandardField();
|
||||
static CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||
|
||||
PvaClientNTMultiPutPtr PvaClientNTMultiPut::create(
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray)
|
||||
{
|
||||
PvaClientNTMultiPutPtr pvaClientNTMultiPut(
|
||||
new PvaClientNTMultiPut(pvaMultiChannel,pvaClientChannelArray));
|
||||
return pvaClientNTMultiPut;
|
||||
}
|
||||
|
||||
PvaClientNTMultiPut::PvaClientNTMultiPut(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray)
|
||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||
pvaClientChannelArray(pvaClientChannelArray),
|
||||
nchannel(pvaClientChannelArray.size()),
|
||||
unionValue(shared_vector<epics::pvData::PVUnionPtr>(nchannel,PVUnionPtr())),
|
||||
value(shared_vector<epics::pvData::PVFieldPtr>(nchannel,PVFieldPtr())),
|
||||
isConnected(false),
|
||||
isDestroyed(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PvaClientNTMultiPut::~PvaClientNTMultiPut()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PvaClientNTMultiPut::destroy()
|
||||
{
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
}
|
||||
pvaClientChannelArray.clear();
|
||||
}
|
||||
|
||||
void PvaClientNTMultiPut::connect()
|
||||
{
|
||||
pvaClientPut.resize(nchannel);
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientPut[i] = pvaClientChannelArray[i]->createPut();
|
||||
pvaClientPut[i]->issueConnect();
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientPut[i]->waitConnect();
|
||||
if(status.isOK()) continue;
|
||||
stringstream ss;
|
||||
string channelName = pvaClientChannelArray[i]->getChannelName();
|
||||
ss << "channel " << channelName << " PvaChannelPut::waitConnect " << status.getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientPut[i]->issueGet();
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientPut[i]->waitGet();
|
||||
if(status.isOK()) continue;
|
||||
stringstream ss;
|
||||
string channelName = pvaClientChannelArray[i]->getChannelName();
|
||||
ss << "channel " << channelName << " PvaChannelPut::waitGet " << status.getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
value[i] = pvaClientPut[i]->getData()->getValue();
|
||||
FieldBuilderPtr builder = fieldCreate->createFieldBuilder();
|
||||
builder->add("value",value[i]->getField());
|
||||
unionValue[i] = pvDataCreate->createPVUnion(builder->createUnion());
|
||||
}
|
||||
}
|
||||
this->isConnected = true;
|
||||
}
|
||||
|
||||
shared_vector<epics::pvData::PVUnionPtr> PvaClientNTMultiPut::getValues()
|
||||
{
|
||||
if(!isConnected) connect();
|
||||
return unionValue;
|
||||
}
|
||||
|
||||
void PvaClientNTMultiPut::put()
|
||||
{
|
||||
if(!isConnected) connect();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
value[i]->copy(*unionValue[i]->get());
|
||||
pvaClientPut[i]->issuePut();
|
||||
}
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientPut[i]->waitPut();
|
||||
if(status.isOK()) continue;
|
||||
stringstream ss;
|
||||
string channelName = pvaClientChannelArray[i]->getChannelName();
|
||||
ss << "channel " << channelName << " PvaChannelPut::waitConnect " << status.getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
Reference in New Issue
Block a user