iop_xdevice.cpp
Go to the documentation of this file.
1 /** @file iop_xdevice.cpp Device container with vDevice interface */
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_xdevice.h"
14 
15 #include "iop_simplenet.h"
16 #include "iop_comedi.h"
17 #include "iop_wago.h"
18 #include "iop_serial.h"
19 #include "iop_modbus.h"
20 #include "iop_d3ripURT.h"
21 #include "iop_d3ripDART.h"
22 
23 namespace faudes {
24 
25 /*
26  **********************************************
27  **********************************************
28  **********************************************
29 
30  implementation: xDevice
31 
32  **********************************************
33  **********************************************
34  **********************************************
35  */
36 
37 // std faudes
38 FAUDES_TYPE_IMPLEMENTATION(DeviceContainer,xDevice,vDevice)
39 
40 // autoregister
41 volatile static AutoRegisterType<xDevice> gRtiRegisterDeviceContainer("DeviceContainer");
42 
43 //constructor
44 xDevice::xDevice(void) : vDevice() {
45  FD_DHV("xDevice(" << mName << ")::xDevice()");
46  mName="IoDevices";
47  // have appropriate default label
48  mDefaultLabel="DeviceContainer";
49 
50  // auto register fix:
51  // for some reasons the global register objects do not work properly.
52  // since the xdevice is autoregeistered by the rti, we ask the constructor
53  // to register the other devices
54 
55 #ifdef FAUDES_IODEVICE_SIMPLENET
56  volatile static AutoRegisterType<nDevice> gRtiIORegisterSimplenetDevice("SimplenetDevice");
57 #endif
58 #ifdef FAUDES_IODEVICE_COMEDI
59  volatile static AutoRegisterType<cDevice> gRtiIORegisterComediDevice("ComediDevice");
60 #endif
61 #ifdef FAUDES_IODEVICE_WAGO
62  volatile static AutoRegisterType<wDevice> gRtiIORegisterWagoDevice("WagoDevice");
63 #endif
64 #ifdef FAUDES_IODEVICE_SERIAL
65  volatile static AutoRegisterType<spiDevice> gRtiIORegisterSerialPiDevice("SpiDevice");
66 #endif
67 #ifdef FAUDES_IODEVICE_MODBUS
68  volatile static AutoRegisterType<mbDevice> gRtiIORegisterSerialPiDevice("ModbusDevice");
69 #endif
70 #ifdef FAUDES_IODEVICE_D3RIP_URT
71  volatile static AutoRegisterType<d3ripURTDevice> gRtiIORegisterD3ripUrtDevice("D3RipUrtDevice");
72 #endif
73 #ifdef FAUDES_IODEVICE_D3RIP_DART
74  volatile static AutoRegisterType<d3ripDARTDevice> gRtiIORegisterD3ripDartDevice("D3RipDartDevice");
75 #endif
76 
77 }
78 
79 // destructor
81  FD_DHV("xDevice(" << mName << ")::~xDevice()");
82  // loop to free devices.
83  Iterator dit;
84  for(dit=Begin();dit!=End();dit++){
85  delete (*dit);
86  }
87 }
88 
89 //FromTokenReader(rTr)
91  // construct from token reader
92  FD_DHV("xDevice::FromTokenReader()");
93  // allocate
94  xDevice* dev=new xDevice();
95  // read
96  dev->DoRead(rTr);
97  return dev;
98 }
99 
100 //FromFile(rFilename)
101 xDevice* xDevice::FromFile(const std::string& rFileName) {
102  // construct from file
103  FD_DHV("xDevice()::FromFile(" << rFileName <<")");
104  // peek first token
105  TokenReader tr(rFileName);
106  return FromTokenReader(tr);
107 }
108 
109 
110 //Status(void)
112 
113  FD_DHV("xDevice(" << mName << ")::Status() ");
114  //prepare result
116  //vector to store states of all devices integrated in xdevice
117  std::vector<xDevice::DeviceState> states;
118  //vector iterator
119  std::vector<DeviceState>::iterator vit;
120  vit = states.begin();
121  //device iterator
122  iterator dit;
123  //identify device state
124  for(dit=Begin();dit!=End();dit++){
125  //get state of current device and insert it in vector
126  states.push_back((DeviceState)(*dit)->Status());
127  //make sure it isnt the first entry
128  if(vit != states.begin()){
129  //if current entry doesnt equal previous
130  //decide depending on last command
131  if (*vit!=*vit--){
132  //if last command was start: "StartUp"
134  res = StartUp;
135  break;
136  }
137  //if last command was stop: "ShutDown"
138  if(!lastCommandWasStart){
139  res = ShutDown;
140  break;
141  }
142  }
143  }
144  //move on to next device
145  vit++;
146  }
147  //if for-loop finished all entries of vector "states" are equal
148  res = *states.begin();
149  return res;
150 }
151 
152 // Start(void)
153 void xDevice::Start(void) {
154 
155  FD_DHV("xDevice(" << mName <<")::Start()");
156  // start implies reset
157  Reset();
158  //start all existing devices
159  Iterator dit;
160  for(dit = Begin();dit!=End();dit++){
161  (*dit)->Start();
162  }
163  //remember this command
164  lastCommandWasStart = true;
165 }
166 
167 // Stop(void)
168 void xDevice::Stop(void) {
169 
170  FD_DHV("xDevice(" << mName <<")::Stop()");
171  // xDevice Reset
172  Reset();
173  // stop all existing devices
174  Iterator dit;
175  for(dit=Begin();dit!=End();dit++){
176  (*dit)->Stop();
177  }
178  //remember this command
179  lastCommandWasStart = false;
180 }
181 
182 // Reset(void)
183 void xDevice::Reset(void){
184  //clear dynamic data
185 
186  FD_DHV("xDevice(" << mName <<")::Reset()");
187  // device-iterator
188  Iterator dit;
189  for(dit=Begin();dit!=End();dit++){
190  (*dit)->Reset();
191  }
192  // call base to reset time and fifo
193  vDevice::Reset();
194 }
195 
196 // Clear(void)
197 void xDevice::Clear(void){
198  //clear static data
199 
200  FD_DHV("xDevice(" << mName << ")::Clear()");
201  // Stop running devices
202  Stop();
203  // device-iterator
204  Iterator dit;
205  // and clear all devices
206  for(dit=Begin();dit!=End();dit++){
207  (*dit)->Clear();
208  }
209  // destroy existing data
210  for(dit=Begin();dit!=End();dit++){
211  delete (*dit);
212  }
213  // compile with empty containers
214  Compile();
215 }
216 
217 // Insert(vDevice*)
218 void xDevice::Insert(vDevice* device){
219 
220  FD_DHV("xDevice("<<mName<<")::Insert(" << device << "):" << device->Name());
221  // insert any vdevice, but no xdevice
222  if(dynamic_cast<xDevice*>(device)) {
223  std::stringstream errstr;
224  errstr << "Attempt to insert xDevice into xDevice";
225  throw Exception("xDevice::Compile", errstr.str(), 550);
226  }
227  // add to mDevices
228  mDevices.push_back(device);
229  // and update compiled data
230  Compile();
231 }
232 
233 //Insert(rFilename)
234 void xDevice::Insert(const std::string& rFileName){
235  //inserts a device by filename
236  FD_DHV("xDevice("<<mName<<")::Insert(rFileName)");
237  //read device
238  vDevice* pdev = vDevice::FromFile(rFileName);
239  //insert device
240  Insert(pdev);
241  //and remember its name
242  mDeviceNames.push_back(rFileName);
243 }
244 
245 
246 // Compile(void)
247 void xDevice::Compile(void) {
248  //build up internal data-structures
249 
250  FD_DHV("xDevice("<<mName<<")::Compile()");
251  Stop();
252  // build up (event-idx,int)-map and memorize all existing events
253  // prepare containers
254  mInputs.Clear();
255  mOutputs.Clear();
256  mInputToDevice.clear();
257  mOutputToDevice.clear();
258  // temporary container
259  EventSet tmpSenEvents;
260  EventSet tmpActEvents;
261  // event-iterator
262  EventSet::Iterator eit;
263  // device-iterator
264  Iterator dit;
265  // helper
266  int j;
267  // iterate over existing devices
268  for(dit=Begin(), j=0; dit!=End(); dit++,j++){
269  // get events by Index
270  tmpSenEvents = (*dit)->Inputs();
271  tmpActEvents = (*dit)->Outputs();
272  //insert output-events in map
273  for(eit=tmpActEvents.Begin();eit!=tmpActEvents.End();eit++){
274  // test if actual event already exists in map
275  if(mOutputs.Exists(*eit)){
276  //throw exeption
277  std::stringstream errstr;
278  errstr << "Event already exists!";
279  throw Exception("xDevice()::Compile", errstr.str(), 550);
280  }
281  mOutputToDevice[*eit] = j;
282  }
283  // memorize events
284  mInputs.InsertSet(tmpSenEvents);
285  mOutputs.InsertSet(tmpActEvents);
286  // tell the device which mutex/condition-pair to use
287  (*dit)->UseCondition(pWaitMutex,pWaitCondition);
288  (*dit)->UseBuffer(pBufferMutex,pInputBuffer);
289  }//end iteration over existing devices
290  // set time scale from first device
291  if(Size()!=0) (*Begin())->TimeScale(mTimeScale);
292 }
293 
294 
295 //Configure(event,attr)
296 void xDevice::Configure(Idx event, const AttributeDeviceEvent& attr){
297  (void) event; (void) attr;
298  // cannot do vDevice style configuration of events
299 
300  FD_DHV("xDevice("<<mName<<")::Configure(Idx,attr): ");
301  std::stringstream errstr;
302  errstr << "Attempt to configure xDevice by event";
303  throw Exception("xDevice::Configure(Idx,attr)", errstr.str(), 550);
304 }
305 
306 //Configure(rEvents)
307 void xDevice::Configure(const EventSet& rEvents){
308  (void) rEvents;
309  // cannot do vDevice style configuration of events
310 
311  FD_DHV("xDevice("<<mName<<")::Configure(rEvents)");
312  std::stringstream errstr;
313  errstr << "Attempt to configure xDevice by events";
314  throw Exception("xDevice::Configure", errstr.str(), 550);
315 }
316 
317 
318 //CurrentTime(void)
320 
321  FD_DHV("xDevice("<<mName<<"): CurrentTime() ");
322  // throw exception if there is no device
323  if(Size()==0) {
324  std::stringstream errstr;
325  errstr << "xDevice owns no device!";
326  throw Exception("xDevice::CurrentTime", errstr.str(),550);
327  }
328  // ask first device
329  return (*Begin())->CurrentTime();
330 }
331 
332 
333 //CurrentTime(void)
334 long int xDevice::CurrentTimeMs(void) {
335  //debug flag: say hello
336  FD_DHV("xDevice("<<mName<<")::CurrentTimeMs() ");
337  // throw exception if there is no device
338  if(Size()==0) {
339  std::stringstream errstr;
340  errstr << "xDevice owns no device!";
341  throw Exception("xDevice::CurrentTimeMs", errstr.str(),550);
342  }
343  // ask first device
344  return (*Begin())->CurrentTimeMs();
345 }
346 
347 //CurrentTime(now)
349  //debug flag: say hello
350  FD_DHV("xDevice("<<mName<<")::CurrentTime("<<now<<") ");
351  // tell first device if such
352  if(Size()!=0) (*Begin())->CurrentTime(now);
353 }
354 
355 //CurrentTimeMs(now)
356 void xDevice::CurrentTimeMs(long int nowms) {
357  //debug flag: say hello
358 
359  FD_DHV("xDevice("<<mName<<")::CurrentTimeMs("<<nowms<<") ");
360  // tell first device if such
361  if(Size()!=0) (*Begin())->CurrentTimeMs(nowms);
362 }
363 
364 //DoWrite(rTr,rLabel)
365 void xDevice::DoWriteConfiguration(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
366  (void) rTw;
367 
368  FD_DHV("xDevice("<<mName<<")::DoWriteConfiguration()");
369  // hard coded begin
370  rTw.WriteBegin("Devices");
371  // define device-iterator
372  Iterator dit;
373  //iterate over all devices
374  for(Idx i=0; i<Size(); i++) {
375  //if device was read from an extra file
376  if(mDeviceNames.at(i) != ""){
377  //write path to TokenWriter
378  FD_DHV("xDevice("<<mName<<")::DoWrite(): "<<mDeviceNames.at(i));
379  rTw.WriteString(mDeviceNames.at(i)); //TODO: relativ path-names
380  }
381  //else device was directly read from base-config-file
382  else if(mDeviceNames.at(i) == ""){
383  //write configuration
384  FD_DHV("xDevice("<<mName<<")::DoWrite(): "<<mDeviceNames.at(i));
385  (mDevices.at(i))->Write(rTw);
386  }
387  }
388  rTw.WriteEnd("Devices");
389 }
390 
391 
392 // ResetRequest()
394  bool res=false;
395  Iterator dit;
396  for(dit=Begin();dit!=End();dit++){
397  res = res | (*dit)->ResetRequest();
398  }
399  return res;
400 }
401 
402 //DoRead(rTr,rLabel)
403 void xDevice::DoReadConfiguration(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
404  (void) rLabel; (void) pContext;
405 
406  FD_DHV("xDevice("<<mName<<")::DoReadConfiguration()");
407  //prepare token
408  Token token;
409  //prepare string
410  std::string filename = ""; //to store filename
411  std::string dirname = ""; //to store directory
412  std::string path; //to store absolut path
413  // have default section
414  std::string label = rLabel;
415  if(label=="") label = "Devices";
416  // read begin
417  rTr.ReadBegin(label);
418  // fill mDevices with devices specified in given file
419  while(!rTr.Eos("Devices")){
420  //peek token
421  rTr.Peek(token);
422  // if Token is a String we assume its the name of a file containing a device
423  if(token.Type()==Token::String) {
424  //read Token
425  rTr.Get(token);
426  //import filename
427  filename = token.StringValue();
428  //build up path to base-file
429  if(rTr.SourceMode()==TokenReader::File) dirname = ExtractDirectory(rTr.FileName());
430  //build up path to specified file
431  path = dirname.append(filename);
432  //insert device
433  Insert(path);
434  continue;
435  }
436  // if its not a file it has to be a device
437  else if(token.Type()==Token::Begin) {
438  // read device
439  vDevice* devp = vDevice::FromTokenReader(rTr);
440  // insert device mDevices
441  Insert(devp);
442  //record that this device was read inline
443  mDeviceNames.push_back("");
444  }
445  }
446  rTr.ReadEnd(label);
447 }
448 
449 
450 // WriteOutput(Idx)
452  FD_DHV("xDevice("<<mName<<")::WriteOutput()");
453  // identify corresponding device(if idx is unique)
454  int didx = mOutputToDevice[output];
455  FD_DH("xDevice("<<mName<<")::WriteOutput(): " << output << " to " << didx);
456  mDevices.at(didx)->WriteOutput(output);
457 }
458 
459 
460 // FlusgBufferes()
462  // iterate over all participating devices
463  for(Iterator dit=Begin(); dit!=End(); dit++)
464  (*dit)->FlushOutputs();
465 }
466 
467 
468 
469 } // name space
470 
471 
#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
Auto register faudes-type with specified type name.
Definition: cfl_registry.h:458
Faudes exception class.
Set of indices with symbolic names.
Definition: cfl_nameset.h:69
bool Exists(const Idx &rIndex) const
Test existence of index.
virtual void InsertSet(const NameSet &rOtherSet)
Inserts all elements of rOtherSet.
Int Type
Datatype for point on time axis.
A TokenReader reads sequential tokens from a file or string.
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().
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.
Mode SourceMode(void) const
Access stream mode.
A TokenWriter writes sequential tokens to a file, a string or stdout.
void WriteString(const std::string &rString)
Write string.
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
const std::string & StringValue(void) const
Get string value of a name token.
Definition: cfl_token.cpp:177
@ Begin
<label> (begin of section)
Definition: cfl_token.h:83
@ String
any string, space separated or quoted, must start with a letter
Definition: cfl_token.h:85
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 Write(const Type *pContext=0) const
Write configuration data to console.
Definition: cfl_types.cpp:139
Virtual base class to define the interface for event io.
Definition: iop_vdevice.h:261
int mTimeScale
FauDES-time: scaling factor in ms/ftu.
Definition: iop_vdevice.h:788
faudes_mutex_t * pBufferMutex
Actual mutex for input buffer (mutexted)
Definition: iop_vdevice.h:803
static vDevice * FromTokenReader(TokenReader &rTr)
Construct on heap from token reader.
faudes_cond_t * pWaitCondition
Actual Wait Condition.
Definition: iop_vdevice.h:782
EventSet mInputs
All inputs.
Definition: iop_vdevice.h:764
EventSet mOutputs
All outputs.
Definition: iop_vdevice.h:767
virtual void Reset(void)
Reset device.
static vDevice * FromFile(const std::string &rFileName)
Construct on heap from file.
void Name(const std::string &rName)
Set the device name.
faudes_mutex_t * pWaitMutex
Actual Wait Condition Mutex.
Definition: iop_vdevice.h:779
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.
virtual int TimeScale(void)
Get timescale.
Definition: iop_vdevice.h:374
Container of devices.
Definition: iop_xdevice.h:49
Iterator End(void) const
Set Iterator to last device.
Definition: iop_xdevice.h:122
static xDevice * FromTokenReader(TokenReader &rTr)
Construct on heap from token reader.
Definition: iop_xdevice.cpp:90
virtual ~xDevice(void)
Explicit destructor.
Definition: iop_xdevice.cpp:80
bool lastCommandWasStart
Current device state: remember last stop/down command.
Definition: iop_xdevice.h:332
Time::Type CurrentTime(void)
Report global fauDES-time Note: per convention we take the time of the first device inserted in xDevi...
DeviceState Status(void)
Get status.
long int CurrentTimeMs(void)
Report global fauDES-time Note: per convention we take the time of the first device inserted in xDevi...
std::vector< vDevice * > mDevices
Vector of member-devices.
Definition: iop_xdevice.h:317
void Start(void)
Activate the devices.
void Configure(Idx event, const AttributeDeviceEvent &attr)
Dummy.
Iterator Begin(void) const
Set Iterator to first device.
Definition: iop_xdevice.h:114
bool ResetRequest(void)
Test for reset request.
void WriteOutput(Idx output)
Run output command on relevant device.
Idx Size(void) const
Get number of devices.
Definition: iop_xdevice.h:128
void Clear(void)
Clear all configuarations and destroy existing devices.
void Compile(void)
Build up internal data structures.
virtual void DoWriteConfiguration(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
Write the device patrameters to a TokenWriter.
static xDevice * FromFile(const std::string &rFileName)
Construct on heap from file.
std::map< Idx, int > mInputToDevice
Compiled data: Input map to map input idx to device no.
Definition: iop_xdevice.h:326
void Insert(vDevice *device)
Insert a new device.
void Stop(void)
Deactivate the device.
void Reset(void)
reset all dynamic state, i.e.
std::map< Idx, int > mOutputToDevice
Compiled data: Output Map to map input idx to device no.
Definition: iop_xdevice.h:329
std::vector< vDevice * >::const_iterator Iterator
Iterator for const access to individual devices.
Definition: iop_xdevice.h:58
virtual void DoReadConfiguration(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
Actual method to read device configuration from tokenreader.
std::vector< std::string > mDeviceNames
Vector of member-device-names.
Definition: iop_xdevice.h:323
xDevice(void)
Default constructor.
Definition: iop_xdevice.cpp:44
virtual void FlushOutputs(void)
Flush any pending IO Operations.
std::vector< vDevice * >::iterator iterator
Definition: iop_xdevice.h:278
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
Iterator Begin(void) const
Iterator to the begin of set.
Definition: cfl_baseset.h:1891
Hardware access via comedi.
iodevice for d3ripDART protocol and friends
iodevice for d3ripURT protocol and friends
Process image via modbus/tcp.
Process image via serial line.
Simple networked events via TCP/IP.
#define FD_DHV(message)
Definition: iop_vdevice.h:37
#define FD_DH(message)
Definition: iop_vdevice.h:27
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)
std::string ExtractDirectory(const std::string &rFullPath)
Extract directory from full path.
Definition: cfl_helper.cpp:262
static volatile AutoRegisterType< xDevice > gRtiRegisterDeviceContainer("DeviceContainer")

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