MRPT  1.9.9
cmt2.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 /*! \file cmt2.cpp
11 
12  For information about objects in this file, see the appropriate header:
13  \ref Cmt2.h
14 
15  \section FileCopyright Copyright Notice
16  Copyright (C) Xsens Technologies B.V., 2006. All rights reserved.
17 
18  This source code is intended for use only by Xsens Technologies BV and
19  those that have explicit written permission to use it from
20  Xsens Technologies BV.
21 
22  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
23  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
24  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
25  PARTICULAR PURPOSE.
26 
27  \section FileChangelog Changelog
28  \par 2006-04-05, v0.0.1
29  \li Job Mulder: Created
30  \par 2006-07-21, v0.1.0
31  \li Job Mulder: Updated file for release 0.1.0
32 */
33 
34 #include "cmt2.h"
35 
36 namespace xsens
37 {
38 #ifdef _LOG_CMT2
39 #define CMT2LOG CMTLOG
40 #else
41 #define CMT2LOG(...)
42 #endif
43 
44 //////////////////////////////////////////////////////////////////////////////////////////
45 int32_t findValidMessage(const uint8_t* buffer, const uint16_t bufferLength)
46 {
47  MessageHeader* hdr = nullptr;
48  uint16_t pre = 0;
49  uint16_t target;
50  bool extended;
52  int32_t res;
53  Message* msg;
54 
55  // find the preamble
56  while (pre < bufferLength && (buffer[pre] != CMT_PREAMBLE)) ++pre;
57 
58  if (pre >= bufferLength) return -1;
59 
60  // check if the message is valid
61  length = bufferLength - pre;
62  if (length < CMT_LEN_MSGHEADERCS) return -1;
63 
64  // parse header
65 
66  hdr = (MessageHeader*)(buffer + pre);
67  if (hdr->m_length == CMT_EXTLENCODE)
68  {
69  extended = true;
70  if (length < CMT_LEN_MSGEXTHEADERCS) return -1;
71  }
72  else
73  extended = false;
74 
75  // check the reported size
76  target = extended
77  ? ((uint16_t)hdr->m_datlen.m_extended.m_length.m_high * 256 +
81  if (target <= length)
82  {
83  // header seems to be ok, check checksum
84  // check the checksum
85 
86  msg = new Message(buffer + pre, (uint16_t)target, (uint16_t)target);
87  if (msg->isChecksumOk())
88  {
89  delete msg;
90  return (int32_t)pre;
91  }
92  delete msg;
93  }
94 
95  // try next message
96  res = findValidMessage(buffer + pre + 1, length - 1);
97  if (res == -1) return -1;
98  return res + pre + 1;
99 }
100 
101 //////////////////////////////////////////////////////////////////////////////////////////
102 ///////////////////////////////////////// Cmt2s
103 ////////////////////////////////////////////
104 //////////////////////////////////////////////////////////////////////////////////////////
105 
106 //////////////////////////////////////////////////////////////////////////////////////////
107 // Default constructor, initializes all members to their default values.
109 {
111  m_readBufferCount = 0;
114  m_toEnd = 0;
115 }
116 
117 //////////////////////////////////////////////////////////////////////////////////////////
118 // Destructor, de-initializes, frees memory allocated for buffers, etc.
121 {
122  if (m_cmt1s.getPortNr())
123  {
124  CMT2LOG("L2: Closing port %d\n", (int32_t)m_cmt1s.getPortNr());
125  m_toEnd = 0;
126  return m_lastResult = m_cmt1s.close();
127  }
128  else
129  return m_lastResult = XRV_NOPORTOPEN;
130 }
131 
132 //////////////////////////////////////////////////////////////////////////////////////////
133 // Retrieve the port that the object is connected to.
135 {
136  m_cmt1s.getPortName(portname);
137  // we know there should be at least "/dev/x"
138  if (strlen(portname) < 6) return m_lastResult = XRV_ERROR;
139  return m_lastResult = XRV_OK;
140 }
141 
142 //////////////////////////////////////////////////////////////////////////////////////////
143 // Retrieve the port that the object is connected to.
145 {
146  port = m_cmt1s.getPortNr();
147  if (port == 0) return m_lastResult = XRV_ERROR;
148  return m_lastResult = XRV_OK;
149 }
150 
151 //////////////////////////////////////////////////////////////////////////////////////////
152 // Retrieve the port that the object is connected to.
154 {
155  port = m_cmt1s.getPortNr();
156  if (port == 0) return m_lastResult = XRV_ERROR;
157  return m_lastResult = XRV_OK;
158 }
159 
160 //////////////////////////////////////////////////////////////////////////////////////////
161 // Open a communication channel to the given serial port name.
162 XsensResultValue Cmt2s::open(const char* portName, const uint32_t baudRate)
163 {
164  CMT2LOG("L2: Opening port %s @baud %d\n", portName, baudRate);
165  m_baudrate = baudRate;
166  m_lastResult = m_cmt1s.open(portName, baudRate);
167  m_toEnd = 0;
168  CMT2LOG(
169  "L2: Port open result %d: %s\n", (int32_t)m_lastResult,
171  return m_lastResult;
172 }
173 
174 #ifdef _WIN32
175 //////////////////////////////////////////////////////////////////////////////////////////
176 // Open a communication channel to the given COM port number.
177 XsensResultValue Cmt2s::open(const uint32_t portNumber, const uint32_t baudRate)
178 {
179  CMT2LOG("L2: Opening port %d @baud %d\n", (int32_t)portNumber, baudRate);
180  m_baudrate = baudRate;
181  m_lastResult = m_cmt1s.open(portNumber, baudRate);
182  m_toEnd = 0;
183  CMT2LOG(
184  "L2: Port open result %d: %s\n", (int32_t)m_lastResult,
186  return m_lastResult;
187 }
188 #endif
189 
190 //////////////////////////////////////////////////////////////////////////////////////////
191 // Read a message from the COM port.
193 {
194  auto* hdr = (MessageHeader*)m_readBuffer;
195  uint16_t pre = 0;
196  uint32_t length = 0;
197  uint32_t target = 0;
198  uint16_t i;
199  bool extended = false;
200 
201  CMT2LOG("L2: readMessage started, bufferCount=%u\n", m_readBufferCount);
202 
203  if (m_readBufferCount == 0)
204  m_readBuffer[0] = (uint8_t)~CMT_PREAMBLE; // create a value that is
205  // definitely NOT a preamble
206 
210  &length);
212 
213  while (m_readBufferCount > 0)
214  {
215  while (m_readBufferCount > 0)
216  {
217  // find preamble
218  while ((pre < m_readBufferCount) &&
219  (m_readBuffer[pre] != CMT_PREAMBLE))
220  ++pre;
221 
222  if (pre == m_readBufferCount)
223  {
224  CMT2LOG("L2: readMessage no preamble found in buffer\n");
225  m_readBufferCount = 0;
226  return m_lastResult = XRV_TIMEOUT;
227  }
228 
229  CMT2LOG(
230  "L2: readMessage preamble found at position %u\n",
231  (uint32_t)pre);
232  // shift buffer to start
233  if (pre)
234  {
235  m_readBufferCount -= pre;
236  for (i = 0; i < m_readBufferCount; ++i)
237  m_readBuffer[i] = m_readBuffer[i + pre];
238  }
239 
241  {
242  CMT2LOG("L2: readMessage not enough header data read\n");
243  return m_lastResult = XRV_TIMEOUT;
244  }
245 
246  // read header
247  if (hdr->m_length == CMT_EXTLENCODE)
248  {
249  extended = true;
251  {
252  CMT2LOG(
253  "L2: readMessage not enough extended header data "
254  "read\n");
255  return m_lastResult = XRV_TIMEOUT;
256  }
257  }
258  else
259  extended = false;
260 
261  // check the reported size
262  target =
263  (extended
264  ? ((uint16_t)hdr->m_datlen.m_extended.m_length.m_high *
265  256 +
266  (uint16_t)hdr->m_datlen.m_extended.m_length.m_low)
267  : (uint16_t)(hdr->m_length));
268  CMT2LOG(
269  "L2: readMessage bytes in buffer=%u, extended=%u, target=%u\n",
270  (uint32_t)m_readBufferCount, (uint32_t)extended,
271  (uint32_t)target);
272  if ((uint32_t)target > (uint32_t)CMT_MAXDATALEN)
273  {
274  // skip current preamble
275  pre = 1;
276  CMT2LOG(
277  "L2: readMessage invalid message length %u\n",
278  (uint32_t)target);
279  continue;
280  }
281  break; // everything seems to be ok, get out of inner while() loop
282  }
283 
284  // header seems to be ok, read until end and check checksum
285  if (extended)
286  target += CMT_LEN_MSGEXTHEADERCS;
287  else
288  target += CMT_LEN_MSGHEADERCS;
289 
290  // read the entire message
291  if (m_readBufferCount < target)
292  {
293  CMT2LOG(
294  "L2: readMessage readBufferCount %u < target %u\n",
296  return m_lastResult = XRV_TIMEOUT;
297  }
298 
299  // check the checksum
300  if (rcv->loadFromString(m_readBuffer, (uint16_t)target) == XRV_OK)
301  {
302  CMT2LOG("L2: readMessage OK\n");
303  if (m_onMessageReceived != nullptr)
304  {
305  auto* bytes = (CmtBinaryData*)malloc(sizeof(CmtBinaryData));
306  bytes->m_size = target;
307  bytes->m_portNr = m_cmt1s.getPortNr();
308  // bytes->m_type = CMT_CALLBACK_ONMESSAGERECEIVED;
309  memcpy(bytes->m_data, m_readBuffer, target);
310 #ifdef _LOG_CALLBACKS
311  CMTLOG(
312  "C2: m_onMessageReceived(%d,(%d,%d),%p)\n",
314  (int32_t)bytes->m_size, (int32_t)bytes->m_portNr,
316 #endif
319  bytes, m_onMessageReceivedParam);
320  }
321 
322  m_readBufferCount -= (uint16_t)target;
323  if (m_readBufferCount)
324  for (i = 0; i < m_readBufferCount; ++i)
325  m_readBuffer[i] = m_readBuffer[i + target];
326 
327  return m_lastResult = XRV_OK;
328  }
329  CMT2LOG(
330  "L2: readMessage invalid checksum %02x %02x %02x %02x %02x\n",
331  rcv->getMessageStart()[0], rcv->getMessageStart()[1],
332  rcv->getMessageStart()[2], rcv->getMessageStart()[3],
333  rcv->getMessageStart()[4]);
334  // skip current preamble
335  pre = 1;
336  }
337 
338  CMT2LOG("L2: readMessage timed out\n");
339  // a timeout occurred
340  return m_lastResult = XRV_TIMEOUT;
341 }
342 
343 //////////////////////////////////////////////////////////////////////////////////////////
344 // Set the callback function for when a message has been received or sent
347  void* param)
348 {
349  switch (tp)
350  {
352  m_onMessageReceived = func;
353  m_onMessageReceivedInstance = instance;
355  return m_lastResult = XRV_OK;
357  m_onMessageSent = func;
358  m_onMessageSentInstance = instance;
360  return m_lastResult = XRV_OK;
361  default:
362  break;
363  }
365 }
366 
367 //////////////////////////////////////////////////////////////////////////////////////////
368 // Set the default timeout value to use in blocking operations.
370 {
371  CMT2LOG("L2: Setting timeout to %u ms\n", ms);
372  if ((m_lastResult = m_cmt1s.setTimeout(ms / 2)) != XRV_OK)
373  return m_lastResult; // this can't actually happen
374  m_timeout = ms;
375  m_toEnd = 0;
376  return (m_lastResult = XRV_OK);
377 }
378 
379 //////////////////////////////////////////////////////////////////////////////////////////
380 // Wait for a message to arrive.
382  Message* rcv, const uint8_t msgId, uint32_t timeoutOverride,
383  bool acceptErrorMessage)
384 {
385  auto* hdr = (MessageHeader*)m_readBuffer;
386  uint16_t pre = 0;
387  uint32_t length = 0;
388  uint32_t target;
389  uint16_t i;
390  bool extended;
391  bool readsome = (m_readBufferCount > 0);
392  uint32_t toRestore = m_toEnd;
393 
394  CMT2LOG(
395  "L2: waitForMessage x%02x, TO=%u, TOend=%u, TOO=%u\n", (uint32_t)msgId,
396  m_timeout, m_toEnd, timeoutOverride);
397 
398  // The end-time may be misinterpreted around midnight, where it may be
399  // considered
400  // expired even if this is not the case. However, this is extremely rare.
401  if (m_toEnd == 0)
402  {
403  if (timeoutOverride != 0)
404  m_toEnd = (getTimeOfDay() + (uint32_t)timeoutOverride) %
406  else
407  m_toEnd =
409  if (m_toEnd == 0) m_toEnd = 1;
410  }
411 
412  if (m_readBufferCount == 0)
413  m_readBuffer[0] = (uint8_t)~CMT_PREAMBLE; // create a value that is
414  // definitely NOT a preamble
415 
416  do
417  {
418  // find preamble
419  while (m_readBuffer[pre] != CMT_PREAMBLE)
420  {
421  if ((++pre) >= m_readBufferCount)
422  {
423  m_readBufferCount = 0;
424  pre = 0;
425  if (m_toEnd >= getTimeOfDay())
426  {
430  if (m_readBufferCount > 0) readsome = true;
431  }
432  }
433  if (m_toEnd < getTimeOfDay()) break;
434  }
435  // shift buffer to start
436  if (pre)
437  {
438  m_readBufferCount -= pre;
439  for (i = 0; i < m_readBufferCount; ++i)
440  {
441  m_readBuffer[i] = m_readBuffer[i + pre];
442  }
443  }
444 
445  pre = 1; // make sure we skip the first item in the next iteration
446  // read header
448  (m_toEnd >= getTimeOfDay()))
449  {
454  }
456  (m_toEnd < getTimeOfDay()))
457  {
458  CMT2LOG(
459  "L2: waitForMessage timeout occurred trying to read header\n");
460  break;
461  }
462 
463  if (hdr->m_length == CMT_EXTLENCODE)
464  {
465  extended = true;
467  (m_toEnd >= getTimeOfDay()))
468  {
473  }
475  (m_toEnd < getTimeOfDay()))
476  {
477  CMT2LOG(
478  "L2: waitForMessage timeout occurred trying to read "
479  "extended header\n");
480  break;
481  }
482  }
483  else
484  extended = false;
485 
486  // check the reported size
487  if (extended &&
488  (((uint16_t)hdr->m_datlen.m_extended.m_length.m_high * 256 +
489  (uint16_t)hdr->m_datlen.m_extended.m_length.m_low) >
491  continue;
492 
493  // header seems to be ok, read until end and check checksum
494  if (extended)
495  target = ((uint16_t)hdr->m_datlen.m_extended.m_length.m_high * 256 +
496  (uint16_t)hdr->m_datlen.m_extended.m_length.m_low) +
498  else
499  target = hdr->m_length + CMT_LEN_MSGHEADERCS;
500 
501  // read the entire message
502  while ((m_readBufferCount < target) && (m_toEnd >= getTimeOfDay()))
503  {
506  &length);
508  }
509  if ((m_readBufferCount < target) && (m_toEnd < getTimeOfDay()))
510  {
511  CMT2LOG("L2: waitForMessage timeout occurred\n");
512  break;
513  }
514 
515  // check the checksum
516  // msg=new Message(m_readBuffer,(uint16_t) target, (uint16_t) target);
517  if (rcv->loadFromString(m_readBuffer, (uint16_t)target) == XRV_OK)
518  {
519  CMT2LOG(
520  "L2: waitForMessage received msg Id x%02x while expecting "
521  "x%02x, msg size=%u\n",
522  (uint32_t)rcv->getMessageId(), (uint32_t)msgId, target);
523  if (m_onMessageReceived != nullptr)
524  {
525  auto* bytes = (CmtBinaryData*)malloc(sizeof(CmtBinaryData));
526  bytes->m_size = target;
527  bytes->m_portNr = m_cmt1s.getPortNr();
528  // bytes->m_type = CMT_CALLBACK_ONMESSAGERECEIVED;
529  memcpy(bytes->m_data, m_readBuffer, target);
530 #ifdef _LOG_CALLBACKS
531  CMTLOG(
532  "C2: m_onMessageReceived(%d,(%d,%d),%p)\n",
534  (int32_t)bytes->m_size, (int32_t)bytes->m_portNr,
536 #endif
539  bytes, m_onMessageReceivedParam);
540  }
541 
542  m_readBufferCount -= (uint16_t)target;
543  if (m_readBufferCount)
544  {
545  for (i = 0; i < m_readBufferCount; ++i)
546  {
547  m_readBuffer[i] = m_readBuffer[i + target];
548  }
549  }
550 
551  if ((msgId == 0) || (msgId == rcv->getMessageId()) ||
552  (acceptErrorMessage && rcv->getMessageId() == CMT_MID_ERROR))
553  {
554  m_toEnd = toRestore;
555  return m_lastResult = XRV_OK;
556  }
557  }
558  else
559  {
560  rcv->clear();
561  CMT2LOG("L2: waitForMessage load from string failed\n");
562  }
563  } while (m_toEnd >= getTimeOfDay());
564 
565  // a timeout occurred
566  if (readsome)
567  {
568  // check if the current data contains a valid message
570 
571  if (pos != -1)
572  {
573  CMT2LOG("L2: waitForMessage found message in message\n");
574  // shift data to start of buffer
575  pre = (uint16_t)pos;
576  m_readBufferCount -= pre;
577  for (i = 0; i < m_readBufferCount; ++i)
578  {
579  m_readBuffer[i] = m_readBuffer[i + pre];
580  }
582  rcv, msgId, 0, acceptErrorMessage); // parse the message
583  m_toEnd = toRestore;
584  return m_lastResult; // set by waitForMessage
585  }
586 
588  }
589  else
591  m_toEnd = toRestore;
592  return m_lastResult;
593 }
594 
595 //////////////////////////////////////////////////////////////////////////////////////////
596 // Send a message over the COM port.
598 {
599  CMT2LOG(
600  "L2: writeMessage %2x %2x %2x %2x %2x\n",
601  (int32_t)msg->getMessageStart()[0], (int32_t)msg->getMessageStart()[1],
602  (int32_t)msg->getMessageStart()[2], (int32_t)msg->getMessageStart()[3],
603  (int32_t)msg->getMessageStart()[4]);
604  uint32_t written = 0;
606  msg->getTotalMessageSize(), msg->getMessageStart(), &written);
607 
608  if (m_lastResult != XRV_OK)
609  {
610  CMT2LOG(
611  "L2: writeMessage returns %d: %s\n", (int32_t)m_lastResult,
613  return m_lastResult;
614  }
615 
616  if (written != msg->getTotalMessageSize())
617  {
618  CMT2LOG(
619  "L2: writeMessage wrote %u of %u bytes, returns %d: %s\n", written,
622  return (m_lastResult = XRV_ERROR);
623  }
624 
625  if (m_onMessageSent != nullptr)
626  {
627  auto* bytes = (CmtBinaryData*)malloc(sizeof(CmtBinaryData));
628  bytes->m_size = msg->getTotalMessageSize();
629  bytes->m_portNr = m_cmt1s.getPortNr();
630  memcpy(
631  bytes->m_data, msg->getMessageStart(), msg->getTotalMessageSize());
632 #ifdef _LOG_CALLBACKS
633  CMTLOG(
634  "C2: m_onMessageSent(%d,(%d,%d),%p)\n",
635  (int32_t)m_onMessageSentInstance, (int32_t)bytes->m_size,
636  (int32_t)bytes->m_portNr, m_onMessageSentParam);
637 #endif
641  }
642 
643  CMT2LOG("L2: writeMessage successful\n");
644  return (m_lastResult = XRV_OK);
645 }
646 
647 //////////////////////////////////////////////////////////////////////////////////////////
648 ///////////////////////////////////////// Cmt2f
649 ////////////////////////////////////////////
650 //////////////////////////////////////////////////////////////////////////////////////////
651 
652 //////////////////////////////////////////////////////////////////////////////////////////
653 // Default constructor
655 {
657  m_readOnly = true;
658 }
659 
660 //////////////////////////////////////////////////////////////////////////////////////////
661 // Destructor.
663 //////////////////////////////////////////////////////////////////////////////////////////
664 // Close the file.
666 {
667  if (!m_cmt1f.isOpen()) return m_lastResult = XRV_NOFILEOPEN;
668 
669  // save any unsaved data
670  // close the file
671  m_cmt1f.close();
672  m_readOnly = true;
673  return m_lastResult = XRV_OK;
674 }
675 
676 //////////////////////////////////////////////////////////////////////////////////////////
677 // Close the file and delete it.
679 {
680  if (!m_cmt1f.isOpen()) return m_lastResult = XRV_NOFILEOPEN;
681 
682  // close the file
684  m_readOnly = true;
685  return m_lastResult = XRV_OK;
686 }
687 
688 //////////////////////////////////////////////////////////////////////////////////////////
689 // Create a new file with level 2 header
690 XsensResultValue Cmt2f::create(const char* filename)
691 {
692  if (m_cmt1f.isOpen()) return m_lastResult = XRV_ALREADYOPEN;
693 
694  // create file
695  m_lastResult = m_cmt1f.create(filename);
696  if (m_lastResult != XRV_OK) return m_lastResult;
697 
698  m_readOnly = false;
699 
700  // check if we can actually write to the file
701  m_lastResult = m_cmt1f.writeData(5, "Xsens");
703  if (m_lastResult != XRV_OK) m_cmt1f.close();
704  return m_lastResult;
705 }
706 
707 //////////////////////////////////////////////////////////////////////////////////////////
708 // Create a new file with level 2 header
709 XsensResultValue Cmt2f::create(const wchar_t* filename)
710 {
711  if (m_cmt1f.isOpen()) return m_lastResult = XRV_ALREADYOPEN;
712 
713  // create file
714  m_lastResult = m_cmt1f.create(filename);
715  if (m_lastResult != XRV_OK) return m_lastResult;
716 
717  m_readOnly = false;
718 
719  // check if we can actually write to the file
720  m_lastResult = m_cmt1f.writeData(5, "Xsens");
722  if (m_lastResult != XRV_OK) m_cmt1f.close();
723  return m_lastResult;
724 }
725 
726 //////////////////////////////////////////////////////////////////////////////////////////
727 Cmt1f* Cmt2f::getCmt1f(void) { return &m_cmt1f; }
728 //////////////////////////////////////////////////////////////////////////////////////////
729 // Return the error code of the last operation.
731 //////////////////////////////////////////////////////////////////////////////////////////
732 // Retrieve the filename that was last successfully opened.
733 XsensResultValue Cmt2f::getName(char* filename) const
734 {
735  return m_lastResult = m_cmt1f.getName(filename);
736 }
737 
738 //////////////////////////////////////////////////////////////////////////////////////////
739 // Retrieve the filename that was last successfully opened.
740 XsensResultValue Cmt2f::getName(wchar_t* filename) const
741 {
742  return m_lastResult = m_cmt1f.getName(filename);
743 }
744 
745 //////////////////////////////////////////////////////////////////////////////////////////
746 // Return whether the file is open or not.
747 bool Cmt2f::isOpen(void) const { return m_cmt1f.isOpen(); }
748 //////////////////////////////////////////////////////////////////////////////////////////
749 // Open a file and read the header
750 XsensResultValue Cmt2f::open(const char* filename, const bool readOnly)
751 {
752  if (m_cmt1f.isOpen()) return m_lastResult = XRV_ALREADYOPEN;
753  m_lastResult = m_cmt1f.open(filename, !readOnly, readOnly);
754  m_readOnly = readOnly;
755  return m_lastResult;
756 }
757 
758 //////////////////////////////////////////////////////////////////////////////////////////
759 // Open a file and read the header
760 XsensResultValue Cmt2f::open(const wchar_t* filename, const bool readOnly)
761 {
762  if (m_cmt1f.isOpen()) return m_lastResult = XRV_ALREADYOPEN;
763  m_lastResult = m_cmt1f.open(filename, !readOnly, readOnly);
764  m_readOnly = readOnly;
765  return m_lastResult;
766 }
767 
768 //////////////////////////////////////////////////////////////////////////////////////////
769 // Read the next message from the file
771 {
772  CmtFilePos pos;
773  uint8_t needle = CMT_PREAMBLE;
775  uint32_t length, bcount;
776  auto* hdr = (MessageHeader*)buffer;
777  bool extended;
778  uint16_t target;
779 
780  while (m_lastResult == XRV_OK)
781  {
782  bcount = 0;
783 
784  // find a message preamble
785  m_lastResult = m_cmt1f.find(&needle, 1, pos);
786 
787  if (m_lastResult != XRV_OK) return m_lastResult;
788 
789  // read header
791  bcount += length;
792  if (m_lastResult != XRV_OK) return m_lastResult;
793 
794  if (hdr->m_length == CMT_EXTLENCODE)
795  {
796  extended = true;
798  CMT_LEN_MSGEXTHEADERCS - bcount, &buffer[bcount], &length);
799  bcount += length;
800  if (m_lastResult != XRV_OK)
801  {
802  m_cmt1f.setReadPos(pos + 1);
803  continue;
804  }
805  }
806  else
807  extended = false;
808 
809  // check the reported size
810  if (extended &&
811  (((uint16_t)hdr->m_datlen.m_extended.m_length.m_high * 256 +
812  (uint16_t)hdr->m_datlen.m_extended.m_length.m_low) >
814  {
815  m_cmt1f.setReadPos(pos + 1);
816  continue;
817  }
818 
819  // header seems to be ok, read until end and check checksum
820  if (extended)
821  target = ((uint16_t)hdr->m_datlen.m_extended.m_length.m_high * 256 +
822  (uint16_t)hdr->m_datlen.m_extended.m_length.m_low) +
824  else
825  target = hdr->m_length + CMT_LEN_MSGHEADERCS;
826 
827  // read the entire message
828  m_lastResult =
829  m_cmt1f.readData(target - bcount, &buffer[bcount], &length);
830  bcount += length;
831  if (m_lastResult != XRV_OK)
832  {
833  m_cmt1f.setReadPos(pos + 1);
834  continue;
835  }
836 
837  // check the checksum
838  // msg=new Message(m_readBuffer,(uint16_t) target, (uint16_t) target);
839  if (msg->loadFromString(buffer, (uint16_t)target) == XRV_OK)
840  {
841  if ((msgId == 0) || (msgId == msg->getMessageId()))
842  return m_lastResult = XRV_OK;
843  pos += target - 1;
844  }
845  msg->clear();
846  m_cmt1f.setReadPos(pos + 1);
847  }
848  return m_lastResult;
849 }
850 
851 //////////////////////////////////////////////////////////////////////////////////////////
852 // Get the current file size
854 //////////////////////////////////////////////////////////////////////////////////////////
855 // Get the current read position of the file
857 //////////////////////////////////////////////////////////////////////////////////////////
858 // Set the read position to the given position
860 {
861  return m_lastResult = m_cmt1f.setReadPos(pos);
862 }
863 
864 //////////////////////////////////////////////////////////////////////////////////////////
865 // Write a message to the end of the file
867 {
868  if (m_readOnly) return m_lastResult = XRV_READONLY;
870  msg->getTotalMessageSize(), msg->getMessageStart());
871 }
872 
873 } // namespace xsens
Operation was performed successfully.
Definition: xsens_std.h:35
A message header.
Definition: cmtmessage.h:36
__int64 CmtFilePos
Definition: cmtf.h:25
unsigned __int16 uint16_t
Definition: rptypes.h:47
XsensResultValue appendData(const uint32_t length, const void *data)
Write data to the end of the file.
Definition: cmt1.cpp:694
#define CMT_MAXDATALEN
Definition: cmtdef.h:75
void getPortName(char *portname) const
Retrieve the port name that was last successfully opened.
Definition: cmt1.h:145
XsensResultValue setReadPos(const CmtFilePos pos)
Set the new absolute read position.
Definition: cmt1.cpp:1272
XsensResultValue open(const char *filename, const bool readOnly=false)
Open a file and read the header.
Definition: cmt2.cpp:750
XsensResultValue writeData(const uint32_t length, const uint8_t *data, uint32_t *written)
Write the data to the serial port.
Definition: cmt1.cpp:633
XsensResultValue getName(char *filename) const
Retrieve the filename that was last successfully opened.
Definition: cmt1.cpp:1010
#define XSENS_MS_PER_DAY
The number of milliseconds in a normal day.
Definition: xsens_time.h:21
CmtCallbackFunction m_onMessageReceived
The message received function.
Definition: cmt2.h:53
GLuint buffer
Definition: glext.h:3928
XsensResultValue getPortNr(uint8_t &port) const
Retrieve the port that the object is connected to.
Definition: cmt2.cpp:144
~Cmt2f()
Destructor.
Definition: cmt2.cpp:662
XsensResultValue setCallbackFunction(CmtCallbackSelector tp, int32_t instance, CmtCallbackFunction func, void *param)
Set the callback function for when a message has been received or sent.
Definition: cmt2.cpp:345
bool isOpen(void) const
Return whether the file is open or not.
Definition: cmt1.h:363
#define CMTLOG(...)
Definition: cmt1.h:41
#define CMT_DEFAULT_BAUD_RATE
The default baud rate of the Cmt1s serial communication.
Definition: cmtdef.h:798
CmtFilePos getReadPos(void) const
Return the current read position.
Definition: cmt1.h:350
XsensResultValue readData(const uint32_t maxLength, void *data, uint32_t *length)
Read data from the file and put it into the data buffer.
Definition: cmt1.cpp:1220
XsensResultValue writeData(const uint32_t length, const void *data)
Write data to the file.
Definition: cmt1.cpp:1312
XsensResultValue closeAndDelete(void)
Close the file and delete it.
Definition: cmt1.cpp:737
#define CMT_MAXMSGLEN
Definition: cmtdef.h:77
void clear(void)
Clear all data in the message.
Definition: cmtmessage.cpp:147
Callback function, called when a full message has been received from a port.
Definition: cmtdef.h:1140
XsensResultValue deleteData(const CmtFilePos start, const uint32_t length)
Delete the given data from the file. The function erases the given data from the file at the given wr...
Definition: cmt1.cpp:867
CmtCallbackFunction m_onMessageSent
The message sent function.
Definition: cmt2.h:67
XsensResultValue getName(char *filename) const
Retrieve the filename that was last successfully opened.
Definition: cmt2.cpp:733
uint32_t m_toEnd
The timestamp at which to end an operation.
Definition: cmt2.h:90
XsensResultValue readData(const uint32_t maxLength, uint8_t *data, uint32_t *length=nullptr)
Read data from the serial port and put it into the data buffer.
Definition: cmt1.cpp:485
#define CMT2_DEFAULT_TIMEOUT
Timeout in ms for level 2.
Definition: cmtdef.h:807
Cmt1s m_cmt1s
The CMT level 1 object that this class operates on.
Definition: cmt2.h:79
XsensResultValue getPortName(char *portname) const
Definition: cmt2.cpp:134
unsigned char uint8_t
Definition: rptypes.h:44
XsensResultValue open(const char *filename, const bool create, const bool readOnly)
Open a file.
Definition: cmt1.cpp:1116
Callback function, called when a full message has been sent by a port.
Definition: cmtdef.h:1142
int32_t m_onMessageReceivedInstance
Custom, user supplied parameter for the OnMessageReceived callback function, passed as the first argu...
Definition: cmt2.h:56
XsensResultValue setTimeout(const uint32_t ms=CMT1_DEFAULT_TIMEOUT)
Set the default timeout value to use in blocking operations.
Definition: cmt1.cpp:561
void * m_onMessageSentParam
Custom, user supplied parameter for the OnMessageSent callback function, passed as the last argument...
Definition: cmt2.h:73
int32_t m_onMessageSentInstance
Custom, user supplied parameter for the OnMessageSent callback function, passed as the first argument...
Definition: cmt2.h:70
XsensResultValue close(void)
Close the file.
Definition: cmt2.cpp:665
XsensResultValue
Xsens return values.
Definition: xsens_std.h:31
XsensResultValue closeAndDelete(void)
Close the file and delete it.
Definition: cmt2.cpp:678
XsensResultValue(__cdecl * CmtCallbackFunction)(int32_t, CmtCallbackSelector, void *, void *)
Definition: cmtdef.h:1160
CmtFilePos getReadPosition(void)
Get the current read position.
Definition: cmt2.cpp:856
#define CMT2LOG(...)
Definition: cmt2.cpp:41
XsensResultValue find(const void *needle, const uint32_t needleLength, CmtFilePos &pos)
Find a string of bytes in the file.
Definition: cmt1.cpp:941
XsensResultValue open(const char *portName, const uint32_t baudRate=CMT_DEFAULT_BAUD_RATE, uint32_t readBufSize=CMT_DEFAULT_READ_BUFFER_SIZE, uint32_t writeBufSize=CMT_DEFAULT_WRITE_BUFFER_SIZE)
Open a communcation channel to the given serial port name.
Definition: cmt1.cpp:322
#define CMT_MID_ERROR
Definition: cmtdef.h:474
Cmt2s()
Default constructor, initialize all members to their default values.
Definition: cmt2.cpp:108
#define CMT_LEN_MSGEXTHEADERCS
Definition: cmtdef.h:68
XsensResultValue open(const char *portName, const uint32_t baudRate=CMT_DEFAULT_BAUD_RATE)
Open a communication channel to the given serial port name.
Definition: cmt2.cpp:162
XsensResultValue waitForMessage(Message *rcv, const uint8_t msgId, uint32_t timeoutOverride, bool acceptErrorMessage)
Wait for a message to arrive.
Definition: cmt2.cpp:381
uint16_t m_readBufferCount
The number of valid bytes in the readBuffer.
Definition: cmt2.h:86
uint8_t m_readBuffer[CMT_DEFAULT_READ_BUFFER_SIZE]
Buffer for reading data until a valid message is read.
Definition: cmt2.h:84
XsensResultValue loadFromString(const uint8_t *source, const uint16_t size)
Read the entire message from the given source string.
Definition: cmtmessage.cpp:398
XsensResultValue close(void)
Close the file.
Definition: cmt1.cpp:713
#define CMT_PREAMBLE
Definition: cmtdef.h:60
void * m_onMessageReceivedParam
Custom, user supplied parameter for the OnMessageReceived callback function, passed as the last argum...
Definition: cmt2.h:59
#define CMT_EXTLENCODE
Definition: cmtdef.h:63
int32_t findValidMessage(const uint8_t *buffer, const uint16_t bufferLength)
Find a valid message in the given buffer.
Definition: cmt2.cpp:45
CmtFilePos getFileSize(void)
Get the current file size.
Definition: cmt2.cpp:853
XsensResultValue setReadPosition(CmtFilePos pos)
Set the read position to the given position.
Definition: cmt2.cpp:859
__int32 int32_t
Definition: rptypes.h:49
struct xsens::MessageHeader::_mdl::_mextd m_extended
uint8_t getMessageId(void) const
Return the current value of the m_messageId field.
Definition: cmtmessage.h:236
XsensResultValue close(void)
Close the serial communication port.
Definition: cmt2.cpp:120
Cmt1f * getCmt1f(void)
Get a reference to the embedded Cmt1f object.
Definition: cmt2.cpp:727
const uint8_t * getMessageStart(void) const
Return the start of the message buffer.
Definition: cmtmessage.h:241
XsensResultValue getLastResult(void) const
Return the error code of the last operation.
Definition: cmt2.cpp:730
uint8_t getPortNr(void) const
Retrieve the port number that was last successfully opened.
Definition: cmt1.h:143
XsensResultValue setTimeout(const uint32_t ms=CMT2_DEFAULT_TIMEOUT)
Set the default timeout value to use in blocking operations.
Definition: cmt2.cpp:369
~Cmt2s()
Destructor, de-initialize, free memory allocated for buffers, etc.
Definition: cmt2.cpp:119
CmtFilePos getFileSize(void) const
Return the size of the file.
Definition: cmt1.h:329
XsensResultValue writeMessage(Message *msg)
Send a message over the COM port.
Definition: cmt2.cpp:597
#define CMT_LEN_MSGHEADERCS
Definition: cmtdef.h:67
XsensResultValue m_lastResult
The last result of an operation.
Definition: cmt2.h:203
XsensResultValue create(const char *filename)
Create a new file with level 2 header.
Definition: cmt2.cpp:690
GLuint GLsizei GLsizei * length
Definition: glext.h:4079
const char * xsensResultText(const XsensResultValue result)
Definition: xsens_std.cpp:13
The low-level file communication class.
Definition: cmt1.h:240
XsensResultValue readMessage(Message *msg, const uint8_t msgId=0)
Read the next message from the file, when msgId is non-zero, the first matching message will be retur...
Definition: cmt2.cpp:770
bool isOpen(void) const
Return whether the file is open or not.
Definition: cmt2.cpp:747
CmtCallbackSelector
Definition: cmtdef.h:1120
The namespace of all Xsens software since 2006.
Definition: cmt1.cpp:95
Cmt2f()
Default constructor.
Definition: cmt2.cpp:654
XsensResultValue create(const char *filename)
Open an empty file.
Definition: cmt1.cpp:789
XsensResultValue close(void)
Close the serial communication port.
Definition: cmt1.cpp:205
#define CMT_LEN_MSGHEADER
Definition: cmtdef.h:65
Cmt1f m_cmt1f
The Cmt1f object that is used for the low-level operations.
Definition: cmt2.h:201
GLuint res
Definition: glext.h:7385
struct xsens::MessageHeader::_mdl::_mextd::_mlen m_length
uint16_t getTotalMessageSize(void) const
Return the length of the message buffer.
Definition: cmtmessage.cpp:378
XsensResultValue writeMessage(const Message *msg)
Write a message to the end of the file.
Definition: cmt2.cpp:866
unsigned __int32 uint32_t
Definition: rptypes.h:50
bool isChecksumOk(void) const
Compute the checksum and compare it with the stored checksum.
Definition: cmtmessage.cpp:390
GLfloat param
Definition: glext.h:3838
uint32_t m_baudrate
The baudrate that was last set to be used by the port.
Definition: cmt2.h:77
uint32_t getTimeOfDay(tm *date_, time_t *secs_)
A platform-independent clock.
Definition: xsens_time.cpp:34
uint32_t m_timeout
Timeout in ms for blocking operations.
Definition: cmt2.h:88
bool m_readOnly
When set to true, the file is read-only and attempts to write to it will fail.
Definition: cmt2.h:207
Class for storing a single message.
Definition: cmtmessage.h:83
union xsens::MessageHeader::_mdl m_datlen
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
Definition: os.cpp:358
XsensResultValue readMessage(Message *rcv)
Read a message from the COM port.
Definition: cmt2.cpp:192
XsensResultValue m_lastResult
The last result of an operation.
Definition: cmt2.h:81



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 8fe78517f Sun Jul 14 19:43:28 2019 +0200 at lun oct 28 02:10:00 CET 2019