all EasyChannel methods are implemented except channelArray; EasyMultiChannel not started.

This commit is contained in:
Marty Kraimer
2015-03-13 15:09:55 -04:00
parent 5dc5e746f4
commit cdc72bc5ae
32 changed files with 4366 additions and 1747 deletions

View File

@ -1078,7 +1078,7 @@ HTML_EXTRA_STYLESHEET =
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES = documentation/easyPVACPP.html
#HTML_EXTRA_FILES = documentation/overview.html
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the stylesheet and background images according to

9
README.txt Normal file
View File

@ -0,0 +1,9 @@
To build do the following:
cd configure
cp ExampleRELEASE.local RELEASE.local
edit RELEASE.local
cd ..
make
Now read documentation/easyPVA.html

View File

@ -28,7 +28,7 @@
<h1>EPICS easyPVA</h1>
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
<h2 class="nocount">EPICS V4 Working Group, Working Draft,
02-Mar-2015</h2>
13-Mar-2015</h2>
<dl>
<dt>This version:</dt>
<dd><a
@ -68,8 +68,6 @@ The first is as an NTMultiChannel. The second is as a double array.
The double array can be used if the value field of every channel is a numeric scalar.
There is code for NTMultiChannel that helps with access to more complicated data types.
</p>
<p>EasyPVA will become part of pvAccess when it is ready. </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
@ -96,159 +94,35 @@ There is code for NTMultiChannel that helps with access to more complicated data
<p>EasyPVA is a synchronous API for accessing PVData via PVAccess. It provides
an interface to many of the features provided by pvData and pvAccess.</p>
<p>The EasyPVA API has the following features:</p>
<ol>
<li>Makes common requests easy to program</li>
<li>Provides full access to the pvAccess API for more demanding
applications</li>
<li>Allows efficient client side programs.</li>
</ol>
<p>This document briefly describes the CPP version of EasyPVA.
Doxygen documentation is available at <a
href="./html/index.html">doxygenDoc</a></p>
<h3>EasyPVA Interfaces</h3>
<h4>Simple</h4>
<p>The following</p>
<pre>
EasyPVAPtr easyPVA = EasyPVA::create();
double value = easyPVA-&gt;channel("exampleDouble")-&gt;get()-&gt;getDouble();
cout &lt;&lt; "as double " &lt;&lt; value &lt;&lt; endl;
</pre>
produces:
<pre>
as double 5
</pre>
<p>This is an example of the simplest way to use EasyPVA.
An important feature is that,
when the simple interface is used,
EasyPva caches Channels, ChannelGets, etc.
This if the above code is replaced by:</p>
<pre>
EasyPVAPtr easyPVA = EasyPVA::create();
double value = easyPVA-&gt;channel("exampleDouble")-&gt;get()-&gt;getDouble();
cout &lt;&lt; "as double " &lt;&lt; value &lt;&lt; endl;
value = easyPVA-&gt;channel("exampleDouble")-&gt;get()-&gt;getDouble();
cout &lt;&lt; "as double " &lt;&lt; value &lt;&lt; endl;
</pre>
The second call will reuse the channel and channelGet created by the first call.
<p>But if any problems occur using the simple interface an exception is thrown.</p>
<h4>More Complex But No Exceptions.</h4>
<p>The following</p>
<pre>
EasyPVAPtr easyPVA = EasyPVA::create();
EasyChannelPtr easyChannel = easyPVA-&gt;createChannel("exampleDouble");
easyChannel-&gt;issueConnect();
Status status = easyChannel-&gt;waitConnect(2.0);
if(!status.isOK()) {cout &lt;&lt; " connect failed\n"; return;}
EasyGetPtr easyGet = easyChannel-&gt;createGet();
easyGet-&gt;issueConnect();
status = easyGet-&gt;waitConnect();
if(!status.isOK()) {cout &lt;&lt; " createGet failed\n"; return;}
value = easyGet-&gt;getDouble();
cout &lt;&lt; "as double " &lt;&lt; value &lt;&lt; endl;
</pre>
also produces:
<pre>
as double 5
</pre>
<p>The main feature of this over the simple way is that no exceptions will be thrown.</p>
<h3>Initialization</h3>
<p>A client obtains the interface to EasyPVA via the call:</p>
<pre>EasyPVAPtr easyPVA = EasyPVAFactorys-&gt;create();</pre>
<p>The client can call this an arbitrary number of times.
On the first call the PVAccess client factory is started.
When the last EasyPVA is destroyed the PVAccess client factory is stopped.
</p>This document describes the layout of the source files in this project.</p>
<p>
A user overview is available via
<a
href="./overiew.html">overview.html
</a>
</p>
<h3>EasyPVA Overview</h3>
<p>EasyPVA creates interfaces to one of the following:</p>
<dl>
<dt>EasyChannel</dt>
<dd>This creates an interface for accessing a single channel.<br />
There are two methods for creating an EasyChannel,
with the difference being that the second
specifiers the name of the provider.
The other assumes that the provider is "pva" (pvAccess).
</dd>
<dt>EasyMultiChannel</dt>
<dd>This creates an interface for accessing a set of channels.<br />
There are multiple methods for creating an EasyMultiChannel.
The provider can be supplied or use a default of "pva".
A union for the UnionArray for accessing the value fields of each channel
can be provided or a default of variant union will be used.
</dd>
</dl>
<h3>EasyChannel Overview</h3>
<p>This interface creates Easy support for each PVAccess::Channel create
method:</p>
<dl>
<dt>EasyField</dt>
<dd>This gets the introspection interface from a channel. The
implementation provides full access to the features of
Channel::getField.</dd>
<dt>EasyProcess</dt>
<dd>This is used to process a channel. The implementation provides full
access to the features of ChannelProcess.</dd>
<dt>EasyGet</dt>
<dd>This is used to get values from a channel. The implementation allows
full access to all the features of ChannelGet. By default it asks for the
fields value, alarm, and timeStamp. If the channel has a value field then
EasyGet provides convenience methods for a scalar value and for an array
value. </dd>
<dt>EasyPut</dt>
<dd>This is used to get the current value of a channel and to put values to
a channel. The implementation allows full access to all the features of
ChannelPut. By default it asks for the field value, alarm, and timeStamp.
If the channel has a value field then EasyPut provides convenience
methods for a scalar value and for an array value. </dd>
<dt>EasyRPC</dt>
<dd>This is an interface to ChannelRPC.
The implementation allows full access to all the features of ChannelRPC.
</dd>
<dt>EasyPutGet</dt>
<dd>This is an interface to ChannelPutGet. Details TBD.</dd>
<dt>EasyMonitor</dt>
<dd>This is an interface to Monitor.
The implementation allows full access to all the features of pvAccess Monitor.
</dd>
<dt>EasyArray</dt>
<dd>This is an interface to ChannelArray. Details TBD.</dd>
<dt>EasyProcess</dt>
<dd>This is an interface to ChannelProcess. Details TBD.</dd>
</dl>
<h3>EasyMultiChannel Overview</h3>
<p>This interface creates Easy support for accessing a set of channels.
The only requirement of the channels is that each must have a top level field named value.
<p>
Doxygen documentation is available at
<a
href="./html/index.html">doxygenDoc
</a>
</p>
<dl>
<dt>EasyMultiGet</dt>
<dd>This is used to get values from a a set of channels.
The result can either be an NTMultiChannel structure or a <b>double[]</b> array.
The createGet method determines the result type.
</dd>
<dt>EasyMultiPut</dt>
<dd>This is used to get and put values from/to a set of channels.
The data supplied can either be an NTMultiChannel structure or a <b>double[]</b> array.
The createPut method determines the type.
</dd>
<dt>EasyMonitor</dt>
<dd>This is used to monitor values from a set of channels.
Each event can either be an NTMultiChannel structure or a <b>double[]</b> array.
The createMonitor method determines the data type.
</dd>
</dl>
<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 source code</h2>
<h3>Example Database</h3>
<h2>Example and Test Database</h2>
<p>The examples 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.
@ -267,8 +141,14 @@ make
cd iocBoot/exampleDatabase
../../bin/&lt;arch:&gt;/exampleDatabase st.cmd
</pre>
<h3>Examples</h3>
<p>These are examples in directory <b>example/src</b>.
<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&gt; pwd
@ -279,8 +159,6 @@ mrk&gt; bin/linux-x86_64/exampleEasyGet
See the source code for each example.
</p>
</div> <!-- class="contents" -->
</body>
</html>

294
documentation/overview.html Normal file
View File

@ -0,0 +1,294 @@
<?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>easyPVA C++ Overview</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>easyPVA C++ Overview</h1>
</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 also provides a number of convience methods.
It allows the client to request access without checking for failure,
but throws an exception when a reuest fails.
A client can also check for failues and thus prevent failures.</p>
<p>The EasyPVA API has the following features:</p>
<ol>
<li>Provides a synchronous API rather than the callback API provided by pvAccess.</li>
<li>Makes common requests easy.</li>
<li>Provides full access to the pvAccess API for more demanding
applications</li>
<li>Allows efficient client side programs.</li>
<li>Takes care of most object resource management problems.</li>
</ol>
<p>Simple examples of using easyPVA:</p>
<pre>
// easyGet
EasyPVAPtr easyPVA = EasyPVA::create();
double value = easyPVA-&gt;channel("exampleDouble")-&gt;get()-&gt;getData()-&gt;getDouble();
// easyPut
EasyChannelPtr channel = easyPVA-&gt;channel("exampleDouble");
EasyPutPtr put = channel-&gt;put();
EasyPutDataPtr putData = put-&gt;getData();
putData-&gt;putDouble(3.0); put-&gt;put();
// easyMonitor
EasyMonitorPtr monitor = easyPVA-&gt;channel("examplePowerSupply")-&gt;monitor("");
EasyMonitorDataPtr easyData = monitor-&gt;getData();
while(true) {
monitor-&gt;waitEvent();
cout &lt;&lt; "changed\n";
easyData-&gt;showChanged(cout);
cout &lt;&lt; "overrun\n";
easyData-&gt;showOverrun(cout);
monitor-&gt;releaseEvent();
}
// easyProcess
EasyChannelPtr channel = easyPVA-&gt;channel("exampleDouble");
EasyProcessPtr process = channel-&gt;createProcess();
process-&gt;process();
</pre>
<h2>EasyPVA</h2>
<p>An instance of EasyPVA is obtained via the call:</p>
<pre>
EasyPVAPtr easyPVA = EasyPVA::create();
</pre>
<p>EasyPVA has methods to create instances of <b>EasyChannel</b>.
The client can specify the provider name or use the default provider.
The client can manage it's own channels or can let easyPVA cache channels.
An example of using the cache method is:</p>
<pre>
string channelName("exampleDouble");
EasyChannelPtr easyChannel = easyPVA-&gt;channel(channelName);
</pre>
<p>This will attempt to connect to channel exampleDouble.
Since the client did not specify a timeout an exception wll be thrown if
the connection request fails.
The client will block until the connection is made or an exception is thrown.
If the request succeeds, easyPVA caches the easyChannel so that if the
client makes another request for the same channel the cached object is
returned to the client.
</p>
<p>An example of using a non cached method is:</p>
<pre>
string channelName("exampleDouble");
EasyChannelPtr easyChannel = easyPVA-&gt;createChannel(channelName);
</pre>
<p>This will create an EasyChannel and return it to the client.
The client must itself connect.
This is useful if the client wants to connect to multiple channels in parallel.
</p>
<h2>EasyChannel - Wrapper For Single Channel</h2>
<h3>EasyChannel</h3>
<p>This provides methods for connecting to a channel and for creating instances of
EasyField, EasyProcess, ..., EasyRPC.</p>
<p>Connection must be made before any crete method is called or
an exception is raised.
The following is a synchronous connection request:</p>
<pre>
easyChannel-&gt;connect(5.0); // BLOCKS
</pre>
<p>This blocks until then connection is made or until timout occurs.
An exception is raised if the connection request fails.
</p>
<p>The same request can be made without blocking and without exceptions.</p>
<pre>
easyChannel-&gt;issueConnect(); // DOES NOT BLOCK
.....
Status status =easyChannel-&gt;waitConnect(5.0); // BLOCKS
if(!status.isOK()) {
// failure do something
}
</pre>
<p>Once the channel is connected other Easy objects can be created.
For example:</p>
<pre>
EasyGetPtr easyGet = easyChannel-&gt;get(); // DOES BLOCK
</pre>
<p>This is a caching request.
If the client already has made an identical request the client will receive the
cached object.
If a new easyGet is created than it is connected before it is returned to the client.
</p>
<p>The client can also managed it's own objects:</p>
<pre>
EasyGetPtr easyGet = easyChannel-&gt;createGet(); // DOES NOT BLOCK
</pre>
<p>The client must connect the easyGet.</p>
<h3>EasyGetData</h3>
<p>This provides the data returned by easyGet and easyPutGet.
It is obtained via:</p>
<pre>
EasyGetDataPtr easyData = easyGet-&gt;getData();
</pre>
<p>It provides methods to get everything returned by channelGet.
In addition there are methods that make it easier to handle a value
field that is a scalar or a scalarArray.
Also for a scalar that is a double or a scalarArray with element type double.
</p>
<p>An example is:</p>
<pre>
double value = easyData-&gt;getDouble();
</pre>
<p>It also keeps a bitSet showing which fields have changed since the last channelGet or channelPutGet.</p>
<h3>EasyMonitorData</h3>
<p>To the client this looks identical to EasyGetData except that
it provides two BitSets: changedBitSet and overrrunBitSet.
It is used by easyMonitor.
</p>
<h3>EasyPutData</h3>
<p>This is used to provided data for easyPut and easyPutGet.
It has many of the same methods as easyGetData.
It does not have a bitSet.
It also has put methods like:</p>
<pre>
void easyData-&gt;putDouble(5.0);
</pre>
<h3>EasyGet</h3>
<p>This provides methods to connect to channelGet and to issue get request.
To connect via a single synchronous call:</p>
<pre>
eastGet-&gt;connect(); // BLOCKS
</pre>
<p>This can also be done in two steps:</p>
<pre>
easyGet-&gt;issueConnect(); // DOES NOT BLOCK
...
Status status = easyGet-&gt;waitConnect(); // BLOCKS
</pre>
<p>Once connected gets are issued via either:</p>
<pre>
void easyGet-&gt;get();
</pre>
or
<pre>
easyGet-&gt;issueGet(); // DOES NOT BLOCK
...
Status status = easyGet-&gt;waitGet(); // BLOCKS
</pre>
<h3>EasyPut</h3>
<p>This is similar to easyGet except that it wraps channelPut instead of channelGet.
</p>
<p>Once connected puts are issued via either:</p>
<pre>
void easyPut-&gt;put();
</pre>
or
<pre>
easyPut-&gt;issuePut(); // DOES NOT BLOCK
...
Status status = easyPut-&gt;waitPut(); // BLOCKS
</pre>
<h3>EasyMonitor</h3>
<p>Connecting is similar to easyGet and easyPut.
The other methods are:</p>
<dl>
<dt>start</dt>
<dd>Starts monitoring</dd>
<dt>stop</dt>
<dd>Stops monitoring</dd>
<dt>poll</dt>
<dd>polls for a monitorEvent.
The data is avalable via easyMonitorData.
</dd>
<dt>releaseEvent</dt>
<dd>Release the data from the last poll.
Note that this must be called before another poll is requested.
</dd>
<dt>waitEvent</dt>
<dd>Block until a monitorEvent is available.
If true is returned a poll has already been issued.
</dd>
<dt>setRequester</dt>
<dd>A client callback is registered to receive notice of monitorEvents.</dd>
</dl>
<h3>EasyProcess</h3>
<p>Connecting is similar to easyGet.
It has methods:</p>
<dl>
<dt>process</dt>
<dd>call issueProcess and waitProcess.</dd>
<dt>issueProcess</dt>
<dd>call channelProcess-&gt;process() and return immediately.
</dd>
<dt>waitProcess</dt>
<dd>Wait for process to complete.</dd>
</dl>
<h3>EasyPutGet</h3>
<p>Connecting is similar to easyGet.
It has methods:</p>
<dl>
<dt>putGet</dt>
<dd>calls issuePutGet and waitPutGet.
throws an exception if not successfull.
</dd>
<dt>issuePutGet</dt>
<dd>
Calls channel-&gt;putGet() and returns.
</dd>
<dt>waitPutGet</dt>
<dd>
Waits until putGet completes and returns status.
</dd>
<dt>getGet,issueGetGet, and waitGetGet</dt>
<dd>Gets the data for the get part of channelPutGet.</dd>
<dt>getPut,issueGetPut,and waitGetPut</dt>
<dd>Gets the data for the put part of channelPutGet.</dd>
<dt>getPutData</dt>
<dd>
Returns the EasyData for the put part of channelPutGet.
</dd>
<dt>getGetData</dt>
<dd>
Returns the EasyData for the get part of channelPutGet.
</dd>
</dl>
<p>Look at javaDoc for details.</p>
<h2>EasyMultiChannel - Wrapper For Multiple Channels</h2>
<p>TBD</p>
</div> <!-- class="contents" -->
</body>
</html>

View File

@ -5,6 +5,13 @@ include $(TOP)/configure/CONFIG
# ADD MACRO DEFINITIONS AFTER THIS LINE
PROD_HOST += exampleEasyProcess
exampleEasyProcess_SRCS += exampleEasyProcess.cpp
exampleEasyProcess_LIBS += easyPVA
exampleEasyProcess_LIBS += pvAccess
exampleEasyProcess_LIBS += pvData
exampleEasyProcess_LIBS += Com
PROD_HOST += exampleEasyGet
exampleEasyGet_SRCS += exampleEasyGet.cpp
exampleEasyGet_LIBS += easyPVA
@ -12,6 +19,20 @@ exampleEasyGet_LIBS += pvAccess
exampleEasyGet_LIBS += pvData
exampleEasyGet_LIBS += Com
PROD_HOST += exampleEasyPut
exampleEasyPut_SRCS += exampleEasyPut.cpp
exampleEasyPut_LIBS += easyPVA
exampleEasyPut_LIBS += pvAccess
exampleEasyPut_LIBS += pvData
exampleEasyPut_LIBS += Com
PROD_HOST += exampleEasyMonitor
exampleEasyMonitor_SRCS += exampleEasyMonitor.cpp
exampleEasyMonitor_LIBS += easyPVA
exampleEasyMonitor_LIBS += pvAccess
exampleEasyMonitor_LIBS += pvData
exampleEasyMonitor_LIBS += Com
#===========================
include $(TOP)/configure/RULES

View File

@ -26,7 +26,7 @@ static void exampleDouble(EasyPVAPtr const &easyPVA)
double value;
try {
cout << "short way\n";
value = easyPVA->channel("exampleDouble")->get()->getDouble();
value = easyPVA->channel("exampleDouble")->get()->getData()->getDouble();
cout << "as double " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
@ -40,17 +40,18 @@ static void exampleDouble(EasyPVAPtr const &easyPVA)
easyGet->issueConnect();
status = easyGet->waitConnect();
if(!status.isOK()) {cout << " createGet failed\n"; return;}
value = easyGet->getDouble();
EasyGetDataPtr easyData = easyGet->getData();
value = easyData->getDouble();
cout << "as double " << value << endl;
}
static void exampleDoubleArray(EasyPVAPtr const &easyPVA)
{
cout << "example double array\n";
shared_vector<double> value;
shared_vector<const double> value;
try {
cout << "short way\n";
value = easyPVA->createChannel("exampleDoubleArray")->createGet()->getDoubleArray();
value = easyPVA->channel("exampleDoubleArray")->get()->getData()->getDoubleArray();
cout << "as doubleArray " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
@ -60,7 +61,8 @@ static void exampleDoubleArray(EasyPVAPtr const &easyPVA)
EasyChannelPtr easyChannel = easyPVA->createChannel("exampleDoubleArray");
easyChannel->connect(2.0);
EasyGetPtr easyGet = easyChannel->createGet();
value = easyGet->getDoubleArray();
EasyGetDataPtr easyData = easyGet->getData();
value = easyData->getDoubleArray();
cout << "as doubleArray " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
@ -73,7 +75,8 @@ static void examplePowerSupply(EasyPVAPtr const &easyPVA)
PVStructurePtr pvStructure;
try {
cout << "short way\n";
pvStructure = easyPVA->createChannel("examplePowerSupply")->createGet("field()")->getPVStructure();
pvStructure = easyPVA->channel("examplePowerSupply")->
get("field()")->getData()->getPVStructure();
cout << pvStructure << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;

View File

@ -0,0 +1,46 @@
/*monitorPowerSupply.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 <epicsThread.h>
#include <iostream>
#include <pv/easyPVA.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::easyPVA;
static void exampleMonitor(EasyPVAPtr const &easyPVA)
{
EasyMonitorPtr monitor = easyPVA->channel("examplePowerSupply")->monitor("");
EasyMonitorDataPtr easyData = monitor->getData();
while(true) {
monitor->waitEvent();
cout << "changed\n";
easyData->showChanged(cout);
cout << "overrun\n";
easyData->showOverrun(cout);
monitor->releaseEvent();
}
}
int main(int argc,char *argv[])
{
EasyPVAPtr easyPVA = EasyPVA::create();
exampleMonitor(easyPVA);
cout << "done\n";
return 0;
}

View File

@ -0,0 +1,44 @@
/*exampleEasyProcess.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/easyPVA.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::easyPVA;
static void exampleProcess(EasyPVAPtr const &easyPVA)
{
cout << "example process\n";
EasyChannelPtr channel = easyPVA->channel("exampleDouble");
EasyProcessPtr process = channel->createProcess();
try {
process->process();
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
process->process();
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
int main(int argc,char *argv[])
{
EasyPVAPtr easyPVA = EasyPVA::create();
exampleProcess(easyPVA);
return 0;
}

View File

@ -0,0 +1,45 @@
/*exampleEasyProcess.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/easyPVA.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::easyPVA;
static void examplePut(EasyPVAPtr const &easyPVA)
{
cout << "example process\n";
EasyChannelPtr channel = easyPVA->channel("exampleDouble");
EasyPutPtr put = channel->put();
EasyPutDataPtr putData = put->getData();
try {
putData->putDouble(3.0); put->put();
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
putData->putDouble(4.0); put->put();
cout << channel->get("field()")->getData()->showChanged(cout) << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
int main(int argc,char *argv[])
{
EasyPVAPtr easyPVA = EasyPVA::create();
examplePut(easyPVA);
return 0;
}

View File

@ -8,11 +8,15 @@ LIBRARY += easyPVA
INC += easyPVA.h
LIBSRCS += easyPVA.cpp
LIBSRCS += easyPVStructure.cpp
LIBSRCS += easyPutData.cpp
LIBSRCS += easyGetData.cpp
LIBSRCS += easyMonitorData.cpp
LIBSRCS += easyChannel.cpp
LIBSRCS += easyProcess.cpp
LIBSRCS += easyGet.cpp
#LIBSRCS += easyPut.cpp
#LIBSRCS += easyMonitor.cpp
LIBSRCS += easyPut.cpp
LIBSRCS += easyMonitor.cpp
LIBSRCS += easyPutGet.cpp
#LIBSRCS += easyRPC.cpp
easyPVA_LIBS += pvAccess pvData Com

View File

@ -25,8 +25,6 @@ using namespace std;
namespace epics { namespace easyPVA {
class EasyGetCache;
typedef std::tr1::shared_ptr<EasyGetCache> EasyGetCachePtr;
class EasyGetCache
{
@ -60,109 +58,65 @@ void EasyGetCache::addGet(string const & request,EasyGetPtr const & easyGet)
request,easyGet));
}
class epicsShareClass EasyChannelImpl :
public EasyChannel,
public std::tr1::enable_shared_from_this<EasyChannelImpl>
class EasyPutCache
{
public:
EasyChannelImpl(
EasyPVAPtr const &pva,
string const & channelName,
string const & providerName);
virtual ~EasyChannelImpl();
// from EasyChannel
void channelCreated(const Status& status, Channel::shared_pointer const & channel);
void channelStateChange(
Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState);
tr1::shared_ptr<Channel> getChannel();
string getRequesterName();
void message(
string const & message,
MessageType messageType);
virtual void destroy();
virtual string getChannelName();
virtual void connect(double timeout);
virtual void issueConnect();
virtual Status waitConnect(double timeout);
virtual EasyFieldPtr createField();
virtual EasyFieldPtr createField(string const & subField);
virtual EasyProcessPtr createProcess();
virtual EasyProcessPtr createProcess(string const & request);
virtual EasyProcessPtr createProcess(PVStructurePtr const & pvRequest);
virtual EasyGetPtr get() {return get("value,alarm,timeStamp");}
virtual EasyGetPtr get(string const & request);
virtual EasyGetPtr createGet();
virtual EasyGetPtr createGet(string const & request);
virtual EasyGetPtr createGet(PVStructurePtr const & pvRequest);
virtual EasyPutPtr createPut();
virtual EasyPutPtr createPut(string const & request);
virtual EasyPutPtr createPut(PVStructurePtr const & pvRequest);
virtual EasyPutGetPtr createPutGet();
virtual EasyPutGetPtr createPutGet(string const & request);
virtual EasyPutGetPtr createPutGet(PVStructurePtr const & pvRequest);
virtual EasyRPCPtr createRPC();
virtual EasyRPCPtr createRPC(string const & request);
virtual EasyRPCPtr createRPC(PVStructurePtr const & pvRequest);
virtual EasyArrayPtr createArray();
virtual EasyArrayPtr createArray(string const & request);
virtual EasyArrayPtr createArray(PVStructurePtr const & pvRequest);
virtual EasyMonitorPtr createMonitor();
virtual EasyMonitorPtr createMonitor(string const & request);
virtual EasyMonitorPtr createMonitor(PVStructurePtr const & pvRequest);
EasyChannelPtr getPtrSelf()
{
return shared_from_this();
EasyPutCache(){}
~EasyPutCache();
void destroy() {
easyPutMap.clear();
}
EasyPutPtr getPut(string const & request);
void addPut(string const & request,EasyPutPtr const & easyPut);
private:
enum ConnectState {connectIdle,connectActive,notConnected,connected};
EasyPVA::weak_pointer easyPVA;
string channelName;
string providerName;
ConnectState connectState;
bool isDestroyed;
CreateRequest::shared_pointer createRequest;
EasyGetCachePtr easyGetCache;
Status channelConnectStatus;
Mutex mutex;
Event waitForConnect;
Channel::shared_pointer channel;
ChannelRequester::shared_pointer channelRequester;
map<string,EasyPutPtr> easyPutMap;
};
namespace easyChannel {
EasyPutCache::~EasyPutCache()
{
destroy();
}
EasyPutPtr EasyPutCache::getPut(string const & request)
{
map<string,EasyPutPtr>::iterator iter = easyPutMap.find(request);
if(iter!=easyPutMap.end()) return iter->second;
return EasyPutPtr();
}
void EasyPutCache::addPut(string const & request,EasyPutPtr const & easyPut)
{
easyPutMap.insert(std::pair<string,EasyPutPtr>(
request,easyPut));
}
class ChannelRequesterImpl : public ChannelRequester
{
EasyChannelImpl *easyChannel;
EasyChannel *easyChannel;
public:
ChannelRequesterImpl(EasyChannelImpl *easyChannel)
ChannelRequesterImpl(EasyChannel *easyChannel)
: easyChannel(easyChannel) {}
virtual void channelCreated(
void channelCreated(
const Status& status,
Channel::shared_pointer const & channel)
{ easyChannel->channelCreated(status,channel); }
virtual void channelStateChange(
void channelStateChange(
Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState)
{easyChannel->channelStateChange(channel,connectionState);}
virtual tr1::shared_ptr<Channel> getChannel() {return easyChannel->getChannel();}
virtual string getRequesterName()
tr1::shared_ptr<Channel> getChannel() {return easyChannel->getChannel();}
string getRequesterName()
{return easyChannel->getRequesterName();}
virtual void message(
void message(
string const & message,
MessageType messageType)
{ easyChannel->message(message,messageType); }
virtual void destroy() {easyChannel->destroy();}
void destroy() {easyChannel->destroy();}
};
} //end namespace easyChannel`
using namespace epics::easyPVA::easyChannel;
EasyChannelImpl::EasyChannelImpl(
EasyChannel::EasyChannel(
EasyPVAPtr const &easyPVA,
string const & channelName,
string const & providerName)
@ -172,25 +126,26 @@ EasyChannelImpl::EasyChannelImpl(
connectState(connectIdle),
isDestroyed(false),
createRequest(CreateRequest::create()),
easyGetCache(new EasyGetCache())
easyGetCache(new EasyGetCache()),
easyPutCache(new EasyPutCache())
{}
EasyChannelImpl::~EasyChannelImpl()
EasyChannel::~EasyChannel()
{
destroy();
}
void EasyChannelImpl::channelCreated(const Status& status, Channel::shared_pointer const & channel)
void EasyChannel::channelCreated(const Status& status, Channel::shared_pointer const & channel)
{
if(isDestroyed) throw std::runtime_error("easyChannel was destroyed");
if(status.isOK()) {
this->channel = channel;
return;
}
cout << "EasyChannelImpl::channelCreated status " << status.getMessage() << " why??\n";
cout << "EasyChannel::channelCreated status " << status.getMessage() << " why??\n";
}
void EasyChannelImpl::channelStateChange(
void EasyChannel::channelStateChange(
Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState)
{
@ -209,20 +164,20 @@ void EasyChannelImpl::channelStateChange(
if(waitingForConnect) waitForConnect.signal();
}
tr1::shared_ptr<Channel> EasyChannelImpl::getChannel()
tr1::shared_ptr<Channel> EasyChannel::getChannel()
{
if(isDestroyed) throw std::runtime_error("easyChannel was destroyed");
return channel;
}
string EasyChannelImpl::getRequesterName()
string EasyChannel::getRequesterName()
{
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("EasyPVA was destroyed");
return yyy->getRequesterName();
}
void EasyChannelImpl::message(
void EasyChannel::message(
string const & message,
MessageType messageType)
{
@ -232,7 +187,7 @@ void EasyChannelImpl::message(
yyy->message(message, messageType);
}
void EasyChannelImpl::destroy()
void EasyChannel::destroy()
{
{
Lock xx(mutex);
@ -242,15 +197,16 @@ void EasyChannelImpl::destroy()
if(channel) channel->destroy();
channel.reset();
easyGetCache.reset();
easyPutCache.reset();
}
string EasyChannelImpl::getChannelName()
string EasyChannel::getChannelName()
{
if(isDestroyed) throw std::runtime_error("easyChannel was destroyed");
return channelName;
}
void EasyChannelImpl::connect(double timeout)
void EasyChannel::connect(double timeout)
{
if(isDestroyed) throw std::runtime_error("easyChannel was destroyed");
issueConnect();
@ -261,7 +217,7 @@ void EasyChannelImpl::connect(double timeout)
throw std::runtime_error(ss.str());
}
void EasyChannelImpl::issueConnect()
void EasyChannel::issueConnect()
{
if(isDestroyed) throw std::runtime_error("easyChannel was destroyed");
if(connectState!=connectIdle) {
@ -279,7 +235,7 @@ void EasyChannelImpl::issueConnect()
}
}
Status EasyChannelImpl::waitConnect(double timeout)
Status EasyChannel::waitConnect(double timeout)
{
if(isDestroyed) throw std::runtime_error("easyChannel was destroyed");
waitForConnect.wait(timeout);
@ -287,22 +243,22 @@ Status EasyChannelImpl::waitConnect(double timeout)
return Status(Status::STATUSTYPE_ERROR,channelConnectStatus.getMessage());
}
EasyFieldPtr EasyChannelImpl::createField()
EasyFieldPtr EasyChannel::createField()
{
return createField("");
}
EasyFieldPtr EasyChannelImpl::createField(string const & subField)
EasyFieldPtr EasyChannel::createField(string const & subField)
{
throw std::runtime_error("EasyChannel::createField not implemented");
}
EasyProcessPtr EasyChannelImpl::createProcess()
EasyProcessPtr EasyChannel::createProcess()
{
return createProcess("");
}
EasyProcessPtr EasyChannelImpl::createProcess(string const & request)
EasyProcessPtr EasyChannel::createProcess(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
@ -314,28 +270,33 @@ EasyProcessPtr EasyChannelImpl::createProcess(string const & request)
return createProcess(pvRequest);
}
EasyProcessPtr EasyChannelImpl::createProcess(PVStructurePtr const & pvRequest)
EasyProcessPtr EasyChannel::createProcess(PVStructurePtr const & pvRequest)
{
throw std::runtime_error("EasyChannel::createProcess not implemented");
if(connectState!=connected) connect(5.0);
if(connectState!=connected) throw std::runtime_error("EasyChannel::creatProcess not connected");
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("EasyPVA was destroyed");
return EasyProcess::create(yyy,getPtrSelf(),channel,pvRequest);
}
EasyGetPtr EasyChannelImpl::get(string const & request)
EasyGetPtr EasyChannel::get() {return get("value,alarm,timeStamp");}
EasyGetPtr EasyChannel::get(string const & request)
{
EasyGetPtr easyGet = easyGetCache->getGet(request);
if(easyGet) return easyGet;
easyGet = createGet(request);
easyGet->connect();
easyGet->get();
easyGetCache->addGet(request,easyGet);
return easyGet;
}
EasyGetPtr EasyChannelImpl::createGet()
EasyGetPtr EasyChannel::createGet()
{
return EasyChannelImpl::createGet("value,alarm,timeStamp");
return EasyChannel::createGet("value,alarm,timeStamp");
}
EasyGetPtr EasyChannelImpl::createGet(string const & request)
EasyGetPtr EasyChannel::createGet(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
@ -347,21 +308,34 @@ EasyGetPtr EasyChannelImpl::createGet(string const & request)
return createGet(pvRequest);
}
EasyGetPtr EasyChannelImpl::createGet(PVStructurePtr const & pvRequest)
EasyGetPtr EasyChannel::createGet(PVStructurePtr const & pvRequest)
{
if(connectState!=connected) connect(5.0);
if(connectState!=connected) throw std::runtime_error("EasyChannel::creatGet not connected");
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("EasyPVA was destroyed");
return EasyGetFactory::createEasyGet(yyy,getPtrSelf(),channel,pvRequest);
return EasyGet::create(yyy,getPtrSelf(),channel,pvRequest);
}
EasyPutPtr EasyChannelImpl::createPut()
EasyPutPtr EasyChannel::put() {return put("value");}
EasyPutPtr EasyChannel::put(string const & request)
{
EasyPutPtr easyPut = easyPutCache->getPut(request);
if(easyPut) return easyPut;
easyPut = createPut(request);
easyPut->connect();
easyPut->get();
easyPutCache->addPut(request,easyPut);
return easyPut;
}
EasyPutPtr EasyChannel::createPut()
{
return createPut("value");
}
EasyPutPtr EasyChannelImpl::createPut(string const & request)
EasyPutPtr EasyChannel::createPut(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
@ -373,17 +347,21 @@ EasyPutPtr EasyChannelImpl::createPut(string const & request)
return createPut(pvRequest);
}
EasyPutPtr EasyChannelImpl::createPut(PVStructurePtr const & pvRequest)
EasyPutPtr EasyChannel::createPut(PVStructurePtr const & pvRequest)
{
throw std::runtime_error("EasyChannel::createPut not implemented");
if(connectState!=connected) connect(5.0);
if(connectState!=connected) throw std::runtime_error("EasyChannel::creatPut not connected");
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("EasyPVA was destroyed");
return EasyPut::create(yyy,getPtrSelf(),channel,pvRequest);
}
EasyPutGetPtr EasyChannelImpl::createPutGet()
EasyPutGetPtr EasyChannel::createPutGet()
{
return createPutGet("putField(argument)getField(result)");
}
EasyPutGetPtr EasyChannelImpl::createPutGet(string const & request)
EasyPutGetPtr EasyChannel::createPutGet(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
@ -395,17 +373,21 @@ EasyPutGetPtr EasyChannelImpl::createPutGet(string const & request)
return createPutGet(pvRequest);
}
EasyPutGetPtr EasyChannelImpl::createPutGet(PVStructurePtr const & pvRequest)
EasyPutGetPtr EasyChannel::createPutGet(PVStructurePtr const & pvRequest)
{
throw std::runtime_error("EasyChannel::createPutGet not implemented");
if(connectState!=connected) connect(5.0);
if(connectState!=connected) throw std::runtime_error("EasyChannel::creatPutGet not connected");
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("EasyPVA was destroyed");
return EasyPutGet::create(yyy,getPtrSelf(),channel,pvRequest);
}
EasyRPCPtr EasyChannelImpl::createRPC()
EasyRPCPtr EasyChannel::createRPC()
{
return createRPC("");
}
EasyRPCPtr EasyChannelImpl::createRPC(string const & request)
EasyRPCPtr EasyChannel::createRPC(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
@ -417,17 +399,17 @@ EasyRPCPtr EasyChannelImpl::createRPC(string const & request)
return createRPC(pvRequest);
}
EasyRPCPtr EasyChannelImpl::createRPC(PVStructurePtr const & pvRequest)
EasyRPCPtr EasyChannel::createRPC(PVStructurePtr const & pvRequest)
{
throw std::runtime_error("EasyChannel::createRPC not implemented");
}
EasyArrayPtr EasyChannelImpl::createArray()
EasyArrayPtr EasyChannel::createArray()
{
return createArray("value");
}
EasyArrayPtr EasyChannelImpl::createArray(string const & request)
EasyArrayPtr EasyChannel::createArray(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
@ -439,17 +421,42 @@ EasyArrayPtr EasyChannelImpl::createArray(string const & request)
return createArray(pvRequest);
}
EasyArrayPtr EasyChannelImpl::createArray(PVStructurePtr const & pvRequest)
EasyArrayPtr EasyChannel::createArray(PVStructurePtr const & pvRequest)
{
throw std::runtime_error("EasyChannel::createArray not implemented");
}
EasyMonitorPtr EasyChannelImpl::createMonitor()
EasyMonitorPtr EasyChannel::monitor() {return monitor("value,alarm,timeStamp");}
EasyMonitorPtr EasyChannel::monitor(string const & request)
{
EasyMonitorPtr easyMonitor = createMonitor(request);
easyMonitor->connect();
easyMonitor->start();
return easyMonitor;
}
EasyMonitorPtr EasyChannel::monitor(EasyMonitorRequesterPtr const & easyMonitorRequester)
{ return monitor("value,alarm,timeStamp",easyMonitorRequester);
}
EasyMonitorPtr EasyChannel::monitor(string const & request,
EasyMonitorRequesterPtr const & easyMonitorRequester)
{
EasyMonitorPtr easyMonitor = createMonitor(request);
easyMonitor->connect();
easyMonitor->setRequester(easyMonitorRequester);
easyMonitor->start();
return easyMonitor;
}
EasyMonitorPtr EasyChannel::createMonitor()
{
return createMonitor("value,alarm,timeStamp");
}
EasyMonitorPtr EasyChannelImpl::createMonitor(string const & request)
EasyMonitorPtr EasyChannel::createMonitor(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
@ -461,25 +468,22 @@ EasyMonitorPtr EasyChannelImpl::createMonitor(string const & request)
return createMonitor(pvRequest);
}
EasyMonitorPtr EasyChannelImpl::createMonitor(PVStructurePtr const & pvRequest)
EasyMonitorPtr EasyChannel::createMonitor(PVStructurePtr const & pvRequest)
{
throw std::runtime_error("EasyChannel::createMonitor not implemented");
if(connectState!=connected) connect(5.0);
if(connectState!=connected) throw std::runtime_error("EasyChannel::createMonitor not connected");
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("EasyPVA was destroyed");
return EasyMonitor::create(yyy,getPtrSelf(),channel,pvRequest);
}
EasyChannelPtr EasyChannelFactory::createEasyChannel(
EasyPVAPtr const &easyPVA,
string const & channelName)
{
return EasyChannelFactory::createEasyChannel(easyPVA,channelName,"pva");
}
EasyChannelPtr EasyChannelFactory::createEasyChannel(
EasyChannelPtr EasyChannel::create(
EasyPVAPtr const &easyPVA,
string const & channelName,
string const & providerName)
{
EasyChannelPtr channel(new EasyChannelImpl(easyPVA,channelName,providerName));
EasyChannelPtr channel(new EasyChannel(easyPVA,channelName,providerName));
return channel;
}

View File

@ -12,9 +12,7 @@
#include <sstream>
#include <pv/event.h>
#include <pv/lock.h>
#include <pv/easyPVA.h>
#include <pv/createRequest.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
@ -23,139 +21,31 @@ using namespace std;
namespace epics { namespace easyPVA {
class epicsShareClass EasyGetImpl :
public EasyGet,
public std::tr1::enable_shared_from_this<EasyGetImpl>
class ChannelGetRequesterImpl : public ChannelGetRequester
{
EasyGet * easyGet;
public:
EasyGetImpl(
EasyPVAPtr const &pva,
EasyChannelPtr const & easyChannel,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest);
~EasyGetImpl();
// from ChannelGetRequester
string getRequesterName();
void message(string const & message,MessageType messageType);
ChannelGetRequesterImpl(EasyGet * easyGet)
: easyGet(easyGet) {}
string getRequesterName()
{return easyGet->getRequesterName();}
void message(string const & message,MessageType messageType)
{easyGet->message(message,messageType);}
void channelGetConnect(
const Status& status,
ChannelGet::shared_pointer const & channelGet,
StructureConstPtr const & structure);
StructureConstPtr const & structure)
{easyGet->channelGetConnect(status,channelGet,structure);}
void getDone(
const Status& status,
ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const & pvStructure,
BitSetPtr const & bitSet);
// from EasyGet
virtual void destroy();
virtual void connect();
virtual void issueConnect();
virtual Status waitConnect();
virtual void get();
virtual void issueGet();
virtual Status waitGet();
virtual BitSetPtr getBitSet();
// from EasyPVStructure
virtual void setMessagePrefix(std::string const & value);
virtual void setPVStructure(epics::pvData::PVStructurePtr const & pvStructure);
virtual Alarm getAlarm();
virtual TimeStamp getTimeStamp();
virtual bool hasValue();
virtual bool isValueScalar();
virtual bool isValueScalarArray();
virtual PVFieldPtr getValue();
virtual PVScalarPtr getScalarValue();
virtual std::tr1::shared_ptr<PVArray> getArrayValue();
virtual std::tr1::shared_ptr<PVScalarArray> getScalarArrayValue();
virtual bool getBoolean();
virtual int8 getByte();
virtual int16 getShort();
virtual int32 getInt();
virtual int64 getLong();
virtual uint8 getUByte();
virtual uint16 getUShort();
virtual uint32 getUInt();
virtual uint64 getULong();
virtual float getFloat();
virtual double getDouble();
virtual std::string getString();
virtual shared_vector<boolean> getBooleanArray();
virtual shared_vector<int8> getByteArray();
virtual shared_vector<int16> getShortArray();
virtual shared_vector<int32> getIntArray();
virtual shared_vector<int64> getLongArray();
virtual shared_vector<uint8> getUByteArray();
virtual shared_vector<uint16> getUShortArray();
virtual shared_vector<uint32> getUIntArray();
virtual shared_vector<uint64> getULongArray();
virtual shared_vector<float> getFloatArray();
virtual shared_vector<double> getDoubleArray();
virtual shared_vector<std::string> getStringArray();
virtual PVStructurePtr getPVStructure();
EasyGetPtr getPtrSelf()
{
return shared_from_this();
}
private:
void checkGetState();
enum GetConnectState {connectIdle,connectActive,connected};
EasyPVA::weak_pointer easyPVA;
EasyChannel::weak_pointer easyChannel;
Channel::shared_pointer channel;
ChannelGetRequester::shared_pointer getRequester;
PVStructurePtr pvRequest;
Mutex mutex;
Event waitForConnect;
Event waitForGet;
EasyPVStructurePtr easyPVStructure;
string messagePrefix;
bool isDestroyed;
Status channelGetConnectStatus;
Status channelGetStatus;
ChannelGet::shared_pointer channelGet;
BitSet::shared_pointer bitSet;
GetConnectState connectState;
enum GetState {getIdle,getActive,getComplete};
GetState getState;
bool getSuccess;
BitSetPtr const & bitSet)
{easyGet->getDone(status,channelGet,pvStructure,bitSet);}
};
namespace easyGet {
class ChannelGetRequesterImpl : public ChannelGetRequester
{
EasyGetImpl * easyGet;
public:
ChannelGetRequesterImpl(EasyGetImpl * easyGet)
: easyGet(easyGet) {}
virtual string getRequesterName()
{return easyGet->getRequesterName();}
virtual void message(string const & message,MessageType messageType)
{easyGet->message(message,messageType);}
virtual void channelGetConnect(
const Status& status,
ChannelGet::shared_pointer const & channelGet,
StructureConstPtr const & structure)
{easyGet->channelGetConnect(status,channelGet,structure);}
virtual void getDone(
const Status& status,
ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const & pvStructure,
BitSetPtr const & bitSet)
{easyGet->getDone(status,channelGet,pvStructure,bitSet);}
};
} // namespace easyGet
using namespace epics::easyPVA::easyGet;
EasyGetImpl::EasyGetImpl(
EasyGet::EasyGet(
EasyPVAPtr const &pva,
EasyChannelPtr const & easyChannel,
Channel::shared_pointer const & channel,
@ -164,20 +54,18 @@ EasyGetImpl::EasyGetImpl(
easyChannel(easyChannel),
channel(channel),
pvRequest(pvRequest),
easyPVStructure(pva->createEasyPVStructure()),
isDestroyed(false),
connectState(connectIdle),
getState(getIdle)
{
easyPVStructure->setMessagePrefix("channel " + channel->getChannelName() + " EasyGet");
}
EasyGetImpl::~EasyGetImpl()
EasyGet::~EasyGet()
{
destroy();
}
void EasyGetImpl::checkGetState()
void EasyGet::checkGetState()
{
if(isDestroyed) throw std::runtime_error("easyGet was destroyed");
if(connectState==connectIdle) connect();
@ -185,14 +73,14 @@ void EasyGetImpl::checkGetState()
}
// from ChannelGetRequester
string EasyGetImpl::getRequesterName()
string EasyGet::getRequesterName()
{
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("easyPVA was destroyed");
return yyy->getRequesterName();
}
void EasyGetImpl::message(string const & message,MessageType messageType)
void EasyGet::message(string const & message,MessageType messageType)
{
if(isDestroyed) throw std::runtime_error("easyGet was destroyed");
EasyPVAPtr yyy = easyPVA.lock();
@ -200,7 +88,7 @@ void EasyGetImpl::message(string const & message,MessageType messageType)
yyy->message(message, messageType);
}
void EasyGetImpl::channelGetConnect(
void EasyGet::channelGetConnect(
const Status& status,
ChannelGet::shared_pointer const & channelGet,
StructureConstPtr const & structure)
@ -209,35 +97,30 @@ void EasyGetImpl::channelGetConnect(
channelGetConnectStatus = status;
this->channelGet = channelGet;
if(status.isOK()) {
connectState = connected;
} else {
connectState = connectIdle;
easyData = EasyGetData::create(structure);
easyData->setMessagePrefix(channel->getChannelName());
}
waitForConnect.signal();
}
void EasyGetImpl::getDone(
void EasyGet::getDone(
const Status& status,
ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const & pvStructure,
BitSetPtr const & bitSet)
{
if(isDestroyed) throw std::runtime_error("easyGet was destroyed");
easyPVStructure->setPVStructure(pvStructure);
this->bitSet = bitSet;
channelGetStatus = status;
if(status.isOK()) {
getState = getComplete;
} else {
getState = getIdle;
easyData->setData(pvStructure,bitSet);
}
waitForGet.signal();
}
// from EasyGet
void EasyGetImpl::destroy()
void EasyGet::destroy()
{
{
Lock xx(mutex);
@ -248,7 +131,7 @@ void EasyGetImpl::destroy()
channelGet.reset();
}
void EasyGetImpl::connect()
void EasyGet::connect()
{
if(isDestroyed) throw std::runtime_error("easyGet was destroyed");
issueConnect();
@ -259,7 +142,7 @@ void EasyGetImpl::connect()
throw std::runtime_error(ss.str());
}
void EasyGetImpl::issueConnect()
void EasyGet::issueConnect()
{
if(isDestroyed) throw std::runtime_error("easyGet was destroyed");
if(connectState!=connectIdle) {
@ -272,7 +155,7 @@ void EasyGetImpl::issueConnect()
channelGet = channel->createChannelGet(getRequester,pvRequest);
}
Status EasyGetImpl::waitConnect()
Status EasyGet::waitConnect()
{
if(isDestroyed) throw std::runtime_error("easyGet was destroyed");
if(connectState!=connectActive) {
@ -281,11 +164,15 @@ Status EasyGetImpl::waitConnect()
throw std::runtime_error(ss.str());
}
waitForConnect.wait();
if(connectState==connected) return Status::Ok;
if(channelGetConnectStatus.isOK()){
connectState = connected;
return Status::Ok;
}
connectState = connectIdle;
return Status(Status::STATUSTYPE_ERROR,channelGetConnectStatus.getMessage());
}
void EasyGetImpl::get()
void EasyGet::get()
{
if(isDestroyed) throw std::runtime_error("easyGet was destroyed");
issueGet();
@ -296,7 +183,7 @@ void EasyGetImpl::get()
throw std::runtime_error(ss.str());
}
void EasyGetImpl::issueGet()
void EasyGet::issueGet()
{
if(isDestroyed) throw std::runtime_error("easyGet was destroyed");
if(connectState==connectIdle) connect();
@ -309,7 +196,7 @@ void EasyGetImpl::issueGet()
channelGet->get();
}
Status EasyGetImpl::waitGet()
Status EasyGet::waitGet()
{
if(isDestroyed) throw std::runtime_error("easyGet was destroyed");
if(getState!=getActive){
@ -318,243 +205,25 @@ Status EasyGetImpl::waitGet()
throw std::runtime_error(ss.str());
}
waitForGet.wait();
if(getState==getComplete) {
getState = getIdle;
getState = getIdle;
if(channelGetStatus.isOK()) {
return Status::Ok;
}
return Status(Status::STATUSTYPE_ERROR,channelGetStatus.getMessage());
}
BitSetPtr EasyGetImpl::getBitSet()
{
if(isDestroyed) throw std::runtime_error("easyGet was destroyed");
return bitSet;
}
void EasyGetImpl::setMessagePrefix(string const & value)
{
messagePrefix = value;
if(value.size()>0) messagePrefix += " ";
}
void EasyGetImpl::setPVStructure(epics::pvData::PVStructurePtr const & pvStructure)
{
if(isDestroyed) throw std::runtime_error("easyGet was destroyed");
throw std::runtime_error("easyGet does not implement setPVStructure");
}
Alarm EasyGetImpl::getAlarm()
EasyGetDataPtr EasyGet::getData()
{
checkGetState();
return easyPVStructure->getAlarm();
return easyData;
}
TimeStamp EasyGetImpl::getTimeStamp()
{
checkGetState();
return easyPVStructure->getTimeStamp();
}
bool EasyGetImpl::hasValue()
{
checkGetState();
return easyPVStructure->hasValue();
}
bool EasyGetImpl::isValueScalar()
{
checkGetState();
return easyPVStructure->isValueScalar();
}
bool EasyGetImpl::isValueScalarArray()
{
checkGetState();
return easyPVStructure->isValueScalarArray();
}
PVFieldPtr EasyGetImpl::getValue()
{
checkGetState();
return easyPVStructure->getValue();
}
PVScalarPtr EasyGetImpl::getScalarValue()
{
checkGetState();
return easyPVStructure->getScalarValue();
}
std::tr1::shared_ptr<PVArray> EasyGetImpl::getArrayValue()
{
checkGetState();
return easyPVStructure->getArrayValue();
}
std::tr1::shared_ptr<PVScalarArray> EasyGetImpl::getScalarArrayValue()
{
checkGetState();
return easyPVStructure->getScalarArrayValue();
}
bool EasyGetImpl::getBoolean()
{
checkGetState();
return easyPVStructure->getBoolean();
}
int8 EasyGetImpl::getByte()
{
checkGetState();
return easyPVStructure->getByte();
}
int16 EasyGetImpl::getShort()
{
checkGetState();
return easyPVStructure->getShort();
}
int32 EasyGetImpl::getInt()
{
checkGetState();
return easyPVStructure->getInt();
}
int64 EasyGetImpl::getLong()
{
checkGetState();
return easyPVStructure->getLong();
}
uint8 EasyGetImpl::getUByte()
{
checkGetState();
return easyPVStructure->getUByte();
}
uint16 EasyGetImpl::getUShort()
{
checkGetState();
return easyPVStructure->getUShort();
}
uint32 EasyGetImpl::getUInt()
{
checkGetState();
return easyPVStructure->getUInt();
}
uint64 EasyGetImpl::getULong()
{
checkGetState();
return easyPVStructure->getULong();
}
float EasyGetImpl::getFloat()
{
checkGetState();
return easyPVStructure->getFloat();
}
double EasyGetImpl::getDouble()
{
checkGetState();
return easyPVStructure->getDouble();
}
std::string EasyGetImpl::getString()
{
checkGetState();
return easyPVStructure->getString();
}
shared_vector<boolean> EasyGetImpl::getBooleanArray()
{
checkGetState();
return easyPVStructure->getBooleanArray();
}
shared_vector<int8> EasyGetImpl::getByteArray()
{
checkGetState();
return easyPVStructure->getByteArray();
}
shared_vector<int16> EasyGetImpl::getShortArray()
{
checkGetState();
return easyPVStructure->getShortArray();
}
shared_vector<int32> EasyGetImpl::getIntArray()
{
checkGetState();
return easyPVStructure->getIntArray();
}
shared_vector<int64> EasyGetImpl::getLongArray()
{
checkGetState();
return easyPVStructure->getLongArray();
}
shared_vector<uint8> EasyGetImpl::getUByteArray()
{
checkGetState();
return easyPVStructure->getUByteArray();
}
shared_vector<uint16> EasyGetImpl::getUShortArray()
{
checkGetState();
return easyPVStructure->getUShortArray();
}
shared_vector<uint32> EasyGetImpl::getUIntArray()
{
checkGetState();
return easyPVStructure->getUIntArray();
}
shared_vector<uint64> EasyGetImpl::getULongArray()
{
checkGetState();
return easyPVStructure->getULongArray();
}
shared_vector<float> EasyGetImpl::getFloatArray()
{
checkGetState();
return easyPVStructure->getFloatArray();
}
shared_vector<double> EasyGetImpl::getDoubleArray()
{
checkGetState();
return easyPVStructure->getDoubleArray();
}
shared_vector<std::string> EasyGetImpl::getStringArray()
{
checkGetState();
return easyPVStructure->getStringArray();
}
PVStructurePtr EasyGetImpl::getPVStructure()
{
checkGetState();
return easyPVStructure->getPVStructure();
}
EasyGetPtr EasyGetFactory::createEasyGet(
EasyGetPtr EasyGet::create(
EasyPVAPtr const &pva,
EasyChannelPtr const & easyChannel,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
EasyGetPtr epv(new EasyGetImpl(pva,easyChannel,channel,pvRequest));
EasyGetPtr epv(new EasyGet(pva,easyChannel,channel,pvRequest));
return epv;
}

200
src/easyGetData.cpp Normal file
View File

@ -0,0 +1,200 @@
/* easyGetData.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2015.02
*/
#define epicsExportSharedSymbols
#include <typeinfo>
#include <sstream>
#include <pv/easyPVA.h>
#include <pv/createRequest.h>
#include <pv/convert.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace easyPVA {
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
static ConvertPtr convert = getConvert();
static string noStructure("no pvStructure ");
static string noValue("no value field");
static string noScalar("value is not a scalar");
static string notCompatibleScalar("value is not a compatible scalar");
static string noArray("value is not an array");
static string noScalarArray("value is not a scalarArray");
static string notDoubleArray("value is not a doubleArray");
static string notStringArray("value is not a stringArray");
EasyGetDataPtr EasyGetData::create(StructureConstPtr const & structure)
{
EasyGetDataPtr epv(new EasyGetData(structure));
return epv;
}
EasyGetData::EasyGetData(StructureConstPtr const & structure)
: structure(structure)
{}
void EasyGetData::checkValue()
{
if(pvValue) return;
throw std::runtime_error(messagePrefix + noValue);
}
void EasyGetData::setMessagePrefix(std::string const & value)
{
messagePrefix = value;
}
StructureConstPtr EasyGetData::getStructure()
{return structure;}
PVStructurePtr EasyGetData::getPVStructure()
{
if(pvStructure) return pvStructure;
throw std::runtime_error(messagePrefix + noStructure);
}
BitSetPtr EasyGetData::getBitSet()
{
if(bitSet)return bitSet;
throw std::runtime_error(messagePrefix + noStructure);
}
std::ostream & EasyGetData::showChanged(std::ostream & out)
{
if(!bitSet) throw std::runtime_error(messagePrefix + noStructure);
size_t nextSet = bitSet->nextSetBit(0);
PVFieldPtr pvField;
while(nextSet!=string::npos) {
if(nextSet==0) {
pvField = pvStructure;
} else {
pvField = pvStructure->getSubField(nextSet);
}
string name = pvField->getFullName();
out << name << " = " << pvField << endl;
nextSet = bitSet->nextSetBit(nextSet+1);
}
return out;
}
void EasyGetData::setData(
PVStructurePtr const & pvStructureFrom,
BitSetPtr const & bitSetFrom)
{
pvStructure = pvStructureFrom;
bitSet = bitSetFrom;
pvValue = pvStructure->getSubField("value");
}
bool EasyGetData::hasValue()
{
if(!pvValue) return false;
return true;
}
bool EasyGetData::isValueScalar()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalar) return true;
return false;
}
bool EasyGetData::isValueScalarArray()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalarArray) return true;
return false;
}
PVFieldPtr EasyGetData::getValue()
{
checkValue();
return pvValue;
}
PVScalarPtr EasyGetData::getScalarValue()
{
checkValue();
PVScalarPtr pv = pvStructure->getSubField<PVScalar>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + noScalar);
}
return pv;
}
PVArrayPtr EasyGetData::getArrayValue()
{
checkValue();
PVArrayPtr pv = pvStructure->getSubField<PVArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + noArray);
}
return pv;
}
PVScalarArrayPtr EasyGetData::getScalarArrayValue()
{
checkValue();
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + noScalarArray);
}
return pv;
}
double EasyGetData::getDouble()
{
PVScalarPtr pvScalar = getScalarValue();
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
return pvDouble->get();
}
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::runtime_error(notCompatibleScalar);
}
return convert->toDouble(pvScalar);
}
string EasyGetData::getString()
{
PVScalarPtr pvScalar = getScalarValue();
return convert->toString(pvScalar);
}
shared_vector<const double> EasyGetData::getDoubleArray()
{
checkValue();
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notDoubleArray);
}
return pv->view();
}
shared_vector<const string> EasyGetData::getStringArray()
{
checkValue();
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notStringArray);
}
return pv->view();
}
}}

250
src/easyMonitor.cpp Normal file
View File

@ -0,0 +1,250 @@
/* easyMonitor.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 <sstream>
#include <pv/event.h>
#include <pv/easyPVA.h>
#include <pv/bitSetUtil.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace easyPVA {
class ChannelMonitorRequester : public MonitorRequester
{
EasyMonitor * easyMonitor;
public:
ChannelMonitorRequester(EasyMonitor * easyMonitor)
: easyMonitor(easyMonitor) {}
string getRequesterName()
{return easyMonitor->getRequesterName();}
void message(string const & message,MessageType messageType)
{easyMonitor->message(message,messageType);}
void monitorConnect(
const Status& status,
Monitor::shared_pointer const & monitor,
StructureConstPtr const & structure)
{easyMonitor->monitorConnect(status,monitor,structure);}
void monitorEvent(MonitorPtr const & monitor)
{
easyMonitor->monitorEvent(monitor);
}
void unlisten(MonitorPtr const & monitor)
{easyMonitor->unlisten();}
};
EasyMonitor::EasyMonitor(
EasyPVAPtr const &pva,
EasyChannelPtr const & easyChannel,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
: easyPVA(pva),
easyChannel(easyChannel),
channel(channel),
pvRequest(pvRequest),
isDestroyed(false),
connectState(connectIdle),
userPoll(false),
userWait(false)
{
}
EasyMonitor::~EasyMonitor()
{
destroy();
}
void EasyMonitor::checkMonitorState()
{
if(isDestroyed) throw std::runtime_error("easyMonitor was destroyed");
if(connectState==connectIdle) connect();
if(connectState==connected) start();
}
// from MonitorRequester
string EasyMonitor::getRequesterName()
{
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("easyPVA was destroyed");
return yyy->getRequesterName();
}
void EasyMonitor::message(string const & message,MessageType messageType)
{
if(isDestroyed) throw std::runtime_error("easyMonitor was destroyed");
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("easyPVA was destroyed");
yyy->message(message, messageType);
}
void EasyMonitor::monitorConnect(
const Status& status,
Monitor::shared_pointer const & monitor,
StructureConstPtr const & structure)
{
if(isDestroyed) throw std::runtime_error("easyMonitor was destroyed");
connectStatus = status;
this->monitor = monitor;
if(status.isOK()) {
easyData = EasyMonitorData::create(structure);
easyData->setMessagePrefix(channel->getChannelName());
}
waitForConnect.signal();
}
void EasyMonitor::monitorEvent(MonitorPtr const & monitor)
{
EasyMonitorRequesterPtr req = easyMonitorRequester.lock();
if(req) req->event(getPtrSelf());
if(userWait) waitForEvent.signal();
}
void EasyMonitor::unlisten()
{
destroy();
}
// from EasyMonitor
void EasyMonitor::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
if(monitor) monitor->destroy();
monitor.reset();
}
void EasyMonitor::connect()
{
if(isDestroyed) throw std::runtime_error("easyMonitor was destroyed");
issueConnect();
Status status = waitConnect();
if(status.isOK()) return;
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyMonitor::connect " << status.getMessage();
throw std::runtime_error(ss.str());
}
void EasyMonitor::issueConnect()
{
if(isDestroyed) throw std::runtime_error("easyMonitor was destroyed");
if(connectState!=connectIdle) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " easyMonitor already connected ";
throw std::runtime_error(ss.str());
}
monitorRequester = ChannelMonitorRequester::shared_pointer(new ChannelMonitorRequester(this));
connectState = connectActive;
monitor = channel->createMonitor(monitorRequester,pvRequest);
}
Status EasyMonitor::waitConnect()
{
if(isDestroyed) throw std::runtime_error("easyMonitor was destroyed");
if(connectState!=connectActive) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " easyMonitor illegal connect state ";
throw std::runtime_error(ss.str());
}
waitForConnect.wait();
if(connectStatus.isOK()){
connectState = connected;
return Status::Ok;
}
connectState = connectIdle;
return Status(Status::STATUSTYPE_ERROR,connectStatus.getMessage());
}
void EasyMonitor::setRequester(EasyMonitorRequesterPtr const & easyMonitorrRequester)
{
this->easyMonitorRequester = easyMonitorrRequester;
}
void EasyMonitor::start()
{
if(isDestroyed) throw std::runtime_error("easyMonitor was destroyed");
if(connectState==monitorStarted) return;
if(connectState==connectIdle) connect();
if(connectState!=connected) throw std::runtime_error("EasyMonitor::start illegal state");
connectState = monitorStarted;
monitor->start();
}
void EasyMonitor::stop()
{
if(isDestroyed) throw std::runtime_error("easyMonitor was destroyed");
if(connectState!=monitorStarted) return;
connectState = connected;
monitor->stop();
}
bool EasyMonitor::poll()
{
checkMonitorState();
if(connectState!=monitorStarted) throw std::runtime_error("EasyMonitor::poll illegal state");
if(userPoll) throw std::runtime_error("EasyMonitor::poll did not release last");
monitorElement = monitor->poll();
if(!monitorElement) return false;
userPoll = true;
easyData->setData(monitorElement);
return true;
}
bool EasyMonitor::waitEvent(double secondsToWait)
{
if(isDestroyed) throw std::runtime_error("easyMonitor was destroyed");
if(connectState!=monitorStarted) throw std::runtime_error("EasyMonitor::poll illegal state");
if(poll()) return true;
userWait = true;
if(secondsToWait==0.0) {
waitForEvent.wait();
} else {
waitForEvent.wait(secondsToWait);
}
userWait = false;
return poll();
}
void EasyMonitor::releaseEvent()
{
if(isDestroyed) throw std::runtime_error("easyMonitor was destroyed");
if(connectState!=monitorStarted) throw std::runtime_error("EasyMonitor::poll illegal state");
if(!userPoll) throw std::runtime_error("EasyMonitor::releaseEvent did not call poll");
userPoll = false;
monitor->release(monitorElement);
}
EasyMonitorDataPtr EasyMonitor::getData()
{
checkMonitorState();
return easyData;
}
EasyMonitorPtr EasyMonitor::create(
EasyPVAPtr const &pva,
EasyChannelPtr const & easyChannel,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
EasyMonitorPtr epv(new EasyMonitor(pva,easyChannel,channel,pvRequest));
return epv;
}
}}

226
src/easyMonitorData.cpp Normal file
View File

@ -0,0 +1,226 @@
/* easyMonitorData.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2015.02
*/
#define epicsExportSharedSymbols
#include <typeinfo>
#include <sstream>
#include <pv/easyPVA.h>
#include <pv/createRequest.h>
#include <pv/convert.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace easyPVA {
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
static StructureConstPtr nullStructure;
static PVStructurePtr nullPVStructure;
static ConvertPtr convert = getConvert();
static string noStructure("no pvStructure ");
static string noValue("no value field");
static string noScalar("value is not a scalar");
static string notCompatibleScalar("value is not a compatible scalar");
static string noArray("value is not an array");
static string noScalarArray("value is not a scalarArray");
static string notDoubleArray("value is not a doubleArray");
static string notStringArray("value is not a stringArray");
EasyMonitorDataPtr EasyMonitorData::create(StructureConstPtr const & structure)
{
EasyMonitorDataPtr epv(new EasyMonitorData(structure));
return epv;
}
EasyMonitorData::EasyMonitorData(StructureConstPtr const & structure)
: structure(structure)
{}
void EasyMonitorData::checkValue()
{
if(pvValue) return;
throw std::runtime_error(messagePrefix + noValue);
}
void EasyMonitorData::setMessagePrefix(std::string const & value)
{
messagePrefix = value;
}
StructureConstPtr EasyMonitorData::getStructure()
{return structure;}
PVStructurePtr EasyMonitorData::getPVStructure()
{
if(pvStructure) return pvStructure;
throw std::runtime_error(messagePrefix + noStructure);
}
BitSetPtr EasyMonitorData::getChangedBitSet()
{
if(!changedBitSet) throw std::runtime_error(messagePrefix + noStructure);
return changedBitSet;
}
BitSetPtr EasyMonitorData::getOverrunBitSet()
{
if(!overrunBitSet) throw std::runtime_error(messagePrefix + noStructure);
return overrunBitSet;
}
std::ostream & EasyMonitorData::showChanged(std::ostream & out)
{
if(!changedBitSet) throw std::runtime_error(messagePrefix + noStructure);
size_t nextSet = changedBitSet->nextSetBit(0);
PVFieldPtr pvField;
while(nextSet!=string::npos) {
if(nextSet==0) {
pvField = pvStructure;
} else {
pvField = pvStructure->getSubField(nextSet);
}
string name = pvField->getFullName();
out << name << " = " << pvField << endl;
nextSet = changedBitSet->nextSetBit(nextSet+1);
}
return out;
}
std::ostream & EasyMonitorData::showOverrun(std::ostream & out)
{
if(!overrunBitSet) throw std::runtime_error(messagePrefix + noStructure);
size_t nextSet = overrunBitSet->nextSetBit(0);
PVFieldPtr pvField;
while(nextSet!=string::npos) {
if(nextSet==0) {
pvField = pvStructure;
} else {
pvField = pvStructure->getSubField(nextSet);
}
string name = pvField->getFullName();
out << name << " = " << pvField << endl;
nextSet = overrunBitSet->nextSetBit(nextSet+1);
}
return out;
}
void EasyMonitorData::setData(MonitorElementPtr const & monitorElement)
{
pvStructure = monitorElement->pvStructurePtr;
changedBitSet = monitorElement->changedBitSet;
overrunBitSet = monitorElement->overrunBitSet;
pvValue = pvStructure->getSubField("value");
}
bool EasyMonitorData::hasValue()
{
if(!pvValue) return false;
return true;
}
bool EasyMonitorData::isValueScalar()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalar) return true;
return false;
}
bool EasyMonitorData::isValueScalarArray()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalarArray) return true;
return false;
}
PVFieldPtr EasyMonitorData::getValue()
{
checkValue();
return pvValue;
}
PVScalarPtr EasyMonitorData::getScalarValue()
{
checkValue();
PVScalarPtr pv = pvStructure->getSubField<PVScalar>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + noScalar);
}
return pv;
}
PVArrayPtr EasyMonitorData::getArrayValue()
{
checkValue();
PVArrayPtr pv = pvStructure->getSubField<PVArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + noArray);
}
return pv;
}
PVScalarArrayPtr EasyMonitorData::getScalarArrayValue()
{
checkValue();
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + noScalarArray);
}
return pv;
}
double EasyMonitorData::getDouble()
{
PVScalarPtr pvScalar = getScalarValue();
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
return pvDouble->get();
}
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::runtime_error(notCompatibleScalar);
}
return convert->toDouble(pvScalar);
}
string EasyMonitorData::getString()
{
PVScalarPtr pvScalar = getScalarValue();
return convert->toString(pvScalar);
}
shared_vector<const double> EasyMonitorData::getDoubleArray()
{
checkValue();
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notDoubleArray);
}
return pv->view();
}
shared_vector<const string> EasyMonitorData::getStringArray()
{
checkValue();
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notStringArray);
}
return pv->view();
}
}}

View File

@ -98,7 +98,6 @@ void EasyChannelCache::removeChannel(string const & channelName)
using namespace epics::easyPVA::easyPVAPvt;
EasyPVAPtr EasyPVA::create()
{
EasyPVAPtr xx(new EasyPVA());
@ -152,11 +151,6 @@ void EasyPVA::message(
cout << getMessageTypeName(messageType) << " " << message << endl;
}
EasyPVStructurePtr EasyPVA::createEasyPVStructure()
{
return EasyPVStructureFactory::createEasyPVStructure();
}
EasyChannelPtr EasyPVA::channel(
std::string const & channelName,
std::string const & providerName,
@ -172,12 +166,12 @@ EasyChannelPtr EasyPVA::channel(
EasyChannelPtr EasyPVA::createChannel(string const & channelName)
{
return EasyChannelFactory::createEasyChannel(getPtrSelf(),channelName);
return EasyChannel::create(getPtrSelf(),channelName);
}
EasyChannelPtr EasyPVA::createChannel(string const & channelName, string const & providerName)
{
return EasyChannelFactory::createEasyChannel(getPtrSelf(),channelName,providerName);
return EasyChannel::create(getPtrSelf(),channelName,providerName);
}
}}

File diff suppressed because it is too large Load Diff

View File

@ -1,597 +0,0 @@
/* easyPVStructure.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2015.02
*/
#define epicsExportSharedSymbols
#include <typeinfo>
#include <sstream>
#include <pv/easyPVA.h>
#include <pv/createRequest.h>
#include <pv/convert.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace easyPVA {
typedef std::tr1::shared_ptr<epics::pvData::PVArray> PVArrayPtr;
static StructureConstPtr nullStructure;
static PVStructurePtr nullPVStructure;
static ConvertPtr convert = getConvert();
static Status statusOK(Status::Ok);
static Status statusDestroyed(Status::STATUSTYPE_ERROR,"was destroyed");
static Status statusNoPVStructure(Status::STATUSTYPE_ERROR,"setPVStructure not called");
static Status statusNoValue(Status::STATUSTYPE_ERROR,"no value field");
static Status statusNoScalar(Status::STATUSTYPE_ERROR,"value is not a scalar");
static Status statusMismatchedScalar(Status::STATUSTYPE_ERROR,"value is not a compatible scalar");
static Status statusNoArray(Status::STATUSTYPE_ERROR,"value is not a array");
static Status statusNoScalarArray(Status::STATUSTYPE_ERROR,"value is not a scalarArray");
static Status statusMismatchedScalarArray(Status::STATUSTYPE_ERROR,"value is not a compatible scalarArray");
static Status statusNoAlarm(Status::STATUSTYPE_ERROR,"no alarm field");
static Status statusNoTimeStamp(Status::STATUSTYPE_ERROR,"no timeStamp field");
class epicsShareClass EasyPVStructureImpl :
public EasyPVStructure,
public std::tr1::enable_shared_from_this<EasyPVStructureImpl>
{
public:
EasyPVStructureImpl();
~EasyPVStructureImpl(){}
virtual void setMessagePrefix(std::string const & value);
virtual void setPVStructure(PVStructurePtr const & pvStructure);
virtual PVStructurePtr getPVStructure();
virtual Alarm getAlarm();
virtual TimeStamp getTimeStamp();
virtual bool hasValue();
virtual bool isValueScalar();
virtual bool isValueScalarArray() ;
virtual PVFieldPtr getValue();
virtual PVScalarPtr getScalarValue();
virtual std::tr1::shared_ptr<PVArray> getArrayValue();
virtual std::tr1::shared_ptr<PVScalarArray> getScalarArrayValue();
virtual bool getBoolean();
virtual int8 getByte();
virtual int16 getShort();
virtual int32 getInt();
virtual int64 getLong();
virtual uint8 getUByte();
virtual uint16 getUShort();
virtual uint32 getUInt();
virtual uint64 getULong();
virtual float getFloat();
virtual double getDouble();
virtual std::string getString();
virtual shared_vector<boolean> getBooleanArray();
virtual shared_vector<int8> getByteArray();
virtual shared_vector<int16> getShortArray();
virtual shared_vector<int32> getIntArray();
virtual shared_vector<int64> getLongArray();
virtual shared_vector<uint8> getUByteArray();
virtual shared_vector<uint16> getUShortArray();
virtual shared_vector<uint32> getUIntArray();
virtual shared_vector<uint64> getULongArray();
virtual shared_vector<float> getFloatArray();
virtual shared_vector<double> getDoubleArray();
virtual shared_vector<string> getStringArray();
EasyPVStructurePtr getPtrSelf()
{
return shared_from_this();
}
private:
void checkPVStructure();
void checkValue();
bool checkOverflow(ScalarType source,ScalarType dest);
PVScalarPtr checkScalar(ScalarType scalarType);
PVScalarArrayPtr checkScalarArray(ScalarType elementType);
string messagePrefix;
PVStructurePtr pvStructure;
PVFieldPtr pvValue;
PVAlarm pvAlarm;
Alarm alarm;
PVTimeStamp pvTimeStamp;
TimeStamp timeStamp;
};
EasyPVStructureImpl::EasyPVStructureImpl()
{}
EasyPVStructurePtr EasyPVStructureFactory::createEasyPVStructure()
{
EasyPVStructurePtr epv(new EasyPVStructureImpl());
return epv;
}
void EasyPVStructureImpl::checkPVStructure()
{
if(pvStructure) return;
throw std::runtime_error(messagePrefix + statusNoPVStructure.getMessage());
}
void EasyPVStructureImpl::checkValue()
{
if(pvValue) return;
throw std::runtime_error(messagePrefix + statusNoValue.getMessage());
}
bool EasyPVStructureImpl::checkOverflow(ScalarType source,ScalarType dest)
{
if(dest==pvFloat||dest==pvDouble) return true;
if(!ScalarTypeFunc::isInteger(source) && !ScalarTypeFunc::isUInteger(source)) return false;
if(ScalarTypeFunc::isUInteger(dest)) {
if(ScalarTypeFunc::isUInteger(source)) {
if(dest>=source) return true;
return false;
}
if(ScalarTypeFunc::isInteger(source)) {
if(dest>=(source+4)) return true;
return false;
}
return false;
}
if(ScalarTypeFunc::isInteger(dest)) {
if(ScalarTypeFunc::isUInteger(source)) {
if(dest>(source-4)) return true;
return false;
}
if(ScalarTypeFunc::isInteger(source)) {
if(dest>=source) return true;
return false;
}
return false;
}
return false;
}
PVScalarPtr EasyPVStructureImpl::checkScalar(ScalarType scalarType)
{
checkPVStructure();
checkValue();
PVScalarPtr pv = pvStructure->getSubField<PVScalar>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + statusNoScalar.getMessage());
}
ScalarType type = pv->getScalar()->getScalarType();
if((scalarType==pvBoolean && type==pvBoolean)
|| (scalarType==pvString && type==pvString)) return pv;
if((ScalarTypeFunc::isNumeric(type) && ScalarTypeFunc::isNumeric(scalarType))
&& checkOverflow(type,scalarType)) return pv;
stringstream ss;
ss << messagePrefix << statusMismatchedScalar.getMessage();
ss << " source " << type << " dest " << scalarType;
throw std::runtime_error(ss.str());
}
PVScalarArrayPtr EasyPVStructureImpl::checkScalarArray(ScalarType elementType)
{
checkPVStructure();
checkValue();
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + statusNoScalarArray.getMessage());
}
ScalarType type = pv->getScalarArray()->getElementType();
if((elementType==pvBoolean && type==pvBoolean)
|| (elementType==pvBoolean && type==pvBoolean)) return pv;
if((ScalarTypeFunc::isNumeric(type) && ScalarTypeFunc::isNumeric(elementType))
&& checkOverflow(type,elementType)) return pv;
throw std::runtime_error(messagePrefix + statusMismatchedScalarArray.getMessage());
}
void EasyPVStructureImpl::setMessagePrefix(string const & value)
{
messagePrefix = value;
if(value.size()>0) messagePrefix += " ";
}
void EasyPVStructureImpl::setPVStructure(PVStructurePtr const & pvStructure)
{
this->pvStructure = pvStructure;
pvValue = pvStructure->getSubField("value");
}
PVStructurePtr EasyPVStructureImpl::getPVStructure()
{
checkPVStructure();
return pvStructure;
}
PVFieldPtr EasyPVStructureImpl::getValue()
{
checkValue();
return pvValue;
}
PVScalarPtr EasyPVStructureImpl::getScalarValue()
{
checkValue();
PVScalarPtr pv = pvStructure->getSubField<PVScalar>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + statusNoScalar.getMessage());
}
return pv;
}
PVArrayPtr EasyPVStructureImpl::getArrayValue()
{
checkValue();
PVArrayPtr pv = pvStructure->getSubField<PVArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + statusNoArray.getMessage());
}
return pv;
}
PVScalarArrayPtr EasyPVStructureImpl::getScalarArrayValue()
{
checkValue();
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + statusNoScalarArray.getMessage());
}
return pv;
}
Alarm EasyPVStructureImpl::getAlarm()
{
Alarm alarm;
alarm.setSeverity(undefinedAlarm);
alarm.setStatus(undefinedStatus);
alarm.setMessage("no alarm field");
if(!pvStructure) return alarm;
PVStructurePtr xxx = pvStructure->getSubField<PVStructure>("alarm");
if(xxx) {
pvAlarm.attach(xxx);
if(pvAlarm.isAttached()) {
pvAlarm.get(alarm);
pvAlarm.detach();
}
}
return alarm;;
}
TimeStamp EasyPVStructureImpl::getTimeStamp()
{
TimeStamp timeStamp;
if(!pvStructure) return timeStamp;
PVStructurePtr xxx = pvStructure->getSubField<PVStructure>("timeStamp");
if(xxx) {
pvTimeStamp.attach(xxx);
if(pvTimeStamp.isAttached()) {
pvTimeStamp.get(timeStamp);
pvTimeStamp.detach();
}
}
return timeStamp;;
}
bool EasyPVStructureImpl::hasValue()
{
if(!pvValue) return false;
return true;
}
bool EasyPVStructureImpl::isValueScalar()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalar) return true;
return false;
}
bool EasyPVStructureImpl::isValueScalarArray()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalarArray) return true;
return false;
}
bool EasyPVStructureImpl::getBoolean()
{
PVScalarPtr pvScalar = checkScalar(pvBoolean);
PVBooleanPtr pv = static_pointer_cast<PVBoolean>(pvScalar);
return pv->get();
}
int8 EasyPVStructureImpl::getByte()
{
PVScalarPtr pvScalar = checkScalar(pvByte);
return convert->toByte(pvScalar);
}
uint8 EasyPVStructureImpl::getUByte()
{
PVScalarPtr pvScalar = checkScalar(pvUByte);
return convert->toUByte(pvScalar);
}
int16 EasyPVStructureImpl::getShort()
{
PVScalarPtr pvScalar = checkScalar(pvShort);
return convert->toShort(pvScalar);
}
uint16 EasyPVStructureImpl::getUShort()
{
PVScalarPtr pvScalar = checkScalar(pvUShort);
return convert->toUShort(pvScalar);
}
int32 EasyPVStructureImpl::getInt()
{
PVScalarPtr pvScalar = checkScalar(pvInt);
return convert->toInt(pvScalar);
}
uint32 EasyPVStructureImpl::getUInt()
{
PVScalarPtr pvScalar = checkScalar(pvUInt);
return convert->toUInt(pvScalar);
}
int64 EasyPVStructureImpl::getLong()
{
PVScalarPtr pvScalar = checkScalar(pvLong);
return convert->toLong(pvScalar);
}
uint64 EasyPVStructureImpl::getULong()
{
PVScalarPtr pvScalar = checkScalar(pvULong);
return convert->toULong(pvScalar);
}
float EasyPVStructureImpl::getFloat()
{
PVScalarPtr pvScalar = checkScalar(pvFloat);
return convert->toFloat(pvScalar);
}
double EasyPVStructureImpl::getDouble()
{
PVScalarPtr pvScalar = checkScalar(pvDouble);
return convert->toDouble(pvScalar);
}
string EasyPVStructureImpl::getString()
{
PVScalarPtr pvScalar = checkScalar(pvString);
PVStringPtr pv = static_pointer_cast<PVString>(pvScalar);
return pv->get();
}
shared_vector<boolean> EasyPVStructureImpl::getBooleanArray()
{
checkScalarArray(pvBoolean);
PVBooleanArrayPtr pv = static_pointer_cast<PVBooleanArray>(pvValue);
return pv->reuse();
}
template <typename T>
shared_vector<T> copy(PVScalarArrayPtr const & pvScalarArray)
{
ScalarType elementType = pvScalarArray->getScalarArray()->getElementType();
switch(elementType) {
case pvBoolean :
break;
case pvByte :
{
PVByteArrayPtr pv = static_pointer_cast<PVByteArray>(pvScalarArray);
shared_vector<int8> data = pv->reuse();
shared_vector<T> to = shared_vector_convert<T,int8>(data);
return to;
}
case pvShort :
{
PVShortArrayPtr pv = static_pointer_cast<PVShortArray>(pvScalarArray);
shared_vector<int16> data = pv->reuse();
shared_vector<T> to = shared_vector_convert<T,int16>(data);
return to;
}
case pvInt :
{
PVIntArrayPtr pv = static_pointer_cast<PVIntArray>(pvScalarArray);
shared_vector<int32> data = pv->reuse();
shared_vector<T> to = shared_vector_convert<T,int32>(data);
return to;
}
case pvLong :
{
PVLongArrayPtr pv = static_pointer_cast<PVLongArray>(pvScalarArray);
shared_vector<int64> data = pv->reuse();
shared_vector<T> to = shared_vector_convert<T,int64>(data);
return to;
}
case pvUByte :
{
PVUByteArrayPtr pv = static_pointer_cast<PVUByteArray>(pvScalarArray);
shared_vector<uint8> data = pv->reuse();
shared_vector<T> to = shared_vector_convert<T,uint8>(data);
return to;
}
case pvUShort :
{
PVUShortArrayPtr pv = static_pointer_cast<PVUShortArray>(pvScalarArray);
shared_vector<uint16> data = pv->reuse();
shared_vector<T> to = shared_vector_convert<T,uint16>(data);
return to;
}
case pvUInt :
{
PVUIntArrayPtr pv = static_pointer_cast<PVUIntArray>(pvScalarArray);
shared_vector<uint32> data = pv->reuse();
shared_vector<T> to = shared_vector_convert<T,uint32>(data);
return to;
}
case pvULong :
{
PVULongArrayPtr pv = static_pointer_cast<PVULongArray>(pvScalarArray);
shared_vector<uint64> data = pv->reuse();
shared_vector<T> to = shared_vector_convert<T,uint64>(data);
return to;
}
case pvFloat :
{
PVFloatArrayPtr pv = static_pointer_cast<PVFloatArray>(pvScalarArray);
shared_vector<float> data = pv->reuse();
shared_vector<T> to = shared_vector_convert<T,float>(data);
return to;
}
case pvDouble :
{
PVDoubleArrayPtr pv = static_pointer_cast<PVDoubleArray>(pvScalarArray);
shared_vector<double> data = pv->reuse();
shared_vector<T> to = shared_vector_convert<T,double>(data);
return to;
}
case pvString :
break;
}
return shared_vector<T>();
}
shared_vector<int8> EasyPVStructureImpl::getByteArray()
{
PVScalarArrayPtr pvScalarArray = checkScalarArray(pvByte);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(scalarType==pvByte) {
PVByteArrayPtr pv = static_pointer_cast<PVByteArray>(pvValue);
return pv->reuse();
}
shared_vector<int8> xx = copy<int8>(pvScalarArray);
return xx;
}
shared_vector<int16> EasyPVStructureImpl::getShortArray()
{
PVScalarArrayPtr pvScalarArray = checkScalarArray(pvShort);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(scalarType==pvShort) {
PVShortArrayPtr pv = static_pointer_cast<PVShortArray>(pvValue);
return pv->reuse();
}
shared_vector<int16> xx = copy<int16>(pvScalarArray);
return xx;
}
shared_vector<int32> EasyPVStructureImpl::getIntArray()
{
PVScalarArrayPtr pvScalarArray = checkScalarArray(pvInt);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(scalarType==pvInt) {
PVIntArrayPtr pv = static_pointer_cast<PVIntArray>(pvValue);
return pv->reuse();
}
shared_vector<int32> xx = copy<int32>(pvScalarArray);
return xx;
}
shared_vector<int64> EasyPVStructureImpl::getLongArray()
{
PVScalarArrayPtr pvScalarArray = checkScalarArray(pvLong);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(scalarType==pvLong) {
PVLongArrayPtr pv = static_pointer_cast<PVLongArray>(pvValue);
return pv->reuse();
}
shared_vector<int64> xx = copy<int64>(pvScalarArray);
return xx;
}
shared_vector<uint8> EasyPVStructureImpl::getUByteArray()
{
PVScalarArrayPtr pvScalarArray = checkScalarArray(pvUByte);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(scalarType==pvUByte) {
PVUByteArrayPtr pv = static_pointer_cast<PVUByteArray>(pvValue);
return pv->reuse();
}
shared_vector<uint8> xx = copy<uint8>(pvScalarArray);
return xx;
}
shared_vector<uint16> EasyPVStructureImpl::getUShortArray()
{
PVScalarArrayPtr pvScalarArray = checkScalarArray(pvUShort);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(scalarType==pvUShort) {
PVUShortArrayPtr pv = static_pointer_cast<PVUShortArray>(pvValue);
return pv->reuse();
}
shared_vector<uint16> xx = copy<uint16>(pvScalarArray);
return xx;
}
shared_vector<uint32> EasyPVStructureImpl::getUIntArray()
{
PVScalarArrayPtr pvScalarArray = checkScalarArray(pvUInt);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(scalarType==pvUInt) {
PVUIntArrayPtr pv = static_pointer_cast<PVUIntArray>(pvValue);
return pv->reuse();
}
shared_vector<uint32> xx = copy<uint32>(pvScalarArray);
return xx;
}
shared_vector<uint64> EasyPVStructureImpl::getULongArray()
{
PVScalarArrayPtr pvScalarArray = checkScalarArray(pvULong);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(scalarType==pvULong) {
PVULongArrayPtr pv = static_pointer_cast<PVULongArray>(pvValue);
return pv->reuse();
}
shared_vector<uint64> xx = copy<uint64>(pvScalarArray);
return xx;
}
shared_vector<float> EasyPVStructureImpl::getFloatArray()
{
checkScalarArray(pvFloat);
PVFloatArrayPtr pv = static_pointer_cast<PVFloatArray>(pvValue);
return pv->reuse();
PVScalarArrayPtr pvScalarArray = checkScalarArray(pvFloat);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(scalarType==pvFloat) {
PVFloatArrayPtr pv = static_pointer_cast<PVFloatArray>(pvValue);
return pv->reuse();
}
shared_vector<float> xx = copy<float>(pvScalarArray);
return xx;
}
shared_vector<double> EasyPVStructureImpl::getDoubleArray()
{
PVScalarArrayPtr pvScalarArray = checkScalarArray(pvDouble);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(scalarType==pvDouble) {
PVDoubleArrayPtr pv = static_pointer_cast<PVDoubleArray>(pvValue);
return pv->reuse();
}
shared_vector<double> xx = copy<double>(pvScalarArray);
return xx;
}
shared_vector<string> EasyPVStructureImpl::getStringArray()
{
checkScalarArray(pvString);
PVStringArrayPtr pv = static_pointer_cast<PVStringArray>(pvValue);
return pv->reuse();
}
}}

212
src/easyProcess.cpp Normal file
View File

@ -0,0 +1,212 @@
/* easyProcess.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2015.02
*/
#define epicsExportSharedSymbols
#include <sstream>
#include <pv/event.h>
#include <pv/easyPVA.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace easyPVA {
class ChannelProcessRequesterImpl : public ChannelProcessRequester
{
EasyProcess * easyProcess;
public:
ChannelProcessRequesterImpl(EasyProcess * easyProcess)
: easyProcess(easyProcess) {}
string getRequesterName()
{return easyProcess->getRequesterName();}
void message(string const & message,MessageType messageType)
{easyProcess->message(message,messageType);}
void channelProcessConnect(
const Status& status,
ChannelProcess::shared_pointer const & channelProcess)
{easyProcess->channelProcessConnect(status,channelProcess);}
void processDone(
const Status& status,
ChannelProcess::shared_pointer const & channelProcess)
{easyProcess->processDone(status,channelProcess);}
};
EasyProcess::EasyProcess(
EasyPVAPtr const &pva,
EasyChannelPtr const & easyChannel,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
: easyPVA(pva),
easyChannel(easyChannel),
channel(channel),
pvRequest(pvRequest),
isDestroyed(false),
connectState(connectIdle),
processState(processIdle)
{
}
EasyProcess::~EasyProcess()
{
destroy();
}
void EasyProcess::checkProcessState()
{
if(isDestroyed) throw std::runtime_error("easyProcess was destroyed");
if(connectState==connectIdle) connect();
if(processState==processIdle) process();
}
// from ChannelProcessRequester
string EasyProcess::getRequesterName()
{
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("easyPVA was destroyed");
return yyy->getRequesterName();
}
void EasyProcess::message(string const & message,MessageType messageType)
{
if(isDestroyed) throw std::runtime_error("easyProcess was destroyed");
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("easyPVA was destroyed");
yyy->message(message, messageType);
}
void EasyProcess::channelProcessConnect(
const Status& status,
ChannelProcess::shared_pointer const & channelProcess)
{
if(isDestroyed) throw std::runtime_error("easyProcess was destroyed");
channelProcessConnectStatus = status;
this->channelProcess = channelProcess;
waitForConnect.signal();
}
void EasyProcess::processDone(
const Status& status,
ChannelProcess::shared_pointer const & channelProcess)
{
if(isDestroyed) throw std::runtime_error("easyProcess was destroyed");
channelProcessStatus = status;
waitForProcess.signal();
}
// from EasyProcess
void EasyProcess::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
if(channelProcess) channelProcess->destroy();
channelProcess.reset();
}
void EasyProcess::connect()
{
if(isDestroyed) throw std::runtime_error("easyProcess was destroyed");
issueConnect();
Status status = waitConnect();
if(status.isOK()) return;
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyProcess::connect " << status.getMessage();
throw std::runtime_error(ss.str());
}
void EasyProcess::issueConnect()
{
if(isDestroyed) throw std::runtime_error("easyProcess was destroyed");
if(connectState!=connectIdle) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " easyProcess already connected ";
throw std::runtime_error(ss.str());
}
processRequester = ChannelProcessRequester::shared_pointer(new ChannelProcessRequesterImpl(this));
connectState = connectActive;
channelProcess = channel->createChannelProcess(processRequester,pvRequest);
}
Status EasyProcess::waitConnect()
{
if(isDestroyed) throw std::runtime_error("easyProcess was destroyed");
if(connectState!=connectActive) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " easyProcess illegal connect state ";
throw std::runtime_error(ss.str());
}
waitForConnect.wait();
if(channelProcessConnectStatus.isOK()){
connectState = connected;
return Status::Ok;
}
connectState = connectIdle;
return Status(Status::STATUSTYPE_ERROR,channelProcessConnectStatus.getMessage());
}
void EasyProcess::process()
{
if(isDestroyed) throw std::runtime_error("easyProcess was destroyed");
issueProcess();
Status status = waitProcess();
if(status.isOK()) return;
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyProcess::process " << status.getMessage();
throw std::runtime_error(ss.str());
}
void EasyProcess::issueProcess()
{
if(isDestroyed) throw std::runtime_error("easyProcess was destroyed");
if(connectState==connectIdle) connect();
if(processState!=processIdle) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyProcess::issueProcess process aleady active ";
throw std::runtime_error(ss.str());
}
processState = processActive;
channelProcess->process();
}
Status EasyProcess::waitProcess()
{
if(isDestroyed) throw std::runtime_error("easyProcess was destroyed");
if(processState!=processActive){
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyProcess::waitProcess llegal process state";
throw std::runtime_error(ss.str());
}
waitForProcess.wait();
processState = processIdle;
if(channelProcessStatus.isOK()) {
return Status::Ok;
}
return Status(Status::STATUSTYPE_ERROR,channelProcessStatus.getMessage());
}
EasyProcessPtr EasyProcess::create(
EasyPVAPtr const &pva,
EasyChannelPtr const & easyChannel,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
EasyProcessPtr epv(new EasyProcess(pva,easyChannel,channel,pvRequest));
return epv;
}
}}

292
src/easyPut.cpp Normal file
View File

@ -0,0 +1,292 @@
/* easyPut.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2015.02
*/
#define epicsExportSharedSymbols
#include <sstream>
#include <pv/event.h>
#include <pv/easyPVA.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace easyPVA {
class ChannelPutRequesterImpl : public ChannelPutRequester
{
EasyPut * easyPut;
public:
ChannelPutRequesterImpl(EasyPut * easyPut)
: easyPut(easyPut) {}
string getRequesterName()
{return easyPut->getRequesterName();}
void message(string const & message,MessageType messageType)
{easyPut->message(message,messageType);}
void channelPutConnect(
const Status& status,
ChannelPut::shared_pointer const & channelPut,
StructureConstPtr const & structure)
{easyPut->channelPutConnect(status,channelPut,structure);}
void getDone(
const Status& status,
ChannelPut::shared_pointer const & channelPut,
PVStructurePtr const & pvStructure,
BitSetPtr const & bitSet)
{easyPut->getDone(status,channelPut,pvStructure,bitSet);}
void putDone(
const Status& status,
ChannelPut::shared_pointer const & channelPut)
{easyPut->putDone(status,channelPut);}
};
EasyPut::EasyPut(
EasyPVAPtr const &pva,
EasyChannelPtr const & easyChannel,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
: easyPVA(pva),
easyChannel(easyChannel),
channel(channel),
pvRequest(pvRequest),
isDestroyed(false),
connectState(connectIdle),
putState(putIdle)
{
}
EasyPut::~EasyPut()
{
destroy();
}
void EasyPut::checkPutState()
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
if(connectState==connectIdle){
connect();
get();
}
}
// from ChannelPutRequester
string EasyPut::getRequesterName()
{
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("easyPVA was destroyed");
return yyy->getRequesterName();
}
void EasyPut::message(string const & message,MessageType messageType)
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("easyPVA was destroyed");
yyy->message(message, messageType);
}
void EasyPut::channelPutConnect(
const Status& status,
ChannelPut::shared_pointer const & channelPut,
StructureConstPtr const & structure)
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
channelPutConnectStatus = status;
this->channelPut = channelPut;
if(status.isOK()) {
easyData = EasyPutData::create(structure);
easyData->setMessagePrefix(easyChannel.lock()->getChannelName());
}
waitForConnect.signal();
}
void EasyPut::getDone(
const Status& status,
ChannelPut::shared_pointer const & channelPut,
PVStructurePtr const & pvStructure,
BitSetPtr const & bitSet)
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
channelGetPutStatus = status;
if(status.isOK()) {
PVStructurePtr pvs = easyData->getPVStructure();
pvs->copyUnchecked(*pvStructure,*bitSet);
BitSetPtr bs = easyData->getBitSet();
bs->clear();
*bs |= *bitSet;
}
waitForGetPut.signal();
}
void EasyPut::putDone(
const Status& status,
ChannelPut::shared_pointer const & channelPut)
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
channelGetPutStatus = status;
waitForGetPut.signal();
}
// from EasyPut
void EasyPut::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
if(channelPut) channelPut->destroy();
channelPut.reset();
}
void EasyPut::connect()
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
issueConnect();
Status status = waitConnect();
if(status.isOK()) return;
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPut::connect " << status.getMessage();
throw std::runtime_error(ss.str());
}
void EasyPut::issueConnect()
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
if(connectState!=connectIdle) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " easyPut already connected ";
throw std::runtime_error(ss.str());
}
putRequester = ChannelPutRequester::shared_pointer(new ChannelPutRequesterImpl(this));
connectState = connectActive;
channelPut = channel->createChannelPut(putRequester,pvRequest);
}
Status EasyPut::waitConnect()
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
if(connectState!=connectActive) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " easyPut illegal connect state ";
throw std::runtime_error(ss.str());
}
waitForConnect.wait();
if(channelPutConnectStatus.isOK()) {
connectState = connected;
return Status::Ok;
}
connectState = connectIdle;
return Status(Status::STATUSTYPE_ERROR,channelPutConnectStatus.getMessage());
}
void EasyPut::get()
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
issueGet();
Status status = waitGet();
if(status.isOK()) return;
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPut::get " << status.getMessage();
throw std::runtime_error(ss.str());
}
void EasyPut::issueGet()
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
if(connectState==connectIdle) connect();
if(putState!=putIdle) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPut::issueGet get or put aleady active ";
throw std::runtime_error(ss.str());
}
putState = getActive;
easyData->getBitSet()->clear();
channelPut->get();
}
Status EasyPut::waitGet()
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
if(putState!=getActive){
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPut::waitGet llegal put state";
throw std::runtime_error(ss.str());
}
waitForGetPut.wait();
putState = putIdle;
if(channelGetPutStatus.isOK()) {
return Status::Ok;
}
return Status(Status::STATUSTYPE_ERROR,channelGetPutStatus.getMessage());
}
void EasyPut::put()
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
issuePut();
Status status = waitPut();
if(status.isOK()) return;
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPut::put " << status.getMessage();
throw std::runtime_error(ss.str());
}
void EasyPut::issuePut()
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
if(connectState==connectIdle) connect();
if(putState!=putIdle) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPut::issueGet get or put aleady active ";
throw std::runtime_error(ss.str());
}
putState = putActive;
channelPut->put(easyData->getPVStructure(),easyData->getBitSet());
}
Status EasyPut::waitPut()
{
if(isDestroyed) throw std::runtime_error("easyPut was destroyed");
if(putState!=putActive){
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPut::waitPut llegal put state";
throw std::runtime_error(ss.str());
}
waitForGetPut.wait();
putState = putIdle;
if(channelGetPutStatus.isOK()) {
easyData->getBitSet()->clear();
return Status::Ok;
}
return Status(Status::STATUSTYPE_ERROR,channelGetPutStatus.getMessage());
}
EasyPutDataPtr EasyPut::getData()
{
checkPutState();
return easyData;
}
EasyPutPtr EasyPut::create(
EasyPVAPtr const &pva,
EasyChannelPtr const & easyChannel,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
EasyPutPtr epv(new EasyPut(pva,easyChannel,channel,pvRequest));
return epv;
}
}}

257
src/easyPutData.cpp Normal file
View File

@ -0,0 +1,257 @@
/* easyPutData.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2015.02
*/
#define epicsExportSharedSymbols
#include <typeinfo>
#include <sstream>
#include <pv/easyPVA.h>
#include <pv/createRequest.h>
#include <pv/convert.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace easyPVA {
class EasyPostHandlerPvt: public PostHandler
{
EasyPutData * easyData;
size_t fieldNumber;
public:
EasyPostHandlerPvt(EasyPutData *easyData,size_t fieldNumber)
: easyData(easyData),fieldNumber(fieldNumber){}
void postPut() { easyData->postPut(fieldNumber);}
};
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
static ConvertPtr convert = getConvert();
static string noValue("no value field");
static string noScalar("value is not a scalar");
static string notCompatibleScalar("value is not a compatible scalar");
static string noArray("value is not an array");
static string noScalarArray("value is not a scalarArray");
static string notDoubleArray("value is not a doubleArray");
static string notStringArray("value is not a stringArray");
EasyPutDataPtr EasyPutData::create(StructureConstPtr const & structure)
{
EasyPutDataPtr epv(new EasyPutData(structure));
return epv;
}
EasyPutData::EasyPutData(StructureConstPtr const & structure)
: structure(structure),
pvStructure(getPVDataCreate()->createPVStructure(structure)),
bitSet(BitSetPtr(new BitSet(pvStructure->getNumberFields())))
{
size_t nfields = pvStructure->getNumberFields();
postHandler.resize(nfields);
PVFieldPtr pvField;
for(size_t i =0; i<nfields; ++i)
{
postHandler[i] = PostHandlerPtr(new EasyPostHandlerPvt(this, i));
if(i==0) {
pvField = pvStructure;
} else {
pvField = pvStructure->getSubField(i);
}
pvField->setPostHandler(postHandler[i]);
}
pvValue = pvStructure->getSubField("value");
}
void EasyPutData::checkValue()
{
if(pvValue) return;
throw std::runtime_error(messagePrefix + noValue);
}
void EasyPutData::postPut(size_t fieldNumber)
{
bitSet->set(fieldNumber);
}
void EasyPutData::setMessagePrefix(std::string const & value)
{
messagePrefix = value;
}
StructureConstPtr EasyPutData::getStructure()
{return structure;}
PVStructurePtr EasyPutData::getPVStructure()
{return pvStructure;}
BitSetPtr EasyPutData::getBitSet()
{return bitSet;}
std::ostream & EasyPutData::showChanged(std::ostream & out)
{
size_t nextSet = bitSet->nextSetBit(0);
PVFieldPtr pvField;
while(nextSet!=string::npos) {
if(nextSet==0) {
pvField = pvStructure;
} else {
pvField = pvStructure->getSubField(nextSet);
}
string name = pvField->getFullName();
out << name << " = " << pvField << endl;
nextSet = bitSet->nextSetBit(nextSet+1);
}
return out;
}
bool EasyPutData::hasValue()
{
if(!pvValue) return false;
return true;
}
bool EasyPutData::isValueScalar()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalar) return true;
return false;
}
bool EasyPutData::isValueScalarArray()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalarArray) return true;
return false;
}
PVFieldPtr EasyPutData::getValue()
{
checkValue();
return pvValue;
}
PVScalarPtr EasyPutData::getScalarValue()
{
checkValue();
PVScalarPtr pv = pvStructure->getSubField<PVScalar>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + noScalar);
}
return pv;
}
PVArrayPtr EasyPutData::getArrayValue()
{
checkValue();
PVArrayPtr pv = pvStructure->getSubField<PVArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + noArray);
}
return pv;
}
PVScalarArrayPtr EasyPutData::getScalarArrayValue()
{
checkValue();
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + noScalarArray);
}
return pv;
}
double EasyPutData::getDouble()
{
PVScalarPtr pvScalar = getScalarValue();
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
return pvDouble->get();
}
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::runtime_error(notCompatibleScalar);
}
return convert->toDouble(pvScalar);
}
string EasyPutData::getString()
{
PVScalarPtr pvScalar = getScalarValue();
return convert->toString(pvScalar);
}
shared_vector<const double> EasyPutData::getDoubleArray()
{
checkValue();
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notDoubleArray);
}
return pv->view();
}
shared_vector<const string> EasyPutData::getStringArray()
{
checkValue();
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notStringArray);
}
return pv->view();
}
void EasyPutData::putDouble(double value)
{
PVScalarPtr pvScalar = getScalarValue();
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
pvDouble->put(value);
}
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::runtime_error(notCompatibleScalar);
}
convert->fromDouble(pvScalar,value);
}
void EasyPutData::putString(std::string const & value)
{
PVScalarPtr pvScalar = getScalarValue();
convert->fromString(pvScalar,value);
}
void EasyPutData::putDoubleArray(shared_vector<const double> const & value)
{
checkValue();
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notDoubleArray);
}
pv->replace(value);
}
void EasyPutData::putStringArray(shared_vector<const std::string> const & value)
{
checkValue();
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notStringArray);
}
pv->replace(value);
}
}}

378
src/easyPutGet.cpp Normal file
View File

@ -0,0 +1,378 @@
/* easyPutGet.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2015.02
*/
#define epicsExportSharedSymbols
#include <sstream>
#include <pv/event.h>
#include <pv/easyPVA.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace easyPVA {
class ChannelPutGetRequesterImpl : public ChannelPutGetRequester
{
EasyPutGet * easyPutGet;
public:
ChannelPutGetRequesterImpl(EasyPutGet * easyPutGet)
: easyPutGet(easyPutGet) {}
string getRequesterName()
{return easyPutGet->getRequesterName();}
void message(string const & message,MessageType messageType)
{easyPutGet->message(message,messageType);}
void channelPutGetConnect(
const epics::pvData::Status& status,
epics::pvAccess::ChannelPutGet::shared_pointer const & channelPutGet,
epics::pvData::StructureConstPtr const & putStructure,
epics::pvData::StructureConstPtr const & getStructure)
{
easyPutGet->channelPutGetConnect(status,channelPutGet,putStructure,getStructure);
}
void putGetDone(
const epics::pvData::Status& status,
epics::pvAccess::ChannelPutGet::shared_pointer const & channelPutGet,
epics::pvData::PVStructurePtr const & getPVStructure,
epics::pvData::BitSetPtr const & getBitSet)
{
easyPutGet->putGetDone(status,channelPutGet,getPVStructure,getBitSet);
}
void getPutDone(
const epics::pvData::Status& status,
epics::pvAccess::ChannelPutGet::shared_pointer const & channelPutGet,
epics::pvData::PVStructurePtr const & putPVStructure,
epics::pvData::BitSet::shared_pointer const & putBitSet)
{
easyPutGet->getPutDone(status,channelPutGet,putPVStructure,putBitSet);
}
void getGetDone(
const epics::pvData::Status& status,
epics::pvAccess::ChannelPutGet::shared_pointer const & channelPutGet,
epics::pvData::PVStructurePtr const & getPVStructure,
epics::pvData::BitSet::shared_pointer const & getBitSet)
{
easyPutGet->getGetDone(status,channelPutGet,getPVStructure,getBitSet);
}
};
EasyPutGet::EasyPutGet(
EasyPVAPtr const &pva,
EasyChannelPtr const & easyChannel,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
: easyPVA(pva),
easyChannel(easyChannel),
channel(channel),
pvRequest(pvRequest),
isDestroyed(false),
connectState(connectIdle),
putGetState(putGetIdle)
{
}
EasyPutGet::~EasyPutGet()
{
destroy();
}
void EasyPutGet::checkPutGetState()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
if(connectState==connectIdle){
connect();
getPut();
}
}
// from ChannelPutGetRequester
string EasyPutGet::getRequesterName()
{
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("easyPVA was destroyed");
return yyy->getRequesterName();
}
void EasyPutGet::message(string const & message,MessageType messageType)
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("easyPVA was destroyed");
yyy->message(message, messageType);
}
void EasyPutGet::channelPutGetConnect(
const Status& status,
ChannelPutGet::shared_pointer const & channelPutGet,
StructureConstPtr const & putStructure,
StructureConstPtr const & getStructure)
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
channelPutGetConnectStatus = status;
this->channelPutGet = channelPutGet;
if(status.isOK()) {
easyPutData = EasyPutData::create(putStructure);
easyPutData->setMessagePrefix(easyChannel.lock()->getChannelName());
easyGetData = EasyGetData::create(getStructure);
easyGetData->setMessagePrefix(easyChannel.lock()->getChannelName());
}
waitForConnect.signal();
}
void EasyPutGet::putGetDone(
const Status& status,
ChannelPutGet::shared_pointer const & channelPutGet,
PVStructurePtr const & getPVStructure,
BitSetPtr const & getBitSet)
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
channelPutGetStatus = status;
if(status.isOK()) {
easyGetData->setData(getPVStructure,getBitSet);
}
waitForPutGet.signal();
}
void EasyPutGet::getPutDone(
const Status& status,
ChannelPutGet::shared_pointer const & channelPutGet,
PVStructurePtr const & putPVStructure,
BitSetPtr const & putBitSet)
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
channelGetPutGetStatus = status;
if(status.isOK()) {
PVStructurePtr pvs = easyPutData->getPVStructure();
pvs->copyUnchecked(*putPVStructure,*putBitSet);
BitSetPtr bs = easyPutData->getBitSet();
bs->clear();
*bs |= *putBitSet;
}
waitForPutGet.signal();
}
void EasyPutGet::getGetDone(
const Status& status,
ChannelPutGet::shared_pointer const & channelPutGet,
PVStructurePtr const & getPVStructure,
BitSetPtr const & getBitSet)
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
channelPutGetStatus = status;
if(status.isOK()) {
easyGetData->setData(getPVStructure,getBitSet);
}
waitForPutGet.signal();
}
// from EasyPutGet
void EasyPutGet::destroy()
{
{
Lock xx(mutex);
if(isDestroyed) return;
isDestroyed = true;
}
if(channelPutGet) channelPutGet->destroy();
channelPutGet.reset();
}
void EasyPutGet::connect()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
issueConnect();
Status status = waitConnect();
if(status.isOK()) return;
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPutGet::connect " << status.getMessage();
throw std::runtime_error(ss.str());
}
void EasyPutGet::issueConnect()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
if(connectState!=connectIdle) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " easyPutGet already connected ";
throw std::runtime_error(ss.str());
}
putGetRequester = ChannelPutGetRequester::shared_pointer(new ChannelPutGetRequesterImpl(this));
connectState = connectActive;
channelPutGet = channel->createChannelPutGet(putGetRequester,pvRequest);
}
Status EasyPutGet::waitConnect()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
if(connectState!=connectActive) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " easyPutGet illegal connect state ";
throw std::runtime_error(ss.str());
}
waitForConnect.wait();
if(channelPutGetConnectStatus.isOK()) {
connectState = connected;
return Status::Ok;
}
connectState = connectIdle;
return Status(Status::STATUSTYPE_ERROR,channelPutGetConnectStatus.getMessage());
}
void EasyPutGet::putGet()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
issuePutGet();
Status status = waitPutGet();
if(status.isOK()) return;
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPutGet::putGet " << status.getMessage();
throw std::runtime_error(ss.str());
}
void EasyPutGet::issuePutGet()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
if(connectState==connectIdle) connect();
if(putGetState!=putGetIdle) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPutGet::issueGet get or put aleady active ";
throw std::runtime_error(ss.str());
}
putGetState = putGetActive;
channelPutGet->putGet(easyPutData->getPVStructure(),easyPutData->getBitSet());
}
Status EasyPutGet::waitPutGet()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
if(putGetState!=putGetActive){
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPutGet::waitPutGet llegal put state";
throw std::runtime_error(ss.str());
}
waitForPutGet.wait();
putGetState = putGetIdle;
if(channelGetPutGetStatus.isOK()) {
return Status::Ok;
}
return Status(Status::STATUSTYPE_ERROR,channelGetPutGetStatus.getMessage());
}
void EasyPutGet::getGet()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
issueGetGet();
Status status = waitGetGet();
if(status.isOK()) return;
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPutGet::getGet " << status.getMessage();
throw std::runtime_error(ss.str());
}
void EasyPutGet::issueGetGet()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
if(connectState==connectIdle) connect();
if(putGetState!=putGetIdle) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPutGet::issueGetGet aleady active ";
throw std::runtime_error(ss.str());
}
putGetState = putGetActive;
channelPutGet->getGet();
}
Status EasyPutGet::waitGetGet()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
if(putGetState!=putGetActive){
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPutGet::waitGetGet illegal state";
throw std::runtime_error(ss.str());
}
waitForPutGet.wait();
putGetState = putGetIdle;
if(channelGetPutGetStatus.isOK()) {
return Status::Ok;
}
return Status(Status::STATUSTYPE_ERROR,channelGetPutGetStatus.getMessage());
}
void EasyPutGet::getPut()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
issueGetPut();
Status status = waitGetPut();
if(status.isOK()) return;
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPutGet::getPut " << status.getMessage();
throw std::runtime_error(ss.str());
}
void EasyPutGet::issueGetPut()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
if(connectState==connectIdle) connect();
if(putGetState!=putGetIdle) {
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPutGet::issueGetPut aleady active ";
throw std::runtime_error(ss.str());
}
putGetState = putGetActive;
channelPutGet->getPut();
}
Status EasyPutGet::waitGetPut()
{
if(isDestroyed) throw std::runtime_error("easyPutGet was destroyed");
if(putGetState!=putGetActive){
stringstream ss;
ss << "channel " << channel->getChannelName() << " EasyPutGet::waitGetPut illegal state";
throw std::runtime_error(ss.str());
}
waitForPutGet.wait();
putGetState = putGetIdle;
if(channelGetPutGetStatus.isOK()) {
return Status::Ok;
}
return Status(Status::STATUSTYPE_ERROR,channelGetPutGetStatus.getMessage());
}
EasyGetDataPtr EasyPutGet::getGetData()
{
checkPutGetState();
return easyGetData;
}
EasyPutDataPtr EasyPutGet::getPutData()
{
checkPutGetState();
return easyPutData;
}
EasyPutGetPtr EasyPutGet::create(
EasyPVAPtr const &pva,
EasyChannelPtr const & easyChannel,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
{
EasyPutGetPtr epv(new EasyPutGet(pva,easyChannel,channel,pvRequest));
return epv;
}
}}

View File

@ -1,27 +1,47 @@
TOP=..
# Makefile for the pvAccess tests
TOP = ..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
TESTPROD_HOST += testEasyPutData
testEasyPutData_SRCS = testEasyPutData
testHarness_SRCS += testEasyPutData.cpp
TESTS += testEasyPutData
TESTPROD_HOST += testEasyGetData
testEasyGetData_SRCS = testEasyGetData
testHarness_SRCS += testEasyGetData.cpp
TESTS += testEasyGetData
TESTPROD_HOST += testEasyMonitorData
testEasyMonitorData_SRCS = testEasyMonitorData
testHarness_SRCS += testEasyMonitorData.cpp
TESTS += testEasyMonitorData
TESTPROD_HOST += testEasyPutGetMonitor
testEasyPutGetMonitor_SRCS = testEasyPutGetMonitor
testHarness_SRCS += testEasyPutGetMonitor.cpp
TESTS += testEasyPutGetMonitor
TESTPROD_HOST += testEasyPutGet
testEasyPutGet_SRCS = testEasyPutGet
testHarness_SRCS += testEasyPutGet.cpp
TESTS += testEasyPutGet
PROD_HOST += exampleEasyPVStructure
exampleEasyPVStructure_SRCS += exampleEasyPVStructure.cpp
exampleEasyPVStructure_LIBS += easyPVA
exampleEasyPVStructure_LIBS += pvAccess
exampleEasyPVStructure_LIBS += pvData
exampleEasyPVStructure_LIBS += Com
PROD_LIBS += easyPVA pvAccess pvData Com
PROD_HOST += exampleEasyGet
exampleEasyGet_SRCS += exampleEasyGet.cpp
exampleEasyGet_LIBS += easyPVA
exampleEasyGet_LIBS += pvAccess
exampleEasyGet_LIBS += pvData
exampleEasyGet_LIBS += Com
testHarness_SRCS += easyAllTests.c
#===========================
PROD_vxWorks = vxTestHarness
vxTestHarness_SRCS += $(testHarness_SRCS)
TESTSPEC_vxWorks = vxTestHarness.$(MUNCH_SUFFIX); easyAllTests
PROD_RTEMS += rtemsTestHarness
rtemsTestHarness_SRCS += rtemsTestHarness.c rtemsConfig.c
rtemsTestHarness_SRCS += $(testHarness_SRCS)
TESTSPEC_RTEMS = rtemsTestHarness.$(MUNCH_SUFFIX); easyAllTests
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

27
test/src/easyAllTests.c Normal file
View File

@ -0,0 +1,27 @@
/*
* Run EasyPVA tests as a batch.
*
* Do *not* include performance measurements here, they don't help to
* prove functionality (which is the point of this convenience routine).
*/
#include <stdio.h>
#include <epicsThread.h>
#include <epicsUnitTest.h>
int testEasyGetData(void);
int testEasyPutData(void);
int testEasyMonitorData(void);
int testEasyPutGetMonitor(void);
int testEasyPutGet(void);
void easyAllTests(void)
{
testHarness();
runTest(testEasyGetData);
runTest(testEasyPutData);
runTest(testEasyMonitorData);
runTest(testEasyPutMonitor);
runTest(testEasyPut);
}

View File

@ -1,91 +0,0 @@
/*exampleEasyGet.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/easyPVA.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::easyPVA;
static void exampleDouble(EasyPVAPtr const &easyPVA)
{
cout << "example double scalar\n";
double value;
try {
cout << "short way\n";
value = easyPVA->channel("exampleDouble")->get()->getDouble();
cout << "as double " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
try {
cout << "long way\n";
EasyChannelPtr easyChannel = easyPVA->createChannel("exampleDouble");
easyChannel->connect(2.0);
EasyGetPtr easyGet = easyChannel->createGet();
value = easyGet->getDouble();
cout << "as double " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
static void exampleDoubleArray(EasyPVAPtr const &easyPVA)
{
cout << "example double array\n";
shared_vector<double> value;
try {
cout << "short way\n";
value = easyPVA->createChannel("exampleDoubleArray")->createGet()->getDoubleArray();
cout << "as doubleArray " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
try {
cout << "long way\n";
EasyChannelPtr easyChannel = easyPVA->createChannel("exampleDoubleArray");
easyChannel->connect(2.0);
EasyGetPtr easyGet = easyChannel->createGet();
value = easyGet->getDoubleArray();
cout << "as doubleArray " << value << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
static void examplePowerSupply(EasyPVAPtr const &easyPVA)
{
cout << "example powerSupply\n";
PVStructurePtr pvStructure;
try {
cout << "short way\n";
pvStructure = easyPVA->createChannel("examplePowerSupply")->createGet("field()")->getPVStructure();
cout << pvStructure << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
int main(int argc,char *argv[])
{
EasyPVAPtr easyPVA = EasyPVA::create();
exampleDouble(easyPVA);
exampleDoubleArray(easyPVA);
examplePowerSupply(easyPVA);
cout << "done\n";
return 0;
}

View File

@ -1,69 +0,0 @@
/*exampleEasyPVStructure.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/easyPVA.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::easyPVA;
int main(int argc,char *argv[])
{
EasyPVAPtr easyPVA = EasyPVA::create();
StandardPVFieldPtr standardPVField = getStandardPVField();
EasyPVStructurePtr easyStruct = easyPVA->createEasyPVStructure();
PVStructurePtr pvStructure = standardPVField->scalar(pvDouble,"alarm,timeStamp");
easyStruct->setPVStructure(pvStructure);
cout << easyStruct->getPVStructure() << endl;
cout << "as double " << easyStruct->getDouble() << endl;
cout << "as float " << easyStruct->getFloat() << endl;
try {
cout << "as ubyte " << easyStruct->getUByte() << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
pvStructure = standardPVField->scalar(pvInt,"alarm,timeStamp");
easyStruct->setPVStructure(pvStructure);
cout << easyStruct->getPVStructure() << endl;
cout << "as double " << easyStruct->getDouble() << endl;
cout << "as float " << easyStruct->getFloat() << endl;
cout << "as int " << easyStruct->getInt() << endl;
cout << "as uint " << easyStruct->getUInt() << endl;
cout << "as long " << easyStruct->getLong() << endl;
cout << "as ulong " << easyStruct->getULong() << endl;
try {
cout << "as byte " << easyStruct->getByte() << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
try {
cout << "as ubyte " << easyStruct->getUByte() << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
try {
cout << "as short " << easyStruct->getShort() << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
try {
cout << "as ushort " << easyStruct->getUShort() << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
return 0;
}

View File

@ -0,0 +1,155 @@
/*testEasyGetData.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 <epicsUnitTest.h>
#include <testMain.h>
#include <pv/easyPVA.h>
#include <pv/bitSet.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::easyPVA;
static EasyPVAPtr easyPVA = EasyPVA::create();
static FieldCreatePtr fieldCreate = getFieldCreate();
static StandardFieldPtr standardField = getStandardField();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
void testDouble()
{
cout << "\nstarting testDouble\n";
StructureConstPtr structure =
fieldCreate->createFieldBuilder()->
add("alarm",standardField->alarm()) ->
add("timeStamp",standardField->timeStamp()) ->
add("value",pvDouble) ->
createStructure();
EasyGetDataPtr easyData = EasyGetData::create(structure);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(easyData->getStructure());
BitSetPtr bitSet = BitSetPtr(new BitSet(pvStructure->getNumberFields()));
easyData->setData(pvStructure,bitSet);
PVDoublePtr pvDouble = pvStructure->getSubField<PVDouble>("value");
size_t valueOffset = pvDouble->getFieldOffset();
BitSetPtr change = easyData->getBitSet();
pvDouble->put(5.0);
change->set(pvDouble->getFieldOffset());
testOk(change->cardinality()==1,"num set bits 1");
testOk(change->get(valueOffset)==true,"value changed");
testOk(easyData->hasValue()==true,"hasValue");
testOk(easyData->isValueScalar()==true,"isValueScalar");
testOk(easyData->isValueScalarArray()==false,"isValueScalarArray");
bool result;
result = false;
if(easyData->getValue()) result = true;
testOk(result==true,"getValue");
result = false;
if(easyData->getScalarValue()) result = true;
testOk(result==true,"getScalarValue");
try {
easyData->getArrayValue();
} catch (std::runtime_error e) {
cout << "getArrayValue " << e.what() << endl;
}
try {
easyData->getScalarArrayValue();
} catch (std::runtime_error e) {
cout << " getScalarArrayValue " << e.what() << endl;
}
cout << "as double " << easyData->getDouble() << endl;
cout << "as string " << easyData->getString() << endl;
try {
shared_vector<const double> value = easyData->getDoubleArray();
} catch (std::runtime_error e) {
cout << " getDoubleArray " << e.what() << endl;
}
try {
shared_vector<const string> value = easyData->getStringArray();
} catch (std::runtime_error e) {
cout << " getStringArray " << e.what() << endl;
}
}
void testDoubleArray()
{
cout << "\nstarting testDoubleArray\n";
StructureConstPtr structure =
fieldCreate->createFieldBuilder()->
add("alarm",standardField->alarm()) ->
add("timeStamp",standardField->timeStamp()) ->
addArray("value",pvDouble) ->
createStructure();
EasyGetDataPtr easyData = EasyGetData::create(structure);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(easyData->getStructure());
BitSetPtr bitSet = BitSetPtr(new BitSet(pvStructure->getNumberFields()));
easyData->setData(pvStructure,bitSet);
PVDoubleArrayPtr pvalue = easyData->getPVStructure()->getSubField<PVDoubleArray>("value");
BitSetPtr change = easyData->getBitSet();
size_t valueOffset = pvalue->getFieldOffset();
size_t len = 5;
shared_vector<double> value(len);
for(size_t i=0; i<len; ++i) value[i] = i*10.0;
pvalue->replace(freeze(value));
change->set(valueOffset);
testOk(change->cardinality()==1,"num set bits 1");
testOk(change->get(valueOffset)==true,"value changed");
testOk(easyData->hasValue()==true,"hasValue");
testOk(easyData->isValueScalar()==false,"isValueScalar");
testOk(easyData->isValueScalarArray()==true,"isValueScalarArray");
bool result;
result = false;
if(easyData->getValue()) result = true;
testOk(result==true,"getValue");
result = false;
if(easyData->getArrayValue()) result = true;
testOk(result==true,"getArrayValue");
result = false;
if(easyData->getScalarArrayValue()) result = true;
testOk(result==true,"getScalarValue");
try {
easyData->getScalarValue();
} catch (std::runtime_error e) {
cout << " getScalarValue " << e.what() << endl;
}
try {
cout << "as double " << easyData->getDouble() << endl;
} catch (std::runtime_error e) {
cout << " getDouble " << e.what() << endl;
}
try {
string val = easyData->getString();
} catch (std::runtime_error e) {
cout << " getString " << e.what() << endl;
}
cout << "as doubleArray " << easyData->getDoubleArray() << endl;
try {
shared_vector<const string> value = easyData->getStringArray();
} catch (std::runtime_error e) {
cout << " getStringArray " << e.what() << endl;
}
}
MAIN(testEasyGetData)
{
cout << "\nstarting testEasyGetData\n";
testPlan(15);
testDouble();
testDoubleArray();
return 0;
}

View File

@ -0,0 +1,153 @@
/*testEasyMonitorData.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 <epicsUnitTest.h>
#include <testMain.h>
#include <pv/easyPVA.h>
#include <pv/bitSet.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::easyPVA;
static EasyPVAPtr easyPVA = EasyPVA::create();
static FieldCreatePtr fieldCreate = getFieldCreate();
static StandardFieldPtr standardField = getStandardField();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
void testDouble()
{
cout << "\nstarting testDouble\n";
StructureConstPtr structure =
fieldCreate->createFieldBuilder()->
add("alarm",standardField->alarm()) ->
add("timeStamp",standardField->timeStamp()) ->
add("value",pvDouble) ->
createStructure();
EasyMonitorDataPtr easyData = EasyMonitorData::create(structure);
MonitorElementPtr monitorElement(new MonitorElement(pvDataCreate->createPVStructure(easyData->getStructure())));
easyData->setData(monitorElement);
PVDoublePtr pvDouble = easyData->getPVStructure()->getSubField<PVDouble>("value");
size_t valueOffset = pvDouble->getFieldOffset();
BitSetPtr change = easyData->getChangedBitSet();
pvDouble->put(5.0);
change->set(pvDouble->getFieldOffset());
testOk(change->cardinality()==1,"num set bits 1");
testOk(change->get(valueOffset)==true,"value changed");
testOk(easyData->hasValue()==true,"hasValue");
testOk(easyData->isValueScalar()==true,"isValueScalar");
testOk(easyData->isValueScalarArray()==false,"isValueScalarArray");
bool result;
result = false;
if(easyData->getValue()) result = true;
testOk(result==true,"getValue");
result = false;
if(easyData->getScalarValue()) result = true;
testOk(result==true,"getScalarValue");
try {
easyData->getArrayValue();
} catch (std::runtime_error e) {
cout << "getArrayValue " << e.what() << endl;
}
try {
easyData->getScalarArrayValue();
} catch (std::runtime_error e) {
cout << " getScalarArrayValue " << e.what() << endl;
}
cout << "as double " << easyData->getDouble() << endl;
cout << "as string " << easyData->getString() << endl;
try {
shared_vector<const double> value = easyData->getDoubleArray();
} catch (std::runtime_error e) {
cout << " getDoubleArray " << e.what() << endl;
}
try {
shared_vector<const string> value = easyData->getStringArray();
} catch (std::runtime_error e) {
cout << " getStringArray " << e.what() << endl;
}
}
void testDoubleArray()
{
cout << "\nstarting testDoubleArray\n";
StructureConstPtr structure =
fieldCreate->createFieldBuilder()->
add("alarm",standardField->alarm()) ->
add("timeStamp",standardField->timeStamp()) ->
addArray("value",pvDouble) ->
createStructure();
EasyMonitorDataPtr easyData = EasyMonitorData::create(structure);
MonitorElementPtr monitorElement(new MonitorElement(pvDataCreate->createPVStructure(easyData->getStructure())));
easyData->setData(monitorElement);
PVDoubleArrayPtr pvalue = easyData->getPVStructure()->getSubField<PVDoubleArray>("value");
BitSetPtr change = easyData->getChangedBitSet();
size_t valueOffset = pvalue->getFieldOffset();
size_t len = 5;
shared_vector<double> value(len);
for(size_t i=0; i<len; ++i) value[i] = i*10.0;
pvalue->replace(freeze(value));
change->set(valueOffset);
testOk(change->cardinality()==1,"num set bits 1");
testOk(change->get(valueOffset)==true,"value changed");
testOk(easyData->hasValue()==true,"hasValue");
testOk(easyData->isValueScalar()==false,"isValueScalar");
testOk(easyData->isValueScalarArray()==true,"isValueScalarArray");
bool result;
result = false;
if(easyData->getValue()) result = true;
testOk(result==true,"getValue");
result = false;
if(easyData->getArrayValue()) result = true;
testOk(result==true,"getArrayValue");
result = false;
if(easyData->getScalarArrayValue()) result = true;
testOk(result==true,"getScalarValue");
try {
easyData->getScalarValue();
} catch (std::runtime_error e) {
cout << " getScalarValue " << e.what() << endl;
}
try {
cout << "as double " << easyData->getDouble() << endl;
} catch (std::runtime_error e) {
cout << " getDouble " << e.what() << endl;
}
try {
string val = easyData->getString();
} catch (std::runtime_error e) {
cout << " getString " << e.what() << endl;
}
cout << "as doubleArray " << easyData->getDoubleArray() << endl;
try {
shared_vector<const string> value = easyData->getStringArray();
} catch (std::runtime_error e) {
cout << " getStringArray " << e.what() << endl;
}
}
MAIN(testEasyMonitorData)
{
cout << "\nstarting testEasyMonitorData\n";
testPlan(15);
testDouble();
testDoubleArray();
return 0;
}

View File

@ -0,0 +1,229 @@
/*testEasyData.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 <epicsUnitTest.h>
#include <testMain.h>
#include <pv/easyPVA.h>
#include <pv/bitSet.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::easyPVA;
static EasyPVAPtr easyPVA = EasyPVA::create();
static FieldCreatePtr fieldCreate = getFieldCreate();
static StandardFieldPtr standardField = getStandardField();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static void testPostPut()
{
cout << "\nstarting testPostPut\n";
StructureConstPtr structure =
fieldCreate->createFieldBuilder()->
add("alarm",standardField->alarm()) ->
add("timeStamp",standardField->timeStamp()) ->
addNestedStructure("power") ->
add("value",pvDouble) ->
add("alarm",standardField->alarm()) ->
endNested()->
addNestedStructure("voltage") ->
add("value",pvDouble) ->
add("alarm",standardField->alarm()) ->
endNested()->
addNestedStructure("current") ->
add("value",pvDouble) ->
add("alarm",standardField->alarm()) ->
endNested()->
createStructure();
EasyPutDataPtr easyData = EasyPutData::create(structure);
PVStructurePtr pvStructure = easyData->getPVStructure();
BitSetPtr change = easyData->getBitSet();
PVDoublePtr powerValue = pvStructure->getSubField<PVDouble>("power.value");
PVDoublePtr voltageValue = pvStructure->getSubField<PVDouble>("voltage.value");
PVDoublePtr currentValue = pvStructure->getSubField<PVDouble>("current.value");
size_t powerOffset = powerValue->getFieldOffset();
size_t voltageOffset = voltageValue->getFieldOffset();
size_t currentOffset = currentValue->getFieldOffset();
change->clear();
powerValue->put(1.0);
voltageValue->put(2.0);
currentValue->put(.5);
cout << "changed\n";
cout << easyData->showChanged(cout) << endl;
testOk(change->cardinality()==3,"num set bits 3");
testOk(change->get(powerOffset)==true,"power changed");
testOk(change->get(voltageOffset)==true,"voltage changed");
testOk(change->get(currentOffset)==true,"current changed");
}
void testDouble()
{
cout << "\nstarting testDouble\n";
StructureConstPtr structure =
fieldCreate->createFieldBuilder()->
add("alarm",standardField->alarm()) ->
add("timeStamp",standardField->timeStamp()) ->
add("value",pvDouble) ->
createStructure();
EasyPutDataPtr easyData = EasyPutData::create(structure);
PVDoublePtr pvDouble = easyData->getPVStructure()->getSubField<PVDouble>("value");
pvDouble->put(5.0);
BitSetPtr change = easyData->getBitSet();
size_t valueOffset = pvDouble->getFieldOffset();
testOk(change->cardinality()==1,"num set bits 1");
testOk(change->get(valueOffset)==true,"value changed");
testOk(easyData->hasValue()==true,"hasValue");
testOk(easyData->isValueScalar()==true,"isValueScalar");
testOk(easyData->isValueScalarArray()==false,"isValueScalarArray");
bool result;
result = false;
if(easyData->getValue()) result = true;
testOk(result==true,"getValue");
result = false;
if(easyData->getScalarValue()) result = true;
testOk(result==true,"getScalarValue");
try {
easyData->getArrayValue();
} catch (std::runtime_error e) {
cout << "getArrayValue " << e.what() << endl;
}
try {
easyData->getScalarArrayValue();
} catch (std::runtime_error e) {
cout << " getScalarArrayValue " << e.what() << endl;
}
cout << "as double " << easyData->getDouble() << endl;
cout << "as string " << easyData->getString() << endl;
try {
shared_vector<const double> value = easyData->getDoubleArray();
} catch (std::runtime_error e) {
cout << " getDoubleArray " << e.what() << endl;
}
try {
shared_vector<const string> value = easyData->getStringArray();
} catch (std::runtime_error e) {
cout << " getStringArray " << e.what() << endl;
}
easyData->putDouble(5.0);
easyData->putString("1e5");
try {
size_t len = 2;
shared_vector<double> val(len);
for(size_t i=0; i<len; ++i) val[i] = (i+1)*10.0;
easyData->putDoubleArray(freeze(val));
} catch (std::runtime_error e) {
cout << " putDoubleArray " << e.what() << endl;
}
try {
size_t len = 2;
shared_vector<string> val(len);
val[0] = "one"; val[1] = "two";
easyData->putStringArray(freeze(val));
} catch (std::runtime_error e) {
cout << " putStringArray " << e.what() << endl;
}
}
void testDoubleArray()
{
cout << "\nstarting testDoubleArray\n";
StructureConstPtr structure =
fieldCreate->createFieldBuilder()->
add("alarm",standardField->alarm()) ->
add("timeStamp",standardField->timeStamp()) ->
addArray("value",pvDouble) ->
createStructure();
EasyPutDataPtr easyData = EasyPutData::create(structure);
PVDoubleArrayPtr pvalue = easyData->getPVStructure()->getSubField<PVDoubleArray>("value");
size_t len = 5;
shared_vector<double> value(len);
for(size_t i=0; i<len; ++i) value[i] = i*10.0;
pvalue->replace(freeze(value));
BitSetPtr change = easyData->getBitSet();
size_t valueOffset = pvalue->getFieldOffset();
testOk(change->cardinality()==1,"num set bits 1");
testOk(change->get(valueOffset)==true,"value changed");
testOk(easyData->hasValue()==true,"hasValue");
testOk(easyData->isValueScalar()==false,"isValueScalar");
testOk(easyData->isValueScalarArray()==true,"isValueScalarArray");
bool result;
result = false;
if(easyData->getValue()) result = true;
testOk(result==true,"getValue");
result = false;
if(easyData->getArrayValue()) result = true;
testOk(result==true,"getArrayValue");
result = false;
if(easyData->getScalarArrayValue()) result = true;
testOk(result==true,"getScalarValue");
try {
easyData->getScalarValue();
} catch (std::runtime_error e) {
cout << " getScalarValue " << e.what() << endl;
}
try {
cout << "as double " << easyData->getDouble() << endl;
} catch (std::runtime_error e) {
cout << " getDouble " << e.what() << endl;
}
try {
string val = easyData->getString();
} catch (std::runtime_error e) {
cout << " getString " << e.what() << endl;
}
cout << "as doubleArray " << easyData->getDoubleArray() << endl;
try {
shared_vector<const string> value = easyData->getStringArray();
} catch (std::runtime_error e) {
cout << " getStringArray " << e.what() << endl;
}
try {
easyData->putDouble(5.0);
} catch (std::runtime_error e) {
cout << " putDouble " << e.what() << endl;
}
try {
easyData->putString("1e5");
} catch (std::runtime_error e) {
cout << " putString " << e.what() << endl;
}
value = shared_vector<double>(len);
for(size_t i=0; i<len; ++i) value[i] = (i+1)* 2;
easyData->putDoubleArray(freeze(value));
cout << "as doubleArray " << easyData->getDoubleArray() << endl;
try {
size_t len = 2;
shared_vector<string> val(len);
val[0] = "one"; val[1] = "two";
easyData->putStringArray(freeze(val));
cout << "as stringArray " << val << endl;
} catch (std::runtime_error e) {
cout << " putStringArray " << e.what() << endl;
}
}
MAIN(testEasyPutData)
{
cout << "\nstarting testEasyPutData\n";
testPlan(19);
testPostPut();
testDouble();
testDoubleArray();
return 0;
}

View File

@ -0,0 +1,66 @@
/*exampleEasyPutGet.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/easyPVA.h>
#include <epicsUnitTest.h>
#include <testMain.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::easyPVA;
static void example(EasyPVAPtr const &easyPVA)
{
cout << "\nstarting channelPutGet example\n";
try {
EasyChannelPtr easyChannel = easyPVA->createChannel("examplePowerSupply");
easyChannel->connect(2.0);
testOk(true==true,"connected");
EasyPutGetPtr putGet = easyChannel->createPutGet(
"putField(power.value,voltage.value)getField()");
EasyPutDataPtr putData = putGet->getPutData();
testOk(true==true,"put connected");
PVStructurePtr pvStructure = putData->getPVStructure();
PVDoublePtr power = pvStructure->getSubField<PVDouble>("power.value");
PVDoublePtr voltage = pvStructure->getSubField<PVDouble>("voltage.value");
power->put(5.0);
voltage->put(5.0);
putGet->putGet();
EasyGetDataPtr getData = putGet->getGetData();
pvStructure = getData->getPVStructure();
BitSetPtr bitSet = getData->getBitSet();
cout << "changed " << getData->showChanged(cout) << endl;
cout << "bitSet " << *bitSet << endl;
power->put(6.0);
putGet->putGet();
pvStructure = getData->getPVStructure();
bitSet = getData->getBitSet();
cout << "changed " << getData->showChanged(cout) << endl;
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
MAIN(testEasyPutGet)
{
cout << "\nstarting testEasyPutGet\n";
testPlan(2);
EasyPVAPtr easyPVA = EasyPVA::create();
example(easyPVA);
cout << "done\n";
return 0;
}

View File

@ -0,0 +1,89 @@
/*exampleEasyPutGetMonitor.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/easyPVA.h>
#include <epicsUnitTest.h>
#include <testMain.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::easyPVA;
class MyMonitor : public EasyMonitorRequester
{
public:
MyMonitor() {}
virtual ~MyMonitor() {}
virtual void event(EasyMonitorPtr monitor)
{
while(true) {
if(!monitor->poll()) return;
EasyMonitorDataPtr easyData = monitor->getData();
cout << "changed\n";
easyData->showChanged(cout);
cout << "overrun\n";
easyData->showOverrun(cout);
monitor->releaseEvent();
}
}
};
static void exampleDouble(EasyPVAPtr const &easyPVA)
{
cout << "\nstarting exampleDouble\n";
try {
cout << "long way\n";
EasyChannelPtr easyChannel = easyPVA->createChannel("exampleDouble");
easyChannel->connect(2.0);
testOk(true==true,"connected");
EasyPutPtr put = easyChannel->createPut();
EasyPutDataPtr putData = put->getData();
testOk(true==true,"put connected");
EasyGetPtr get = easyChannel->createGet();
EasyGetDataPtr getData = get->getData();
testOk(true==true,"get connected");
EasyMonitorRequesterPtr requester(new MyMonitor());
EasyMonitorPtr monitor = easyChannel->monitor(requester);
testOk(true==true,"monitor connected");
double out;
double in;
for(size_t i=0 ; i< 5; ++i) {
out = i;
putData->putDouble(out);
put->put();
get->get();
in = getData->getDouble();
cout << "out " << out << " in " << in << endl;
}
EasyProcessPtr process = easyChannel->createProcess();
process->connect();
process->process();
} catch (std::runtime_error e) {
cout << "exception " << e.what() << endl;
}
}
MAIN(testEasyPutGetMonitor)
{
cout << "\nstarting testEasyPutGetMonitor\n";
testPlan(4);
EasyPVAPtr easyPVA = EasyPVA::create();
exampleDouble(easyPVA);
cout << "done\n";
return 0;
}