iomonitor.cpp
Go to the documentation of this file.
1 /** @file iomonitor.cpp Test utility for IO devices
2 
3 
4 This tutorial demonstrates elementary access to external signals
5 via the class faudes::vDevice. It can be used as a test uitility
6 for device configuration.
7 
8 
9 @ingroup Tutorials
10 
11 @include iomonitor.cpp
12 
13 */
14 
15 
16 #include "libfaudes.h"
17 
18 #include <signal.h>
19 
20 using namespace faudes;
21 
22 ///////////////////////////////////////////////////////
23 // clean exit on signals
24 
25 // iomonitor clean-up on exit
26 void iomonitor_exit(void);
27 
28 // signal handler recursion flag
29 volatile sig_atomic_t signal_in_progress = 0;
30 
31 // signal handler to stop devices
32 void catch_signal(int sig) {
33  // detect recursion, pass on
34  if(signal_in_progress) raise(sig);
36  // report
37  std::cerr << "iomonitor: signal: " << faudes_strsignal(sig) << std::endl;
38  // call my exit function
40  // re-install default handler
41  signal(sig, SIG_DFL);
42  // pass on signal
43  raise(sig);
44 }
45 
46 // iomonitor clean-up on exit
47 void iomonitor_exit(void) {
48  // stop all devices
50 }
51 
52 
53 ///////////////////////////////////////////////////////
54 //Basic handling
55 
56 // list all known events
57 void ListEvents(const vDevice* dev) {
58  std::cout<< "% ###############################################################" << std::endl;
59  std::cout<< "% # InputEvents" << std::endl;
60  dev->Inputs().Write();
61  std::cout<< "% ###############################################################" << std::endl;
62  std::cout<< "% # OutputEvents " << std::endl;
63  dev->Outputs().Write();
64  std::cout<< "% ###############################################################" << std::endl;
65 }
66 
67 
68 ///////////////////////////////////////////////////////
69 // Query Time
70 
71 // read time
72 void ReadTime(vDevice* dev) {
73 
74  // read and report
75  std::cout << "% ###############################################################" << std::endl;
76  std::cout << "% # ReadTime: current time in ftu: " << dev->CurrentTime() << std::endl;
77  std::cout << "% # ReadTime: using scale: " << dev->TimeScale() << std::endl;
78 
79 }
80 
81 
82 ///////////////////////////////////////////////////////
83 //Signal-I/O
84 
85 // read signal value
87  // declare static buffer
88  static bool* samplePrevious=0;
89  static bool* sampleCurrent=0;
90  static int sampleSize=-1;
91  // allocate memory for buffer
92  if(sampleSize != dev->MaxBitAddress()+1) {
93  sampleSize = dev->MaxBitAddress()+1;
94  if(samplePrevious!=0) delete samplePrevious;
95  if(sampleCurrent!=0) delete sampleCurrent;
96  samplePrevious= new bool[sampleSize];
97  sampleCurrent= new bool[sampleSize];
98  }
99  // read and report
100  std::cout << "% ###############################################################" << std::endl;
101  for(int bit=0; bit<sampleSize; bit++) {
102  samplePrevious[bit]=sampleCurrent[bit];
103  }
104  for(int bit=0; bit<sampleSize; bit++) {
105  sampleCurrent[bit]=dev->ReadSignal(bit);
106  }
107  std::cout << "% # ReadValue: current input reading: " << std::endl;
108  for(int bit=0; bit<sampleSize; bit++) {
109  std::cout<< "@" << (bit < 10 ? "0" : "") << bit << ":" << sampleCurrent[bit] << " ";
110  if((bit%8)==7 || bit+1==sampleSize) std::cout << std::endl;
111  }
112  std::cout <<"% # ReadValue: edges wrt previous reading: " << std::endl;
113  int cnt =0;
114  for(int bit=0; bit<sampleSize; bit++) {
115  if(samplePrevious[bit]!=sampleCurrent[bit]) {
116  std::cout<< "@"<< (bit < 10 ? "0" : "") << bit << ":" << sampleCurrent[bit] << " ";
117  if((cnt%8)==7 || bit+1==sampleSize) std::cout << std::endl;
118  cnt+=1;
119  }
120  }
121  std::cout << "% ###############################################################" << std::endl;
122 }
123 
124 
125 // poll input signals
127  std::cout<<"ReadInputs: time (secs) to monitor input signals: ";
128  faudes_mstime_t time_all;
129  std::cin>>time_all;
130  time_all*=1000; // convert to msecs
131  std::cout<<"ReadEvents: time (msecs) to sleep between two polls: ";
132  faudes_mstime_t time_delta;
133  std::cin>>time_delta;
134  // reset all input data so far
135  sdev->Reset();
136  // report performace, part 1
137  faudes_systime_t time_start, time_stop;
138  faudes_gettimeofday(&time_start);
139 
140  // declare static buffer
141  static bool* samplePrevious=0;
142  static bool* sampleCurrent=0;
143  static int sampleSize=-1;
144  // allocate memory for buffer
145  if(sampleSize != sdev->MaxBitAddress()+1) {
146  sampleSize = sdev->MaxBitAddress()+1;
147  if(samplePrevious!=0) delete samplePrevious;
148  if(sampleCurrent!=0) delete sampleCurrent;
149  samplePrevious= new bool[sampleSize];
150  sampleCurrent= new bool[sampleSize];
151  }
152  // reset buffer
153  for(int bit=0; bit<sampleSize; bit++) {
154  samplePrevious[bit]=false;
155  sampleCurrent[bit]=false;
156  }
157 
158  // loop until time is up
159  bool edges=true;
160  for(int time_togo=time_all; time_togo>0; time_togo-=time_delta) {
161  // read
162  for(int bit=0; bit<sampleSize; bit++) {
163  sampleCurrent[bit]=sdev->ReadSignal(bit);
164  if(sampleCurrent[bit] != samplePrevious[bit]) edges=true;
165  }
166  // report
167  if(edges) {
168  std::cout << "% ###############################################################" << std::endl;
169  for(int bit=0; bit<sampleSize; bit++) {
170  std::cout<< "@"<< (bit < 10 ? "0" : "") << bit << ":" << sampleCurrent[bit];
171  if(sampleCurrent[bit] != samplePrevious[bit])
172  std::cout << "! ";
173  else
174  std::cout << " ";
175  if((bit%8)==7 || bit+1==sampleSize) std::cout << std::endl;
176  }
177  }
178  // copy
179  for(int bit=0; bit<sampleSize; bit++) {
180  samplePrevious[bit]=sampleCurrent[bit];
181  }
182  // clear edge detection
183  edges=0;
184  // sleep
185  faudes_usleep(1000*time_delta);
186  };
187 
188  // report performance, part2
189  faudes_gettimeofday(&time_stop);
190  faudes_mstime_t diffms;
191  faudes_diffsystime(time_stop,time_start,&diffms);
192  std::cout << "# performance: overall time: " << diffms << "ms" << std::endl;
193  std::cout << "# performance: sleep time: " << time_all << "ms" << std::endl;
194  std::cout << "# performance: process time per loop: " <<
195  ((double) (diffms - time_all)) / (time_all/time_delta)<< "ms" << std::endl;
196 }
197 
198 // write signal value
200  int bit, val;
201  std::cout<<"WriteValue: enter bit address (or -1 to exit): ";
202  std::cin>>bit;
203  if(bit<0) return;
204  std::cout<<"WriteValue: enter value (or -1 to exit): ";
205  std::cin>>val;
206  if(val<0) return;
207  std::cout<<"WriteValue: setting output " << bit << " to value " << val << std::endl;
208  sdev->WriteSignal(bit,val!=0);
209 }
210 
211 //////////////////////////////////////////////////////////////
212 //Event-handling
213 
214 // execute output event
216  std::cout<<"WriteOutput: enter event by name: ";
217  std::string testEvent;
218  std::cin>>testEvent;
219  if(!dev->Outputs().Exists(testEvent)) {
220  std::cout<<"Unknown output event " << std::endl;
221  return;
222  }
223  faudes::Idx fev= dev->Outputs().Index(testEvent);
224  dev->WriteOutput(fev);
225  dev->FlushOutputs();
226 }
227 
228 
229 // poll input events
231  std::cout<<"ReadInputs: time (secs) to monitor input events: ";
232  faudes_mstime_t time_all;
233  std::cin>>time_all;
234  time_all*=1000; // convert to msecs
235  std::cout<<"ReadEvents: time (msecs) to sleep between two polls: ";
236  faudes_mstime_t time_delta;
237  std::cin>>time_delta;
238  // reset all input data so far
239  dev->Reset();
240  // report performace, part 1
241  faudes_systime_t time_start, time_stop;
242  faudes_gettimeofday(&time_start);
243 
244  // loop until time is up
245  for(int time_togo=time_all; time_togo>0; time_togo-=time_delta) {
246  Idx sev=dev->ReadInput();
247  if(sev!=0)
248  std::cout<<"ReadInputs: event " << dev->Inputs().SymbolicName(sev) << std::endl;
249  faudes_usleep(1000*time_delta);
250  };
251 
252  // report performance, part2
253  faudes_gettimeofday(&time_stop);
254  faudes_mstime_t diffms;
255  faudes_diffsystime(time_stop,time_start,&diffms);
256  std::cout << "# performance: overall time: " << diffms << "ms" << std::endl;
257  std::cout << "# performance: sleep time: " << time_all << "ms" << std::endl;
258  std::cout << "# performance: process time per loop: " <<
259  ((double) (diffms - time_all)) / (time_all/time_delta)<< "ms" << std::endl;
260 
261 }
262 
263 // WaitInputEvent(vDevice* dev)
265  std::cout<<"Enter max. duration (in faudes-time units) to wait for a input-event to occur"<<std::endl;
266  std::cout<<"Note: 1 faudes-time unit is configured to " << dev->TimeScale() << " msecs" <<std::endl;
267  Time::Type duration;
268  std::cin>>duration;
269  EventSet occuredEvents;
270  //wait for input-event to occur
271  dev->WaitInputs(duration);
272  //identify occured events
273  while(Idx sev=dev->ReadInput()) occuredEvents.Insert(sev);
274  //report occured events
275  if(!occuredEvents.Empty()) std::cout << occuredEvents.ToString();
276  else std::cout<<"No event recognized";
277 }
278 
279 // FlushInputEvent(vDevice* dev)
281  //identify occured events
282  EventSet occuredEvents;
283  while(Idx sev=dev->ReadInput()) occuredEvents.Insert(sev);
284  //report occured events
285  if(!occuredEvents.Empty()) std::cout << occuredEvents.ToString();
286  else std::cout<<"No event recognized";
287 }
288 
289 
290 //////////////////////////////////////////////////////////////
291 //User-Interface loop
292 
293 int main(int argc, char* argv[]) {
294 
295  // debugging autoregistration :-(
296  /*
297  std::cerr << " ====== auto registration " << std::endl;
298  TypeRegistry::G()->Write();
299  std::cerr << " ====== registration " << std::endl;
300  AutoRegisterType<cDevice> gRtiLocalIOReg("ComediDevice");
301  TypeRegistry::G()->Write();
302  */
303 
304  // install my signal handler
306 
307  // first argument has to be filename
308  if(argc!=2) {
309  std::cerr << "iomonitor: " << VersionString() << std::endl;
310  std::cerr << "usage: iomonitor <device-file>" << std::endl;
311  return -1;
312  }
313 
314 #ifdef FAUDES_NETWORK
315 #ifdef FAUDES_WINDOWS
316  // initialise winsocks
317  WSADATA wsaData;
318  if(WSAStartup(MAKEWORD(2,2), &wsaData)!=0) {
319  std::cerr << "iomonitor: failed to initialize winsocks" << std::endl;
320  return -1;
321  }
322 #endif
323 #endif
324 
325  //initialize vDevice
326  FD_DH("Initialize vDevice");
327  std::cout << "iomonitor: instantiate device from file" << std::endl;
328  vDevice* dev;
329  dev=vDevice::FromFile(std::string(argv[1]));
330  sDevice* sdev=dynamic_cast<sDevice*>(dev);
331 
332  //start vDevice
333  std::cout << "iomonitor: starting device " << std::endl;
334  dev->Start();
335 
336  //loop until device is up
337  while(dev->Status()!=vDevice::Up){;}
338 
339  // loop until user terminates
340  while(true) {
341 
342  // set up cheap console userinterface
343  std::cout << std::endl;
344  std::cout << std::endl;
345  std::cout << "# iomonitor commands are:" << std::endl;
346  std::cout << "#" << std::endl;
347  std::cout << "# read faudes event via wait (re)" << std::endl;
348  std::cout << "# read faudes events via polling (pe)" << std::endl;
349  std::cout << "# flush faudes input events (fe)" << std::endl;
350  if(sdev) std::cout << "# read signal value by bitaddress (rs)" << std::endl;
351  if(sdev) std::cout << "# read signal values via polling (ps)" << std::endl;
352  std::cout << "#" << std::endl;
353  std::cout << "# write faudes event (we)" << std::endl;
354  if(sdev) std::cout << "# write signal value by bitaddress (ws)" << std::endl;
355  std::cout << "#" << std::endl;
356  std::cout << "# device time (time)" << std::endl;
357  std::cout << "# reset device (reset)" << std::endl;
358  std::cout << "# list all device events (list) " << std::endl;
359  std::cout << "# exit (exit) " << std::endl;
360  std::cout << "#" << std::endl;
361  std::cout << ">";
362  // get user-choice
363  std::string choice;
364  std::cin >> choice;
365  //execute user-choice
366  if(choice=="exit") break;
367  if(choice=="reset") {dev->Reset();};
368  if(choice=="time") ReadTime(dev);
369  if(choice=="list") ListEvents(dev);
370  if(choice=="pe") PollInputEvents(dev);
371  if(choice=="re") WaitInputEvent(dev);
372  if(choice=="fe") FlushInputEvents(dev);
373  if(sdev && choice=="rs") ReadSignalValue(sdev);
374  if(sdev && choice=="ps") PollInputSignals(sdev);
375  if(choice=="we") WriteOutputEvent(dev);
376  if(sdev && choice=="ws") WriteSignalValue(sdev);
377 
378  }
379 
380  std::cout << "# iomonitor: done " << std::endl;
381  std::cout << "##########################################" << std::endl;
382 
383 
384  FD_DH("Stopping vDevice");
385 
386  //stop background thread
387  dev->Stop();
388 
389  return 0;
390 }
391 
392 
393 
const char * faudes_strsignal(int sig)
void faudes_termsignal(void(*sighandler)(int))
void faudes_diffsystime(const faudes_systime_t &end, const faudes_systime_t &begin, faudes_systime_t *res)
FAUDES_API void faudes_usleep(long int usec)
Definition: cfl_platform.h:208
Set of indices with symbolic names.
Definition: cfl_nameset.h:69
bool Exists(const Idx &rIndex) const
Test existence of index.
void SymbolicName(Idx index, const std::string &rName)
Set new name for existing index.
bool Insert(const Idx &rIndex)
Add an element by index.
Idx Index(const std::string &rName) const
Index lookup.
Int Type
Datatype for point on time axis.
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Write configuration data to a string.
Definition: cfl_types.cpp:169
void Write(const Type *pContext=0) const
Write configuration data to console.
Definition: cfl_types.cpp:139
An sDevice implements signal based semantics for faudes events.
Definition: iop_sdevice.h:291
int MaxBitAddress(void) const
Report max bit address.
Definition: iop_sdevice.h:385
void WriteSignal(int bitaddr, bool value)
Set output signal.
virtual void Reset(void)
Clear dynamic data and restart device.
bool ReadSignal(int bitaddr)
Get input signal.
Virtual base class to define the interface for event io.
Definition: iop_vdevice.h:261
virtual const EventSet & Inputs(void) const
Get inputs as plain set.
virtual void TimeScale(unsigned int scale)
Set timescale.
Definition: iop_vdevice.h:364
static void StopAll(void)
Stop all devices.
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.
virtual void WriteOutput(Idx output)=0
Run output command.
virtual void Reset(void)
Reset device.
static vDevice * FromFile(const std::string &rFileName)
Construct on heap from file.
virtual Idx ReadInput(void)
Read sensed input events.
virtual bool WaitInputs(Time::Type duration)
Wait for input trigger.
virtual Time::Type CurrentTime(void)
Report physical time in ftu.
virtual void FlushOutputs(void)
Flush pending IO Operations.
virtual const EventSet & Outputs(void) const
Get outputs as plain set.
bool Empty(void) const
Test whether if the TBaseSet is Empty.
Definition: cfl_baseset.h:1824
int main(int argc, char *argv[])
Definition: iomonitor.cpp:293
void PollInputSignals(sDevice *sdev)
Definition: iomonitor.cpp:126
void WaitInputEvent(vDevice *dev)
Definition: iomonitor.cpp:264
void ReadTime(vDevice *dev)
Definition: iomonitor.cpp:72
void iomonitor_exit(void)
Definition: iomonitor.cpp:47
void ListEvents(const vDevice *dev)
Definition: iomonitor.cpp:57
void FlushInputEvents(vDevice *dev)
Definition: iomonitor.cpp:280
volatile sig_atomic_t signal_in_progress
Definition: iomonitor.cpp:29
void WriteOutputEvent(vDevice *dev)
Definition: iomonitor.cpp:215
void PollInputEvents(vDevice *dev)
Definition: iomonitor.cpp:230
void WriteSignalValue(sDevice *sdev)
Definition: iomonitor.cpp:199
void ReadSignalValue(sDevice *dev)
Definition: iomonitor.cpp:86
void catch_signal(int sig)
Definition: iomonitor.cpp:32
#define FD_DH(message)
Definition: iop_vdevice.h:27
Includes all libFAUDES headers, incl plugings
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
std::string VersionString()
Return FAUDES_VERSION as std::string.
Definition: cfl_helper.cpp:131

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