8 Commits

Author SHA1 Message Date
Andrew Johnson aba40922e6 Release notes for 4.6.0 2019-07-29 11:47:36 -05:00
Andrew Johnson 2c1cb03cd0 Use new CONFIG_PVACLIENT_VERSION file for SHRLIB_VERSION 2019-07-29 11:46:54 -05:00
Marty Kraimer 4c56116827 Merge pull request #60 from mrkraimer/master
working on issue #56; still problems with monitor
2019-04-26 12:51:02 -04:00
mrkraimer 81f5e25276 working on issue #56; still problems with monitor 2019-04-26 10:09:56 -04:00
Marty Kraimer 703b2224ce Merge pull request #59 from mrkraimer/master
fix issue #57
2019-04-25 05:07:20 -04:00
mrkraimer ed0b1cbf08 fix issue #57 2019-04-24 14:53:18 -04:00
Marty Kraimer 914e382dea Merge pull request #58 from mrkraimer/master
address issue #54
2019-04-24 05:18:19 -04:00
mrkraimer fd77d35b20 address issue #54 2019-04-23 14:04:13 -04:00
10 changed files with 71 additions and 45 deletions
+3
View File
@@ -0,0 +1,3 @@
EPICS_PVACLIENT_MAJOR_VERSION = 4
EPICS_PVACLIENT_MINOR_VERSION = 6
EPICS_PVACLIENT_MAINTENANCE_VERSION = 0
+2
View File
@@ -2,6 +2,8 @@ TOP=..
include $(TOP)/configure/CONFIG include $(TOP)/configure/CONFIG
CFG += CONFIG_PVACLIENT_VERSION
TARGETS = $(CONFIG_TARGETS) TARGETS = $(CONFIG_TARGETS)
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS))) CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
+6
View File
@@ -2,6 +2,12 @@
This document summarizes the changes to the module between releases. This document summarizes the changes to the module between releases.
## Release 4.6.0 (EPICS 7.0.3, Jul 2019)
* pvaClient now handles exceptions from the server properly (issue #54).
* MultiChannel classes now properly handle PV structures that don't have a top-level `value` field (issue #56), and are more tolerant of other missing fields (issue #57).
## Release 4.5.0 (EPICS 7.0.2.2, Apr 2019) ## Release 4.5.0 (EPICS 7.0.2.2, Apr 2019)
Changes have been made for getDouble, putDouble, getDoubleArray, putDoubleArray, getString, putString, getStringArray, and putStringArray. Changes have been made for getDouble, putDouble, getDoubleArray, putDoubleArray, getString, putString, getStringArray, and putStringArray.
+1 -1
View File
@@ -6,7 +6,7 @@ include $(TOP)/configure/CONFIG
LIBRARY += pvaClient LIBRARY += pvaClient
# shared library ABI version. # shared library ABI version.
SHRLIB_VERSION ?= 4.5.0 SHRLIB_VERSION ?= $(EPICS_PVACLIENT_MAJOR_VERSION).$(EPICS_PVACLIENT_MINOR_VERSION).$(EPICS_PVACLIENT_MAINTENANCE_VERSION)
INC += pv/pvaClient.h INC += pv/pvaClient.h
INC += pv/pvaClientMultiChannel.h INC += pv/pvaClientMultiChannel.h
+1
View File
@@ -1813,6 +1813,7 @@ private:
enum RPCState {rpcIdle,rpcActive,rpcComplete}; enum RPCState {rpcIdle,rpcActive,rpcComplete};
RPCState rpcState; RPCState rpcState;
epics::pvData::Status requestStatus;
double responseTimeout; double responseTimeout;
friend class RPCRequesterImpl; friend class RPCRequesterImpl;
}; };
+8 -5
View File
@@ -360,8 +360,10 @@ public:
void connect(); void connect();
/** /**
* @brief Get each channel. * @brief Get each channel.
*
* @param valueOnly use only value for union.
*/ */
void get(); void get(bool valueOnly = true);
/** /**
* @brief Get the data from the last get. * @brief Get the data from the last get.
* @return the pvaClientNTMultiData. * @return the pvaClientNTMultiData.
@@ -476,10 +478,11 @@ public:
/** /**
* @brief Poll each channel. * @brief Poll each channel.
* *
* @param valueOnly use only value for union.
* If any has new data it is used to update the double[]. * If any has new data it is used to update the double[].
* @return (false,true) if (no, at least one) value was updated. * @return (false,true) if (no, at least one) value was updated.
*/ */
bool poll(); bool poll(bool valueOnly = true);
/** /**
* @brief Wait until poll returns true. * @brief Wait until poll returns true.
* @param secondsToWait The time to keep trying. * @param secondsToWait The time to keep trying.
@@ -551,11 +554,12 @@ public:
* @brief Set the timeStamp base for computing deltaTimes. * @brief Set the timeStamp base for computing deltaTimes.
*/ */
void startDeltaTime(); void startDeltaTime();
/** /**
* @brief Update NTMultiChannel fields. * @brief Update NTMultiChannel fields.
*
* @param valueOnly use only value for union.
*/ */
void endDeltaTime(); void endDeltaTime(bool valueOnly = true);
/** /**
* @brief Get the time when the last get was made. * @brief Get the time when the last get was made.
* @return The timeStamp. * @return The timeStamp.
@@ -579,7 +583,6 @@ private:
PvaClientMultiChannelPtr const &pvaNTMultiChannel, PvaClientMultiChannelPtr const &pvaNTMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray, PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest); epics::pvData::PVStructurePtr const & pvRequest);
void setStructure(epics::pvData::StructureConstPtr const & structure,size_t index);
void setPVStructure( void setPVStructure(
epics::pvData::PVStructurePtr const &pvStructure,size_t index); epics::pvData::PVStructurePtr const &pvStructure,size_t index);
+31 -24
View File
@@ -44,10 +44,6 @@ PvaClientNTMultiData::PvaClientNTMultiData(
gotTimeStamp(false) gotTimeStamp(false)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::PvaClientNTMultiData()\n"; if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::PvaClientNTMultiData()\n";
PVFieldPtr pvValue = pvRequest->getSubField("field.value");
if(!pvValue) {
throw std::runtime_error("pvRequest did not specify value");
}
topPVStructure.resize(nchannel); topPVStructure.resize(nchannel);
unionValue.resize(nchannel); unionValue.resize(nchannel);
PVDataCreatePtr pvDataCreate = getPVDataCreate(); PVDataCreatePtr pvDataCreate = getPVDataCreate();
@@ -88,18 +84,6 @@ PvaClientNTMultiData::~PvaClientNTMultiData()
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::~PvaClientNTMultiData()\n"; if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::~PvaClientNTMultiData()\n";
} }
void PvaClientNTMultiData::setStructure(StructureConstPtr const & structure,size_t index)
{
FieldConstPtr field = structure->getField("value");
if(!field) {
string message = "channel "
+ pvaClientChannelArray[index]->getChannel()->getChannelName()
+ " does not have top level value field";
throw std::runtime_error(message);
}
}
void PvaClientNTMultiData::setPVStructure( void PvaClientNTMultiData::setPVStructure(
PVStructurePtr const &pvStructure,size_t index) PVStructurePtr const &pvStructure,size_t index)
{ {
@@ -137,7 +121,7 @@ void PvaClientNTMultiData::startDeltaTime()
} }
void PvaClientNTMultiData::endDeltaTime() void PvaClientNTMultiData::endDeltaTime(bool valueOnly)
{ {
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
{ {
@@ -145,18 +129,41 @@ void PvaClientNTMultiData::endDeltaTime()
if(!pvst) { if(!pvst) {
unionValue[i] = PVUnionPtr(); unionValue[i] = PVUnionPtr();
} else if(unionValue[i]) { } else if(unionValue[i]) {
unionValue[i]->set(pvst->getSubField("value")); if(valueOnly) {
PVFieldPtr pvValue = pvst->getSubField("value");
if(pvValue) {
unionValue[i]->set(pvst->getSubField("value"));
} else {
unionValue[i] = PVUnionPtr();
}
} else {
unionValue[i]->set(pvst);
}
if(gotAlarm) if(gotAlarm)
{ {
severity[i] = pvst->getSubField<PVInt>("alarm.severity")->get(); PVIntPtr pvSeverity = pvst->getSubField<PVInt>("alarm.severity");
status[i] = pvst->getSubField<PVInt>("alarm.status")->get(); PVIntPtr pvStatus = pvst->getSubField<PVInt>("alarm.status");
message[i] = pvst->getSubField<PVString>("alarm.message")->get(); PVStringPtr pvMessage = pvst->getSubField<PVString>("alarm.message");
if(pvSeverity&&pvStatus&&pvMessage) {
severity[i] = pvSeverity->get();
status[i] = pvStatus->get();
message[i] = pvMessage->get();
} else {
severity[i] = undefinedAlarm;
status[i] = undefinedStatus;
message[i] = "no alarm field";
}
} }
if(gotTimeStamp) if(gotTimeStamp)
{ {
secondsPastEpoch[i] = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch")->get(); PVLongPtr pvEpoch = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch");
nanoseconds[i] = pvst->getSubField<PVInt>("timeStamp.nanoseconds")->get(); PVIntPtr pvNano = pvst->getSubField<PVInt>("timeStamp.nanoseconds");
userTag[i] = pvst->getSubField<PVInt>("timeStamp.userTag")->get(); PVIntPtr pvTag = pvst->getSubField<PVInt>("timeStamp.userTag");
if(pvEpoch&&pvNano&&pvTag) {
secondsPastEpoch[i] = pvEpoch->get();
nanoseconds[i] = pvNano->get();
userTag[i] = pvTag->get();
}
} }
} }
} }
+3 -6
View File
@@ -63,13 +63,10 @@ void PvaClientNTMultiGet::connect()
{ {
pvaClientGet.resize(nchannel); pvaClientGet.resize(nchannel);
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
string request = "value";
if(pvRequest->getSubField("field.alarm")) request += ",alarm";
if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
{ {
if(isConnected[i]) { if(isConnected[i]) {
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(request); pvaClientGet[i] = pvaClientChannelArray[i]->createGet(pvRequest);
pvaClientGet[i]->issueConnect(); pvaClientGet[i]->issueConnect();
} }
} }
@@ -86,7 +83,7 @@ void PvaClientNTMultiGet::connect()
this->isConnected = true; this->isConnected = true;
} }
void PvaClientNTMultiGet::get() void PvaClientNTMultiGet::get(bool valueOnly)
{ {
if(!isConnected) connect(); if(!isConnected) connect();
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
@@ -114,7 +111,7 @@ void PvaClientNTMultiGet::get()
pvaClientNTMultiData->setPVStructure(pvaClientGet[i]->getData()->getPVStructure(),i); pvaClientNTMultiData->setPVStructure(pvaClientGet[i]->getData()->getPVStructure(),i);
} }
} }
pvaClientNTMultiData->endDeltaTime(); pvaClientNTMultiData->endDeltaTime(valueOnly);
} }
PvaClientNTMultiDataPtr PvaClientNTMultiGet::getData() PvaClientNTMultiDataPtr PvaClientNTMultiGet::getData()
+3 -6
View File
@@ -67,13 +67,10 @@ void PvaClientNTMultiMonitor::connect()
{ {
pvaClientMonitor.resize(nchannel); pvaClientMonitor.resize(nchannel);
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
string request = "value";
if(pvRequest->getSubField("field.alarm")) request += ",alarm";
if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
{ {
if(isConnected[i]) { if(isConnected[i]) {
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(request); pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(pvRequest);
pvaClientMonitor[i]->issueConnect(); pvaClientMonitor[i]->issueConnect();
} }
} }
@@ -94,7 +91,7 @@ void PvaClientNTMultiMonitor::connect()
this->isConnected = true; this->isConnected = true;
} }
bool PvaClientNTMultiMonitor::poll() bool PvaClientNTMultiMonitor::poll(bool valueOnly)
{ {
if(!isConnected) connect(); if(!isConnected) connect();
bool result = false; bool result = false;
@@ -111,7 +108,7 @@ bool PvaClientNTMultiMonitor::poll()
} }
} }
} }
if(result) pvaClientNTMultiData->endDeltaTime(); if(result) pvaClientNTMultiData->endDeltaTime(valueOnly);
return result; return result;
} }
+13 -3
View File
@@ -12,6 +12,7 @@
#include <sstream> #include <sstream>
#include <pv/event.h> #include <pv/event.h>
#include <pv/bitSetUtil.h> #include <pv/bitSetUtil.h>
#include <pv/rpcService.h>
#define epicsExportSharedSymbols #define epicsExportSharedSymbols
@@ -180,6 +181,7 @@ void PvaClientRPC::requestDone(
PvaClientRPCRequesterPtr req = pvaClientRPCRequester.lock(); PvaClientRPCRequesterPtr req = pvaClientRPCRequester.lock();
{ {
Lock xx(mutex); Lock xx(mutex);
requestStatus = status;
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected"); string channelName("disconnected");
Channel::shared_pointer chan(channel.lock()); Channel::shared_pointer chan(channel.lock());
@@ -224,7 +226,7 @@ void PvaClientRPC::connect()
+ channelName + channelName
+ " PvaClientRPC::connect " + " PvaClientRPC::connect "
+ status.getMessage(); + status.getMessage();
throw std::runtime_error(message); throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
} }
void PvaClientRPC::issueConnect() void PvaClientRPC::issueConnect()
@@ -305,10 +307,18 @@ PVStructure::shared_pointer PvaClientRPC::request(PVStructure::shared_pointer co
string message = "channel " string message = "channel "
+ channelName + channelName
+ " PvaClientRPC::request request timeout "; + " PvaClientRPC::request request timeout ";
throw std::runtime_error(message); throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
} }
rpcState = rpcIdle; rpcState = rpcIdle;
return pvResponse; if(requestStatus.isOK()) return pvResponse;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = "channel "
+ channelName
+ " PvaClientRPC::request status ";
message += requestStatus.getMessage();
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
} }