Message.cpp
Go to the documentation of this file.
1 
47 #include <unistd.h>
48 #include <iostream>
49 #include <string.h>
55 
56 // Conditions on the below to handle compiling for nonstandard hardware
57 #ifdef LOGGING_AVAIL
59 #endif
60 
61 using namespace std;
62 
63 namespace clearpath
64 {
65 
66  MessageException::MessageException(const char *msg, enum errors ex_type)
67  : Exception(msg), type(ex_type)
68  {
69 #ifdef LOGGING_AVAIL
70  CPR_EXCEPT() << "MessageException "<<type<<": "<< message << endl << flush;
71 #endif
72  }
73 
75  is_sent(false)
76  {
78  memset(data, 0, MAX_MSG_LENGTH);
79  }
80 
81  Message::Message(void *input, size_t msg_len) :
82  is_sent(false)
83  {
84  total_len = msg_len;
85  memset(data, 0, MAX_MSG_LENGTH);
86  memcpy(data, input, msg_len);
87  }
88 
89  Message::Message(const Message &other) :
90  is_sent(false)
91  {
92  total_len = other.total_len;
93  memset(data, 0, MAX_MSG_LENGTH);
94  memcpy(data, other.data, total_len);
95  }
96 
97  Message::Message(uint16_t type, uint8_t *payload, size_t payload_len,
98  uint32_t timestamp, uint8_t flags, uint8_t version) :
99  is_sent(false)
100  {
101  /* Copy in data */
102  total_len = HEADER_LENGTH + payload_len + CRC_LENGTH;
104  {
105  /* If payload is too long, the only recourse we have in constructor
106  * (other than an abort()) is to truncate silently. */
108  payload_len = MAX_MSG_LENGTH - HEADER_LENGTH - CRC_LENGTH;
109  }
110  memset(data, 0, MAX_MSG_LENGTH);
111  memcpy(data + PAYLOAD_OFST, payload, payload_len);
112 
113  /* Fill header */
114  data[SOH_OFST] = SOH;
115  setLength(total_len - 3);
116  setType(type);
117  setTimestamp(timestamp);
118  setFlags(flags);
119  setVersion(version);
120  data[STX_OFST] = STX;
121 
122  /* Generate checksum */
123  uint16_t checksum = crc16(crcOffset(), CRC_INIT_VAL, data);
124  utob(data + crcOffset(), 2, checksum);
125  }
126 
128  {
129  // nothing to do, actually.
130  }
131 
133  {
134  // We will retry up to 3 times if we receive CRC errors
135  for (int i = 0; i < 2; ++i)
136  {
137  try
138  {
139  Transport::instance().send(this);
140  return;
141  }
142  catch (BadAckException *ex)
143  {
144  // Any bad ack other than bad checksum needs to
145  // be thrown on
147  {
148  throw ex;
149  }
150  }
151  }
152 
153  /* Make the final attempt outside the try, so any exception
154  * just goes straight through */
155 #ifdef LOGGING_AVAIL
156  CPR_WARN() << "Bad checksum twice in a row." << endl;
157 #endif
158  Transport::instance().send(this);
159  }
160 
167  size_t Message::getPayload(void *buf, size_t buf_size)
168  {
169  // If we don't have enough space in the buffer, don't even try
170  if (getPayloadLength() > buf_size) { return 0; }
171 
172  memcpy(buf, data + PAYLOAD_OFST, getPayloadLength());
173  return getPayloadLength();
174  }
175 
181  uint8_t *Message::getPayloadPointer(size_t offset)
182  {
183  return data + PAYLOAD_OFST + offset;
184  }
185 
187  {
188  return data[LENGTH_OFST];
189  }
190 
192  {
193  return data[LENGTH_COMP_OFST];
194  }
195 
197  {
198  return data[VERSION_OFST];
199  }
200 
202  {
203  return btou(data + TIMESTAMP_OFST, 4);
204  }
205 
207  {
208  return data[FLAGS_OFST];
209  }
210 
211  uint16_t Message::getType()
212  {
213  return btou(data + TYPE_OFST, 2);
214  }
215 
217  {
218  return btou(data + crcOffset(), 2);
219  }
220 
221  void Message::setLength(uint8_t len)
222  {
223  size_t new_total_len = len + 3;
224  if (new_total_len > MAX_MSG_LENGTH) { return; }
225  total_len = new_total_len;
226  data[LENGTH_OFST] = len;
227  data[LENGTH_COMP_OFST] = ~len;
228  }
229 
230  void Message::setVersion(uint8_t version)
231  {
232  data[VERSION_OFST] = version;
233  }
234 
235  void Message::setTimestamp(uint32_t timestamp)
236  {
237  utob(data + TIMESTAMP_OFST, 4, timestamp);
238  }
239 
240  void Message::setFlags(uint8_t flags)
241  {
242  data[FLAGS_OFST] = flags;
243  }
244 
245  void Message::setType(uint16_t type)
246  {
247  utob(data + TYPE_OFST, 2, type);
248  }
249 
256  void Message::setPayloadLength(uint8_t len)
257  {
258 
259  if (((size_t) (len) + HEADER_LENGTH + CRC_LENGTH) > MAX_MSG_LENGTH) { return; }
261  }
262 
270  void Message::setPayload(void *buf, size_t buf_size)
271  {
272  if ((buf_size + HEADER_LENGTH + CRC_LENGTH) > MAX_MSG_LENGTH) { return; }
273  setPayloadLength(buf_size);
274  if (buf_size > getPayloadLength()) { return; }
275  memcpy(data + PAYLOAD_OFST, buf, buf_size);
276  }
277 
284  size_t Message::toBytes(void *buf, size_t buf_size)
285  {
286  // If we don't have enough space in the buffer, don't even try
287  if (total_len > buf_size)
288  {
289  return 0;
290  }
291  memcpy(buf, data, total_len);
292  return total_len;
293  }
294 
302  bool Message::isValid(char *whyNot, size_t strLen)
303  {
304  // Check SOH
305  if (data[SOH_OFST] != SOH)
306  {
307  if (whyNot) { strncpy(whyNot, "SOH is not present.", strLen); }
308  return false;
309  }
310  // Check STX
311  if (data[STX_OFST] != STX)
312  {
313  if (whyNot) { strncpy(whyNot, "STX is not present.", strLen); }
314  return false;
315  }
316  // Check length matches complement
317  if (getLength() != ((~getLengthComp()) & 0xff))
318  {
319  if (whyNot) { strncpy(whyNot, "Length does not match complement.", strLen); }
320  return false;
321  }
322  // Check length is correct
323  if (getLength() != (total_len - 3))
324  {
325  if (whyNot) { strncpy(whyNot, "Length is wrong.", strLen); }
326  return false;
327  }
328  // Check the CRC
329  if (crc16(crcOffset(), CRC_INIT_VAL, this->data) != getChecksum())
330  {
331  if (whyNot) { strncpy(whyNot, "CRC is wrong.", strLen); }
332  return false;
333  }
334  return true;
335  }
336 
341  {
342  data[SOH_OFST] = SOH;
343  data[STX_OFST] = STX;
344  data[LENGTH_OFST] = total_len - 3;
346  uint16_t checksum = crc16(crcOffset(), CRC_INIT_VAL, data);
347  utob(data + crcOffset(), 2, checksum);
348  }
349 
350  std::ostream &Message::printMessage(std::ostream &stream)
351  {
352  stream << "Message" << endl;
353  stream << "=======" << endl;
354  stream << "Length : " << (int) (getLength()) << endl;
355  stream << "~Length : " << (int) (getLengthComp()) << endl;
356  stream << "Version : " << (int) (getVersion()) << endl;
357  stream << "Flags : " << hex << (int) (getFlags()) << endl;
358  stream << "Timestamp: " << dec << getTimestamp() << endl;
359  stream << "Type : " << hex << (int) (getType()) << endl;
360  stream << "Checksum : " << hex << (int) (getChecksum()) << endl;
361  stream << dec;
362  stream << "Raw : ";
363  printRaw(stream);
364  return stream;
365  }
366 
367  void Message::printRaw(std::ostream &stream)
368  {
369  stream << hex << uppercase;
370  for (unsigned int i = 0; i < total_len; i++)
371  {
372  stream << static_cast<short>(data[i]) << " ";
373  }
374  stream << dec;
375  stream << endl;
376  }
377 
385  Message *Message::factory(void *input, size_t msg_len)
386  {
387  uint16_t type = btou((char *) input + TYPE_OFST, 2);
388 
389  switch (type)
390  {
391  case DATA_ACCEL:
392  return new DataPlatformAcceleration(input, msg_len);
393 
394  case DATA_ACCEL_RAW:
395  return new DataRawAcceleration(input, msg_len);
396 
398  return new DataAckermannOutput(input, msg_len);
399 
400  case DATA_CURRENT_RAW:
401  return new DataRawCurrent(input, msg_len);
402 
403  case DATA_PLATFORM_NAME:
404  return new DataPlatformName(input, msg_len);
405 
407  return new DataDifferentialControl(input, msg_len);
408 
410  return new DataDifferentialSpeed(input, msg_len);
411 
413  return new DataDifferentialOutput(input, msg_len);
414 
415  case DATA_DISTANCE_DATA:
416  return new DataRangefinders(input, msg_len);
417 
419  return new DataRangefinderTimings(input, msg_len);
420 
421  case DATA_ECHO:
422  return new DataEcho(input, msg_len);
423 
424  case DATA_ENCODER:
425  return new DataEncoders(input, msg_len);
426 
427  case DATA_ENCODER_RAW:
428  return new DataEncodersRaw(input, msg_len);
429 
430  case DATA_FIRMWARE_INFO:
431  return new DataFirmwareInfo(input, msg_len);
432 
433  case DATA_GYRO_RAW:
434  return new DataRawGyro(input, msg_len);
435 
436  case DATA_MAGNETOMETER:
437  return new DataPlatformMagnetometer(input, msg_len);
438 
440  return new DataRawMagnetometer(input, msg_len);
441 
442  case DATA_MAX_ACCEL:
443  return new DataMaxAcceleration(input, msg_len);
444 
445  case DATA_MAX_SPEED:
446  return new DataMaxSpeed(input, msg_len);
447 
448  case DATA_ORIENT:
449  return new DataPlatformOrientation(input, msg_len);
450 
451  case DATA_ORIENT_RAW:
452  return new DataRawOrientation(input, msg_len);
453 
454  case DATA_PLATFORM_INFO:
455  return new DataPlatformInfo(input, msg_len);
456 
457  case DATA_POWER_SYSTEM:
458  return new DataPowerSystem(input, msg_len);
459 
460  case DATA_PROC_STATUS:
461  return new DataProcessorStatus(input, msg_len);
462 
463  case DATA_ROT_RATE:
464  return new DataPlatformRotation(input, msg_len);
465 
466  case DATA_SAFETY_SYSTEM:
467  return new DataSafetySystemStatus(input, msg_len);
468 
469  case DATA_SYSTEM_STATUS:
470  return new DataSystemStatus(input, msg_len);
471 
473  return new DataRawTemperature(input, msg_len);
474 
475  case DATA_VELOCITY_SETPT:
476  return new DataVelocity(input, msg_len);
477 
478  case DATA_VOLTAGE_RAW:
479  return new DataRawVoltage(input, msg_len);
480 
481  default:
482  return new Message(input, msg_len);
483  } // switch getType()
484  } // factory()
485 
487  {
488  return Transport::instance().popNext();
489  }
490 
491  Message *Message::waitNext(double timeout)
492  {
493  return Transport::instance().waitNext(timeout);
494  }
495 
496 }; // namespace clearpath
497 
498 std::ostream &operator<<(std::ostream &stream, clearpath::Message &msg)
499 {
500  return msg.printMessage(stream);
501 }
502 
void setFlags(uint8_t flags)
Definition: Message.cpp:240
uint8_t data[MAX_MSG_LENGTH]
Definition: Message.h:101
void utob(void *dest, size_t dest_len, uint64_t src)
Definition: Number.cpp:56
enum clearpath::BadAckException::ackFlags ack_flag
static Transport & instance()
Definition: Transport.cpp:129
static Message * waitNext(double timeout=0.0)
Definition: Message.cpp:491
static Message * factory(void *input, size_t msg_len)
Definition: Message.cpp:385
uint8_t getLengthComp()
Definition: Message.cpp:191
uint8_t getFlags()
Definition: Message.cpp:206
uint64_t btou(void *src, size_t src_len)
Definition: Number.cpp:121
void setType(uint16_t type)
Definition: Message.cpp:245
#define CPR_EXCEPT()
Definition: Logger.h:106
uint8_t getLength()
Definition: Message.cpp:186
size_t toBytes(void *buf, size_t buf_size)
Definition: Message.cpp:284
size_t crcOffset()
Definition: Message.h:117
size_t getPayload(void *buf, size_t max_size)
Definition: Message.cpp:167
size_t total_len
Definition: Message.h:103
virtual std::ostream & printMessage(std::ostream &stream=std::cout)
Definition: Message.cpp:350
uint16_t getChecksum()
Definition: Message.cpp:216
Message * waitNext(double timeout=0.0)
Definition: Transport.cpp:525
const char * message
Definition: Exception.h:58
void setTimestamp(uint32_t timestamp)
Definition: Message.cpp:235
static Message * popNext()
Definition: Message.cpp:486
std::ostream & operator<<(std::ostream &stream, clearpath::Message &msg)
Definition: Message.cpp:498
uint8_t * getPayloadPointer(size_t offset=0)
Definition: Message.cpp:181
void send(Message *m)
Definition: Transport.cpp:406
static const size_t CRC_LENGTH
Definition: Message.h:82
void setPayload(void *buf, size_t buf_size)
Definition: Message.cpp:270
void printRaw(std::ostream &stream=std::cout)
Definition: Message.cpp:367
static const uint8_t STX
Definition: Message.h:114
static const uint16_t CRC_INIT_VAL
Definition: Message.h:83
uint16_t crc16(int size, int init_val, uint8_t *data)
Definition: crc.cpp:80
void setVersion(uint8_t version)
Definition: Message.cpp:230
void setLength(uint8_t len)
Definition: Message.cpp:221
static const size_t MAX_MSG_LENGTH
Definition: Message.h:78
uint16_t getType()
Definition: Message.cpp:211
Message * popNext()
Definition: Transport.cpp:476
static const uint8_t SOH
Definition: Message.h:113
uint8_t getVersion()
Definition: Message.cpp:196
void setPayloadLength(uint8_t len)
Definition: Message.cpp:256
virtual ~Message()
Definition: Message.cpp:127
bool isValid(char *whyNot=NULL, size_t strLen=0)
Definition: Message.cpp:302
#define CPR_WARN()
Definition: Logger.h:107
size_t getPayloadLength()
Definition: Message.h:167
static const size_t HEADER_LENGTH
Definition: Message.h:85
uint32_t getTimestamp()
Definition: Message.cpp:201


husky_base
Author(s): Mike Purvis , Paul Bovbel
autogenerated on Fri Oct 2 2020 03:40:07