DABC (Data Acquisition Backbone Core)  2.9.9
EpicsInput.cxx
Go to the documentation of this file.
1 // $Id: EpicsInput.cxx 4473 2020-04-15 13:35:08Z linev $
2 
3 /************************************************************
4  * The Data Acquisition Backbone Core (DABC) *
5  ************************************************************
6  * Copyright (C) 2009 - *
7  * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
8  * Planckstr. 1, 64291 Darmstadt, Germany *
9  * Contact: http://dabc.gsi.de *
10  ************************************************************
11  * This software can be used under the GPL license *
12  * agreements as stated in LICENSE.txt file *
13  * which is part of the distribution. *
14  ************************************************************/
15 
16 #include "ezca/EpicsInput.h"
17 
18 #include "dabc/Pointer.h"
19 #include "dabc/timing.h"
20 #include "dabc/Manager.h"
21 #include "mbs/MbsTypeDefs.h"
22 #include "mbs/Iterator.h"
23 #include "mbs/SlowControlData.h"
24 
25 #include "ezca/Definitions.h"
26 
27 #include <ctime>
28 
29 
30 #include "tsDefs.h"
31 #include "cadef.h"
32 
33 #include "ezca.h"
34 
35 
36 ezca::EpicsInput::EpicsInput(const std::string &name) :
37  dabc::DataInput(),
38  fName(name),
39  fTimeout(1),
40  fSubeventId(8),
41  fLastFlagValue(0),
42  fEventNumber(0),
43  fCounter(0),
44  fEzcaTimeout(-1.),
45  fEzcaRetryCnt(-1),
46  fEzcaDebug(false),
47  fEzcaAutoError(false)
48 {
50 }
51 
53 {
54  Close();
55 }
56 
58 {
59  if (!dabc::DataInput::Read_Init(wrk, cmd)) return false;
60 
61  fName = wrk.Cfg(ezca::xmlEpicsName, cmd).AsStr(fName);
62  fTimeout = wrk.Cfg(ezca::xmlTimeout, cmd).AsDouble(fTimeout);
63  fSubeventId = wrk.Cfg(ezca::xmlEpicsSubeventId, cmd).AsInt(fSubeventId);
64 
65  fUpdateFlagRecord = wrk.Cfg(ezca::xmlUpdateFlagRecord,cmd).AsStr();
66  fIDNumberRecord = wrk.Cfg(ezca::xmlEventIDRecord,cmd).AsStr();
67  fUpdateCommandReceiver = wrk.Cfg(ezca::xmlCommandReceiver,cmd).AsStr("");
68 
69  fLongRecords = wrk.Cfg(ezca::xmlNameLongRecords, cmd).AsStrVect();
70  fLongValues.resize(fLongRecords.size(), 0);
71  fLongRes.resize(fLongRecords.size(), false);
72 
73  fDoubleRecords = wrk.Cfg(ezca::xmlNameDoubleRecords, cmd).AsStrVect();
74  fDoubleValues.resize(fDoubleRecords.size(), 0.);
75  fDoubleRes.resize(fDoubleRecords.size(), false);
76 
77  fEzcaTimeout = wrk.Cfg(ezca::xmlEzcaTimeout, cmd).AsDouble(fEzcaTimeout);
78  fEzcaRetryCnt = wrk.Cfg(ezca::xmlEzcaRetryCount, cmd).AsInt(fEzcaRetryCnt);
79  fEzcaDebug = wrk.Cfg(ezca::xmlEzcaDebug, cmd).AsBool(fEzcaDebug);
80  fEzcaAutoError = wrk.Cfg(ezca::xmlEzcaAutoError, cmd).AsBool(fEzcaAutoError);
81 
82  DOUT1("EpicsInput %s - Timeout = %e s, subevtid:%d, update flag:%s id:%s ",
83  fName.c_str(), fTimeout,fSubeventId, fUpdateFlagRecord.c_str(),fIDNumberRecord.c_str());
84 
85  return true;
86 }
87 
88 
90 {
91  ResetDescriptors();
92  DOUT1("EpicsInput::Close");
93  return true;
94 }
95 
96 
98 {
99 
100  if (fEzcaTimeout>0) ezcaSetTimeout(fEzcaTimeout);
101 
102  if (fEzcaRetryCnt>0) ezcaSetRetryCount(fEzcaRetryCnt);
103 
104  if (fEzcaDebug) ezcaDebugOn();
105  else ezcaDebugOff();
106 
107  if (fEzcaAutoError) ezcaAutoErrorMessageOn();
108  else ezcaAutoErrorMessageOff();
109 
110  if (!fUpdateFlagRecord.empty()) {
111  long flag = 0;
112 
113  // first check the flag record:
114  if (CA_GetLong(fUpdateFlagRecord, flag) != 0) {
115  EOUT("Cannot get update record %s", fUpdateFlagRecord.c_str());
116  return dabc::di_RepeatTimeOut;
117  }
118 
119  if (flag == fLastFlagValue) { // read on every change of flag if not 0
120  //oldflag = flag;
121  DOUT3("EpicsInput::Read_Size same flag value, repeat after timeout %3.1f", fTimeout);
122  return dabc::di_RepeatTimeOut;
123  }
124 
125  fLastFlagValue = flag;
126 
127  if (!fUpdateCommandReceiver.empty()) {
129  cmd.SetReceiver(fUpdateCommandReceiver);
130  cmd.SetInt(xmlUpdateFlagRecord, flag);
131  dabc::mgr.Submit(cmd);
132  }
133  // if this is nonzero, read other records and write buffer
134  } else {
135 
136  // use last flag as switch to timeout reading of data
137  if(fLastFlagValue) {
138  fLastFlagValue = 0;
139 // DOUT0("Return timeout");
140  return dabc::di_RepeatTimeOut;
141  }
142  fLastFlagValue = 1;
143  }
144 
145 // DOUT0("ezca::EpicsInput::Read_Size middle %s", fIDNumberRecord.c_str());
146 
147  if (!fIDNumberRecord.empty()) {
148 // ezcaAutoErrorMessageOn();
149 // ezcaDebugOn();
150  DOUT1("Event number record reading %s retr %d tmout %5.3f", fIDNumberRecord.c_str(), ezcaGetRetryCount(), ezcaGetTimeout());
151  if (CA_GetLong(fIDNumberRecord, fEventNumber) != 0) {
152  EOUT("Cannot read event number from record %s", fIDNumberRecord.c_str());
153  return dabc::di_RepeatTimeOut;
154  }
155  DOUT1("Event number record reading %s = %ld ", fIDNumberRecord.c_str(), fEventNumber);
156  } else {
157  fEventNumber = fCounter;
158  }
159 
160  return dabc::di_DfltBufSize;
161 }
162 
163 
165 {
166  fCounter++;
167 
168 // DOUT0("Buffer size %u", buf.GetTotalSize());
169 
170  dabc::TimeStamp tm = dabc::Now();
171 
172  if ((NumLongRecords() + NumDoubleRecords()) > 0) {
173 
174  ezcaStartGroup();
175 
176  // now the data values for each record in order:
177  for (unsigned ix = 0; ix < NumLongRecords(); ix++) {
178  fLongValues[ix] = 0;
179  fLongRes[ix] = true;
180  int ret = CA_GetLong(GetLongRecord(ix), fLongValues[ix]);
181  if (ret!=EZCA_OK) EOUT("Request long %s Ret = %s", GetLongRecord(ix).c_str(), CA_RetCode(ret));
182  }
183 
184  for (unsigned ix = 0; ix < NumDoubleRecords(); ix++) {
185  fDoubleValues[ix] = 0;
186  fDoubleRes[ix] = true;
187  int ret = CA_GetDouble(GetDoubleRecord(ix), fDoubleValues[ix]);
188  if (ret!=EZCA_OK) EOUT("Request double %s Ret = %s", GetDoubleRecord(ix).c_str(), CA_RetCode(ret));
189  }
190 
191  int *rcs(0), nrcs(0);
192 
193  if (ezcaEndGroupWithReport(&rcs, &nrcs) != EZCA_OK) {
194  EOUT("EZCA error %s", CA_ErrorString().c_str());
195  for (unsigned i=0; i< (unsigned) nrcs; i++)
196  if (i<fLongRecords.size()) {
197  unsigned ix = i;
198  fLongRes[ix] = (rcs[i]==EZCA_OK);
199  if (!fLongRes[ix])
200  EOUT("Problem getting long %s ret %s", fLongRecords[ix].c_str(), CA_RetCode(rcs[i]));
201  } else {
202  unsigned ix = i - fLongRecords.size();
203  fDoubleRes[ix] = (rcs[i]==EZCA_OK);
204  if (!fDoubleRes[ix])
205  EOUT("Problem getting double %s ret %s", fDoubleRecords[ix].c_str(), CA_RetCode(rcs[i]));
206  }
207  }
208 
209  ezcaFree(rcs);
210  }
211 
212  DOUT2("EpicsInput:: readout time is = %7.5f s", tm.SpentTillNow());
213 
215 
216  for (unsigned ix = 0; ix < fLongRecords.size(); ++ix)
217  if (fLongRes[ix]) rec.AddLong(fLongRecords[ix], fLongValues[ix]);
218 
219  for (unsigned ix = 0; ix < fDoubleRecords.size(); ++ix)
220  if (fDoubleRes[ix]) rec.AddDouble(fDoubleRecords[ix], fDoubleValues[ix]);
221 
222 
223  rec.SetEventId(fEventNumber);
224  rec.SetEventTime(time(NULL));
225 
226  mbs::WriteIterator iter(buf);
227 
228  iter.NewEvent(fEventNumber);
229  iter.NewSubevent2(fSubeventId);
230 
231  unsigned size = rec.Write(iter.rawdata(), iter.maxrawdatasize());
232 
233  if (size==0) {
234  EOUT("Fail to write data into MBS subevent");
235  }
236 
237  iter.FinishSubEvent(size);
238  iter.FinishEvent();
239 
240  buf = iter.Close();
241 
242 // DOUT0("Read buf size = %u", buf.GetTotalSize());
243 
244  return dabc::di_Ok;
245 }
246 
247 
248 int ezca::EpicsInput::CA_GetLong(const std::string &name, long& val)
249 {
250  int rev = ezcaGet((char*) name.c_str(), ezcaLong, 1, &val);
251  if(rev!=EZCA_OK)
252  EOUT("%s", CA_ErrorString().c_str());
253  else
254  DOUT3("EpicsInput::CA_GetLong(%s) = %d",name.c_str(),val);
255  return rev;
256 }
257 
258 int ezca::EpicsInput::CA_GetDouble(const std::string &name, double& val)
259 {
260  int rev=ezcaGet((char*) name.c_str(), ezcaDouble, 1, &val);
261  if(rev!=EZCA_OK)
262  EOUT("%s", CA_ErrorString().c_str());
263  else
264  DOUT3("EpicsInput::CA_GetDouble(%s) = %f",name.c_str(),val);
265  return rev;
266 }
267 
269 {
270  std::string res;
271 
272  char *error_msg_buff(0);
273  ezcaGetErrorString(NULL, &error_msg_buff);
274  if (error_msg_buff!=0) res = error_msg_buff;
275  ezcaFree(error_msg_buff);
276 
277  return res;
278 }
279 
280 const char* ezca::EpicsInput::CA_RetCode(int ret)
281 {
282  switch (ret) {
283  case EZCA_OK: return "EZCA_OK";
284  case EZCA_INVALIDARG: return "EZCA_INVALIDARG";
285  case EZCA_FAILEDMALLOC: return "EZCA_FAILEDMALLOC";
286  case EZCA_CAFAILURE: return "EZCA_CAFAILURE";
287  case EZCA_UDFREQ: return "EZCA_UDFREQ";
288  case EZCA_NOTCONNECTED: return "EZCA_NOTCONNECTED";
289  case EZCA_NOTIMELYRESPONSE: return "EZCA_NOTIMELYRESPONSE";
290  case EZCA_INGROUP: return "EZCA_INGROUP";
291  case EZCA_NOTINGROUP: return "EZCA_NOTINGROUP";
292  case EZCA_ABORTED: return "EZCA_ABORTED";
293  }
294 
295  return "unknown";
296 }
Reference on memory from memory pool.
Definition: Buffer.h:135
Represents command with its arguments.
Definition: Command.h:99
bool SetInt(const std::string &name, int v)
Definition: Command.h:138
Command & SetReceiver(const std::string &itemname)
These methods prepare command so, that one can submit command to the manager like: dabc::mgr....
Definition: Command.h:264
virtual bool Read_Init(const WorkerRef &wrk, const Command &cmd)
Initialize data input, using port and command.
Definition: DataIO.h:82
std::vector< std::string > AsStrVect() const
Definition: Record.cxx:923
bool AsBool(bool dflt=false) const
Definition: Record.cxx:477
std::string AsStr(const std::string &dflt="") const
Definition: Record.cxx:749
int64_t AsInt(int64_t dflt=0) const
Definition: Record.cxx:501
double AsDouble(double dflt=0.) const
Definition: Record.cxx:549
Reference on dabc::Worker
Definition: Worker.h:466
RecordField Cfg(const std::string &name, Command cmd=nullptr) const
Returns configuration record of specified name.
Definition: Worker.h:482
bool Submit(Command cmd)
Definition: Worker.cxx:1139
virtual bool Read_Init(const dabc::WorkerRef &wrk, const dabc::Command &cmd)
Initialize data input, using port and command.
Definition: EpicsInput.cxx:57
const char * CA_RetCode(int ret)
Definition: EpicsInput.cxx:280
int CA_GetDouble(const std::string &name, double &val)
Definition: EpicsInput.cxx:258
virtual unsigned Read_Complete(dabc::Buffer &buf)
Complete reading of the buffer from source,.
Definition: EpicsInput.cxx:164
void ResetDescriptors()
Definition: EpicsInput.h:91
int CA_GetLong(const std::string &name, long &val)
Definition: EpicsInput.cxx:248
virtual unsigned Read_Size()
Defines required buffer size for next operation.
Definition: EpicsInput.cxx:97
EpicsInput(const std::string &name="")
Definition: EpicsInput.cxx:36
std::string CA_ErrorString()
Return error string with error description.
Definition: EpicsInput.cxx:268
virtual ~EpicsInput()
Definition: EpicsInput.cxx:52
Record for manipulation with slow control data.
void SetEventId(uint32_t id)
void SetEventTime(uint32_t tm)
unsigned Write(void *buf, unsigned buflen)
void AddDouble(const std::string &name, double value, bool checkduplicate=false)
Method add double record.
void AddLong(const std::string &name, int64_t value, bool checkduplicate=false)
Method add long record.
Write iterator for MBS events/subevents.
Definition: Iterator.h:97
bool FinishSubEvent(uint32_t rawdatasz=0)
Definition: Iterator.cxx:378
void * rawdata() const
Definition: Iterator.h:158
bool NewSubevent2(uint32_t fullid)
Definition: Iterator.cxx:347
uint32_t maxrawdatasize() const
Definition: Iterator.h:159
bool NewEvent(EventNumType event_number=0, uint32_t subeventsize=0)
Definition: Iterator.cxx:304
dabc::Buffer Close()
Definition: Iterator.cxx:237
#define DOUT2(args ...)
Definition: logging.h:170
#define DOUT3(args ...)
Definition: logging.h:176
#define EOUT(args ...)
Definition: logging.h:150
#define DOUT1(args ...)
Definition: logging.h:162
Event manipulation API.
Definition: api.h:23
TimeStamp Now()
Definition: timing.h:260
ManagerRef mgr
Definition: Manager.cxx:42
@ di_Ok
Definition: DataIO.h:38
@ di_DfltBufSize
Definition: DataIO.h:42
@ di_RepeatTimeOut
Definition: DataIO.h:36
const char * xmlUpdateFlagRecord
Definition: Factory.cxx:30
const char * nameUpdateCommand
Definition: Factory.cxx:41
const char * xmlEzcaAutoError
indicates if error should be automatically printed
Definition: Factory.cxx:39
const char * xmlNameLongRecords
Definition: Factory.cxx:32
const char * xmlCommandReceiver
Definition: Factory.cxx:42
const char * xmlEventIDRecord
Definition: Factory.cxx:31
const char * xmlTimeout
Definition: Factory.cxx:34
const char * xmlEpicsSubeventId
Definition: Factory.cxx:35
const char * xmlEpicsName
Definition: Factory.cxx:29
const char * xmlEzcaDebug
retry counter for ezca operation
Definition: Factory.cxx:38
const char * xmlEzcaTimeout
timeout for ezca operation
Definition: Factory.cxx:36
const char * xmlEzcaRetryCount
retry counter for ezca operation
Definition: Factory.cxx:37
const char * xmlNameDoubleRecords
Definition: Factory.cxx:33
Class for acquiring and holding timestamps.
Definition: timing.h:40
double SpentTillNow() const
Method return time in second, spent from the time kept in TimeStamp instance If time was not set befo...
Definition: timing.h:144