added NTMultiChannel

This commit is contained in:
Marty Kraimer
2014-08-21 07:59:46 -04:00
parent fdeda9dc97
commit 7f521bdc3c
6 changed files with 457 additions and 82 deletions

View File

@@ -10,13 +10,88 @@
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
/*<![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>
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<div class="head">
<h1>EPICS pvDataCPP</h1>
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 23-July-2014</h2>
<dl>
<dt>Latest version:</dt>
<dd><a
href="pvDataCPP.html">pvDataCPP.html</a>
</dd>
<dt>This version:</dt>
<dd><a
href="pvDataCPP_20140708.html">pvDataCPP_20140708.html</a>
</dd>
<dt>Previous version:</dt>
<dd><a
href="pvDataCPP_20140501.html">pvDataCPP_20140501.html</a>
</dd>
<dt>Editors:</dt>
<dd>Marty Kraimer, BNL</dd>
<dd>Michael Davidsaver, BNL</dd>
<dd>Matej Sekoranja, CosyLab</dd>
</dl>
<p class="copyright">This product is made available subject to acceptance of the <a
href="http://epics-pvdata.sourceforge.net/LICENSE.html">EPICS open source
license.</a></p>
<hr />
</div>
<h2 class="nocount">Abstract</h2>
<p>EPICS Version 4 provides efficient
storage, access, and communication, of memory resident structured data.
pvData is the storage compoment.
pvDataCPP is the C++ implementation of pvData.
It is one part of the set of related products in the EPICS
V4 control system programming environment:<br />
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
</p>
<h2 class="nocount">Status of this Document</h2>
<p>For now this is a working copy so it is not the same as "This version" shown above.</p>
<p>This is the 23-July-2014 version of the C++ implementation of pvData.
</p>
<p>RELEASE_NOTES.md provides changes since the last release.
TODO.md describes things to do before the next release.
</p>
<div id="toc">
<h2 class="nocount" style="page-break-before: always">Table of Contents</h2>
</div>
<div id="contents" class="contents">
<body>
<h1 style="text-align: center">EPICS normative type C++ implementation
@@ -27,14 +102,14 @@
<dt>This version:</dt>
<dd><a href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/normativeTypesCPP/raw-file/tip/documentation/ntCPP.html">ntCPP.html</a></dd>
<dt>Editors:</dt>
<dd>Guobao Shen, BNL<br>
Marty Kraimer, BNL<span style="font-weight: bold;"></span></dd>
<dd>Matej Sekoranja, CosyLab<br>
Marty Kraimer, BNL
</dd>
</dl>
<hr />
</div>
<h2 style="text-align: center">Normative Types</h2>
<hr />
<h2>Introduction</h2>
<p>This section describes the C++ implemmentation of normative types. Two (2) helper classes are implemented,
ntNameValue and NTTable respectively. </p>
@@ -49,7 +124,7 @@ public:
static NTFieldPtr get();
~NTField() {}
PVStructurePtr createEnumerated(StringArray const & choices);
PVStructurePtr createEnumerated(StringArray const &amp; choices);
PVStructurePtr createTimeStamp();
PVStructurePtr createAlarm();
PVStructurePtr createDisplay();
@@ -193,83 +268,24 @@ public:
<dt>getPVField</dt>
<dd>Get the data field for the specified field.</dd>
</dl>
<hr />
<h2 style="text-align: center">License Agreement</h2>
<hr />
<pre>Copyright (c) 2008 Martin R. Kraimer
Copyright (c) 2007 Control System Laboratory,
(COSYLAB) Ljubljana Slovenia
Copyright (c) 2010 Brookhaven National Laboratory
<h2>MTMultiChannel</h2>
<pre>
structure NTMultiChannel
union_t[] value
string[] channelName
time_t timeStamp :opt // time when data collected
alarm_t alarm :opt // alarm associated with data collection
int[] severity :opt // alarm severity for each value
int[] status :opt // alarm status for each value
string[] message :opt // alarm message for each value
long[] secondsPastEpoch :opt // seconds for each value.
int[] nanoseconds :opt // nanoseconds for each value
string descriptor :opt // descriptor data
</pre>
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
________________________________________________________________________
This software is in part copyrighted by Brookhaven National Laboratory(BNL)
In no event shall BNL be liable to any party for direct, indirect,
special, incidental, or consequential damages arising out of the use of
this software, its documentation, or any derivatives thereof, even if
BNL has been advised of the possibility of such damage.
BNL specifically disclaims any warranties, including, but not limited
to, the implied warranties of merchantability, fitness for a particular
purpose, and non-infringement. This software is provided on an "as is"
basis, and BNL has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________
This software is in part copyrighted by the BERLINER SPEICHERRING
GESELLSCHAFT FUER SYNCHROTRONSTRAHLUNG M.B.H. (BESSY), BERLIN, GERMANY.
In no event shall BESSY be liable to any party for direct, indirect,
special, incidental, or consequential damages arising out of the use of
this software, its documentation, or any derivatives thereof, even if
BESSY has been advised of the possibility of such damage.
BESSY specifically disclaims any warranties, including, but not limited
to, the implied warranties of merchantability, fitness for a particular
purpose, and non-infringement. This software is provided on an "as is"
basis, and BESSY has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________
This software is in part copyrighted by the Deutsches Elektronen-Synchroton,
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
In no event shall DESY be liable to any party for direct, indirect,
special, incidental, or consequential damages arising out of the use of
this software, its documentation, or any derivatives thereof, even if
DESY has been advised of the possibility of such damage.
DESY specifically disclaims any warranties, including, but not limited
to, the implied warranties of merchantability, fitness for a particular
purpose, and non-infringement. This software is provided on an "as is"
basis, and DESY has no obligation to provide maintenance, support,
updates, enhancements, or modifications.
________________________________________________________________________</pre>
</div>
</body>
</html>

View File

@@ -9,10 +9,12 @@ INC += nt.h
INC += ntfield.h
INC += ntnameValue.h
INC += nttable.h
INC += ntmultiChannel.h
LIBSRCS += ntfield.cpp
LIBSRCS += ntnameValue.cpp
LIBSRCS += nttable.cpp
LIBSRCS += ntmultiChannel.cpp
LIBRARY=nt

152
src/nt/ntmultiChannel.cpp Normal file
View File

@@ -0,0 +1,152 @@
/* ntmultiChannel.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#include <pv/ntmultiChannel.h>
namespace epics { namespace nt {
using namespace epics::pvData;
using std::tr1::static_pointer_cast;
using std::string;
using std::cout;
using std::endl;
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
bool NTMultiChannel::isNTMultiChannel(PVStructurePtr const & pvStructure)
{
PVUnionArrayPtr pvValue = pvStructure->getSubField<PVUnionArray>("value");
if(!pvValue) return false;
PVStringArrayPtr pvChannelName =
pvStructure->getSubField<PVStringArray>("channelName");
return true;
}
NTMultiChannelPtr NTMultiChannel::create(
std::vector<std::string> const & optionNames)
{
return NTMultiChannel::create(optionNames,fieldCreate->createVariantUnion());
}
NTMultiChannelPtr NTMultiChannel::create(
std::vector<std::string> const & optionNames,
epics::pvData::UnionConstPtr const & unionPtr)
{
shared_vector<const std::string> channelNames;
return NTMultiChannel::create(optionNames,unionPtr,channelNames);
}
NTMultiChannelPtr NTMultiChannel::create(
std::vector<std::string> const & optionNames,
UnionConstPtr const & unionPtr,
shared_vector<const std::string> channelNames)
{
StandardFieldPtr standardField = getStandardField();
size_t nfields = 2;
bool hasAlarm = false;
bool hasTimeStamp = false;
bool hasSeverity = false;
bool hasStatus = false;
bool hasMessage = false;
bool hasSecondsPastEpoch = false;
bool hasNanoseconds = false;
bool hasDescriptor = false;
for(size_t i=0; i<optionNames.size(); ++i) {
string name = optionNames[i];
if(name.compare("alarm")==0) {hasAlarm = true; ++nfields;}
if(name.compare("timeStamp")==0) {hasTimeStamp = true; ++nfields;}
if(name.compare("severity")==0) {hasSeverity = true; ++nfields;}
if(name.compare("status")==0) {hasStatus = true; ++nfields;}
if(name.compare("message")==0) {hasMessage = true; ++nfields;}
if(name.compare("secondsPastEpoch")==0) {hasSecondsPastEpoch = true; ++nfields;}
if(name.compare("nanoseconds`")==0) {hasNanoseconds = true; ++nfields;}
if(name.compare("descriptor")==0) {hasDescriptor = true; ++nfields;}
}
FieldConstPtrArray fields(nfields);
StringArray names(nfields);
size_t ind = 0;
names[ind] = "value";
fields[ind++] = fieldCreate->createUnionArray(unionPtr);
names[ind] = "channelName";
fields[ind++] = fieldCreate->createScalarArray(pvString);
if(hasTimeStamp) {
names[ind] = "timeStamp";
fields[ind++] = standardField->timeStamp();
}
if(hasAlarm) {
names[ind] = "alarm";
fields[ind++] = standardField->alarm();
}
if(hasDescriptor) {
names[ind] = "descriptor";
fields[ind++] = fieldCreate->createScalar(pvString);
}
if(hasSeverity) {
names[ind] = "severity";
fields[ind++] = fieldCreate->createScalarArray(pvInt);
}
if(hasStatus) {
names[ind] = "status";
fields[ind++] = fieldCreate->createScalarArray(pvInt);
}
if(hasMessage) {
names[ind] = "message";
fields[ind++] = fieldCreate->createScalarArray(pvString);
}
if(hasSecondsPastEpoch) {
names[ind] = "secondsPastEpoch";
fields[ind++] = fieldCreate->createScalarArray(pvLong);
}
if(hasNanoseconds) {
names[ind] = "nanoseconds";
fields[ind++] = fieldCreate->createScalarArray(pvInt);
}
StructureConstPtr st = fieldCreate->createStructure(names,fields);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(st);
if(channelNames.size()>0) {
PVStringArrayPtr pvName = pvStructure->getSubField<PVStringArray>("channelName");
pvName->replace(channelNames);
}
return NTMultiChannelPtr(new NTMultiChannel(pvStructure));
}
NTMultiChannelPtr NTMultiChannel::clone(PVStructurePtr const & pv)
{
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(pv);
return NTMultiChannelPtr(new NTMultiChannel(pvStructure));
}
NTMultiChannel::NTMultiChannel(PVStructurePtr const & pvStructure)
: pvNTMultiChannel(pvStructure),
pvTimeStamp(pvStructure->getSubField<PVStructure>("timeStamp")),
pvAlarm(pvStructure->getSubField<PVStructure>("alarm")),
pvValue(pvStructure->getSubField<PVUnionArray>("value")),
pvChannelName(pvStructure->getSubField<PVStringArray>("channelName")),
pvSeverity(pvStructure->getSubField<PVIntArray>("severity")),
pvStatus(pvStructure->getSubField<PVIntArray>("status")),
pvMessage(pvStructure->getSubField<PVStringArray>("message")),
pvSecondsPastEpoch(pvStructure->getSubField<PVLongArray>("secondsPastEpoch")),
pvNanoseconds(pvStructure->getSubField<PVIntArray>("nanoseconds")),
pvDescriptor(pvStructure->getSubField<PVString>("descriptor"))
{
}
void NTMultiChannel::attachTimeStamp(PVTimeStamp &pv)
{
if(!pvTimeStamp) return;
pv.attach(pvTimeStamp);
}
void NTMultiChannel::attachAlarm(PVAlarm &pv)
{
if(!pvAlarm) return;
pv.attach(pvAlarm);
}
}}

99
src/nt/ntmultiChannel.h Normal file
View File

@@ -0,0 +1,99 @@
/* ntmultiChannel.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef NTMULTICHANNEL_H
#define NTMULTICHANNEL_H
#include <pv/ntfield.h>
namespace epics { namespace nt {
/**
* Convenience Class for NTMultiChannel
* @author mrk
*
*/
class NTMultiChannel;
typedef std::tr1::shared_ptr<NTMultiChannel> NTMultiChannelPtr;
class NTMultiChannel
{
public:
POINTER_DEFINITIONS(NTMultiChannel);
/**
* Is the pvStructure an NTMultiChannel.
* @param pvStructure The pvStructure to test.
* @return (false,true) if (is not, is) an NTMultiChannel.
*/
static bool isNTMultiChannel(
epics::pvData::PVStructurePtr const &pvStructure);
static NTMultiChannelPtr create(
std::vector<std::string> const & optionNames);
static NTMultiChannelPtr create(
std::vector<std::string> const & optionNames,
epics::pvData::UnionConstPtr const & unionPtr);
static NTMultiChannelPtr create(
std::vector<std::string> const & optionNames,
epics::pvData::UnionConstPtr const & unionPtr,
epics::pvData::shared_vector<const std::string> channelNames);
static NTMultiChannelPtr clone(epics::pvData::PVStructurePtr const &);
/**
* Destructor
*/
~NTMultiChannel() {}
/**
* Attach a pvTimeStamp.
* @param pvTimeStamp The pvTimeStamp that will be attached.
* Does nothing if no timeStamp
*/
void attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp);
/**
* Attach a pvAlarm.
* @param pvAlarm The pvAlarm that will be attached.
* Does nothing if no alarm
*/
void attachAlarm(epics::pvData::PVAlarm &pvAlarm);
/**
* Get the pvStructure.
* @return PVStructurePtr.
*/
epics::pvData::PVStructurePtr getPVStructure(){return pvNTMultiChannel;}
/**
* Get the timeStamp.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getTimeStamp(){return pvTimeStamp;}
/**
* Get the alarm.
* @return PVStructurePtr which may be null.
*/
epics::pvData::PVStructurePtr getAlarm() {return pvAlarm;}
epics::pvData::PVUnionArrayPtr getValue() {return pvValue;}
epics::pvData::PVStringArrayPtr getChannelName() { return pvChannelName;};
epics::pvData::PVIntArrayPtr getSeverity() {return pvSeverity;}
epics::pvData::PVIntArrayPtr getStatus() {return pvStatus;}
epics::pvData::PVStringArrayPtr getMessage() {return pvMessage;}
epics::pvData::PVLongArrayPtr getSecondsPastEpoch() {return pvSecondsPastEpoch;}
epics::pvData::PVIntArrayPtr getNanoseconds() {return pvNanoseconds;}
epics::pvData::PVStringPtr getDescriptor() {return pvDescriptor;}
private:
NTMultiChannel(epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvNTMultiChannel;
epics::pvData::PVStructurePtr pvTimeStamp;
epics::pvData::PVStructurePtr pvAlarm;
epics::pvData::PVUnionArrayPtr pvValue;
epics::pvData::PVStringArrayPtr pvChannelName;
epics::pvData::PVIntArrayPtr pvSeverity;
epics::pvData::PVIntArrayPtr pvStatus;
epics::pvData::PVStringArrayPtr pvMessage;
epics::pvData::PVLongArrayPtr pvSecondsPastEpoch;
epics::pvData::PVIntArrayPtr pvNanoseconds;
epics::pvData::PVStringPtr pvDescriptor;
};
}}
#endif /* NTMULTICHANNEL_H */

View File

@@ -12,10 +12,18 @@ PROD_HOST += ntnameValueTest
ntnameValueTest_SRCS += ntnameValueTest.cpp
ntnameValueTest_LIBS += nt pvData Com
PROD_HOST += ntmultiChannelTest
ntmultiChannelTest_SRCS += ntmultiChannelTest.cpp
ntmultiChannelTest_LIBS += nt pvData Com
TESTPROD_HOST += nttableTest
nttableTest_SRCS = nttableTest.cpp
TESTS += nttableTest
TESTPROD_HOST += ntmultiChannelTest
ntmultiChannelTest_SRCS = ntmultiChannelTest.cpp
TESTS += ntmultiChannelTest
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
include $(TOP)/configure/RULES

View File

@@ -0,0 +1,98 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/*
* ntnameValueTest.cpp
*
* Created on: 2014.08
* Author: Marty Kraimer
*/
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <list>
#include <iostream>
#include <epicsUnitTest.h>
#include <testMain.h>
#include <pv/nt.h>
#include <pv/sharedVector.h>
#include <pv/ntmultiChannel.h>
using namespace epics::pvData;
using namespace epics::nt;
using std::string;
using std::cout;
using std::endl;
using std::vector;
static bool debug = true;
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static NTFieldPtr ntField = NTField::get();
static PVNTFieldPtr pvntField = PVNTField::get();
static void test()
{
vector<string> optionNames(10);
optionNames[0] = "alarm";
optionNames[1] = "timeStamp";
optionNames[2] = "severity";
NTMultiChannelPtr multiChannel = NTMultiChannel::create(optionNames);
testOk1(multiChannel.get()!=NULL);
PVStructurePtr pvStructure = multiChannel->getPVStructure();
testOk1(pvStructure.get()!=NULL);
size_t nchan = 3;
shared_vector<string> names(nchan);
names[0] = "channel 0";
names[1] = "channel 1";
names[2] = "channel 2";
shared_vector<const string> channelNames(freeze(names));
PVStringArrayPtr pvChannelName = multiChannel->getChannelName();
pvChannelName->replace(channelNames);
if(debug) {cout << *pvStructure << endl;}
UnionConstPtr unionPtr =
fieldCreate->createFieldBuilder()->
add("doubleValue", pvDouble)->
add("intValue", pvInt)->
createUnion();
multiChannel = NTMultiChannel::create(
optionNames,unionPtr,channelNames);
testOk1(multiChannel.get()!=NULL);
pvStructure = multiChannel->getPVStructure();
if(debug) {cout << *pvStructure << endl;}
PVUnionArrayPtr pvValue = multiChannel->getValue();
shared_vector<PVUnionPtr> unions(2);
unions[0] = pvDataCreate->createPVUnion(unionPtr);
unions[1] = pvDataCreate->createPVUnion(unionPtr);
unions[0]->select("doubleValue");
unions[1]->select("intValue");
PVDoublePtr pvDouble = unions[0]->get<PVDouble>();
pvDouble->put(1.235);
PVIntPtr pvInt = unions[1]->get<PVInt>();
pvInt->put(5);
pvValue->replace(freeze(unions));
shared_vector<int32> severities(nchan);
severities[0] = 0;
severities[1] = 1;
severities[2] = 2;
PVIntArrayPtr pvSeverity = multiChannel->getSeverity();
pvSeverity->replace(freeze(severities));
if(debug) {cout << *pvStructure << endl;}
}
MAIN(testCreateRequest)
{
testPlan(10);
test();
return testDone();
}