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:
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)
101xDevice* 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"
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)
153void 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)
168void 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)
183void 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
194}
195
196// Clear(void)
197void 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*)
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)
234void 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)
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)
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)
307void 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)
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)
356void 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)
365void 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)
403void 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
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)
Definition cfl_types.h:958
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.33k --- 2025.09.16 --- c++ api documentaion by doxygen