29 #ifndef UBLOX_SERIALIZATION_H 30 #define UBLOX_SERIALIZATION_H 34 #include <boost/call_traits.hpp> 76 static void read(
const uint8_t *data, uint32_t count,
77 typename boost::call_traits<T>::reference message);
86 typename boost::call_traits<T>::param_type message);
94 static void write(uint8_t *data, uint32_t size,
95 typename boost::call_traits<T>::param_type message);
102 template <
typename T>
111 static bool canDecode(uint8_t class_id, uint8_t message_id) {
112 return std::find(keys_.begin(), keys_.end(),
113 std::make_pair(class_id, message_id)) != keys_.end();
122 static void addKey(uint8_t class_id, uint8_t message_id) {
123 keys_.push_back(std::make_pair(class_id, message_id));
134 static std::vector<std::pair<uint8_t,uint8_t> >
keys_;
144 Options() : sync_a(DEFAULT_SYNC_A), sync_b(DEFAULT_SYNC_B),
145 header_length(kHeaderLength), checksum_length(kChecksumLength) {}
160 return header_length + checksum_length;
175 Reader(
const uint8_t *data, uint32_t count,
177 data_(data), count_(count), found_(false), options_(options) {}
190 for( ; count_ > 0; --count_, ++data_) {
191 if (data_[0] == options_.sync_a &&
192 (count_ == 1 || data_[1] == options_.sync_b))
205 if (found_)
return true;
207 if (count_ < options_.wrapper_length())
return false;
209 if (data_[0] != options_.sync_a || data_[1] != options_.sync_b)
213 if (count_ < length() + options_.wrapper_length())
return false;
228 uint32_t size = length() + options_.wrapper_length();
229 data_ += size; count_ -= size;
244 return data_ + count_;
257 uint32_t
length() {
return (data_[5] << 8) + data_[4]; }
258 const uint8_t *
data() {
return data_ + options_.header_length; }
266 return *
reinterpret_cast<const uint16_t *
>(data_ + options_.header_length +
275 template <
typename T>
276 bool read(
typename boost::call_traits<T>::reference message,
277 bool search =
false) {
279 if (!found())
return false;
285 ROS_DEBUG(
"U-Blox read checksum error: 0x%02x / 0x%02x", classId(),
299 template <
typename T>
301 if (!found())
return false;
311 if (!found())
return false;
312 return (classId() == class_id && messageId() == message_id);
340 data_(data), size_(size), options_(options) {}
349 template <
typename T>
bool write(
const T& message,
350 uint8_t class_id = T::CLASS_ID,
351 uint8_t message_id = T::MESSAGE_ID) {
354 if (size_ < length + options_.wrapper_length()) {
355 ROS_ERROR(
"u-blox write buffer overflow. Message %u / %u not written",
356 class_id, message_id);
361 size_ - options_.header_length, message);
362 return write(0, length, class_id, message_id);
374 bool write(
const uint8_t* message, uint32_t length, uint8_t class_id,
375 uint8_t message_id) {
376 if (size_ < length + options_.wrapper_length()) {
377 ROS_ERROR(
"u-blox write buffer overflow. Message %u / %u not written",
378 class_id, message_id);
381 iterator
start = data_;
384 *data_++ = options_.sync_a;
385 *data_++ = options_.sync_b;
387 *data_++ = message_id;
388 *data_++ = length & 0xFF;
389 *data_++ = (length >> 8) & 0xFF;
390 size_ -= options_.header_length;
393 if (message) std::copy(message, message + length, data_);
402 size_ -= options_.checksum_length;
424 #define DECLARE_UBLOX_MESSAGE(class_id, message_id, package, message) \ 425 template class ublox::Serializer<package::message>; \ 426 template class ublox::Message<package::message>; \ 427 namespace package { namespace { \ 428 static const ublox::Message<message>::StaticKeyInitializer static_key_initializer_##message(class_id, message_id); \ 434 #define DECLARE_UBLOX_MESSAGE_ID(class_id, message_id, package, message, name) \ 435 namespace package { namespace { \ 436 static const ublox::Message<message>::StaticKeyInitializer static_key_initializer_##name(class_id, message_id); \ 443 #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.
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
bool write(const T &message, uint8_t class_id=T::CLASS_ID, uint8_t message_id=T::MESSAGE_ID)
Encode the u-blox message.
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.
Keeps track of which class and message IDs can be decoded by a given message type.
Encodes and decodes messages.