refactor: move sender role logic into sender_state_machine

This commit is contained in:
2026-02-18 02:17:12 +01:00
parent 9d7f2ae076
commit 56960e05e2
3 changed files with 1604 additions and 16 deletions

View File

@@ -12,6 +12,7 @@
#include "display_ui.h" #include "display_ui.h"
#include "test_mode.h" #include "test_mode.h"
#include "sd_logger.h" #include "sd_logger.h"
#include "sender_state_machine.h"
#include <stdarg.h> #include <stdarg.h>
#include <math.h> #include <math.h>
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
@@ -151,6 +152,7 @@ enum class TxBuildError : uint8_t {
}; };
static TxBuildError g_last_tx_build_error = TxBuildError::None; static TxBuildError g_last_tx_build_error = TxBuildError::None;
static SenderStateMachine g_sender_state_machine;
static void watchdog_kick(); static void watchdog_kick();
static void finish_inflight_batch(); static void finish_inflight_batch();
@@ -1277,21 +1279,10 @@ void setup() {
display_set_self_ids(g_short_id, g_device_id); display_set_self_ids(g_short_id, g_device_id);
if (g_role == DeviceRole::Sender) { if (g_role == DeviceRole::Sender) {
power_sender_init(); SenderStateMachineConfig sender_cfg = {};
power_configure_unused_pins_sender(); sender_cfg.short_id = g_short_id;
meter_init(); sender_cfg.device_id = g_device_id;
#ifdef ARDUINO_ARCH_ESP32 g_sender_state_machine.begin(sender_cfg);
if (!meter_reader_start()) {
serial_debug_printf("meter: using inline polling fallback");
}
#endif
g_last_sample_ms = millis() - METER_SAMPLE_INTERVAL_MS;
g_last_send_ms = millis();
g_last_sync_request_ms = millis() - SYNC_REQUEST_INTERVAL_MS;
g_time_acquired = false;
g_sender_faults_reset_after_first_sync = false;
g_sender_faults_reset_hour_utc = UINT32_MAX;
update_battery_cache();
} else { } else {
power_receiver_init(); power_receiver_init();
lora_receive_continuous(); lora_receive_continuous();
@@ -1815,7 +1806,7 @@ void loop() {
#endif #endif
if (g_role == DeviceRole::Sender) { if (g_role == DeviceRole::Sender) {
sender_loop(); g_sender_state_machine.loop();
} else { } else {
receiver_loop(); receiver_loop();
} }

1553
src/sender_state_machine.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
#pragma once
#include <Arduino.h>
struct SenderStateMachineConfig {
uint16_t short_id;
const char *device_id;
};
struct SenderStats {
uint8_t queue_depth;
uint8_t build_count;
uint16_t inflight_batch_id;
uint16_t last_sent_batch_id;
uint16_t last_acked_batch_id;
uint8_t retry_count;
bool ack_pending;
uint32_t ack_timeout_total;
uint32_t ack_retry_total;
uint32_t ack_miss_streak;
uint32_t rx_window_ms;
uint32_t sleep_ms;
};
class SenderStateMachine {
public:
bool begin(const SenderStateMachineConfig &config);
void loop();
SenderStats stats() const;
private:
enum class State : uint8_t {
Syncing = 0,
Normal = 1,
Catchup = 2,
WaitAck = 3
};
void handleMeterRead(uint32_t now_ms);
void maybeSendBatch(uint32_t now_ms);
void handleAckWindow(uint32_t now_ms);
bool applyTimeFromAck(uint8_t time_valid, uint32_t ack_epoch);
void validateInvariants();
};