29 #ifndef UBLOX_SERIALIZATION_H 30 #define UBLOX_SERIALIZATION_H 34 #include <boost/call_traits.hpp> 78 static void read(
const uint8_t *data, uint32_t count,
79 typename boost::call_traits<T>::reference message);
88 typename boost::call_traits<T>::param_type message);
96 static void write(uint8_t *data, uint32_t size,
97 typename boost::call_traits<T>::param_type message);
104 template <
typename T>
113 static bool canDecode(uint8_t class_id, uint8_t message_id) {
114 return std::find(keys_.begin(), keys_.end(),
115 std::make_pair(class_id, message_id)) != keys_.end();
124 static void addKey(uint8_t class_id, uint8_t message_id) {
125 keys_.push_back(std::make_pair(class_id, message_id));
136 static std::vector<std::pair<uint8_t,uint8_t> >
keys_;
146 Options() : sync_a(DEFAULT_SYNC_A), sync_b(DEFAULT_SYNC_B),
147 max_payload_length(kMaxPayloadLength),
148 header_length(kHeaderLength), checksum_length(kChecksumLength) {}
165 return header_length + checksum_length;
180 Reader(
const uint8_t *data, uint32_t count,
182 data_(data), count_(count), found_(false), options_(options)
184 unused_data_.reserve(1024);
197 for( ; count_ > 0; --count_, ++data_) {
198 if (data_[0] == options_.sync_a &&
199 (count_ == 1 || data_[1] == options_.sync_b)) {
201 if (length() > options_.max_payload_length) {
203 ROS_ERROR(
"U-Blox message exceeds maximum payload length %u: " 204 "0x%02x / 0x%02x", options_.max_payload_length,
205 classId(), messageId());
211 unused_data_.push_back(data_[0]);
224 if (found_)
return true;
226 if (count_ < options_.wrapper_length())
return false;
228 if (data_[0] != options_.sync_a || data_[1] != options_.sync_b)
232 if (count_ < length() + options_.wrapper_length())
return false;
247 uint32_t size = length() + options_.wrapper_length();
248 data_ += size; count_ -= size;
263 return data_ + count_;
277 if (count_ < 6)
return 0u;
278 return (data_[5] << 8) + data_[4];
280 const uint8_t *
data() {
return data_ + options_.header_length; }
288 return *
reinterpret_cast<const uint16_t *
>(data_ + options_.header_length +
297 template <
typename T>
298 bool read(
typename boost::call_traits<T>::reference message,
299 bool search =
false) {
301 if (!found())
return false;
307 ROS_DEBUG(
"U-Blox read checksum error: 0x%02x / 0x%02x", classId(),
321 template <
typename T>
323 if (!found())
return false;
333 if (!found())
return false;
334 return (classId() == class_id && messageId() == message_id);
366 data_(data), size_(size), options_(options) {}
375 template <
typename T>
bool write(
const T& message,
376 uint8_t class_id = T::CLASS_ID,
377 uint8_t message_id = T::MESSAGE_ID) {
380 if (size_ < length + options_.wrapper_length()) {
381 ROS_ERROR(
"u-blox write buffer overflow. Message %u / %u not written",
382 class_id, message_id);
387 size_ - options_.header_length, message);
388 return write(0, length, class_id, message_id);
400 bool write(
const uint8_t* message, uint32_t length, uint8_t class_id,
401 uint8_t message_id) {
402 if (size_ < length + options_.wrapper_length()) {
403 ROS_ERROR(
"u-blox write buffer overflow. Message %u / %u not written",
404 class_id, message_id);
407 iterator
start = data_;
410 *data_++ = options_.sync_a;
411 *data_++ = options_.sync_b;
413 *data_++ = message_id;
414 *data_++ = length & 0xFF;
415 *data_++ = (length >> 8) & 0xFF;
416 size_ -= options_.header_length;
419 if (message) std::copy(message, message + length, data_);
428 size_ -= options_.checksum_length;
450 #define DECLARE_UBLOX_MESSAGE(class_id, message_id, package, message) \ 451 template class ublox::Serializer<package::message>; \ 452 template class ublox::Message<package::message>; \ 453 namespace package { namespace { \ 454 static const ublox::Message<message>::StaticKeyInitializer static_key_initializer_##message(class_id, message_id); \ 460 #define DECLARE_UBLOX_MESSAGE_ID(class_id, message_id, package, message, name) \ 461 namespace package { namespace { \ 462 static const ublox::Message<message>::StaticKeyInitializer static_key_initializer_##name(class_id, message_id); \ 469 #endif // UBLOX_SERIALIZATION_H
uint8_t sync_a
The sync_a byte value identifying the start of a message.
bool isMessage(uint8_t class_id, uint8_t message_id)
Does the u-blox message have the given class and message ID?
static const uint8_t DEFAULT_SYNC_A
u-blox message Sync A char
iterator search()
Search the buffer for the beginning of the next u-blox message.
Options options_
Options representing the sync char values, etc.
uint32_t length()
Get the length of the u-blox message payload.
static void write(uint8_t *data, uint32_t size, typename boost::call_traits< T >::param_type message)
Encode the message payload as a byte array.
uint32_t max_payload_length
The maximum payload length.
int wrapper_length()
Get the number of bytes in the header and footer.
StaticKeyInitializer(uint8_t class_id, uint8_t message_id)
static void calculateChecksum(const uint8_t *data, uint32_t size, uint8_t &ck_a, uint8_t &ck_b)
calculate the checksum of a u-blox_message
const std::string & getUnusedData() const
bool write(const T &message, uint8_t class_id=T::CLASS_ID, uint8_t message_id=T::MESSAGE_ID)
Encode the u-blox message.
static const uint32_t kMaxPayloadLength
Maximum payload length.
uint16_t checksum()
Get the checksum of the u-blox message.
static bool canDecode(uint8_t class_id, uint8_t message_id)
Can this message type decode a u-blox message with the given ID?
iterator data_
The buffer of message bytes.
const uint8_t * data_
The buffer of message bytes.
Options for the Reader and Writer for encoding and decoding messages.
static std::vector< std::pair< uint8_t, uint8_t > > keys_
Encodes a u-blox ROS message as a byte array.
static void read(const uint8_t *data, uint32_t count, typename boost::call_traits< T >::reference message)
Decode the message payload from the data buffer.
Options options_
Options representing the sync char values, etc.
Writer(uint8_t *data, uint32_t size, const Options &options=Options())
Construct a Writer with the given buffer.
uint32_t count_
the number of bytes in the buffer, //! decrement as the buffer is read
uint32_t size_
The number of remaining bytes in the buffer.
uint8_t sync_b
The sync_b byte value identifying the start of a message.
iterator next()
Go to the start of the next message based on the received message length.
Decodes byte messages into u-blox ROS messages.
static uint32_t serializedLength(typename boost::call_traits< T >::param_type message)
Get the length of the message payload in bytes.
bool hasType()
Can the given message type decode the current message in the buffer?
static void addKey(uint8_t class_id, uint8_t message_id)
Indicate that this message type can decode u-blox messages with the given ID.
static const uint8_t kHeaderLength
Number of bytes in a message header (Sync chars + class ID + message ID)
bool found()
Has a u-blox message been found in the buffer?
static const uint8_t kChecksumLength
Number of checksum bytes in the u-blox message.
iterator pos()
Get the current position in the read buffer.
Reader(const uint8_t *data, uint32_t count, const Options &options=Options())
ROSCPP_DECL bool search(const std::string &ns, const std::string &key, std::string &result)
uint8_t header_length
The length of the message header in bytes (everything before the payload)
static const uint8_t DEFAULT_SYNC_B
u-blox message Sync B char
bool found_
Whether or not a message has been found.
uint8_t checksum_length
The length of the checksum in bytes.
bool read(typename boost::call_traits< T >::reference message, bool search=false)
Decode the given message.
bool write(const uint8_t *message, uint32_t length, uint8_t class_id, uint8_t message_id)
Wrap the encoded message payload with a header and checksum and add it to the buffer.
std::string unused_data_
Unused data from the read buffer, contains nmea messages.
Keeps track of which class and message IDs can be decoded by a given message type.
Encodes and decodes messages.