30
README.md
Normal file
30
README.md
Normal file
@@ -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
|
||||
@@ -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
|
||||
@@ -1,222 +0,0 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||
<title>EPICS easyPVA</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://epics-pvdata.sourceforge.net/base.css" />
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
|
||||
<style type="text/css">
|
||||
/*<![CDATA[*/
|
||||
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
||||
table { margin-left: auto; margin-right: auto }
|
||||
.diagram { text-align: center; margin: 2.5em 0 }
|
||||
body { margin-right: 10% }
|
||||
/*]]>*/</style>
|
||||
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="head">
|
||||
<h1>EPICS easyPVA</h1>
|
||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
||||
<h2 class="nocount">EPICS V4 Working Group, Working Draft,
|
||||
25-Mar-2015</h2>
|
||||
<dl>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="easyPVA.html">easyPVA.html
|
||||
</a> </dd>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="easyPVA_20150609.html">easyPVA_20150609.html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href="easyPVA_20150325.html">easyPVA_20150325.html</a>
|
||||
</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
<dd>Matej Sekoranja, Cosylab</dd>
|
||||
</dl>
|
||||
|
||||
<h2 class="nocount">Abstract</h2>
|
||||
<p><b>NO LONGER SUPPPORTED:</b>
|
||||
The functionality has been moved to pvAccessCPP and EasyPva renamed to Pva.
|
||||
</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<!-- last para of Abstract is boilerplate reference to EPICS -->
|
||||
<p>For more information about EPICS generally, please refer to the home page of the <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System</a>.</p>
|
||||
|
||||
|
||||
|
||||
<h2 class="nocount">Status of this Document and of the EasyPVA Software</h2>
|
||||
|
||||
<p>EasyPVACPP is ready for use.</p>
|
||||
|
||||
</div> <!-- head -->
|
||||
|
||||
<div id="toc">
|
||||
<h2 class="nocount">Table of Contents</h2>
|
||||
</div>
|
||||
|
||||
<!-- Place what you would like in the Table of Contents, inside the contents div -->
|
||||
<div id="contents" class="contents">
|
||||
<hr />
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
<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>
|
||||
A user overview is available via
|
||||
<a
|
||||
href="./overview.html">overview.html
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
Doxygen documentation is available at
|
||||
<a
|
||||
href="./html/index.html">doxygenDoc
|
||||
</a>
|
||||
</p>
|
||||
<h2>Building</h2>
|
||||
<p>After obtaining the source:</p>
|
||||
<pre>
|
||||
cd configure
|
||||
cp ExampleRELEASE.local RELEASE.local
|
||||
</pre>
|
||||
<p>Edit <b>RELEASE.local</b> so that all path names are correct for you environment.
|
||||
</p>
|
||||
<p>
|
||||
Then:</p>
|
||||
<pre>
|
||||
cd ..
|
||||
make
|
||||
</pre>
|
||||
|
||||
<h2>Example and Test Database</h2>
|
||||
<p>The examples and tests require that an example pvAccess server is runnimg.
|
||||
This distribution has a file <b>exampleDatabaseEasyPVA.zip</b>.
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
After unzipping the file:
|
||||
</p>
|
||||
<pre>
|
||||
cd configure
|
||||
cp ExampleRELEASE.local RELEASE.local
|
||||
edit RELEASE.local
|
||||
cd ..
|
||||
make
|
||||
cd iocBoot/exampleDatabase
|
||||
../../bin/<arch:>/exampleDatabase st.cmd
|
||||
</pre>
|
||||
<h2>Testing</h2>
|
||||
<p>The tests will fail unless the example database is running.</p>
|
||||
<p>Once it is running:</p>
|
||||
<pre>
|
||||
make runtests
|
||||
</pre>
|
||||
<h2>Examples</h2>
|
||||
<p>Examples are in directory <b>example/src</b>.
|
||||
An example of how to run them is:</p>
|
||||
<pre>
|
||||
mrk> pwd
|
||||
/home/hg/easyPVACPP/example
|
||||
mrk> bin/linux-x86_64/exampleEasyGet
|
||||
</pre>
|
||||
<p>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.</p>
|
||||
<h2>exampleEasyGet</h2>
|
||||
<p>This has a number of examples:</p>
|
||||
<dl>
|
||||
<dt>exampleDouble</dt>
|
||||
<dd>
|
||||
This shows two methods for getting data from a channel that has a numeric
|
||||
scalar value field.
|
||||
</dd>
|
||||
<dt>exampleDoubleArray</dt>
|
||||
<dd>
|
||||
This shows two methods for getting data from a channel that has a
|
||||
double array value field.
|
||||
</dd>
|
||||
<dt>exampleCADouble</dt>
|
||||
<dd>
|
||||
This is like exampleDouble except it uses provider <b>ca</b>.
|
||||
</dd>
|
||||
<dt>exampleCADoubleArray</dt>
|
||||
<dd>
|
||||
This is like exampleDoubleArray except it uses provider <b>ca</b>.
|
||||
</dd>
|
||||
<dt>examplePowerSupply</dt>
|
||||
<dd>
|
||||
This is an example of getting data from a channel that does not
|
||||
have a value field.
|
||||
</dd>
|
||||
</dl>
|
||||
<h2>exampleEasyMonitor</h2>
|
||||
<p>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.
|
||||
</p>
|
||||
<p>After starting the example a change can be made to the powerSupply by issuing:</p>
|
||||
<pre>
|
||||
pvput -r "power.value,voltage.value" examplePowerSupply 6 6
|
||||
</pre>
|
||||
<h2>exampleEasyPut</h2>
|
||||
<p>This example gets and puts to channel exampleDouble.</p>
|
||||
<h2>exampleEasyProcess</h2>
|
||||
<p>This example makes a process request to channel exampleDouble.</p>
|
||||
<h2>helloWorldPutGet</h2>
|
||||
<p>This is an example of issuing a channelPutGet.</p>
|
||||
<h2>exampleEasyMultiDouble</h2>
|
||||
<p>This is an example of issuing gets and puts to multiple channels where each
|
||||
channel has a numeric scalar value field.</p>
|
||||
<h2>exampleEasyNTMultiChannel</h2>
|
||||
<p>This is an example of using NDMultiChannel to obtain data from multiple channels.
|
||||
</p>
|
||||
<h2>helloWorldRPC</h2>
|
||||
<p>This is an example of issuing a channelRPC request.
|
||||
It does <b>not</b> use easyPVA.</p>
|
||||
</div> <!-- class="contents" -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -4,7 +4,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||
<title>EPICS easyPVA</title>
|
||||
<title>EPICS pva</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://epics-pvdata.sourceforge.net/base.css" />
|
||||
<link rel="stylesheet" type="text/css"
|
||||
@@ -25,49 +25,50 @@
|
||||
<body>
|
||||
|
||||
<div class="head">
|
||||
<h1>EPICS easyPVA</h1>
|
||||
<h1>EPICS pvaClientCPP</h1>
|
||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
||||
<h2 class="nocount">EPICS V4 Working Group, Working Draft,
|
||||
25-Mar-2015</h2>
|
||||
03-August-2015</h2>
|
||||
<dl>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="easyPVA.html">easyPVA.html
|
||||
href="pvaClientCPP.html">pvaClientCPP.html
|
||||
</a> </dd>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="easyPVA_20150325.html">easyPVA_20150325.html</a>
|
||||
</dd>
|
||||
href="pvaClientCPP_20150803.html">pvaClientCPP_20150803.html
|
||||
</a> </dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd>none</dd>
|
||||
<dd><a
|
||||
href="pvaClientCPP_20150626.html">pvaClientCPP_20150626.html
|
||||
</a> </dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
<dd>Matej Sekoranja, Cosylab</dd>
|
||||
</dl>
|
||||
|
||||
<h2 class="nocount">Abstract</h2>
|
||||
|
||||
<p>EasyPVA (Easy PVAccess) is a software library that provides to an EPICS client programmer, a friendly
|
||||
<p>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.</p>
|
||||
|
||||
<p>Specifically, easyPVA provides an easy interface for pvAccess, which is the
|
||||
<p>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.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
@@ -78,9 +79,9 @@ The data for the channels is presented via normative type NTMultiChannel.
|
||||
|
||||
|
||||
|
||||
<h2 class="nocount">Status of this Document and of the EasyPVA Software</h2>
|
||||
<h2 class="nocount">Status of this Document and of the pvaClient Software</h2>
|
||||
|
||||
<p>EasyPVACPP is ready for use.</p>
|
||||
<p>pvaClientCPP is ready for use.</p>
|
||||
|
||||
</div> <!-- head -->
|
||||
|
||||
@@ -94,14 +95,14 @@ The data for the channels is presented via normative type NTMultiChannel.
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
<p>EasyPVA is a synchronous API for accessing PVData via PVAccess. It provides
|
||||
<p>pvaClient 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>
|
||||
A user overview is available via
|
||||
<a
|
||||
href="./overview.html">overview.html
|
||||
href="./pvaClientOverview.html">pvaClientOverview.html
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
@@ -110,58 +111,27 @@ Doxygen documentation is available at
|
||||
href="./html/index.html">doxygenDoc
|
||||
</a>
|
||||
</p>
|
||||
<h2>Building</h2>
|
||||
<p>After obtaining the source:</p>
|
||||
<h2>Example Database</h2>
|
||||
<p>The examples require that the database provided by project pvaClientTestCPP
|
||||
is running.
|
||||
For example:</p>
|
||||
<pre>
|
||||
cd configure
|
||||
cp ExampleRELEASE.local RELEASE.local
|
||||
</pre>
|
||||
<p>Edit <b>RELEASE.local</b> so that all path names are correct for you environment.
|
||||
</p>
|
||||
<p>
|
||||
Then:</p>
|
||||
<pre>
|
||||
cd ..
|
||||
make
|
||||
</pre>
|
||||
|
||||
<h2>Example and Test Database</h2>
|
||||
<p>The examples and tests require that an example pvAccess server is runnimg.
|
||||
This distribution has a file <b>exampleDatabaseEasyPVA.zip</b>.
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
After unzipping the file:
|
||||
</p>
|
||||
<pre>
|
||||
cd configure
|
||||
cp ExampleRELEASE.local RELEASE.local
|
||||
edit RELEASE.local
|
||||
cd ..
|
||||
make
|
||||
cd iocBoot/exampleDatabase
|
||||
../../bin/<arch:>/exampleDatabase st.cmd
|
||||
</pre>
|
||||
<h2>Testing</h2>
|
||||
<p>The tests will fail unless the example database is running.</p>
|
||||
<p>Once it is running:</p>
|
||||
<pre>
|
||||
make runtests
|
||||
mrk> pwd
|
||||
/home/epicsv4/pvaClientTestCPP/database/iocBoot/exampleDatabase
|
||||
mrk> ../../bin/linux-x86_64/exampleDatabase st.cmd
|
||||
</pre>
|
||||
<h2>Examples</h2>
|
||||
<p>Examples are in directory <b>example/src</b>.
|
||||
An example of how to run them is:</p>
|
||||
<pre>
|
||||
mrk> pwd
|
||||
/home/hg/easyPVACPP/example
|
||||
mrk> bin/linux-x86_64/exampleEasyGet
|
||||
/home/epicsv4/pvaClientCPP/example
|
||||
mrk> bin/linux-x86_64/examplePvaClientGet
|
||||
</pre>
|
||||
<p>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.</p>
|
||||
<h2>exampleEasyGet</h2>
|
||||
helps to also look at the source for the example.</p>
|
||||
<h2>examplePvaClientGet</h2>
|
||||
<p>This has a number of examples:</p>
|
||||
<dl>
|
||||
<dt>exampleDouble</dt>
|
||||
@@ -188,30 +158,25 @@ helps to also bee loooking at the source for the example.</p>
|
||||
have a value field.
|
||||
</dd>
|
||||
</dl>
|
||||
<h2>exampleEasyMonitor</h2>
|
||||
<h2>examplePvaClientMonitor</h2>
|
||||
<p>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.
|
||||
</p>
|
||||
<p>After starting the example a change can be made to the powerSupply by issuing:</p>
|
||||
<pre>
|
||||
pvput -r "power.value,voltage.value" examplePowerSupply 6 6
|
||||
</pre>
|
||||
<h2>exampleEasyPut</h2>
|
||||
<p>This example gets and puts to channel exampleDouble.</p>
|
||||
<h2>exampleEasyProcess</h2>
|
||||
<h2>examplePvaClientPut</h2>
|
||||
<p>This example gets and puts to channels exampleDouble
|
||||
and exampleDoubleArray.</p>
|
||||
<h2>examplePvaClientProcess</h2>
|
||||
<p>This example makes a process request to channel exampleDouble.</p>
|
||||
<h2>helloWorldPutGet</h2>
|
||||
<p>This is an example of issuing a channelPutGet.</p>
|
||||
<h2>exampleEasyMultiDouble</h2>
|
||||
<p>This is an example of issuing gets and puts to multiple channels where each
|
||||
channel has a numeric scalar value field.</p>
|
||||
<h2>exampleEasyNTMultiChannel</h2>
|
||||
<p>This is an example of using NDMultiChannel to obtain data from multiple channels.
|
||||
<h2>examplePvaClientMultiDouble</h2>
|
||||
<p>This is an example of using pvaClientMultiChannel,
|
||||
pvaClientMultiGetDouble, pvaClientMultiPutDouble, and pvaClientMultiMonitorDouble.
|
||||
</p>
|
||||
<h2>helloWorldRPC</h2>
|
||||
<p>This is an example of issuing a channelRPC request.
|
||||
It does <b>not</b> use easyPVA.</p>
|
||||
It does <b>not</b> use pva.</p>
|
||||
</div> <!-- class="contents" -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -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
|
||||
|
||||
@@ -33,7 +33,7 @@ cout << "num " << num << " names " << channelNames << endl;
|
||||
PvaClientMultiPutDoublePtr multiPut(multiChannel->createPut());
|
||||
PvaClientMultiMonitorDoublePtr multiMonitor(multiChannel->createMonitor());
|
||||
shared_vector<double> 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<num; ++i) data[i] = value + i;
|
||||
cout << "put " << data << endl;
|
||||
@@ -57,7 +57,7 @@ int main(int argc,char *argv[])
|
||||
size_t num = 5;
|
||||
shared_vector<string> 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<string>(num);
|
||||
channelNames[0] = "exampleDouble01";
|
||||
channelNames[1] = "exampleDouble02";
|
||||
channelNames[1] = "exampleInt";
|
||||
channelNames[2] = "exampleDouble03";
|
||||
channelNames[3] = "exampleDouble04";
|
||||
channelNames[4] = "exampleDouble05";
|
||||
|
||||
141
example/src/examplePvaClientNTMulti.cpp
Normal file
141
example/src/examplePvaClientNTMulti.cpp
Normal file
@@ -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 <iostream>
|
||||
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/convert.h>
|
||||
|
||||
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<const Scalar>(field);
|
||||
ScalarType scalarType = scalar->getScalarType();
|
||||
if(scalarType==pvDouble) {
|
||||
PVDoublePtr pvValue = static_pointer_cast<PVDouble>(
|
||||
pvDataCreate->createPVScalar(pvDouble));
|
||||
pvValue->put(value);
|
||||
pvUnion->set(0,pvValue);
|
||||
return;
|
||||
}
|
||||
if(scalarType==pvString) {
|
||||
PVStringPtr pvValue = static_pointer_cast<PVString>(
|
||||
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<const ScalarArray>(field);
|
||||
ScalarType scalarType = scalarArray->getElementType();
|
||||
if(scalarType==pvDouble) {
|
||||
size_t num = 5;
|
||||
PVDoubleArrayPtr pvValue = static_pointer_cast<PVDoubleArray>(
|
||||
pvDataCreate->createPVScalarArray(pvDouble));
|
||||
shared_vector<double> data(num);
|
||||
for(size_t i=0; i<num; ++i) data[i] = value +i;
|
||||
pvValue->replace(freeze(data));
|
||||
pvUnion->set(0,pvValue);
|
||||
return;
|
||||
}
|
||||
if(scalarType==pvString) {
|
||||
size_t num = 5;
|
||||
PVStringArrayPtr pvValue = static_pointer_cast<PVStringArray>(
|
||||
pvDataCreate->createPVScalarArray(pvString));
|
||||
shared_vector<string> data(num);
|
||||
for(size_t i=0; i<num; ++i) {
|
||||
stringstream ss;
|
||||
ss << "value" << value << i;
|
||||
data[i] = ss.str();
|
||||
}
|
||||
pvValue->replace(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 string> 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<epics::pvData::PVUnionPtr> data = multiPut->getValues();
|
||||
for(double value = 0.0; value< 2.1; value+= 1.0) {
|
||||
for(size_t i=0; i<num ; ++i) {
|
||||
PVUnionPtr pvUnion = data[i];
|
||||
setValue(pvUnion,value);
|
||||
}
|
||||
multiPut->put();
|
||||
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<string> channelNames(num);
|
||||
channelNames[0] = "double01";
|
||||
channelNames[1] = "string01";
|
||||
channelNames[2] = "doubleArray01";
|
||||
channelNames[3] = "stringArray01";
|
||||
cout << "dbRecord pva\n";
|
||||
shared_vector<const string> names(freeze(channelNames));
|
||||
example(pva,"pva",names);
|
||||
cout << "dbRecord ca\n";
|
||||
example(pva,"ca",names);
|
||||
channelNames = shared_vector<string>(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;
|
||||
}
|
||||
@@ -13,12 +13,16 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
#include <pv/convert.h>
|
||||
|
||||
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<PVScalar>(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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <pv/event.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/createRequest.h>
|
||||
|
||||
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
@@ -52,7 +52,8 @@ PvaClientMultiChannel::PvaClientMultiChannel(
|
||||
numChannel(channelName.size()),
|
||||
numConnected(0),
|
||||
pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())),
|
||||
isConnected(shared_vector<bool>(numChannel,false)),
|
||||
isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)),
|
||||
createRequest(CreateRequest::create()),
|
||||
isDestroyed(false)
|
||||
{
|
||||
}
|
||||
@@ -131,7 +132,7 @@ bool PvaClientMultiChannel::connectionChange()
|
||||
return false;
|
||||
}
|
||||
|
||||
epics::pvData::shared_vector<bool> PvaClientMultiChannel::getIsConnected()
|
||||
epics::pvData::shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected()
|
||||
{
|
||||
if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
|
||||
for(size_t i=0; i<numChannel; ++i) {
|
||||
@@ -181,5 +182,47 @@ PvaClientMultiMonitorDoublePtr PvaClientMultiChannel::createMonitor()
|
||||
return PvaClientMultiMonitorDouble::create(getPtrSelf(), pvaClientChannelArray);
|
||||
}
|
||||
|
||||
PvaClientNTMultiPutPtr PvaClientMultiChannel::createNTPut()
|
||||
{
|
||||
checkConnected();
|
||||
return PvaClientNTMultiPut::create(getPtrSelf(), pvaClientChannelArray);
|
||||
}
|
||||
|
||||
|
||||
PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet()
|
||||
{
|
||||
return createNTGet("value,alarm,timeStamp");
|
||||
}
|
||||
|
||||
PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet(std::string const &request)
|
||||
{
|
||||
checkConnected();
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(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);
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -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 <pv/pvaClient.h>
|
||||
#include <pv/ntmultiChannel.h>
|
||||
#include <pv/createRequest.h>
|
||||
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
@@ -32,11 +33,20 @@ typedef std::tr1::shared_ptr<PvaClientMultiPutDouble> PvaClientMultiPutDoublePtr
|
||||
class PvaClientMultiMonitorDouble;
|
||||
typedef std::tr1::shared_ptr<PvaClientMultiMonitorDouble> PvaClientMultiMonitorDoublePtr;
|
||||
|
||||
class PvaClientNTMultiGet;
|
||||
typedef std::tr1::shared_ptr<PvaClientNTMultiGet> PvaClientNTMultiGetPtr;
|
||||
class PvaClientNTMultiPut;
|
||||
typedef std::tr1::shared_ptr<PvaClientNTMultiPut> PvaClientNTMultiPutPtr;
|
||||
class PvaClientNTMultiMonitor;
|
||||
typedef std::tr1::shared_ptr<PvaClientNTMultiMonitor> PvaClientNTMultiMonitorPtr;
|
||||
class PvaClientNTMultiData;
|
||||
typedef std::tr1::shared_ptr<PvaClientNTMultiData> PvaClientNTMultiDataPtr;
|
||||
|
||||
|
||||
typedef epics::pvData::shared_vector<PvaClientChannelPtr> 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<bool> getIsConnected();
|
||||
epics::pvData::shared_vector<epics::pvData::boolean> 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<bool> isConnected;
|
||||
epics::pvData::shared_vector<epics::pvData::boolean> 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<PvaClientNTMultiGet>
|
||||
{
|
||||
|
||||
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<PvaClientGetPtr> 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<PvaClientNTMultiPut>
|
||||
{
|
||||
|
||||
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<epics::pvData::PVUnionPtr> 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<epics::pvData::PVUnionPtr> unionValue;
|
||||
epics::pvData::shared_vector<epics::pvData::PVFieldPtr> value;
|
||||
std::vector<PvaClientPutPtr> 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<PvaClientNTMultiMonitor>
|
||||
{
|
||||
|
||||
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<PvaClientMonitorPtr> pvaClientMonitor;
|
||||
bool isConnected;
|
||||
bool isDestroyed;
|
||||
};
|
||||
|
||||
/**
|
||||
* This provides NTMultiChannel data for both PvaClientNTMultiGet and PvaClientNTMultiMonitor.
|
||||
*/
|
||||
class epicsShareClass PvaClientNTMultiData :
|
||||
public std::tr1::enable_shared_from_this<PvaClientNTMultiData>
|
||||
{
|
||||
|
||||
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<epics::pvData::PVStructurePtr> topPVStructure;
|
||||
bool gotAlarm;
|
||||
bool gotTimeStamp;
|
||||
bool isDestroyed;
|
||||
|
||||
epics::nt::NTMultiChannelPtr ntMultiChannel;
|
||||
epics::pvData::PVStructurePtr pvTop;
|
||||
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> unionValue;
|
||||
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;
|
||||
friend class PvaClientNTMultiGet;
|
||||
friend class PvaClientNTMultiPut;
|
||||
friend class PvaClientNTMultiMonitor;
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVACLIENTMULTICHANNEL_H */
|
||||
|
||||
@@ -68,7 +68,7 @@ void PvaClientMultiGetDouble::destroy()
|
||||
|
||||
void PvaClientMultiGetDouble::connect()
|
||||
{
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
string request = "value";
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
@@ -94,7 +94,7 @@ void PvaClientMultiGetDouble::connect()
|
||||
epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
|
||||
{
|
||||
if(!isGetConnected) connect();
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
|
||||
@@ -69,7 +69,7 @@ void PvaClientMultiMonitorDouble::destroy()
|
||||
|
||||
void PvaClientMultiMonitorDouble::connect()
|
||||
{
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
string request = "value";
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
@@ -103,7 +103,7 @@ bool PvaClientMultiMonitorDouble::poll()
|
||||
epicsThreadSleep(.01);
|
||||
}
|
||||
bool result = false;
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
|
||||
@@ -70,7 +70,7 @@ void PvaClientMultiPutDouble::destroy()
|
||||
|
||||
void PvaClientMultiPutDouble::connect()
|
||||
{
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
@@ -98,13 +98,13 @@ void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &da
|
||||
if(data.size()!=nchannel) {
|
||||
throw std::runtime_error("data has wrong size");
|
||||
}
|
||||
shared_vector<bool> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure();
|
||||
PVDoublePtr pvValue = pvTop->getSubField<PVDouble>("value");
|
||||
pvValue->put(data[i]);
|
||||
PVScalarPtr pvValue = pvTop->getSubField<PVScalar>("value");
|
||||
convert->fromDouble(pvValue,data[i]);
|
||||
pvaClientPut[i]->issuePut();
|
||||
}
|
||||
if(isConnected[i]) {
|
||||
|
||||
232
src/pvaClientNTMultiData.cpp
Normal file
232
src/pvaClientNTMultiData.cpp
Normal file
@@ -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 <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/convert.h>
|
||||
#include <epicsMath.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
static ConvertPtr convert = getConvert();
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static StandardFieldPtr standardField = getStandardField();
|
||||
|
||||
|
||||
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; i<nchannel; ++i)
|
||||
{
|
||||
topPVStructure[i] = PVStructurePtr();
|
||||
if(gotAlarm)
|
||||
{
|
||||
alarm.setSeverity(noAlarm);
|
||||
alarm.setStatus(noStatus);
|
||||
alarm.setMessage("");
|
||||
severity[i] = invalidAlarm;
|
||||
status[i] = undefinedStatus;
|
||||
message[i] = "not connected";
|
||||
}
|
||||
if(gotTimeStamp)
|
||||
{
|
||||
timeStamp.getCurrent();
|
||||
secondsPastEpoch[i] = 0;
|
||||
nanoseconds[i] = 0;
|
||||
userTag[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PvaClientNTMultiData::endDeltaTime()
|
||||
{
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
PVStructurePtr pvst = topPVStructure[i];
|
||||
if(!pvst) {
|
||||
unionValue[i] = PVUnionPtr();
|
||||
} else {
|
||||
unionValue[i]->set(pvst->getSubField("value"));
|
||||
}
|
||||
if(gotAlarm)
|
||||
{
|
||||
severity[i] = pvst->getSubField<PVInt>("alarm.severity")->get();
|
||||
status[i] = pvst->getSubField<PVInt>("alarm.status")->get();
|
||||
message[i] = pvst->getSubField<PVString>("alarm.message")->get();
|
||||
}
|
||||
if(gotTimeStamp)
|
||||
{
|
||||
secondsPastEpoch[i] = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch")->get();
|
||||
nanoseconds[i] = pvst->getSubField<PVInt>("timeStamp.nanoseconds")->get();
|
||||
userTag[i] = pvst->getSubField<PVInt>("timeStamp.userTag")->get();
|
||||
}
|
||||
|
||||
}
|
||||
shared_vector<epics::pvData::PVUnionPtr> val(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) val[i] = unionValue[i];
|
||||
ntMultiChannel->getValue()->replace(freeze(val));
|
||||
shared_vector<epics::pvData::boolean> connected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean> isConnected(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) isConnected[i] = connected[i];
|
||||
ntMultiChannel->getIsConnected()->replace(freeze(isConnected));
|
||||
if(gotAlarm)
|
||||
{
|
||||
shared_vector<int32> sev(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) sev[i] = severity[i];
|
||||
ntMultiChannel->getSeverity()->replace(freeze(sev));
|
||||
shared_vector<int32> sta(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) sta[i] = status[i];
|
||||
ntMultiChannel->getStatus()->replace(freeze(sta));
|
||||
shared_vector<string> mes(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) mes[i] = message[i];
|
||||
ntMultiChannel->getMessage()->replace(freeze(mes));
|
||||
}
|
||||
if(gotTimeStamp)
|
||||
{
|
||||
shared_vector<int64> sec(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) sec[i] = secondsPastEpoch[i];
|
||||
ntMultiChannel->getSecondsPastEpoch()->replace(freeze(sec));
|
||||
shared_vector<int32> nano(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) nano[i] = nanoseconds[i];
|
||||
ntMultiChannel->getNanoseconds()->replace(freeze(nano));
|
||||
shared_vector<int32> tag(nchannel);
|
||||
for(size_t i=0; i<nchannel; ++i) tag[i] = userTag[i];
|
||||
ntMultiChannel->getUserTag()->replace(freeze(tag));
|
||||
}
|
||||
}
|
||||
|
||||
TimeStamp PvaClientNTMultiData::getTimeStamp()
|
||||
{
|
||||
pvTimeStamp.get(timeStamp);
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
NTMultiChannelPtr PvaClientNTMultiData::getNTMultiChannel()
|
||||
{
|
||||
return ntMultiChannel;
|
||||
}
|
||||
|
||||
PVStructurePtr PvaClientNTMultiData::getPVTop()
|
||||
{
|
||||
return ntMultiChannel->getPVStructure();
|
||||
}
|
||||
|
||||
}}
|
||||
143
src/pvaClientNTMultiGet.cpp
Normal file
143
src/pvaClientNTMultiGet.cpp
Normal file
@@ -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 <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/convert.h>
|
||||
#include <epicsMath.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
static ConvertPtr convert = getConvert();
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static StandardFieldPtr standardField = getStandardField();
|
||||
|
||||
|
||||
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<epics::pvData::boolean> 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; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(request);
|
||||
pvaClientGet[i]->issueConnect();
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientGet[i]->waitConnect();
|
||||
if(status.isOK()) continue;
|
||||
stringstream ss;
|
||||
string channelName = pvaClientChannelArray[i]->getChannelName();
|
||||
ss << "channel " << channelName << " PvaChannelGet::waitConnect " << status.getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
this->isConnected = true;
|
||||
}
|
||||
|
||||
void PvaClientNTMultiGet::get()
|
||||
{
|
||||
if(!isConnected) connect();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientGet[i]->issueGet();
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientGet[i]->waitGet();
|
||||
if(status.isOK()) continue;
|
||||
stringstream ss;
|
||||
string channelName = pvaClientChannelArray[i]->getChannelName();
|
||||
ss << "channel " << channelName << " PvaChannelGet::waitConnect " << status.getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
pvaClientNTMultiData->startDeltaTime();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientNTMultiData->setPVStructure(pvaClientGet[i]->getData()->getPVStructure(),i);
|
||||
}
|
||||
}
|
||||
pvaClientNTMultiData->endDeltaTime();
|
||||
}
|
||||
|
||||
PvaClientNTMultiDataPtr PvaClientNTMultiGet::getData()
|
||||
{
|
||||
return pvaClientNTMultiData;
|
||||
}
|
||||
|
||||
}}
|
||||
155
src/pvaClientNTMultiMonitor.cpp
Normal file
155
src/pvaClientNTMultiMonitor.cpp
Normal file
@@ -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 <epicsThread.h>
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/convert.h>
|
||||
#include <epicsMath.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
static ConvertPtr convert = getConvert();
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static StandardFieldPtr standardField = getStandardField();
|
||||
|
||||
|
||||
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<epics::pvData::boolean> 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; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(request);
|
||||
pvaClientMonitor[i]->issueConnect();
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientMonitor[i]->waitConnect();
|
||||
if(status.isOK()) continue;
|
||||
stringstream ss;
|
||||
string channelName = pvaClientChannelArray[i]->getChannelName();
|
||||
ss << "channel " << channelName << " PvaChannelMonitor::waitConnect " << status.getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) pvaClientMonitor[i]->start();
|
||||
}
|
||||
this->isConnected = true;
|
||||
}
|
||||
|
||||
bool PvaClientNTMultiMonitor::poll()
|
||||
{
|
||||
if(!isConnected) connect();
|
||||
bool result = false;
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
pvaClientNTMultiData->startDeltaTime();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
if(pvaClientMonitor[i]->poll()) {
|
||||
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;
|
||||
}
|
||||
|
||||
}}
|
||||
149
src/pvaClientNTMultiPut.cpp
Normal file
149
src/pvaClientNTMultiPut.cpp
Normal file
@@ -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 <pv/pvaClientMultiChannel.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/convert.h>
|
||||
#include <epicsMath.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
static ConvertPtr convert = getConvert();
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static StandardFieldPtr standardField = getStandardField();
|
||||
static CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||
|
||||
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<epics::pvData::PVUnionPtr>(nchannel,PVUnionPtr())),
|
||||
value(shared_vector<epics::pvData::PVFieldPtr>(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<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientPut[i] = pvaClientChannelArray[i]->createPut();
|
||||
pvaClientPut[i]->issueConnect();
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientPut[i]->waitConnect();
|
||||
if(status.isOK()) continue;
|
||||
stringstream ss;
|
||||
string channelName = pvaClientChannelArray[i]->getChannelName();
|
||||
ss << "channel " << channelName << " PvaChannelPut::waitConnect " << status.getMessage();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientPut[i]->issueGet();
|
||||
}
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientPut[i]->waitGet();
|
||||
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; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
value[i] = pvaClientPut[i]->getData()->getValue();
|
||||
FieldBuilderPtr builder = fieldCreate->createFieldBuilder();
|
||||
builder->add("value",value[i]->getField());
|
||||
unionValue[i] = pvDataCreate->createPVUnion(builder->createUnion());
|
||||
}
|
||||
}
|
||||
this->isConnected = true;
|
||||
}
|
||||
|
||||
shared_vector<epics::pvData::PVUnionPtr> PvaClientNTMultiPut::getValues()
|
||||
{
|
||||
if(!isConnected) connect();
|
||||
return unionValue;
|
||||
}
|
||||
|
||||
void PvaClientNTMultiPut::put()
|
||||
{
|
||||
if(!isConnected) connect();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
value[i]->copy(*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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
Reference in New Issue
Block a user