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