Message.cpp
Go to the documentation of this file.
1 
47 #include <unistd.h>
48 #include <iostream>
49 #include <string.h>
50 #include "roch_base/core/crc.h"
51 #include "roch_base/core/Message.h"
53 #include "roch_base/core/Number.h"
55 #include <stdio.h>
56 #ifdef DEBUG_INFO
58 #endif
59 // Conditions on the below to handle compiling for nonstandard hardware
60 #ifdef LOGGING_AVAIL
61 #include "roch_base/core/Logger.h"
62 #endif
63 
64 using namespace std;
65 
66 namespace sawyer
67 {
68 
69  MessageException::MessageException(const char *msg, enum errors ex_type)
70  : Exception(msg), type(ex_type)
71  {
72 #ifdef LOGGING_AVAIL
73  CPR_EXCEPT() << "MessageException "<<type<<": "<< message << endl << flush;
74 #endif
75  }
76 
78  is_sent(false)
79  {
81  memset(data, 0, MAX_MSG_LENGTH);
82  }
83 
84  Message::Message(void *input, size_t msg_len) :
85  is_sent(false)
86  {
87  total_len = msg_len;
88  memset(data, 0, MAX_MSG_LENGTH);
89  memcpy(data, input, msg_len);
90 
91  }
92 
93  Message::Message(const Message &other) :
94  is_sent(false)
95  {
96  total_len = other.total_len;
97  memset(data, 0, MAX_MSG_LENGTH);
98  memcpy(data, other.data, total_len);
99  }
100 
101 Message::Message(uint16_t type, uint8_t *payload, size_t payload_len,
102  uint32_t timestamp, uint8_t flags, uint8_t version) :
103  is_sent(false)
104  {
105  /* Copy in data */
106  total_len = HEADER_LENGTH + payload_len + CRC_LENGTH;
108  {
109  /* If payload is too long, the only recourse we have in constructor
110  * (other than an abort()) is to truncate silently. */
112  payload_len = (MAX_MSG_LENGTH - HEADER_LENGTH - CRC_LENGTH);
113  }
114  memset(data, 0, MAX_MSG_LENGTH);
115  memcpy(data + PAYLOAD_OFST, payload, payload_len);
116 
117  /* Fill header */
118  data[SOH_OFST] = SOH;
119  setLength(total_len - 3);
120  setType(type);
121  setFlags(flags);
122  setVersion(version);
123  data[STX_OFST] = STX;
124 
125  /* Generate checksum */
126  uint16_t checksum = crc16(crcOffset(), CRC_INIT_VAL, data);
127  utob(data + crcOffset(), 2, checksum);
128 
129  }
130 
132  {
133  // nothing to do, actually.
134  }
135 
137  {
138 
139  // We will retry up to 3 times if we receive CRC errors
140  for (int i = 0; i < 2; ++i)
141  {
142  try
143  {
144 
145  Transport::instance().send(this);
146  return;
147  }
148  catch (BadAckException *ex)
149  {
150  // Any bad ack other than bad checksum needs to
151  // be thrown on
153  {
154  throw ex;
155  }
156  }
157  }
158 
159  /* Make the final attempt outside the try, so any exception
160  * just goes straight through */
161 #ifdef LOGGING_AVAIL
162  CPR_WARN() << "Bad checksum twice in a row." << endl;
163 #endif
164  Transport::instance().send(this);
165  }
166 
167 
169  {
170  Message * getMessage=NULL;
171  // We will retry up to 3 times if we receive CRC errors
172  for (int i = 0; i < 2; ++i)
173  {
174  try
175  {
176 
177  getMessage = Transport::instance().sendRequest(this);
178  return getMessage;
179  }
180  catch (BadAckException *ex)
181  {
182  // Any bad ack other than bad checksum needs to
183  // be thrown on
185  {
186  throw ex;
187  }
188  }
189  }
190 
191  /* Make the final attempt outside the try, so any exception
192  * just goes straight through */
193 #ifdef LOGGING_AVAIL
194  CPR_WARN() << "Bad checksum twice in a row." << endl;
195 #endif
197  }
204  size_t Message::getPayload(void *buf, size_t buf_size)
205  {
206  // If we don't have enough space in the buffer, don't even try
207  if (getPayloadLength() > buf_size) { return 0; }
208 
209  memcpy(buf, data + PAYLOAD_OFST, getPayloadLength());
210  return getPayloadLength();
211  }
212 
218  uint8_t *Message::getPayloadPointer(size_t offset)
219  {
220  return data + PAYLOAD_OFST + offset;
221  }
222 
224  {
225  return data[LENGTH_OFST];
226  }
227 
229  {
230  return data[LENGTH_COMP_OFST];
231  }
232 
234  {
235  return data[VERSION_OFST];
236  }
237 
239  {
240  return data[FLAGS_OFST];
241  }
242 
243  uint16_t Message::getType()
244  {
245  return btou(data + TYPE_OFST, 2);
246  }
247 
249  {
250  return btou(data + crcOffset(), 2);
251  }
252 
253  void Message::setLength(uint8_t len)
254  {
255  size_t new_total_len = len + 3;
256  if (new_total_len > MAX_MSG_LENGTH) { return; }
257  total_len = new_total_len;
258  data[LENGTH_OFST] = len;
259  data[LENGTH_COMP_OFST] = ~len;
260  }
261 
262  void Message::setVersion(uint8_t version)
263  {
264  data[VERSION_OFST] = version;
265  }
266 
267  void Message::setFlags(uint8_t flags)
268  {
269  data[FLAGS_OFST] = flags;
270  }
271 
272  void Message::setType(uint16_t type)
273  {
274  utob(data + TYPE_OFST, 2, type);
275  }
282  void Message::setPayloadLength(uint8_t len)
283  {
284 
285  if (((size_t) (len) + HEADER_LENGTH + CRC_LENGTH) > MAX_MSG_LENGTH) { return; }
287  }
288 
296  void Message::setPayload(void *buf, size_t buf_size)
297  {
298  if ((buf_size + HEADER_LENGTH + CRC_LENGTH) > MAX_MSG_LENGTH) { return; }//�±� *2
299  setPayloadLength(buf_size);
300  if (buf_size > getPayloadLength()) { return; }
301  memcpy(data + PAYLOAD_OFST, buf, buf_size);
302  }
303 
304 
311  size_t Message::toBytes(void *buf, size_t buf_size)
312  {
313  // If we don't have enough space in the buffer, don't even try
314  if (total_len > buf_size)
315  {
316  return 0;
317  }
318  memcpy(buf, data, total_len);
319  return total_len;
320  }
321 
329  bool Message::isValid(char *whyNot, size_t strLen)
330  {
331  // Check SOH
332  if (data[SOH_OFST] != SOH)
333  {
334  if (whyNot) { strncpy(whyNot, "SOH is not present.", strLen); }
335  return false;
336  }
337  // Check STX
338  if (data[STX_OFST] != STX)
339  {
340  if (whyNot) { strncpy(whyNot, "STX is not present.", strLen); }
341  return false;
342  }
343  // Check length matches complement
344  if (getLength() != ((~getLengthComp()) & 0xff))
345  {
346  if (whyNot) { strncpy(whyNot, "Length does not match complement.", strLen); }
347  return false;
348  }
349  // Check length is correct
350  if (getLength() != (total_len - 3))
351  {
352  if (whyNot) { strncpy(whyNot, "Length is wrong.", strLen); }
353  return false;
354  }
355  // Check the CRC
356  if (crc16(crcOffset(), CRC_INIT_VAL, this->data) != getChecksum())
357  {
358  if (whyNot) { strncpy(whyNot, "CRC is wrong.", strLen); }
359 #ifdef DEBUG_INFO
360  for (int i=0; i<crcOffset(); ++i) printf(" %x", (unsigned char)(this->data[i]));
361  printf(" crc16:%x getChecksum:%x",(unsigned char)(crc16(crcOffset(), CRC_INIT_VAL, this->data)),getChecksum());
362  printf("\r\n");
363 #endif
364  return false;
365  }
366  return true;
367  }
368 
373  {
374  data[SOH_OFST] = SOH;
375  data[STX_OFST] = STX;
376  data[LENGTH_OFST] = total_len - 3;
378  uint16_t checksum = crc16(crcOffset(), CRC_INIT_VAL, data);
379  utob(data + crcOffset(), 2, checksum);
380 #ifdef DEBUG_INFO
381  std::cout<<"message data:";
382  for(int i = 0 ; i < total_len;i++){
383  printf(" %x",(unsigned char)(data[i]));
384  }
385  std::cout<<" !!"<<std::endl;
386 #endif
387  }
388 
389  std::ostream &Message::printMessage(std::ostream &stream)
390  {
391  stream << "Message" << endl;
392  stream << "=======" << endl;
393  stream << "Length : " << (int) (getLength()) << endl;
394  stream << "~Length : " << (int) (getLengthComp()) << endl;
395  stream << "Version : " << (int) (getVersion()) << endl;
396  stream << "Flags : " << hex << (int) (getFlags()) << endl;
397  stream << "Type : " << hex << (int) (getType()) << endl;//ԭ�� �±�����Ϊ�ɱ�
398  stream << "Checksum : " << hex << (int) (getChecksum()) << endl;
399  stream << dec;
400  stream << "Raw : ";
401  printRaw(stream);
402  return stream;
403  }
404 
405  void Message::printRaw(std::ostream &stream)
406  {
407  stream << hex << uppercase;
408  for (unsigned int i = 0; i < total_len; i++)
409  {
410  stream << static_cast<short>(data[i]) << " ";
411  }
412  stream << dec;
413  stream << endl;
414  }
415 
423  Message *Message::factory(void *input, size_t msg_len)
424  {
425  uint16_t type = btou((char *) input + TYPE_OFST, 2);
426  switch (type)
427  {
428  case DATA_ACCEL:
429  return new DataPlatformAcceleration(input, msg_len);
430 
431  case DATA_ACCEL_RAW:
432  return new DataRawAcceleration(input, msg_len);
433 
434  case DATA_6AXIS_YAW:
435  return new Data6AxisYaw(input, msg_len);
436 
438  return new DataAckermannOutput(input, msg_len);
439 
440  case DATA_CURRENT_RAW:
441  return new DataRawCurrent(input, msg_len);
442 
443  case DATA_PLATFORM_NAME:
444  return new DataPlatformName(input, msg_len);
445 
447  return new DataDifferentialControl(input, msg_len);
448 
450  return new DataDifferentialSpeed(input, msg_len);
451 
453  return new DataDifferentialOutput(input, msg_len);
454 
455  case DATA_WHEEL_INFO:
456  return new DataWheelInfo(input,msg_len);
457 
458  case DATA_DISTANCE_DATA:
459  return new DataRangefinders(input, msg_len);
460 
462  return new DataRangefinderTimings(input, msg_len);
463 
464  case DATA_ECHO:
465  return new DataEcho(input, msg_len);
466 
467  case DATA_ENCODER:
468  return new DataEncoders(input, msg_len);
469 
470  case DATA_ENCODER_RAW:
471  return new DataEncodersRaw(input, msg_len);
472 
473  case DATA_FIRMWARE_INFO:
474  return new DataFirmwareInfo(input, msg_len);
475 
476  case DATA_GYRO_RAW:
477  return new DataRawGyro(input, msg_len);
478 
479  case DATA_MAGNETOMETER:
480  return new DataPlatformMagnetometer(input, msg_len);
481 
483  return new DataRawMagnetometer(input, msg_len);
484 
485  case DATA_XYZ_DATA:
486  return new DataXYZData(input, msg_len);
487 
488  case DATA_MAX_ACCEL:
489  return new DataMaxAcceleration(input, msg_len);
490 
491  case DATA_MAX_SPEED:
492  return new DataMaxSpeed(input, msg_len);
493 
494  case DATA_ORIENT:
495  return new DataPlatformOrientation(input, msg_len);
496 
497  case DATA_ORIENT_RAW:
498  return new DataRawOrientation(input, msg_len);
499 
500  case DATA_PLATFORM_INFO:
501  return new DataPlatformInfo(input, msg_len);
502 
503  case DATA_POWER_SYSTEM:
504  return new DataPowerSystem(input, msg_len);
505 
506  case DATA_PROC_STATUS:
507  return new DataProcessorStatus(input, msg_len);
508 
509  case DATA_ROT_RATE:
510  return new DataPlatformRotation(input, msg_len);
511 
512  case DATA_SAFETY_SYSTEM:
513  return new DataSafetySystemStatus(input, msg_len);
514 
515  case DATA_SYSTEM_STATUS:
516  return new DataSystemStatus(input, msg_len);
517 
519  return new DataRawTemperature(input, msg_len);
520 
521  case DATA_VELOCITY_SETPT:
522  return new DataVelocity(input, msg_len);
523 
524  case DATA_VOLTAGE_RAW:
525  return new DataRawVoltage(input, msg_len);
526 
527  default:
528  return new Message(input, msg_len);
529  } // switch getType()
530  } // factory()
531 
533  {
534  return Transport::instance().popNext();
535  }
536 
537  Message *Message::waitNext(double timeout)
538  {
539  return Transport::instance().waitNext(timeout);
540  }
541 
542 }; // namespace sawyer
543 
544 std::ostream &operator<<(std::ostream &stream, sawyer::Message &msg)
545 {
546  return msg.printMessage(stream);
547 }
548 
size_t getPayload(void *buf, size_t max_size)
Definition: Message.cpp:204
static Message * waitNext(double timeout=0.0)
Definition: Message.cpp:537
Message * sendRequest(Message *m)
Definition: Transport.cpp:485
static const size_t MAX_MSG_LENGTH
Definition: Message.h:70
void setType(uint16_t type)
Definition: Message.cpp:272
bool isValid(char *whyNot=NULL, size_t strLen=0)
Definition: Message.cpp:329
Message * sendRequest()
Definition: Message.cpp:168
void setFlags(uint8_t flags)
Definition: Message.cpp:267
uint64_t btou(void *src, size_t src_len)
Definition: Number.cpp:120
uint8_t getLengthComp()
Definition: Message.cpp:228
void utob(void *dest, size_t dest_len, uint64_t src)
Definition: Number.cpp:55
size_t total_len
Definition: Message.h:74
static Transport & instance()
Definition: Transport.cpp:129
#define CPR_EXCEPT()
Definition: Logger.h:97
size_t crcOffset()
Definition: Message.h:107
static Message * factory(void *input, size_t msg_len)
Definition: Message.cpp:423
uint8_t * getPayloadPointer(size_t offset=0)
Definition: Message.cpp:218
uint16_t getChecksum()
Definition: Message.cpp:248
void setPayload(void *buf, size_t buf_size)
Definition: Message.cpp:296
void printRaw(std::ostream &stream=std::cout)
Definition: Message.cpp:405
size_t getPayloadLength()
Definition: Message.h:161
bool is_sent
Definition: Message.h:97
void setVersion(uint8_t version)
Definition: Message.cpp:262
const char * message
Definition: Exception.h:49
Message * popNext()
Definition: Transport.cpp:558
size_t toBytes(void *buf, size_t buf_size)
Definition: Message.cpp:311
void setLength(uint8_t len)
Definition: Message.cpp:253
std::ostream & operator<<(std::ostream &stream, sawyer::Message &msg)
Definition: Message.cpp:544
uint16_t crc16(int size, int init_val, uint8_t *data)
Definition: crc.cpp:80
virtual std::ostream & printMessage(std::ostream &stream=std::cout)
Definition: Message.cpp:389
void setPayloadLength(uint8_t len)
Definition: Message.cpp:282
Message * waitNext(double timeout=0.0)
Definition: Transport.cpp:607
uint8_t getLength()
Definition: Message.cpp:223
enum errors type
Definition: Message.h:62
uint16_t getType()
Definition: Message.cpp:243
static Message * popNext()
Definition: Message.cpp:532
static const size_t CRC_LENGTH
Definition: Message.h:77
void makeValid()
Definition: Message.cpp:372
#define CPR_WARN()
Definition: Logger.h:98
static const uint8_t STX
Definition: Message.h:104
void send(Message *m)
Definition: Transport.cpp:408
static const size_t HEADER_LENGTH
Definition: Message.h:80
static const uint16_t CRC_INIT_VAL
Definition: Message.h:78
uint8_t data[MAX_MSG_LENGTH]
Definition: Message.h:72
static const uint8_t SOH
Definition: Message.h:103
virtual ~Message()
Definition: Message.cpp:131
enum sawyer::BadAckException::ackFlags ack_flag
uint8_t getVersion()
Definition: Message.cpp:233
uint8_t getFlags()
Definition: Message.cpp:238


roch_base
Author(s): Mike Purvis , Paul Bovbel , Chen
autogenerated on Mon Jun 10 2019 14:41:13