From 7f521bdc3c67b3a0e14175a9b714440af97c73fc Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Thu, 21 Aug 2014 07:59:46 -0400 Subject: [PATCH] added NTMultiChannel --- documentation/ntCPP.html | 180 ++++++++++++++++++--------------- src/Makefile | 2 + src/nt/ntmultiChannel.cpp | 152 ++++++++++++++++++++++++++++ src/nt/ntmultiChannel.h | 99 ++++++++++++++++++ test/nt/Makefile | 8 ++ test/nt/ntmultiChannelTest.cpp | 98 ++++++++++++++++++ 6 files changed, 457 insertions(+), 82 deletions(-) create mode 100644 src/nt/ntmultiChannel.cpp create mode 100644 src/nt/ntmultiChannel.h create mode 100644 test/nt/ntmultiChannelTest.cpp diff --git a/documentation/ntCPP.html b/documentation/ntCPP.html index fcfa8cb..c6b8ef3 100644 --- a/documentation/ntCPP.html +++ b/documentation/ntCPP.html @@ -10,13 +10,88 @@ + 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; } + /*]]>*/ + + + + +
+

EPICS pvDataCPP

+ + +

EPICS v4 Working Group, Working Draft, 23-July-2014

+ +
+
Latest version:
+
pvDataCPP.html +
+
This version:
+
pvDataCPP_20140708.html +
+
Previous version:
+
pvDataCPP_20140501.html +
+
Editors:
+
Marty Kraimer, BNL
+
Michael Davidsaver, BNL
+
Matej Sekoranja, CosyLab
+
+ + +
+
+

Abstract

+ +

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:
+relatedDocumentsV4.html +

+ + +

Status of this Document

+ +

For now this is a working copy so it is not the same as "This version" shown above.

+ +

This is the 23-July-2014 version of the C++ implementation of pvData. +

+ +

RELEASE_NOTES.md provides changes since the last release. +TODO.md describes things to do before the next release. +

+ + + +
+

Table of Contents

+
+

EPICS normative type C++ implementation @@ -27,14 +102,14 @@
This version:
ntCPP.html
Editors:
-
Guobao Shen, BNL
- Marty Kraimer, BNL
+
Matej Sekoranja, CosyLab
+ Marty Kraimer, BNL +

-

Normative Types

-
+

Introduction

This section describes the C++ implemmentation of normative types. Two (2) helper classes are implemented, ntNameValue and NTTable respectively.

@@ -49,7 +124,7 @@ public: static NTFieldPtr get(); ~NTField() {} - PVStructurePtr createEnumerated(StringArray const & choices); + PVStructurePtr createEnumerated(StringArray const & choices); PVStructurePtr createTimeStamp(); PVStructurePtr createAlarm(); PVStructurePtr createDisplay(); @@ -193,83 +268,24 @@ public:
getPVField
Get the data field for the specified field.
-
-

License Agreement

-
-
Copyright (c) 2008 Martin R. Kraimer
-Copyright (c) 2007 Control System Laboratory,
-    (COSYLAB) Ljubljana Slovenia
-Copyright (c) 2010 Brookhaven National Laboratory
+

MTMultiChannel

+
+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
+
-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. -________________________________________________________________________
+ diff --git a/src/Makefile b/src/Makefile index e184efd..c81926a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 diff --git a/src/nt/ntmultiChannel.cpp b/src/nt/ntmultiChannel.cpp new file mode 100644 index 0000000..cf2efc4 --- /dev/null +++ b/src/nt/ntmultiChannel.cpp @@ -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 + +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("value"); + if(!pvValue) return false; + PVStringArrayPtr pvChannelName = + pvStructure->getSubField("channelName"); + return true; +} + +NTMultiChannelPtr NTMultiChannel::create( + std::vector const & optionNames) +{ + return NTMultiChannel::create(optionNames,fieldCreate->createVariantUnion()); +} + +NTMultiChannelPtr NTMultiChannel::create( + std::vector const & optionNames, + epics::pvData::UnionConstPtr const & unionPtr) +{ + shared_vector channelNames; + return NTMultiChannel::create(optionNames,unionPtr,channelNames); +} + +NTMultiChannelPtr NTMultiChannel::create( + std::vector const & optionNames, + UnionConstPtr const & unionPtr, + shared_vector 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; icreateUnionArray(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("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("timeStamp")), + pvAlarm(pvStructure->getSubField("alarm")), + pvValue(pvStructure->getSubField("value")), + pvChannelName(pvStructure->getSubField("channelName")), + pvSeverity(pvStructure->getSubField("severity")), + pvStatus(pvStructure->getSubField("status")), + pvMessage(pvStructure->getSubField("message")), + pvSecondsPastEpoch(pvStructure->getSubField("secondsPastEpoch")), + pvNanoseconds(pvStructure->getSubField("nanoseconds")), + pvDescriptor(pvStructure->getSubField("descriptor")) +{ +} + + +void NTMultiChannel::attachTimeStamp(PVTimeStamp &pv) +{ + if(!pvTimeStamp) return; + pv.attach(pvTimeStamp); +} + +void NTMultiChannel::attachAlarm(PVAlarm &pv) +{ + if(!pvAlarm) return; + pv.attach(pvAlarm); +} + +}} diff --git a/src/nt/ntmultiChannel.h b/src/nt/ntmultiChannel.h new file mode 100644 index 0000000..fd61a54 --- /dev/null +++ b/src/nt/ntmultiChannel.h @@ -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 + +namespace epics { namespace nt { + +/** + * Convenience Class for NTMultiChannel + * @author mrk + * + */ + +class NTMultiChannel; +typedef std::tr1::shared_ptr 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 const & optionNames); + static NTMultiChannelPtr create( + std::vector const & optionNames, + epics::pvData::UnionConstPtr const & unionPtr); + static NTMultiChannelPtr create( + std::vector const & optionNames, + epics::pvData::UnionConstPtr const & unionPtr, + epics::pvData::shared_vector 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 */ diff --git a/test/nt/Makefile b/test/nt/Makefile index cb1f656..86da46d 100644 --- a/test/nt/Makefile +++ b/test/nt/Makefile @@ -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 diff --git a/test/nt/ntmultiChannelTest.cpp b/test/nt/ntmultiChannelTest.cpp new file mode 100644 index 0000000..64f4731 --- /dev/null +++ b/test/nt/ntmultiChannelTest.cpp @@ -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 +#include +#include +#include +#include +#include + +#include +#include + + +#include +#include +#include + +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 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 names(nchan); + names[0] = "channel 0"; + names[1] = "channel 1"; + names[2] = "channel 2"; + shared_vector 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 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->put(1.235); + PVIntPtr pvInt = unions[1]->get(); + pvInt->put(5); + pvValue->replace(freeze(unions)); + shared_vector 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(); +} +