OpcUaCanOpen
CANopen OPC-UA server
AnaCanScan.cpp
Go to the documentation of this file.
1 
27 #include "AnaCanScan.h"
28 
29 #include <time.h>
30 #include <string.h>
31 #include <map>
32 #include <LogIt.h>
33 #include <sstream>
34 #include <iostream>
35 #include <boost/thread/thread.hpp>
36 
37 #include "CanModuleUtils.h"
38 
39 #ifdef _WIN32
40 
41 #define DLLEXPORTFLAG __declspec(dllexport)
42 
43 #else
44 
45 #include <sys/time.h>
46 
47 #define DLLEXPORTFLAG
48 #define WINAPI
49 
50 #endif
51 
52 
53 using namespace CanModule;
54 using namespace std;
55 
56 boost::mutex anagateReconnectMutex;
57 
58 /* static */ bool AnaCanScan::s_isCanHandleInUseArray[256];
59 /* static */ AnaInt32 AnaCanScan::s_canHandleArray[256];
61 /* static */ std::map<string,bool> AnaCanScan::reconnectInProgress_map;
62 
63 #define MLOGANA(LEVEL,THIS) LOG(Log::LEVEL, AnaCanScan::st_logItHandleAnagate) << __FUNCTION__ << " " << " anagate bus= " << THIS->getBusName() << " "
64 
71 std::map<AnaInt32, AnaCanScan*> g_AnaCanScanPointerMap;
72 
74  m_canPortNumber(0),
75  m_canIPAddress( (char *) string("192.168.1.2").c_str()),
76  m_baudRate(0),
77  m_idCanScanThread(0),
78  m_canCloseDevice(false),
79  m_busName(""),
80  m_busParameters(""),
81  m_UcanHandle(0),
82  m_timeout ( 12000 )
83 {
85 }
86 
91 {
92  stopBus();
93 }
94 
96 {
97  MLOGANA(TRC,this) << __FUNCTION__ << " m_busName= " << m_busName << " m_canPortNumber= " << m_canPortNumber;
98  CANSetCallback(m_UcanHandle, 0);
99  CANCloseDevice(m_UcanHandle);
100 
101 // setCanHandleInUse(m_canPortNumber,false);
103 
104 #ifdef _WIN32
105 #else
106  MLOGANA(TRC, this ) << " imposing a delay of 7 seconds before continuing";
107  boost::this_thread::sleep_for(boost::chrono::milliseconds( 7000 ));
108 #endif
109  MLOGANA(TRC,this) << " finished";
110 }
111 
112 
113 /* static */ void AnaCanScan::setIpReconnectInProgress( string ip, bool flag ){
114  // only called inside the locked mutex
115  std::map<string,bool>::iterator it = AnaCanScan::reconnectInProgress_map.find( ip );
116 
117  if ( flag ){
118  // mark as in progress if not yet exists/marked
119  if ( it == AnaCanScan::reconnectInProgress_map.end() ) {
120  AnaCanScan::reconnectInProgress_map.insert ( std::pair<string,bool>( ip, true ) );
121  }
122  } else {
123  // erase existing if still exists/marked
124  if ( it != AnaCanScan::reconnectInProgress_map.end() ) {
126  }
127  }
128 }
129 
130 /* static */ bool AnaCanScan::isIpReconnectInProgress( string ip ){
131  // only called inside the locked mutex
132  std::map<string,bool>::iterator it = AnaCanScan::reconnectInProgress_map.find( ip );
133  if ( it == AnaCanScan::reconnectInProgress_map.end() )
134  return( false );
135  else
136  return( true );
137 }
138 
139 
144 {
145  CCanAccess *canAccess = new AnaCanScan;
146  return canAccess;
147 }
148 
149 
154 void WINAPI InternalCallback(AnaUInt32 nIdentifier, const char * pcBuffer, AnaInt32 nBufferLen, AnaInt32 nFlags, AnaInt32 hHandle, AnaInt32 nSeconds, AnaInt32 nMicroseconds)
155 {
156  CanMessage canMsgCopy;
157  if (nFlags == 2) return;
158  canMsgCopy.c_id = nIdentifier;
159  canMsgCopy.c_dlc = nBufferLen;
160  canMsgCopy.c_ff = nFlags;
161  for (int i = 0; i < nBufferLen; i++)
162  canMsgCopy.c_data[i] = pcBuffer[i];
163 
165 
166  //cout << __FILE__ << " " << __LINE__ << " " << __FUNCTION__
167  // << " anagate message reception hHandle= " << hHandle
168  // << " nIdentifier= " << nIdentifier
169  // << endl;
170  MLOGANA(TRC, g_AnaCanScanPointerMap[hHandle] ) << "read(): " << AnaCanScan::canMessageToString(canMsgCopy);
171  //MLOGANA(TRC, this) << __FUNCTION__ << " CanModule anagate " << AnaCanScan::canMessageToString(canMsgCopy);
172  g_AnaCanScanPointerMap[hHandle]->callbackOnRecieve(canMsgCopy);
173  g_AnaCanScanPointerMap[hHandle]->statisticsOnRecieve( nBufferLen );
174 }
175 
177 {
178  std::string result;
179  result = "[id=0x"+CanModuleUtils::toHexString(f.c_id, 3, '0')+" ";
180  if (f.c_id & f.c_rtr)
181  result += "RTR ";
182  result+="dlc=" + CanModuleUtils::toString(int(f.c_dlc)) + " data=[";
183 
184  for (int i=0; i<f.c_dlc; i++)
185  result+= CanModuleUtils::toHexString((unsigned int)f.c_data[i], 2, '0')+" ";
186  result += "]]";
187 
188  return result;
189 }
190 
195 {
196  m_statistics.onReceive( bytes );
197 }
198 
203 {
204  canMessageCame( msg );
205 }
206 
230 bool AnaCanScan::createBus(const string name,const string parameters)
231 {
232  m_busName = name;
233  m_busParameters = parameters;
234 
235  // calling base class to get the instance from there
236  Log::LogComponentHandle myHandle;
237  LogItInstance* logItInstance = CCanAccess::getLogItInstance(); // actually calling instance method, not class
238  // std::cout << __FILE__ << " " << __LINE__ << " " << __FUNCTION__ << " ptr= 0x" << logItInstance << std::endl;
239 
240  // register anagate component for logging
241  if ( !LogItInstance::setInstance(logItInstance))
242  std::cout << __FILE__ << " " << __LINE__ << " " << __FUNCTION__
243  << " could not set LogIt instance" << std::endl;
244 
245 
246  if (!logItInstance->getComponentHandle(CanModule::LogItComponentName, myHandle))
247  std::cout << __FILE__ << " " << __LINE__ << " " << __FUNCTION__
248  << " could not get LogIt component handle for " << LogItComponentName << std::endl;
249 
250  //LOG(Log::TRC, myHandle) << __FUNCTION__ << " " __FILE__ << " " << __LINE__;
252  int returnCode = configureCanBoard(name, parameters);
253  if ( returnCode < 0 ) {
254  return false;
255  }
256  MLOGANA(DBG,this) << " OK, Bus created with name= " << name << " parameters= " << parameters;
257  return true;
258 }
259 
260 
264 int AnaCanScan::configureCanBoard(const string name,const string parameters)
265 {
266  MLOGANA(DBG, this) << "(user supplied) name= " << name << " parameters= " << parameters;
267  vector<string> stringVector;
268  stringVector = parseNameAndParameters(name, parameters);
269 
270  // we should decode 3 elements from this:0="an" for anagate library, 1=can port, 2=ip number
271  // like "an:0:128.141.159.194"
272  if ( stringVector.size() != 3 ){
273  MLOGANA(ERR, this) << " need exactly 3 elements delimited by \":\" like \"an:0:128.141.159.194\", got "
274  << stringVector.size();
275  for ( unsigned i = 0; i < stringVector.size(); i++ ){
276  MLOGANA(ERR, this) << " stringVector[" << i << "]= " << stringVector[ i ];
277  }
278  return(-1);
279  } else {
280  for ( unsigned i = 0; i < stringVector.size(); i++ ){
281  MLOGANA(TRC, this) << "(cleaned up) stringVector[" << i << "]= " << stringVector[ i ];
282  }
283  m_canPortNumber = atoi(stringVector[1].c_str());
284  m_canIPAddress = (char *) stringVector[2].c_str();
285  }
286  MLOGANA(TRC, this) << "(cleaned up) canPortNumber= " << m_canPortNumber << " ip= " << m_canIPAddress;
287 
288  // handle up to 5 parameter, assume defaults if needed
289  m_baudRate = 125000L;
290 
291  if (strcmp(parameters.c_str(), "Unspecified") != 0) {
292 
293  MLOGANA(TRC, this) << "m_CanParameters.m_iNumberOfDetectedParameters" << m_CanParameters.m_iNumberOfDetectedParameters;
294 
297 
298  MLOGANA(TRC, this) << "m_lBaudRate= " << m_CanParameters.m_lBaudRate;
299  MLOGANA(TRC, this) << "m_iOperationMode= " << m_CanParameters.m_iOperationMode;
300  MLOGANA(TRC, this) << "m_iTermination= " << m_CanParameters.m_iTermination;
301  MLOGANA(TRC, this) << "m_iHighSpeed= " << m_CanParameters.m_iHighSpeed;
302  MLOGANA(TRC, this) << "m_iTimeStamp= " << m_CanParameters.m_iTimeStamp;
303 
304  // any other parameters are already set, either to 0 by init,
305  // or by decoding. They are always used.
306  } else {
307  MLOGANA(ERR, this) << "Error while parsing parameters: this syntax is incorrect: [" << parameters << "]";
308  MLOGANA(ERR, this) << "you need up to 5 numbers separated by whitespaces, i.e. \"125000 0 0 0 0\" \"p0 p1 p2 p3 p4\"";
309  MLOGANA(ERR, this) << " p0 = baud rate, 125000 or whatever the module supports";
310  MLOGANA(ERR, this) << " p1 = operation mode";
311  MLOGANA(ERR, this) << " p2 = termination";
312  MLOGANA(ERR, this) << " p3 = high speed";
313  MLOGANA(ERR, this) << " p4 = time stamp";
314  return -1;
315  }
316  } else {
317  MLOGANA(INF, this) << "Unspecified parameters, default values will be used.";
318  }
319  return openCanPort();
320 }
321 
332 {
333  AnaInt32 anaCallReturn;
334  AnaInt32 canModuleHandle;
335 
336  // check if USB-CANmodul already is initialized
337  //if (isCanHandleInUse(m_canPortNumber)) {
338  // //if it is, we get the handle
339  // canModuleHandle = getCanHandleFromPort(m_canPortNumber);
340  //} else {
341  //Otherwise we create it.
342  MLOGANA(DBG, this) << "Will call CANOpenDevice with parameters m_canHandleNumber:[" << m_canPortNumber << "], m_canIPAddress:[" << m_canIPAddress << "]";
343  anaCallReturn = CANOpenDevice(&canModuleHandle, FALSE, TRUE, m_canPortNumber, m_canIPAddress.c_str(), m_timeout);
344  if (anaCallReturn != 0) {
345  // fill out initialisation struct
346  MLOGANA(ERR,this) << "Error in CANOpenDevice, return code = [" << anaCallReturn << "]";
347  return -1;
348  }
349 // }
350 
351 // setCanHandleInUse(m_canPortNumber,true);
352 
353  // initialize CAN interface
354  MLOGANA(TRC,this) << "calling CANSetGlobals with m_lBaudRate= "
356  << " m_iOperationMode= " << m_CanParameters.m_iOperationMode
357  << " m_iTermination= " << m_CanParameters.m_iTermination
358  << " m_iHighSpeed= " << m_CanParameters.m_iHighSpeed
359  << " m_iTimeStamp= " << m_CanParameters.m_iTimeStamp;
360 
361  anaCallReturn = CANSetGlobals(canModuleHandle, m_CanParameters.m_lBaudRate, m_CanParameters.m_iOperationMode,
363  switch ( anaCallReturn ){
364  case 0:{ break; }
365  case 0x30000: {
366  MLOGANA(ERR,this) << "Connection to TCP/IP partner can't be established or is disconnected. Lost TCP/IP: 0x" << hex << anaCallReturn << dec;
367  return -1;
368  }
369  case 0x40000: {
370  MLOGANA(ERR,this) << "No answer was received from TCP/IP partner within the defined timeout. Lost TCP/IP: 0x" << hex << anaCallReturn << dec;
371  return -1;
372  }
373  case 0x900000: {
374  MLOGANA(ERR,this) << "Invalid device handle. Lost TCP/IP: 0x" << hex << anaCallReturn << dec;
375  return -1;
376  }
377  default : {
378  MLOGANA(ERR,this) << "Other Error in CANSetGlobals: 0x" << hex << anaCallReturn << dec;
379  return -1;
380  }
381  }
382  // set handler for managing incoming messages
383  anaCallReturn = CANSetCallbackEx(canModuleHandle, InternalCallback);
384  if (anaCallReturn != 0) {
385  MLOGANA(ERR,this) << "Error in CANSetCallbackEx, return code = [" << anaCallReturn << "]";
386  return -1;
387  } else {
388  MLOGANA(TRC,this) << "OK CANSetCallbackEx, return code = [" << anaCallReturn << "]";
389  }
390 
391 // setCanHandleOfPort(m_canPortNumber, canModuleHandle);
392  g_AnaCanScanPointerMap[canModuleHandle] = this;
393 
394  // We associate in the global map the handle with the instance of the AnaCanScan object,
395  // so it can later be identified by the callback InternalCallback in a speedy way
396  m_UcanHandle = canModuleHandle;
397 
398  MLOGANA(TRC,this) << "handles: ";
400  return 0;
401 }
402 
403 bool AnaCanScan::sendErrorCode(AnaInt32 status)
404 {
405  char errorMessage[120];
406  timeval ftTimeStamp;
407  if (status != 0) {
408  auto now = std::chrono::system_clock::now();
409  auto nMicrosecs =
410  duration_cast<std::chrono::microseconds>(
411  now.time_since_epoch()
412  );
413  ftTimeStamp.tv_sec = nMicrosecs.count() / 1000000L;
414  ftTimeStamp.tv_usec = (nMicrosecs.count() % 1000000L) ;
415 
416  if (!errorCodeToString(status, errorMessage))
417  canMessageError(status, errorMessage, ftTimeStamp);
418  }
419  return true;
420 }
421 
432 bool AnaCanScan::sendMessage(short cobID, unsigned char len, unsigned char *message, bool rtr)
433 {
434  MLOGANA(DBG,this) << "Sending message: [" << ( message == 0 ? "" : (const char *) message) << "], cobID: [" << cobID << "], Message Length: [" << static_cast<int>(len) << "]";
435  AnaInt32 anaCallReturn;
436  unsigned char *messageToBeSent[8];
437  AnaInt32 flags = 0x0;
438  if (rtr) {
439  flags = 2; // Bit 1: If set, the telegram is marked as remote frame.
440  }
441  int messageLengthToBeProcessed;
442 
443  //If there is more than 8 characters to process, we process 8 of them in this iteration of the loop
445  if (len > 8) {
446  messageLengthToBeProcessed = 8;
447  MLOGANA(DBG, this) << "The length is more than 8 bytes, ignoring overhead, no extended CAN msg yet " << len;
448  } else {
449  messageLengthToBeProcessed = len;
450  }
451  // MLOG(TRC, this) << "Going to memcopy " << messageToBeSent << ";" << message << ";" << messageLengthToBeProcessed;
452  memcpy(messageToBeSent, message, messageLengthToBeProcessed);
453  MLOGANA(TRC, this) << " m_canPortNumber= " << m_canPortNumber
454  << " cobID= " << cobID
455  << " length = " << messageLengthToBeProcessed
456  << " flags= " << flags << " m_UcanHandle= " << m_UcanHandle;
457  anaCallReturn = CANWrite(m_UcanHandle, cobID, reinterpret_cast<char*>(messageToBeSent), messageLengthToBeProcessed, flags);
458  if (anaCallReturn != 0) {
459  MLOGANA(ERR, this) << "There was a problem when sending a message with CANWrite: 0x" << hex << anaCallReturn << dec;
460  m_canCloseDevice = false;
461 
470  AnaInt32 anaCallReturn0 = AnaCanScan::reconnectAllPorts( m_canIPAddress );
471  while ( anaCallReturn0 < 0 ){
472  MLOGANA(WRN, this) << "failed to reconnect all module CAN ports once, keep on trying to reconnect. ip= " << m_canIPAddress;
473  anaCallReturn0 = AnaCanScan::reconnectAllPorts( m_canIPAddress );
474  }
475  objectMapSize();
476  } else {
477  m_statistics.onTransmit(messageLengthToBeProcessed);
478  }
479  return sendErrorCode(anaCallReturn);
480 }
481 
482 /* static */ void AnaCanScan::objectMapSize(){
483  uint32_t size = g_AnaCanScanPointerMap.size();
484  LOG(Log::TRC, AnaCanScan::st_logItHandleAnagate ) << __FUNCTION__ << " RECEIVE obj. map size= " << size << " : ";
485  for (std::map<AnaInt32, AnaCanScan*>::iterator it=g_AnaCanScanPointerMap.begin(); it!=g_AnaCanScanPointerMap.end(); it++){
486  LOG(Log::TRC, AnaCanScan::st_logItHandleAnagate ) << __FUNCTION__ << " obj. map "
487  << " key= " << it->first
488  << " ip= " << it->second->ipAdress()
489  << " CAN port= " << it->second->canPortNumber()
490  << " handle= " << it->second->handle()
491  << " (used?= " << it->second->isCanHandleInUse(it->second->handle()) << ")"
492  << " ptr= 0x" << hex << (unsigned long) (it->second) << dec;
493 
494  }
495 }
496 
513 /* static */ AnaInt32 AnaCanScan::reconnectAllPorts( string ip ){
514 
515  // protect against several calls on the same ip.
516  // We need a mutex to force serialize this.
517  {
518  anagateReconnectMutex.lock();
520  LOG(Log::WRN, AnaCanScan::st_logItHandleAnagate ) << "reconnecting all ports for ip= " << ip
521  << " is already in progress, skipping.";
522 
523  int us = 10000000;
524  boost::this_thread::sleep(boost::posix_time::microseconds( us ));
525  anagateReconnectMutex.unlock();
526 
527  return(1);
528  }
530  LOG(Log::TRC, AnaCanScan::st_logItHandleAnagate ) << "reconnecting all ports for ip= " << ip
531  << " is now in progress.";
532  anagateReconnectMutex.unlock();
533  }
534 
535  int ret = 0;
536  AnaInt32 anaRet = 0;
537 
538  // re-open the can port and get a new handle, but do NOT yet put the new object (this, again) into
539  // the global map. Keep the reception disconnected still.
540  int nbCANportsOnModule = 0;
541  bool reconnectFailed = false;
542  for (std::map<AnaInt32, AnaCanScan*>::iterator it=g_AnaCanScanPointerMap.begin(); it!=g_AnaCanScanPointerMap.end(); it++){
543  if ( ip == it->second->ipAdress() ){
545  << " key= " << it->first
546  << " found ip= " << ip
547  << " for CAN port= " << it->second->canPortNumber()
548  << " reconnecting...";
549 
550  ret = it->second->reconnect();
551  if ( ret ){
553  << " key= " << it->first
554  << " found ip= " << ip
555  << " for CAN port= " << it->second->canPortNumber()
556  << " failed to reconnect";
557  reconnectFailed = true;
558  }
559  nbCANportsOnModule++;
560  }
561  }
562  LOG(Log::TRC, AnaCanScan::st_logItHandleAnagate) << " CAN bridge at ip= " << ip << " uses nbCANportsOnModule= " << nbCANportsOnModule;
563 
564  if ( reconnectFailed ) {
565  LOG(Log::WRN, AnaCanScan::st_logItHandleAnagate ) << " Problem reconnecting CAN ports for ip= " << ip
566  << " last ret= " << ret << ". Just abandoning and trying again in 10 secs, module might not be ready yet.";
567  int us = 10000000;
568  boost::this_thread::sleep(boost::posix_time::microseconds( us ));
569 
571  LOG(Log::TRC, AnaCanScan::st_logItHandleAnagate ) << "reconnecting all ports for ip= " << ip
572  << " cancel.";
573  return(-1);
574  }
575 
576  // register the new handler with the obj. map and connect the reception handler. Cleanup the stale handlers
577  std::map<AnaInt32, AnaCanScan*> lmap = g_AnaCanScanPointerMap; // use a local copy of the map, in order
578  // not to change the map we are iterating on
579 
580  LOG(Log::TRC, AnaCanScan::st_logItHandleAnagate) << __FUNCTION__ << " " __FILE__ << " " << __LINE__
581  << " receive handler map map before reconnect for ip= " << ip;
583 
584  for (std::map<AnaInt32, AnaCanScan*>::iterator it=lmap.begin(); it!=lmap.end(); it++){
585  if ( ip == it->second->ipAdress() ){
586  anaRet = it->second->connectReceptionHandler();
587  if ( anaRet != 0 ){
588  LOG(Log::ERR, AnaCanScan::st_logItHandleAnagate) << __FUNCTION__ << " " __FILE__ << " " << __LINE__
589  << " failed to reconnect reception handler for ip= " << ip
590  << " handle= " << it->second->handle()
591  << " port= " << it->second->canPortNumber()
592  << " anaRet= " << anaRet;
593  } else {
594  LOG(Log::TRC, AnaCanScan::st_logItHandleAnagate ) << __FUNCTION__ << " " __FILE__ << " " << __LINE__
595  << " reconnect reception handler for ip= " << ip
596  << " handle= " << it->second->handle()
597  << " looking good= " << anaRet;
598  }
599 
605  if ( it->first != it->second->handle()){
606  LOG(Log::TRC, AnaCanScan::st_logItHandleAnagate) << __FUNCTION__ << " " __FILE__ << " " << __LINE__
607  << " erasing stale handler " << it->first
608  << " for object handle= " << it->second->handle() << " from obj. map";
609  g_AnaCanScanPointerMap.erase( it->first );
610  }
611  AnaCanScan::setIpReconnectInProgress( ip, false ); // all done, may fail another time
612  LOG(Log::TRC, AnaCanScan::st_logItHandleAnagate ) << "reconnecting all ports for ip= " << ip
613  << " is done and OK.";
614  }
615  }
616  LOG(Log::TRC, AnaCanScan::st_logItHandleAnagate) << __FUNCTION__ << " " __FILE__ << " " << __LINE__
617  << " receive handler map after reconnect for ip= " << ip;
619 
620  // be easy on the switch, can maybe suppress this later
621  int us = 100000;
622  boost::this_thread::sleep(boost::posix_time::microseconds( us ));
623  return( anaRet );
624 }
625 
632  AnaInt32 anaCallReturn;
633 
634  // this is needed otherwise the bridge hangs in a bad state
637  switch ( anaCallReturn ){
638  case 0:{ break; }
639  case 0x30000: {
640  MLOGANA(ERR,this) << "Connection to TCP/IP partner can't be established or is disconnected. Lost TCP/IP: 0x" << hex << anaCallReturn << dec;
641  return -1;
642  }
643  case 0x40000: {
644  MLOGANA(ERR,this) << "No answer was received from TCP/IP partner within the defined timeout. Lost TCP/IP: 0x" << hex << anaCallReturn << dec;
645  return -1;
646  }
647  case 0x900000: {
648  MLOGANA(ERR,this) << "Invalid device handle. Lost TCP/IP: 0x" << hex << anaCallReturn << dec;
649  return -1;
650  }
651  default : {
652  MLOGANA(ERR,this) << "Other Error in CANSetGlobals: 0x" << hex << anaCallReturn << dec;
653  return -1;
654  }
655  }
656 
657  MLOGANA(WRN,this) << "connecting RECEIVE canModuleHandle= " << m_UcanHandle
658  << " ip= " << m_canIPAddress;
659  anaCallReturn = CANSetCallbackEx(m_UcanHandle, InternalCallback);
660  if (anaCallReturn != 0) {
661  MLOGANA(ERR,this) << "failed CANSetCallbackEx, return code = [" << anaCallReturn << "]"
662  << " canModuleHandle= " << m_UcanHandle
663  << " in a reconnect! Can't fix this, maybe hardware/firmware problem.";
664  // that is very schlecht, need a good idea (~check keepalive and sending fake messages)
665  // to detect and possibly recuperate from that. Does this case happen actually?
666  }
667  MLOGANA(DBG,this) << "adding RECEIVE handler, handle= " << m_UcanHandle
668  << " CAN port= " << m_canPortNumber
669  << " ip= " << m_canIPAddress << " to obj.map.";
672 
673  MLOGANA(DBG,this) << "RECEIVE handler looks good, handle= " << m_UcanHandle
674  << " CAN port= " << m_canPortNumber
675  << " ip= " << m_canIPAddress << " Congratulations.";
676  return( anaCallReturn );
677 }
678 
679 
681  std::map<AnaInt32, AnaCanScan *>::iterator it = g_AnaCanScanPointerMap.find( h );
682  if (it != g_AnaCanScanPointerMap.end()) {
683  g_AnaCanScanPointerMap.erase ( it );
684  m_busName = "nobus";
685  } else {
686  MLOGANA(DBG,this) << " handler " << h << " not found in map, not erased";
687  }
688 }
689 
699  AnaInt32 anaCallReturn;
700  AnaInt32 canModuleHandle;
701  // we are not too fast. sleep to wait for network and don't hammer the switch
702  int us = 100000;
703 
704  MLOGANA(WRN, this) << "try to reconnect ip= " << m_canIPAddress
705  << " m_canPortNumber= " << m_canPortNumber
706  << " m_UcanHandle= " << m_UcanHandle;
707 
708  int state = CANDeviceConnectState( m_UcanHandle );
709  MLOGANA(TRC, this) << "CANDeviceConnectState: device connect state= 0x" << hex << state << dec;
728  switch ( state ){
729  case 2: {
730  MLOGANA(INF,this) << "device is in state CONNECTING, don't try to reconnect for now, skip.";
731  break;
732  }
733 
734  case 3: {
735  MLOGANA(INF,this) << "device is in state CONNECTED, don't try to reconnect, just skip.";
736  break;
737  }
738  default:
739  case 1:
740  case 4:
741  case 5:{
742  if ( !m_canCloseDevice ) {
743  anaCallReturn = CANCloseDevice( m_UcanHandle );
744  MLOGANA(WRN, this) << "closed device m_UcanHandle= " << m_UcanHandle
745  << " anaCallReturn= 0x" << hex << anaCallReturn << dec;
746  if ( anaCallReturn != 0 ) {
747  MLOGANA(WRN, this) << "could not close device m_UcanHandle= " << m_UcanHandle
748  << " anaCallReturn= 0x" << hex << anaCallReturn << dec;
749  // return(-3);
750  }
751  m_canCloseDevice = true;
752  MLOGANA(TRC, this) << "device is closed. stale handle= " << m_UcanHandle;
753  } else {
754  MLOGANA(WRN, this) << "device is already closed, try reopen. stale handle= " << m_UcanHandle;
755  }
757 
758  MLOGANA(TRC,this) << "try CANOpenDevice m_canPortNumber= " << m_canPortNumber
759  << " m_UcanHandle= " << m_UcanHandle
760  << " ip= " << m_canIPAddress << " timeout= " << m_timeout;
761  anaCallReturn = CANOpenDevice(&canModuleHandle, FALSE, TRUE, m_canPortNumber, m_canIPAddress.c_str(), m_timeout);
762  if (anaCallReturn != 0) {
763  MLOGANA(ERR,this) << "CANOpenDevice failed: 0x" << hex << anaCallReturn << dec;
764  m_canCloseDevice = false;
765  return(-1);
766  }
767  MLOGANA(DBG,this) << "CANOpenDevice m_canPortNumber= " << m_canPortNumber
768  << " canModuleHandle= " << canModuleHandle
769  << " ip= " << m_canIPAddress << " timeout= " << m_timeout << " reconnect for SEND looks good";
770 
772  setCanHandleOfPort( m_canPortNumber, canModuleHandle );
773 
774  m_UcanHandle = canModuleHandle;
775  m_canCloseDevice = false;
776  break;
777  }
778  }
779  boost::this_thread::sleep(boost::posix_time::microseconds( us ));
780  return( 0 ); // OK
781 }
782 
788 void AnaCanScan::setConnectWaitTime( int timeout_ms ){
789  m_timeout = timeout_ms;
790  MLOGANA(WRN,this) << "reconnect CANOpenDevice m_UcanHandle= " << m_UcanHandle << " to apply new timeout= " << m_timeout;
791  reconnect();
792 }
793 
798 void AnaCanScan::startAlive( int aliveTime_sec ){
799  AnaInt32 anaCallReturn = CANStartAlive( m_UcanHandle, aliveTime_sec );
800  if ( anaCallReturn != 0 ){
801  MLOGANA(ERR,this) << "could not start alive mechanism, error= 0x" << hex << anaCallReturn << dec;
802  } else {
803  MLOGANA(DBG,this) << "started alive mechanism on handle= " << m_UcanHandle;
804  }
805 }
806 
808 {
809  return sendMessage(short(canm->c_id), canm->c_dlc, canm->c_data, canm->c_rtr);
810 }
811 
820 {
821  AnaInt32 anaCallReturn;
822  AnaInt32 flags = 2;// Bit 1: If set, the telegram is marked as remote frame.
823 
824  anaCallReturn = CANWrite(m_UcanHandle,cobID,NULL, 0, flags);
825  if (anaCallReturn != 0) {
826  MLOGANA(ERR,this) << "There was a problem when sending a message with CANWrite";
827  }
828  return sendErrorCode(anaCallReturn);
829 }
830 
836 bool AnaCanScan::errorCodeToString(long error, char message[])
837 {
838  char tmp[300] = "Error";
839  // canGetErrorText((canStatus)error, tmp, sizeof(tmp));
840  // *message = new char[strlen(tmp)+1];
841  // message[0] = 0;
842  strcpy(message,tmp);
843  return true;
844 }
845 
847 {
849  result = m_statistics; // copy whole structure
851 }