STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1/**
2 * Ball Valve Hotfire — motorized ball valve prototype board.
3 *
4 * Each valve has an enable line and a position readback:
5 *
6 * enable A pull-up holds the 4-20 mA driver's input at 5 V; an NMOS on
7 * the enable pin pulls it to 0 V. ACTUATOR_COMMAND state 1 leaves
8 * the NMOS off (pin LOW, 5 V to the driver: 20 mA, valve open);
9 * state 0 turns it on (pin HIGH, line pulled low: valve closed).
10 * position The valve's 4-20 mA position signal across a 100 ohm shunt
11 * (0.4-2.0 V) on an ADC1 pin, streamed to the server as
12 * SENSOR_DATA: raw 12-bit ADC counts, which is what daq_bridge
13 * and calibration_service read for an ACTUATOR board
14 * (V = counts / 4095 * 3.3; mA = V * 1000 / 100).
15 *
16 * State machine: WaitingForServer -> Active while SERVER_HEARTBEATs are
17 * current, back to WaitingForServer with every valve in SAFE_STATE (1, open)
18 * when they stop for HEARTBEAT_TIMEOUT_MS, and when an OTA starts. A command
19 * to SAFE_STATE is always obeyed; leaving it needs Active. Losing the ESP32's
20 * 3.3 V fails the same way: the NMOS gate drops and 5 V reaches the driver.
21 * Boot is 0 (closed), from the first instruction of setup(), as the gate
22 * pull-up holds it before the firmware runs. Position is streamed in both
23 * states.
24 *
25 * Prototype: pins are hardcoded below; two valves, actuator/sensor ids 1 and 2.
26 * The server's [boards.ball_valve_board] lists them as active_connectors
27 * [1, 2]. Networking, heartbeats, logs, firmware hash and Ethernet OTA match
28 * the hotfire boards (Actuator_Hotfire, common/).
29 */
30
31#include "main.h"
32
33#include <Arduino.h>
34#include <Ethernet.h>
35#include <EthernetUdp.h>
36#include <SPI.h>
37#include <STAR_EthernetOTA.h>
38#include <daq-protocol.h>
39#include <esp_mac.h>
40
41#include <cstring>
42#include <vector>
43
44#include "actuator_config.h"
45#include "board_net.h"
46#include "firmware_hash.h"
47
48//-----------------------------------------------------------------------------
49// Pin definitions — prototype, ESP32-WROOM-32
50//-----------------------------------------------------------------------------
51
52// W5500 Ethernet on the default VSPI pins
53static constexpr int ETH_CS = 5;
54static constexpr int ETH_MOSI = 23;
55static constexpr int ETH_SCLK = 18;
56static constexpr int ETH_MISO = 19;
57
58// Position readback samples averaged per reading; the ESP32 ADC is noisy
59static constexpr int POSITION_SAMPLES = 16;
60
61// Where every valve goes when the server is lost: 1 = 20 mA = open.
62static constexpr uint8_t SAFE_STATE = 1;
63
64struct Valve {
65 uint8_t actuator_id; // ACTUATOR_COMMAND id (1-based)
66 uint8_t sensor_id; // SENSOR_DATA id of its position readback
67 int enable_pin; // NMOS gate: LOW = state 1, HIGH = state 0
68 int position_pin; // ADC1 (GPIO32-39): 4-20 mA across a 100 ohm shunt
69 uint8_t state; // last state written to the pin
70};
71
72// Enable pins: neither GPIO25 nor GPIO14 is a strapping pin, and the 10k gate
73// pull-up to 3.3 V holds each valve at state 0 through boot and uploads.
74// GPIO14 (MTMS) may toggle for a few ms in the boot ROM, far shorter than a
75// valve stroke; setup() drives it HIGH (state 0) first thing. Avoid the
76// strapping pins (0, 2, 5, 12, 15), flash (6-11), UART0 (1, 3), the W5500
77// (5, 18, 19, 23) and the input-only 34-39.
78// Position pins: ADC1 only (GPIO32-39); ADC2 is shared with the radio.
79static Valve valves[] = {
80 {1, 1, 25, 32, 0},
81 {2, 2, 14, 35, 0},
82};
83static constexpr uint8_t NUM_VALVES = sizeof(valves) / sizeof(valves[0]);
84
85//-----------------------------------------------------------------------------
86// Board identity and network
87//-----------------------------------------------------------------------------
88static uint8_t board_id = 0; // from the DHCP-assigned address; see board_net.h
89static byte mac[6];
90static IPAddress gateway(0, 0, 0, 0);
91static IPAddress subnet(255, 255, 255, 0);
92static IPAddress dns(192, 168, 2, 1);
94static const int udpListenPort = 5005;
96static EthernetUDP udp;
99// False when no W5500 answered at boot. The Ethernet library then reads
100// garbage socket state and network calls can stall, so they are all skipped
101// and the valves stay at 0.
102static bool eth_present = false;
103
104#include "hotfire_log.h"
105bool g_verbose = true;
106
107//-----------------------------------------------------------------------------
108// State machine
109//-----------------------------------------------------------------------------
110enum class BallValveState : uint8_t {
111 WaitingForServer = 1, // SETUP
113};
114
116static unsigned long last_server_heartbeat_ms = 0;
117static unsigned long last_position_read_ms = 0;
118static unsigned long lastHeartbeatMillis = 0;
119
120static const char* stateName(BallValveState s) {
121 switch (s) {
123 return "WaitingForServer";
125 return "Active";
126 default:
127 return "?";
128 }
129}
130
131static void setState(BallValveState new_state) {
132 if (state != new_state) {
133 HF_LOG("State -> ");
134 HF_LOGLN(stateName(new_state));
135 Serial.flush();
136 state = new_state;
137 }
138}
139
140//-----------------------------------------------------------------------------
141// Valves
142//-----------------------------------------------------------------------------
143static Valve* findValve(uint8_t actuator_id) {
144 for (auto& v : valves)
145 if (v.actuator_id == actuator_id)
146 return &v;
147 return nullptr;
148}
149
150static void setValve(Valve& v, uint8_t new_state, const char* reason) {
151 digitalWrite(v.enable_pin, new_state ? LOW : HIGH);
152 if (v.state != new_state) {
153 v.state = new_state;
154 HF_LOG("[VALVE ");
155 HF_LOG(static_cast<unsigned>(v.actuator_id));
156 HF_LOG("] -> ");
157 HF_LOG(static_cast<unsigned>(new_state));
158 HF_LOG(" (");
159 HF_LOG(reason);
160 HF_LOGLN(")");
161 }
162}
163
164static void setAllValvesSafe(const char* reason) {
165 for (auto& v : valves)
166 setValve(v, SAFE_STATE, reason);
167}
168
170 const std::vector<daq::ActuatorCommand>& commands) {
171 for (const auto& cmd : commands) {
172 Valve* v = findValve(cmd.actuator_id);
173 if (v == nullptr)
174 continue;
175 uint8_t new_state = (cmd.actuator_state != 0) ? 1 : 0;
176 if (new_state == SAFE_STATE || state == BallValveState::Active) {
177 setValve(*v, new_state, "command");
178 } else {
179 HF_LOG("[VALVE ");
180 HF_LOG(static_cast<unsigned>(v->actuator_id));
181 HF_LOG("] ");
182 HF_LOG(static_cast<unsigned>(new_state));
183 HF_LOGLN(" ignored -- no current SERVER_HEARTBEAT");
184 }
185 }
186}
187
188/** Raw 12-bit ADC counts, averaged over POSITION_SAMPLES. */
189static uint32_t readPositionCounts(const Valve& v) {
190 uint32_t sum = 0;
191 for (int i = 0; i < POSITION_SAMPLES; i++)
192 sum += analogRead(v.position_pin);
193 return (sum + POSITION_SAMPLES / 2) / POSITION_SAMPLES;
194}
195
196//-----------------------------------------------------------------------------
197// Outgoing packets
198//-----------------------------------------------------------------------------
200 switch (state) {
204 default:
206 }
207}
208
209static void sendBoardHeartbeatTo(IPAddress dest_ip, int dest_port) {
210 daq::BoardHeartbeatPacket hb;
211 memcpy(hb.firmware_hash, FirmwareHash::get(), 32);
212 hb.board_id = board_id;
213 hb.engine_state = daq::EngineState::SAFE;
214 hb.board_state = getBoardStateForHeartbeat();
215
218 sizeof(packetBuffer));
219 if (len == 0)
220 return;
221
222 udp.beginPacket(dest_ip, dest_port);
223 udp.write(packetBuffer, len);
224 udp.endPacket();
225 HF_VERBOSE("Sent: heartbeat to ");
226 HF_VERBOSE(dest_ip);
227 HF_VERBOSE(":");
228 HF_VERBOSELN(dest_port);
229}
230
231static void sendPositions() {
233 for (const auto& v : valves)
234 chunk.add_datapoint(v.sensor_id, readPositionCounts(v));
235
237 std::vector<daq::SensorDataChunkCollection> chunks;
238 chunks.push_back(chunk);
241 if (len == 0)
242 return;
243
244 udp.beginPacket(serverIP, serverPort);
245 udp.write(packetBuffer, len);
246 udp.endPacket();
247 HF_VERBOSE("Sent: sensor_data to ");
249 HF_VERBOSE(":");
251}
252
253static void flushLogs() {
254 if (g_logbuf.empty())
255 return;
256 static uint8_t pkt[sizeof(daq::PacketHeader) + 3 + LOG_BUF_SIZE];
257 size_t n =
259 g_logbuf.length(), millis(), pkt, sizeof(pkt));
260 if (n > 0) {
261 udp.beginPacket(serverIP, serverPort);
262 udp.write(pkt, n);
263 udp.endPacket();
264 }
265 g_logbuf.clear();
266}
267
268//-----------------------------------------------------------------------------
269// Incoming packets
270//-----------------------------------------------------------------------------
271static void processIncomingPacket(const uint8_t* buffer, size_t len,
272 IPAddress remoteIP) {
273 if (len < sizeof(daq::PacketHeader))
274 return;
275 daq::PacketHeader hdr;
276 memcpy(&hdr, buffer, sizeof(hdr));
277
278 switch (hdr.packet_type) {
280 daq::PacketHeader dummy;
281 daq::ServerHeartbeatPacket data;
282 if (daq::parse_server_heartbeat_packet(buffer, len, dummy, data)) {
284#ifdef SENSOR_ETH_USE_DHCP
286#endif
288 }
289 break;
290 }
292 // Only the logging mode is used; this board takes no part in the
293 // abort sequence.
294 daq::PacketHeader dummy;
295 uint8_t is_controller = 0;
296 uint8_t enable_serial = 0;
297 std::vector<daq::AbortActuatorLocation> act_locs;
298 std::vector<daq::AbortPTLocation> pt_locs;
299 if (daq::parse_actuator_config_packet(buffer, len, dummy,
300 is_controller, act_locs,
301 pt_locs, enable_serial)) {
302 g_verbose = (enable_serial & 1);
304 (enable_serial >= 2) ? (enable_serial - 1) : 0;
305 }
306 break;
307 }
309 daq::PacketHeader dummy;
310 std::vector<daq::ActuatorCommand> commands;
311 if (daq::parse_actuator_command_packet(buffer, len, dummy,
312 commands))
314 break;
315 }
316 default:
317 break;
318 }
319}
320
321//-----------------------------------------------------------------------------
322// Setup and loop
323//-----------------------------------------------------------------------------
324
325/**
326 * An OTA blocks the loop until the board reboots, so the heartbeat watchdog
327 * cannot run: put every valve in SAFE_STATE first, then freeze our DHCP
328 * address for the duration of the flash.
329 */
330static void otaStart(void*, uint32_t) {
331 setAllValvesSafe("OTA starting");
333}
334
335/**
336 * Read the W5500's VERSIONR (common register 0x0039, always 0x04) straight
337 * over SPI and say what the answer implies, so a dead link can be traced to
338 * a wire without a logic analyser.
339 */
340static void probeW5500Version() {
341 SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
343 SPI.transfer(0x00); // address high
344 SPI.transfer(0x39); // address low: VERSIONR
345 SPI.transfer(0x00); // control: common block, read, variable length
346 uint8_t version = SPI.transfer(0x00);
348 SPI.endTransaction();
349
350 Serial.print("[ETH] W5500 VERSIONR read: 0x");
351 if (version < 0x10)
352 Serial.print("0");
353 Serial.print(version, HEX);
354 if (version == 0x04)
355 Serial.println(" -- chip answers; init failed, try a reset");
356 else if (version == 0x00)
357 Serial.println(
358 " -- MISO stuck low: check MISO (19), SCK (18), CS (5)"
359 " and the module's GND");
360 else if (version == 0xFF)
361 Serial.println(
362 " -- MISO floating/high: check MISO (19), CS (5) and"
363 " the module's 3.3 V");
364 else
365 Serial.println(" -- garbled: check MOSI (23), SCK (18), loose jumpers");
366}
367
368static void initializeValves() {
369 for (auto& v : valves) {
370 // Write the level before switching to OUTPUT so the pin never
371 // glitches LOW (= state 1) on the way.
372 digitalWrite(v.enable_pin, HIGH);
373 pinMode(v.enable_pin, OUTPUT);
374 v.state = 0;
375 pinMode(v.position_pin, INPUT);
376 analogSetPinAttenuation(v.position_pin, ADC_11db); // 0-3.3 V range
377 }
378}
379
380void setup() {
381 // First thing: every valve to 0 before anything that waits.
383
384 Serial.begin(115200);
387 Serial.println("Ball Valve Hotfire starting...");
388
389 ESP_ERROR_CHECK(esp_read_mac(mac, ESP_MAC_ETH));
392 SPI.begin(ETH_SCLK, ETH_MISO, ETH_MOSI, ETH_CS);
394 Ethernet.init(ETH_CS);
396#ifdef SENSOR_ETH_USE_DHCP
397 // The ground station decides our address, and our ID with it.
400#else
401 board_id = static_cast<uint8_t>(BOARD_ID);
402 Ethernet.begin(mac, IPAddress(192, 168, 2, board_id), dns, gateway, subnet);
403#endif
404 Serial.print("Board ID: ");
405 Serial.println(static_cast<unsigned>(board_id));
407
408 // Same prints as the other hotfire boards so the shared test-GUI serial
409 // parser understands this one too.
410 eth_present = Ethernet.hardwareStatus() == EthernetW5500;
411 Serial.println("[ETH] Ethernet initialized (SPI WIZnet)");
412 Serial.print("Address source: ");
413 Serial.println(BoardNet::sourceName(net.source));
414 Serial.print("Stack IP (Ethernet.localIP): ");
415 Serial.println(Ethernet.localIP());
416 Serial.print("Hardware: ");
417 Serial.println(eth_present ? "W5500"
418 : "no chip detected — check CS / SPI wiring. "
419 "Ethernet disabled; valves held at 0.");
420 if (!eth_present) {
422 } else {
423 Serial.print("Link status: ");
424 Serial.println(Ethernet.linkStatus() == LinkON ? "Connected"
425 : "Disconnected");
426 udp.begin(udpListenPort);
427 otaServer.onStart(otaStart);
428 otaServer.begin();
429 Serial.print("UDP listening on port ");
430 Serial.println(udpListenPort);
431 }
432
433 for (const auto& v : valves) {
434 Serial.print("Valve: actuator_id ");
435 Serial.print(static_cast<unsigned>(v.actuator_id));
436 Serial.print(" (GPIO");
437 Serial.print(v.enable_pin);
438 Serial.print("), position sensor_id ");
439 Serial.print(static_cast<unsigned>(v.sensor_id));
440 Serial.print(" (GPIO");
441 Serial.print(v.position_pin);
442 Serial.println("), state 0");
443 }
444 Serial.println("State -> WaitingForServer");
445 Serial.flush();
446
447 HF_LOG("ONLINE board=");
448 HF_LOG(static_cast<unsigned>(board_id));
449 HF_LOG(" ip=");
450 HF_LOG(Ethernet.localIP());
451 HF_LOGLN_();
452 if (eth_present)
453 flushLogs();
454}
455
456static void pollNetwork() {
457#ifdef SENSOR_ETH_USE_DHCP
458 // Renew the lease as it expires; no-op while an OTA is in flight.
460 // On the recovery address, keep asking; a lease brings our ID with it.
463 HF_LOG("ONLINE board=");
464 HF_LOG(static_cast<unsigned>(board_id));
465 HF_LOG(" ip=");
466 HF_LOG(Ethernet.localIP());
467 HF_LOGLN_();
468 flushLogs();
469 }
470#endif
471 // Blocks only if a client connects; never returns on success.
472 otaServer.poll();
474
475 int packetSize = udp.parsePacket();
476 if (packetSize > 0) {
477 IPAddress remoteIP = udp.remoteIP();
479 int bytesRead = udp.read(packetBuffer, sizeof(packetBuffer));
480 if (bytesRead > 0)
481 processIncomingPacket(packetBuffer, static_cast<size_t>(bytesRead),
482 remoteIP);
483 }
484
485#ifdef SENSOR_ETH_USE_DHCP
486 // Server gone quiet: forget it and resume discovery broadcasts. Our
487 // address stays; only the outbound destination resets.
489 net.serverLearned = false;
491 Serial.println("[NET] server silent -- resuming discovery");
492 Serial.flush();
493 }
494#endif
495
496 unsigned long now = millis();
500 }
501
505#ifdef SENSOR_ETH_USE_DHCP
506 // Discovery: announce to everyone until a server is learned.
507 if (!net.serverLearned)
508 sendBoardHeartbeatTo(IPAddress(255, 255, 255, 255),
510#endif
511 }
512
513 // Flush buffered logs to the server ~1 Hz (or sooner if filling).
514 static unsigned long s_last_log_flush_ms = 0;
515 if (!g_logbuf.empty() &&
516 (g_logbuf.nearFull() || now - s_last_log_flush_ms >= 1000)) {
517 s_last_log_flush_ms = now;
518 flushLogs();
519 }
520}
521
522void loop() {
523 // Failsafe: no current server heartbeat -> every valve to SAFE_STATE.
526 setAllValvesSafe("server heartbeat lost");
528 }
529
530 if (eth_present)
531 pollNetwork();
532
534}
static SerialStub Serial
Definition Arduino.h:128
#define INPUT
Definition Arduino.h:21
#define HIGH
Definition Arduino.h:19
void pinMode(int, int)
Definition Arduino.h:46
#define OUTPUT
Definition Arduino.h:22
unsigned long millis()
Definition Arduino.h:29
#define HEX
Definition Arduino.h:24
int analogRead(int)
Definition Arduino.h:53
#define LOW
Definition Arduino.h:20
void digitalWrite(int, int)
Definition Arduino.h:48
#define ETHERNET_INIT_DELAY_MS
#define LOOP_DELAY_MS
#define ETHERNET_BEGIN_DELAY_MS
#define HEARTBEAT_TIMEOUT_MS
#define ADC_READ_INTERVAL_MS
#define BOARD_HEARTBEAT_INTERVAL_MS
#define ETHERNET_SPI_DELAY_MS
static EthernetClass Ethernet
Definition Ethernet.h:116
#define MAX_PACKET_SIZE
Definition main.h:6
const int IPAddress
void delay(int ms)
static uint8_t chunk[64]
Definition board_uart9.c:12
The OTA listener.
void setup()
Definition main.cpp:142
void loop()
Definition main.cpp:201
std::vector< daq::SensorDataChunkCollection > chunks
Definition main.cpp:55
static unsigned long lastHeartbeatMillis
Definition main.cpp:81
static unsigned long last_server_heartbeat_ms
Definition main.cpp:59
const int serverPort
Definition main.cpp:38
const int udpListenPort
Definition main.cpp:37
IPAddress dns(192, 168, 2, 1)
byte mac[6]
Definition main.cpp:31
IPAddress subnet(255, 255, 255, 0)
IPAddress serverIP(192, 168, 2, 20)
static uint8_t board_id
Definition main.cpp:30
EthernetUDP udp
Definition main.cpp:40
IPAddress gateway(0, 0, 0, 0)
static ActuatorControllerState state
Definition main.cpp:57
static IPAddress subnet(255, 255, 255, 0)
static IPAddress gateway(192, 168, 2, 1)
StarOTA::Server otaServer(OTA_TCP_PORT)
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]
Definition main.cpp:15
IPAddress dns(192, 168, 2, 1)
bool g_verbose
Definition main.cpp:65
static BoardNet::State net
Definition main.cpp:57
static void sendBoardHeartbeatTo(IPAddress dest_ip, int dest_port)
Definition main.cpp:209
static void setValve(Valve &v, uint8_t new_state, const char *reason)
Definition main.cpp:150
static constexpr uint8_t SAFE_STATE
Definition main.cpp:62
static bool eth_present
Definition main.cpp:102
static void setState(BallValveState new_state)
Definition main.cpp:131
static Valve valves[]
Definition main.cpp:79
static void pollNetwork()
Definition main.cpp:456
static constexpr int ETH_CS
Ball Valve Hotfire — motorized ball valve prototype board.
Definition main.cpp:53
static uint32_t readPositionCounts(const Valve &v)
Raw 12-bit ADC counts, averaged over POSITION_SAMPLES.
Definition main.cpp:189
static void probeW5500Version()
Read the W5500's VERSIONR (common register 0x0039, always 0x04) straight over SPI and say what the an...
Definition main.cpp:340
static void setAllValvesSafe(const char *reason)
Definition main.cpp:164
static constexpr int POSITION_SAMPLES
Definition main.cpp:59
static unsigned long last_position_read_ms
Definition main.cpp:117
static const char * stateName(BallValveState s)
Definition main.cpp:120
static void otaStart(void *, uint32_t)
An OTA blocks the loop until the board reboots, so the heartbeat watchdog cannot run: put every valve...
Definition main.cpp:330
static void initializeValves()
Definition main.cpp:368
static void processIncomingPacket(const uint8_t *buffer, size_t len, IPAddress remoteIP)
Definition main.cpp:271
static constexpr int ETH_SCLK
Definition main.cpp:55
static Valve * findValve(uint8_t actuator_id)
Definition main.cpp:143
static constexpr int ETH_MISO
Definition main.cpp:56
static constexpr int ETH_MOSI
Definition main.cpp:54
static void processActuatorCommands(const std::vector< daq::ActuatorCommand > &commands)
Definition main.cpp:169
BallValveState
Definition main.cpp:110
static constexpr uint8_t NUM_VALVES
Definition main.cpp:83
static daq::BoardState getBoardStateForHeartbeat()
Definition main.cpp:199
static void sendPositions()
Definition main.cpp:231
static IPAddress serverIP(192, 168, 2, HOTFIRE_SERVER_IP_OCTET_4)
static void flushLogs()
Definition main.cpp:253
#define HOTFIRE_SERVER_PORT
#define HOTFIRE_SERVER_IP_OCTET_4
#define HOTFIRE_OTA_PORT
#define BOARD_ID
#define SERIAL_MONITOR_READY_DELAY_MS
LogBuffer g_logbuf
Definition hotfire_log.h:93
uint8_t g_log_stream_level
Definition hotfire_log.h:94
#define LOG_BUF_SIZE
Definition hotfire_log.h:42
#define HF_VERBOSE(...)
#define HF_LOG(...)
Definition hotfire_log.h:99
#define HF_VERBOSELN(...)
#define HF_LOGLN_()
#define HF_LOGLN(...)
static osMessageQueueId_t commands
Definition idle_task.c:28
void configure(State &s, const byte mac[6])
Definition board_net.h:93
AddressSource begin(State &s, IPAddress dns, IPAddress gateway)
Bring the interface up: ask the ground station for an address, and take the recovery address only if ...
Definition board_net.h:181
void printMac(const State &s)
Print the MAC as aa:bb:cc:dd:ee:ff.
Definition board_net.h:103
uint8_t boardId(const State &s)
The board's ID: the last octet of the address the server assigned (192.168.2.31 -> 31).
Definition board_net.h:129
void beginOtaHold(State &s)
Called when an OTA transfer starts, so the address cannot move under it.
Definition board_net.h:144
bool retryDhcp(State &s, IPAddress dns, IPAddress gateway)
On the recovery address, ask for a lease again every SENSOR_ETH_DHCP_RETRY_INTERVAL_MS.
Definition board_net.h:213
bool serverWentSilent(const State &s)
Server has stopped talking — forget it and resume discovery broadcasts.
Definition board_net.h:166
bool onServerPacket(State &s, IPAddress remote_ip, IPAddress &serverIP)
A server packet arrived from remote_ip; adopt it as the server address.
Definition board_net.h:152
void maintainLease(State &s)
Renew the lease as it expires.
Definition board_net.h:138
const char * sourceName(AddressSource s)
Definition board_net.h:52
const uint8_t * get()
void printTestMessage()
Bench-test helper: prints STAR_OTA_TEST_MESSAGE on a timer as.
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.
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.
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.
BoardState
Defines the operational state of a board.
Definition DiabloEnums.h:31
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.
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.
*brief user defined string literal for JSON values *sa std::size_t n
Definition json.hpp:24474
Definition main.cpp:64
uint8_t state
Definition main.cpp:69
int position_pin
Definition main.cpp:68
uint8_t actuator_id
Definition main.cpp:65
int enable_pin
Definition main.cpp:67
uint8_t sensor_id
Definition main.cpp:66
Represents a single data chunk with timestamp and sensor datapoints.