fusion_engine_framer.h
Go to the documentation of this file.
1 /**************************************************************************/ /**
2  * @brief FusionEngine message framer.
3  * @file
4  ******************************************************************************/
5 
6 #pragma once
7 
8 #include <cstddef> // For size_t
9 #include <cstdint>
10 
12 
13 namespace point_one {
14 namespace fusion_engine {
15 namespace parsers {
16 
17 /**
18  * @brief Frame and validate incoming FusionEngine messages.
19  *
20  * This class locates and validates FusionEngine messages within a stream of
21  * binary data. Data may be stored in an internally allocated buffer, or in an
22  * external buffer supplied by the user.
23  *
24  * The callback function provided to @ref SetMessageCallback() will be called
25  * each time a complete message is received. Any messages that do not pass the
26  * CRC check, or that are too big to be stored in the data buffer, will be
27  * discarded.
28  *
29  * Example usage:
30  * ```cpp
31  * void MessageReceived(const MessageHeader& header, const void* payload) {
32  * if (header.message_type == MessageType::POSE) {
33  * auto& contents = *static_cast<const PoseMessage*>(payload);
34  * ...
35  * }
36  * }
37  *
38  * FusionEngineFramer framer(1024);
39  * framer.SetMessageCallback(MessageReceived);
40  * framer.OnData(my_data, my_data_size);
41  * ```
42  */
44  public:
45  using MessageCallback = void (*)(const messages::MessageHeader&, const void*);
46 
47  /**
48  * @brief Construct a framer instance with no buffer allocated.
49  *
50  * @note
51  * You must call @ref SetBuffer() to assign a buffer, otherwise all incoming
52  * data will be discarded.
53  */
54  FusionEngineFramer() = default;
55 
56  /**
57  * @brief Construct a framer instance with an internally allocated buffer.
58  *
59  * @param capacity_bytes The maximum framing buffer capacity (in bytes).
60  */
61  explicit FusionEngineFramer(size_t capacity_bytes)
62  : FusionEngineFramer(nullptr, capacity_bytes) {}
63 
64  /**
65  * @brief Construct a framer instance with a user-specified buffer.
66  *
67  * @post
68  * `buffer` must exist for the lifetime of this instance.
69  *
70  * @param buffer The framing buffer to use. Set to `nullptr` to allocate a
71  * buffer internally.
72  * @param capacity_bytes The maximum framing buffer capacity (in bytes).
73  */
74  FusionEngineFramer(void* buffer, size_t capacity_bytes);
75 
77 
78  // Don't allow copying or moving to avoid issues with managed buffer_.
79  FusionEngineFramer(const FusionEngineFramer&) = delete; // Copy constructor
80  FusionEngineFramer(FusionEngineFramer&&) = delete; // Move constructor
82  delete; // Copy assignment operator
84  delete; // Move assignment operator
85 
86  /**
87  * @brief Set the buffer to use for message framing.
88  *
89  * @post
90  * `buffer` must exist for the lifetime of this instance.
91  *
92  * @param buffer The framing buffer to use. Set to `nullptr` to allocate a
93  * buffer internally.
94  * @param capacity_bytes The maximum framing buffer capacity (in bytes).
95  */
96  void SetBuffer(void* buffer, size_t capacity_bytes);
97 
98  /**
99  * @brief Enable/disable warnings for CRC and "message too large" failures.
100  *
101  * This is typically used when the incoming stream has multiple types of
102  * binary content (e.g., interleaved FusionEngine and RTCM messages), and the
103  * FusionEngine message preamble is expected to appear in the non-FusionEngine
104  * content occasionally.
105  *
106  * @param enabled If `true`, issue warnings on errors.
107  */
108  void WarnOnError(bool enabled) { warn_on_error_ = enabled; }
109 
110  /**
111  * @brief Specify a function to be called when a message is framed.
112  *
113  * @param callback The function to be called with the message header and a
114  * pointer to the message payload.
115  */
116  void SetMessageCallback(MessageCallback callback) { callback_ = callback; }
117 
118  /**
119  * @brief Reset the framer and discard all pending data.
120  */
121  void Reset();
122 
123  /**
124  * @brief Process incoming data.
125  *
126  * @param buffer A buffer containing data to be framed.
127  * @param length_bytes The number of bytes to be framed.
128  *
129  * @return The total size of all valid, complete messages, or 0 if no messages
130  * were completed.
131  */
132  size_t OnData(const uint8_t* buffer, size_t length_bytes);
133 
134  private:
135  enum class State {
136  SYNC0 = 0,
137  SYNC1 = 1,
138  HEADER = 2,
139  DATA = 3,
140  };
141 
142  MessageCallback callback_ = nullptr;
143 
144  bool warn_on_error_ = true;
145  bool is_buffer_managed_ = false;
146  uint8_t* buffer_{nullptr};
147  uint32_t capacity_bytes_{0};
148 
149  State state_{State::SYNC0};
150  uint32_t next_byte_index_{0};
151  uint32_t current_message_size_{0};
152 
153  /**
154  * @brief Process a single byte.
155  *
156  * @pre
157  * The byte must be located at `buffer_[next_byte_index_ - 1]`.
158  *
159  * @param quiet If `true`, suppress failure warning messages.
160  *
161  * @return The total size of all valid, complete messages, 0 if no messages
162  * were completed, or <0 CRC or "message too large" error.
163  */
164  int32_t OnByte(bool quiet);
165 
166  /**
167  * @brief Perform a resynchronization operation starting at `buffer_[1]`.
168  *
169  * @return The total size of all valid, complete messages, or 0 if no messages
170  * were completed.
171  */
172  uint32_t Resync();
173 
174  /**
175  * @brief Free the @ref buffer_ if it's being managed internally.
176  */
177  void ClearManagedBuffer();
178 };
179 
180 } // namespace parsers
181 } // namespace fusion_engine
182 } // namespace point_one
FusionEngineFramer & operator=(const FusionEngineFramer &)=delete
void WarnOnError(bool enabled)
Enable/disable warnings for CRC and "message too large" failures.
The header present at the beginning of every message.
Definition: defs.h:531
FusionEngineFramer(size_t capacity_bytes)
Construct a framer instance with an internally allocated buffer.
#define P1_EXPORT
Definition: portability.h:33
FusionEngineFramer & operator=(FusionEngineFramer &&)=delete
GNSS signal and frequency type definitions.
Definition: logging.h:38
FusionEngineFramer()=default
Construct a framer instance with no buffer allocated.
Frame and validate incoming FusionEngine messages.
FusionEngineFramer(FusionEngineFramer &&)=delete
FusionEngineFramer(const FusionEngineFramer &)=delete
Point One FusionEngine output message common definitions.
State
void(*)(const messages::MessageHeader &, const void *) MessageCallback
void SetMessageCallback(MessageCallback callback)
Specify a function to be called when a message is framed.