OpcUaCanOpen
CANopen OPC-UA server
STCanScan.cpp
Go to the documentation of this file.
1 
25 #include "STCanScan.h"
26 
27 #include <time.h>
28 #include <string.h>
29 #include "CanModuleUtils.h"
30 
31 #include <LogIt.h>
32 
35 tUcanHandle STCanScan::s_canHandleArray[256];
36 
39 
40 #define MLOGST(LEVEL,THIS) LOG(Log::LEVEL, THIS->logItHandle()) << __FUNCTION__ << " " << " systec bus= " << THIS->getBusName() << " "
41 
42 #ifdef _WIN32
43 
44 #define DLLEXPORTFLAG __declspec(dllexport)
45 
46 #else
47 
48 #include <sys/time.h>
49 
50 #define DLLEXPORTFLAG
51 #define WINAPI
52 
53 #endif
54 
56 {
57  CCanAccess *canAccess = new STCanScan;
58  return canAccess;
59 }
60 
62  m_CanScanThreadShutdownFlag(true),
63  m_moduleNumber(0),
64  m_channelNumber(0),
65  m_canHandleNumber(0),
66  m_busStatus(USBCAN_SUCCESSFUL),
67  m_baudRate(0),
68  m_idCanScanThread(0)
69 {
70  m_statistics.beginNewRun();
71 }
72 
73 
78 {
79  BYTE status;
80  tCanMsgStruct readCanMessage;
81  STCanScan *canScanInstancePointer = reinterpret_cast<STCanScan *>(pCanScan);
82  MLOGST(DBG,canScanInstancePointer) << "CanScanControlThread Started. m_CanScanThreadShutdownFlag = [" << canScanInstancePointer->m_CanScanThreadShutdownFlag <<"]";
83  while (canScanInstancePointer->m_CanScanThreadShutdownFlag) {
84  status = UcanReadCanMsgEx(canScanInstancePointer->m_UcanHandle, (BYTE *)&canScanInstancePointer->m_channelNumber, &readCanMessage, 0);
85  if (status == USBCAN_SUCCESSFUL) {
86  if (readCanMessage.m_bFF == USBCAN_MSG_FF_RTR)
87  continue;
88  CanMessage canMsgCopy;
89 
90  canMsgCopy.c_id = readCanMessage.m_dwID;
91  canMsgCopy.c_dlc = readCanMessage.m_bDLC;
92  canMsgCopy.c_ff = readCanMessage.m_bFF;
93  for (int i = 0; i < 8; i++)
94  canMsgCopy.c_data[i] = readCanMessage.m_bData[i];
95 
97  MLOGST(DBG, canScanInstancePointer) << "Received message: [" << hex << (int)canMsgCopy.c_data[0] << hex <<
98  (int)canMsgCopy.c_data[1] << (int)canMsgCopy.c_data[2] << (int)canMsgCopy.c_data[3] << (int)canMsgCopy.c_data[4] << (int)canMsgCopy.c_data[5] << (int)canMsgCopy.c_data[6] << (int)canMsgCopy.c_data[7] <<
99  "], cobID: [" << readCanMessage.m_dwID << "], Message Length: [" << static_cast<int>(readCanMessage.m_bDLC) << "]";
100 
101  canScanInstancePointer->canMessageCame(canMsgCopy);
102  canScanInstancePointer->m_statistics.onReceive( readCanMessage.m_bDLC );
103  } else {
104  if (status == USBCAN_WARN_NODATA) {
105  Sleep(100);
106  } else {
107  canScanInstancePointer->sendErrorCode(status);
108  }
109  }
110  }
111  ExitThread(0);
112  return 0;
113 }
114 
116 {
118  //Shut down can scan thread
119  DWORD result = WaitForSingleObject(m_hCanScanThread, INFINITE);
120  // deinitialize CAN interface
121  ::UcanDeinitCanEx (m_UcanHandle,(BYTE)m_channelNumber);
122  MLOGST(DBG,this) << "ST Can Scan component closed successfully";
123 }
124 
151 bool STCanScan::createBus(const string name,const string parameters)
152 {
153  LogItInstance* logItInstance = CCanAccess::getLogItInstance(); // actually calling instance method, not class
154 
155  if ( !LogItInstance::setInstance(logItInstance))
156  std::cout << __FILE__ << " " << __LINE__ << " " << __FUNCTION__
157  << " could not set LogIt instance" << std::endl;
158 
160  std::cout << __FILE__ << " " << __LINE__ << " " << __FUNCTION__
161  << " could not get LogIt component handle for " << LogItComponentName << std::endl;
162 
163 
164  MLOGST(DBG, this) << " name= " << name << " parameters= " << parameters << ", configuring CAN board";
165  m_sBusName = name;
166  int returnCode = configureCanBoard(name, parameters);
167  if (returnCode < 0) {
168  return false;
169  }
170 
171  // After the canboard is configured and started, we start the scan control thread
172  m_hCanScanThread = CreateThread(NULL, 0, CanScanControlThread, this, 0, &m_idCanScanThread);
173  if (NULL == m_hCanScanThread) {
174  MLOGST(ERR,this) << "creating the canScanControl thread.";
175  return false;
176  }
177  MLOGST(DBG,this) << " Bus [" << name << "] created with parameters [" << parameters << "]";
178  return true;
179 }
180 
181 int STCanScan::configureCanBoard(const string name,const string parameters)
182 {
183  long baudRate = USBCAN_BAUD_125kBit;
184 
185  vector<string> stringVector;
186  stringVector = parseNameAndParameters(name, parameters);
187 
188  const char *na = stringVector[1].c_str();
189  m_canHandleNumber = atoi(na);
192 
193  MLOGST(TRC, this) << " m_canHandleNumber:[" << m_canHandleNumber << "], m_moduleNumber:[" << m_moduleNumber << "], m_channelNumber:[" << m_channelNumber << "]";
194 
195  if (strcmp(parameters.c_str(), "Unspecified") != 0) {
196  /* Set baud rate to 125 Kbits/second. */
199  {
200  case 50000: baudRate = USBCAN_BAUD_50kBit; break;
201  case 100000: baudRate = USBCAN_BAUD_100kBit; break;
202  case 125000: baudRate = USBCAN_BAUD_125kBit; break;
203  case 250000: baudRate = USBCAN_BAUD_250kBit; break;
204  case 500000: baudRate = USBCAN_BAUD_500kBit; break;
205  case 1000000: baudRate = USBCAN_BAUD_1MBit; break;
206  default: baudRate = m_CanParameters.m_lBaudRate;
207  }
208  } else {
209  MLOGST(ERR, this) << "parsing parameters: this syntax is incorrect: [" << parameters << "]";
210  return -1;
211  }
212  m_baudRate = baudRate;
213  } else {
214  m_baudRate = baudRate;
215  MLOGST(DBG, this) << "Unspecified parameters, default values will be used.";
216  }
217 
218  // We create and fill initializationParameters, to pass it to openCanPort
219  tUcanInitCanParam initializationParameters;
220  initializationParameters.m_dwSize = sizeof(initializationParameters); // size of this struct
221  initializationParameters.m_bMode = kUcanModeNormal; // normal operation mode
222  initializationParameters.m_bBTR0 = HIBYTE(baudRate); // baudrate
223  initializationParameters.m_bBTR1 = LOBYTE(baudRate);
224  initializationParameters.m_bOCR = 0x1A; // standard output
225  initializationParameters.m_dwAMR = USBCAN_AMR_ALL; // receive all CAN messages
226  initializationParameters.m_dwACR = USBCAN_ACR_ALL;
227  initializationParameters.m_dwBaudrate = USBCAN_BAUDEX_USE_BTR01;
228  initializationParameters.m_wNrOfRxBufferEntries = USBCAN_DEFAULT_BUFFER_ENTRIES;
229  initializationParameters.m_wNrOfTxBufferEntries = USBCAN_DEFAULT_BUFFER_ENTRIES;
230 
231  return openCanPort(initializationParameters);
232 }
233 
240 int STCanScan::openCanPort(tUcanInitCanParam initializationParameters)
241 {
242  BYTE systecCallReturn = USBCAN_SUCCESSFUL;
243  //The Handle of the can Module
244  tUcanHandle canModuleHandle;
245 
246  // check if USB-CANmodul already is initialized
248  {
249  //if it is, we get the handle
250  canModuleHandle = getCanHandle(m_moduleNumber);
251  }
252  else
253  {
254  //Otherwise we create it.
255  systecCallReturn = ::UcanInitHardwareEx(&canModuleHandle, m_moduleNumber, 0, 0);
256  if (systecCallReturn != USBCAN_SUCCESSFUL)
257  {
258  // fill out initialisation struct
259  MLOGST(ERR,this) << "UcanInitHardwareEx, return code = [" << systecCallReturn << "]";
260  ::UcanDeinitHardware(canModuleHandle);
261  return -1;
262  }
263  }
264 
266  // initialize CAN interface
267  systecCallReturn = ::UcanInitCanEx2(canModuleHandle, m_channelNumber, &initializationParameters);
268  if (systecCallReturn != USBCAN_SUCCESSFUL)
269  {
270  MLOGST(ERR,this) << "UcanInitCanEx2, return code = [" << systecCallReturn << "]";
271  ::UcanDeinitCanEx(canModuleHandle, m_channelNumber);
272  return -1;
273  }
274  setCanHandle(m_moduleNumber, canModuleHandle);
275  m_UcanHandle = canModuleHandle;
276  return 0;
277 }
278 
279 bool STCanScan::sendErrorCode(long status)
280 {
281  char errorMessage[120];
282  timeval ftTimeStamp;
283  if (status != m_busStatus) {
284 
286 
287  if (!errorCodeToString(status, errorMessage))
288  canMessageError(status, errorMessage, ftTimeStamp);
289  m_busStatus = status;
290  }
291  return true;
292 }
293 
305 bool STCanScan::sendMessage(short cobID, unsigned char len, unsigned char *message, bool rtr)
306 {
307  MLOGST(DBG,this) << "Sending message: [" << ( message == 0 ? "" : (const char *) message) << "], cobID: [" << cobID << "], Message Length: [" << static_cast<int>(len) << "]";
308 
309  tCanMsgStruct canMsgToBeSent;
310  BYTE Status;
311 
312  canMsgToBeSent.m_dwID = cobID;
313  canMsgToBeSent.m_bDLC = len;
314  canMsgToBeSent.m_bFF = 0;
315  if (rtr)
316  {
317  canMsgToBeSent.m_bFF = USBCAN_MSG_FF_RTR;
318  }
319  int messageLengthToBeProcessed;
320  if (len > 8)//If there is more than 8 characters to process, we process 8 of them in this iteration of the loop
321  {
322  messageLengthToBeProcessed = 8;
323  MLOGST(DBG, this) << "The length is more then 8 bytes, adjust to 8, ignore >8. len= " << len;
324  }
325  else //Otherwise if there is less than 8 characters to process, we process all of them in this iteration of the loop
326  {
327  messageLengthToBeProcessed = len;
328  if (len < 8) {
329  MLOGST(DBG, this) << "The length is less then 8 bytes, process only. len= " << len;
330  }
331  }
332  canMsgToBeSent.m_bDLC = messageLengthToBeProcessed;
333  memcpy(canMsgToBeSent.m_bData, message, messageLengthToBeProcessed);
334  // MLOG(TRC,this) << "Channel Number: [" << m_channelNumber << "], cobID: [" << canMsgToBeSent.m_dwID << "], Message Length: [" << static_cast<int>(canMsgToBeSent.m_bDLC) << "]";
335  Status = UcanWriteCanMsgEx(m_UcanHandle, m_channelNumber, &canMsgToBeSent, NULL);
336  if (Status != USBCAN_SUCCESSFUL)
337  {
338  MLOGST(ERR,this) << "There was a problem when sending a message.";
339  }
340  else
341  {
342  m_statistics.onTransmit( canMsgToBeSent.m_bDLC );
343  }
344  return sendErrorCode(Status);
345 }
346 
347 bool STCanScan::sendRemoteRequest(short cobID)
348 {
349  tCanMsgStruct canMsg;
350  BYTE Status;
351  canMsg.m_dwID = cobID;
352  canMsg.m_bDLC = 0;
353  canMsg.m_bFF = USBCAN_MSG_FF_RTR; //Needed for send message rtr
354 
355  Status = UcanWriteCanMsgEx(m_UcanHandle, m_channelNumber, &canMsg, NULL);
356  return sendErrorCode(Status);
357 }
358 
359 bool STCanScan::errorCodeToString(long error, char message[])//TODO: Fix this method, this doesn't do anything!!
360 {
361  char tmp[300] = "Error";
362  // canGetErrorText((canStatus)error, tmp, sizeof(tmp));
363  // message = new char[strlen(tmp)+1];
364  message[0] = 0;
365  strcpy(message,tmp);
366  return true;
367 }
368 
370 {
372  result = m_statistics; // copy whole structure
374 }
375