added multiChannel support

This commit is contained in:
Marty Kraimer
2015-03-20 10:31:35 -04:00
parent cdc72bc5ae
commit 8f054db6cd
25 changed files with 1378 additions and 64 deletions
+6 -1
View File
@@ -6,6 +6,8 @@ include $(TOP)/configure/CONFIG
LIBRARY += easyPVA
INC += easyPVA.h
INC += easyMultiDouble.h
INC += easyNTMultiChannel.h
LIBSRCS += easyPVA.cpp
LIBSRCS += easyPutData.cpp
@@ -17,9 +19,12 @@ LIBSRCS += easyGet.cpp
LIBSRCS += easyPut.cpp
LIBSRCS += easyMonitor.cpp
LIBSRCS += easyPutGet.cpp
LIBSRCS += easyMultiChannel.cpp
LIBSRCS += easyMultiDouble.cpp
LIBSRCS += easyNTMultiChannel.cpp
#LIBSRCS += easyRPC.cpp
easyPVA_LIBS += pvAccess pvData Com
easyPVA_LIBS += pvAccess pvData nt Com
easyPVA_LIBS += $(EPICS_BASE_IOC_LIBS)
include $(TOP)/configure/RULES
+9 -7
View File
@@ -164,12 +164,6 @@ void EasyChannel::channelStateChange(
if(waitingForConnect) waitForConnect.signal();
}
tr1::shared_ptr<Channel> EasyChannel::getChannel()
{
if(isDestroyed) throw std::runtime_error("easyChannel was destroyed");
return channel;
}
string EasyChannel::getRequesterName()
{
EasyPVAPtr yyy = easyPVA.lock();
@@ -206,6 +200,12 @@ string EasyChannel::getChannelName()
return channelName;
}
Channel::shared_pointer EasyChannel::getChannel()
{
if(isDestroyed) throw std::runtime_error("easyChannel was destroyed");
return channel;
}
void EasyChannel::connect(double timeout)
{
if(isDestroyed) throw std::runtime_error("easyChannel was destroyed");
@@ -225,7 +225,9 @@ void EasyChannel::issueConnect()
}
channelRequester = ChannelRequester::shared_pointer(new ChannelRequesterImpl(this));
channelConnectStatus = Status(Status::STATUSTYPE_ERROR,"createChannel failed");
channelConnectStatus = Status(
Status::STATUSTYPE_ERROR,
getChannelName() + " createChannel failed");
connectState = connectActive;
ChannelProviderRegistry::shared_pointer reg = getChannelProviderRegistry();
ChannelProvider::shared_pointer provider = reg->getProvider(providerName);
+2 -2
View File
@@ -55,7 +55,7 @@ void EasyGetData::checkValue()
void EasyGetData::setMessagePrefix(std::string const & value)
{
messagePrefix = value;
messagePrefix = value + " ";
}
StructureConstPtr EasyGetData::getStructure()
@@ -165,7 +165,7 @@ double EasyGetData::getDouble()
return pvDouble->get();
}
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::runtime_error(notCompatibleScalar);
throw std::runtime_error(messagePrefix + notCompatibleScalar);
}
return convert->toDouble(pvScalar);
}
+2 -2
View File
@@ -58,7 +58,7 @@ void EasyMonitorData::checkValue()
void EasyMonitorData::setMessagePrefix(std::string const & value)
{
messagePrefix = value;
messagePrefix = value + " ";
}
StructureConstPtr EasyMonitorData::getStructure()
@@ -191,7 +191,7 @@ double EasyMonitorData::getDouble()
return pvDouble->get();
}
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::runtime_error(notCompatibleScalar);
throw std::runtime_error(messagePrefix + notCompatibleScalar);
}
return convert->toDouble(pvScalar);
}
+165
View File
@@ -0,0 +1,165 @@
/* easyMultiChannel.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/easyPVA.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 easyPVA {
EasyMultiChannel::EasyMultiChannel(
EasyPVAPtr const &easyPVA,
PVStringArrayPtr const & channelName,
string const & providerName)
: easyPVA(easyPVA),
channelName(channelName),
providerName(providerName),
numChannel(channelName->getLength()),
isConnected(getPVDataCreate()->createPVScalarArray<PVBooleanArray>()),
isDestroyed(false)
{
}
EasyMultiChannel::~EasyMultiChannel()
{
destroy();
}
void EasyMultiChannel::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
easyChannelArray.reset();
}
PVStringArrayPtr EasyMultiChannel::getChannelNames()
{
if(isDestroyed) throw std::runtime_error("easyMultiChannel was destroyed");
return channelName;
}
Status EasyMultiChannel::connect(double timeout,size_t maxNotConnected)
{
if(isDestroyed) throw std::runtime_error("easyMultiChannel was destroyed");
if(easyChannelArray) throw std::runtime_error("easyMultiChannel already connected");
EasyPVAPtr easy = easyPVA.lock();
if(!easy) return Status(Status::STATUSTYPE_ERROR,"easyPVA is gone");
shared_vector<EasyChannelPtr> easyChannel(numChannel,EasyChannelPtr());
PVStringArray::const_svector channelNames = channelName->view();
shared_vector<boolean> isConnected(numChannel,false);
for(size_t i=0; i< numChannel; ++i) {
easyChannel[i] = easy->createChannel(channelNames[i],providerName);
easyChannel[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 = easyChannel[i]->waitConnect(timeout);
} else {
status = easyChannel[i]->waitConnect(.001);
}
if(status.isOK()) {
++numConnected;
isConnected[i] = true;
continue;
}
if(returnStatus.isOK()) returnStatus = status;
++numBad;
if(numBad>maxNotConnected) break;
}
easyChannelArray = EasyChannelArrayPtr(new EasyChannelArray(freeze(easyChannel)));
this->isConnected->replace(freeze(isConnected));
return numBad>maxNotConnected ? returnStatus : Status::Ok;
}
bool EasyMultiChannel::allConnected()
{
if(isDestroyed) throw std::runtime_error("easyMultiChannel was destroyed");
if(!easyChannelArray) throw std::runtime_error("easyMultiChannel not connected");
if(numConnected==numChannel) return true;
return (numConnected==numChannel) ? true : false;
}
bool EasyMultiChannel::connectionChange()
{
if(isDestroyed) throw std::runtime_error("easyMultiChannel was destroyed");
if(!easyChannelArray) throw std::runtime_error("easyMultiChannel not connected");
if(numConnected==numChannel) return true;
PVBooleanArray::const_svector isConnected = this->isConnected->view();
shared_vector<const EasyChannelPtr> channels = *easyChannelArray.get();
for(size_t i=0; i<numChannel; ++i) {
const EasyChannelPtr easyChannel = channels[i];
Channel::shared_pointer channel = easyChannel->getChannel();
Channel::ConnectionState stateNow = channel->getConnectionState();
bool connectedNow = stateNow==Channel::CONNECTED ? true : false;
if(connectedNow!=isConnected[i]) return true;
}
return false;
}
PVBooleanArrayPtr EasyMultiChannel::getIsConnected()
{
if(isDestroyed) throw std::runtime_error("easyMultiChannel was destroyed");
if(!easyChannelArray) throw std::runtime_error("easyMultiChannel not connected");
if(!connectionChange()) return isConnected;
shared_vector<boolean> isConnected(numChannel,false);
shared_vector<const EasyChannelPtr> channels = *easyChannelArray.get();
for(size_t i=0; i<numChannel; ++i) {
const EasyChannelPtr easyChannel = channels[i];
Channel::shared_pointer channel = easyChannel->getChannel();
Channel::ConnectionState stateNow = channel->getConnectionState();
if(stateNow==Channel::CONNECTED) isConnected[i] = true;
}
this->isConnected->replace(freeze(isConnected));
return this->isConnected;
}
EasyChannelArrayWPtr EasyMultiChannel::getEasyChannelArray()
{
if(isDestroyed) throw std::runtime_error("easyMultiChannel was destroyed");
if(!easyChannelArray) throw std::runtime_error("easyMultiChannel not connected");
return easyChannelArray;
}
EasyPVA::weak_pointer EasyMultiChannel::getEasyPVA()
{
if(isDestroyed) throw std::runtime_error("easyMultiChannel was destroyed");
return easyPVA;
}
EasyMultiChannelPtr EasyMultiChannel::create(
EasyPVAPtr const &easyPVA,
PVStringArrayPtr const & channelNames,
string const & providerName)
{
EasyMultiChannelPtr channel(new EasyMultiChannel(easyPVA,channelNames,providerName));
return channel;
}
}}
+138
View File
@@ -0,0 +1,138 @@
/* easyMultiDouble.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
*/
#include <pv/easyMultiDouble.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace easyPVA {
EasyMultiDoublePtr EasyMultiDouble::create(
EasyPVAPtr const & easyPVA,
PVStringArrayPtr const & channelName,
double timeout,
std::string const & providerName)
{
EasyMultiChannelPtr easyMultiChannel(
EasyMultiChannel::create(easyPVA,channelName,providerName));
Status status = easyMultiChannel->connect(timeout,0);
if(!status.isOK()) throw std::runtime_error(status.getMessage());
return EasyMultiDoublePtr(new EasyMultiDouble(easyMultiChannel));
}
EasyMultiDouble::EasyMultiDouble(EasyMultiChannelPtr const &easyMultiChannel)
:
easyMultiChannel(easyMultiChannel)
{}
EasyMultiDouble::~EasyMultiDouble()
{
}
void EasyMultiDouble::createGet()
{
EasyChannelArrayPtr easyChannelArray = easyMultiChannel->getEasyChannelArray().lock();
if(!easyChannelArray) throw std::runtime_error("easyChannelArray is gone");
shared_vector<const EasyChannelPtr> easyChannels = *easyChannelArray;
size_t numChannel = easyChannels.size();
easyGet = std::vector<EasyGetPtr>(numChannel,EasyGetPtr());
bool allOK = true;
string message;
for(size_t i=0; i<numChannel; ++i)
{
easyGet[i] = easyChannels[i]->createGet("value");
easyGet[i]->issueConnect();
}
for(size_t i=0; i<numChannel; ++i)
{
Status status = easyGet[i]->waitConnect();
if(!status.isOK()) {
message = "connect status " + status.getMessage();
allOK = false;
break;
}
}
if(!allOK) throw std::runtime_error(message);
}
void EasyMultiDouble::createPut()
{
EasyChannelArrayPtr easyChannelArray = easyMultiChannel->getEasyChannelArray().lock();
if(!easyChannelArray) throw std::runtime_error("easyChannelArray is gone");
shared_vector<const EasyChannelPtr> easyChannels = *easyChannelArray;
size_t numChannel = easyChannels.size();
easyPut = std::vector<EasyPutPtr>(numChannel,EasyPutPtr());
bool allOK = true;
string message;
for(size_t i=0; i<numChannel; ++i)
{
easyPut[i] = easyChannels[i]->createPut("value");
easyPut[i]->issueConnect();
}
for(size_t i=0; i<numChannel; ++i)
{
Status status = easyPut[i]->waitConnect();
if(!status.isOK()) {
message = "connect status " + status.getMessage();
allOK = false;
break;
}
}
if(!allOK) throw std::runtime_error(message);
}
epics::pvData::shared_vector<double> EasyMultiDouble::get()
{
if(easyGet.empty()) createGet();
shared_vector<const string> channelNames = easyMultiChannel->getChannelNames()->view();
size_t numChannel = channelNames.size();
epics::pvData::shared_vector<double> data(channelNames.size());
for(size_t i=0; i<numChannel; ++i)
{
easyGet[i]->issueGet();
}
for(size_t i=0; i<numChannel; ++i)
{
Status status = easyGet[i]->waitGet();
if(!status.isOK()) {
string message = channelNames[i] + " " + status.getMessage();
throw std::runtime_error(message);
}
data[i] = easyGet[i]->getData()->getDouble();
}
return data;
}
void EasyMultiDouble::put(shared_vector<double> const &value)
{
if(easyPut.empty()) createPut();
shared_vector<const string> channelNames = easyMultiChannel->getChannelNames()->view();
size_t numChannel = channelNames.size();
for(size_t i=0; i<numChannel; ++i)
{
easyPut[i]->getData()->putDouble(value[i]);
easyPut[i]->issuePut();
}
for(size_t i=0; i<numChannel; ++i)
{
Status status = easyPut[i]->waitPut();
if(!status.isOK()) {
string message = channelNames[i] + " " + status.getMessage();
throw std::runtime_error(message);
}
}
}
}}
+81
View File
@@ -0,0 +1,81 @@
/* easyMultiDouble.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 EASYMULTIDOUBLE_H
#define EASYMULTIDOUBLE_H
#ifdef epicsExportSharedSymbols
# define easyPVAEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/easyPVA.h>
namespace epics { namespace easyPVA {
class EasyMultiDouble;
typedef std::tr1::shared_ptr<EasyMultiDouble> EasyMultiDoublePtr;
/**
* @brief Support for multiple channels where each channel has a value field that is a scalar double.
* If any problems arise an exception is thrown.
*
* @author mrk
*/
class epicsShareClass EasyMultiDouble
{
public:
POINTER_DEFINITIONS(EasyMultiDouble);
/**
* @brief Create a EasyMultiDouble.
* @param &easyPVA Interface to EasyPVA
* @param channelName PVStringArray of channelNames.
* @param timeout The timeout in seconds for connecting.
* @param providerName The name of the channelProvider for each channel.
* @return The interface to EasyMultiDouble.
*/
static EasyMultiDoublePtr create(
EasyPVAPtr const & easyPVA,
epics::pvData::PVStringArrayPtr const & channelName,
double timeout = 5.0,
std::string const & providerName = "pva");
/**
* @brief destructor
*/
~EasyMultiDouble();
/**
* @brief destroy any resources used.
*/
void destroy();
/**
* @brief get the value of all the channels.
* @return The data.
*/
epics::pvData::shared_vector<double> get();
/**
* @brief put a new value to each channel.
* @param value The data.
*/
void put(epics::pvData::shared_vector<double> const &value);
EasyMultiChannelPtr getEasyMultiChannel();
private:
EasyMultiDouble(
EasyMultiChannelPtr const & channelName);
void createGet();
void createPut();
EasyMultiChannelPtr easyMultiChannel;
std::vector<EasyGetPtr> easyGet;
std::vector<EasyPutPtr> easyPut;
};
}}
#endif // EASYMULTIDOUBLE_H
+262
View File
@@ -0,0 +1,262 @@
/* easyNTMultiChannel.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
*/
#include <pv/easyNTMultiChannel.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 easyPVA {
EasyNTMultiChannelPtr EasyNTMultiChannel::create(
EasyPVAPtr const & easyPVA,
PVStringArrayPtr const & channelName,
StructureConstPtr const &structure,
double timeout,
std::string const & providerName)
{
EasyMultiChannelPtr easyMultiChannel(
EasyMultiChannel::create(easyPVA,channelName,providerName));
Status status = easyMultiChannel->connect(timeout,0);
if(!status.isOK()) throw std::runtime_error(status.getMessage());
if(!NTMultiChannel::is_a(structure)) throw std::runtime_error("structure is not valid");
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(structure);
pvStructure->getSubField<PVStringArray>("channelName")->
replace(easyMultiChannel->getChannelNames()->view());
pvStructure->getSubField<PVBooleanArray>("isConnected")->
replace(easyMultiChannel->getIsConnected()->view());
NTMultiChannelPtr ntMultiChannel(NTMultiChannel::wrap(pvStructure));
return EasyNTMultiChannelPtr(new EasyNTMultiChannel(easyMultiChannel,ntMultiChannel));
}
EasyNTMultiChannel::EasyNTMultiChannel(
EasyMultiChannelPtr const &easyMultiChannel,
NTMultiChannelPtr const &ntMultiChannel)
:
easyMultiChannel(easyMultiChannel),
ntMultiChannel(ntMultiChannel),
pvUnionArray(ntMultiChannel->getPVStructure()->getSubField<PVUnionArray>("value")),
pvDataCreate(getPVDataCreate())
{}
EasyNTMultiChannel::~EasyNTMultiChannel()
{
}
void EasyNTMultiChannel::createGet()
{
PVStructurePtr pvStructure = ntMultiChannel->getPVStructure();
bool getAlarm = false;
if(pvStructure->getSubField("severity")) getAlarm = true;
if(pvStructure->getSubField("status")) getAlarm = true;
if(pvStructure->getSubField("severity")) getAlarm = true;
bool getTimeStamp = false;
if(pvStructure->getSubField("secondsPastEpoch")) getTimeStamp = true;
if(pvStructure->getSubField("nanoseconds")) getTimeStamp = true;
if(pvStructure->getSubField("userTag")) getTimeStamp = true;
string request = "value";
if(getAlarm) request += ",alarm";
if(getTimeStamp) request += ",timeStamp";
EasyChannelArrayPtr easyChannelArray = easyMultiChannel->getEasyChannelArray().lock();
if(!easyChannelArray) throw std::runtime_error("easyChannelArray is gone");
shared_vector<const EasyChannelPtr> easyChannels = *easyChannelArray;
size_t numChannel = easyChannels.size();
easyGet = std::vector<EasyGetPtr>(numChannel,EasyGetPtr());
bool allOK = true;
string message;
for(size_t i=0; i<numChannel; ++i)
{
easyGet[i] = easyChannels[i]->createGet(request);
easyGet[i]->issueConnect();
}
for(size_t i=0; i<numChannel; ++i)
{
Status status = easyGet[i]->waitConnect();
if(!status.isOK()) {
message = "connect status " + status.getMessage();
allOK = false;
break;
}
}
if(!allOK) throw std::runtime_error(message);
}
void EasyNTMultiChannel::createPut()
{
EasyChannelArrayPtr easyChannelArray = easyMultiChannel->getEasyChannelArray().lock();
if(!easyChannelArray) throw std::runtime_error("easyChannelArray is gone");
shared_vector<const EasyChannelPtr> easyChannels = *easyChannelArray;
size_t numChannel = easyChannels.size();
easyPut = std::vector<EasyPutPtr>(numChannel,EasyPutPtr());
bool allOK = true;
string message;
for(size_t i=0; i<numChannel; ++i)
{
easyPut[i] = easyChannels[i]->createPut("value");
easyPut[i]->issueConnect();
}
for(size_t i=0; i<numChannel; ++i)
{
Status status = easyPut[i]->waitConnect();
if(!status.isOK()) {
message = "connect status " + status.getMessage();
allOK = false;
break;
}
}
if(!allOK) throw std::runtime_error(message);
}
NTMultiChannelPtr EasyNTMultiChannel::get()
{
if(easyGet.empty()) createGet();
PVStructurePtr pvStructure = ntMultiChannel->getPVStructure();
shared_vector<const string> channelNames = easyMultiChannel->getChannelNames()->view();
size_t numChannel = channelNames.size();
bool severityExists = false;
bool statusExists = false;
bool messageExists = false;
bool secondsPastEpochExists = false;
bool nanosecondsExists = false;
bool userTagExists = false;
if(pvStructure->getSubField("severity")) {
severity.resize(numChannel);
severityExists = true;
}
if(pvStructure->getSubField("status")) {
status.resize(numChannel);
statusExists = true;
}
if(pvStructure->getSubField("message")) {
message.resize(numChannel);
messageExists = true;
}
if(pvStructure->getSubField("secondsPastEpoch")) {
secondsPastEpoch.resize(numChannel);
secondsPastEpochExists = true;
}
if(pvStructure->getSubField("nanoseconds")) {
nanoseconds.resize(numChannel);
nanosecondsExists = true;
}
if(pvStructure->getSubField("userTag")) {
userTag.resize(numChannel);
userTagExists = true;
}
valueVector.resize(numChannel);
for(size_t i=0; i<numChannel; ++i)
{
easyGet[i]->issueGet();
}
for(size_t i=0; i<numChannel; ++i)
{
Status stat = easyGet[i]->waitGet();
if(!stat.isOK()) {
string message = channelNames[i] + " " + stat.getMessage();
throw std::runtime_error(message);
}
PVStructurePtr pvStructure = easyGet[i]->getData()->getPVStructure();
PVFieldPtr pvField = pvStructure->getSubField("value");
if(!pvField) {
string message = channelNames[i] + " no value field";
throw std::runtime_error(message);
}
UnionConstPtr u = pvUnionArray->getUnionArray()->getUnion();
if(u->isVariant()) {
PVUnionPtr pvUnion = pvDataCreate->createPVVariantUnion();
pvUnion->set(pvField);
valueVector[i] = pvUnion;
} else {
PVUnionPtr pvUnion = pvDataCreate->createPVUnion(u);
pvUnion->set(pvField);
valueVector[i] = pvUnion;
}
pvField = pvStructure->getSubField("alarm");
if(pvField) {
if(pvAlarm.attach(pvField)) {
pvAlarm.get(alarm);
if(severityExists) severity[i] = alarm.getSeverity();
if(statusExists) status[i] = alarm.getStatus();
if(messageExists) message[i] = alarm.getMessage();
}
}
pvField = pvStructure->getSubField("timeStamp");
if(pvField) {
if(pvTimeStamp.attach(pvField)) {
pvTimeStamp.get(timeStamp);
if(secondsPastEpochExists) secondsPastEpoch[i] =
timeStamp.getSecondsPastEpoch();
if(nanosecondsExists) nanoseconds[i] =
timeStamp.getNanoseconds();
if(userTagExists) userTag[i] = timeStamp.getUserTag();
}
}
}
pvUnionArray->replace(freeze(valueVector));
if(severityExists) {
pvStructure->getSubField<PVIntArray>("severity")->replace(
freeze(severity));
}
if(statusExists) {
pvStructure->getSubField<PVIntArray>("status")->replace(
freeze(status));
}
if(messageExists) {
pvStructure->getSubField<PVStringArray>("message")->replace(freeze(message));
}
if(secondsPastEpochExists) {
pvStructure->getSubField<PVLongArray>("secondsPastEpoch")->replace(freeze(secondsPastEpoch));
}
if(nanosecondsExists) {
pvStructure->getSubField<PVIntArray>("nanoseconds")->replace(freeze(nanoseconds));
}
if(userTagExists) {
pvStructure->getSubField<PVIntArray>("userTag")->replace(freeze(userTag));
}
return ntMultiChannel;
}
void EasyNTMultiChannel::put(NTMultiChannelPtr const &value)
{
if(easyPut.empty()) createPut();
shared_vector<const string> channelNames = easyMultiChannel->getChannelNames()->view();
size_t numChannel = channelNames.size();
PVUnionArrayPtr pvValue = value->getPVStructure()->
getSubField<PVUnionArray>("value");
shared_vector<const PVUnionPtr> valueVector = pvValue->view();
for(size_t i=0; i<numChannel; ++i)
{
try {
PVFieldPtr pvFrom = valueVector[i]->get();
PVFieldPtr pvTo = easyPut[i]->getData()->getValue();
pvTo->copy(*pvFrom);
easyPut[i]->issuePut();
} catch (std::exception e) {
string message = channelNames[i] + e.what();
throw std::runtime_error(message);
}
}
for(size_t i=0; i<numChannel; ++i)
{
Status status = easyPut[i]->waitPut();
if(!status.isOK()) {
string message = channelNames[i] + " " + status.getMessage();
throw std::runtime_error(message);
}
}
}
}}
+102
View File
@@ -0,0 +1,102 @@
/* easyNTMultiChannel.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 EASYNTMULTIChannel_H
#define EASYNTMULTIChannel_H
#ifdef epicsExportSharedSymbols
# define easyPVAEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/easyPVA.h>
namespace epics { namespace easyPVA {
class EasyNTMultiChannel;
typedef std::tr1::shared_ptr<EasyNTMultiChannel> EasyNTMultiChannelPtr;
/**
* @brief Support for multiple channels where each channel has a value field that is a scalar double.
* If any problems arise an exception is thrown.
*
* @author mrk
*/
class epicsShareClass EasyNTMultiChannel
{
public:
POINTER_DEFINITIONS(EasyNTMultiChannel);
/**
* @brief Create a EasyNTMultiChannel.
* @param &easyPVA Interface to EasyPVA
* @param channelName PVStringArray of channelNames.
* @param structure valid NTMultiChannel structure.
* @param timeout Timeout for connecting.
* @param providerName The provider for each channel.
* @return The interface to EasyNTMultiChannel.
*/
static EasyNTMultiChannelPtr create(
EasyPVAPtr const & easyPVA,
epics::pvData::PVStringArrayPtr const & channelName,
epics::pvData::StructureConstPtr const & structure,
double timeout = 5.0,
std::string const & providerName = "pva");
/**
* @brief destructor
*/
~EasyNTMultiChannel();
/**
* @brief destroy any resources used.
*/
void destroy();
/**
* @brief get the value of all the channels.
* @return The data.
*/
epics::nt::NTMultiChannelPtr get();
/**
* @brief put a new value to each channel.
* @param value The data.
*/
void put(epics::nt::NTMultiChannelPtr const &value);
/**
* @brief Get the EasyMultiChannel.
* @return The interface.
*/
EasyMultiChannelPtr getEasyMultiChannel();
private:
EasyNTMultiChannel(
EasyMultiChannelPtr const & channelName,
epics::nt::NTMultiChannelPtr const &ntMultiChannel);
void createGet();
void createPut();
EasyMultiChannelPtr easyMultiChannel;
epics::nt::NTMultiChannelPtr ntMultiChannel;
epics::pvData::PVUnionArrayPtr pvUnionArray;
epics::pvData::PVDataCreatePtr pvDataCreate;
std::vector<EasyGetPtr> easyGet;
std::vector<EasyPutPtr> easyPut;
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> valueVector;
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;
};
}}
#endif // EASYNTMULTIChannel_H
+13
View File
@@ -174,5 +174,18 @@ EasyChannelPtr EasyPVA::createChannel(string const & channelName, string const &
return EasyChannel::create(getPtrSelf(),channelName,providerName);
}
EasyMultiChannelPtr EasyPVA::createMultiChannel(
epics::pvData::PVStringArrayPtr const & channelNames)
{
return createMultiChannel(channelNames,"pva");
}
EasyMultiChannelPtr EasyPVA::createMultiChannel(
epics::pvData::PVStringArrayPtr const & channelNames,
std::string const & providerName)
{
return EasyMultiChannel::create(getPtrSelf(),channelNames,providerName);
}
}}
+118 -31
View File
@@ -32,6 +32,7 @@
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/createRequest.h>
#include <pv/nt.h>
#ifdef easyPVAEpicsExportSharedSymbols
# define epicsExportSharedSymbols
@@ -72,16 +73,13 @@ typedef std::tr1::shared_ptr<EasyArray> EasyArrayPtr;
class EasyRPC;
typedef std::tr1::shared_ptr<EasyRPC> EasyRPCPtr;
class EasyMultiData;
typedef std::tr1::shared_ptr<EasyMultiData> EasyMultiDataPtr;
typedef epics::pvData::shared_vector<const EasyChannelPtr> EasyChannelArray;
typedef std::tr1::shared_ptr<EasyChannelArray> EasyChannelArrayPtr;
typedef std::tr1::weak_ptr<EasyChannelArray> EasyChannelArrayWPtr;
class EasyMultiChannel;
typedef std::tr1::shared_ptr<EasyMultiChannel> EasyMultiChannelPtr;
class EasyMultiGet;
typedef std::tr1::shared_ptr<EasyMultiGet> EasyMultiGetPtr;
class EasyMultiPut;
typedef std::tr1::shared_ptr<EasyMultiPut> EasyMultiPutPtr;
class EasyMultiMonitor;
typedef std::tr1::shared_ptr<EasyMultiMonitor> EasyMultiMonitorPtr;
class EasyMultiChannelGet;
// following are private to easyPVA
class EasyChannelCache;
@@ -165,7 +163,8 @@ public:
* @param channelName The channelName array.
* @return The interface.
*/
EasyMultiChannelPtr createMultiChannel(epics::pvData::StringArray const & channelName);
EasyMultiChannelPtr createMultiChannel(
epics::pvData::PVStringArrayPtr const & channelNames);
/**
* @brief Create an EasyMultiChannel with the specified provider.
* @param channelName The channelName array.
@@ -173,19 +172,8 @@ public:
* @return The interface.
*/
EasyMultiChannelPtr createMultiChannel(
epics::pvData::StringArray const & channelName,
std::string const & providerName);
/**
* @brief Create an EasyMultiChannel with the specified provider.
* @param channelName The channelName.
* @param providerName The provider.
* @param union The union interface for the value field of each channel.
* @return The interface.
*/
EasyMultiChannelPtr createMultiChannel(
epics::pvData::StringArray const & channelName,
std::string const & providerName,
epics::pvData::UnionConstPtr const & u);
epics::pvData::PVStringArrayPtr const & channelNames,
std::string const & providerName);
/**
* @brief Set a requester.
* The default is for EasyPVA to handle messages by printing to System.out.
@@ -235,11 +223,12 @@ public:
* @brief Create a EasyChannel.
* @param easyPVA Interface to EasyPVA
* @param channelName The name of the channel.
* @return The interface to the EasyPVAStructure.
* @return The interface.
*/
static EasyChannelPtr create(
EasyPVAPtr const &easyPVA,
std::string const & channelName) {return create(easyPVA,channelName,"pva");}
std::string const & channelName)
{return create(easyPVA,channelName,"pva");}
/**
* @brief Create a EasyChannel.
* @param channelName The name of the channel.
@@ -260,13 +249,18 @@ public:
* @return The channel name.
*/
std::string getChannelName();
/**
* @brief Get the the channel to which EasyChannel is connected.
* @return The channel interface.
*/
epics::pvAccess::Channel::shared_pointer getChannel();
/**
* @brief Connect to the channel.
* This calls issueConnect and waitConnect.
* An exception is thrown if connect fails.
* @param timeout The time to wait for connecting to the channel.
*/
void connect(double timeout);
void connect(double timeout=5.0);
/**
* @brief Issue a connect request and return immediately.
*/
@@ -479,7 +473,6 @@ private:
void channelStateChange(
epics::pvAccess::Channel::shared_pointer const & channel,
epics::pvAccess::Channel::ConnectionState connectionState);
std::tr1::shared_ptr<epics::pvAccess::Channel> getChannel();
std::string getRequesterName();
void message(
std::string const & message,
@@ -916,7 +909,7 @@ private:
epics::pvData::PVTimeStamp pvTimeStamp;
};
class ChannelProcessRequesterImpl; // private to ChannelProcess.
class ChannelProcessRequesterImpl; // private to EasyProcess
/**
* @brief An easy to use alternative to ChannelProcess.
*
@@ -1016,7 +1009,7 @@ private:
friend class ChannelProcessRequesterImpl;
};
class ChannelGetRequesterImpl; // private to ChannelGet.
class ChannelGetRequesterImpl; // private to EasyGet
/**
* @brief An easy to use alternative to ChannelGet.
*
@@ -1125,7 +1118,7 @@ private:
friend class ChannelGetRequesterImpl;
};
class ChannelPutRequesterImpl; // private to ChannelPut.
class ChannelPutRequesterImpl; // private to EasyPut
/**
* @brief An easy to use alternative to ChannelPut.
*
@@ -1251,7 +1244,7 @@ private :
friend class ChannelPutRequesterImpl;
};
class ChannelPutGetRequesterImpl; // private to ChannelPutGet.
class ChannelPutGetRequesterImpl; // private to EasyPutGet
/**
* @brief An easy to use alternative to ChannelPutGet.
*
@@ -1558,13 +1551,107 @@ private:
friend class ChannelMonitorRequester;
};
/**
* @brief Provides access to multiple channels.
*
* @author mrk
*/
class epicsShareClass EasyMultiChannel :
public std::tr1::enable_shared_from_this<EasyMultiChannel>
{
public:
POINTER_DEFINITIONS(EasyMultiChannel);
/**
* @brief Create a EasyMultiChannel.
* @param channelNames The name. of the channel..
* @param providerName The name of the provider.
* @param u The union interface for each channel.
* @return The interface to the EasyPVAStructure.
*/
static EasyMultiChannelPtr create(
EasyPVAPtr const &easyPVA,
epics::pvData::PVStringArrayPtr const & channelNames,
std::string const & providerName = "pva");
~EasyMultiChannel();
/**
* @brief Destroy the pvAccess connection.
*/
void destroy();
/**
* @brief Get the channelNames.
* @return The names.
*/
epics::pvData::PVStringArrayPtr getChannelNames();
/**
* @brief Connect to the channel.
* This calls issueConnect and waitConnect.
* An exception is thrown if connect fails.
* @param timeout The time to wait for connecting to the channel.
* @param maxNotConnected Maximum number of channels that do not connect.
* @return status of request
*/
epics::pvData::Status connect(
double timeout=5,
size_t maxNotConnected=0);
/**
* 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::PVBooleanArrayPtr getIsConnected();
/**
* Get the easyChannelArray.
* @return The weak shared pointer.
*/
EasyChannelArrayWPtr getEasyChannelArray();
/**
* Get easyPVA.
* @return The weak shared pointer.
*/
EasyPVA::weak_pointer getEasyPVA();
/**
* Get the shared pointer to self.
* @return The shared pointer.
*/
EasyMultiChannelPtr getPtrSelf()
{
return shared_from_this();
}
private:
EasyMultiChannel(
EasyPVAPtr const &pva,
epics::pvData::PVStringArrayPtr const & channelName,
std::string const & providerName);
EasyPVA::weak_pointer easyPVA;
epics::pvData::PVStringArrayPtr channelName;
std::string providerName;
size_t numChannel;
epics::pvData::Mutex mutex;
size_t numConnected;
EasyChannelArrayPtr easyChannelArray;
epics::pvData::PVBooleanArrayPtr isConnected;
bool isDestroyed;
};
}}
#endif /* EASYPVA_H */
/** @page Overview Documentation
*
* <a href = "easyPVA.html">easyPVA.html</a>
* <a href = "overview.html">overview.html</a>
*
*/
+2 -2
View File
@@ -86,7 +86,7 @@ void EasyPutData::postPut(size_t fieldNumber)
void EasyPutData::setMessagePrefix(std::string const & value)
{
messagePrefix = value;
messagePrefix = value + " ";
}
StructureConstPtr EasyPutData::getStructure()
@@ -221,7 +221,7 @@ void EasyPutData::putDouble(double value)
pvDouble->put(value);
}
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::runtime_error(notCompatibleScalar);
throw std::runtime_error(messagePrefix + notCompatibleScalar);
}
convert->fromDouble(pvScalar,value);
}