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
23namespace faudes {
24
25/*
26 **********************************************
27 **********************************************
28 **********************************************
29
30 implementation: xDevice
31
32 **********************************************
33 **********************************************
34 **********************************************
35 */
36
37// std faudes
38FAUDES_TYPE_IMPLEMENTATION(DeviceContainer,xDevice,vDevice)
39
40// autoregister
41volatile static AutoRegisterType<xDevice> gRtiRegisterDeviceContainer("DeviceContainer");
42
43//constructor
45 FD_DHV("xDevice(" << mName << ")::xDevice()");
46 mName="IoDevices";
47 // have appropriate default label
48 mDefaultLabel="DeviceContainer";
49
50 // auto register fix (old compilers 2010; fine with C++11)
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 /*
56#ifdef FAUDES_IODEVICE_SIMPLENET
57 volatile static AutoRegisterType<nDevice> gRtiIORegisterSimplenetDevice("SimplenetDevice");
58#endif
59#ifdef FAUDES_IODEVICE_COMEDI
60 volatile static AutoRegisterType<cDevice> gRtiIORegisterComediDevice("ComediDevice");
61#endif
62#ifdef FAUDES_IODEVICE_WAGO
63 volatile static AutoRegisterType<wDevice> gRtiIORegisterWagoDevice("WagoDevice");
64#endif
65#ifdef FAUDES_IODEVICE_SERIAL
66 volatile static AutoRegisterType<spiDevice> gRtiIORegisterSerialPiDevice("SpiDevice");
67#endif
68#ifdef FAUDES_IODEVICE_MODBUS
69 volatile static AutoRegisterType<mbDevice> gRtiIORegisterSerialPiDevice("ModbusDevice");
70#endif
71#ifdef FAUDES_IODEVICE_D3RIP_URT
72 volatile static AutoRegisterType<d3ripURTDevice> gRtiIORegisterD3ripUrtDevice("D3RipUrtDevice");
73#endif
74#ifdef FAUDES_IODEVICE_D3RIP_DART
75 volatile static AutoRegisterType<d3ripDARTDevice> gRtiIORegisterD3ripDartDevice("D3RipDartDevice");
76#endif
77 */
78
79}
80
81
82//copy constructor
83xDevice::xDevice(const xDevice& rOther) : xDevice() {
84 /* my configuration */
85 Iterator dit;
86 for(dit=rOther.Begin();dit!=rOther.End();dit++){
87 mDevices.push_back((*dit)->NewCpy());
88 }
90 /* compile */
91 Compile();
92}
93
94// destructor
96 FD_DHV("xDevice(" << mName << ")::~xDevice()");
97 // loop to free devices.
98 Iterator dit;
99 for(dit=Begin();dit!=End();dit++){
100 delete (*dit);
101 }
102}
103
104//FromTokenReader(rTr)
106 // construct from token reader
107 FD_DHV("xDevice::FromTokenReader()");
108 // allocate
109 xDevice* dev=new xDevice();
110 // read
111 dev->DoRead(rTr);
112 return dev;
113}
114
115//FromFile(rFilename)
116xDevice* xDevice::FromFile(const std::string& rFileName) {
117 // construct from file
118 FD_DHV("xDevice()::FromFile(" << rFileName <<")");
119 // peek first token
120 TokenReader tr(rFileName);
121 return FromTokenReader(tr);
122}
123
124
125//Status(void)
127
128 FD_DHV("xDevice(" << mName << ")::Status() ");
129 //prepare result
131 //vector to store states of all devices integrated in xdevice
132 std::vector<xDevice::DeviceState> states;
133 //vector iterator
134 std::vector<DeviceState>::iterator vit;
135 vit = states.begin();
136 //device iterator
137 iterator dit;
138 //identify device state
139 for(dit=Begin();dit!=End();dit++){
140 //get state of current device and insert it in vector
141 states.push_back((DeviceState)(*dit)->Status());
142 //make sure it isnt the first entry
143 if(vit != states.begin()){
144 //if current entry doesnt equal previous
145 //decide depending on last command
146 if (*vit!=*vit--){
147 //if last command was start: "StartUp"
149 res = StartUp;
150 break;
151 }
152 //if last command was stop: "ShutDown"
154 res = ShutDown;
155 break;
156 }
157 }
158 }
159 //move on to next device
160 vit++;
161 }
162 //if for-loop finished all entries of vector "states" are equal
163 res = *states.begin();
164 return res;
165}
166
167// Start(void)
168void xDevice::Start(void) {
169
170 FD_DHV("xDevice(" << mName <<")::Start()");
171 // start implies reset
172 Reset();
173 //start all existing devices
174 Iterator dit;
175 for(dit = Begin();dit!=End();dit++){
176 (*dit)->Start();
177 }
178 //remember this command
179 lastCommandWasStart = true;
180}
181
182// Stop(void)
183void xDevice::Stop(void) {
184
185 FD_DHV("xDevice(" << mName <<")::Stop()");
186 // xDevice Reset
187 Reset();
188 // stop all existing devices
189 Iterator dit;
190 for(dit=Begin();dit!=End();dit++){
191 (*dit)->Stop();
192 }
193 //remember this command
194 lastCommandWasStart = false;
195}
196
197// Reset(void)
198void xDevice::Reset(void){
199 //clear dynamic data
200
201 FD_DHV("xDevice(" << mName <<")::Reset()");
202 // device-iterator
203 Iterator dit;
204 for(dit=Begin();dit!=End();dit++){
205 (*dit)->Reset();
206 }
207 // call base to reset time and fifo
209}
210
211// Clear(void)
212void xDevice::Clear(void){
213 //clear static data
214 FD_DHV("xDevice(" << mName << ")::Clear()");
215 // Stop running devices
216 Stop();
217 // device-iterator
218 Iterator dit;
219 // and clear all devices
220 for(dit=Begin();dit!=End();dit++){
221 (*dit)->Clear();
222 }
223 // destroy existing data
224 for(dit=Begin();dit!=End();dit++){
225 delete (*dit);
226 }
227 // compile with empty containers
228 Compile();
229}
230
231// Insert(vDevice*)
233
234 FD_DHV("xDevice("<<mName<<")::Insert(" << device << "):" << device->Name());
235 // insert any vdevice, but no xdevice
236 if(dynamic_cast<xDevice*>(device)) {
237 std::stringstream errstr;
238 errstr << "Attempt to insert xDevice into xDevice";
239 throw Exception("xDevice::Compile", errstr.str(), 550);
240 }
241 // add to mDevices
242 mDevices.push_back(device);
243 // and update compiled data
244 Compile();
245}
246
247//Insert(rFilename)
248void xDevice::Insert(const std::string& rFileName){
249 //inserts a device by filename
250 FD_DHV("xDevice("<<mName<<")::Insert(rFileName)");
251 //read device
252 vDevice* pdev = vDevice::FromFile(rFileName);
253 //insert device
254 Insert(pdev);
255 //and remember its name
256 mDeviceNames.push_back(rFileName);
257}
258
259
260// Compile(void)
262 //build up internal data-structures
263
264 FD_DHV("xDevice("<<mName<<")::Compile()");
265 Stop();
266 // build up (event-idx,int)-map and memorize all existing events
267 // prepare containers
268 mInputs.Clear();
269 mOutputs.Clear();
270 mInputToDevice.clear();
271 mOutputToDevice.clear();
272 // temporary container
273 EventSet tmpSenEvents;
274 EventSet tmpActEvents;
275 // event-iterator
276 EventSet::Iterator eit;
277 // device-iterator
278 Iterator dit;
279 // helper
280 int j;
281 // iterate over existing devices
282 for(dit=Begin(), j=0; dit!=End(); dit++,j++){
283 // get events by Index
284 tmpSenEvents = (*dit)->Inputs();
285 tmpActEvents = (*dit)->Outputs();
286 //insert output-events in map
287 for(eit=tmpActEvents.Begin();eit!=tmpActEvents.End();eit++){
288 // test if actual event already exists in map
289 if(mOutputs.Exists(*eit)){
290 //throw exeption
291 std::stringstream errstr;
292 errstr << "Event already exists!";
293 throw Exception("xDevice()::Compile", errstr.str(), 550);
294 }
295 mOutputToDevice[*eit] = j;
296 }
297 // memorize events
298 mInputs.InsertSet(tmpSenEvents);
299 mOutputs.InsertSet(tmpActEvents);
300 // tell the device which mutex/condition-pair to use
301 (*dit)->UseCondition(pWaitMutex,pWaitCondition);
302 (*dit)->UseBuffer(pBufferMutex,pInputBuffer);
303 }//end iteration over existing devices
304 // set time scale from first device
305 if(Size()!=0) (*Begin())->TimeScale(mTimeScale);
306}
307
308
309//Configure(event,attr)
311 (void) event; (void) attr;
312 // cannot do vDevice style configuration of events
313
314 FD_DHV("xDevice("<<mName<<")::Configure(Idx,attr): ");
315 std::stringstream errstr;
316 errstr << "Attempt to configure xDevice by event";
317 throw Exception("xDevice::Configure(Idx,attr)", errstr.str(), 550);
318}
319
320//Configure(rEvents)
321void xDevice::Configure(const EventSet& rEvents){
322 (void) rEvents;
323 // cannot do vDevice style configuration of events
324
325 FD_DHV("xDevice("<<mName<<")::Configure(rEvents)");
326 std::stringstream errstr;
327 errstr << "Attempt to configure xDevice by events";
328 throw Exception("xDevice::Configure", errstr.str(), 550);
329}
330
331
332//CurrentTime(void)
334
335 FD_DHV("xDevice("<<mName<<"): CurrentTime() ");
336 // throw exception if there is no device
337 if(Size()==0) {
338 std::stringstream errstr;
339 errstr << "xDevice owns no device!";
340 throw Exception("xDevice::CurrentTime", errstr.str(),550);
341 }
342 // ask first device
343 return (*Begin())->CurrentTime();
344}
345
346
347//CurrentTime(void)
349 //debug flag: say hello
350 FD_DHV("xDevice("<<mName<<")::CurrentTimeMs() ");
351 // throw exception if there is no device
352 if(Size()==0) {
353 std::stringstream errstr;
354 errstr << "xDevice owns no device!";
355 throw Exception("xDevice::CurrentTimeMs", errstr.str(),550);
356 }
357 // ask first device
358 return (*Begin())->CurrentTimeMs();
359}
360
361//CurrentTime(now)
363 //debug flag: say hello
364 FD_DHV("xDevice("<<mName<<")::CurrentTime("<<now<<") ");
365 // tell first device if such
366 if(Size()!=0) (*Begin())->CurrentTime(now);
367}
368
369//CurrentTimeMs(now)
370void xDevice::CurrentTimeMs(long int nowms) {
371 //debug flag: say hello
372
373 FD_DHV("xDevice("<<mName<<")::CurrentTimeMs("<<nowms<<") ");
374 // tell first device if such
375 if(Size()!=0) (*Begin())->CurrentTimeMs(nowms);
376}
377
378//DoWrite(rTr,rLabel)
379void xDevice::DoWriteConfiguration(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
380 (void) rTw;
381
382 FD_DHV("xDevice("<<mName<<")::DoWriteConfiguration()");
383 // hard coded begin
384 rTw.WriteBegin("Devices");
385 //iterate over all devices
386 for(Idx i=0; i<Size(); i++) {
387 //if device was read from an extra file
388 if(mDeviceNames.at(i) != ""){
389 //write path to TokenWriter
390 FD_DHV("xDevice("<<mName<<")::DoWrite(): "<<mDeviceNames.at(i));
391 rTw.WriteString(mDeviceNames.at(i)); //TODO: relativ path-names
392 }
393 //else device was directly read from base-config-file
394 else if(mDeviceNames.at(i) == ""){
395 //write configuration
396 FD_DHV("xDevice("<<mName<<")::DoWrite(): "<<mDeviceNames.at(i));
397 (mDevices.at(i))->Write(rTw);
398 }
399 }
400 rTw.WriteEnd("Devices");
401}
402
403
404// ResetRequest()
406 bool res=false;
407 Iterator dit;
408 for(dit=Begin();dit!=End();dit++){
409 res = res | (*dit)->ResetRequest();
410 }
411 return res;
412}
413
414//DoRead(rTr,rLabel)
415void xDevice::DoReadConfiguration(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
416 (void) rLabel; (void) pContext;
417
418 FD_DHV("xDevice("<<mName<<")::DoReadConfiguration()");
419 //prepare token
420 Token token;
421 //prepare string
422 std::string filename = ""; //to store filename
423 std::string dirname = ""; //to store directory
424 std::string path; //to store absolut path
425 // have default section
426 std::string label = rLabel;
427 if(label=="") label = "Devices";
428 // read begin
429 rTr.ReadBegin(label);
430 // fill mDevices with devices specified in given file
431 while(!rTr.Eos("Devices")){
432 //peek token
433 rTr.Peek(token);
434 // if Token is a String we assume its the name of a file containing a device
435 if(token.Type()==Token::String) {
436 //read Token
437 rTr.Get(token);
438 //import filename
439 filename = token.StringValue();
440 //build up path to base-file
441 if(rTr.SourceMode()==TokenReader::File) dirname = ExtractDirectory(rTr.FileName());
442 //build up path to specified file
443 path = dirname.append(filename);
444 //insert device
445 Insert(path);
446 continue;
447 }
448 // if its not a file it has to be a device
449 else if(token.Type()==Token::Begin) {
450 // read device
452 // insert device mDevices
453 Insert(devp);
454 //record that this device was read inline
455 mDeviceNames.push_back("");
456 }
457 }
458 rTr.ReadEnd(label);
459}
460
461
462// WriteOutput(Idx)
464 FD_DHV("xDevice("<<mName<<")::WriteOutput()");
465 // identify corresponding device(if idx is unique)
466 int didx = mOutputToDevice[output];
467 FD_DH("xDevice("<<mName<<")::WriteOutput(): " << output << " to " << didx);
468 mDevices.at(didx)->WriteOutput(output);
469}
470
471
472// FlusgBufferes()
474 // iterate over all participating devices
475 for(Iterator dit=Begin(); dit!=End(); dit++)
476 (*dit)->FlushOutputs();
477}
478
479
480
481} // name space
482
483
#define FAUDES_TYPE_IMPLEMENTATION(ftype, ctype, cbase)
Definition cfl_types.h:1017
bool Exists(const Idx &rIndex) const
virtual void InsertSet(const NameSet &rOtherSet)
bool Eos(const std::string &rLabel)
void ReadEnd(const std::string &rLabel)
void ReadBegin(const std::string &rLabel)
bool Get(Token &token)
bool Peek(Token &token)
std::string FileName(void) const
Mode SourceMode(void) const
void WriteString(const std::string &rString)
void WriteEnd(const std::string &rLabel)
void WriteBegin(const std::string &rLabel)
const std::string & StringValue(void) const
@ Begin
<label> (begin of section)
Definition cfl_token.h:84
@ String
any string, space separated or quoted, must start with a letter
Definition cfl_token.h:86
TokenType Type(void) const
void Write(const Type *pContext=0) const
faudes_mutex_t * pBufferMutex
static vDevice * FromTokenReader(TokenReader &rTr)
faudes_cond_t * pWaitCondition
EventSet mOutputs
virtual void Reset(void)
static vDevice * FromFile(const std::string &rFileName)
void Name(const std::string &rName)
faudes_mutex_t * pWaitMutex
std::string mName
std::deque< Idx > * pInputBuffer
virtual void DoRead(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
virtual int TimeScale(void)
Iterator End(void) const
static xDevice * FromTokenReader(TokenReader &rTr)
virtual ~xDevice(void)
Time::Type CurrentTime(void)
DeviceState Status(void)
long int CurrentTimeMs(void)
std::vector< vDevice * > mDevices
void Configure(Idx event, const AttributeDeviceEvent &attr)
Iterator Begin(void) const
bool ResetRequest(void)
void WriteOutput(Idx output)
Idx Size(void) const
void Compile(void)
virtual void DoWriteConfiguration(TokenWriter &rTw, const std::string &rLabel="", const Type *pContext=0) const
static xDevice * FromFile(const std::string &rFileName)
std::map< Idx, int > mInputToDevice
void Insert(vDevice *device)
std::map< Idx, int > mOutputToDevice
std::vector< vDevice * >::const_iterator Iterator
Definition iop_xdevice.h:58
virtual void DoReadConfiguration(TokenReader &rTr, const std::string &rLabel="", const Type *pContext=0)
std::vector< std::string > mDeviceNames
virtual void FlushOutputs(void)
std::vector< vDevice * >::iterator iterator
virtual void Clear(void)
Iterator End(void) const
Iterator Begin(void) const
#define FD_DHV(message)
Definition iop_vdevice.h:37
#define FD_DH(message)
Definition iop_vdevice.h:27
uint32_t Idx
std::string ExtractDirectory(const std::string &rFullPath)
static volatile AutoRegisterType< xDevice > gRtiRegisterDeviceContainer("DeviceContainer")

libFAUDES 2.34e --- 2026.03.16 --- c++ api documentaion by doxygen