added support for multi channel double
This commit is contained in:
@@ -33,6 +33,13 @@ examplePvaClientMonitor_LIBS += pvAccess
|
||||
examplePvaClientMonitor_LIBS += pvData
|
||||
examplePvaClientMonitor_LIBS += Com
|
||||
|
||||
PROD_HOST += examplePvaClientMultiDouble
|
||||
examplePvaClientMultiDouble_SRCS += examplePvaClientMultiDouble.cpp
|
||||
examplePvaClientMultiDouble_LIBS += pvaClient
|
||||
examplePvaClientMultiDouble_LIBS += pvAccess
|
||||
examplePvaClientMultiDouble_LIBS += pvData
|
||||
examplePvaClientMultiDouble_LIBS += Com
|
||||
|
||||
PROD_HOST += helloWorldRPC
|
||||
helloWorldRPC_SRCS += helloWorldRPC.cpp
|
||||
helloWorldRPC_LIBS += pvaClient
|
||||
|
||||
@@ -22,25 +22,29 @@ using namespace epics::pvAccess;
|
||||
using namespace epics::pvaClient;
|
||||
|
||||
|
||||
static void exampleMonitor(PvaClientPtr const &pva)
|
||||
static void exampleMonitor(PvaClientPtr const &pva,string provider)
|
||||
{
|
||||
PvaClientMonitorPtr monitor = pva->channel("exampleDouble")->monitor("");
|
||||
PvaClientMonitorDataPtr pvaData = monitor->getData();
|
||||
PvaClientPutPtr put = pva->channel("exampleDouble")->put("");
|
||||
PvaClientMonitorPtr monitor = pva->channel("double00",provider,2.0)->monitor("");
|
||||
PvaClientMonitorDataPtr monitorData = monitor->getData();
|
||||
PvaClientPutPtr put = pva->channel("double00",provider,2.0)->put("");
|
||||
PvaClientPutDataPtr putData = put->getData();
|
||||
for(size_t ntimes=0; ntimes<5; ++ntimes)
|
||||
{
|
||||
double value = ntimes;
|
||||
cout << "put " << value << endl;
|
||||
putData->putDouble(value); put->put();
|
||||
if(!monitor->waitEvent()) {
|
||||
if(!monitor->waitEvent(.1)) {
|
||||
cout << "waitEvent returned false. Why???";
|
||||
continue;
|
||||
} else while(true) {
|
||||
cout << "monitor " << monitorData->getDouble() << endl;
|
||||
cout << "changed\n";
|
||||
monitorData->showChanged(cout);
|
||||
cout << "overrun\n";
|
||||
monitorData->showOverrun(cout);
|
||||
monitor->releaseEvent();
|
||||
if(!monitor->poll()) break;
|
||||
}
|
||||
cout << "changed\n";
|
||||
pvaData->showChanged(cout);
|
||||
cout << "overrun\n";
|
||||
pvaData->showOverrun(cout);
|
||||
monitor->releaseEvent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +52,10 @@ static void exampleMonitor(PvaClientPtr const &pva)
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
PvaClientPtr pva = PvaClient::create();
|
||||
exampleMonitor(pva);
|
||||
cout << "exampleMonitor pva\n";
|
||||
exampleMonitor(pva,"pva");
|
||||
cout << "exampleMonitor ca\n";
|
||||
exampleMonitor(pva,"ca");
|
||||
cout << "done\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
79
example/src/examplePvaClientMultiDouble.cpp
Normal file
79
example/src/examplePvaClientMultiDouble.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/*examplePvaClientMultiDouble.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>
|
||||
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvaClient;
|
||||
|
||||
static void example(
|
||||
PvaClientPtr const &pva,
|
||||
string provider,
|
||||
shared_vector<const string> const &channelNames)
|
||||
{
|
||||
|
||||
size_t num = channelNames.size();
|
||||
cout << "num " << num << " names " << channelNames << endl;
|
||||
PvaClientMultiChannelPtr multiChannel(
|
||||
PvaClientMultiChannel::create(pva,channelNames,provider));
|
||||
PvaClientMultiGetDoublePtr multiGet(multiChannel->createGet());
|
||||
PvaClientMultiPutDoublePtr multiPut(multiChannel->createPut());
|
||||
PvaClientMultiMonitorDoublePtr multiMonitor(multiChannel->createMonitor());
|
||||
shared_vector<double> data(num,0);
|
||||
for(double value = 0.0; value< 1.0; value+= .2) {
|
||||
try {
|
||||
for(size_t i=0; i<num; ++i) data[i] = value + i;
|
||||
cout << "put " << data << endl;
|
||||
multiPut->put(data);
|
||||
data = multiGet->get();
|
||||
cout << "get " << data << endl;
|
||||
bool result = multiMonitor->waitEvent(.1);
|
||||
while(result) {
|
||||
cout << "monitor data " << multiMonitor->get() << endl;
|
||||
result = multiMonitor->poll();
|
||||
}
|
||||
} catch (std::runtime_error e) {
|
||||
cout << "exception " << e.what() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
PvaClientPtr pva = PvaClient::create();
|
||||
size_t num = 5;
|
||||
shared_vector<string> channelNames(num);
|
||||
channelNames[0] = "double01";
|
||||
channelNames[1] = "double02";
|
||||
channelNames[2] = "double03";
|
||||
channelNames[3] = "double04";
|
||||
channelNames[4] = "double05";
|
||||
cout << "double pva\n";
|
||||
shared_vector<const string> names(freeze(channelNames));
|
||||
example(pva,"pva",names);
|
||||
cout << "double ca\n";
|
||||
example(pva,"ca",names);
|
||||
channelNames = shared_vector<string>(num);
|
||||
channelNames[0] = "exampleDouble01";
|
||||
channelNames[1] = "exampleDouble02";
|
||||
channelNames[2] = "exampleDouble03";
|
||||
channelNames[3] = "exampleDouble04";
|
||||
channelNames[4] = "exampleDouble05";
|
||||
names = freeze(channelNames);
|
||||
cout << "exampleDouble pva\n";
|
||||
example(pva,"pva",names);
|
||||
return 0;
|
||||
}
|
||||
@@ -26,11 +26,20 @@ static void examplePut(PvaClientPtr const &pva)
|
||||
PvaClientChannelPtr channel = pva->channel("exampleDouble");
|
||||
PvaClientPutPtr put = channel->put();
|
||||
PvaClientPutDataPtr putData = put->getData();
|
||||
PvaClientMonitorPtr monitor = pva->channel("exampleDouble")->monitor("");
|
||||
PvaClientMonitorDataPtr monitorData = monitor->getData();
|
||||
try {
|
||||
putData->putDouble(3.0); put->put();
|
||||
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
|
||||
putData->putDouble(4.0); put->put();
|
||||
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
|
||||
if(!monitor->waitEvent()) {
|
||||
cout << "waitEvent returned false. Why???";
|
||||
} else while(true) {
|
||||
cout << "monitor changed\n" << monitorData->showChanged(cout);
|
||||
monitor->releaseEvent();
|
||||
if(!monitor->poll()) break;
|
||||
}
|
||||
} catch (std::runtime_error e) {
|
||||
cout << "exception " << e.what() << endl;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ include $(TOP)/configure/CONFIG
|
||||
LIBRARY += pvaClient
|
||||
|
||||
INC += pvaClient.h
|
||||
INC += pvaClientMultiChannel.h
|
||||
|
||||
LIBSRCS += pvaClient.cpp
|
||||
LIBSRCS += pvaClientPutData.cpp
|
||||
@@ -17,6 +18,10 @@ LIBSRCS += pvaClientGet.cpp
|
||||
LIBSRCS += pvaClientPut.cpp
|
||||
LIBSRCS += pvaClientMonitor.cpp
|
||||
LIBSRCS += pvaClientPutGet.cpp
|
||||
LIBSRCS += pvaClientMultiChannel.cpp
|
||||
LIBSRCS += pvaClientMultiGetDouble.cpp
|
||||
LIBSRCS += pvaClientMultiPutDouble.cpp
|
||||
LIBSRCS += pvaClientMultiMonitorDouble.cpp
|
||||
|
||||
pvaClient_LIBS += pvAccess pvData nt Com
|
||||
pvaClient_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
|
||||
185
src/pvaClientMultiChannel.cpp
Normal file
185
src/pvaClientMultiChannel.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
/* pvaClientMultiChannel.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.02
|
||||
*/
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <pv/event.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/createRequest.h>
|
||||
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static CreateRequest::shared_pointer createRequestPvt = CreateRequest::create();
|
||||
|
||||
PvaClientMultiChannelPtr PvaClientMultiChannel::create(
|
||||
PvaClientPtr const &pvaClient,
|
||||
epics::pvData::shared_vector<const string> const & channelNames,
|
||||
string const & providerName,
|
||||
size_t maxNotConnected)
|
||||
{
|
||||
PvaClientMultiChannelPtr channel(
|
||||
new PvaClientMultiChannel(pvaClient,channelNames,providerName,maxNotConnected));
|
||||
return channel;
|
||||
}
|
||||
|
||||
|
||||
PvaClientMultiChannel::PvaClientMultiChannel(
|
||||
PvaClientPtr const &pvaClient,
|
||||
epics::pvData::shared_vector<const string> const & channelName,
|
||||
string const & providerName,
|
||||
size_t maxNotConnected)
|
||||
: pvaClient(pvaClient),
|
||||
channelName(channelName),
|
||||
providerName(providerName),
|
||||
maxNotConnected(maxNotConnected),
|
||||
numChannel(channelName.size()),
|
||||
numConnected(0),
|
||||
pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())),
|
||||
isConnected(shared_vector<bool>(numChannel,false)),
|
||||
isDestroyed(false)
|
||||
{
|
||||
}
|
||||
|
||||
PvaClientMultiChannel::~PvaClientMultiChannel()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PvaClientMultiChannel::destroy()
|
||||
{
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
}
|
||||
pvaClientChannelArray.clear();
|
||||
}
|
||||
|
||||
void PvaClientMultiChannel::checkConnected()
|
||||
{
|
||||
if(numConnected==0) connect(3.0);
|
||||
}
|
||||
|
||||
epics::pvData::shared_vector<const string> PvaClientMultiChannel::getChannelNames()
|
||||
{
|
||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
||||
return channelName;
|
||||
}
|
||||
|
||||
Status PvaClientMultiChannel::connect(double timeout)
|
||||
{
|
||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
||||
for(size_t i=0; i< numChannel; ++i) {
|
||||
pvaClientChannelArray[i] = pvaClient->createChannel(channelName[i],providerName);
|
||||
pvaClientChannelArray[i]->issueConnect();
|
||||
}
|
||||
Status returnStatus = Status::Ok;
|
||||
Status status = Status::Ok;
|
||||
size_t numBad = 0;
|
||||
for(size_t i=0; i< numChannel; ++i) {
|
||||
if(numBad==0) {
|
||||
status = pvaClientChannelArray[i]->waitConnect(timeout);
|
||||
} else {
|
||||
status = pvaClientChannelArray[i]->waitConnect(.001);
|
||||
}
|
||||
if(status.isOK()) {
|
||||
++numConnected;
|
||||
isConnected[i] = true;
|
||||
continue;
|
||||
}
|
||||
if(returnStatus.isOK()) returnStatus = status;
|
||||
++numBad;
|
||||
if(numBad>maxNotConnected) break;
|
||||
}
|
||||
return numBad>maxNotConnected ? returnStatus : Status::Ok;
|
||||
}
|
||||
|
||||
|
||||
bool PvaClientMultiChannel::allConnected()
|
||||
{
|
||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
||||
return (numConnected==numChannel) ? true : false;
|
||||
}
|
||||
|
||||
bool PvaClientMultiChannel::connectionChange()
|
||||
{
|
||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
||||
for(size_t i=0; i<numChannel; ++i) {
|
||||
PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
|
||||
Channel::shared_pointer channel = pvaClientChannel->getChannel();
|
||||
Channel::ConnectionState stateNow = channel->getConnectionState();
|
||||
bool connectedNow = stateNow==Channel::CONNECTED ? true : false;
|
||||
if(connectedNow!=isConnected[i]) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
epics::pvData::shared_vector<bool> PvaClientMultiChannel::getIsConnected()
|
||||
{
|
||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
||||
for(size_t i=0; i<numChannel; ++i) {
|
||||
PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
|
||||
if(!pvaClientChannel) {
|
||||
isConnected[i] = false;
|
||||
continue;
|
||||
}
|
||||
Channel::shared_pointer channel = pvaClientChannel->getChannel();
|
||||
Channel::ConnectionState stateNow = channel->getConnectionState();
|
||||
isConnected[i] = (stateNow==Channel::CONNECTED) ? true : false;
|
||||
}
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
PvaClientChannelArray PvaClientMultiChannel::getPvaClientChannelArray()
|
||||
{
|
||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
||||
return pvaClientChannelArray;
|
||||
}
|
||||
|
||||
PvaClientPtr PvaClientMultiChannel::getPvaClient()
|
||||
{
|
||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
||||
return pvaClient;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PvaClientMultiGetDoublePtr PvaClientMultiChannel::createGet()
|
||||
{
|
||||
checkConnected();
|
||||
return PvaClientMultiGetDouble::create(getPtrSelf(),pvaClientChannelArray);
|
||||
}
|
||||
|
||||
|
||||
PvaClientMultiPutDoublePtr PvaClientMultiChannel::createPut()
|
||||
{
|
||||
checkConnected();
|
||||
return PvaClientMultiPutDouble::create(getPtrSelf(),pvaClientChannelArray);
|
||||
}
|
||||
|
||||
|
||||
PvaClientMultiMonitorDoublePtr PvaClientMultiChannel::createMonitor()
|
||||
{
|
||||
checkConnected();
|
||||
return PvaClientMultiMonitorDouble::create(getPtrSelf(), pvaClientChannelArray);
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
331
src/pvaClientMultiChannel.h
Normal file
331
src/pvaClientMultiChannel.h
Normal file
@@ -0,0 +1,331 @@
|
||||
/* pvaClient.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2015.02
|
||||
*/
|
||||
#ifndef PVACLIENTMULTICHANNEL_H
|
||||
#define PVACLIENTMULTICHANNEL_H
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define pvaClientEpicsExportSharedSymbols
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
#include <pv/ntmultiChannel.h>
|
||||
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
|
||||
class PvaClientMultiChannel;
|
||||
typedef std::tr1::shared_ptr<PvaClientMultiChannel> PvaClientMultiChannelPtr;
|
||||
class PvaClientMultiGetDouble;
|
||||
typedef std::tr1::shared_ptr<PvaClientMultiGetDouble> PvaClientMultiGetDoublePtr;
|
||||
class PvaClientMultiPutDouble;
|
||||
typedef std::tr1::shared_ptr<PvaClientMultiPutDouble> PvaClientMultiPutDoublePtr;
|
||||
class PvaClientMultiMonitorDouble;
|
||||
typedef std::tr1::shared_ptr<PvaClientMultiMonitorDouble> PvaClientMultiMonitorDoublePtr;
|
||||
|
||||
|
||||
typedef epics::pvData::shared_vector<PvaClientChannelPtr> PvaClientChannelArray;
|
||||
|
||||
/**
|
||||
* Provides access to multiple channels.
|
||||
*
|
||||
* @author mrk
|
||||
*/
|
||||
class epicsShareClass PvaClientMultiChannel :
|
||||
public std::tr1::enable_shared_from_this<PvaClientMultiChannel>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientMultiChannel);
|
||||
/** Create a PvaClientMultiChannel.
|
||||
* @param pvaClient The interface to pvaClient.
|
||||
* @param channelNames The names of the channel..
|
||||
* @param providerName The name of the provider.
|
||||
* @param maxNotConnected The maximum number of channels that can be disconnected.
|
||||
* @return The interface to the PvaClientMultiChannel
|
||||
*/
|
||||
static PvaClientMultiChannelPtr create(
|
||||
PvaClientPtr const &pvaClient,
|
||||
epics::pvData::shared_vector<const std::string> const & channelNames,
|
||||
std::string const & providerName = "pva",
|
||||
size_t maxNotConnected=0
|
||||
);
|
||||
|
||||
~PvaClientMultiChannel();
|
||||
/** Destroy the pvAccess connection.
|
||||
*/
|
||||
void destroy();
|
||||
/** Get the channelNames.
|
||||
* @return The names.
|
||||
*/
|
||||
epics::pvData::shared_vector<const std::string> getChannelNames();
|
||||
/** Connect to the channels.
|
||||
* This calls issueConnect and waitConnect.
|
||||
* An exception is thrown if connect fails.
|
||||
* @param timeout The time to wait for connecting to the channel.
|
||||
* @return status of request
|
||||
*/
|
||||
epics::pvData::Status connect(double timeout=5);
|
||||
/** Are all channels connected?
|
||||
* @return if all are connected.
|
||||
*/
|
||||
bool allConnected();
|
||||
/** Has a connection state change occured?
|
||||
* @return (true, false) if (at least one, no) channel has changed state.
|
||||
*/
|
||||
bool connectionChange();
|
||||
/** Get the connection state of each channel.
|
||||
* @return The state of each channel.
|
||||
*/
|
||||
epics::pvData::shared_vector<bool> getIsConnected();
|
||||
/** Get the pvaClientChannelArray.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
PvaClientChannelArray getPvaClientChannelArray();
|
||||
/** Get pvaClient.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
PvaClientPtr getPvaClient();
|
||||
/**
|
||||
* create a pvaClientMultiGetDouble
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientMultiGetDoublePtr createGet();
|
||||
/**
|
||||
* create a pvaClientMultiPutDouble
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientMultiPutDoublePtr createPut();
|
||||
/**
|
||||
* Create a pvaClientMultiMonitorDouble.
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientMultiMonitorDoublePtr createMonitor();
|
||||
/** Get the shared pointer to self.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
PvaClientMultiChannelPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
private:
|
||||
PvaClientMultiChannel(
|
||||
PvaClientPtr const &pvaClient,
|
||||
epics::pvData::shared_vector<const std::string> const & channelName,
|
||||
std::string const & providerName,
|
||||
size_t maxNotConnected);
|
||||
|
||||
void checkConnected();
|
||||
|
||||
PvaClientPtr pvaClient;
|
||||
epics::pvData::shared_vector<const std::string> channelName;
|
||||
std::string providerName;
|
||||
size_t maxNotConnected;
|
||||
|
||||
size_t numChannel;
|
||||
epics::pvData::Mutex mutex;
|
||||
|
||||
size_t numConnected;
|
||||
PvaClientChannelArray pvaClientChannelArray;
|
||||
epics::pvData::shared_vector<bool> isConnected;
|
||||
bool isDestroyed;
|
||||
};
|
||||
|
||||
/**
|
||||
* This provides channelGet to multiple channels where each channel has a numeric scalar value field.
|
||||
*/
|
||||
class epicsShareClass PvaClientMultiGetDouble :
|
||||
public std::tr1::enable_shared_from_this<PvaClientMultiGetDouble>
|
||||
{
|
||||
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientMultiGetDouble);
|
||||
|
||||
/**
|
||||
* Factory method that creates a PvaClientMultiGetDouble.
|
||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
||||
* @return The interface.
|
||||
*/
|
||||
static PvaClientMultiGetDoublePtr create(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray);
|
||||
|
||||
~PvaClientMultiGetDouble();
|
||||
|
||||
/** Destroy the pvAccess connection.
|
||||
*/
|
||||
void destroy();
|
||||
/**
|
||||
* Create a channelGet for each channel.
|
||||
*/
|
||||
void connect();
|
||||
/**
|
||||
* get the data.
|
||||
* @return The double[] where each element is the value field of the corresponding channel.
|
||||
*/
|
||||
epics::pvData::shared_vector<double> get();
|
||||
/** Get the shared pointer to self.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
PvaClientMultiGetDoublePtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
private:
|
||||
PvaClientMultiGetDouble(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray);
|
||||
|
||||
PvaClientMultiChannelPtr pvaClientMultiChannel;
|
||||
PvaClientChannelArray pvaClientChannelArray;
|
||||
size_t nchannel;
|
||||
epics::pvData::Mutex mutex;
|
||||
|
||||
epics::pvData::shared_vector<double> doubleValue;
|
||||
std::vector<PvaClientGetPtr> pvaClientGet;
|
||||
bool isGetConnected;
|
||||
bool isDestroyed;
|
||||
};
|
||||
|
||||
/**
|
||||
* This provides channelPut to multiple channels where each channel has a numeric scalar value field.
|
||||
*/
|
||||
class epicsShareClass PvaClientMultiPutDouble :
|
||||
public std::tr1::enable_shared_from_this<PvaClientMultiPutDouble>
|
||||
{
|
||||
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientMultiPutDouble);
|
||||
|
||||
/**
|
||||
* Factory method that creates a PvaClientMultiPutDouble.
|
||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
||||
* @return The interface.
|
||||
*/
|
||||
static PvaClientMultiPutDoublePtr create(
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray);
|
||||
~PvaClientMultiPutDouble();
|
||||
|
||||
/** Destroy the pvAccess connection.
|
||||
*/
|
||||
void destroy();
|
||||
/**
|
||||
* Create a channelPut for each channel.
|
||||
*/
|
||||
void connect();
|
||||
/** put data to each channel as a double
|
||||
* @param data The array of data for each channel.
|
||||
*/
|
||||
void put(epics::pvData::shared_vector<double> const &data);
|
||||
/** Get the shared pointer to self.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
PvaClientMultiPutDoublePtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
private:
|
||||
PvaClientMultiPutDouble(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray);
|
||||
|
||||
PvaClientMultiChannelPtr pvaClientMultiChannel;
|
||||
PvaClientChannelArray pvaClientChannelArray;
|
||||
size_t nchannel;
|
||||
epics::pvData::Mutex mutex;
|
||||
|
||||
std::vector<PvaClientPutPtr> pvaClientPut;
|
||||
bool isPutConnected;
|
||||
bool isDestroyed;
|
||||
};
|
||||
|
||||
/**
|
||||
* This provides a monitor to multiple channels where each channel has a numeric scalar value field.
|
||||
*/
|
||||
class epicsShareClass PvaClientMultiMonitorDouble :
|
||||
public std::tr1::enable_shared_from_this<PvaClientMultiMonitorDouble>
|
||||
{
|
||||
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientMultiMonitorDouble);
|
||||
|
||||
/**
|
||||
* Factory method that creates a PvaClientMultiMonitorDouble.
|
||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
||||
* @return The interface.
|
||||
*/
|
||||
static PvaClientMultiMonitorDoublePtr create(
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray);
|
||||
~PvaClientMultiMonitorDouble();
|
||||
|
||||
/** 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 double[] where each element is the value field of the corresponding channel.
|
||||
*/
|
||||
epics::pvData::shared_vector<double> get();
|
||||
/** Monitor the shared pointer to self.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
PvaClientMultiMonitorDoublePtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
private:
|
||||
PvaClientMultiMonitorDouble(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray);
|
||||
|
||||
PvaClientMultiChannelPtr pvaClientMultiChannel;
|
||||
PvaClientChannelArray pvaClientChannelArray;
|
||||
size_t nchannel;
|
||||
epics::pvData::Mutex mutex;
|
||||
|
||||
epics::pvData::shared_vector<double> doubleValue;
|
||||
std::vector<PvaClientMonitorPtr> pvaClientMonitor;
|
||||
bool isMonitorConnected;
|
||||
bool isDestroyed;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVACLIENTMULTICHANNEL_H */
|
||||
|
||||
/** @page Overview Documentation
|
||||
*
|
||||
* <a href = "../pvaClientOverview.html">pvaClientOverview.html</a>
|
||||
*
|
||||
*/
|
||||
|
||||
130
src/pvaClientMultiGetDouble.cpp
Normal file
130
src/pvaClientMultiGetDouble.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/* pvaClientMultiGetDouble.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();
|
||||
|
||||
|
||||
PvaClientMultiGetDoublePtr PvaClientMultiGetDouble::create(
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray)
|
||||
{
|
||||
PvaClientMultiGetDoublePtr pvaClientMultiGetDouble(
|
||||
new PvaClientMultiGetDouble(pvaMultiChannel,pvaClientChannelArray));
|
||||
return pvaClientMultiGetDouble;
|
||||
}
|
||||
|
||||
PvaClientMultiGetDouble::PvaClientMultiGetDouble(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray)
|
||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||
pvaClientChannelArray(pvaClientChannelArray),
|
||||
nchannel(pvaClientChannelArray.size()),
|
||||
doubleValue(shared_vector<double>(nchannel)),
|
||||
pvaClientGet(std::vector<PvaClientGetPtr>(nchannel,PvaClientGetPtr())),
|
||||
isGetConnected(false),
|
||||
isDestroyed(false)
|
||||
{
|
||||
}
|
||||
|
||||
PvaClientMultiGetDouble::~PvaClientMultiGetDouble()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PvaClientMultiGetDouble::destroy()
|
||||
{
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
}
|
||||
pvaClientChannelArray.clear();
|
||||
}
|
||||
|
||||
void PvaClientMultiGetDouble::connect()
|
||||
{
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
string request = "value";
|
||||
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());
|
||||
}
|
||||
}
|
||||
isGetConnected = true;
|
||||
}
|
||||
|
||||
epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
|
||||
{
|
||||
if(!isGetConnected) connect();
|
||||
shared_vector<bool> 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());
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i])
|
||||
{
|
||||
PVStructurePtr pvStructure = pvaClientGet[i]->getData()->getPVStructure();
|
||||
doubleValue[i] = convert->toDouble(pvStructure->getSubField<PVScalar>("value"));
|
||||
} else {
|
||||
doubleValue[i] = nan("");
|
||||
}
|
||||
}
|
||||
return doubleValue;
|
||||
}
|
||||
|
||||
}}
|
||||
142
src/pvaClientMultiMonitorDouble.cpp
Normal file
142
src/pvaClientMultiMonitorDouble.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/* pvaClientMultiMonitorDouble.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();
|
||||
|
||||
|
||||
PvaClientMultiMonitorDoublePtr PvaClientMultiMonitorDouble::create(
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray)
|
||||
{
|
||||
PvaClientMultiMonitorDoublePtr pvaClientMultiMonitorDouble(
|
||||
new PvaClientMultiMonitorDouble(pvaMultiChannel,pvaClientChannelArray));
|
||||
return pvaClientMultiMonitorDouble;
|
||||
}
|
||||
|
||||
PvaClientMultiMonitorDouble::PvaClientMultiMonitorDouble(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray)
|
||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||
pvaClientChannelArray(pvaClientChannelArray),
|
||||
nchannel(pvaClientChannelArray.size()),
|
||||
doubleValue(shared_vector<double>(nchannel,nan(""))),
|
||||
pvaClientMonitor(std::vector<PvaClientMonitorPtr>(nchannel,PvaClientMonitorPtr())),
|
||||
isMonitorConnected(false),
|
||||
isDestroyed(false)
|
||||
{
|
||||
}
|
||||
|
||||
PvaClientMultiMonitorDouble::~PvaClientMultiMonitorDouble()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PvaClientMultiMonitorDouble::destroy()
|
||||
{
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
}
|
||||
pvaClientChannelArray.clear();
|
||||
}
|
||||
|
||||
void PvaClientMultiMonitorDouble::connect()
|
||||
{
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
string request = "value";
|
||||
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 << " PvaChannelGet::waitConnect " << status.getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) pvaClientMonitor[i]->start();
|
||||
}
|
||||
isMonitorConnected = true;
|
||||
}
|
||||
|
||||
bool PvaClientMultiMonitorDouble::poll()
|
||||
{
|
||||
if(!isMonitorConnected){
|
||||
connect();
|
||||
epicsThreadSleep(.01);
|
||||
}
|
||||
bool result = false;
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
if(pvaClientMonitor[i]->poll()) {
|
||||
doubleValue[i] = pvaClientMonitor[i]->getData()->getDouble();
|
||||
pvaClientMonitor[i]->releaseEvent();
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PvaClientMultiMonitorDouble::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;
|
||||
}
|
||||
|
||||
epics::pvData::shared_vector<double> PvaClientMultiMonitorDouble::get()
|
||||
{
|
||||
return doubleValue;
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
121
src/pvaClientMultiPutDouble.cpp
Normal file
121
src/pvaClientMultiPutDouble.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/* pvaClientMultiPutDouble.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();
|
||||
|
||||
|
||||
PvaClientMultiPutDoublePtr PvaClientMultiPutDouble::create(
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray)
|
||||
{
|
||||
PvaClientMultiPutDoublePtr pvaClientMultiPutDouble(
|
||||
new PvaClientMultiPutDouble(pvaMultiChannel,pvaClientChannelArray));
|
||||
return pvaClientMultiPutDouble;
|
||||
}
|
||||
|
||||
PvaClientMultiPutDouble::PvaClientMultiPutDouble(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray)
|
||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||
pvaClientChannelArray(pvaClientChannelArray),
|
||||
nchannel(pvaClientChannelArray.size()),
|
||||
pvaClientPut(std::vector<PvaClientPutPtr>(nchannel,PvaClientPutPtr())),
|
||||
isPutConnected(false),
|
||||
isDestroyed(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
PvaClientMultiPutDouble::~PvaClientMultiPutDouble()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PvaClientMultiPutDouble::destroy()
|
||||
{
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
}
|
||||
pvaClientChannelArray.clear();
|
||||
}
|
||||
|
||||
void PvaClientMultiPutDouble::connect()
|
||||
{
|
||||
shared_vector<bool> 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());
|
||||
}
|
||||
}
|
||||
isPutConnected = true;
|
||||
}
|
||||
|
||||
void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &data)
|
||||
{
|
||||
if(!isPutConnected) connect();
|
||||
if(data.size()!=nchannel) {
|
||||
throw std::runtime_error("data has wrong size");
|
||||
}
|
||||
shared_vector<bool> 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]);
|
||||
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