added support for multi channel double

This commit is contained in:
mrkraimer
2015-07-31 15:46:22 -04:00
parent 985e1c5900
commit 4b3e6c641b
10 changed files with 1027 additions and 11 deletions

View File

@@ -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

View File

@@ -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;
}

View 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;
}

View File

@@ -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;
}

View File

@@ -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)

View 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
View 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>
*
*/

View 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;
}
}}

View 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;
}
}}

View 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());
}
}
}
}}