iop_vdevice.cpp
Go to the documentation of this file.
1 /** @file iop_vdevice.cpp Virtual device for interface definition */
2 
3 /*
4  FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2008, Thomas Moor
7  Exclusive copyright is granted to Klaus Schmidt
8 
9 */
10 
11 
12 
13 #include "iop_vdevice.h"
14 
15 #include "iop_simplenet.h"
16 #include "iop_comedi.h"
17 #include "iop_wago.h"
18 #include "iop_xdevice.h"
19 #include "sp_densityfnct.h"
20 
21 
22 namespace faudes {
23 
24 
25 
26 /*
27  **********************************************
28  **********************************************
29  **********************************************
30 
31  implementation: AttributeDeviceEvent
32 
33  **********************************************
34  **********************************************
35  **********************************************
36  */
37 
38 
39 // faudes type std
40 FAUDES_TYPE_IMPLEMENTATION(Void,AttributeDeviceEvent,AttributeVoid)
41 
42 // Default constructor (no attributes, aka undefined) */
44  AttributeVoid(),
45  mpOutputAttribute(0),
46  mpInputAttribute(0),
47  pOutputPrototype(0),
48  pInputPrototype(0)
49 {
50  FD_DHV("AttributeDeviceEvent::AttributeDeviceEvent(" << this << ")");
51  pOutputPrototype= FallbackAttributep();
52  pInputPrototype= FallbackAttributep();
53 }
54 
55 // Copy constructor (never called)
57  AttributeVoid(),
58  mpOutputAttribute(0),
59  mpInputAttribute(0),
60  pOutputPrototype(0),
61  pInputPrototype(0)
62 {
63  FD_DHV("AttributeDeviceEvent(" << this << "): form other attr " << &rOtherAttr);
66  DoAssign(rOtherAttr);
67 }
68 
69 // Destructor
73 }
74 
75 // pseudo statics
77  static AttributeVoid* avoid=new AttributeVoid();
78  return avoid;
79 }
80 
81 // Clear
87 }
88 
89 // Assignement
91  FD_DHV("AttributeDeviceEvent(" << this << "):DoAssign(): "
92  << typeid(*this).name() << " from " << typeid(rSrcAttr).name());
93  Clear();
94  if(rSrcAttr.IsInput()) Input(*rSrcAttr.Inputp());
95  if(rSrcAttr.IsOutput()) Output(*rSrcAttr.Outputp());
96 }
97 
98 
99 
100 // DoWrite(rTw,rLabel,pContext)
101 void AttributeDeviceEvent::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
102  FD_DHV("AttributeDeviceEvent(" << this << ")::DoWrite(tw): " << IsOutput() << " " << IsInput() );
103  if(IsOutput()) mpOutputAttribute->Write(rTw,rLabel,pContext);
104  if(IsInput()) mpInputAttribute->Write(rTw,rLabel,pContext);
105 }
106 
107 //DoRead(rTr,rLabel,pContext)
108 void AttributeDeviceEvent::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
109  FD_DHV("AttributeDeviceEvent(" << this << ")::DoRead(tr)");
110  // clear
115  // test for output/input section
116  Token token;
117  rTr.Peek(token);
118  if(!token.IsBegin()) return;
119  // read output/input
120  if(token.StringValue()=="Output" || token.StringValue()=="Actuator") {
121  DefaultOutput();
122  mpOutputAttribute->Read(rTr,rLabel,pContext);
123  FD_DHV("Found Output : " << mpOutputAttribute->ToString());
124  }
125  // read output/input
126  if(token.StringValue()=="Input" || token.StringValue()=="Sensor") {
127  DefaultInput();
128  mpInputAttribute->Read(rTr,rLabel,pContext);
129  FD_DHV("Found Input: " << mpInputAttribute->ToString() << " " << rLabel);
130  }
131  // ignore others
132 }
133 
134 
135 /*
136  **********************************************
137  **********************************************
138  **********************************************
139 
140  implementation: vDevice
141 
142  **********************************************
143  **********************************************
144  **********************************************
145  */
146 
147 
148 //vDevice()
150  // constructor
151 
152  FD_DHV("vDevice(" << mName << ")::vDevice()");
153  //set defaults
154  mName = "IoDevice"; //device-name
155  mpConfiguration = NULL; //derived class to set: pointer to config-set
156  mState = Down; //initial state
157  mDefaultLabel ="Device"; //label used with token-io
158  mTimeScale = 1000; //faudes-time scaling-factor 1[ftu] =^ 1[sec]
159  mMaxSyncGap = Time::Step(); //max time-delay used with simulator
160  pWaitMutex=&mWaitMutex; //use object - mutex
161  pWaitCondition=&mWaitCondition; //use object - condition
162  pBufferMutex=&mBufferMutex; //use object - buffer-mutex
163  pInputBuffer=&mInputBuffer; //use object - input-buffer
164 
165  //initial mutex- and condition variables
166  faudes_mutex_init(&mWaitMutex);
167  faudes_cond_init(&mWaitCondition);
168  faudes_mutex_init(&mBufferMutex);
169 
170 #ifdef FAUDES_DEBUG_IOPERF
171  // initialize arrays to store time stamps
172  mpPerformanceWaitEnter = new faudes_systime_t[FAUDES_DEBUG_IOPERF_SAMPLES];
173  mpPerformanceWaitExit = new faudes_systime_t[FAUDES_DEBUG_IOPERF_SAMPLES];
176 #endif
177 
178  // track devices
179  AllDevices().insert(this);
180 
181 }
182 
183 // pseudo static members
184 std::set<vDevice*>& vDevice::AllDevices(void) {
185  static std::set<vDevice*> *dlist = new std::set< vDevice* >();
186  return *dlist;
187 }
188 
189 
190 //~vDevice()
192  // destructor
193  FD_DHV("vDevice(" << mName << ")::~vDevice()");
194  //delete configuration
195  if(mpConfiguration) delete mpConfiguration;
196  //destroy mutex
197  faudes_mutex_destroy(&mWaitMutex);
198  faudes_cond_destroy(&mWaitCondition);
199  faudes_mutex_destroy(&mBufferMutex);
200 
201 #ifdef FAUDES_DEBUG_IOPERF
202  // delete time stamps
203  delete mpPerformanceWaitEnter;
204  delete mpPerformanceWaitExit;
205 #endif
206 
207  // track devices
208  AllDevices().erase(this);
209 }
210 
211 //FromTokenReader
213  // construct from token reader
214  FD_DHV("vDevice::FromTokenReader()");
215  // peek first token // s&e tr->rTr
216  Token token;
217  rTr.Peek(token);
218  if(!token.IsBegin()) {
219  std::stringstream errstr;
220  errstr << "Expected Begin Section in \"" << rTr.FileName() << "\"";
221  throw Exception("vDevice::FromFile", errstr.str(), 52);
222  }
223  // instantiate typed faudes object
224  std::string ftype=token.StringValue();
225  FD_DHV("vDevice::FromFile(" << rTr.FileName() <<"): device type " << ftype);
226  Type* fobject= NewFaudesObject(ftype);
227  if(!fobject) {
228  std::stringstream errstr;
229  errstr << "Unknown type \"" << ftype << "\" at \"" << rTr.FileLine() << "\"";
230  throw Exception("vDevice()::FromFile", errstr.str(), 52);
231  return 0;
232  }
233  // cast to vdevice
234  vDevice* fdevice= dynamic_cast<vDevice*>(fobject);
235  if(!fdevice) {
236  std::stringstream errstr;
237  errstr << "Could not cast to device object from type \"" << ftype << "\" at \"" << rTr.FileLine() << "\")";
238  throw Exception("vDevice()::FromFile", errstr.str(), 52);
239  return 0;
240  }
241  // do read stream
242  fdevice->Read(rTr);
243  return fdevice;
244 }
245 
246 
247 //FromFile(rFileName)
248 vDevice* vDevice::FromFile(const std::string& rFileName) {
249  FD_DHV("vDevice::FromFile(" << rFileName <<")");
250  // peek first token
251  TokenReader tr(rFileName);
252  return FromTokenReader(tr);
253 }
254 
255 
256 // static member function
257 void vDevice::StopAll(void) {
258  // cosmetic bail out
259  if(AllDevices().size()==0) return;
260  // report
261  FD_DH("vDevice::StopAll()");
262  // reset
263  std::set<vDevice*>::const_iterator dit;
264  for(dit=AllDevices().begin(); dit != AllDevices().end(); dit++) {
265  if( dynamic_cast<xDevice*>(*dit) ) continue;
266  FD_DH("vDevice::StopAll(): Reset: " << (*dit)->Name());
267  (*dit)->Reset();
268  }
269  // stop
270  for(dit=AllDevices().begin(); dit != AllDevices().end(); dit++) {
271  if( dynamic_cast<xDevice*>(*dit) ) continue;
272  FD_DH("vDevice::StopAll(): Stop " << (*dit)->Name());
273  (*dit)->Stop();
274  }
275  // report
276  FD_DH("vDevice::StopAll(): done");
277 }
278 
279 
280 // Start(void)
281 void vDevice::Start(void) {
282  // only start if currently down
283  if(mState!=Down) return;
284 
285  FD_DHV("vDevice(" << mName << ")::Start()");
286  if(!mpConfiguration) {
287  std::stringstream errstr;
288  errstr << "cannot start device when not configured";
289  throw Exception("vDevice()::Start()", errstr.str(), 550);
290  }
291  // optimistic default in base class
292  mState=Up;
293  // Start implies Reset
294  Reset();
295 }
296 
297 
298 // Stop()
299 void vDevice::Stop(void) {
300  // stop implies Reset
301  Reset();
302  // only stop if up or starting up
303  if(mState!=Up && mState!=StartUp) return;
304  FD_DHV("vDevice(" << mName << ")::Stop()");
305  // indicate success
306  mState=Down;
307 }
308 
309 
310 // Reset()
311 void vDevice::Reset(void){
312  //delete dynamic data
313  FD_DHV("vDevice(" << mName <<")::Reset()");
314  //reset time and delete dynamic data
315  CurrentTime(0);
316  // reset input buffer
317  faudes_mutex_lock(pBufferMutex);
318  pInputBuffer->clear();
319  mResetRequest=false;
320  faudes_mutex_unlock(pBufferMutex);
321 }
322 
323 
324 // Clear()
325 void vDevice::Clear(void) {
326  //delete static data
327  FD_DHV("vDevice("<< mName <<")::Clear()");
328  //implies stop
329  Stop();
330  //clear exisiting data
332  mOutputs.Clear();
333  mInputs.Clear();
334  // sensible defaults
335  mTimeScale=1000;
336 }
337 
338 
339 // Name(rName)
340 void vDevice::Name(const std::string& rName) {
341  FD_DHV("vDevice(" << mName << ")::Name(\"" << rName << "\")");
342  mName = rName;
343 }
344 
345 // Name()
346 const std::string& vDevice::Name(void) const {
347  FD_DHV("vDevice(" << mName << ")::Name()");
348  return mName;
349 }
350 
351 
352 //StatusString()
353 std::string vDevice::StatusString(void) {
354  //status string, informal (should prepare mutex)
355 
356  FD_DHV("vDevice(" << mName << ")::Name()");
357  //prepare result
358  std::string res;
359  //get curretn device state
360  DeviceState currentState=Status();
361  switch(currentState) {
362  case Down: res="down"; break;
363  case StartUp: res="starting up"; break;
364  case Up: res="up and running"; break;
365  case ShutDown: res="shutting down"; break;
366  }
367 
368  return res;
369 }
370 
371 
372 //DoWrite(rTr,rLabel,pContext)
373 void vDevice::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
374  (void) pContext; (void) rTw;
375  FD_DHV("vDevice("<<mName<<")::DoWrite()");
376  // Set up defaults
377  std::string label=rLabel;
378  std::string ftype=TypeName();
379  // Write begin
380  if(label=="") label=TypeName();
381  if(label=="") label = mDefaultLabel;
382  Token btag;
383  btag.SetBegin(label);
384  if(Name()!=label) btag.InsAttributeString("name",Name());
385  if(ftype!=label && ftype!="") btag.InsAttributeString("ftype",ftype);
386  rTw << btag;
387  // dispatch
388  DoWritePreface(rTw,"",pContext);
389  DoWriteConfiguration(rTw,"",pContext);
390  // end of my section
391  rTw.WriteEnd(label);
392 }
393 
394 //DoWritePreface(rTw,rLabel,pContext)
395 void vDevice::DoWritePreface(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
396  (void) pContext; (void) rTw;
397  // virtual interface for token-output: device specific parameters
398  FD_DHV("vDevice("<<mName<<")::DoWritePreface()");
399  // write faudes-time scaling-factor
400  Token atoken;
401  atoken.SetEmpty("TimeScale");
402  atoken.InsAttributeInteger("value",mTimeScale);
403  rTw<<atoken;
404 }
405 
406 
407 //DoWriteConfiguration(rTw,rLabel,pContext)
408 void vDevice::DoWriteConfiguration(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
409  (void) pContext; (void) rTw;
410  // virtual interface for for token-output: event configuration
411  FD_DHV("vDevice("<<mName<<")::DoWriteConfiguration()");
412  // figure section, write begin
413  std::string label=rLabel;
414  if(label == "") label = "EventConfiguration";
415  rTw.WriteBegin(label);
416  // loop events
417  for (EventSet::Iterator it = mpConfiguration->Begin(); it != mpConfiguration->End(); ++it) {
418  Token etoken;
419  const AttributeVoid& attr=mpConfiguration->Attribute(*it);
420  const AttributeDeviceEvent* attrp = dynamic_cast<const AttributeDeviceEvent*>(&attr);
421 #ifdef FAUDES_DEBUG_CODE
422  if(!attrp) {
423  std::stringstream errstr;
424  errstr << "Invalid attribute configuration";
425  throw Exception("vDevice::DoWriteConfiguration", errstr.str(), 550);
426  }
427 #endif
428  if(!attrp) continue;
429  // figure whether we have an effetively default attribute
430  // note: we should have a smart token writer to figure empty sections automatically
431  bool def=false;
432  if(attrp->IsInput())
433  if(attrp->Inputp()->IsDefault()) def=true;
434  if(attrp->IsOutput())
435  if(attrp->Outputp()->IsDefault()) def=true;
436  // case a: no attribute value
437  if(def) {
438  etoken.SetEmpty("Event");
439  etoken.InsAttributeString("name",mpConfiguration->SymbolicName(*it));
440  if(attrp->IsInput()) etoken.InsAttributeString("iotype","input");
441  if(attrp->IsOutput()) etoken.InsAttributeString("iotype","output");
442  rTw << etoken;
443  }
444  // case b: incl attribute value
445  if(!def) {
446  etoken.SetBegin("Event");
447  etoken.InsAttributeString("name",mpConfiguration->SymbolicName(*it));
448  if(attrp->IsInput()) etoken.InsAttributeString("iotype",std::string("input"));
449  if(attrp->IsOutput()) etoken.InsAttributeString("iotype","output");
450  rTw << etoken;
451  attrp->Write(rTw,"",pContext);
452  etoken.SetEnd("Event");
453  rTw << etoken;
454  }
455  }
456  // loop done
457  rTw.WriteEnd(label);
458 
459 
460  // write event-configuration
461  //if(mpConfiguration) mpConfiguration->XWrite(rTw,label);
462 }
463 
464 //DoRead(rTr,rLabel,pContext)
465 void vDevice::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
466  (void) pContext; (void) rLabel; (void) rTr;
467  // virtual interface for token-input: dispatcher
468  FD_DHV("vDevice("<<mName<<")::DoRead()");
469  Clear();
470  // set default label if no label specified (configure in type constructor)
471  std::string label = rLabel;
472  if(label=="") label = mDefaultLabel;
473  // read my section
474  Token btag;
475  rTr.ReadBegin(label,btag);
476  // extract name
477  Name(label);
478  if(btag.ExistsAttributeString("name"))
479  Name(btag.AttributeStringValue("name"));
480  // call DoReadConfiguration and DoReadPreface
481  DoReadPreface(rTr,"",pContext);
482  DoReadConfiguration(rTr,"",pContext);
483  // end of my section
484  rTr.ReadEnd(label);
485  // organize internal data structures
486  Compile();
487 }
488 
489 //DoReadConfiguration(rTr,rLabel,pContext)
490 void vDevice::DoReadConfiguration(TokenReader& rTr,const std::string& rLabel, const Type* pContext){
491  // bail out on bad configuration
492  if(!mpConfiguration) return;
493  // set default label if no label specified
494  std::string label=rLabel;
495  if(label=="") label="EventConfiguration";
496  // set name
497  mpConfiguration->Name(label);
498  // test for begin
499  /*
500  Token token;
501  rTr.Peek(token);
502  if(!token.IsBegin()) return;
503  if(token.StringValue()!=label) return;
504  */
505  // read begin
506  rTr.ReadBegin(label);
507  FD_DHV("vDevice("<<mName<<")::DoReadConfiguration()");
508  // prepare attribute
510  AttributeDeviceEvent* attrp = dynamic_cast<AttributeDeviceEvent*>(vattrp);
511 #ifdef FAUDES_DEBUG_CODE
512  if(!attrp) {
513  std::stringstream errstr;
514  errstr << "Invalid attribute configuration" << rTr.FileLine();
515  throw Exception("vDevice::DoReadConfiguration", errstr.str(), 550);
516  }
517 #endif
518  if(!attrp) return;
519  FD_DHV("vDevice::DoReadConfiguration(" << this << "): attribute type " << typeid(*attrp).name());
520  // loop tokens
521  std::string name;
522  std::string iotype;
523  while(!rTr.Eos(label)) {
524  Token token;
525  rTr.Peek(token);
526 
527  // snse and digest pre 2.16 format
528  if(token.IsString()) {
529  rTr.Get(token);
530  name=token.StringValue();
531  // read faudes attribute
532  attrp->Read(rTr,"",pContext);
533  // skip unknown faudes attributes
534  AttributeVoid::Skip(rTr);
535  // insert element with attribute
536  Idx index=mpConfiguration->Insert(name);
537  mpConfiguration->Attribute(index,*attrp);
538  continue;
539  }
540 
541  // read element section
542  if(token.IsBegin())
543  if(token.StringValue()=="Event") {
544  FD_DHV("vDevice(" << this << ")::DoReadConfiguration(..): " << token.Str() << "\"");
545  rTr.ReadBegin("Event",token);
546  name=token.AttributeStringValue("name");
547  iotype=token.AttributeStringValue("iotype");
548  // input event
549  if(iotype=="input")
550  attrp->ReadInput(rTr);
551  // output event
552  if(iotype=="output")
553  attrp->ReadOutput(rTr);
554  // valid
555  if((iotype=="input") || (iotype=="output")) {
556  // insert element with attribute
557  Idx index=mpConfiguration->Insert(name);
558  mpConfiguration->Attribute(index,*attrp);
559  rTr.ReadEnd("Event");
560  continue;
561  }
562  }
563  // cannot process token
564  delete attrp;
565  std::stringstream errstr;
566  errstr << "Invalid token of type " << token.Type() << " at " << rTr.FileLine();
567  throw Exception("vDevice::DoReadConfiguration", errstr.str(), 50);
568  }
569  rTr.ReadEnd(label);
570  delete attrp;
571 }
572 
573 //DoReadPreface(rTr,rLabel,pContext)
574 void vDevice::DoReadPreface(TokenReader& rTr, const std::string& rLabel, const Type* pContext){
575  (void) pContext; (void) rLabel; (void) rTr;
576  // virtual interface for token-input: device specific parameters
577  FD_DHV("vDevice("<<mName<<")::DoReadPreface()");
578 
579  // sense and digest pre 2.16 format
580  Token token;
581  rTr.Peek(token);
582  if(token.IsString()) {
583  mName = rTr.ReadString();
584  mTimeScale = rTr.ReadInteger();
585  return;
586  }
587 
588  // loop my members
589  while(true) {
590  Token token;
591  rTr.Peek(token);
592  // time scale
593  if(token.IsBegin())
594  if(token.StringValue()=="TimeScale") {
595  rTr.ReadBegin("TimeScale", token);
596  mTimeScale=token.AttributeIntegerValue("value");
597  rTr.ReadEnd("TimeScale");
598  continue;
599  }
600  // break on unknown
601  break;
602  }
603 }
604 
605 // Configure(Idx,AttributeDeviceEvent&)
606 void vDevice::Configure(Idx event, const AttributeDeviceEvent& attr){
607  //inserts an attributed event and compiles internal data structure
608  FD_DHV("vDevice(" << mName << ")::Configure(event)");
609  Stop();
610  // test type
612  if(typeid(attr)!=typeid(*cap)) {
613  std::stringstream errstr;
614  errstr << "Cannot cast attribute to device event attribute";
615  throw Exception("vDevice::Configure", errstr.str(), 550);
616  }
617  // record
618  mpConfiguration->Insert(event);
619  mpConfiguration->Attribute(event,attr);
620  // setup internal data structure
621  Compile();
622 }
623 
624 // Configure(EventSet)
625 void vDevice::Configure(const EventSet& rPhysicalEvents){
626  FD_DHV("vDevice(" << mName << ")::Configure(alphabet)");
627  Stop();
628  // test type
630  const AttributeVoid* oap = rPhysicalEvents.AttributeType();
631  if(typeid(*oap)!=typeid(*cap)) {
632  std::stringstream errstr;
633  errstr << "Cannot cast attribute to device event attribute";
634  throw Exception("vDevice::Configure", errstr.str(), 550);
635  }
636  // record events
637  for(EventSet::Iterator eit=rPhysicalEvents.Begin(); eit!=rPhysicalEvents.End(); eit++) {
638  const AttributeVoid attr = rPhysicalEvents.Attribute(*eit);
639  mpConfiguration->Insert(*eit);
640  mpConfiguration->Attribute(*eit,attr); // why does this do the job???
641  }
642  // setup internal data structure
643  Compile();
644 }
645 
646 //Compile()
647 void vDevice::Compile(void){
648  FD_DHV("vDevice(" << mName << ")::Compile()");
649  // Compile() implies Stop()
650  Stop();
651  // clear input- and output-set
652  mInputs.Clear();
653  mOutputs.Clear();
654  // loop over events and set outputs and inputs
655  mInputs.Clear();
656  mOutputs.Clear();
657  for(EventSet::Iterator eit=mpConfiguration->Begin(); eit!=mpConfiguration->End(); eit++) {
659  AttributeDeviceEvent* dattr = dynamic_cast< AttributeDeviceEvent* >(attr);
660  if(!dattr) {
661  std::stringstream errstr;
662  errstr << "Cannot cast attribute to device event attribute";
663  throw Exception("vDevice()::Configure", errstr.str(), 550);
664  }
665  if(dattr->IsInput()) mInputs.Insert(*eit);
666  if(dattr->IsOutput()) mOutputs.Insert(*eit);
667  }
668 }
669 
670 //UseCondition(faudes_mutex_t*)
671 void vDevice::UseCondition(faudes_mutex_t* wmutex, faudes_cond_t* wcond) {
672  // tell device which condition variable to use
673  FD_DHV("vDevice(" << mName << ")::UseCondition()");
674  // set cond/mutex for wait inputs
675  if(wmutex) pWaitMutex=wmutex;
676  if(wcond) pWaitCondition=wcond;
677 }
678 
679 //UseBuffer(mutex, buffer)
680 void vDevice::UseBuffer(faudes_mutex_t* bmutex, std::deque<Idx>* bbuffer) {
681  // Tell the device which buffer to use
682  FD_DHV("vDevice(" << mName << ")::UseBuffer()");
683  //set input buffer and buffer-mutex and
684  if(bmutex) pBufferMutex=bmutex;
685  if(bbuffer) pInputBuffer=bbuffer;
686 }
687 
688 // Outputs()
689 const EventSet& vDevice::Outputs(void) const {
690  return mOutputs;
691 }
692 
693 // Inputs()
694 const EventSet& vDevice::Inputs(void) const {
695  return mInputs;
696 }
697 
698 //FtuToSystemTime(int)
699 faudes_systime_t vDevice::FtuToSystemTime(Time::Type duration){
700  // convert faudes-time to sys.time)
701  FD_DHV("vDevice("<<mName<<")::FtuToSystemTime(" << duration << "): using scale " << mTimeScale);
702  //prepare result
703  faudes_systime_t res;
704  //get current system-time
705  faudes_systime_t now;
706  faudes_gettimeofday(&now);
707  //convert duration to real time msec
708  long int durationMsec = mTimeScale*duration;
709  //convert duration from msec (long int) to nsec (sys.time)
710  faudes_systime_t delta;
711  delta.tv_sec = durationMsec/1000;
712  delta.tv_nsec = ( durationMsec - (delta.tv_sec*1000) ) *1000000;
713  //specify the absolut point of time
714  faudes_sumsystime(now,delta,&res);
715  // done
716  return res;
717 }
718 
719 // FtuToMs(Time::Type)
720 long int vDevice::FtuToMs(Time::Type faudes_time){
721  //convert faudes-time to realtime in ms
722  FD_DHV("vDevice("<<mName<<")::FtuToMs() ");
723  // avoid buffer-overflow while trying to convert an
724  // "infinite" periode of time
725  if(faudes_time>= Time::Max()/ (mTimeScale+1)) return Time::Max();
726  // return real time in ms
727  return mTimeScale*faudes_time;
728 }
729 
730 // MsToFtu(long int)
731 Time::Type vDevice::MsToFtu(long int real_time){
732  //Convert real time in ms to faudes-time
733 
734  FD_DHV("vDevice(" << mName << ")::MsToFtu()");
735  return (long int)((1.0/mTimeScale)*real_time/1000*1000);
736 }
737 
738 //CurrentTime(void)
740  //return current faudes-time
741  FD_DHV("vDevice("<<mName<<")::CurrentTime() ");
742  //get current system-time
743  faudes_systime_t now;
744  faudes_gettimeofday(&now);
745  // compute the time elapsed since backgroundthread-startup
746  faudes_systime_t diff;
747  faudes_diffsystime(now,mTimeZero,&diff);
748  // convert physical time to faudes-time
749  return (long int) ((1000.0/mTimeScale) * (diff.tv_sec + diff.tv_nsec*1e-9));
750 }
751 
752 //CurrentTime(now)
754  // set current faudes-time
755  FD_DHV("vDevice(" << mName <<")::CurrentTime("<<Time::Str(now) <<")");
757 }
758 
759 //CurrentTimeMs()
760 long int vDevice::CurrentTimeMs(void) {
761  //return current real-time in ms
762  FD_DHV("vDevice("<<mName<<")::CurrentTimeMs() ");
763  //get current system-time
764  faudes_systime_t now;
765  faudes_gettimeofday(&now);
766  // compute the time elapsed since backgroundthread-startup
767  faudes_systime_t diffTime;
768  faudes_diffsystime(now,mTimeZero,&diffTime);
769  // convert current physical time to msecs
770  return 1000*diffTime.tv_sec + diffTime.tv_nsec/1000000;
771 }
772 
773 
774 //CurrentTimeMs(long int)
775 void vDevice::CurrentTimeMs(long int nowms){
776  // set current real-time in ms
777  FD_DHV("vDevice("<<mName<<")::CurrentTimeMs(nowms) ");
778  // set for now =0
779  faudes_systime_t now;
780  faudes_gettimeofday(&now);
781  // adjust to now
782  faudes_systime_t delta;
783  delta.tv_sec = nowms/1000;
784  delta.tv_nsec = 1000000*(nowms%1000);
785  // do adjust
786  faudes_diffsystime(now,delta,&mTimeZero);
787  // report
788  /*
789  time_t systime;
790  time(&systime);
791  struct tm* timeinfo;
792  timeinfo= localtime(&systime);
793  char strbuf[80];
794  strftime(strbuf,80,"%X",timeinfo);
795  */
796 }
797 
798 
799 // WaitInputs(Time::Type)
801  //wait a specified time for input events to occur
802 
803  FD_DHV("vDevice("<<mName<<")::WaitInputs("<< duration << ")");
804 
805  // adjust arguments TODO
806  if(duration> 3600*24) { duration= 3600*24;};
807 
808  // if this is a nontrivial wait, flush outputs
809  if(duration>0) FlushOutputs();
810 
811  // wait mutex gets released while waiting
812  faudes_mutex_lock(pWaitMutex);
813 
814  // get preliminary result
815  bool sr=InputReady();
816 
817  // actually wait only if there are no input yet
818  if(!sr && duration>0) {
819 
820 #ifdef FAUDES_DEBUG_IOPERF
821  // performance time stamp
822  faudes_systime_t now;
823  faudes_gettimeofday(&now);
825 #endif
826 
827  //convert duration in systemtime
828  faudes_systime_t condtime = vDevice::FtuToSystemTime(duration);
829  //wait for report from background thread about on available events
830  FD_DHV("vDevice("<<mName<<")::WaitInputs("<< duration << "): waiting for condition");
831  faudes_cond_timedwait(pWaitCondition, pWaitMutex, &condtime);
832  FD_DHV("vDevice("<<mName<<")::WaitInputs("<< duration << "): release at "<< CurrentTime());
833  // update result
834  sr=InputReady();
835 
836 #ifdef FAUDES_DEBUG_IOPERF
837  // performance time stamp
838  faudes_gettimeofday(&now);
847 #endif
848 
849  }
850 
851  // release wait mutex
852  faudes_mutex_unlock(pWaitMutex);
853 
854 
855  return sr;
856 }
857 
858 
859 // WaitInputsMs(long int)
860 bool vDevice::WaitInputsMs(long int duration) {
861  //wait a specified time for input events to occur
862 
863  FD_DHV("vDevice("<<mName<<")::WaitInputsMs("<< duration << ")");
864 
865  // adjust arguments TODO
866  if(duration> 30*3600*24) { duration= 30*3600*24;};
867 
868  // if this is a nontrivial wait, flush outputs
869  if(duration>0) FlushOutputs();
870 
871  // wait mutex gets released while waiting
872  faudes_mutex_lock(pWaitMutex);
873 
874  // get preliminary result
875  bool sr=InputReady();
876  // actually wait onnly if there are no input yet
877  if(!sr && duration>0) {
878 
879 #ifdef FAUDES_DEBUG_IOPERF
880  // performance time stamp
881  faudes_systime_t now;
882  faudes_gettimeofday(&now);
884 #endif
885 
886  //convert duration in nsec spec
887  faudes_systime_t condtime;
888  faudes_msdelay(duration,&condtime);
889  //wait for report from background thread on available events
890  faudes_cond_timedwait(pWaitCondition, pWaitMutex, &condtime);
891  // update result
892  sr=InputReady();
893 
894 #ifdef FAUDES_DEBUG_IOPERF
895  // performance time stamp
896  faudes_gettimeofday(&now);
905 #endif
906 
907  }
908 
909  // released wait mutex
910  faudes_mutex_unlock(pWaitMutex);
911 
912  return sr;
913 }
914 
915 // FlushOutputs(void)
917 }
918 
919 // ResetRequest()
921  bool res=false;
922  faudes_mutex_lock(pBufferMutex);
923  res=mResetRequest;
924  mResetRequest=false;
925  faudes_mutex_unlock(pBufferMutex);
926  return res;
927 }
928 
929 //ReadInputs()
931  //reads input-buffer and returns first occured events by index
932 
933  FD_DHV("vDevice("<<mName<<")::ReadInput()");
934  // prepare result, invalid
935  Idx res=0;
936 
937  // take oldest entry
938  faudes_mutex_lock(pBufferMutex);
939  if(!pInputBuffer->empty()) {
940  res=pInputBuffer->front();
941  pInputBuffer->pop_front();
942  }
943  faudes_mutex_unlock(pBufferMutex);
944  FD_DHV("vDevice("<<mName<<")::ReadInput(): found: " << res);
945  return res;
946 }
947 
948 
949 //PeekInputs()
951  //reads input-buffer and returns first occured events by index
952  // does not remove the event from the buffer
953 
954  FD_DHV("vDevice("<<mName<<")::PeekInput()");
955  // prepare result, invalid
956  Idx res=0;
957 
958  // take oldest entry
959  faudes_mutex_lock(pBufferMutex);
960  if(!pInputBuffer->empty()) {
961  res=pInputBuffer->front();
962  }
963  faudes_mutex_unlock(pBufferMutex);
964 
965  FD_DHV("vDevice("<<mName<<")::PeekInput(): found: " << res);
966  return res;
967 }
968 
969 
970 //InputReady()
972  // returns true if a input-event occured
973 
974  FD_DHV("vDevice("<<mName<<")::ReadInput()");
975  //prepare result
976  bool res;
977  //read buffer
978  faudes_mutex_lock(pBufferMutex);
979  res= !mInputBuffer.empty();
980  faudes_mutex_unlock(pBufferMutex);
981 
982  return res;
983 }
984 
985 
986 // timing analysis
988 #ifdef FAUDES_DEBUG_IOPERF
989 
990  FD_DHV("vDevice::Performance(" << Name() << "): " << mPerformanceBeginIterator << " " << mPerformanceEndIterator);
991 
992  // have samples
993  SampledDensityFunction busyduration;
994  busyduration.Dim(50);
995  busyduration.Clear();
996  busyduration.Name("performance " + Name() + " (busy duration in usecs)");
997 
998  // inspect time stamps
999  for(int i = mPerformanceBeginIterator; ;i++){
1000  if(i>= FAUDES_DEBUG_IOPERF_SAMPLES) i=0;
1001  int ip = i+1;
1002  if(ip>= FAUDES_DEBUG_IOPERF_SAMPLES) ip =0;
1003  if(ip==mPerformanceEndIterator) break;
1004  faudes_systime_t busy;
1006  busyduration.Sample(busy.tv_sec*1000000 + busy.tv_nsec/1000);
1007  }
1008 
1009  // compile
1010  busyduration.Compile();
1011 
1012  // done
1013  return busyduration;
1014 
1015 #else
1016 
1017  FD_DHV("vDevice::Performance(" << Name() << "): not enabled");
1018  SampledDensityFunction busyduration;
1019  busyduration.Name("performance monitoring not enabled");
1020  return busyduration;
1021 
1022 #endif
1023 }
1024 
1025 // WritePerformance
1027 #ifdef FAUDES_DEBUG_IOPERF
1028  SampledDensityFunction busyduration=Performance();
1029  // token output
1030  busyduration.Write();
1031  // pretty print
1032  std::cout << busyduration.Str() << std::endl;
1033 #endif
1034 }
1035 
1036 // ClearPerformance
1038 
1039 #ifdef FAUDES_DEBUG_IOPERF
1042 #endif
1043 
1044 }
1045 
1046 } // name space
1047 
void faudes_sumsystime(const faudes_systime_t &begin, const faudes_systime_t &duration, faudes_systime_t *res)
void faudes_msdelay(faudes_mstime_t msecs, faudes_systime_t *end)
void faudes_diffsystime(const faudes_systime_t &end, const faudes_systime_t &begin, faudes_systime_t *res)
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
faudes type implementation macros, overall
Definition: cfl_types.h:946
Attribute for the configuration of a input or output mapping.
Definition: iop_vdevice.h:68
const AttributeVoid * pOutputPrototype
Output Prototype (set to nontrivial attribute in derived classes)
Definition: iop_vdevice.h:148
void DefaultOutput(void)
Set to default output attribute.
Definition: iop_vdevice.h:97
const AttributeVoid * Outputp(void) const
Get output mapping (return 0 if its not an output)
Definition: iop_vdevice.h:133
const AttributeVoid * Inputp(void) const
Get input mapping (return 0 if its not a input)
Definition: iop_vdevice.h:136
virtual void Output(const AttributeVoid &rOutputAttribute)
Set output attribute.
Definition: iop_vdevice.h:109
virtual void Clear(void)
Clear.
Definition: iop_vdevice.cpp:82
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Reads the attribute from TokenReader, see AttributeVoid for public wrappers.
void DoAssign(const AttributeDeviceEvent &rSrcAttr)
Assignment.
Definition: iop_vdevice.cpp:90
virtual void Input(const AttributeVoid &rInputAttribute)
Set input attribute.
Definition: iop_vdevice.h:115
const AttributeVoid * pInputPrototype
Input Prototype (set to nontrivial attribute in derived classes)
Definition: iop_vdevice.h:151
virtual void ReadInput(TokenReader &rTr)
Read input attribute.
Definition: iop_vdevice.h:127
AttributeDeviceEvent(void)
Default constructor (no attributes, aka undefined)
Definition: iop_vdevice.cpp:43
bool IsOutput(void) const
Does this attribute define an output mapping?
Definition: iop_vdevice.h:91
virtual ~AttributeDeviceEvent(void)
Destructor.
Definition: iop_vdevice.cpp:70
void DefaultInput(void)
Set to default input attribute.
Definition: iop_vdevice.h:103
AttributeVoid * mpInputAttribute
Input Attribute (use cast in derived classes)
Definition: iop_vdevice.h:145
static const AttributeVoid * FallbackAttributep(void)
Fallback attribute type (initialize on first use static construct)
Definition: iop_vdevice.cpp:76
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Writes the attribute to TokenWriter, see AttributeVoid for public wrappers.
AttributeVoid * mpOutputAttribute
Output Attribute (use cast in derived classes)
Definition: iop_vdevice.h:136
bool IsInput(void) const
Does this attribute define a input mapping?
Definition: iop_vdevice.h:94
virtual void ReadOutput(TokenReader &rTr)
Read output attribute.
Definition: iop_vdevice.h:121
Minimal Attribute.
AttributeVoid(void)
Constructor.
virtual bool IsDefault(void) const
Test for default value.
static void Skip(TokenReader &rTr)
Skip attribute tokens.
void Write(TokenWriter &rTw) const
const std::string & Name(void) const
std::string Str(void) const
Faudes exception class.
Set of indices with symbolic names.
Definition: cfl_nameset.h:69
void SymbolicName(Idx index, const std::string &rName)
Set new name for existing index.
bool Insert(const Idx &rIndex)
Add an element by index.
void Sample(Time::Type time)
Int Type
Datatype for point on time axis.
static std::string Str(Type time)
convert to string
static Type Step(void)
Smallest representable time step.
static Type Max(void)
Maximum time, associated with infinitiy.
A TokenReader reads sequential tokens from a file or string.
long int ReadInteger(void)
Read integer token.
std::string FileLine(void) const
Return "filename:line".
bool Eos(const std::string &rLabel)
Peek a token and check whether it ends the specified section.
void ReadEnd(const std::string &rLabel)
Close the current section by matching the previous ReadBegin().
std::string ReadString(void)
Read string token.
void ReadBegin(const std::string &rLabel)
Open a section by specified label.
bool Get(Token &token)
Get next token.
bool Peek(Token &token)
Peek next token.
std::string FileName(void) const
Access the filename.
A TokenWriter writes sequential tokens to a file, a string or stdout.
void WriteEnd(const std::string &rLabel)
Write end label.
void WriteBegin(const std::string &rLabel)
Write begin label.
Tokens model atomic data for stream IO.
Definition: cfl_token.h:53
std::string Str(void) const
Pretty print string representation.
Definition: cfl_token.cpp:1296
const std::string & StringValue(void) const
Get string value of a name token.
Definition: cfl_token.cpp:177
Int AttributeIntegerValue(const std::string &name)
Access attribute value.
Definition: cfl_token.cpp:396
bool IsString(void) const
Test token Type.
Definition: cfl_token.cpp:243
bool ExistsAttributeString(const std::string &name)
Test attibute existence.
Definition: cfl_token.cpp:355
bool IsBegin(void) const
Test token Type.
Definition: cfl_token.cpp:258
void SetEmpty(const std::string &rName)
Initialize as empty-tag token.
Definition: cfl_token.cpp:105
void SetBegin(const std::string &rName)
Initialize as Begin token.
Definition: cfl_token.cpp:91
void InsAttributeInteger(const std::string &name, Int value)
Insert named attribute with integer value.
Definition: cfl_token.cpp:318
void InsAttributeString(const std::string &name, const std::string &value)
Insert named attribute with string value.
Definition: cfl_token.cpp:309
const std::string & AttributeStringValue(const std::string &name)
Access attribute value.
Definition: cfl_token.cpp:385
TokenType Type(void) const
Get token Type.
Definition: cfl_token.cpp:198
Base class of all libFAUDES objects that participate in the run-time interface.
Definition: cfl_types.h:239
void Read(const std::string &rFileName, const std::string &rLabel="", const Type *pContext=0)
Read configuration data from file with label specified.
Definition: cfl_types.cpp:261
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Write configuration data to a string.
Definition: cfl_types.cpp:169
virtual Type * New(void) const
Construct on heap.
Definition: cfl_types.cpp:54
void Write(const Type *pContext=0) const
Write configuration data to console.
Definition: cfl_types.cpp:139
virtual const std::string & TypeName(void) const
Get objects's type name.
Definition: cfl_types.cpp:132
Virtual base class to define the interface for event io.
Definition: iop_vdevice.h:261
int mPerformanceBeginIterator
Definition: iop_vdevice.h:832
bool mResetRequest
Reset request marker (mutexed)
Definition: iop_vdevice.h:806
virtual void DoWrite(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Token output, see Type::Write for public wrappers.
Time::Type mMaxSyncGap
Toleance for time sync.
Definition: iop_vdevice.h:791
int mTimeScale
FauDES-time: scaling factor in ms/ftu.
Definition: iop_vdevice.h:788
virtual Idx PeekInput(void)
Peek for sensed events.
faudes_systime_t mTimeZero
physical timepoint zero
Definition: iop_vdevice.h:785
faudes_mutex_t * pBufferMutex
Actual mutex for input buffer (mutexted)
Definition: iop_vdevice.h:803
virtual bool WaitInputsMs(long int duration)
Wait for input trigger.
const std::string & Name(void) const
Get device name.
static vDevice * FromTokenReader(TokenReader &rTr)
Construct on heap from token reader.
virtual void Clear(void)
Clear all configuration.
faudes_cond_t mWaitCondition
Default Wait Condition.
Definition: iop_vdevice.h:776
virtual Time::Type MsToFtu(long int real_time)
convert duration in ms to faudes-time units
faudes_systime_t * mpPerformanceWaitEnter
Structures to store time-samples in.
Definition: iop_vdevice.h:827
virtual const EventSet & Inputs(void) const
Get inputs as plain set.
virtual void Compile(void)
Compile inner data-structures.
std::string mDefaultLabel
Default label for token io.
Definition: iop_vdevice.h:721
faudes_cond_t * pWaitCondition
Actual Wait Condition.
Definition: iop_vdevice.h:782
virtual long int FtuToMs(Time::Type faudes_time)
convert duration from fauDES-time units to ms
void ResetPerformance(void)
Clear performance (need compiletime option)
SampledDensityFunction Performance(void)
Get performance (need compiletime option)
faudes_mutex_t mWaitMutex
Default Wait Condition Mutex.
Definition: iop_vdevice.h:773
virtual std::string StatusString(void)
Get status as infromal string.
static std::set< vDevice * > & AllDevices(void)
virtual bool ResetRequest(void)
A device may ask for a reset by returning true for ResetRequest().
virtual ~vDevice(void)
Explicit destructor.
void UseBuffer(faudes_mutex_t *bmutex, std::deque< Idx > *bbuffer)
Tell the device which buffer to use for inputs.
static void StopAll(void)
Stop all devices.
virtual void DoReadPreface(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Reads non-event-configuration data from TokenReader.
virtual DeviceState Status(void)
Get status.
Definition: iop_vdevice.h:486
virtual void Stop(void)
Deactivate the device.
virtual void Start(void)
Activate the device.
EventSet * mpConfiguration
Overall event configuration (uses cast for type)
Definition: iop_vdevice.h:761
EventSet mInputs
All inputs.
Definition: iop_vdevice.h:764
EventSet mOutputs
All outputs.
Definition: iop_vdevice.h:767
virtual faudes_systime_t FtuToSystemTime(Time::Type duration)
Convert faudes time unit duration to system time.
std::deque< Idx > mInputBuffer
Default Fifo buffer for input readings.
Definition: iop_vdevice.h:794
virtual void Configure(Idx event, const AttributeDeviceEvent &attr)
Insert/edit input or output configuration.
virtual void Reset(void)
Reset device.
static vDevice * FromFile(const std::string &rFileName)
Construct on heap from file.
virtual void DoReadConfiguration(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Reads event-configuration data from TokenReader.
virtual Idx ReadInput(void)
Read sensed input events.
virtual void DoWritePreface(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Writes non-event-configuration data from TokenWriter.
virtual void DoWriteConfiguration(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Writes event-configuration to TokenWriter.
virtual bool InputReady(void)
Report whether a input-event is ready.
virtual bool WaitInputs(Time::Type duration)
Wait for input trigger.
faudes_mutex_t * pWaitMutex
Actual Wait Condition Mutex.
Definition: iop_vdevice.h:779
void UseCondition(faudes_mutex_t *wmutex, faudes_cond_t *wcond)
Tell the device which condition to use for waiting.
std::string mName
Name.
Definition: iop_vdevice.h:758
std::deque< Idx > * pInputBuffer
Actual Fifo buffer for input readings.
Definition: iop_vdevice.h:797
DeviceState
Enum for device stages.
Definition: iop_vdevice.h:270
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Token input, see Type::DRead for public wrappers.
faudes_systime_t * mpPerformanceWaitExit
Definition: iop_vdevice.h:828
virtual long int CurrentTimeMs(void)
Report physical time in ms.
int mPerformanceEndIterator
Global iterator.
Definition: iop_vdevice.h:831
virtual Time::Type CurrentTime(void)
Report physical time in ftu.
virtual void FlushOutputs(void)
Flush pending IO Operations.
DeviceState mState
Status: running, starting etc.
Definition: iop_vdevice.h:770
vDevice(void)
Default constructor.
faudes_mutex_t mBufferMutex
Default mutex for input buffer (mutexted)
Definition: iop_vdevice.h:800
void WritePerformance(void)
Convenience method.
virtual const EventSet & Outputs(void) const
Get outputs as plain set.
Container of devices.
Definition: iop_xdevice.h:49
virtual const AttributeVoid * AttributeType(void) const
Attribute typeinfo.
Definition: cfl_baseset.h:2171
virtual void Clear(void)
Clear all set.
Definition: cfl_baseset.h:1902
Iterator End(void) const
Iterator to the end of set.
Definition: cfl_baseset.h:1896
virtual AttributeVoid * Attributep(const T &rElem)
Attribute access.
Definition: cfl_baseset.h:2279
Iterator Begin(void) const
Iterator to the begin of set.
Definition: cfl_baseset.h:1891
virtual const AttributeVoid & Attribute(const T &rElem) const
Attribute access.
Definition: cfl_baseset.h:2290
const std::string & Name(void) const
Return name of TBaseSet.
Definition: cfl_baseset.h:1755
Type * NewFaudesObject(const std::string &rTypeName)
Instantiate faudes typed objects by type name.
Hardware access via comedi.
Simple networked events via TCP/IP.
Virtual device for interface definition
#define FD_DHV(message)
Definition: iop_vdevice.h:37
#define FD_DH(message)
Definition: iop_vdevice.h:27
#define FAUDES_DEBUG_IOPERF_SAMPLES
Definition: iop_vdevice.h:50
Hardware access via comedi.
Virtual device for interface definition
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
Discrete density function approximation.

libFAUDES 2.32b --- 2024.03.01 --- c++ api documentaion by doxygen