This is Unofficial EPICS BASE Doxygen Site
pvcall.cpp
Go to the documentation of this file.
1 /*
2  * Copyright information and license terms for this software can be
3  * found in the file LICENSE that is included with the distribution
4  */
5 
6 #include <stdio.h>
7 
8 #include <epicsStdlib.h>
9 #include <epicsGetopt.h>
10 
11 #include <pv/pvData.h>
12 #include <pv/json.h>
13 #include <pva/client.h>
14 
15 #include "pvutils.h"
16 
17 #ifndef EXECNAME
18 # define EXECNAME "pvcall"
19 #endif
20 
21 namespace {
22 
23 void callusage (void)
24 {
25  fprintf (stderr, "\nUsage: " EXECNAME " [options] <PV name> [<arg1>=<value>]...\n"
26  "\n"
28  " -s <service name>: legacy form of PV name\n"
29  " -a <service arg=value>: legacy form of argument\n"
30  " deprecated options:\n"
31  " -q, -t, -i, -n, -F: ignored\n"
32  " -f <input file>: errors\n"
33  "\nexample: " EXECNAME " pv:name:add lhs=1 rhs=2\n\n"
34  , request.c_str(), timeout, defaultProvider.c_str());
35 }
36 
37 typedef std::pair<std::string, pvd::PVFieldPtr> arg_t;
38 typedef std::vector<arg_t> args_t;
39 
40 arg_t parseArg(const std::string& raw) {
41  size_t equal = raw.find_first_of('=');
42  if(equal==raw.npos)
43  throw std::runtime_error("Argument missing '='");
44 
45  std::string sval(raw.substr(equal+1));
46 
48  if(sval.size()>=2 && sval[0]=='[' && sval[sval.size()-1]==']') {
50 
51  jarray(sarr, sval.c_str());
52 
53  pvd::PVStringArrayPtr V(pvd::getPVDataCreate()->createPVScalarArray<pvd::PVStringArray>());
54  V->replace(pvd::freeze(sarr));
55  value = V;
56 
57  } else if(sval.size()>=2 && sval[0]=='{' && sval[sval.size()-1]=='}') {
58  std::istringstream strm(sval);
59 
60  value = pvd::parseJSON(strm);
61 
62  } else {
63  pvd::PVStringPtr V(pvd::getPVDataCreate()->createPVScalar<pvd::PVString>());
64  V->put(sval);
65  value = V;
66  }
67 
68  assert(!!value);
69  return std::make_pair(raw.substr(0, equal), value);
70 }
71 
72 } //namespace
73 
74 #ifndef MAIN
75 # define MAIN main
76 #endif
77 
78 int MAIN (int argc, char *argv[])
79 {
80  try {
81  int opt; /* getopt() current option */
82  std::string pv;
83 
84  args_t args;
85 
86  while ((opt = getopt(argc, argv, ":hvVM:r:w:p:ds:a:")) != -1) {
87  switch (opt) {
88  case 'h': /* Print usage */
89  callusage();
90  return 0;
91  case 'v':
92  verbosity++;
93  break;
94  case 'V': /* Print version */
95  {
96  fprintf(stdout, "pvAccess %u.%u.%u%s\n",
97  EPICS_PVA_MAJOR_VERSION,
98  EPICS_PVA_MINOR_VERSION,
99  EPICS_PVA_MAINTENANCE_VERSION,
100  (EPICS_PVA_DEVELOPMENT_FLAG)?"-SNAPSHOT":"");
101  fprintf(stdout, "pvData %u.%u.%u%s\n",
102  EPICS_PVD_MAJOR_VERSION,
103  EPICS_PVD_MINOR_VERSION,
104  EPICS_PVD_MAINTENANCE_VERSION,
105  (EPICS_PVD_DEVELOPMENT_FLAG)?"-SNAPSHOT":"");
106  fprintf(stdout, "Base %s\n", EPICS_VERSION_FULL);
107  return 0;
108  }
109  break;
110  case 'M':
111  if(strcmp(optarg, "raw")==0) {
112  outmode = pvd::PVStructure::Formatter::Raw;
113  } else if(strcmp(optarg, "nt")==0) {
114  outmode = pvd::PVStructure::Formatter::NT;
115  } else if(strcmp(optarg, "json")==0) {
116  outmode = pvd::PVStructure::Formatter::JSON;
117  } else {
118  fprintf(stderr, "Unknown output mode '%s'\n", optarg);
119  outmode = pvd::PVStructure::Formatter::Raw;
120  }
121  break;
122  case 'w': /* Set PVA timeout value */
123  {
124  double temp;
125  if((epicsScanDouble(optarg, &temp)) != 1)
126  {
127  fprintf(stderr, "'%s' is not a valid timeout value "
128  "- ignored. ('" EXECNAME " -h' for help.)\n", optarg);
129  } else {
130  timeout = temp;
131  }
132  }
133  break;
134  case 'r': /* Set PVA timeout value */
135  request = optarg;
136  break;
137  case 'p': /* Set default provider */
139  break;
140  case 'd': /* Debug log level */
141  debugFlag = true;
142  break;
143  case 's':
144  pv = optarg;
145  break;
146  case 'a':
147  try {
148  args.push_back(parseArg(optarg));
149  } catch(std::exception& e){
150  std::cerr<<"Error parsing argument '"<<optarg<<"'\n";
151  return 1;
152  }
153  break;
154  case '?':
155  fprintf(stderr,
156  "Unrecognized option: '-%c'. ('" EXECNAME " -h' for help.)\n",
157  optopt);
158  return 1;
159  case ':':
160  fprintf(stderr,
161  "Option '-%c' requires an argument. ('" EXECNAME " -h' for help.)\n",
162  optopt);
163  return 1;
164  default :
165  callusage();
166  return 1;
167  }
168  }
169 
170  if(!pv.empty()) {
171  // ok
172  } else if (argc <= optind) {
173  fprintf(stderr, "No pv name specified. ('pvput -h' for help.)\n");
174  return 1;
175  } else {
176  pv = argv[optind++];
177  }
178 
179 
180  for(int i=optind; i<argc; i++) {
181  try {
182  args.push_back(parseArg(argv[i]));
183  } catch(std::exception& e){
184  std::cerr<<"Error parsing argument '"<<optarg<<"'\n";
185  return 1;
186  }
187  }
188 
189  pvd::PVStructure::shared_pointer pvRequest;
190  try {
191  pvRequest = pvd::createRequest(request);
192  } catch(std::exception& e){
193  fprintf(stderr, "failed to parse request string: %s\n", e.what());
194  return 1;
195  }
196 
197  pvd::PVStructurePtr argument;
198  {
199  pvd::FieldBuilderPtr builder(pvd::getFieldCreate()->createFieldBuilder());
200  builder = builder->setId("epics:nt/NTURI:1.0")
201  ->add("scheme", pvd::pvString)
202  ->add("authority", pvd::pvString)
203  ->add("path", pvd::pvString)
204  ->addNestedStructure("query");
205 
206  for(args_t::const_iterator it(args.begin()), end(args.end()); it!=end; ++it) {
207  builder = builder->add(it->first, it->second->getField());
208  }
209 
210  pvd::StructureConstPtr type(builder->endNested()
211  ->createStructure());
212  argument = pvd::getPVDataCreate()->createPVStructure(type);
213 
214  argument->getSubFieldT<pvd::PVString>("scheme")->put(defaultProvider);
215  argument->getSubFieldT<pvd::PVString>("path")->put(pv);
216  pvd::PVStructurePtr query(argument->getSubFieldT<pvd::PVStructure>("query"));
217 
218  for(args_t::const_iterator it(args.begin()), end(args.end()); it!=end; ++it) {
219  query->getSubFieldT(it->first)->copy(*it->second);
220  }
221  }
222 
223  if(verbosity>=1)
224  std::cout<<"# Argument\n"<<argument->stream().format(outmode);
225 
227 
228  pvac::ClientChannel chan(prov.connect(pv));
229 
230  pvd::PVStructure::const_shared_pointer ret;
231  try {
232  ret = chan.rpc(timeout, argument, pvRequest);
233  }catch(pvac::Timeout&){
234  std::cerr<<"Timeout\n";
235  return 1;
236  }catch(std::exception& e) {
237  std::cerr<<"Error: "<<e.what()<<"\n";
238  return 1;
239  }
240 
241  if(verbosity>=1)
242  std::cout<<"# Result\n";
243  if(ret)
244  std::cout<<ret->stream().format(outmode);
245 
246  return 0;
247  } catch(std::exception& e) {
248  std::cerr<<"Error: "<<e.what()<<"\n";
249  return 1;
250  }
251 }
Thrown by blocking methods of ClientChannel on operation timeout.
Definition: client.h:247
double timeout
Definition: pvutils.cpp:25
int getopt(int nargc, char *const *nargv, const char *ostr)
Definition: epicsGetopt.c:65
Definition: link.h:174
std::string request
#define assert(exp)
Declare that a condition should be true.
Definition: epicsAssert.h:70
std::tr1::shared_ptr< detail::SharedPut > put
#define EXECNAME
Definition: pvcall.cpp:18
int i
Definition: scan.c:967
Operation rpc(GetCallback *cb, const epics::pvData::PVStructure::const_shared_pointer &arguments, epics::pvData::PVStructure::const_shared_pointer pvRequest=epics::pvData::PVStructure::const_shared_pointer())
Definition: clientRPC.cpp:158
int optind
Definition: epicsGetopt.c:50
Definition: tool_lib.h:67
pvd::StructureConstPtr type
std::tr1::shared_ptr< const Structure > StructureConstPtr
Definition: pvIntrospect.h:162
#define epicsScanDouble(str, to)
Definition: epicsStdlib.h:78
std::tr1::shared_ptr< PVStringArray > PVStringArrayPtr
Definition: pvData.h:1464
std::tr1::shared_ptr< FieldBuilder > FieldBuilderPtr
PVStructure::shared_pointer createRequest(std::string const &request)
int optopt
Definition: epicsGetopt.c:50
PVString is special case, since it implements SerializableArray.
Definition: pvData.h:521
void jarray(pvd::shared_vector< std::string > &out, const char *inp)
Definition: pvutils.cpp:68
int verbosity
Definition: pvutils.cpp:29
epics::pvData::PVStructure::shared_pointer parseJSON(std::istream &strm)
Definition: parseany.cpp:255
#define MAIN
Definition: pvcall.cpp:75
Data interface for a structure,.
Definition: pvData.h:712
#define stdout
Definition: epicsStdio.h:30
FORCE_INLINE const FieldCreatePtr & getFieldCreate()
Central client context.
Definition: client.h:517
#define COMMON_OPTIONS
Definition: pvutils.h:25
std::tr1::shared_ptr< PVStructure > PVStructurePtr
Definition: pvData.h:87
std::tr1::shared_ptr< PVString > PVStringPtr
Definition: pvData.h:540
ClientChannel connect(const std::string &name, const ClientChannel::Options &conf=ClientChannel::Options())
Definition: client.cpp:295
std::tr1::shared_ptr< PVField > PVFieldPtr
Definition: pvData.h:66
#define stderr
Definition: epicsStdio.h:32
bool debugFlag
Definition: pvutils.cpp:26
std::string defaultProvider
char * optarg
Definition: epicsGetopt.c:55
pvd::PVStructure::Formatter::format_t outmode
Definition: pvutils.cpp:28
FORCE_INLINE const PVDataCreatePtr & getPVDataCreate()
Definition: pvData.h:1648