diff --git a/testApp/remote/Makefile b/testApp/remote/Makefile index 7e2f161..b8393d4 100644 --- a/testApp/remote/Makefile +++ b/testApp/remote/Makefile @@ -42,6 +42,10 @@ PROD_HOST += testServer testServer_SRCS += testServer.cpp testServer_LIBS += pvData pvAccess Com +PROD_HOST += pvaget +pvaget_SRCS += pvaget.cpp +pvaget_LIBS += pvData pvAccess Com + include $(TOP)/configure/RULES #---------------------------------------- # ADD RULES AFTER THIS LINE diff --git a/testApp/remote/pvaget.cpp b/testApp/remote/pvaget.cpp new file mode 100644 index 0000000..c9a6eb2 --- /dev/null +++ b/testApp/remote/pvaget.cpp @@ -0,0 +1,528 @@ +#include +#include + +#include +#include +#include + +#include +#include + +using namespace std; +using namespace epics::pvData; +using namespace epics::pvAccess; + + + + + +void convertStructure(StringBuilder buffer,PVStructure *data,int indentLevel); +void convertArray(StringBuilder buffer,PVScalarArray * pv,int indentLevel); +void convertStructureArray(StringBuilder buffer,PVStructureArray * pvdata,int indentLevel); + + + + + + + + +void convertToString(StringBuilder buffer,PVField * pv,int indentLevel) +{ + Type type = pv->getField()->getType(); + if(type==structure) { + convertStructure(buffer,static_cast(pv),indentLevel); + return; + } + *buffer += "\t"; + if(type==scalarArray) { + convertArray(buffer,static_cast(pv),indentLevel); + return; + } + if(type==structureArray) { + convertStructureArray( + buffer,static_cast(pv),indentLevel); + return; + } + PVScalar *pvScalar = static_cast(pv); + ScalarConstPtr pscalar = pvScalar->getScalar(); + ScalarType scalarType = pscalar->getScalarType(); + switch(scalarType) { + case pvBoolean: { + PVBoolean *data = static_cast(pv); + bool value = data->get(); + if(value) { + *buffer += "true"; + } else { + *buffer += "false"; + } + } + return; + case pvByte: { + PVByte *data = static_cast(pv); + char xxx[30]; + sprintf(xxx,"%d",(int)data->get()); + *buffer += xxx; + } + return; + case pvShort: { + PVShort *data = static_cast(pv); + char xxx[30]; + sprintf(xxx,"%d",(int)data->get()); + *buffer += xxx; + } + return; + case pvInt: { + PVInt *data = static_cast(pv); + char xxx[30]; + sprintf(xxx,"%d",(int)data->get()); + *buffer += xxx; + } + return; + case pvLong: { + PVLong *data = static_cast(pv); + char xxx[30]; + sprintf(xxx,"%lld",(int64)data->get()); + *buffer += xxx; + } + return; + case pvFloat: { + PVFloat *data = static_cast(pv); + char xxx[30]; + sprintf(xxx,"%g",data->get()); + *buffer += xxx; + } + return; + case pvDouble: { + PVDouble *data = static_cast(pv); + char xxx[30]; + sprintf(xxx,"%lg",data->get()); + *buffer += xxx; + } + return; + case pvString: { + PVString *data = static_cast(pv); + *buffer += data->get(); + } + return; + default: + *buffer += "(unknown ScalarType)"; + } +} + +void convertStructure(StringBuilder buffer,PVStructure *data,int indentLevel) +{ + PVFieldPtrArray fieldsData = data->getPVFields(); + if (fieldsData != 0) { + int length = data->getStructure()->getNumberFields(); + for(int i=0; igetScalarArray(); + ScalarType type = array->getElementType(); + switch(type) { + case pvBoolean: { + PVBooleanArray *pvdata = static_cast(pv); + BooleanArrayData data = BooleanArrayData(); + *buffer += "["; + for(int i=0; i < pvdata->getLength(); i++) { + if(i!=0) *buffer += ","; + int num = pvdata->get(i,1,&data); + if(num==1) { + BooleanArray value = data.data; + if(value[data.offset]) { + *buffer += "true"; + } else { + *buffer += "false"; + } + } else { + *buffer += "???? "; + } + } + *buffer += "]"; + break; + } + case pvByte: { + PVByteArray *pvdata = static_cast(pv); + ByteArrayData data = ByteArrayData(); + *buffer += "["; + for(int i=0; i < pvdata->getLength(); i++) { + if(i!=0) *buffer += ","; + int num = pvdata->get(i,1,&data); + if(num==1) { + int val = data.data[data.offset]; + char buf[16]; + sprintf(buf,"%d",val); + *buffer += buf; + } else { + *buffer += "???? "; + } + } + *buffer += "]"; + break; + } + case pvShort: { + PVShortArray *pvdata = static_cast(pv); + ShortArrayData data = ShortArrayData(); + *buffer += "["; + for(int i=0; i < pvdata->getLength(); i++) { + if(i!=0) *buffer += ','; + int num = pvdata->get(i,1,&data); + if(num==1) { + int val = data.data[data.offset]; + char buf[16]; + sprintf(buf,"%d",val); + *buffer += buf; + } else { + *buffer += "???? "; + } + } + *buffer += "]"; + break; + } + case pvInt: { + PVIntArray *pvdata = static_cast(pv); + IntArrayData data = IntArrayData(); + *buffer += "["; + for(int i=0; i < pvdata->getLength(); i++) { + if(i!=0) *buffer += ','; + int num = pvdata->get(i,1,&data); + if(num==1) { + int val = data.data[data.offset]; + char buf[16]; + sprintf(buf,"%d",val); + *buffer += buf; + } else { + *buffer += "???? "; + } + } + *buffer += "]"; + break; + } + case pvLong: { + PVLongArray *pvdata = static_cast(pv); + LongArrayData data = LongArrayData(); + *buffer += "["; + for(int i=0; i < pvdata->getLength(); i++) { + if(i!=0) *buffer += ','; + int num = pvdata->get(i,1,&data); + if(num==1) { + int64 val = data.data[data.offset]; + char buf[16]; + sprintf(buf,"%lld",val); + *buffer += buf; + } else { + *buffer += "???? "; + } + } + *buffer += "]"; + break; + } + case pvFloat: { + PVFloatArray *pvdata = static_cast(pv); + FloatArrayData data = FloatArrayData(); + *buffer += "["; + for(int i=0; i < pvdata->getLength(); i++) { + if(i!=0) *buffer += ','; + int num = pvdata->get(i,1,&data); + if(num==1) { + float val = data.data[data.offset]; + char buf[16]; + sprintf(buf,"%g",val); + *buffer += buf; + } else { + *buffer += "???? "; + } + } + *buffer += "]"; + break; + } + case pvDouble: { + PVDoubleArray *pvdata = static_cast(pv); + DoubleArrayData data = DoubleArrayData(); + *buffer += "["; + for(int i=0; i < pvdata->getLength(); i++) { + if(i!=0) *buffer += ','; + int num = pvdata->get(i,1,&data); + if(num==1) { + double val = data.data[data.offset]; + char buf[16]; + sprintf(buf,"%lg",val); + *buffer += buf; + } else { + *buffer += "???? "; + } + } + *buffer += ("]"); + break; + } + case pvString: { + PVStringArray *pvdata = static_cast(pv); + StringArrayData data = StringArrayData(); + *buffer += "["; + for(int i=0; i < pvdata->getLength(); i++) { + if(i!=0) *buffer += ","; + int num = pvdata->get(i,1,&data); + StringArray value = data.data; + if(num==1) { + if(value[data.offset].length()>0) { + *buffer += value[data.offset].c_str(); + } else { + *buffer += "null"; + } + } else { + *buffer += "null"; + } + } + *buffer += "]"; + break; + } + default: + *buffer += "(array element is unknown ScalarType)"; + } +} + +void convertStructureArray(StringBuilder buffer, + PVStructureArray * pvdata,int indentLevel) +{ + int length = pvdata->getLength(); + if(length<=0) { + return; + } + StructureArrayData data = StructureArrayData(); + pvdata->get(0, length, &data); + for (int i = 0; i < length; i++) { + PVStructure *pvStructure = data.data[i]; + if (pvStructure == 0) { + *buffer += "null"; + } else { + convertToString(buffer,pvStructure,indentLevel+1); + } + } +} + + + + + + + + + + + + + + + + + + + +#define DEFAULT_TIMEOUT 3.0 +#define DEFAULT_REQUEST "field(value)" + +double caTimeout = DEFAULT_TIMEOUT; +string request(DEFAULT_REQUEST); + +PVStructure::shared_pointer pvRequest; + +void usage (void) +{ + fprintf (stderr, "\nUsage: pvaget [options] ...\n\n" + " -h: Help: Print this message\n" + "options:\n" + " -r : Request, specifies what fields to return and options, default is '%s'\n" + " -w : Wait time, specifies timeout, default is %f second(s)\n" + "\nExample: pvaget my_channel \n\n" + , DEFAULT_REQUEST, DEFAULT_TIMEOUT); +} + + +class ChannelGetRequesterImpl : public ChannelGetRequester +{ + private: + +ChannelGet::shared_pointer m_channelGet; + epics::pvData::PVStructure::shared_pointer m_pvStructure; + epics::pvData::BitSet::shared_pointer m_bitSet; + + public: + + virtual String getRequesterName() + { + return "ChannelGetRequesterImpl"; + }; + + virtual void message(String message,MessageType messageType) + { + std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; + } + + virtual void channelGetConnect(const epics::pvData::Status& status,ChannelGet::shared_pointer const & channelGet, + epics::pvData::PVStructure::shared_pointer const & pvStructure, + epics::pvData::BitSet::shared_pointer const & bitSet) + { + // TODO remove (cyclic shared_pointers) + m_channelGet = channelGet; + + m_pvStructure = pvStructure; + m_bitSet = bitSet; + channelGet->get(true); + } + + virtual void getDone(const epics::pvData::Status& status) + { + std::cout << "getDone(" << status.toString() << ")" << std::endl; + + if (status.isSuccess()) + { + String str; + + m_pvStructure->toString(&str); + + //convertToString(&str, m_pvStructure.get(), 0); + + std::cout << str; + std::cout << std::endl; + } + } +}; + +class ChannelRequesterImpl : public ChannelRequester +{ + virtual String getRequesterName() + { + return "ChannelRequesterImpl"; + }; + + virtual void message(String message,MessageType messageType) + { + std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; + } + + virtual void channelCreated(const epics::pvData::Status& status, Channel::shared_pointer const & channel) + { + if (status.isSuccess()) + { + // show warning + if (!status.isOK()) + { + std::cout << "channel create: " << status.toString() << std::endl; + } + } + else + { + std::cout << "failed to create a channel: " << status.toString() << std::endl; + } + } + + virtual void channelStateChange(Channel::shared_pointer const & channel, Channel::ConnectionState connectionState) + { + if (connectionState == Channel::CONNECTED) + { + ChannelGetRequester::shared_pointer getRequester(new ChannelGetRequesterImpl()); + channel->createChannelGet(getRequester, pvRequest); + } + /* + else if (connectionState != Channel::DESTROYED) + { + std::cout << "channel state change: " << Channel::ConnectionStateNames[connectionState] << std::endl; + } + */ + } +}; + +/*+************************************************************************** + * + * Function: main + * + * Description: pvaget main() + * Evaluate command line options, set up CA, connect the + * channels, print the data as requested + * + * Arg(s) In: [options] ... + * + * Arg(s) Out: none + * + * Return(s): Standard return code (0=success, 1=error) + * + **************************************************************************-*/ + +int main (int argc, char *argv[]) +{ + int opt; /* getopt() current option */ + + setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */ + + while ((opt = getopt(argc, argv, ":hr:w:")) != -1) { + switch (opt) { + case 'h': /* Print usage */ + usage(); + return 0; + case 'w': /* Set CA timeout value */ + if(epicsScanDouble(optarg, &caTimeout) != 1) + { + fprintf(stderr, "'%s' is not a valid timeout value " + "- ignored. ('cainfo -h' for help.)\n", optarg); + caTimeout = DEFAULT_TIMEOUT; + } + break; + case 'r': /* Set CA timeout value */ + request = optarg; + break; + case '?': + fprintf(stderr, + "Unrecognized option: '-%c'. ('pvaget -h' for help.)\n", + optopt); + return 1; + case ':': + fprintf(stderr, + "Option '-%c' requires an argument. ('pvaget -h' for help.)\n", + optopt); + return 1; + default : + usage(); + return 1; + } + } + + int nPvs = argc - optind; /* Remaining arg list are PV names */ + if (nPvs < 1) + { + fprintf(stderr, "No pv name specified. ('pvaget -h' for help.)\n"); + return 1; + } + + vector pvs; /* Array of PV structures */ + for (int n = 0; optind < argc; n++, optind++) + pvs.push_back(argv[optind]); /* Copy PV names from command line */ + + try { + pvRequest = getCreateRequest()->createRequest(request); + } catch (std::exception &ex) { + printf("failed to parse request string: %s\n", ex.what()); + return 1; + } + + + + ClientFactory::start(); + ChannelProvider::shared_pointer provider = getChannelAccess()->getProvider("pvAccess"); + + ChannelRequester::shared_pointer channelRequester(new ChannelRequesterImpl()); + Channel::shared_pointer tmpChannel = provider->createChannel(pvs[0], channelRequester); // TODO + + epicsThreadSleep ( 3.0 ); + + + ClientFactory::stop(); + + return 0; +}