NTMultiChannel support now available.
This commit is contained in:
32
README.md
Normal file
32
README.md
Normal file
@@ -0,0 +1,32 @@
|
||||
Status
|
||||
===========
|
||||
|
||||
* The API should be almost ready for feature freeze for release 4.5
|
||||
* Everything defined in pvaClient.h should be ready but see below for remaining work.
|
||||
* Everything defined in pvaClientMultiChannel.h is ready but see below for remaining work.
|
||||
|
||||
Examples
|
||||
------------
|
||||
|
||||
The examples require the database in pvaClientTestCPP.
|
||||
For example:
|
||||
|
||||
...
|
||||
mrk> pwd
|
||||
/home/epicsv4/pvaClientTestCPP/database/iocBoot/exampleDatabase
|
||||
mrk> ../../bin/linux-x86_64/exampleDatabase st.cmd
|
||||
...
|
||||
|
||||
pvaClientChannel
|
||||
---------------
|
||||
|
||||
Channel::getField and channelArray are not supported for release 4.5.
|
||||
|
||||
pvaClientMultiChannel
|
||||
---------------
|
||||
|
||||
For release 4.6 support is available for multiDouble and NTMultiChannel.
|
||||
In the future additional support should be provided that at least includes NTScalarMultiChannel.
|
||||
|
||||
Testing with some channels not connected have not been done.
|
||||
At least some testing with missing channels should be done before release 4.5
|
||||
@@ -1,9 +0,0 @@
|
||||
To build do the following:
|
||||
|
||||
cd configure
|
||||
cp ExampleRELEASE.local RELEASE.local
|
||||
edit RELEASE.local
|
||||
cd ..
|
||||
make
|
||||
|
||||
Now read documentation/pvaClientCPP.html
|
||||
@@ -40,6 +40,13 @@ examplePvaClientMultiDouble_LIBS += pvAccess
|
||||
examplePvaClientMultiDouble_LIBS += pvData
|
||||
examplePvaClientMultiDouble_LIBS += Com
|
||||
|
||||
PROD_HOST += examplePvaClientNTMulti
|
||||
examplePvaClientNTMulti_SRCS += examplePvaClientNTMulti.cpp
|
||||
examplePvaClientNTMulti_LIBS += pvaClient
|
||||
examplePvaClientNTMulti_LIBS += pvAccess
|
||||
examplePvaClientNTMulti_LIBS += pvData
|
||||
examplePvaClientNTMulti_LIBS += Com
|
||||
|
||||
PROD_HOST += helloWorldRPC
|
||||
helloWorldRPC_SRCS += helloWorldRPC.cpp
|
||||
helloWorldRPC_LIBS += pvaClient
|
||||
|
||||
@@ -33,7 +33,7 @@ cout << "num " << num << " names " << channelNames << endl;
|
||||
PvaClientMultiPutDoublePtr multiPut(multiChannel->createPut());
|
||||
PvaClientMultiMonitorDoublePtr multiMonitor(multiChannel->createMonitor());
|
||||
shared_vector<double> data(num,0);
|
||||
for(double value = 0.0; value< 1.0; value+= .2) {
|
||||
for(double value = 0.2; value< 2.3; value+= 1.0) {
|
||||
try {
|
||||
for(size_t i=0; i<num; ++i) data[i] = value + i;
|
||||
cout << "put " << data << endl;
|
||||
@@ -57,7 +57,7 @@ int main(int argc,char *argv[])
|
||||
size_t num = 5;
|
||||
shared_vector<string> channelNames(num);
|
||||
channelNames[0] = "double01";
|
||||
channelNames[1] = "double02";
|
||||
channelNames[1] = "int01";
|
||||
channelNames[2] = "double03";
|
||||
channelNames[3] = "double04";
|
||||
channelNames[4] = "double05";
|
||||
@@ -68,7 +68,7 @@ int main(int argc,char *argv[])
|
||||
example(pva,"ca",names);
|
||||
channelNames = shared_vector<string>(num);
|
||||
channelNames[0] = "exampleDouble01";
|
||||
channelNames[1] = "exampleDouble02";
|
||||
channelNames[1] = "exampleInt";
|
||||
channelNames[2] = "exampleDouble03";
|
||||
channelNames[3] = "exampleDouble04";
|
||||
channelNames[4] = "exampleDouble05";
|
||||
|
||||
141
example/src/examplePvaClientNTMulti.cpp
Normal file
141
example/src/examplePvaClientNTMulti.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/*examplePvaClientNTMulti.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
|
||||
*/
|
||||
|
||||
/* Author: Marty Kraimer */
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/convert.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvaClient;
|
||||
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static ConvertPtr convert = getConvert();
|
||||
|
||||
static void setValue(PVUnionPtr const &pvUnion, double value)
|
||||
{
|
||||
UnionConstPtr u = pvUnion->getUnion();
|
||||
FieldConstPtr field = u->getField(0);
|
||||
Type type = field->getType();
|
||||
if(type==scalar) {
|
||||
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(field);
|
||||
ScalarType scalarType = scalar->getScalarType();
|
||||
if(scalarType==pvDouble) {
|
||||
PVDoublePtr pvValue = static_pointer_cast<PVDouble>(
|
||||
pvDataCreate->createPVScalar(pvDouble));
|
||||
pvValue->put(value);
|
||||
pvUnion->set(0,pvValue);
|
||||
return;
|
||||
}
|
||||
if(scalarType==pvString) {
|
||||
PVStringPtr pvValue = static_pointer_cast<PVString>(
|
||||
pvDataCreate->createPVScalar(pvString));
|
||||
stringstream ss;
|
||||
ss << "value" << value;
|
||||
pvValue->put(ss.str());
|
||||
pvUnion->set(0,pvValue);
|
||||
return;
|
||||
}
|
||||
throw std::runtime_error("only pvDouble and pvString are supported");
|
||||
}
|
||||
if(type==scalarArray) {
|
||||
ScalarArrayConstPtr scalarArray = static_pointer_cast<const ScalarArray>(field);
|
||||
ScalarType scalarType = scalarArray->getElementType();
|
||||
if(scalarType==pvDouble) {
|
||||
size_t num = 5;
|
||||
PVDoubleArrayPtr pvValue = static_pointer_cast<PVDoubleArray>(
|
||||
pvDataCreate->createPVScalarArray(pvDouble));
|
||||
shared_vector<double> data(num);
|
||||
for(size_t i=0; i<num; ++i) data[i] = value +i;
|
||||
pvValue->replace(freeze(data));
|
||||
pvUnion->set(0,pvValue);
|
||||
return;
|
||||
}
|
||||
if(scalarType==pvString) {
|
||||
size_t num = 5;
|
||||
PVStringArrayPtr pvValue = static_pointer_cast<PVStringArray>(
|
||||
pvDataCreate->createPVScalarArray(pvString));
|
||||
shared_vector<string> data(num);
|
||||
for(size_t i=0; i<num; ++i) {
|
||||
stringstream ss;
|
||||
ss << "value" << value << i;
|
||||
data[i] = ss.str();
|
||||
}
|
||||
pvValue->replace(freeze(data));
|
||||
pvUnion->set(0,pvValue);
|
||||
return;
|
||||
}
|
||||
throw std::runtime_error("only pvDouble and pvString are supported");
|
||||
}
|
||||
throw std::runtime_error("only scalar and scalarArray fields are supported");
|
||||
}
|
||||
|
||||
static void example(
|
||||
PvaClientPtr const &pva,
|
||||
string provider,
|
||||
shared_vector<const string> const &channelNames)
|
||||
{
|
||||
|
||||
size_t num = channelNames.size();
|
||||
PvaClientMultiChannelPtr multiChannel(
|
||||
PvaClientMultiChannel::create(pva,channelNames,provider));
|
||||
PvaClientNTMultiGetPtr multiGet(multiChannel->createNTGet());
|
||||
PvaClientNTMultiPutPtr multiPut(multiChannel->createNTPut());
|
||||
PvaClientNTMultiMonitorPtr multiMonitor(multiChannel->createNTMonitor());
|
||||
shared_vector<epics::pvData::PVUnionPtr> data = multiPut->getValues();
|
||||
for(double value = 0.0; value< 2.1; value+= 1.0) {
|
||||
for(size_t i=0; i<num ; ++i) {
|
||||
PVUnionPtr pvUnion = data[i];
|
||||
setValue(pvUnion,value);
|
||||
}
|
||||
multiPut->put();
|
||||
multiGet->get();
|
||||
PvaClientNTMultiDataPtr multiData = multiGet->getData();
|
||||
PVStructurePtr pvStructure = multiData->getPVTop();
|
||||
cout << "pvStructure\n" << pvStructure << endl;
|
||||
bool result = multiMonitor->waitEvent(.1);
|
||||
while(result) {
|
||||
multiData = multiMonitor->getData();
|
||||
pvStructure = multiData->getPVTop();
|
||||
cout << "monitor pvStructure\n" << pvStructure << endl;
|
||||
result = multiMonitor->poll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
PvaClientPtr pva = PvaClient::create();
|
||||
size_t num = 4;
|
||||
shared_vector<string> channelNames(num);
|
||||
channelNames[0] = "double01";
|
||||
channelNames[1] = "string01";
|
||||
channelNames[2] = "doubleArray01";
|
||||
channelNames[3] = "stringArray01";
|
||||
cout << "dbRecord pva\n";
|
||||
shared_vector<const string> names(freeze(channelNames));
|
||||
example(pva,"pva",names);
|
||||
cout << "dbRecord ca\n";
|
||||
example(pva,"ca",names);
|
||||
channelNames = shared_vector<string>(num);
|
||||
channelNames[0] = "exampleDouble";
|
||||
channelNames[1] = "exampleString";
|
||||
channelNames[2] = "exampleDoubleArray";
|
||||
channelNames[3] = "exampleStringArray";
|
||||
names = freeze(channelNames);
|
||||
cout << "pvRecord pva\n";
|
||||
example(pva,"pva",names);
|
||||
return 0;
|
||||
}
|
||||
@@ -13,12 +13,16 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
#include <pv/convert.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvaClient;
|
||||
|
||||
static ConvertPtr convert = getConvert();
|
||||
|
||||
|
||||
static void examplePut(PvaClientPtr const &pva)
|
||||
{
|
||||
@@ -45,10 +49,29 @@ static void examplePut(PvaClientPtr const &pva)
|
||||
}
|
||||
}
|
||||
|
||||
static void examplePVFieldPut(PvaClientPtr const &pva)
|
||||
{
|
||||
cout << "example put\n";
|
||||
PvaClientChannelPtr channel = pva->channel("exampleDouble");
|
||||
PvaClientPutPtr put = channel->put();
|
||||
PvaClientPutDataPtr putData = put->getData();
|
||||
PVFieldPtr pvField = putData->getValue();
|
||||
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
|
||||
try {
|
||||
convert->fromDouble(pvScalar,1.0); put->put();
|
||||
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
|
||||
convert->fromDouble(pvScalar,2.0); put->put();
|
||||
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
|
||||
} catch (std::runtime_error e) {
|
||||
cout << "exception " << e.what() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
PvaClientPtr pva = PvaClient::create();
|
||||
examplePut(pva);
|
||||
examplePVFieldPut(pva);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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