added multiChannel support
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
|
||||
|
||||
EPICS_BASE=/home/install/epics/base
|
||||
PVCOMMON=/home/hg/pvCommonCPP
|
||||
PVDATA=/home/hg/pvDataCPP
|
||||
PVACCESS=/home/hg/pvAccessCPP
|
||||
V4BASE=/home/hg
|
||||
PVCOMMON=${V4BASE}/pvCommonCPP
|
||||
PVDATA=${V4BASE}/pvDataCPP
|
||||
NORMATIVETYPES=${V4BASE}/normativeTypesCPP
|
||||
PVACCESS=${V4BASE}/pvAccessCPP
|
||||
|
||||
@@ -94,7 +94,7 @@ There is code for NTMultiChannel that helps with access to more complicated data
|
||||
<p>EasyPVA is a synchronous API for accessing PVData via PVAccess. It provides
|
||||
an interface to many of the features provided by pvData and pvAccess.</p>
|
||||
|
||||
</p>This document describes the layout of the source files in this project.</p>
|
||||
<p>This document describes the layout of the source files in this project.</p>
|
||||
<p>
|
||||
A user overview is available via
|
||||
<a
|
||||
|
||||
@@ -121,11 +121,11 @@ This is useful if the client wants to connect to multiple channels in parallel.
|
||||
<h3>EasyChannel</h3>
|
||||
<p>This provides methods for connecting to a channel and for creating instances of
|
||||
EasyField, EasyProcess, ..., EasyRPC.</p>
|
||||
<p>Connection must be made before any crete method is called or
|
||||
<p>Connection must be made before any create method is called or
|
||||
an exception is raised.
|
||||
The following is a synchronous connection request:</p>
|
||||
<pre>
|
||||
easyChannel->connect(5.0); // BLOCKS
|
||||
easyChannel->connect(5.0); // BLOCKS AND THROWS IF NO CONNECT
|
||||
</pre>
|
||||
<p>This blocks until then connection is made or until timout occurs.
|
||||
An exception is raised if the connection request fails.
|
||||
@@ -134,7 +134,7 @@ An exception is raised if the connection request fails.
|
||||
<pre>
|
||||
easyChannel->issueConnect(); // DOES NOT BLOCK
|
||||
.....
|
||||
Status status =easyChannel->waitConnect(5.0); // BLOCKS
|
||||
Status status =easyChannel->waitConnect(5.0); // BLOCKS DOES NOT THROW
|
||||
if(!status.isOK()) {
|
||||
// failure do something
|
||||
}
|
||||
@@ -189,36 +189,36 @@ void easyData->putDouble(5.0);
|
||||
<p>This provides methods to connect to channelGet and to issue get request.
|
||||
To connect via a single synchronous call:</p>
|
||||
<pre>
|
||||
eastGet->connect(); // BLOCKS
|
||||
eastGet->connect(); // BLOCKS AND CAN THROW
|
||||
</pre>
|
||||
<p>This can also be done in two steps:</p>
|
||||
<pre>
|
||||
easyGet->issueConnect(); // DOES NOT BLOCK
|
||||
...
|
||||
Status status = easyGet->waitConnect(); // BLOCKS
|
||||
Status status = easyGet->waitConnect(); // BLOCKS AND DOES NOT HROW
|
||||
</pre>
|
||||
<p>Once connected gets are issued via either:</p>
|
||||
<pre>
|
||||
void easyGet->get();
|
||||
void easyGet->get(); // BLOCKS AND CAN THROW
|
||||
</pre>
|
||||
or
|
||||
<pre>
|
||||
easyGet->issueGet(); // DOES NOT BLOCK
|
||||
...
|
||||
Status status = easyGet->waitGet(); // BLOCKS
|
||||
Status status = easyGet->waitGet(); // BLOCKS AND DOES NOT THROW
|
||||
</pre>
|
||||
<h3>EasyPut</h3>
|
||||
<p>This is similar to easyGet except that it wraps channelPut instead of channelGet.
|
||||
</p>
|
||||
<p>Once connected puts are issued via either:</p>
|
||||
<pre>
|
||||
void easyPut->put();
|
||||
void easyPut->put(); // BLOCKS AND CAN THROW
|
||||
</pre>
|
||||
or
|
||||
<pre>
|
||||
easyPut->issuePut(); // DOES NOT BLOCK
|
||||
...
|
||||
Status status = easyPut->waitPut(); // BLOCKS
|
||||
Status status = easyPut->waitPut(); // BLOCKS AND DOES NOT THROW
|
||||
</pre>
|
||||
<h3>EasyMonitor</h3>
|
||||
<p>Connecting is similar to easyGet and easyPut.
|
||||
@@ -287,7 +287,26 @@ It has methods:</p>
|
||||
<p>Look at javaDoc for details.</p>
|
||||
|
||||
<h2>EasyMultiChannel - Wrapper For Multiple Channels</h2>
|
||||
<p>TBD</p>
|
||||
<h3>EasyMultiChannel</h3>
|
||||
<p>This provides methods for connecting to multiple channels.
|
||||
For now clients has no reason to use this directly.
|
||||
Instead they will use it via EasyMultiDouble or EasyNTMultiChannel.
|
||||
</p>
|
||||
<h3>EasyMultiDouble</h3>
|
||||
<p>This provides support for gets and puts to the value field of multiple channels.
|
||||
Each channel must have a value field that is a numeric scalar.
|
||||
The client always sees that data as a PVDoubleArray.
|
||||
All channels must connect.
|
||||
If any problems occur an exception is thrown.
|
||||
</p>
|
||||
<h3>EasyNTMultiChannel</h3>
|
||||
<p>This provides support for gets and puts to the value field of multiple channels.
|
||||
Each channel must have a value field.
|
||||
The client always sees that data as a NTMultiChannel, which is one
|
||||
of the types provided by normativeTypesCPP.
|
||||
All channels must connect.
|
||||
If any problems occur an exception is thrown.
|
||||
</p>
|
||||
|
||||
</div> <!-- class="contents" -->
|
||||
</body>
|
||||
|
||||
@@ -33,6 +33,21 @@ exampleEasyMonitor_LIBS += pvAccess
|
||||
exampleEasyMonitor_LIBS += pvData
|
||||
exampleEasyMonitor_LIBS += Com
|
||||
|
||||
PROD_HOST += exampleEasyMultiDouble
|
||||
exampleEasyMultiDouble_SRCS += exampleEasyMultiDouble.cpp
|
||||
exampleEasyMultiDouble_LIBS += easyPVA
|
||||
exampleEasyMultiDouble_LIBS += pvAccess
|
||||
exampleEasyMultiDouble_LIBS += pvData
|
||||
exampleEasyMultiDouble_LIBS += Com
|
||||
|
||||
PROD_HOST += exampleEasyNTMultiChannel
|
||||
exampleEasyNTMultiChannel_SRCS += exampleEasyNTMultiChannel.cpp
|
||||
exampleEasyNTMultiChannel_LIBS += easyPVA
|
||||
exampleEasyNTMultiChannel_LIBS += pvAccess
|
||||
exampleEasyNTMultiChannel_LIBS += nt
|
||||
exampleEasyNTMultiChannel_LIBS += pvData
|
||||
exampleEasyNTMultiChannel_LIBS += Com
|
||||
|
||||
#===========================
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
56
example/src/exampleEasyMultiDouble.cpp
Normal file
56
example/src/exampleEasyMultiDouble.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*exampleEasyMultiDouble.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/easyMultiDouble.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::easyPVA;
|
||||
|
||||
|
||||
static void example(EasyPVAPtr const &easyPVA)
|
||||
{
|
||||
cout << "example multiDouble\n";
|
||||
size_t num = 5;
|
||||
shared_vector<string> channelNames(num);
|
||||
channelNames[0] = "exampleDouble01";
|
||||
channelNames[1] = "exampleDouble02";
|
||||
channelNames[2] = "exampleDouble03";
|
||||
channelNames[3] = "exampleDouble04";
|
||||
channelNames[4] = "exampleDouble05";
|
||||
PVStringArrayPtr pvNames =
|
||||
getPVDataCreate()->createPVScalarArray<PVStringArray>();
|
||||
pvNames->replace(freeze(channelNames));
|
||||
EasyMultiDoublePtr multiDouble(EasyMultiDouble::create(easyPVA,pvNames));
|
||||
try {
|
||||
shared_vector<double> data = multiDouble->get();
|
||||
cout << "initial " << data << endl;
|
||||
for(size_t i=0; i<num; ++i) data[i] = data[i] + 1.1;
|
||||
multiDouble->put(data);
|
||||
data = multiDouble->get();
|
||||
cout << "final " << data << endl;
|
||||
} catch (std::runtime_error e) {
|
||||
cout << "exception " << e.what() << endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
EasyPVAPtr easyPVA = EasyPVA::create();
|
||||
example(easyPVA);
|
||||
return 0;
|
||||
}
|
||||
65
example/src/exampleEasyNTMultiChannel.cpp
Normal file
65
example/src/exampleEasyNTMultiChannel.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/*exampleEasyNTMultiChannel.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/easyNTMultiChannel.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::easyPVA;
|
||||
using namespace epics::nt;
|
||||
|
||||
|
||||
static void example(EasyPVAPtr const &easyPVA)
|
||||
{
|
||||
cout << "example ntMultiChannel\n";
|
||||
size_t num = 5;
|
||||
shared_vector<string> channelNames(num);
|
||||
channelNames[0] = "exampleDouble";
|
||||
channelNames[1] = "exampleDoubleArray";
|
||||
channelNames[2] = "exampleString";
|
||||
channelNames[3] = "exampleBoolean";
|
||||
channelNames[4] = "exampleEnum";
|
||||
PVStringArrayPtr pvNames =
|
||||
getPVDataCreate()->createPVScalarArray<PVStringArray>();
|
||||
pvNames->replace(freeze(channelNames));
|
||||
NTMultiChannelBuilderPtr builder = NTMultiChannel::createBuilder();
|
||||
StructureConstPtr structure = builder->
|
||||
addTimeStamp()->
|
||||
addSeverity() ->
|
||||
addStatus() ->
|
||||
addMessage() ->
|
||||
addSecondsPastEpoch() ->
|
||||
addNanoseconds() ->
|
||||
addUserTag() ->
|
||||
createStructure();
|
||||
EasyNTMultiChannelPtr easy = EasyNTMultiChannel::create(
|
||||
easyPVA,pvNames,structure);
|
||||
try {
|
||||
NTMultiChannelPtr nt = easy->get();
|
||||
cout << "initial\n" << nt->getPVStructure() << endl;
|
||||
|
||||
} catch (std::runtime_error e) {
|
||||
cout << "exception " << e.what() << endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
EasyPVAPtr easyPVA = EasyPVA::create();
|
||||
example(easyPVA);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/*exampleEasyProcess.cpp */
|
||||
/*exampleEasyPut.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
@@ -22,7 +22,7 @@ using namespace epics::easyPVA;
|
||||
|
||||
static void examplePut(EasyPVAPtr const &easyPVA)
|
||||
{
|
||||
cout << "example process\n";
|
||||
cout << "example put\n";
|
||||
EasyChannelPtr channel = easyPVA->channel("exampleDouble");
|
||||
EasyPutPtr put = channel->put();
|
||||
EasyPutDataPtr putData = put->getData();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
src/easyMultiChannel.cpp
Normal file
165
src/easyMultiChannel.cpp
Normal 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
src/easyMultiDouble.cpp
Normal file
138
src/easyMultiDouble.cpp
Normal 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
src/easyMultiDouble.h
Normal file
81
src/easyMultiDouble.h
Normal 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
src/easyNTMultiChannel.cpp
Normal file
262
src/easyNTMultiChannel.cpp
Normal 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
src/easyNTMultiChannel.h
Normal file
102
src/easyNTMultiChannel.h
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
|
||||
149
src/easyPVA.h
149
src/easyPVA.h
@@ -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>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -28,8 +28,18 @@ testEasyPutGet_SRCS = testEasyPutGet
|
||||
testHarness_SRCS += testEasyPutGet.cpp
|
||||
TESTS += testEasyPutGet
|
||||
|
||||
TESTPROD_HOST += testEasyMultiDouble
|
||||
testEasyMultiDouble_SRCS = testEasyMultiDouble
|
||||
testHarness_SRCS += testEasyMultiDouble.cpp
|
||||
TESTS += testEasyMultiDouble
|
||||
|
||||
PROD_LIBS += easyPVA pvAccess pvData Com
|
||||
TESTPROD_HOST += testEasyNTMultiChannel
|
||||
testEasyNTMultiChannel_SRCS = testEasyNTMultiChannel
|
||||
testHarness_SRCS += testEasyNTMultiChannel.cpp
|
||||
TESTS += testEasyNTMultiChannel
|
||||
|
||||
|
||||
PROD_LIBS += easyPVA pvAccess pvData nt Com
|
||||
|
||||
testHarness_SRCS += easyAllTests.c
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ int testEasyPutData(void);
|
||||
int testEasyMonitorData(void);
|
||||
int testEasyPutGetMonitor(void);
|
||||
int testEasyPutGet(void);
|
||||
int testEasyMultiDouble(void);
|
||||
int testEasyNTMultiChannel(void);
|
||||
|
||||
void easyAllTests(void)
|
||||
{
|
||||
@@ -23,5 +25,7 @@ void easyAllTests(void)
|
||||
runTest(testEasyMonitorData);
|
||||
runTest(testEasyPutMonitor);
|
||||
runTest(testEasyPut);
|
||||
runTest(testEasyMultiDouble);
|
||||
runTest(testEasyNTMultiChannel);
|
||||
}
|
||||
|
||||
|
||||
156
test/src/testEasyMultiDouble.cpp
Normal file
156
test/src/testEasyMultiDouble.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
/*testEasyMultiDouble.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/easyMultiDouble.h>
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::easyPVA;
|
||||
|
||||
|
||||
static void testGood(EasyPVAPtr const &easyPVA)
|
||||
{
|
||||
bool isOk = true;
|
||||
cout << "\nstarting testGood\n";
|
||||
try {
|
||||
EasyPVAPtr easyPVA(EasyPVA::create());
|
||||
size_t num = 5;
|
||||
shared_vector<string> channelNames(num);
|
||||
channelNames[0] = "exampleDouble01";
|
||||
channelNames[1] = "exampleDouble02";
|
||||
channelNames[2] = "exampleDouble03";
|
||||
channelNames[3] = "exampleDouble04";
|
||||
channelNames[4] = "exampleDouble05";
|
||||
PVStringArrayPtr pvNames =
|
||||
getPVDataCreate()->createPVScalarArray<PVStringArray>();
|
||||
pvNames->replace(freeze(channelNames));
|
||||
EasyMultiDoublePtr multiDouble(EasyMultiDouble::create(easyPVA,pvNames));
|
||||
shared_vector<double> data = multiDouble->get();
|
||||
cout << "initial " << data << endl;
|
||||
for(size_t i=0; i<num; ++i) data[i] = data[i] + 1.1;
|
||||
multiDouble->put(data);
|
||||
data = multiDouble->get();
|
||||
cout << "final " << data << endl;
|
||||
} catch (std::runtime_error e) {
|
||||
cout << "exception " << e.what() << endl;
|
||||
isOk = false;
|
||||
}
|
||||
testOk(isOk==true,"all channels double");
|
||||
}
|
||||
|
||||
static void testGoodMixed(EasyPVAPtr const &easyPVA)
|
||||
{
|
||||
bool isOk = true;
|
||||
cout << "\nstarting testGoodMixed\n";
|
||||
try {
|
||||
EasyPVAPtr easyPVA(EasyPVA::create());
|
||||
size_t num = 5;
|
||||
shared_vector<string> channelNames(num);
|
||||
channelNames[0] = "exampleByte";
|
||||
channelNames[1] = "exampleShort";
|
||||
channelNames[2] = "exampleInt";
|
||||
channelNames[3] = "exampleFloat";
|
||||
channelNames[4] = "exampleDouble";
|
||||
PVStringArrayPtr pvNames =
|
||||
getPVDataCreate()->createPVScalarArray<PVStringArray>();
|
||||
pvNames->replace(freeze(channelNames));
|
||||
EasyMultiDoublePtr multiDouble(EasyMultiDouble::create(easyPVA,pvNames));
|
||||
shared_vector<double> data = multiDouble->get();
|
||||
cout << "initial " << data << endl;
|
||||
for(size_t i=0; i<num; ++i) data[i] = data[i] + 1.1;
|
||||
multiDouble->put(data);
|
||||
data = multiDouble->get();
|
||||
cout << "final " << data << endl;
|
||||
} catch (std::runtime_error e) {
|
||||
cout << "exception " << e.what() << endl;
|
||||
isOk = false;
|
||||
}
|
||||
testOk(isOk==true,"channels mixed type");
|
||||
}
|
||||
|
||||
static void testChannelNotExist(EasyPVAPtr const &easyPVA)
|
||||
{
|
||||
bool isOk = true;
|
||||
cout << "\nstarting testChannelNotExist\n";
|
||||
try {
|
||||
EasyPVAPtr easyPVA(EasyPVA::create());
|
||||
size_t num = 5;
|
||||
shared_vector<string> channelNames(num);
|
||||
channelNames[0] = "exampleDouble01";
|
||||
channelNames[1] = "exampleDouble02";
|
||||
channelNames[2] = "exampleDouble03";
|
||||
channelNames[3] = "NoneExistChannel";
|
||||
channelNames[4] = "exampleDouble05";
|
||||
PVStringArrayPtr pvNames =
|
||||
getPVDataCreate()->createPVScalarArray<PVStringArray>();
|
||||
pvNames->replace(freeze(channelNames));
|
||||
EasyMultiDoublePtr multiDouble(EasyMultiDouble::create(easyPVA,pvNames));
|
||||
shared_vector<double> data = multiDouble->get();
|
||||
cout << "initial " << data << endl;
|
||||
for(size_t i=0; i<num; ++i) data[i] = data[i] + 1.1;
|
||||
multiDouble->put(data);
|
||||
data = multiDouble->get();
|
||||
cout << "final " << data << endl;
|
||||
} catch (std::runtime_error e) {
|
||||
cout << "exception " << e.what() << endl;
|
||||
isOk = false;
|
||||
}
|
||||
testOk(isOk==false,"channel not exist");
|
||||
}
|
||||
|
||||
static void testNonNumeric(EasyPVAPtr const &easyPVA)
|
||||
{
|
||||
bool isOk = true;
|
||||
cout << "\nstarting testNonNumeric\n";
|
||||
try {
|
||||
EasyPVAPtr easyPVA(EasyPVA::create());
|
||||
size_t num = 5;
|
||||
shared_vector<string> channelNames(num);
|
||||
channelNames[0] = "exampleDouble01";
|
||||
channelNames[1] = "exampleDouble02";
|
||||
channelNames[2] = "exampleDouble03";
|
||||
channelNames[3] = "exampleDouble04";
|
||||
channelNames[4] = "exampleDouble05Array";
|
||||
PVStringArrayPtr pvNames =
|
||||
getPVDataCreate()->createPVScalarArray<PVStringArray>();
|
||||
pvNames->replace(freeze(channelNames));
|
||||
EasyMultiDoublePtr multiDouble(EasyMultiDouble::create(easyPVA,pvNames));
|
||||
shared_vector<double> data = multiDouble->get();
|
||||
cout << "initial " << data << endl;
|
||||
for(size_t i=0; i<num; ++i) data[i] = data[i] + 1.1;
|
||||
multiDouble->put(data);
|
||||
data = multiDouble->get();
|
||||
cout << "final " << data << endl;
|
||||
} catch (std::runtime_error e) {
|
||||
cout << "exception " << e.what() << endl;
|
||||
isOk = false;
|
||||
}
|
||||
testOk(isOk==false,"channel not numeric");
|
||||
}
|
||||
|
||||
MAIN(testEasyMultiDouble)
|
||||
{
|
||||
cout << "\nstarting testEasyMultiDouble\n";
|
||||
testPlan(4);
|
||||
EasyPVAPtr easyPVA = EasyPVA::create();
|
||||
testGood(easyPVA);
|
||||
testGoodMixed(easyPVA);
|
||||
testChannelNotExist(easyPVA);
|
||||
testNonNumeric(easyPVA);
|
||||
cout << "done\n";
|
||||
return 0;
|
||||
}
|
||||
132
test/src/testEasyNTMultiChannel.cpp
Normal file
132
test/src/testEasyNTMultiChannel.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/*testEasyNTMultiChannel.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/easyNTMultiChannel.h>
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::easyPVA;
|
||||
using namespace epics::nt;
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
|
||||
static void testGood(EasyPVAPtr const &easyPVA)
|
||||
{
|
||||
PVDataCreatePtr pvDataCreate(getPVDataCreate());
|
||||
bool isOk = true;
|
||||
cout << "\nstarting testGood\n";
|
||||
try {
|
||||
EasyPVAPtr easyPVA(EasyPVA::create());
|
||||
size_t num = 5;
|
||||
shared_vector<string> channelNames(num);
|
||||
channelNames[0] = "exampleDouble";
|
||||
channelNames[1] = "exampleDoubleArray";
|
||||
channelNames[2] = "exampleString";
|
||||
channelNames[3] = "exampleBoolean";
|
||||
channelNames[4] = "exampleEnum";
|
||||
PVStringArrayPtr pvNames = pvDataCreate->
|
||||
createPVScalarArray<PVStringArray>();
|
||||
pvNames->replace(freeze(channelNames));
|
||||
NTMultiChannelBuilderPtr builder = NTMultiChannel::createBuilder();
|
||||
StructureConstPtr structure = builder->
|
||||
addTimeStamp()->
|
||||
addSeverity() ->
|
||||
addStatus() ->
|
||||
addMessage() ->
|
||||
addSecondsPastEpoch() ->
|
||||
addNanoseconds() ->
|
||||
addUserTag() ->
|
||||
createStructure();
|
||||
EasyNTMultiChannelPtr easy = EasyNTMultiChannel::create(
|
||||
easyPVA,pvNames,structure);
|
||||
NTMultiChannelPtr nt = easy->get();
|
||||
cout << "initial\n" << nt->getPVStructure() << endl;
|
||||
for(size_t numtimes=0; numtimes<3; ++numtimes) {
|
||||
PVUnionArrayPtr pvValue = nt->getPVStructure()->
|
||||
getSubField<PVUnionArray>("value");
|
||||
shared_vector<PVUnionPtr> valueVector = pvValue->reuse();
|
||||
for(size_t i=0; i<num; ++i)
|
||||
{
|
||||
PVFieldPtr pvField = valueVector[i]->get();
|
||||
Type type = pvField->getField()->getType();
|
||||
if(type==scalar) {
|
||||
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
|
||||
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
|
||||
if(ScalarTypeFunc::isNumeric(scalarType)) {
|
||||
double oldValue = pvScalar->getAs<double>();
|
||||
oldValue++;
|
||||
pvScalar->putFrom<double>(oldValue);
|
||||
} else if(scalarType==pvString) {
|
||||
PVStringPtr pv = static_pointer_cast<PVString>(pvField);
|
||||
string val = pv->get();
|
||||
val += " added";
|
||||
pv->put(val);
|
||||
} else if(scalarType==pvBoolean) {
|
||||
PVBooleanPtr pv = static_pointer_cast<PVBoolean>(pvField);
|
||||
bool val = pv->get();
|
||||
pv->put(!val);
|
||||
}
|
||||
} else if(type==scalarArray) {
|
||||
PVScalarArrayPtr pv =
|
||||
static_pointer_cast<PVScalarArray>(pvField);
|
||||
ScalarType scalarType = pv->getScalarArray()->getElementType();
|
||||
if(scalarType==pvDouble) {
|
||||
PVDoubleArrayPtr pvd = static_pointer_cast<PVDoubleArray>(pv);
|
||||
shared_vector<double> valvec = pvd->reuse();
|
||||
if(valvec.capacity()==0) {
|
||||
valvec.resize(4);
|
||||
for(size_t i=0; i<valvec.size(); ++i) valvec[i] = i;
|
||||
}
|
||||
for(size_t i=0; i<valvec.size(); ++i) valvec[i] = valvec[i] + 1.0;
|
||||
pvd->replace(freeze(valvec));
|
||||
}
|
||||
} else if(type==epics::pvData::structure) {
|
||||
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||
PVIntPtr pv = pvStructure->getSubField<PVInt>("index");
|
||||
if(pv) {
|
||||
PVStringArrayPtr choices = pvStructure->getSubField<PVStringArray>("choices");
|
||||
if(choices) {
|
||||
int32 nchoices = choices->getLength();
|
||||
int32 oldval = pv->get();
|
||||
int32 newval = (oldval==nchoices) ? 0 : ++oldval;
|
||||
pv->put(newval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pvValue->replace(freeze(valueVector));
|
||||
easy->put(nt);
|
||||
nt = easy->get();
|
||||
cout << "after put\n" << nt->getPVStructure() << endl;
|
||||
}
|
||||
} catch (std::runtime_error e) {
|
||||
cout << "exception " << e.what() << endl;
|
||||
isOk = false;
|
||||
}
|
||||
testOk(isOk==true,"no problems");
|
||||
}
|
||||
|
||||
|
||||
MAIN(testEasyNTMultiChannel)
|
||||
{
|
||||
cout << "\nstarting testEasyNTMultiChannel\n";
|
||||
testPlan(1);
|
||||
EasyPVAPtr easyPVA = EasyPVA::create();
|
||||
testGood(easyPVA);
|
||||
cout << "done\n";
|
||||
return 0;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/*testEasyData.cpp */
|
||||
/*testEasyPutData.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*exampleEasyPutGetMonitor.cpp */
|
||||
/*testEasyPutGetMonitor.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
|
||||
Reference in New Issue
Block a user