iop_xdevice.cpp

Go to the documentation of this file.
00001 /** @file iop_xdevice.cpp Device container with vDevice interface */
00002 
00003 /*
00004    FAU Discrete Event Systems Library (libfaudes)
00005 
00006    Copyright (C) 2008, Thomas Moor
00007    Exclusive copyright is granted to Klaus Schmidt
00008 
00009 */
00010 
00011 
00012 
00013 #include "iop_xdevice.h"
00014 #include "sys/time.h"
00015 
00016 #include "iop_simplenet.h"
00017 #include "iop_comedi.h"
00018 #include "iop_wago.h"
00019 #include "iop_serial.h"
00020 #include "iop_modbus.h"
00021 #include "iop_d3ripURT.h" 
00022 #include "iop_d3ripDART.h"
00023 
00024 namespace faudes {
00025 
00026 /*
00027  **********************************************
00028  **********************************************
00029  **********************************************
00030 
00031  implementation: xDevice
00032 
00033  **********************************************
00034  **********************************************
00035  **********************************************
00036  */
00037 
00038 // std faudes
00039 FAUDES_TYPE_IMPLEMENTATION(DeviceContainer,xDevice,vDevice)
00040 
00041 // autoregister
00042 volatile static AutoRegisterType<xDevice> gRtiRegisterDeviceContainer("DeviceContainer");
00043 
00044 //constructor
00045 xDevice::xDevice(void) : vDevice() {
00046   FD_DHV("xDevice(" << mName << ")::xDevice()");
00047   mName="IoDevices";
00048   // have appropriate default label
00049   mDefaultLabel="DeviceContainer";
00050 
00051   // auto register fix: 
00052   // for some reasons the global register objects do not work properly.
00053   // since the xdevice is autoregeistered by the rti, we ask the constructor
00054   // to register the other devices
00055 
00056 #ifdef FAUDES_IODEVICE_SIMPLENET
00057   volatile static AutoRegisterType<nDevice> gRtiIORegisterSimplenetDevice("SimplenetDevice");
00058 #endif
00059 #ifdef FAUDES_IODEVICE_COMEDI
00060   volatile static AutoRegisterType<cDevice> gRtiIORegisterComediDevice("ComediDevice");
00061 #endif
00062 #ifdef FAUDES_IODEVICE_WAGO
00063   volatile static AutoRegisterType<wDevice> gRtiIORegisterWagoDevice("WagoDevice");
00064 #endif
00065 #ifdef FAUDES_IODEVICE_SERIAL
00066   volatile static AutoRegisterType<spiDevice> gRtiIORegisterSerialPiDevice("SpiDevice");
00067 #endif
00068 #ifdef FAUDES_IODEVICE_MODBUS
00069   volatile static AutoRegisterType<mbDevice> gRtiIORegisterSerialPiDevice("ModbusDevice");
00070 #endif
00071 #ifdef FAUDES_IODEVICE_D3RIP_URT
00072   volatile static AutoRegisterType<d3ripURTDevice> gRtiIORegisterD3ripUrtDevice("D3RipUrtDevice");
00073 #endif
00074 #ifdef FAUDES_IODEVICE_D3RIP_DART
00075   volatile static AutoRegisterType<d3ripDARTDevice> gRtiIORegisterD3ripDartDevice("D3RipDartDevice");
00076 #endif
00077 
00078 }
00079 
00080 // destructor
00081 xDevice::~xDevice(void) {
00082   FD_DHV("xDevice(" << mName << ")::~xDevice()");
00083   // loop to free devices.
00084   Iterator dit;
00085   for(dit=Begin();dit!=End();dit++){
00086     delete (*dit);
00087   }
00088 }
00089 
00090 //FromTokenReader(rTr)
00091 xDevice* xDevice::FromTokenReader(TokenReader& rTr) {
00092   // construct from token reader
00093   FD_DHV("xDevice::FromTokenReader()");
00094   // allocate
00095   xDevice* dev=new xDevice();
00096   // read
00097   dev->DoRead(rTr);
00098   return dev;
00099 }
00100 
00101 //FromFile(rFilename)
00102 xDevice* xDevice::FromFile(const std::string& rFileName) {
00103   // construct from file
00104   FD_DHV("xDevice()::FromFile(" << rFileName <<")");
00105   // peek first token
00106   TokenReader tr(rFileName);
00107   return FromTokenReader(tr);
00108 }
00109 
00110 
00111 //Status(void)
00112 xDevice::DeviceState xDevice::Status(void){
00113 
00114   FD_DHV("xDevice(" << mName << ")::Status() ");
00115   //prepare result
00116   xDevice::DeviceState res;
00117   //vector to store states of all devices integrated in xdevice
00118   std::vector<xDevice::DeviceState> states;
00119   //vector iterator
00120   std::vector<DeviceState>::iterator vit;
00121   vit = states.begin();
00122   //device iterator
00123   iterator dit;
00124   //identify device state
00125   for(dit=Begin();dit!=End();dit++){
00126     //get state of current device and insert it in vector
00127     states.push_back((DeviceState)(*dit)->Status());
00128     //make sure it isnt the first entry
00129     if(vit != states.begin()){
00130       //if current entry doesnt equal previous
00131       //decide depending on last command
00132       if (*vit!=*vit--){
00133         //if last command was start: "StartUp"
00134         if(lastCommandWasStart){
00135           res = StartUp;
00136           break;
00137         }
00138         //if last command was stop: "ShutDown"
00139         if(!lastCommandWasStart){
00140           res = ShutDown;
00141           break;
00142         }
00143       }
00144     }
00145     //move on to next device
00146     vit++;
00147   }
00148   //if for-loop finished all entries of vector "states" are equal
00149   res =  *states.begin();
00150   return res;
00151 }
00152 
00153 // Start(void)
00154 void xDevice::Start(void) {
00155 
00156   FD_DHV("xDevice(" << mName <<")::Start()");
00157   // start implies reset
00158   Reset();
00159   //start all existing devices
00160   Iterator dit;
00161   for(dit = Begin();dit!=End();dit++){
00162     (*dit)->Start();
00163   }
00164   //remember this command
00165   lastCommandWasStart = true;
00166 }
00167 
00168 // Stop(void)
00169 void xDevice::Stop(void) {
00170 
00171   FD_DHV("xDevice(" << mName <<")::Stop()");
00172   // xDevice Reset
00173   Reset();
00174   // stop all existing devices
00175   Iterator dit;
00176   for(dit=Begin();dit!=End();dit++){
00177     (*dit)->Stop();
00178   }
00179   //remember this command
00180   lastCommandWasStart = false;
00181 }
00182 
00183 // Reset(void)
00184 void xDevice::Reset(void){
00185   //clear dynamic data
00186 
00187   FD_DHV("xDevice(" << mName <<")::Reset()");
00188   // device-iterator
00189   Iterator dit;
00190   for(dit=Begin();dit!=End();dit++){
00191     (*dit)->Reset();
00192   }
00193   // call base to reset time and fifo
00194   vDevice::Reset();
00195 }
00196 
00197 // Clear(void)
00198 void xDevice::Clear(void){
00199   //clear static data
00200 
00201   FD_DHV("xDevice(" << mName << ")::Clear()");
00202   // Stop running devices
00203   Stop();
00204   // device-iterator
00205   Iterator dit;
00206   // and clear all devices
00207   for(dit=Begin();dit!=End();dit++){
00208     (*dit)->Clear();
00209   }
00210   // destroy existing data
00211   for(dit=Begin();dit!=End();dit++){
00212     delete (*dit);
00213   }
00214   // compile with empty containers
00215   Compile();
00216 }
00217 
00218 // Insert(vDevice*)
00219 void xDevice::Insert(vDevice* device){
00220 
00221   FD_DHV("xDevice("<<mName<<")::Insert(" << device << "):" <<  device->Name());
00222   // insert any vdevice, but no xdevice
00223   if(dynamic_cast<xDevice*>(device)) {
00224     std::stringstream errstr;
00225     errstr << "Attempt to insert xDevice into xDevice";
00226     throw Exception("xDevice::Compile", errstr.str(), 550);
00227   }
00228   // add to mDevices
00229   mDevices.push_back(device);
00230   // and update compiled data
00231   Compile();
00232 }
00233 
00234 //Insert(rFilename)
00235 void xDevice::Insert(const std::string& rFileName){
00236   //inserts a device by filename
00237   FD_DHV("xDevice("<<mName<<")::Insert(rFileName)");
00238   //read device
00239   vDevice* pdev = vDevice::FromFile(rFileName);
00240   //insert device
00241   Insert(pdev);
00242   //and remember its name
00243   mDeviceNames.push_back(rFileName);
00244 }
00245 
00246 
00247 // Compile(void)
00248 void xDevice::Compile(void) {
00249   //build up internal data-structures
00250 
00251   FD_DHV("xDevice("<<mName<<")::Compile()");
00252   Stop();
00253   // build up (event-idx,int)-map and memorize all existing events
00254   // prepare containers
00255   mInputs.Clear();
00256   mOutputs.Clear();
00257   mInputToDevice.clear();
00258   mOutputToDevice.clear();
00259   // temporary container
00260   EventSet tmpSenEvents;
00261   EventSet tmpActEvents;
00262   // event-iterator
00263   EventSet::Iterator eit;
00264   // device-iterator
00265   Iterator dit;
00266   // helper
00267   int j;
00268   // iterate over existing devices
00269   for(dit=Begin(), j=0;  dit!=End(); dit++,j++){
00270     // get events by Index
00271     tmpSenEvents = (*dit)->Inputs();
00272     tmpActEvents = (*dit)->Outputs();
00273     //insert output-events in map
00274     for(eit=tmpActEvents.Begin();eit!=tmpActEvents.End();eit++){
00275       // test if actual event already exists in map
00276       if(mOutputs.Exists(*eit)){
00277         //throw exeption
00278         std::stringstream errstr;
00279         errstr << "Event already exists!";
00280         throw Exception("xDevice()::Compile", errstr.str(), 550);
00281       }
00282       mOutputToDevice[*eit] = j;
00283     }
00284     // memorize events
00285     mInputs.InsertSet(tmpSenEvents);
00286     mOutputs.InsertSet(tmpActEvents);
00287     // tell the device which mutex/condition-pair to use
00288     (*dit)->UseCondition(pWaitMutex,pWaitCondition);
00289     (*dit)->UseBuffer(pBufferMutex,pInputBuffer);
00290   }//end iteration over existing devices
00291   // set time scale from first device
00292   if(Size()!=0) (*Begin())->TimeScale(mTimeScale);
00293 }
00294 
00295 
00296 //Configure(event,attr)
00297 void xDevice::Configure(Idx event, const AttributeDeviceEvent& attr){
00298   (void) event; (void) attr;
00299   // cannot do vDevice style configuration of events
00300 
00301   FD_DHV("xDevice("<<mName<<")::Configure(Idx,attr): ");
00302   std::stringstream errstr;
00303   errstr << "Attempt to configure xDevice by event";
00304   throw Exception("xDevice::Configure(Idx,attr)", errstr.str(), 550);
00305 }
00306 
00307 //Configure(rEvents)
00308 void xDevice::Configure(const EventSet& rEvents){
00309   (void) rEvents;
00310   // cannot do vDevice style configuration of events
00311   
00312   FD_DHV("xDevice("<<mName<<")::Configure(rEvents)");
00313   std::stringstream errstr;
00314   errstr << "Attempt to configure xDevice by events";
00315   throw Exception("xDevice::Configure", errstr.str(), 550);
00316 }
00317 
00318 
00319 //CurrentTime(void)
00320 tpTime::Type xDevice::CurrentTime(void) {
00321 
00322   FD_DHV("xDevice("<<mName<<"): CurrentTime() ");
00323   // throw exception if there is no device
00324   if(Size()==0) {
00325     std::stringstream errstr;
00326     errstr << "xDevice owns no device!";
00327     throw Exception("xDevice::CurrentTime", errstr.str(),550);
00328   }
00329   // ask first device
00330   return (*Begin())->CurrentTime();
00331 }
00332 
00333 
00334 //CurrentTime(void)
00335 long int xDevice::CurrentTimeMs(void) {
00336   //debug flag: say hello
00337   FD_DHV("xDevice("<<mName<<")::CurrentTimeMs() ");
00338   // throw exception if there is no device
00339   if(Size()==0) {
00340     std::stringstream errstr;
00341     errstr << "xDevice owns no device!";
00342     throw Exception("xDevice::CurrentTimeMs", errstr.str(),550);
00343   }
00344   // ask first device
00345   return (*Begin())->CurrentTimeMs();
00346 }
00347 
00348 //CurrentTime(now)
00349 void xDevice::CurrentTime(tpTime::Type now) {
00350   //debug flag: say hello
00351   FD_DHV("xDevice("<<mName<<")::CurrentTime("<<now<<") ");
00352   // tell first device if such
00353   if(Size()!=0) (*Begin())->CurrentTime(now);
00354 }
00355 
00356 //CurrentTimeMs(now)
00357 void xDevice::CurrentTimeMs(long int nowms) {
00358   //debug flag: say hello
00359 
00360   FD_DHV("xDevice("<<mName<<")::CurrentTimeMs("<<nowms<<") ");
00361   // tell first device if such
00362   if(Size()!=0) (*Begin())->CurrentTimeMs(nowms);
00363 }
00364 
00365 //DoWrite(rTr,rLabel)
00366 void xDevice::DoWriteConfiguration(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
00367   (void) rTw;
00368 
00369   FD_DHV("xDevice("<<mName<<")::DoWriteConfiguration()");
00370   // hard coded begin
00371   rTw.WriteBegin("Devices");
00372   // define device-iterator
00373   Iterator dit;
00374   //iterate over all devices 
00375   for(Idx i=0; i<Size(); i++) {
00376     //if device was read from an extra file
00377     if(mDeviceNames.at(i) != ""){ 
00378       //write path to TokenWriter
00379       FD_DHV("xDevice("<<mName<<")::DoWrite(): "<<mDeviceNames.at(i));
00380       rTw.WriteString(mDeviceNames.at(i)); //TODO: relativ path-names
00381     }
00382     //else device was directly read from base-config-file
00383     else if(mDeviceNames.at(i) == ""){
00384       //write configuration 
00385       FD_DHV("xDevice("<<mName<<")::DoWrite(): "<<mDeviceNames.at(i));
00386       (mDevices.at(i))->Write(rTw);
00387     }
00388   } 
00389   rTw.WriteEnd("Devices");
00390 }
00391 
00392 
00393 // ResetRequest()
00394 bool xDevice::ResetRequest(void) {
00395   bool res=false;
00396   Iterator dit;
00397   for(dit=Begin();dit!=End();dit++){
00398     res = res | (*dit)->ResetRequest();
00399   }
00400   return res;
00401 }
00402 
00403 //DoRead(rTr,rLabel)
00404 void xDevice::DoReadConfiguration(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
00405   (void) rLabel; (void) pContext;
00406 
00407   FD_DHV("xDevice("<<mName<<")::DoReadConfiguration()");
00408   //prepare token
00409   Token token;
00410   //prepare string 
00411   std::string filename = "";      //to store filename
00412   std::string dirname = "";  //to store directory
00413   std::string path;          //to store absolut path
00414   // have default section
00415   std::string label = rLabel;
00416   if(label=="") label = "Devices";
00417   // read begin
00418   rTr.ReadBegin(label);
00419   // fill mDevices with devices specified in given file
00420   while(!rTr.Eos("Devices")){
00421     //peek token
00422     rTr.Peek(token);
00423     // if Token is a String we assume its the name of a file containing a device
00424     if(token.Type()==Token::String) {
00425       //read Token
00426       rTr.Get(token);
00427       //import filename
00428       filename = token.StringValue();
00429       //build up path to base-file
00430       if(rTr.SourceMode()==TokenReader::File) dirname = ExtractDirectory(rTr.FileName());
00431       //build up path to specified file
00432       path = dirname.append(filename);
00433       //insert device
00434       Insert(path);
00435       continue;
00436     }
00437     // if its not a file it has to be a device
00438     else if(token.Type()==Token::Begin) {
00439       // read device
00440       vDevice* devp = vDevice::FromTokenReader(rTr);
00441       // insert device mDevices
00442       Insert(devp);
00443       //record that this device was read inline
00444       mDeviceNames.push_back("");
00445     }    
00446   }
00447   rTr.ReadEnd(label);
00448 }
00449 
00450 
00451 // WriteOutput(Idx)
00452 void xDevice::WriteOutput(Idx output){
00453   FD_DHV("xDevice("<<mName<<")::WriteOutput()");
00454   // identify corresponding device(if idx is unique)
00455   int didx = mOutputToDevice[output];
00456   FD_DH("xDevice("<<mName<<")::WriteOutput(): " << output << " to " << didx);
00457   mDevices.at(didx)->WriteOutput(output);
00458 }
00459 
00460 
00461 // FlusgBufferes()
00462 void xDevice::FlushOutputs(void) {
00463   // iterate over all participating devices
00464   for(Iterator dit=Begin();  dit!=End(); dit++)
00465     (*dit)->FlushOutputs();
00466 }
00467 
00468 
00469 
00470 } // name space
00471 
00472 

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen