diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a787a96
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+Status
+===========
+
+* The API should be almost ready for feature freeze for release 4.5
+* Everything defined in pvaClient.h should be ready but see below for remaining work.
+* Everything defined in pvaClientMultiChannel.h is ready but see below for remaining work.
+
+Examples
+------------
+
+The examples require the database in pvaClientTestCPP.
+For example:
+
+ mrk> pwd
+ /home/epicsv4/pvaClientTestCPP/database/iocBoot/exampleDatabase
+ mrk> ../../bin/linux-x86_64/exampleDatabase st.cmd
+
+pvaClientChannel
+---------------
+
+Channel::getField and channelArray are not supported for release 4.5.
+
+pvaClientMultiChannel
+---------------
+
+For release 4.6 support is available for multiDouble and NTMultiChannel.
+In the future additional support should be provided that at least includes NTScalarMultiChannel.
+
+Testing with some channels not connected have not been done.
+At least some testing with missing channels should be done before release 4.5
diff --git a/README.txt b/README.txt
deleted file mode 100644
index 123cdc6..0000000
--- a/README.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-To build do the following:
-
-cd configure
-cp ExampleRELEASE.local RELEASE.local
-edit RELEASE.local
-cd ..
-make
-
-Now read documentation/pvaClientCPP.html
diff --git a/documentation/easyPVA_20150609.html b/documentation/easyPVA_20150609.html
deleted file mode 100644
index dec0657..0000000
--- a/documentation/easyPVA_20150609.html
+++ /dev/null
@@ -1,222 +0,0 @@
-
-
-
-
-
- EPICS easyPVA
-
-
-
-
-
-
-
-
-
-
-
-
-
EPICS easyPVA
-
-
EPICS V4 Working Group, Working Draft,
-25-Mar-2015
-
- This version:
- easyPVA.html
-
- Latest version:
- easyPVA_20150609.html
-
- Previous version:
- easyPVA_20150325.html
-
- Editors:
- Marty Kraimer, BNL
- Matej Sekoranja, Cosylab
-
-
-
Abstract
-
NO LONGER SUPPPORTED:
-The functionality has been moved to pvAccessCPP and EasyPva renamed to Pva.
-
-
-
EasyPVA (Easy PVAccess) is a software library that provides to an EPICS client programmer, a friendly
-client side programming interface to the data of an EPICS based control system. It is intended
-for such uses as rapid development of ad hoc programs by controls engineers, or to provide
-scientists a way to directly develop analytical applications.
-
-
Specifically, easyPVA provides an easy interface for pvAccess, which is the
-software support for high speed controls network communications used in EPICS version 4.
-PvAccess provides a callback based interface, which can be hard to use.
-EasyPVA provides an interface that does not require callbacks even for monitors.
-
-
-EasyChannel provides many "convenience" methods to directly get and put
-scalar and scalarArray data types.
-Additional methods provide access to the full features of pvAccess.
-
-
-EasyMultiChannel provides access to data from multiple channels.
-It can be used directly by a client or via EasyMultiDouble or EasyNTMultiChannel.
-EasyMultiDouble allows the client to get and put data to multiple channels.
-But each channel must have a value field that is a numeric scalar.
-EasyNTMultiChannel allows the client to get and put data to multiple channels.
-Each channel must have a value field.
-The data for the channels is presented via normative type NTMultiChannel.
-
-
-
For more information about EPICS generally, please refer to the home page of the Experimental Physics and Industrial
- Control System .
-
-
-
-
Status of this Document and of the EasyPVA Software
-
-
EasyPVACPP is ready for use.
-
-
-
-
-
Table of Contents
-
-
-
-
-
-
-
Introduction
-
-
EasyPVA is a synchronous API for accessing PVData via PVAccess. It provides
-an interface to many of the features provided by pvData and pvAccess.
-
-
This document describes the layout of the source files in this project.
-
-A user overview is available via
-overview.html
-
-
-
-Doxygen documentation is available at
-doxygenDoc
-
-
-
Building
-
After obtaining the source:
-
-cd configure
-cp ExampleRELEASE.local RELEASE.local
-
-
Edit RELEASE.local so that all path names are correct for you environment.
-
-
-Then:
-
-cd ..
-make
-
-
-
Example and Test Database
-
The examples and tests require that an example pvAccess server is runnimg.
-This distribution has a file exampleDatabaseEasyPVA.zip .
-When unzipped this is used to create an example IOC database.
-The database has the record used by the examples are tests that come with easyPVAJava.
-It uses pvDatabaseCPP to build the database.
-
-
-After unzipping the file:
-
-
-cd configure
-cp ExampleRELEASE.local RELEASE.local
-edit RELEASE.local
-cd ..
-make
-cd iocBoot/exampleDatabase
-../../bin/<arch:>/exampleDatabase st.cmd
-
-
Testing
-
The tests will fail unless the example database is running.
-
Once it is running:
-
-make runtests
-
-
Examples
-
Examples are in directory example/src .
-An example of how to run them is:
-
-mrk> pwd
-/home/hg/easyPVACPP/example
-mrk> bin/linux-x86_64/exampleEasyGet
-
-
The following is a brief description of each example.
-In order to understand each example it
-helps to also bee loooking at the source for the example.
-
exampleEasyGet
-
This has a number of examples:
-
- exampleDouble
-
- This shows two methods for getting data from a channel that has a numeric
- scalar value field.
-
- exampleDoubleArray
-
- This shows two methods for getting data from a channel that has a
- double array value field.
-
- exampleCADouble
-
- This is like exampleDouble except it uses provider ca .
-
- exampleCADoubleArray
-
- This is like exampleDoubleArray except it uses provider ca .
-
- examplePowerSupply
-
- This is an example of getting data from a channel that does not
- have a value field.
-
-
-
exampleEasyMonitor
-
This is an example of creating a monitor on a channel.
-It monitors a channel that models a powerSupply, i. e. it is not a "standard" record.
-It does not have a value field.
-
-
After starting the example a change can be made to the powerSupply by issuing:
-
-pvput -r "power.value,voltage.value" examplePowerSupply 6 6
-
-
exampleEasyPut
-
This example gets and puts to channel exampleDouble.
-
exampleEasyProcess
-
This example makes a process request to channel exampleDouble.
-
helloWorldPutGet
-
This is an example of issuing a channelPutGet.
-
exampleEasyMultiDouble
-
This is an example of issuing gets and puts to multiple channels where each
-channel has a numeric scalar value field.
-
exampleEasyNTMultiChannel
-
This is an example of using NDMultiChannel to obtain data from multiple channels.
-
-
helloWorldRPC
-
This is an example of issuing a channelRPC request.
-It does not use easyPVA.
-
-
-
diff --git a/documentation/easyPVA_20150325.html b/documentation/pvaClientCPP_20150803.html
similarity index 58%
rename from documentation/easyPVA_20150325.html
rename to documentation/pvaClientCPP_20150803.html
index 487937d..10eb3b5 100644
--- a/documentation/easyPVA_20150325.html
+++ b/documentation/pvaClientCPP_20150803.html
@@ -4,7 +4,7 @@
- EPICS easyPVA
+ EPICS pva
-
EPICS easyPVA
+
EPICS pvaClientCPP
EPICS V4 Working Group, Working Draft,
-25-Mar-2015
+03-August-2015
This version:
easyPVA.html
+ href="pvaClientCPP.html">pvaClientCPP.html
Latest version:
easyPVA_20150325.html
-
+ href="pvaClientCPP_20150803.html">pvaClientCPP_20150803.html
+
Previous version:
- none
+ pvaClientCPP_20150626.html
+
Editors:
Marty Kraimer, BNL
- Matej Sekoranja, Cosylab
Abstract
-
EasyPVA (Easy PVAccess) is a software library that provides to an EPICS client programmer, a friendly
+
pvaClient is a software library that provides to an EPICS client programmer, a friendly
client side programming interface to the data of an EPICS based control system. It is intended
for such uses as rapid development of ad hoc programs by controls engineers, or to provide
scientists a way to directly develop analytical applications.
-
Specifically, easyPVA provides an easy interface for pvAccess, which is the
+
Specifically, pvaClient provides a synchronous interface for pvAccess, which is the
software support for high speed controls network communications used in EPICS version 4.
-PvAccess provides a callback based interface, which can be hard to use.
-EasyPVA provides an interface that does not require callbacks even for monitors.
+pvAccess provides a callback based interface, which can be hard to use.
+pvaClient provides an interface that does not require callbacks even for monitors.
-EasyChannel provides many "convenience" methods to directly get and put
+pvaClientChannel provides many "convenience" methods to directly get and put
scalar and scalarArray data types.
Additional methods provide access to the full features of pvAccess.
-EasyMultiChannel provides access to data from multiple channels.
-It can be used directly by a client or via EasyMultiDouble or EasyNTMultiChannel.
-EasyMultiDouble allows the client to get and put data to multiple channels.
+pvaClientMultiChannel provides access to data from multiple channels.
+It can be used directly by a client or via pvaClientMultiDouble or pvaClientNTMultiChannel.
+pvaClientMultiDouble allows the client to get and put data to multiple channels.
But each channel must have a value field that is a numeric scalar.
-EasyNTMultiChannel allows the client to get and put data to multiple channels.
+pvaClientNTMultiChannel allows the client to get and put data to multiple channels.
Each channel must have a value field.
The data for the channels is presented via normative type NTMultiChannel.
@@ -78,9 +79,9 @@ The data for the channels is presented via normative type NTMultiChannel.
-
Status of this Document and of the EasyPVA Software
+
Status of this Document and of the pvaClient Software
-
EasyPVACPP is ready for use.
+
pvaClientCPP is ready for use.
@@ -94,14 +95,14 @@ The data for the channels is presented via normative type NTMultiChannel.
Introduction
-EasyPVA is a synchronous API for accessing PVData via PVAccess. It provides
+
pvaClient is a synchronous API for accessing PVData via PVAccess. It provides
an interface to many of the features provided by pvData and pvAccess.
This document describes the layout of the source files in this project.
A user overview is available via
overview.html
+href="./pvaClientOverview.html">pvaClientOverview.html
@@ -110,58 +111,27 @@ Doxygen documentation is available at
href="./html/index.html">doxygenDoc
-Building
-After obtaining the source:
+Example Database
+The examples require that the database provided by project pvaClientTestCPP
+is running.
+For example:
-cd configure
-cp ExampleRELEASE.local RELEASE.local
-
-Edit RELEASE.local so that all path names are correct for you environment.
-
-
-Then:
-
-cd ..
-make
-
-
-Example and Test Database
-The examples and tests require that an example pvAccess server is runnimg.
-This distribution has a file exampleDatabaseEasyPVA.zip .
-When unzipped this is used to create an example IOC database.
-The database has the record used by the examples are tests that come with easyPVAJava.
-It uses pvDatabaseCPP to build the database.
-
-
-After unzipping the file:
-
-
-cd configure
-cp ExampleRELEASE.local RELEASE.local
-edit RELEASE.local
-cd ..
-make
-cd iocBoot/exampleDatabase
-../../bin/<arch:>/exampleDatabase st.cmd
-
-Testing
-The tests will fail unless the example database is running.
-Once it is running:
-
-make runtests
+mrk> pwd
+/home/epicsv4/pvaClientTestCPP/database/iocBoot/exampleDatabase
+mrk> ../../bin/linux-x86_64/exampleDatabase st.cmd
Examples
Examples are in directory example/src .
An example of how to run them is:
mrk> pwd
-/home/hg/easyPVACPP/example
-mrk> bin/linux-x86_64/exampleEasyGet
+/home/epicsv4/pvaClientCPP/example
+mrk> bin/linux-x86_64/examplePvaClientGet
The following is a brief description of each example.
In order to understand each example it
-helps to also bee loooking at the source for the example.
-exampleEasyGet
+helps to also look at the source for the example.
+examplePvaClientGet
This has a number of examples:
exampleDouble
@@ -188,30 +158,25 @@ helps to also bee loooking at the source for the example.
have a value field.
-exampleEasyMonitor
+examplePvaClientMonitor
This is an example of creating a monitor on a channel.
-It monitors a channel that models a powerSupply, i. e. it is not a "standard" record.
-It does not have a value field.
+It monitors a scalar double field.
+It also issues puts to the same channel so that it can make the monitors occur.
-After starting the example a change can be made to the powerSupply by issuing:
-
-pvput -r "power.value,voltage.value" examplePowerSupply 6 6
-
-exampleEasyPut
-This example gets and puts to channel exampleDouble.
-exampleEasyProcess
+examplePvaClientPut
+This example gets and puts to channels exampleDouble
+and exampleDoubleArray.
+examplePvaClientProcess
This example makes a process request to channel exampleDouble.
helloWorldPutGet
This is an example of issuing a channelPutGet.
-exampleEasyMultiDouble
-This is an example of issuing gets and puts to multiple channels where each
-channel has a numeric scalar value field.
-exampleEasyNTMultiChannel
-This is an example of using NDMultiChannel to obtain data from multiple channels.
+
examplePvaClientMultiDouble
+This is an example of using pvaClientMultiChannel,
+pvaClientMultiGetDouble, pvaClientMultiPutDouble, and pvaClientMultiMonitorDouble.
helloWorldRPC
This is an example of issuing a channelRPC request.
-It does not use easyPVA.
+It does not use pva.
diff --git a/example/src/Makefile b/example/src/Makefile
index 4f48aaf..6654b6e 100644
--- a/example/src/Makefile
+++ b/example/src/Makefile
@@ -40,6 +40,13 @@ examplePvaClientMultiDouble_LIBS += pvAccess
examplePvaClientMultiDouble_LIBS += pvData
examplePvaClientMultiDouble_LIBS += Com
+PROD_HOST += examplePvaClientNTMulti
+examplePvaClientNTMulti_SRCS += examplePvaClientNTMulti.cpp
+examplePvaClientNTMulti_LIBS += pvaClient
+examplePvaClientNTMulti_LIBS += pvAccess
+examplePvaClientNTMulti_LIBS += pvData
+examplePvaClientNTMulti_LIBS += Com
+
PROD_HOST += helloWorldRPC
helloWorldRPC_SRCS += helloWorldRPC.cpp
helloWorldRPC_LIBS += pvaClient
diff --git a/example/src/examplePvaClientMultiDouble.cpp b/example/src/examplePvaClientMultiDouble.cpp
index 2c5b986..054024c 100644
--- a/example/src/examplePvaClientMultiDouble.cpp
+++ b/example/src/examplePvaClientMultiDouble.cpp
@@ -33,7 +33,7 @@ cout << "num " << num << " names " << channelNames << endl;
PvaClientMultiPutDoublePtr multiPut(multiChannel->createPut());
PvaClientMultiMonitorDoublePtr multiMonitor(multiChannel->createMonitor());
shared_vector data(num,0);
- for(double value = 0.0; value< 1.0; value+= .2) {
+ for(double value = 0.2; value< 2.3; value+= 1.0) {
try {
for(size_t i=0; i channelNames(num);
channelNames[0] = "double01";
- channelNames[1] = "double02";
+ channelNames[1] = "int01";
channelNames[2] = "double03";
channelNames[3] = "double04";
channelNames[4] = "double05";
@@ -68,7 +68,7 @@ int main(int argc,char *argv[])
example(pva,"ca",names);
channelNames = shared_vector(num);
channelNames[0] = "exampleDouble01";
- channelNames[1] = "exampleDouble02";
+ channelNames[1] = "exampleInt";
channelNames[2] = "exampleDouble03";
channelNames[3] = "exampleDouble04";
channelNames[4] = "exampleDouble05";
diff --git a/example/src/examplePvaClientNTMulti.cpp b/example/src/examplePvaClientNTMulti.cpp
new file mode 100644
index 0000000..be72505
--- /dev/null
+++ b/example/src/examplePvaClientNTMulti.cpp
@@ -0,0 +1,141 @@
+/*examplePvaClientNTMulti.cpp */
+/**
+ * Copyright - See the COPYRIGHT that is included with this distribution.
+ * EPICS pvData is distributed subject to a Software License Agreement found
+ * in file LICENSE that is included with this distribution.
+ */
+/**
+ * @author mrk
+ */
+
+/* Author: Marty Kraimer */
+
+#include
+
+#include
+#include
+
+using std::tr1::static_pointer_cast;
+using namespace std;
+using namespace epics::pvData;
+using namespace epics::pvAccess;
+using namespace epics::pvaClient;
+
+static PVDataCreatePtr pvDataCreate = getPVDataCreate();
+static ConvertPtr convert = getConvert();
+
+static void setValue(PVUnionPtr const &pvUnion, double value)
+{
+ UnionConstPtr u = pvUnion->getUnion();
+ FieldConstPtr field = u->getField(0);
+ Type type = field->getType();
+ if(type==scalar) {
+ ScalarConstPtr scalar = static_pointer_cast(field);
+ ScalarType scalarType = scalar->getScalarType();
+ if(scalarType==pvDouble) {
+ PVDoublePtr pvValue = static_pointer_cast(
+ pvDataCreate->createPVScalar(pvDouble));
+ pvValue->put(value);
+ pvUnion->set(0,pvValue);
+ return;
+ }
+ if(scalarType==pvString) {
+ PVStringPtr pvValue = static_pointer_cast(
+ pvDataCreate->createPVScalar(pvString));
+ stringstream ss;
+ ss << "value" << value;
+ pvValue->put(ss.str());
+ pvUnion->set(0,pvValue);
+ return;
+ }
+ throw std::runtime_error("only pvDouble and pvString are supported");
+ }
+ if(type==scalarArray) {
+ ScalarArrayConstPtr scalarArray = static_pointer_cast(field);
+ ScalarType scalarType = scalarArray->getElementType();
+ if(scalarType==pvDouble) {
+ size_t num = 5;
+ PVDoubleArrayPtr pvValue = static_pointer_cast(
+ pvDataCreate->createPVScalarArray(pvDouble));
+ shared_vector data(num);
+ for(size_t i=0; ireplace(freeze(data));
+ pvUnion->set(0,pvValue);
+ return;
+ }
+ if(scalarType==pvString) {
+ size_t num = 5;
+ PVStringArrayPtr pvValue = static_pointer_cast(
+ pvDataCreate->createPVScalarArray(pvString));
+ shared_vector data(num);
+ for(size_t i=0; ireplace(freeze(data));
+ pvUnion->set(0,pvValue);
+ return;
+ }
+ throw std::runtime_error("only pvDouble and pvString are supported");
+ }
+ throw std::runtime_error("only scalar and scalarArray fields are supported");
+}
+
+static void example(
+ PvaClientPtr const &pva,
+ string provider,
+ shared_vector const &channelNames)
+{
+
+ size_t num = channelNames.size();
+ PvaClientMultiChannelPtr multiChannel(
+ PvaClientMultiChannel::create(pva,channelNames,provider));
+ PvaClientNTMultiGetPtr multiGet(multiChannel->createNTGet());
+ PvaClientNTMultiPutPtr multiPut(multiChannel->createNTPut());
+ PvaClientNTMultiMonitorPtr multiMonitor(multiChannel->createNTMonitor());
+ shared_vector data = multiPut->getValues();
+ for(double value = 0.0; value< 2.1; value+= 1.0) {
+ for(size_t i=0; iput();
+ multiGet->get();
+ PvaClientNTMultiDataPtr multiData = multiGet->getData();
+ PVStructurePtr pvStructure = multiData->getPVTop();
+ cout << "pvStructure\n" << pvStructure << endl;
+ bool result = multiMonitor->waitEvent(.1);
+ while(result) {
+ multiData = multiMonitor->getData();
+ pvStructure = multiData->getPVTop();
+ cout << "monitor pvStructure\n" << pvStructure << endl;
+ result = multiMonitor->poll();
+ }
+ }
+}
+
+int main(int argc,char *argv[])
+{
+ PvaClientPtr pva = PvaClient::create();
+ size_t num = 4;
+ shared_vector channelNames(num);
+ channelNames[0] = "double01";
+ channelNames[1] = "string01";
+ channelNames[2] = "doubleArray01";
+ channelNames[3] = "stringArray01";
+ cout << "dbRecord pva\n";
+ shared_vector names(freeze(channelNames));
+ example(pva,"pva",names);
+ cout << "dbRecord ca\n";
+ example(pva,"ca",names);
+ channelNames = shared_vector(num);
+ channelNames[0] = "exampleDouble";
+ channelNames[1] = "exampleString";
+ channelNames[2] = "exampleDoubleArray";
+ channelNames[3] = "exampleStringArray";
+ names = freeze(channelNames);
+ cout << "pvRecord pva\n";
+ example(pva,"pva",names);
+ return 0;
+}
diff --git a/example/src/examplePvaClientPut.cpp b/example/src/examplePvaClientPut.cpp
index c6202be..dfa3559 100644
--- a/example/src/examplePvaClientPut.cpp
+++ b/example/src/examplePvaClientPut.cpp
@@ -13,12 +13,16 @@
#include
#include
+#include
+using std::tr1::static_pointer_cast;
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvaClient;
+static ConvertPtr convert = getConvert();
+
static void examplePut(PvaClientPtr const &pva)
{
@@ -45,10 +49,29 @@ static void examplePut(PvaClientPtr const &pva)
}
}
+static void examplePVFieldPut(PvaClientPtr const &pva)
+{
+ cout << "example put\n";
+ PvaClientChannelPtr channel = pva->channel("exampleDouble");
+ PvaClientPutPtr put = channel->put();
+ PvaClientPutDataPtr putData = put->getData();
+ PVFieldPtr pvField = putData->getValue();
+ PVScalarPtr pvScalar = static_pointer_cast(pvField);
+ try {
+ convert->fromDouble(pvScalar,1.0); put->put();
+ cout << channel->get("field()")->getData()->showChanged(cout) << endl;
+ convert->fromDouble(pvScalar,2.0); put->put();
+ cout << channel->get("field()")->getData()->showChanged(cout) << endl;
+ } catch (std::runtime_error e) {
+ cout << "exception " << e.what() << endl;
+ }
+}
+
int main(int argc,char *argv[])
{
PvaClientPtr pva = PvaClient::create();
examplePut(pva);
+ examplePVFieldPut(pva);
return 0;
}
diff --git a/src/Makefile b/src/Makefile
index 8a23f7a..5a278f5 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -22,6 +22,10 @@ LIBSRCS += pvaClientMultiChannel.cpp
LIBSRCS += pvaClientMultiGetDouble.cpp
LIBSRCS += pvaClientMultiPutDouble.cpp
LIBSRCS += pvaClientMultiMonitorDouble.cpp
+LIBSRCS += pvaClientNTMultiPut.cpp
+LIBSRCS += pvaClientNTMultiData.cpp
+LIBSRCS += pvaClientNTMultiGet.cpp
+LIBSRCS += pvaClientNTMultiMonitor.cpp
pvaClient_LIBS += pvAccess pvData nt Com
pvaClient_LIBS += $(EPICS_BASE_IOC_LIBS)
diff --git a/src/pvaClientMultiChannel.cpp b/src/pvaClientMultiChannel.cpp
index 3e3f2e7..228dc37 100644
--- a/src/pvaClientMultiChannel.cpp
+++ b/src/pvaClientMultiChannel.cpp
@@ -15,7 +15,7 @@
#include
#include
#include
-#include
+
using std::tr1::static_pointer_cast;
@@ -52,7 +52,8 @@ PvaClientMultiChannel::PvaClientMultiChannel(
numChannel(channelName.size()),
numConnected(0),
pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())),
- isConnected(shared_vector(numChannel,false)),
+ isConnected(shared_vector(numChannel,false)),
+ createRequest(CreateRequest::create()),
isDestroyed(false)
{
}
@@ -131,7 +132,7 @@ bool PvaClientMultiChannel::connectionChange()
return false;
}
-epics::pvData::shared_vector PvaClientMultiChannel::getIsConnected()
+epics::pvData::shared_vector PvaClientMultiChannel::getIsConnected()
{
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
for(size_t i=0; icreateRequest(request);
+ if(!pvRequest) {
+ stringstream ss;
+ ss << " PvaClientMultiChannel::createNTGet invalid pvRequest: " + createRequest->getMessage();
+ throw std::runtime_error(ss.str());
+ }
+ return PvaClientNTMultiGet::create(getPtrSelf(), pvaClientChannelArray,pvRequest);
+}
+
+
+PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor()
+{
+ return createNTMonitor("value,alarm,timeStamp");
+}
+
+PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor(std::string const &request)
+{
+ checkConnected();
+ PVStructurePtr pvRequest = createRequest->createRequest(request);
+ if(!pvRequest) {
+ stringstream ss;
+ ss << " PvaClientMultiChannel::createNTMonitor invalid pvRequest: " + createRequest->getMessage();
+ throw std::runtime_error(ss.str());
+ }
+ return PvaClientNTMultiMonitor::create(getPtrSelf(), pvaClientChannelArray,pvRequest);
+}
+
}}
diff --git a/src/pvaClientMultiChannel.h b/src/pvaClientMultiChannel.h
index ff6c167..86ae925 100644
--- a/src/pvaClientMultiChannel.h
+++ b/src/pvaClientMultiChannel.h
@@ -1,4 +1,4 @@
-/* pvaClient.h */
+/* pvaClientMultiChannel.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
@@ -18,6 +18,7 @@
#include
#include
+#include
namespace epics { namespace pvaClient {
@@ -32,11 +33,20 @@ typedef std::tr1::shared_ptr PvaClientMultiPutDoublePtr
class PvaClientMultiMonitorDouble;
typedef std::tr1::shared_ptr PvaClientMultiMonitorDoublePtr;
+class PvaClientNTMultiGet;
+typedef std::tr1::shared_ptr PvaClientNTMultiGetPtr;
+class PvaClientNTMultiPut;
+typedef std::tr1::shared_ptr PvaClientNTMultiPutPtr;
+class PvaClientNTMultiMonitor;
+typedef std::tr1::shared_ptr PvaClientNTMultiMonitorPtr;
+class PvaClientNTMultiData;
+typedef std::tr1::shared_ptr PvaClientNTMultiDataPtr;
+
typedef epics::pvData::shared_vector PvaClientChannelArray;
/**
- * Provides access to multiple channels.
+ * @brief PvaMultiChannel is a synchronous interface for accessing multiple channels.
*
* @author mrk
*/
@@ -58,9 +68,11 @@ public:
std::string const & providerName = "pva",
size_t maxNotConnected=0
);
-
+ /**
+ * Destructor
+ */
~PvaClientMultiChannel();
- /** Destroy the pvAccess connection.
+ /** Destroy the pvAccess connections.
*/
void destroy();
/** Get the channelNames.
@@ -85,7 +97,7 @@ public:
/** Get the connection state of each channel.
* @return The state of each channel.
*/
- epics::pvData::shared_vector getIsConnected();
+ epics::pvData::shared_vector getIsConnected();
/** Get the pvaClientChannelArray.
* @return The shared pointer.
*/
@@ -109,6 +121,35 @@ public:
* @return The interface.
*/
PvaClientMultiMonitorDoublePtr createMonitor();
+ /**
+ * Create a pvaClientNTMultiPut.
+ * @return The interface.
+ */
+ PvaClientNTMultiPutPtr createNTPut();
+ /**
+ * Create a pvaClientNTMultiGet.
+ * This calls the next method with request = "value,alarm,timeStamp"
+ * @return The interface.
+ */
+ PvaClientNTMultiGetPtr createNTGet();
+ /**
+ * Create a pvaClientNTMultiGet;
+ * @param request The request for each channel.
+ * @return The interface.
+ */
+ PvaClientNTMultiGetPtr createNTGet(std::string const &request);
+ /**
+ * Create a pvaClientNTMultiMonitor.
+ * This calls the next method with request = "value,alarm,timeStamp"
+ * @return The interface.
+ */
+ PvaClientNTMultiMonitorPtr createNTMonitor();
+ /**
+ * Create a pvaClientNTMultiPut.
+ * @param request The request for each channel.
+ * @return The interface.
+ */
+ PvaClientNTMultiMonitorPtr createNTMonitor(std::string const &request);
/** Get the shared pointer to self.
* @return The shared pointer.
*/
@@ -135,8 +176,10 @@ private:
size_t numConnected;
PvaClientChannelArray pvaClientChannelArray;
- epics::pvData::shared_vector isConnected;
+ epics::pvData::shared_vector isConnected;
+ epics::pvData::CreateRequest::shared_pointer createRequest;
bool isDestroyed;
+
};
/**
@@ -319,6 +362,312 @@ private:
bool isDestroyed;
};
+/**
+ * This provides channelGet to multiple channels where the value field of each channel is presented as a union.
+ */
+class epicsShareClass PvaClientNTMultiGet :
+ public std::tr1::enable_shared_from_this
+{
+
+public:
+ POINTER_DEFINITIONS(PvaClientNTMultiGet);
+ /**
+ * Factory method that creates a PvaClientNTMultiGet.
+ * @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
+ * @param pvaClientChannelArray The PvaClientChannel array.
+ * @param pvRequest The pvRequest for each channel.
+ * @return The interface.
+ */
+ static PvaClientNTMultiGetPtr create(
+ PvaClientMultiChannelPtr const &pvaClientMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray,
+ epics::pvData::PVStructurePtr const & pvRequest);
+
+ ~PvaClientNTMultiGet();
+
+ /** Destroy the pvAccess connection.
+ */
+ void destroy();
+ /**
+ * Create a channelGet for each channel.
+ */
+ void connect();
+ /**
+ * get data for each channel.
+ */
+ void get();
+ /**
+ * get the data.
+ * @return the pvaClientNTMultiData.
+ */
+ PvaClientNTMultiDataPtr getData();
+ /** Get the shared pointer to self.
+ * @return The shared pointer.
+ */
+ PvaClientNTMultiGetPtr getPtrSelf()
+ {
+ return shared_from_this();
+ }
+private:
+ PvaClientNTMultiGet(
+ epics::pvData::UnionConstPtr const & u,
+ PvaClientMultiChannelPtr const &pvaClientMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray,
+ epics::pvData::PVStructurePtr const & pvRequest);
+
+ PvaClientMultiChannelPtr pvaClientMultiChannel;
+ PvaClientChannelArray pvaClientChannelArray;
+ size_t nchannel;
+ epics::pvData::Mutex mutex;
+
+ epics::pvData::PVStructurePtr pvRequest;
+ PvaClientNTMultiDataPtr pvaClientNTMultiData;
+ std::vector pvaClientGet;
+ bool isConnected;
+ bool isDestroyed;
+};
+
+/**
+ * This provides channelPut to multiple channels where the value field of each channel is presented as a union.
+ */
+class epicsShareClass PvaClientNTMultiPut :
+ public std::tr1::enable_shared_from_this
+{
+
+public:
+ POINTER_DEFINITIONS(PvaClientNTMultiPut);
+ /**
+ * Factory method that creates a PvaClientNTMultiPut.
+ * @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
+ * @param pvaClientChannelArray The PvaClientChannel array.
+ * @return The interface.
+ */
+ static PvaClientNTMultiPutPtr create(
+ PvaClientMultiChannelPtr const &pvaClientMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray);
+ ~PvaClientNTMultiPut();
+
+ /** Destroy the pvAccess connection.
+ */
+ void destroy();
+ /**
+ * Create a channelPut for each channel.
+ */
+ void connect();
+ /**
+ * get the value field of each channel as a union.
+ * @return A shared vector of union.
+ */
+ epics::pvData::shared_vector getValues();
+ /**
+ * put the data to each channel.
+' */
+ void put();
+ /** Get the shared pointer to self.
+ * @return The shared pointer.
+ */
+ PvaClientNTMultiPutPtr getPtrSelf()
+ {
+ return shared_from_this();
+ }
+private:
+ PvaClientNTMultiPut(
+ PvaClientMultiChannelPtr const &pvaClientMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray);
+
+ PvaClientMultiChannelPtr pvaClientMultiChannel;
+ PvaClientChannelArray pvaClientChannelArray;
+ size_t nchannel;
+ epics::pvData::Mutex mutex;
+
+ epics::pvData::shared_vector unionValue;
+ epics::pvData::shared_vector value;
+ std::vector pvaClientPut;
+ bool isConnected;
+ bool isDestroyed;
+};
+
+/**
+ * This provides channel monitor to multiple channels where the value field of each channel is presented as a union.
+ */
+class epicsShareClass PvaClientNTMultiMonitor :
+ public std::tr1::enable_shared_from_this
+{
+
+public:
+ POINTER_DEFINITIONS(PvaClientNTMultiMonitor);
+ /**
+ * Factory method that creates a PvaClientNTMultiMonitor.
+ * @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
+ * @param pvaClientChannelArray The PvaClientChannel array.
+ * @param pvRequest The pvRequest for each channel.
+ * @return The interface.
+ */
+ static PvaClientNTMultiMonitorPtr create(
+ PvaClientMultiChannelPtr const &pvaNTMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray,
+ epics::pvData::PVStructurePtr const & pvRequest);
+ ~PvaClientNTMultiMonitor();
+
+ /** Destroy the pvAccess connection.
+ */
+ void destroy();
+ /**
+ * Create a channel monitor for each channel.
+ */
+ void connect();
+ /**
+ * poll each channel.
+ * If any has new data it is used to update the double[].
+ * @return (false,true) if (no, at least one) value was updated.
+ */
+ bool poll();
+ /**
+ * Wait until poll returns true.
+ * @param waitForEvent The time to keep trying.
+ * A thread sleep of .1 seconds occurs between each call to poll.
+ * @return (false,true) if (timeOut, poll returned true).
+ */
+ bool waitEvent(double waitForEvent);
+ /**
+ * get the data.
+ * @return the pvaClientNTMultiData.
+ */
+ PvaClientNTMultiDataPtr getData();
+ /** Monitor the shared pointer to self.
+ * @return The shared pointer.
+ */
+ PvaClientNTMultiMonitorPtr getPtrSelf()
+ {
+ return shared_from_this();
+ }
+private:
+ PvaClientNTMultiMonitor(
+ epics::pvData::UnionConstPtr const & u,
+ PvaClientMultiChannelPtr const &pvaClientMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray,
+ epics::pvData::PVStructurePtr const & pvRequest);
+
+ PvaClientMultiChannelPtr pvaClientMultiChannel;
+ PvaClientChannelArray pvaClientChannelArray;
+ size_t nchannel;
+ epics::pvData::Mutex mutex;
+
+ epics::pvData::PVStructurePtr pvRequest;
+ PvaClientNTMultiDataPtr pvaClientNTMultiData;
+ std::vector pvaClientMonitor;
+ bool isConnected;
+ bool isDestroyed;
+};
+
+/**
+ * This provides NTMultiChannel data for both PvaClientNTMultiGet and PvaClientNTMultiMonitor.
+ */
+class epicsShareClass PvaClientNTMultiData :
+ public std::tr1::enable_shared_from_this
+{
+
+public:
+ POINTER_DEFINITIONS(PvaClientNTMultiData);
+ /**
+ * Factory method that creates a PvaClientNTMultiData.
+ * Normally only called by PvaClientNTMultiGet and PvaClientNTMultiMonitor.
+ * @param u The union interface for the value field of each channel.
+ * @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
+ * @param pvaClientChannelArray The PvaClientChannel array.
+ * @param pvRequest The pvRequest for each channel.
+ */
+ static PvaClientNTMultiDataPtr create(
+ epics::pvData::UnionConstPtr const & u,
+ PvaClientMultiChannelPtr const &pvaNTMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray,
+ epics::pvData::PVStructurePtr const & pvRequest);
+ ~PvaClientNTMultiData();
+ /** Destroy the pvAccess connection.
+ */
+ void destroy();
+
+ /**
+ * Get the number of channels.
+ * @return The number of channels.
+ */
+ size_t getNumber();
+
+ /**
+ * Set the timeStamp base for computing deltaTimes.
+ */
+ void startDeltaTime();
+
+ /**
+ * Update NTMultiChannel fields.
+ */
+ void endDeltaTime();
+ /**
+ * Get the time when the last get was made.
+ * @return The timeStamp.
+ */
+ epics::pvData::TimeStamp getTimeStamp();
+ /**
+ * Get the NTMultiChannel.
+ * @return The value.
+ */
+ epics::nt::NTMultiChannelPtr getNTMultiChannel();
+
+ /**
+ * Get the top level structure.
+ * @return The top level structure.
+ */
+ epics::pvData::PVStructurePtr getPVTop();
+ /** Get the shared pointer to self.
+ * @return The shared pointer.
+ */
+ PvaClientNTMultiDataPtr getPtrSelf()
+ {
+ return shared_from_this();
+ }
+
+private:
+ PvaClientNTMultiData(
+ epics::pvData::UnionConstPtr const & u,
+ PvaClientMultiChannelPtr const &pvaNTMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray,
+ epics::pvData::PVStructurePtr const & pvRequest);
+ static epics::pvData::PVStructurePtr createRequest(std::string const & request);
+ void setStructure(epics::pvData::StructureConstPtr const & structure,size_t index);
+ void setPVStructure(
+ epics::pvData::PVStructurePtr const &pvStructure,size_t index);
+
+ PvaClientMultiChannelPtr pvaClientMultiChannel;
+ PvaClientChannelArray pvaClientChannelArray;
+ epics::pvData::PVStructurePtr pvRequest;
+ epics::pvData::UnionConstPtr u;
+ size_t nchannel;
+ epics::pvData::Mutex mutex;
+
+ std::vector topPVStructure;
+ bool gotAlarm;
+ bool gotTimeStamp;
+ bool isDestroyed;
+
+ epics::nt::NTMultiChannelPtr ntMultiChannel;
+ epics::pvData::PVStructurePtr pvTop;
+ epics::pvData::shared_vector unionValue;
+ epics::pvData::shared_vector severity;
+ epics::pvData::shared_vector status;
+ epics::pvData::shared_vector message;
+ epics::pvData::shared_vector secondsPastEpoch;
+ epics::pvData::shared_vector nanoseconds;
+ epics::pvData::shared_vector userTag;
+ epics::pvData::Alarm alarm;
+ epics::pvData::PVAlarm pvAlarm;
+ epics::pvData::TimeStamp timeStamp;;
+ epics::pvData::PVTimeStamp pvTimeStamp;
+ friend class PvaClientNTMultiGet;
+ friend class PvaClientNTMultiPut;
+ friend class PvaClientNTMultiMonitor;
+};
+
+
}}
#endif /* PVACLIENTMULTICHANNEL_H */
diff --git a/src/pvaClientMultiGetDouble.cpp b/src/pvaClientMultiGetDouble.cpp
index be975dc..3697337 100644
--- a/src/pvaClientMultiGetDouble.cpp
+++ b/src/pvaClientMultiGetDouble.cpp
@@ -68,7 +68,7 @@ void PvaClientMultiGetDouble::destroy()
void PvaClientMultiGetDouble::connect()
{
- shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
+ shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
string request = "value";
for(size_t i=0; i PvaClientMultiGetDouble::get()
{
if(!isGetConnected) connect();
- shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
+ shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
for(size_t i=0; i isConnected = pvaClientMultiChannel->getIsConnected();
+ shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
string request = "value";
for(size_t i=0; i isConnected = pvaClientMultiChannel->getIsConnected();
+ shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
for(size_t i=0; i isConnected = pvaClientMultiChannel->getIsConnected();
+ shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
for(size_t i=0; i const &da
if(data.size()!=nchannel) {
throw std::runtime_error("data has wrong size");
}
- shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
+ shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
for(size_t i=0; igetData()->getPVStructure();
- PVDoublePtr pvValue = pvTop->getSubField("value");
- pvValue->put(data[i]);
+ PVScalarPtr pvValue = pvTop->getSubField("value");
+ convert->fromDouble(pvValue,data[i]);
pvaClientPut[i]->issuePut();
}
if(isConnected[i]) {
diff --git a/src/pvaClientNTMultiData.cpp b/src/pvaClientNTMultiData.cpp
new file mode 100644
index 0000000..57c571b
--- /dev/null
+++ b/src/pvaClientNTMultiData.cpp
@@ -0,0 +1,232 @@
+/* pvaClientNTMultiData.cpp */
+/**
+ * Copyright - See the COPYRIGHT that is included with this distribution.
+ * EPICS pvData is distributed subject to a Software License Agreement found
+ * in file LICENSE that is included with this distribution.
+ */
+/**
+ * @author mrk
+ * @date 2015.03
+ */
+
+#define epicsExportSharedSymbols
+#include
+#include
+#include
+#include
+
+using std::tr1::static_pointer_cast;
+using namespace epics::pvData;
+using namespace epics::pvAccess;
+using namespace epics::nt;
+using namespace std;
+
+namespace epics { namespace pvaClient {
+
+static ConvertPtr convert = getConvert();
+static FieldCreatePtr fieldCreate = getFieldCreate();
+static PVDataCreatePtr pvDataCreate = getPVDataCreate();
+static StandardFieldPtr standardField = getStandardField();
+
+
+PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
+ epics::pvData::UnionConstPtr const & u,
+ PvaClientMultiChannelPtr const &pvaMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray,
+ PVStructurePtr const & pvRequest)
+{
+ PvaClientNTMultiDataPtr pvaClientNTMultiData(
+ new PvaClientNTMultiData(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
+ return pvaClientNTMultiData;
+}
+
+PvaClientNTMultiData::PvaClientNTMultiData(
+ epics::pvData::UnionConstPtr const & u,
+ PvaClientMultiChannelPtr const &pvaClientMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray,
+ epics::pvData::PVStructurePtr const & pvRequest)
+: pvaClientMultiChannel(pvaClientMultiChannel),
+ pvaClientChannelArray(pvaClientChannelArray),
+ pvRequest(pvRequest),
+ u(u),
+ nchannel(pvaClientChannelArray.size()),
+ gotAlarm(false),
+ gotTimeStamp(false),
+ isDestroyed(false)
+{
+ PVFieldPtr pvValue = pvRequest->getSubField("field.value");
+ if(!pvValue) {
+ throw std::runtime_error("pvRequest did not specify value");
+ }
+ topPVStructure.resize(nchannel);
+ unionValue.resize(nchannel);
+ for(size_t i=0; i< nchannel; ++i) {
+ topPVStructure[i] = PVStructurePtr();
+ unionValue[i] = pvDataCreate->createPVUnion(u);
+ }
+ NTMultiChannelBuilderPtr builder = NTMultiChannel::createBuilder();
+ builder->value(u);
+ if(pvRequest->getSubField("field.alarm"))
+ {
+ gotAlarm = true;
+ builder->addAlarm();
+ builder->addSeverity();
+ builder->addStatus();
+ builder->addMessage();
+ severity.resize(nchannel);
+ status.resize(nchannel);
+ message.resize(nchannel);
+
+ }
+ if(pvRequest->getSubField("field.timeStamp")) {
+ gotTimeStamp = true;
+ builder->addTimeStamp();
+ builder->addSecondsPastEpoch();
+ builder->addNanoseconds();
+ builder->addUserTag();
+ secondsPastEpoch.resize(nchannel);
+ nanoseconds.resize(nchannel);
+ userTag.resize(nchannel);
+ }
+ ntMultiChannel = builder->create();
+ ntMultiChannel->getChannelName()->replace(pvaClientMultiChannel->getChannelNames());
+}
+
+
+PvaClientNTMultiData::~PvaClientNTMultiData()
+{
+ destroy();
+}
+
+void PvaClientNTMultiData::destroy()
+{
+ {
+ Lock xx(mutex);
+ if(isDestroyed) return;
+ isDestroyed = true;
+ }
+ pvaClientChannelArray.clear();
+}
+
+void PvaClientNTMultiData::setStructure(StructureConstPtr const & structure,size_t index)
+{
+ FieldConstPtr field = structure->getField("value");
+ if(!field) {
+ string message = "channel "
+ + pvaClientChannelArray[index]->getChannel()->getChannelName()
+ + " does not have top level value field";
+ throw std::runtime_error(message);
+ }
+}
+
+void PvaClientNTMultiData::setPVStructure(
+ PVStructurePtr const &pvStructure,size_t index)
+{
+ topPVStructure[index] = pvStructure;
+}
+
+
+size_t PvaClientNTMultiData::getNumber()
+{
+ return nchannel;
+}
+
+void PvaClientNTMultiData::startDeltaTime()
+{
+ for(size_t i=0; iset(pvst->getSubField("value"));
+ }
+ if(gotAlarm)
+ {
+ severity[i] = pvst->getSubField("alarm.severity")->get();
+ status[i] = pvst->getSubField("alarm.status")->get();
+ message[i] = pvst->getSubField("alarm.message")->get();
+ }
+ if(gotTimeStamp)
+ {
+ secondsPastEpoch[i] = pvst->getSubField("timeStamp.secondsPastEpoch")->get();
+ nanoseconds[i] = pvst->getSubField("timeStamp.nanoseconds")->get();
+ userTag[i] = pvst->getSubField("timeStamp.userTag")->get();
+ }
+
+ }
+ shared_vector val(nchannel);
+ for(size_t i=0; igetValue()->replace(freeze(val));
+ shared_vector connected = pvaClientMultiChannel->getIsConnected();
+ shared_vector isConnected(nchannel);
+ for(size_t i=0; igetIsConnected()->replace(freeze(isConnected));
+ if(gotAlarm)
+ {
+ shared_vector sev(nchannel);
+ for(size_t i=0; igetSeverity()->replace(freeze(sev));
+ shared_vector sta(nchannel);
+ for(size_t i=0; igetStatus()->replace(freeze(sta));
+ shared_vector mes(nchannel);
+ for(size_t i=0; igetMessage()->replace(freeze(mes));
+ }
+ if(gotTimeStamp)
+ {
+ shared_vector sec(nchannel);
+ for(size_t i=0; igetSecondsPastEpoch()->replace(freeze(sec));
+ shared_vector nano(nchannel);
+ for(size_t i=0; igetNanoseconds()->replace(freeze(nano));
+ shared_vector tag(nchannel);
+ for(size_t i=0; igetUserTag()->replace(freeze(tag));
+ }
+}
+
+TimeStamp PvaClientNTMultiData::getTimeStamp()
+{
+ pvTimeStamp.get(timeStamp);
+ return timeStamp;
+}
+
+NTMultiChannelPtr PvaClientNTMultiData::getNTMultiChannel()
+{
+ return ntMultiChannel;
+}
+
+PVStructurePtr PvaClientNTMultiData::getPVTop()
+{
+ return ntMultiChannel->getPVStructure();
+}
+
+}}
diff --git a/src/pvaClientNTMultiGet.cpp b/src/pvaClientNTMultiGet.cpp
new file mode 100644
index 0000000..c541096
--- /dev/null
+++ b/src/pvaClientNTMultiGet.cpp
@@ -0,0 +1,143 @@
+/* pvaClientNTMultiGet.cpp */
+/**
+ * Copyright - See the COPYRIGHT that is included with this distribution.
+ * EPICS pvData is distributed subject to a Software License Agreement found
+ * in file LICENSE that is included with this distribution.
+ */
+/**
+ * @author mrk
+ * @date 2015.03
+ */
+
+#define epicsExportSharedSymbols
+#include
+#include
+#include
+#include
+
+using std::tr1::static_pointer_cast;
+using namespace epics::pvData;
+using namespace epics::pvAccess;
+using namespace epics::nt;
+using namespace std;
+
+namespace epics { namespace pvaClient {
+
+static ConvertPtr convert = getConvert();
+static FieldCreatePtr fieldCreate = getFieldCreate();
+static PVDataCreatePtr pvDataCreate = getPVDataCreate();
+static StandardFieldPtr standardField = getStandardField();
+
+
+PvaClientNTMultiGetPtr PvaClientNTMultiGet::create(
+ PvaClientMultiChannelPtr const &pvaMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray,
+ PVStructurePtr const & pvRequest)
+{
+ UnionConstPtr u = fieldCreate->createVariantUnion();
+ PvaClientNTMultiGetPtr pvaClientNTMultiGet(
+ new PvaClientNTMultiGet(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
+ return pvaClientNTMultiGet;
+}
+
+PvaClientNTMultiGet::PvaClientNTMultiGet(
+ UnionConstPtr const & u,
+ PvaClientMultiChannelPtr const &pvaClientMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray,
+ epics::pvData::PVStructurePtr const & pvRequest)
+: pvaClientMultiChannel(pvaClientMultiChannel),
+ pvaClientChannelArray(pvaClientChannelArray),
+ nchannel(pvaClientChannelArray.size()),
+ pvRequest(pvRequest),
+ pvaClientNTMultiData(
+ PvaClientNTMultiData::create(
+ u,
+ pvaClientMultiChannel,
+ pvaClientChannelArray,
+ pvRequest)),
+ isConnected(false),
+ isDestroyed(false)
+{
+}
+
+PvaClientNTMultiGet::~PvaClientNTMultiGet()
+{
+ destroy();
+}
+
+void PvaClientNTMultiGet::destroy()
+{
+ {
+ Lock xx(mutex);
+ if(isDestroyed) return;
+ isDestroyed = true;
+ }
+ pvaClientChannelArray.clear();
+}
+
+void PvaClientNTMultiGet::connect()
+{
+ pvaClientGet.resize(nchannel);
+ shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
+ string request = "value";
+ if(pvRequest->getSubField("field.alarm")) request += ",alarm";
+ if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
+ for(size_t i=0; icreateGet(request);
+ pvaClientGet[i]->issueConnect();
+ }
+ }
+ for(size_t i=0; iwaitConnect();
+ if(status.isOK()) continue;
+ stringstream ss;
+ string channelName = pvaClientChannelArray[i]->getChannelName();
+ ss << "channel " << channelName << " PvaChannelGet::waitConnect " << status.getMessage();
+ throw std::runtime_error(ss.str());
+ }
+ }
+ this->isConnected = true;
+}
+
+void PvaClientNTMultiGet::get()
+{
+ if(!isConnected) connect();
+ shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
+
+ for(size_t i=0; iissueGet();
+ }
+ }
+ for(size_t i=0; iwaitGet();
+ if(status.isOK()) continue;
+ stringstream ss;
+ string channelName = pvaClientChannelArray[i]->getChannelName();
+ ss << "channel " << channelName << " PvaChannelGet::waitConnect " << status.getMessage();
+ throw std::runtime_error(ss.str());
+ }
+ }
+ pvaClientNTMultiData->startDeltaTime();
+ for(size_t i=0; isetPVStructure(pvaClientGet[i]->getData()->getPVStructure(),i);
+ }
+ }
+ pvaClientNTMultiData->endDeltaTime();
+}
+
+PvaClientNTMultiDataPtr PvaClientNTMultiGet::getData()
+{
+ return pvaClientNTMultiData;
+}
+
+}}
diff --git a/src/pvaClientNTMultiMonitor.cpp b/src/pvaClientNTMultiMonitor.cpp
new file mode 100644
index 0000000..5fd1709
--- /dev/null
+++ b/src/pvaClientNTMultiMonitor.cpp
@@ -0,0 +1,155 @@
+/* pvaClientNTMultiMonitor.cpp */
+/**
+ * Copyright - See the COPYRIGHT that is included with this distribution.
+ * EPICS pvData is distributed subject to a Software License Agreement found
+ * in file LICENSE that is included with this distribution.
+ */
+/**
+ * @author mrk
+ * @date 2015.03
+ */
+
+#define epicsExportSharedSymbols
+#include
+#include
+#include
+#include
+#include
+
+using std::tr1::static_pointer_cast;
+using namespace epics::pvData;
+using namespace epics::pvAccess;
+using namespace epics::nt;
+using namespace std;
+
+namespace epics { namespace pvaClient {
+
+static ConvertPtr convert = getConvert();
+static FieldCreatePtr fieldCreate = getFieldCreate();
+static PVDataCreatePtr pvDataCreate = getPVDataCreate();
+static StandardFieldPtr standardField = getStandardField();
+
+
+PvaClientNTMultiMonitorPtr PvaClientNTMultiMonitor::create(
+ PvaClientMultiChannelPtr const &pvaMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray,
+ epics::pvData::PVStructurePtr const & pvRequest)
+{
+ UnionConstPtr u = fieldCreate->createVariantUnion();
+ PvaClientNTMultiMonitorPtr pvaClientNTMultiMonitor(
+ new PvaClientNTMultiMonitor(u,pvaMultiChannel,pvaClientChannelArray,pvRequest));
+ return pvaClientNTMultiMonitor;
+}
+
+PvaClientNTMultiMonitor::PvaClientNTMultiMonitor(
+ UnionConstPtr const & u,
+ PvaClientMultiChannelPtr const &pvaClientMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray,
+ PVStructurePtr const & pvRequest)
+: pvaClientMultiChannel(pvaClientMultiChannel),
+ pvaClientChannelArray(pvaClientChannelArray),
+ nchannel(pvaClientChannelArray.size()),
+ pvRequest(pvRequest),
+ pvaClientNTMultiData(
+ PvaClientNTMultiData::create(
+ u,
+ pvaClientMultiChannel,
+ pvaClientChannelArray,
+ pvRequest)),
+ isConnected(false),
+ isDestroyed(false)
+{
+}
+
+
+PvaClientNTMultiMonitor::~PvaClientNTMultiMonitor()
+{
+ destroy();
+}
+
+void PvaClientNTMultiMonitor::destroy()
+{
+ {
+ Lock xx(mutex);
+ if(isDestroyed) return;
+ isDestroyed = true;
+ }
+ pvaClientChannelArray.clear();
+}
+
+
+void PvaClientNTMultiMonitor::connect()
+{
+ pvaClientMonitor.resize(nchannel);
+ shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
+ string request = "value";
+ if(pvRequest->getSubField("field.alarm")) request += ",alarm";
+ if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
+ for(size_t i=0; icreateMonitor(request);
+ pvaClientMonitor[i]->issueConnect();
+ }
+ }
+ for(size_t i=0; iwaitConnect();
+ if(status.isOK()) continue;
+ stringstream ss;
+ string channelName = pvaClientChannelArray[i]->getChannelName();
+ ss << "channel " << channelName << " PvaChannelMonitor::waitConnect " << status.getMessage();
+ throw std::runtime_error(ss.str());
+ }
+ }
+ for(size_t i=0; istart();
+ }
+ this->isConnected = true;
+}
+
+bool PvaClientNTMultiMonitor::poll()
+{
+ if(!isConnected) connect();
+ bool result = false;
+ shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
+ pvaClientNTMultiData->startDeltaTime();
+ for(size_t i=0; ipoll()) {
+ pvaClientNTMultiData->setPVStructure(
+ pvaClientMonitor[i]->getData()->getPVStructure(),i);
+ pvaClientMonitor[i]->releaseEvent();
+ result = true;
+ }
+ }
+ }
+ if(result) pvaClientNTMultiData->endDeltaTime();
+ return result;
+}
+
+bool PvaClientNTMultiMonitor::waitEvent(double waitForEvent)
+{
+ if(poll()) return true;
+ TimeStamp start;
+ start.getCurrent();
+ TimeStamp now;
+ while(true) {
+ epicsThreadSleep(.1);
+ if(poll()) return true;
+ now.getCurrent();
+ double diff = TimeStamp::diff(now,start);
+ if(diff>=waitForEvent) break;
+ }
+ return false;
+}
+
+PvaClientNTMultiDataPtr PvaClientNTMultiMonitor::getData()
+{
+ return pvaClientNTMultiData;
+}
+
+}}
diff --git a/src/pvaClientNTMultiPut.cpp b/src/pvaClientNTMultiPut.cpp
new file mode 100644
index 0000000..d947d34
--- /dev/null
+++ b/src/pvaClientNTMultiPut.cpp
@@ -0,0 +1,149 @@
+/* PvaClientNTMultiPut.cpp */
+/**
+ * Copyright - See the COPYRIGHT that is included with this distribution.
+ * EPICS pvData is distributed subject to a Software License Agreement found
+ * in file LICENSE that is included with this distribution.
+ */
+/**
+ * @author mrk
+ * @date 2015.03
+ */
+
+#define epicsExportSharedSymbols
+#include
+#include
+#include
+#include
+
+using std::tr1::static_pointer_cast;
+using namespace epics::pvData;
+using namespace epics::pvAccess;
+using namespace epics::nt;
+using namespace std;
+
+namespace epics { namespace pvaClient {
+
+static ConvertPtr convert = getConvert();
+static FieldCreatePtr fieldCreate = getFieldCreate();
+static PVDataCreatePtr pvDataCreate = getPVDataCreate();
+static StandardFieldPtr standardField = getStandardField();
+static CreateRequest::shared_pointer createRequest = CreateRequest::create();
+
+PvaClientNTMultiPutPtr PvaClientNTMultiPut::create(
+ PvaClientMultiChannelPtr const &pvaMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray)
+{
+ PvaClientNTMultiPutPtr pvaClientNTMultiPut(
+ new PvaClientNTMultiPut(pvaMultiChannel,pvaClientChannelArray));
+ return pvaClientNTMultiPut;
+}
+
+PvaClientNTMultiPut::PvaClientNTMultiPut(
+ PvaClientMultiChannelPtr const &pvaClientMultiChannel,
+ PvaClientChannelArray const &pvaClientChannelArray)
+: pvaClientMultiChannel(pvaClientMultiChannel),
+ pvaClientChannelArray(pvaClientChannelArray),
+ nchannel(pvaClientChannelArray.size()),
+ unionValue(shared_vector(nchannel,PVUnionPtr())),
+ value(shared_vector(nchannel,PVFieldPtr())),
+ isConnected(false),
+ isDestroyed(false)
+{
+}
+
+
+PvaClientNTMultiPut::~PvaClientNTMultiPut()
+{
+ destroy();
+}
+
+void PvaClientNTMultiPut::destroy()
+{
+ {
+ Lock xx(mutex);
+ if(isDestroyed) return;
+ isDestroyed = true;
+ }
+ pvaClientChannelArray.clear();
+}
+
+void PvaClientNTMultiPut::connect()
+{
+ pvaClientPut.resize(nchannel);
+ shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
+ for(size_t i=0; icreatePut();
+ pvaClientPut[i]->issueConnect();
+ }
+ }
+ for(size_t i=0; iwaitConnect();
+ if(status.isOK()) continue;
+ stringstream ss;
+ string channelName = pvaClientChannelArray[i]->getChannelName();
+ ss << "channel " << channelName << " PvaChannelPut::waitConnect " << status.getMessage();
+ throw std::runtime_error(ss.str());
+ }
+ }
+ for(size_t i=0; iissueGet();
+ }
+ }
+ for(size_t i=0; iwaitGet();
+ if(status.isOK()) continue;
+ stringstream ss;
+ string channelName = pvaClientChannelArray[i]->getChannelName();
+ ss << "channel " << channelName << " PvaChannelPut::waitGet " << status.getMessage();
+ throw std::runtime_error(ss.str());
+ }
+ }
+ for(size_t i=0; igetData()->getValue();
+ FieldBuilderPtr builder = fieldCreate->createFieldBuilder();
+ builder->add("value",value[i]->getField());
+ unionValue[i] = pvDataCreate->createPVUnion(builder->createUnion());
+ }
+ }
+ this->isConnected = true;
+}
+
+shared_vector PvaClientNTMultiPut::getValues()
+{
+ if(!isConnected) connect();
+ return unionValue;
+}
+
+void PvaClientNTMultiPut::put()
+{
+ if(!isConnected) connect();
+ shared_vector isConnected = pvaClientMultiChannel->getIsConnected();
+ for(size_t i=0; icopy(*unionValue[i]->get());
+ pvaClientPut[i]->issuePut();
+ }
+ if(isConnected[i]) {
+ Status status = pvaClientPut[i]->waitPut();
+ if(status.isOK()) continue;
+ stringstream ss;
+ string channelName = pvaClientChannelArray[i]->getChannelName();
+ ss << "channel " << channelName << " PvaChannelPut::waitConnect " << status.getMessage();
+ throw std::runtime_error(ss.str());
+ }
+ }
+}
+
+
+}}