iop_xdevice.cppGo 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 |