コード例 #1
0
void PVStructure::appendPVField(
    String const &fieldName,
    PVFieldPtr const & pvField)
{
    size_t origLength = pvFields.size();
    size_t newLength = origLength+1;
    PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
    xxx->push_back(pvField);
    FieldConstPtr field = getFieldCreate()->appendField(
        structurePtr,fieldName,pvField->getField());
    replaceField(field);
    structurePtr = static_pointer_cast<const Structure>(field);
    StringArray fieldNames = structurePtr->getFieldNames();
    for(size_t i=0; i<newLength; i++) {
        pvFields[i]->setParentAndName(this,fieldNames[i]);
    }
    fixParentStructure();
}
コード例 #2
0
PVStructure::shared_pointer ValueBuilder::buildPVStructure() const
{
    if(parent)
        THROW_EXCEPTION2(std::logic_error, "Only top level structure may be built.  Missing endNested() ?");

    StructureConstPtr type;
    {
        FieldBuilderPtr tbuild(getFieldCreate()->createFieldBuilder());

        child_struct::buildStruct(*this, tbuild);

        type = tbuild->createStructure();
    }

    PVStructure::shared_pointer root(type->build());

    child_struct::storeStruct(*this, root);

    return root;
}
コード例 #3
0
RecordListRecordPtr RecordListRecord::create(
    std::string const & recordName)
{
    FieldCreatePtr fieldCreate = getFieldCreate();
    PVDataCreatePtr pvDataCreate = getPVDataCreate();
    StructureConstPtr  topStructure = fieldCreate->createFieldBuilder()->
        addNestedStructure("argument")->
            add("database",pvString)->
            add("regularExpression",pvString)->
            endNested()->
        addNestedStructure("result") ->
            add("status",pvString) ->
            addArray("names",pvString) ->
            endNested()->
        createStructure();
    PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
    RecordListRecordPtr pvRecord(
        new RecordListRecord(recordName,pvStructure));
    if(!pvRecord->init()) pvRecord.reset();
    return pvRecord;
}
コード例 #4
0
ExampleHelloPtr ExampleHello::create(
    string const & recordName)
{
    StandardFieldPtr standardField = getStandardField();
    FieldCreatePtr fieldCreate = getFieldCreate();
    PVDataCreatePtr pvDataCreate = getPVDataCreate();
    StructureConstPtr  topStructure = fieldCreate->createFieldBuilder()->
        addNestedStructure("argument")->
            add("value",pvString)->
            endNested()->
        addNestedStructure("result") ->
            add("value",pvString) ->
            add("timeStamp",standardField->timeStamp()) ->
            endNested()->
        createStructure();
    PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);

    ExampleHelloPtr pvRecord(
        new ExampleHello(recordName,pvStructure));
    if(!pvRecord->init()) pvRecord.reset();
    return pvRecord;
}
コード例 #5
0
void PVStructure::fixParentStructure()
{
    PVStructure *parent = getParent();
    if(parent==NULL) return;
    StructureConstPtr parentStructure = parent->structurePtr;
    String fieldName = getFieldName();
    size_t index = parentStructure->getFieldIndex(fieldName);
    StringArray const &fieldNames = parentStructure->getFieldNames();
    size_t num = fieldNames.size();
    FieldConstPtrArray fields(num);
    FieldConstPtrArray const & oldFields = parentStructure->getFields();
    for(size_t i=0; i< num; i++) {
        if(i==index) {
            fields[i] = structurePtr;
        } else {
            fields[i] = oldFields[i];
        }
    }
    FieldConstPtr field = getFieldCreate()->createStructure(
        parentStructure->getID(),fieldNames,fields);
    parent->replaceField(field);
    parent->fixParentStructure();
}
コード例 #6
0
/**
 * Creates an NTURI request.
 *
 * @param  path          the value of the NTURI path field
 * @param  fieldnames    the names of fields in the NTURI query
 * @return values        the values of fields in the NTURI query
 */
PVStructurePtr createRequest(const std::string & path,
    const std::vector<std::string> & fieldnames,
    const std::vector<std::string> & values)
{    
    StructureConstPtr archiverStructure = makeRequestStructure(*getFieldCreate(), fieldnames);
    PVStructurePtr request(getPVDataCreate()->createPVStructure(archiverStructure));

    // set scheme.
    request->getStringField("scheme")->put("pva");

    // set path.
    request->getStringField("path")->put(path);

    // Set query.
    PVStructurePtr query = request->getStructureField("query");

    for (size_t i = 0; i < fieldnames.size(); ++i)
    {
        query->getStringField(fieldnames[i])->put(values[i]);
    }
 
    return request;
}
コード例 #7
0
void PVStructure::removePVField(String const &fieldName)
{
    PVFieldPtr pvField = getSubField(fieldName);
    if(pvField.get()==NULL) {
        String message("removePVField ");
        message +=  fieldName + " does not exist";
        this->message(message, errorMessage);
        return;
    }
    size_t origLength = pvFields.size();
    size_t newLength = origLength - 1;
    PVFieldPtrArray const & origPVFields = pvFields;
    FieldConstPtrArray origFields = structurePtr->getFields();
    PVFieldPtrArray newPVFields;
    newPVFields.reserve(newLength);
    StringArray newFieldNames;
    newFieldNames.reserve(newLength);
    FieldConstPtrArray fields;
    fields.reserve(newLength);
    for(size_t i=0; i<origLength; i++) {
        if(origPVFields[i]!=pvField) {
            newFieldNames.push_back(origPVFields[i]->getFieldName());
            newPVFields.push_back(origPVFields[i]);
            fields.push_back(origFields[i]);
        }
    }
    PVFieldPtrArray * xxx = const_cast<PVFieldPtrArray *>(&pvFields);
    xxx->swap(newPVFields);
    FieldConstPtr field = getFieldCreate()->createStructure(
        structurePtr->getID(),newFieldNames,fields);
    replaceField(field);
    structurePtr = static_pointer_cast<const Structure>(field);
    StringArray fieldNames = structurePtr->getFieldNames();
    for(size_t i=0; i<newLength; i++) {
        pvFields[i]->setParentAndName(this,fieldNames[i]);
    }
}
コード例 #8
0
PVStructurePtr createPowerSupply()
{
    FieldCreatePtr fieldCreate = getFieldCreate();
    StandardFieldPtr standardField = getStandardField();
    PVDataCreatePtr pvDataCreate = getPVDataCreate();

    return pvDataCreate->createPVStructure(
        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());
}
コード例 #9
0
PVDataCreate::PVDataCreate()
: fieldCreate(getFieldCreate())
{ }
コード例 #10
0
namespace epics { namespace pvaClient {

static FieldCreatePtr fieldCreate = getFieldCreate();
static CreateRequest::shared_pointer  createRequestPvt = CreateRequest::create();

PvaClientMultiChannelPtr PvaClientMultiChannel::create(
   PvaClientPtr const &pvaClient,
   epics::pvData::shared_vector<const string> const & channelNames,
   string const & providerName,
   size_t maxNotConnected)
{
    return PvaClientMultiChannelPtr(
        new PvaClientMultiChannel(pvaClient,channelNames,providerName,maxNotConnected));
}


PvaClientMultiChannel::PvaClientMultiChannel(
    PvaClientPtr const &pvaClient,
    epics::pvData::shared_vector<const string> const & channelName,
    string const & providerName,
    size_t maxNotConnected)
: pvaClient(pvaClient),
  channelName(channelName),
  providerName(providerName),
  maxNotConnected(maxNotConnected),
  numChannel(channelName.size()),
  numConnected(0),
  pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())),
  isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)),
  createRequest(CreateRequest::create()),
  isDestroyed(false)
{
}

PvaClientMultiChannel::~PvaClientMultiChannel()
{
    destroy();
}

void PvaClientMultiChannel::destroy()
{
    {
        Lock xx(mutex);
        if(isDestroyed) return;
        isDestroyed = true;
    }
    pvaClientChannelArray.clear();
}

void PvaClientMultiChannel::checkConnected()
{
    if(numConnected==0){
        Status status = connect(3.0);
        if(status.isOK()) return;
        throw std::runtime_error("pvaClientMultiChannel connect failure");
    }
}

epics::pvData::shared_vector<const string> PvaClientMultiChannel::getChannelNames()
{
    if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
    return channelName;
}

Status PvaClientMultiChannel::connect(double timeout)
{
    if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
    for(size_t i=0; i< numChannel; ++i) {
        pvaClientChannelArray[i] = pvaClient->createChannel(channelName[i],providerName);
        pvaClientChannelArray[i]->issueConnect();
    }
    Status returnStatus = Status::Ok;
    Status status = Status::Ok;
    size_t numBad = 0;
    for(size_t i=0; i< numChannel; ++i) {
	if(numBad==0) {
            status = pvaClientChannelArray[i]->waitConnect(timeout);
        } else {
            status = pvaClientChannelArray[i]->waitConnect(.001);
        }
        if(status.isOK()) {
            ++numConnected;
            isConnected[i] = true;
            continue;
        }
        if(returnStatus.isOK()) returnStatus = status;
        ++numBad;
        if(numBad>maxNotConnected) break;
    }
    return numBad>maxNotConnected ? returnStatus : Status::Ok;
}


bool PvaClientMultiChannel::allConnected()
{
    if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
    return (numConnected==numChannel) ? true : false;
}

bool PvaClientMultiChannel::connectionChange()
{
    if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
    for(size_t i=0; i<numChannel; ++i) {
         PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
         Channel::shared_pointer channel = pvaClientChannel->getChannel();
         Channel::ConnectionState stateNow = channel->getConnectionState();
         bool connectedNow = stateNow==Channel::CONNECTED ? true : false;
         if(connectedNow!=isConnected[i]) return true;
    }
    return false;
}

epics::pvData::shared_vector<epics::pvData::boolean>  PvaClientMultiChannel::getIsConnected()
{
    if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
    for(size_t i=0; i<numChannel; ++i) {
         PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
         if(!pvaClientChannel) {
              isConnected[i] = false;
              continue;
         }
         Channel::shared_pointer channel = pvaClientChannel->getChannel();
         Channel::ConnectionState stateNow = channel->getConnectionState();
         isConnected[i] = (stateNow==Channel::CONNECTED) ? true : false;
    }
    return isConnected;
}

PvaClientChannelArray PvaClientMultiChannel::getPvaClientChannelArray()
{
    if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
    return pvaClientChannelArray;
}

PvaClientPtr PvaClientMultiChannel::getPvaClient()
{
    if(isDestroyed) throw std::runtime_error("pvaClientMultiChannel was destroyed");
    return pvaClient;
}

 

PvaClientMultiGetDoublePtr PvaClientMultiChannel::createGet()
{
    checkConnected();
    return PvaClientMultiGetDouble::create(getPtrSelf(),pvaClientChannelArray);
}


PvaClientMultiPutDoublePtr PvaClientMultiChannel::createPut()
{
    checkConnected();
    return PvaClientMultiPutDouble::create(getPtrSelf(),pvaClientChannelArray);
}


PvaClientMultiMonitorDoublePtr PvaClientMultiChannel::createMonitor()
{
    checkConnected();
     return PvaClientMultiMonitorDouble::create(getPtrSelf(), pvaClientChannelArray);
}

PvaClientNTMultiPutPtr PvaClientMultiChannel::createNTPut()
{
    checkConnected();
    return PvaClientNTMultiPut::create(getPtrSelf(), pvaClientChannelArray);
}


PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet()
{
    return createNTGet("value,alarm,timeStamp");
}

PvaClientNTMultiGetPtr PvaClientMultiChannel::createNTGet(std::string const &request)
{
    checkConnected();
    PVStructurePtr pvRequest = createRequest->createRequest(request);
    if(!pvRequest) {
        string message = " PvaClientMultiChannel::createNTGet invalid pvRequest: "
             + createRequest->getMessage();
        throw std::runtime_error(message);
    }
    return PvaClientNTMultiGet::create(getPtrSelf(), pvaClientChannelArray,pvRequest);
}


PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor()
{
    return createNTMonitor("value,alarm,timeStamp");
}

PvaClientNTMultiMonitorPtr PvaClientMultiChannel::createNTMonitor(std::string const &request)
{
    checkConnected();
    PVStructurePtr pvRequest = createRequest->createRequest(request);
    if(!pvRequest) {
        string message = " PvaClientMultiChannel::createNTMonitor invalid pvRequest: "
             + createRequest->getMessage();
        throw std::runtime_error(message);
    }
    return PvaClientNTMultiMonitor::create(getPtrSelf(), pvaClientChannelArray,pvRequest);
}


}}
コード例 #11
0
StandardPVField::StandardPVField()
: standardField(getStandardField()),
  fieldCreate(getFieldCreate()),
  pvDataCreate(getPVDataCreate()),
  notImplemented("not implemented")
{}
コード例 #12
0
namespace epics { namespace nt { 


static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static NTFieldPtr ntField = NTField::get();

namespace detail {

NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::value(UnionConstPtr valuePtr)
{
    valueType = valuePtr;
    return shared_from_this();
}


NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addDescriptor()
{
    descriptor = true;
    return shared_from_this();
}

NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addAlarm()
{
    alarm = true;
    return shared_from_this();
}

NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addTimeStamp()
{
    timeStamp = true;
    return shared_from_this();
}

NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addSeverity()
{
    severity = true;
    return shared_from_this();
}

NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addStatus()
{
    status = true;
    return shared_from_this();
}

NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addMessage()
{
    message = true;
    return shared_from_this();
}

NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addSecondsPastEpoch()
{
    secondsPastEpoch = true;
    return shared_from_this();
}

NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addNanoseconds()
{
    nanoseconds = true;
    return shared_from_this();
}

NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::addUserTag()
{
    userTag = true;
    return shared_from_this();
}

StructureConstPtr NTMultiChannelBuilder::createStructure()
{
    StandardFieldPtr standardField = getStandardField();
    size_t nfields = 3;
    size_t extraCount = extraFieldNames.size();
    nfields += extraCount;
    if(descriptor) ++nfields;
    if(alarm) ++nfields;
    if(timeStamp) ++nfields;
    if(severity) ++nfields;
    if(status) ++nfields;
    if(message) ++nfields;
    if(secondsPastEpoch) ++nfields;
    if(nanoseconds) ++nfields;
    if(userTag) ++nfields;
    FieldConstPtrArray fields(nfields);
    StringArray names(nfields);
    size_t ind = 0;
    names[ind] = "value";
    if(valueType) {
        fields[ind++] =  fieldCreate->createUnionArray(valueType);
    } else {
        fields[ind++] =  fieldCreate->createVariantUnionArray();
    }
    names[ind] = "channelName";
    fields[ind++] =  fieldCreate->createScalarArray(pvString);
    names[ind] = "isConnected";
    fields[ind++] =  fieldCreate->createScalarArray(pvBoolean);
    if(timeStamp) {
        names[ind] = "timeStamp";
        fields[ind++] = standardField->timeStamp();
    }
    if(alarm) {
        names[ind] = "alarm";
        fields[ind++] = standardField->alarm();
    }
    if(descriptor) {
        names[ind] = "descriptor";
        fields[ind++] = fieldCreate->createScalar(pvString);
    }
    if(severity) {
        names[ind] = "severity";
        fields[ind++] = fieldCreate->createScalarArray(pvInt);
    }
    if(status) {
        names[ind] = "status";
        fields[ind++] = fieldCreate->createScalarArray(pvInt);
    }
    if(message) {
        names[ind] = "message";
        fields[ind++] = fieldCreate->createScalarArray(pvString);
    }
    if(secondsPastEpoch) {
        names[ind] = "secondsPastEpoch";
        fields[ind++] = fieldCreate->createScalarArray(pvLong);
    }
    if(nanoseconds) {
        names[ind] = "nanoseconds";
        fields[ind++] = fieldCreate->createScalarArray(pvInt);
    }
    if(userTag) {
        names[ind] = "userTag";
        fields[ind++] = fieldCreate->createScalarArray(pvInt);
    }
    for (size_t i = 0; i< extraCount; i++) {
        names[ind] = extraFieldNames[i];
        fields[ind++] = extraFields[i];
    }

    StructureConstPtr st = fieldCreate->createStructure(NTMultiChannel::URI,names,fields);
    reset();
    return st;
}

PVStructurePtr NTMultiChannelBuilder::createPVStructure()
{
    return pvDataCreate->createPVStructure(createStructure());
}

NTMultiChannelPtr NTMultiChannelBuilder::create()
{
    return NTMultiChannelPtr(new NTMultiChannel(createPVStructure()));
}

NTMultiChannelBuilder::NTMultiChannelBuilder()
{
    reset();
}

void NTMultiChannelBuilder::reset()
{
    valueType.reset();
    extraFieldNames.clear();
    extraFields.clear();
    descriptor = false;
    alarm = false;
    timeStamp = false;
    severity = false;
    status = false;
    message = false;
    secondsPastEpoch = false;
    nanoseconds = false;
    userTag = false;
}


NTMultiChannelBuilder::shared_pointer NTMultiChannelBuilder::add(string const & name, FieldConstPtr const & field)
{
    extraFields.push_back(field); extraFieldNames.push_back(name);
    return shared_from_this();
}

}

const std::string NTMultiChannel::URI("epics:nt/NTMultiChannel:1.0");

NTMultiChannel::shared_pointer NTMultiChannel::wrap(PVStructurePtr const & structure)
{
    if(!isCompatible(structure)) return shared_pointer();
    return wrapUnsafe(structure);
}

NTMultiChannel::shared_pointer NTMultiChannel::wrapUnsafe(PVStructurePtr const & structure)
{
    return shared_pointer(new NTMultiChannel(structure));
}

bool NTMultiChannel::is_a(StructureConstPtr const &structure)
{
    return NTUtils::is_a(structure->getID(), URI);
}

bool NTMultiChannel::isCompatible(PVStructurePtr const &pvStructure)
{
    if(!pvStructure) return false;
    PVUnionArrayPtr pvValue = pvStructure->getSubField<PVUnionArray>("value");
    if(!pvValue) return false;
    PVFieldPtr pvField = pvStructure->getSubField("descriptor");
    if(pvField && !pvStructure->getSubField<PVString>("descriptor")) return false;
    pvField = pvStructure->getSubField("alarm");
    if(pvField && !ntField->isAlarm(pvField->getField())) return false;
    pvField = pvStructure->getSubField("timeStamp");
    if(pvField && !ntField->isTimeStamp(pvField->getField())) return false;
    pvField = pvStructure->getSubField("severity");
    if(pvField && !pvStructure->getSubField<PVIntArray>("severity")) return false;
    pvField = pvStructure->getSubField("status");
    if(pvField && !pvStructure->getSubField<PVIntArray>("status")) return false;
    pvField = pvStructure->getSubField("message");
    if(pvField && !pvStructure->getSubField<PVStringArray>("message")) return false;
    pvField = pvStructure->getSubField("secondsPastEpoch");
    if(pvField && !pvStructure->getSubField<PVLongArray>("secondsPastEpoch")) return false;
    pvField = pvStructure->getSubField("nanoseconds");
    if(pvField && !pvStructure->getSubField<PVIntArray>("nanoseconds")) return false;
    pvField = pvStructure->getSubField("userTag");
    if(pvField && !pvStructure->getSubField<PVIntArray>("userTag")) return false;
    return true;
}

NTMultiChannelBuilderPtr NTMultiChannel::createBuilder()
{
    return NTMultiChannelBuilderPtr(new detail::NTMultiChannelBuilder());
}


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")),
  pvIsConnected(pvStructure->getSubField<PVBooleanArray>("isConnected")),
  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")),
  pvUserTag(pvStructure->getSubField<PVIntArray>("userTag")),
  pvDescriptor(pvStructure->getSubField<PVString>("descriptor"))
{
}


void  NTMultiChannel::attachTimeStamp(PVTimeStamp &pv) const
{
    if(!pvTimeStamp) return;
    pv.attach(pvTimeStamp);
}

void  NTMultiChannel::attachAlarm(PVAlarm &pv) const
{
    if(!pvAlarm) return;
    pv.attach(pvAlarm);
}

}}
コード例 #13
0
namespace epics { namespace pvaClient { 

static ConvertPtr convert = getConvert();
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static StandardFieldPtr standardField = getStandardField();


PvaClientMultiMonitorDoublePtr PvaClientMultiMonitorDouble::create(
    PvaClientMultiChannelPtr const &pvaMultiChannel,
    PvaClientChannelArray const &pvaClientChannelArray)
{
    PvaClientMultiMonitorDoublePtr pvaClientMultiMonitorDouble(
         new PvaClientMultiMonitorDouble(pvaMultiChannel,pvaClientChannelArray));
    return pvaClientMultiMonitorDouble;
}

PvaClientMultiMonitorDouble::PvaClientMultiMonitorDouble(
     PvaClientMultiChannelPtr const &pvaClientMultiChannel,
     PvaClientChannelArray const &pvaClientChannelArray)
: pvaClientMultiChannel(pvaClientMultiChannel),
  pvaClientChannelArray(pvaClientChannelArray),
  nchannel(pvaClientChannelArray.size()),
  doubleValue(shared_vector<double>(nchannel,epicsNAN)),
  pvaClientMonitor(std::vector<PvaClientMonitorPtr>(nchannel,PvaClientMonitorPtr())),
  isMonitorConnected(false),
  isDestroyed(false)
{
}

PvaClientMultiMonitorDouble::~PvaClientMultiMonitorDouble()
{
    destroy();
}

void PvaClientMultiMonitorDouble::destroy()
{
    {
        Lock xx(mutex);
        if(isDestroyed) return;
        isDestroyed = true;
    }
    pvaClientChannelArray.clear();
}

void PvaClientMultiMonitorDouble::connect()
{
    shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
    string request = "value";
    for(size_t i=0; i<nchannel; ++i)
    {
         if(isConnected[i]) {
               pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(request);
               pvaClientMonitor[i]->issueConnect();
         }
    }
    for(size_t i=0; i<nchannel; ++i)
    {
         if(isConnected[i]) {
               Status status = pvaClientMonitor[i]->waitConnect();
               if(status.isOK()) continue;
               string message = string("channel ") + pvaClientChannelArray[i]->getChannelName()
                   + " PvaChannelMonitor::waitConnect " + status.getMessage();
               throw std::runtime_error(message);
         }
    }
     for(size_t i=0; i<nchannel; ++i)
    {
         if(isConnected[i]) pvaClientMonitor[i]->start();
    }
    isMonitorConnected = true;
}

bool PvaClientMultiMonitorDouble::poll()
{
    if(!isMonitorConnected){
         connect();
         epicsThreadSleep(.01);
    }
    bool result = false;
    shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
    for(size_t i=0; i<nchannel; ++i)
    {
         if(isConnected[i]) {
              if(pvaClientMonitor[i]->poll()) {
                   doubleValue[i] = pvaClientMonitor[i]->getData()->getDouble();
                   pvaClientMonitor[i]->releaseEvent();
                   result = true;
              }
         }
    }
    return result;
}

bool PvaClientMultiMonitorDouble::waitEvent(double waitForEvent)
{
    if(poll()) return true;
    TimeStamp start;
    start.getCurrent();
    TimeStamp now;
    while(true) {
          epicsThreadSleep(.1);
          if(poll()) return true;
          now.getCurrent();
          double diff = TimeStamp::diff(now,start);
          if(diff>=waitForEvent) break;
    }
    return false;
}

epics::pvData::shared_vector<double> PvaClientMultiMonitorDouble::get()
{
    return doubleValue;
}


}}
コード例 #14
0
namespace epics { namespace pvaClient { 

static ConvertPtr convert = getConvert();
static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
static StandardFieldPtr standardField = getStandardField();
static CreateRequest::shared_pointer  createRequest = CreateRequest::create();


PvaClientMultiPutDoublePtr PvaClientMultiPutDouble::create(
    PvaClientMultiChannelPtr const &pvaMultiChannel,
    PvaClientChannelArray const &pvaClientChannelArray)
{
    PvaClientMultiPutDoublePtr pvaClientMultiPutDouble(
         new PvaClientMultiPutDouble(pvaMultiChannel,pvaClientChannelArray));
    return pvaClientMultiPutDouble;
}

PvaClientMultiPutDouble::PvaClientMultiPutDouble(
     PvaClientMultiChannelPtr const &pvaClientMultiChannel,
     PvaClientChannelArray const &pvaClientChannelArray)
: pvaClientMultiChannel(pvaClientMultiChannel),
  pvaClientChannelArray(pvaClientChannelArray),
  nchannel(pvaClientChannelArray.size()),
  pvaClientPut(std::vector<PvaClientPutPtr>(nchannel,PvaClientPutPtr())),
  isPutConnected(false),
  isDestroyed(false)
{
}



PvaClientMultiPutDouble::~PvaClientMultiPutDouble()
{
    destroy();
}

void PvaClientMultiPutDouble::destroy()
{
    {
        Lock xx(mutex);
        if(isDestroyed) return;
        isDestroyed = true;
    }
    pvaClientChannelArray.clear();
}

void PvaClientMultiPutDouble::connect()
{
    shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
    for(size_t i=0; i<nchannel; ++i)
    {
         if(isConnected[i]) {
               pvaClientPut[i] = pvaClientChannelArray[i]->createPut();
               pvaClientPut[i]->issueConnect();
         }
    }
    for(size_t i=0; i<nchannel; ++i)
    {
         if(isConnected[i]) {
               Status status = pvaClientPut[i]->waitConnect();
               if(status.isOK()) continue;
               string message = string("channel ") + pvaClientChannelArray[i]->getChannelName()
                   + " PvaChannelPut::waitConnect " + status.getMessage();
               throw std::runtime_error(message);
         }
    }
    isPutConnected = true;
}

void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &data)
{
    if(!isPutConnected) connect();
    if(data.size()!=nchannel) {
         throw std::runtime_error("data has wrong size");
    }
    shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
    for(size_t i=0; i<nchannel; ++i)
    {
         if(isConnected[i]) {
               PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure();
               PVScalarPtr pvValue = pvTop->getSubField<PVScalar>("value");
               convert->fromDouble(pvValue,data[i]);
               pvaClientPut[i]->issuePut();
         }
         if(isConnected[i]) {
              Status status = pvaClientPut[i]->waitPut();
              if(status.isOK())  continue;
              string message = string("channel ") + pvaClientChannelArray[i]->getChannelName()
                   + " PvaChannelPut::waitPut " + status.getMessage();
              throw std::runtime_error(message);
         }
    }
}

}}
コード例 #15
0
StandardField::StandardField()
:  fieldCreate(getFieldCreate()),
   notImplemented("not implemented"),
   valueFieldName("value")
{}
コード例 #16
0
namespace detail {

static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();

static Mutex mutex;

StructureConstPtr NTNDArrayBuilder::createStructure()
{
    enum
    {
        DISCRIPTOR_INDEX,
        TIMESTAMP_INDEX,
        ALARM_INDEX,
        DISPLAY_INDEX
    };

    const size_t NUMBER_OF_INDICES = DISPLAY_INDEX+1;
    const size_t NUMBER_OF_STRUCTURES = 1 << NUMBER_OF_INDICES;

    Lock xx(mutex);

    static StructureConstPtr ntndarrayStruc[NUMBER_OF_STRUCTURES];
    static UnionConstPtr valueType;
    static StructureConstPtr codecStruc;
    static StructureConstPtr dimensionStruc;
    static StructureConstPtr attributeStruc;

    StructureConstPtr returnedStruc;

    size_t index = 0;
    if (descriptor) index  |= 1 << DISCRIPTOR_INDEX;
    if (timeStamp)  index  |= 1 << TIMESTAMP_INDEX;
    if (alarm)      index  |= 1 << ALARM_INDEX;
    if (display)    index  |= 1 << DISPLAY_INDEX;

    bool isExtended = !extraFieldNames.empty();

    if (isExtended || !ntndarrayStruc[index])
    {
        StandardFieldPtr standardField = getStandardField();
        FieldBuilderPtr fb = fieldCreate->createFieldBuilder();

        if (!valueType)
        {
            for (int i = pvBoolean; i < pvString; ++i)
            {
                ScalarType st = static_cast<ScalarType>(i);
                fb->addArray(std::string(ScalarTypeFunc::name(st)) + "Value", st);
            }
            valueType = fb->createUnion();                
        }

        if (!codecStruc)
        {
            codecStruc = fb->setId("codec_t")->
                add("name", pvString)->
                add("parameters", fieldCreate->createVariantUnion())->
                createStructure();
        }

        if (!dimensionStruc)
        {
            dimensionStruc = fb->setId("dimension_t")->
                add("size", pvInt)->
                add("offset",  pvInt)->
                add("fullSize",  pvInt)->
                add("binning",  pvInt)->
                add("reverse",  pvBoolean)->
                createStructure();
        }

        if (!attributeStruc)
        {
            attributeStruc = NTNDArrayAttribute::createBuilder()->createStructure();
        }

        fb->setId(NTNDArray::URI)->
            add("value", valueType)->
            add("codec", codecStruc)->
            add("compressedSize", pvLong)->
            add("uncompressedSize", pvLong)->
            addArray("dimension", dimensionStruc)->
            add("uniqueId", pvInt)->
            add("dataTimeStamp", standardField->timeStamp())->
            addArray("attribute", attributeStruc);

        if (descriptor)
            fb->add("descriptor", pvString);

        if (alarm)
            fb->add("alarm", standardField->alarm());

        if (timeStamp)
            fb->add("timeStamp", standardField->timeStamp());

        if (display)
            fb->add("display", standardField->display());

        size_t extraCount = extraFieldNames.size();
        for (size_t i = 0; i< extraCount; i++)
            fb->add(extraFieldNames[i], extraFields[i]);

        returnedStruc = fb->createStructure();

        if (!isExtended)
            ntndarrayStruc[index] = returnedStruc; 
    }
    else
    {
        return ntndarrayStruc[index];
    }

    return returnedStruc;
}

NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDescriptor()
{
    descriptor = true;
    return shared_from_this();
}

NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addAlarm()
{
    alarm = true;
    return shared_from_this();
}

NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addTimeStamp()
{
    timeStamp = true;
    return shared_from_this();
}

NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDisplay()
{
    display = true;
    return shared_from_this();
}

PVStructurePtr NTNDArrayBuilder::createPVStructure()
{
    return getPVDataCreate()->createPVStructure(createStructure());
}

NTNDArrayPtr NTNDArrayBuilder::create()
{
    return NTNDArrayPtr(new NTNDArray(createPVStructure()));
}

NTNDArrayBuilder::NTNDArrayBuilder()
{
    reset();
}

void NTNDArrayBuilder::reset()
{
    descriptor = false;
    timeStamp = false;
    alarm = false;
    display = false;
    extraFieldNames.clear();
    extraFields.clear();
}

NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::add(string const & name, FieldConstPtr const & field)
{
    extraFields.push_back(field); extraFieldNames.push_back(name);
    return shared_from_this();
}


}
コード例 #17
0
namespace epics { namespace nt {

static NTFieldPtr ntField = NTField::get();


namespace detail {

static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();

static Mutex mutex;

StructureConstPtr NTNDArrayBuilder::createStructure()
{
    enum
    {
        DISCRIPTOR_INDEX,
        TIMESTAMP_INDEX,
        ALARM_INDEX,
        DISPLAY_INDEX
    };

    const size_t NUMBER_OF_INDICES = DISPLAY_INDEX+1;
    const size_t NUMBER_OF_STRUCTURES = 1 << NUMBER_OF_INDICES;

    Lock xx(mutex);

    static StructureConstPtr ntndarrayStruc[NUMBER_OF_STRUCTURES];
    static UnionConstPtr valueType;
    static StructureConstPtr codecStruc;
    static StructureConstPtr dimensionStruc;
    static StructureConstPtr attributeStruc;

    StructureConstPtr returnedStruc;

    size_t index = 0;
    if (descriptor) index  |= 1 << DISCRIPTOR_INDEX;
    if (timeStamp)  index  |= 1 << TIMESTAMP_INDEX;
    if (alarm)      index  |= 1 << ALARM_INDEX;
    if (display)    index  |= 1 << DISPLAY_INDEX;

    bool isExtended = !extraFieldNames.empty();

    if (isExtended || !ntndarrayStruc[index])
    {
        StandardFieldPtr standardField = getStandardField();
        FieldBuilderPtr fb = fieldCreate->createFieldBuilder();

        if (!valueType)
        {
            for (int i = pvBoolean; i < pvString; ++i)
            {
                ScalarType st = static_cast<ScalarType>(i);
                fb->addArray(std::string(ScalarTypeFunc::name(st)) + "Value", st);
            }
            valueType = fb->createUnion();                
        }

        if (!codecStruc)
        {
            codecStruc = fb->setId("codec_t")->
                add("name", pvString)->
                add("parameters", fieldCreate->createVariantUnion())->
                createStructure();
        }

        if (!dimensionStruc)
        {
            dimensionStruc = fb->setId("dimension_t")->
                add("size", pvInt)->
                add("offset",  pvInt)->
                add("fullSize",  pvInt)->
                add("binning",  pvInt)->
                add("reverse",  pvBoolean)->
                createStructure();
        }

        if (!attributeStruc)
        {
            attributeStruc = NTNDArrayAttribute::createBuilder()->createStructure();
        }

        fb->setId(NTNDArray::URI)->
            add("value", valueType)->
            add("codec", codecStruc)->
            add("compressedSize", pvLong)->
            add("uncompressedSize", pvLong)->
            addArray("dimension", dimensionStruc)->
            add("uniqueId", pvInt)->
            add("dataTimeStamp", standardField->timeStamp())->
            addArray("attribute", attributeStruc);

        if (descriptor)
            fb->add("descriptor", pvString);

        if (alarm)
            fb->add("alarm", standardField->alarm());

        if (timeStamp)
            fb->add("timeStamp", standardField->timeStamp());

        if (display)
            fb->add("display", standardField->display());

        size_t extraCount = extraFieldNames.size();
        for (size_t i = 0; i< extraCount; i++)
            fb->add(extraFieldNames[i], extraFields[i]);

        returnedStruc = fb->createStructure();

        if (!isExtended)
            ntndarrayStruc[index] = returnedStruc; 
    }
    else
    {
        return ntndarrayStruc[index];
    }

    return returnedStruc;
}

NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDescriptor()
{
    descriptor = true;
    return shared_from_this();
}

NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addAlarm()
{
    alarm = true;
    return shared_from_this();
}

NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addTimeStamp()
{
    timeStamp = true;
    return shared_from_this();
}

NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDisplay()
{
    display = true;
    return shared_from_this();
}

PVStructurePtr NTNDArrayBuilder::createPVStructure()
{
    return getPVDataCreate()->createPVStructure(createStructure());
}

NTNDArrayPtr NTNDArrayBuilder::create()
{
    return NTNDArrayPtr(new NTNDArray(createPVStructure()));
}

NTNDArrayBuilder::NTNDArrayBuilder()
{
    reset();
}

void NTNDArrayBuilder::reset()
{
    descriptor = false;
    timeStamp = false;
    alarm = false;
    display = false;
    extraFieldNames.clear();
    extraFields.clear();
}

NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::add(string const & name, FieldConstPtr const & field)
{
    extraFields.push_back(field); extraFieldNames.push_back(name);
    return shared_from_this();
}


}

const std::string NTNDArray::URI("epics:nt/NTNDArray:1.0");
const std::string ntAttrStr("epics:nt/NTAttribute:1.0");

static FieldCreatePtr fieldCreate = getFieldCreate();
static PVDataCreatePtr pvDataCreate = getPVDataCreate();

class NTValueType
{
public:
    static bool isCompatible(UnionConstPtr const &u)
    {
        if(!u.get()) return false;

        if (u->getID() != Union::defaultId()) return false;
        if (u->isVariant()) return false;

        for (int i = pvBoolean; i != pvString; ++i)
        {
            ScalarType scalarType = static_cast<ScalarType>(i);
            std::string name(ScalarTypeFunc::name(scalarType));
            name += "Value";
            ScalarArrayConstPtr scalarField = u->getField<ScalarArray>(name);
            if (scalarField.get() == 0 ||
                    scalarField->getElementType() != scalarType)
                return false;
        }

        return true;
    }
};

class NTCodec
{
public:
    static bool isCompatible(StructureConstPtr const &structure)
    {
        if(!structure.get()) return false;

        if (structure->getID() != "codec_t") return false;

        ScalarConstPtr scalarField = structure->getField<Scalar>("name");
        if (scalarField.get() == 0 || scalarField->getScalarType() != pvString)
            return false;

        UnionConstPtr paramField = structure->getField<Union>("parameters");
        if (paramField.get() == 0 || !paramField->isVariant())
            return false;

        return true;
    }
};


class NTDimension
{
public:
    static bool isCompatible(StructureConstPtr const &structure)
    {
        if(!structure.get()) return false;

        if (structure->getID() != "dimension_t") return false;

        ScalarConstPtr scalarField = structure->getField<Scalar>("size");
        if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt)
            return false;

        scalarField = structure->getField<Scalar>("offset");
        if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt)
            return false;

        scalarField = structure->getField<Scalar>("fullSize");
        if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt)
            return false;

        scalarField = structure->getField<Scalar>("binning");
        if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt)
            return false;

        scalarField = structure->getField<Scalar>("reverse");
        if (scalarField.get() == 0 || scalarField->getScalarType() != pvBoolean)
            return false;

        return true;
    }
};

NTNDArray::shared_pointer NTNDArray::wrap(PVStructurePtr const & pvStructure)
{
    if(!isCompatible(pvStructure)) return shared_pointer();
    return wrapUnsafe(pvStructure);
}

NTNDArray::shared_pointer NTNDArray::wrapUnsafe(PVStructurePtr const & pvStructure)
{
    return shared_pointer(new NTNDArray(pvStructure));
}

bool NTNDArray::is_a(StructureConstPtr const & structure)
{
    return NTUtils::is_a(structure->getID(), URI);
}

bool NTNDArray::isCompatible(StructureConstPtr const &structure)
{
    if(!structure.get()) return false;

    UnionConstPtr valueField = structure->getField<Union>("value");
    if(!NTValueType::isCompatible(valueField)) return false;

    StructureConstPtr codecField = structure->getField<Structure>("codec");
    if(!NTCodec::isCompatible(codecField)) return false;

    ScalarConstPtr compressedSizeField = structure->getField<Scalar>("compressedSize");
    if (compressedSizeField.get() == 0)
        return false;

    if (compressedSizeField->getScalarType() != pvLong)
        return false;


    ScalarConstPtr uncompressedSizeField = structure->getField<Scalar>("uncompressedSize");
    if (uncompressedSizeField.get() == 0)
        return false;

    if (uncompressedSizeField->getScalarType() != pvLong)
        return false;

    StructureArrayConstPtr dimensionField = structure->getField<StructureArray>("dimension");
    if (dimensionField.get() == 0)
        return false;
    StructureConstPtr dimElementStruc = dimensionField->getStructure();

    if(!NTDimension::isCompatible(dimElementStruc))
       return false;

    NTFieldPtr ntField = NTField::get();

    StructureConstPtr dataTimeStampField = structure->getField<Structure>(
        "dataTimeStamp");
    if (dataTimeStampField.get() == 0 || !ntField->isTimeStamp(dataTimeStampField))
        return false;


    ScalarConstPtr uniqueIdField = structure->getField<Scalar>("uniqueId");
    if (uniqueIdField.get() == 0)
        return false;

    if (uniqueIdField->getScalarType() != pvInt)
        return false;


    StructureArrayConstPtr attributeField = structure->getField<StructureArray>( "attribute");

    StructureConstPtr attributeElementStruc = attributeField->getStructure();

    if (!NTNDArrayAttribute::isCompatible(attributeElementStruc))
        return false;


    FieldConstPtr field = structure->getField("descriptor");
    if (field.get())
    {
        ScalarConstPtr descriptorField = structure->getField<Scalar>("descriptor");
        if (!descriptorField.get() || descriptorField->getScalarType() != pvString)
            return false;
    }

    field = structure->getField("alarm");
    if (field.get() && !ntField->isAlarm(field))
        return false;

    field = structure->getField("timeStamp");
    if (field.get() && !ntField->isTimeStamp(field))
        return false;

    field = structure->getField("display");
    if (field.get() && !ntField->isDisplay(field))
        return false;

    return true;
}


bool NTNDArray::isCompatible(PVStructurePtr const & pvStructure)
{
    if(!pvStructure.get()) return false;

    return isCompatible(pvStructure->getStructure());
}


bool NTNDArray::isValid()
{
    int64 valueSize = getValueSize();
    int64 compressedSize = getCompressedDataSize()->get();
    if (valueSize != compressedSize)
        return false;

    long expectedUncompressed = getExpectedUncompressedSize();
    long uncompressedSize = getUncompressedDataSize()->get();
    if (uncompressedSize != expectedUncompressed)
        return false;

    std::string codecName = getCodec()->getSubField<PVString>("name")->get();
    if (codecName == "" && valueSize < uncompressedSize)
        return false;

    return true;
}

int64 NTNDArray::getExpectedUncompressedSize()
{
    int64 size = 0;
    PVStructureArrayPtr pvDim = getDimension();

    if (pvDim->getLength() != 0)
    {
        PVStructureArray::const_svector data = pvDim->view();
        size = getValueTypeSize();
        for (PVStructureArray::const_svector::const_iterator it = data.begin();
        it != data.end(); ++it )
        {
            PVStructurePtr dim = *it;
            size *= dim->getSubField<PVInt>("size")->get();
        }
    }

    return size;
}

int64 NTNDArray::getValueSize()
{
    int64 size = 0;
    PVScalarArrayPtr storedValue = getValue()->get<PVScalarArray>();
    if (!storedValue.get())
    {
        size = storedValue->getLength()*getValueTypeSize();
    }
    return size;
}

int64 NTNDArray::getValueTypeSize()
{
    int64 typeSize = 0;
    PVScalarArrayPtr storedValue = getValue()->get<PVScalarArray>();
    if (storedValue.get())
    {
        switch (storedValue->getScalarArray()->getElementType())
        {
        case pvBoolean:
        case pvByte:
        case pvUByte:
            typeSize = 1;
            break;

        case pvShort:
        case pvUShort:
            typeSize = 2;
            break;

        case pvInt:
        case pvUInt:
        case pvFloat:
            typeSize = 4;
            break;

        case pvLong:
        case pvULong:
        case pvDouble:
            typeSize = 8;
            break;

        default:
            break;
        }
    }
    return typeSize;
}

NTNDArrayBuilderPtr NTNDArray::createBuilder()
{
    return NTNDArrayBuilderPtr(new detail::NTNDArrayBuilder());
}


bool NTNDArray::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
{
    PVStructurePtr ts = getTimeStamp();
    if (ts)
        return pvTimeStamp.attach(ts);
    else
        return false;
}

bool NTNDArray::attachDataTimeStamp(PVTimeStamp &pvTimeStamp) const
{
    PVStructurePtr ts = getDataTimeStamp();
    if (ts)
        return pvTimeStamp.attach(ts);
    else
        return false;
}

bool NTNDArray::attachAlarm(PVAlarm &pvAlarm) const
{
    PVStructurePtr al = getAlarm();
    if (al)
        return pvAlarm.attach(al);
    else
        return false;
}

bool NTNDArray::attachDisplay(PVDisplay &pvDisplay) const
{
    PVStructurePtr dp = getDisplay();
    if (dp)
        return pvDisplay.attach(dp);
    else
        return false;
}

PVStructurePtr NTNDArray::getPVStructure() const
{
    return pvNTNDArray;
}

PVUnionPtr NTNDArray::getValue() const
{
    return pvNTNDArray->getSubField<PVUnion>("value");
}

PVStructurePtr NTNDArray::getCodec() const
{
    return pvNTNDArray->getSubField<PVStructure>("codec");
}

PVLongPtr NTNDArray::getCompressedDataSize() const
{
    return pvNTNDArray->getSubField<PVLong>("compressedSize");
}

PVLongPtr NTNDArray::getUncompressedDataSize() const
{
    return pvNTNDArray->getSubField<PVLong>("uncompressedSize");
}

PVStructureArrayPtr NTNDArray::getDimension() const
{
    return pvNTNDArray->getSubField<PVStructureArray>("dimension");
}

PVIntPtr NTNDArray::getUniqueId() const
{
    return pvNTNDArray->getSubField<PVInt>("uniqueId");
}

PVStructurePtr NTNDArray::getDataTimeStamp() const
{
    return pvNTNDArray->getSubField<PVStructure>("dataTimeStamp");
}

PVStructureArrayPtr NTNDArray::getAttribute() const
{
    return pvNTNDArray->getSubField<PVStructureArray>("attribute");
}

PVStringPtr NTNDArray::getDescriptor() const
{
    return pvNTNDArray->getSubField<PVString>("descriptor");
}

PVStructurePtr NTNDArray::getTimeStamp() const
{
    return pvNTNDArray->getSubField<PVStructure>("timeStamp");
}

PVStructurePtr NTNDArray::getAlarm() const
{
    return pvNTNDArray->getSubField<PVStructure>("alarm");
}

PVStructurePtr NTNDArray::getDisplay() const
{
    return pvNTNDArray->getSubField<PVStructure>("display");
}


NTNDArray::NTNDArray(PVStructurePtr const & pvStructure) :
    pvNTNDArray(pvStructure)
{}


}}