14 uint32_t timestamp_ms,
15 uint8_t *buffer,
size_t buffer_size) {
17 const size_t header_size =
sizeof(PacketHeader);
18 const size_t body_size =
sizeof(BoardHeartbeatPacket);
19 const size_t total_size = header_size + body_size;
22 if (buffer_size < total_size) {
30 header.timestamp = timestamp_ms;
33 memcpy(buffer, &header, header_size);
36 memcpy(buffer + header_size, &data, body_size);
42 uint32_t timestamp_ms,
43 uint8_t *buffer,
size_t buffer_size) {
44 const size_t header_size =
sizeof(PacketHeader);
45 const size_t body_header_size =
sizeof(SensorDataPacket);
47 const size_t num_chunks =
chunks.size();
50 const size_t per_chunk_size =
sizeof(SensorDataChunk) + (
static_cast<size_t>(num_sensors) *
sizeof(SensorDatapoint));
51 const size_t total_size = header_size + body_header_size + (num_chunks * per_chunk_size);
53 if (buffer_size < total_size) {
61 header.timestamp = timestamp_ms;
64 uint8_t *
ptr = buffer;
65 memcpy(
ptr, &header, header_size);
69 SensorDataPacket body;
70 body.num_chunks = num_chunks;
71 body.num_sensors = num_sensors;
72 memcpy(
ptr, &body, body_header_size);
73 ptr += body_header_size;
76 for (uint8_t i = 0; i < num_chunks; ++i) {
78 SensorDataChunk chunk_hdr;
79 chunk_hdr.timestamp =
chunks[i].timestamp;
80 memcpy(
ptr, &chunk_hdr,
sizeof(SensorDataChunk));
81 ptr +=
sizeof(SensorDataChunk);
84 const SensorDatapoint *dp =
chunks[i].datapoints.data();
85 size_t datapoints_total_size =
static_cast<size_t>(num_sensors) *
sizeof(SensorDatapoint);
86 memcpy(
ptr, dp, datapoints_total_size);
87 ptr += datapoints_total_size;
94 uint8_t *buffer,
size_t buffer_size) {
96 const size_t header_size =
sizeof(PacketHeader);
99 if (buffer_size < header_size) {
107 header.timestamp = timestamp_ms;
110 memcpy(buffer, &header, header_size);
116 uint32_t timestamp_ms,
117 uint8_t *buffer,
size_t buffer_size) {
118 const size_t header_size =
sizeof(PacketHeader);
119 const size_t body_size =
sizeof(ActuatorCommandPacket);
120 const size_t num_commands =
commands.size();
122 if (num_commands > 255 || num_commands == 0) {
126 const size_t commands_bytes = num_commands *
sizeof(ActuatorCommand);
127 const size_t total_size = header_size + body_size + commands_bytes;
129 if (buffer_size < total_size) {
137 header.timestamp = timestamp_ms;
139 uint8_t *
ptr = buffer;
140 memcpy(
ptr, &header, header_size);
144 ActuatorCommandPacket body;
145 body.num_commands =
static_cast<uint8_t
>(num_commands);
146 memcpy(
ptr, &body, body_size);
158 const std::vector<SelfTestResult> &results,
159 uint32_t timestamp_ms,
160 uint8_t *buffer,
size_t buffer_size) {
161 const size_t header_size =
sizeof(PacketHeader);
162 const size_t body_size =
sizeof(SelfTestPacket);
163 const size_t num_sensors = results.size();
165 if (num_sensors > 255) {
169 const size_t results_bytes = num_sensors *
sizeof(SelfTestResult);
170 const size_t total_size = header_size + body_size + results_bytes;
172 if (buffer_size < total_size) {
180 header.timestamp = timestamp_ms;
182 uint8_t *
ptr = buffer;
183 memcpy(
ptr, &header, header_size);
188 body.adc_good = adc_good;
189 body.num_sensors =
static_cast<uint8_t
>(num_sensors);
190 memcpy(
ptr, &body, body_size);
195 memcpy(
ptr, results.data(), results_bytes);
202 uint32_t pressure_pa,
204 uint32_t timestamp_ms,
205 uint8_t *buffer,
size_t buffer_size) {
206 const size_t header_size =
sizeof(PacketHeader);
207 const size_t body_size =
sizeof(EnvironmentalDataPacket);
208 const size_t total_size = header_size + body_size;
210 if (!buffer || buffer_size < total_size) {
217 header.timestamp = timestamp_ms;
219 EnvironmentalDataPacket body;
220 body.temperature_c = temperature_c;
221 body.pressure_pa = pressure_pa;
222 body.humidity_rh = humidity_rh;
224 uint8_t *
ptr = buffer;
225 memcpy(
ptr, &header, header_size);
227 memcpy(
ptr, &body, body_size);
232 uint32_t timestamp_ms,
233 uint8_t *buffer,
size_t buffer_size) {
234 const size_t header_size =
sizeof(PacketHeader);
235 const size_t body_size =
sizeof(StacklightCommandPacket);
236 const size_t total_size = header_size + body_size;
238 if (!buffer || buffer_size < total_size) {
245 header.timestamp = timestamp_ms;
247 uint8_t *
ptr = buffer;
248 memcpy(
ptr, &header, header_size);
250 memcpy(
ptr, &data, body_size);
255 PacketHeader &header_out,
256 BoardHeartbeatPacket &data_out) {
257 const size_t header_size =
sizeof(PacketHeader);
258 const size_t body_size =
sizeof(BoardHeartbeatPacket);
259 const size_t total_size = header_size + body_size;
260 if (!buffer || buffer_size < total_size)
return false;
264 memcpy(&hdr, buffer, header_size);
268 memcpy(&data_out, buffer + header_size, body_size);
274 PacketHeader &header_out,
275 ServerHeartbeatPacket &data_out) {
276 const size_t header_size =
sizeof(PacketHeader);
277 const size_t body_size =
sizeof(ServerHeartbeatPacket);
278 const size_t total_size = header_size + body_size;
279 if (!buffer || buffer_size < total_size)
return false;
283 memcpy(&hdr, buffer, header_size);
287 memcpy(&data_out, buffer + header_size, body_size);
293 PacketHeader &header_out,
294 EnvironmentalDataPacket &data_out) {
295 const size_t header_size =
sizeof(PacketHeader);
296 const size_t body_size =
sizeof(EnvironmentalDataPacket);
297 const size_t total_size = header_size + body_size;
298 if (!buffer || buffer_size < total_size)
return false;
301 memcpy(&hdr, buffer, header_size);
304 memcpy(&data_out, buffer + header_size, body_size);
310 PacketHeader &header_out,
311 StacklightCommandPacket &data_out) {
312 const size_t header_size =
sizeof(PacketHeader);
313 const size_t body_size =
sizeof(StacklightCommandPacket);
314 const size_t total_size = header_size + body_size;
315 if (!buffer || buffer_size < total_size)
return false;
318 memcpy(&hdr, buffer, header_size);
321 memcpy(&data_out, buffer + header_size, body_size);
327 PacketHeader &header_out,
328 std::vector<SensorDataChunkCollection> &chunks_out) {
329 const size_t header_size =
sizeof(PacketHeader);
330 const size_t body_hdr_size =
sizeof(SensorDataPacket);
332 if (!buffer || buffer_size < header_size + body_hdr_size)
return false;
336 memcpy(&hdr, buffer, header_size);
339 const uint8_t *
ptr = buffer + header_size;
341 SensorDataPacket body;
342 memcpy(&body,
ptr, body_hdr_size);
343 ptr += body_hdr_size;
345 const size_t per_chunk_size =
sizeof(SensorDataChunk) + (
static_cast<size_t>(body.num_sensors) *
sizeof(SensorDatapoint));
346 const size_t expected_size = header_size + body_hdr_size + (
static_cast<size_t>(body.num_chunks) * per_chunk_size);
347 if (buffer_size < expected_size)
return false;
350 chunks_out.reserve(body.num_chunks);
352 for (uint8_t c = 0; c < body.num_chunks; ++c) {
354 SensorDataChunk chunk_hdr;
355 memcpy(&chunk_hdr,
ptr,
sizeof(SensorDataChunk));
356 ptr +=
sizeof(SensorDataChunk);
360 if (body.num_sensors) {
362 memcpy(col.
datapoints.data(),
ptr,
static_cast<size_t>(body.num_sensors) *
sizeof(SensorDatapoint));
363 ptr +=
static_cast<size_t>(body.num_sensors) *
sizeof(SensorDatapoint);
365 chunks_out.push_back(std::move(col));
373 PacketHeader &header_out) {
374 const size_t header_size =
sizeof(PacketHeader);
375 if (!buffer || buffer_size < header_size)
return false;
378 memcpy(&hdr, buffer, header_size);
385 PacketHeader &header_out,
386 std::vector<ActuatorCommand> &commands_out) {
387 const size_t header_size =
sizeof(PacketHeader);
388 const size_t body_size =
sizeof(ActuatorCommandPacket);
389 if (!buffer || buffer_size < header_size + body_size)
return false;
392 memcpy(&hdr, buffer, header_size);
395 const uint8_t *
ptr = buffer + header_size;
396 ActuatorCommandPacket body;
397 memcpy(&body,
ptr, body_size);
400 const size_t commands_bytes =
static_cast<size_t>(body.num_commands) *
sizeof(ActuatorCommand);
401 const size_t expected_size = header_size + body_size + commands_bytes;
402 if (buffer_size < expected_size)
return false;
404 commands_out.clear();
405 if (body.num_commands) {
406 commands_out.resize(body.num_commands);
407 memcpy(commands_out.data(),
ptr, commands_bytes);
415 PacketHeader &header_out,
416 uint8_t &adc_good_out,
417 std::vector<SelfTestResult> &results_out) {
418 const size_t header_size =
sizeof(PacketHeader);
419 const size_t body_size =
sizeof(SelfTestPacket);
420 if (!buffer || buffer_size < header_size + body_size)
return false;
423 memcpy(&hdr, buffer, header_size);
426 const uint8_t *
ptr = buffer + header_size;
428 memcpy(&body,
ptr, body_size);
431 const size_t results_bytes =
static_cast<size_t>(body.num_sensors) *
sizeof(SelfTestResult);
432 const size_t expected_size = header_size + body_size + results_bytes;
433 if (buffer_size < expected_size)
return false;
435 adc_good_out = body.adc_good;
438 if (body.num_sensors) {
439 results_out.resize(body.num_sensors);
440 memcpy(results_out.data(),
ptr, results_bytes);
448 uint32_t timestamp_ms,
449 uint8_t *buffer,
size_t buffer_size) {
450 const size_t header_size =
sizeof(PacketHeader);
451 const size_t body_size =
sizeof(PWMActuatorCommandPacket);
452 const size_t num_commands =
commands.size();
454 if (num_commands > 255 || num_commands == 0) {
458 const size_t commands_bytes = num_commands *
sizeof(PWMActuatorCommand);
459 const size_t total_size = header_size + body_size + commands_bytes;
461 if (buffer_size < total_size) {
469 header.timestamp = timestamp_ms;
471 uint8_t *
ptr = buffer;
472 memcpy(
ptr, &header, header_size);
476 PWMActuatorCommandPacket body;
477 body.num_commands =
static_cast<uint8_t
>(num_commands);
478 memcpy(
ptr, &body, body_size);
490 PacketHeader &header_out,
491 std::vector<PWMActuatorCommand> &commands_out) {
492 const size_t header_size =
sizeof(PacketHeader);
493 const size_t body_size =
sizeof(PWMActuatorCommandPacket);
494 if (!buffer || buffer_size < header_size + body_size)
return false;
497 memcpy(&hdr, buffer, header_size);
500 const uint8_t *
ptr = buffer + header_size;
501 PWMActuatorCommandPacket body;
502 memcpy(&body,
ptr, body_size);
505 const size_t commands_bytes =
static_cast<size_t>(body.num_commands) *
sizeof(PWMActuatorCommand);
506 const size_t expected_size = header_size + body_size + commands_bytes;
507 if (buffer_size < expected_size)
return false;
509 commands_out.clear();
510 if (body.num_commands) {
511 commands_out.resize(body.num_commands);
512 memcpy(commands_out.data(),
ptr, commands_bytes);
520 uint8_t reference_voltage,
521 bool necessary_for_abort,
522 uint32_t controller_ip,
523 uint8_t enable_serial_printing,
524 uint32_t timestamp_ms,
525 uint8_t *buffer,
size_t buffer_size) {
526 const size_t header_size =
sizeof(PacketHeader);
527 const size_t num_sensors = sensor_ids.size();
529 if (num_sensors > 255) {
533 const size_t body_size = 1u
537 + (necessary_for_abort ? 4u : 0u)
539 const size_t total_size = header_size + body_size;
541 if (buffer_size < total_size) {
548 header.timestamp = timestamp_ms;
550 uint8_t *
ptr = buffer;
551 memcpy(
ptr, &header, header_size);
554 *
ptr =
static_cast<uint8_t
>(num_sensors);
558 memcpy(
ptr, sensor_ids.data(), num_sensors);
562 *
ptr = reference_voltage;
565 *
ptr = necessary_for_abort ? 1u : 0u;
568 if (necessary_for_abort) {
569 memcpy(
ptr, &controller_ip,
sizeof(uint32_t));
570 ptr +=
sizeof(uint32_t);
573 *
ptr = enable_serial_printing;
579 PacketHeader &header_out,
580 std::vector<uint8_t> &sensor_ids_out,
581 uint8_t &reference_voltage_out,
582 bool &necessary_for_abort_out,
583 uint32_t &controller_ip_out,
584 uint8_t &enable_serial_printing_out) {
585 const size_t header_size =
sizeof(PacketHeader);
587 const size_t min_body = 4u;
589 if (!buffer || buffer_size < header_size + min_body) {
594 memcpy(&hdr, buffer, header_size);
599 const uint8_t *
ptr = buffer + header_size;
601 const uint8_t num_sensors = *
ptr;
606 const size_t min_remaining =
static_cast<size_t>(num_sensors) + 3u;
607 if (buffer_size < header_size + 1u + min_remaining) {
611 sensor_ids_out.clear();
613 sensor_ids_out.resize(num_sensors);
614 memcpy(sensor_ids_out.data(),
ptr, num_sensors);
618 reference_voltage_out = *
ptr;
621 const uint8_t abort_flag = *
ptr;
623 necessary_for_abort_out = (abort_flag != 0);
625 if (necessary_for_abort_out) {
627 const size_t consumed =
static_cast<size_t>(
ptr - buffer);
628 if (buffer_size < consumed +
sizeof(uint32_t) + 1u) {
631 memcpy(&controller_ip_out,
ptr,
sizeof(uint32_t));
632 ptr +=
sizeof(uint32_t);
634 controller_ip_out = 0;
638 const size_t consumed =
static_cast<size_t>(
ptr - buffer);
639 if (buffer_size < consumed + 1u) {
642 enable_serial_printing_out = *
ptr;
650 const std::vector<AbortActuatorLocation> &abort_actuators,
651 const std::vector<AbortPTLocation> &abort_pts,
652 uint8_t enable_serial_printing,
653 uint32_t timestamp_ms,
654 uint8_t *buffer,
size_t buffer_size) {
655 const size_t header_size =
sizeof(PacketHeader);
656 const size_t config_header_size =
sizeof(ActuatorConfigPacket);
657 const size_t N = abort_actuators.size();
658 const size_t X = abort_pts.size();
664 const size_t actuator_bytes = N *
sizeof(AbortActuatorLocation);
665 const size_t pt_count_size =
sizeof(AbortPTSectionHeader);
666 const size_t pt_entries_bytes = X *
sizeof(AbortPTLocation);
667 const size_t trailer_size = 1u;
668 const size_t body_size = config_header_size + actuator_bytes + pt_count_size + pt_entries_bytes + trailer_size;
669 const size_t total_size = header_size + body_size;
671 if (buffer_size < total_size) {
678 header.timestamp = timestamp_ms;
680 uint8_t *
ptr = buffer;
681 memcpy(
ptr, &header, header_size);
684 ActuatorConfigPacket
config;
686 config.num_abort_actuators =
static_cast<uint8_t
>(N);
687 memcpy(
ptr, &
config, config_header_size);
688 ptr += config_header_size;
691 memcpy(
ptr, abort_actuators.data(), actuator_bytes);
692 ptr += actuator_bytes;
695 AbortPTSectionHeader pt_header;
696 pt_header.num_abort_pts =
static_cast<uint8_t
>(X);
697 memcpy(
ptr, &pt_header, pt_count_size);
698 ptr += pt_count_size;
701 memcpy(
ptr, abort_pts.data(), pt_entries_bytes);
702 ptr += pt_entries_bytes;
705 *
ptr = enable_serial_printing;
711 PacketHeader &header_out,
712 uint8_t &is_abort_controller_out,
713 std::vector<AbortActuatorLocation> &abort_actuators_out,
714 std::vector<AbortPTLocation> &abort_pts_out,
715 uint8_t &enable_serial_printing_out) {
716 const size_t header_size =
sizeof(PacketHeader);
717 const size_t config_header_size =
sizeof(ActuatorConfigPacket);
718 const size_t pt_count_size =
sizeof(AbortPTSectionHeader);
719 const size_t trailer_size = 1u;
721 if (!buffer || buffer_size < header_size + config_header_size + pt_count_size + trailer_size) {
726 memcpy(&hdr, buffer, header_size);
731 const uint8_t *
ptr = buffer + header_size;
732 ActuatorConfigPacket
config;
733 memcpy(&
config,
ptr, config_header_size);
734 ptr += config_header_size;
736 const size_t N =
config.num_abort_actuators;
737 const size_t actuator_bytes = N *
sizeof(AbortActuatorLocation);
738 const size_t min_size_after_config = actuator_bytes + pt_count_size + trailer_size;
739 if (buffer_size < header_size + config_header_size + min_size_after_config) {
743 abort_actuators_out.clear();
748 abort_actuators_out.resize(N);
749 memcpy(abort_actuators_out.data(),
ptr, actuator_bytes);
750 ptr += actuator_bytes;
753 AbortPTSectionHeader pt_header;
754 memcpy(&pt_header,
ptr, pt_count_size);
755 ptr += pt_count_size;
757 const size_t X = pt_header.num_abort_pts;
758 const size_t pt_entries_bytes = X *
sizeof(AbortPTLocation);
759 const size_t expected_total = header_size + config_header_size + actuator_bytes + pt_count_size + pt_entries_bytes + trailer_size;
760 if (buffer_size < expected_total) {
767 abort_pts_out.clear();
769 abort_pts_out.resize(X);
770 memcpy(abort_pts_out.data(),
ptr, pt_entries_bytes);
771 ptr += pt_entries_bytes;
774 enable_serial_printing_out = *
ptr;
775 is_abort_controller_out =
config.is_abort_controller;
781 uint32_t timestamp_ms,
782 uint8_t *buffer,
size_t buffer_size) {
783 const size_t header_size =
sizeof(PacketHeader);
784 const size_t total_size = header_size + 1 + 2 + text_len;
785 if (buffer_size < total_size) {
792 header.timestamp = timestamp_ms;
794 uint8_t *
ptr = buffer;
795 memcpy(
ptr, &header, header_size);
799 memcpy(
ptr, &text_len,
sizeof(text_len));
800 ptr +=
sizeof(text_len);
801 if (text_len && text) {
802 memcpy(
ptr, text, text_len);
808 PacketHeader &header_out,
810 const uint8_t *&text_out,
811 uint16_t &text_len_out) {
812 const size_t header_size =
sizeof(PacketHeader);
813 const size_t fixed_body = 1u + 2u ;
814 if (!buffer || buffer_size < header_size + fixed_body)
return false;
817 memcpy(&hdr, buffer, header_size);
820 const uint8_t *
ptr = buffer + header_size;
821 const uint8_t flags = *
ptr++;
824 memcpy(&text_len,
ptr,
sizeof(text_len));
825 ptr +=
sizeof(text_len);
827 if (buffer_size < header_size + fixed_body + text_len)
return false;
831 text_len_out = text_len;
#define MAX_ABORT_ACTUATORS
#define DIABLO_COMMS_VERSION
std::vector< daq::SensorDataChunkCollection > chunks
static bool is_abort_controller
static osMessageQueueId_t commands
static const idle_config_t config
*brief write string representation of the JSON pointer to stream *sa const json_pointer & ptr
bool parse_self_test_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out, uint8_t &adc_good_out, std::vector< SelfTestResult > &results_out)
Parses a Self Test packet from buffer.
size_t create_sensor_data_packet(const std::vector< SensorDataChunkCollection > &chunks, const uint8_t num_sensors, uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a complete Sensor Data packet in the provided buffer.
bool parse_server_heartbeat_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out, ServerHeartbeatPacket &data_out)
Parses a Server Heartbeat packet from buffer.
bool parse_log_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out, uint8_t &flags_out, const uint8_t *&text_out, uint16_t &text_len_out)
Parses a LOGS packet (type 15) from buffer.
size_t create_abort_done_packet(uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a simple Abort Done packet.
bool parse_sensor_config_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out, std::vector< uint8_t > &sensor_ids_out, uint8_t &reference_voltage_out, bool &necessary_for_abort_out, uint32_t &controller_ip_out, uint8_t &enable_serial_printing_out)
Parses a Sensor Config packet from buffer.
size_t create_log_packet(uint8_t flags, const uint8_t *text, uint16_t text_len, uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a LOGS packet (type 15): buffered board log text for the server.
bool parse_board_heartbeat_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out, BoardHeartbeatPacket &data_out)
Parses a Board Heartbeat packet from buffer.
size_t create_board_heartbeat_packet(const BoardHeartbeatPacket &data, uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a complete Board Heartbeat packet in the provided buffer.
bool parse_pwm_actuator_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out, std::vector< PWMActuatorCommand > &commands_out)
Parses a PWM Actuator Command packet from buffer.
size_t create_pwm_actuator_packet(const std::vector< PWMActuatorCommand > &commands, uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a complete PWM Actuator Command packet in the provided buffer.
size_t create_stacklight_command_packet(const StacklightCommandPacket &data, uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a complete Stacklight Command packet in the provided buffer.
bool parse_stacklight_command_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out, StacklightCommandPacket &data_out)
Parses a Stacklight Command packet from buffer.
size_t create_environmental_data_packet(float temperature_c, uint32_t pressure_pa, float humidity_rh, uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a complete Environmental Data packet in the provided buffer.
bool parse_actuator_command_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out, std::vector< ActuatorCommand > &commands_out)
Parses an Actuator Command packet from buffer.
size_t create_sensor_config_packet(const std::vector< uint8_t > &sensor_ids, uint8_t reference_voltage, bool necessary_for_abort, uint32_t controller_ip, uint8_t enable_serial_printing, uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a complete Sensor Config packet in the provided buffer.
bool parse_environmental_data_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out, EnvironmentalDataPacket &data_out)
Parses an Environmental Data packet from buffer.
size_t create_self_test_packet(uint8_t adc_good, const std::vector< SelfTestResult > &results, uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a complete Self Test packet in the provided buffer.
bool parse_abort_done_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out)
Parses an Abort Done packet from buffer.
size_t create_actuator_config_packet(uint8_t is_abort_controller, const std::vector< AbortActuatorLocation > &abort_actuators, const std::vector< AbortPTLocation > &abort_pts, uint8_t enable_serial_printing, uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a complete Actuator Config packet in the provided buffer.
bool parse_actuator_config_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out, uint8_t &is_abort_controller_out, std::vector< AbortActuatorLocation > &abort_actuators_out, std::vector< AbortPTLocation > &abort_pts_out, uint8_t &enable_serial_printing_out)
Parses an Actuator Config packet from buffer.
bool parse_sensor_data_packet(const uint8_t *buffer, size_t buffer_size, PacketHeader &header_out, std::vector< SensorDataChunkCollection > &chunks_out)
Parses a Sensor Data packet from buffer into chunk collections.
size_t create_actuator_command_packet(const std::vector< ActuatorCommand > &commands, uint32_t timestamp_ms, uint8_t *buffer, size_t buffer_size)
Creates a complete Actuator Command packet in the provided buffer.
Represents a single data chunk with timestamp and sensor datapoints.
std::vector< SensorDatapoint > datapoints