Rework test mode to use normal LoRa batching and ACK flow

This commit is contained in:
2026-02-20 20:42:06 +01:00
parent 1169eab626
commit ae5b4a940a
3 changed files with 65 additions and 20 deletions
+51
View File
@@ -145,6 +145,10 @@ static uint32_t g_build_invalid = 0;
static constexpr uint32_t METER_SAMPLE_MAX_AGE_MS = 15000;
static constexpr uint32_t METER_TIME_DELTA_TOLERANCE_S = 2;
static constexpr int64_t METER_TIME_ANCHOR_DRIFT_TOLERANCE_S = 2;
#ifdef ENABLE_TEST_MODE
static uint32_t g_test_meter_last_emit_ms = 0;
static uint32_t g_test_meter_tick = 0;
#endif
struct MeterSampleEvent {
MeterData data;
@@ -350,6 +354,27 @@ static bool parse_meter_frame_sample(const char *frame, size_t frame_len, MeterD
return meter_parse_frame(frame, frame_len, parsed);
}
#ifdef ENABLE_TEST_MODE
static bool generate_test_meter_sample(uint32_t now_ms, MeterData &parsed) {
if (g_test_meter_last_emit_ms != 0 && now_ms - g_test_meter_last_emit_ms < METER_SAMPLE_INTERVAL_MS) {
return false;
}
g_test_meter_last_emit_ms = now_ms;
g_test_meter_tick++;
parsed = {};
parsed.valid = true;
parsed.meter_seconds_valid = true;
parsed.meter_seconds = MIN_ACCEPTED_EPOCH_UTC + g_test_meter_tick;
parsed.energy_total_kwh = static_cast<float>(g_test_meter_tick) / 1000.0f; // 1 Wh step per sample.
parsed.phase_power_w[0] = static_cast<float>(g_test_meter_tick);
parsed.phase_power_w[1] = static_cast<float>(g_test_meter_tick);
parsed.phase_power_w[2] = static_cast<float>(g_test_meter_tick);
parsed.total_power_w = parsed.phase_power_w[0] + parsed.phase_power_w[1] + parsed.phase_power_w[2];
return true;
}
#endif
#ifdef ARDUINO_ARCH_ESP32
static void meter_queue_push_latest(const MeterSampleEvent &event) {
if (!g_meter_sample_queue) {
@@ -374,6 +399,20 @@ static void meter_queue_push_latest(const MeterSampleEvent &event) {
static void meter_reader_task_entry(void *arg) {
(void)arg;
for (;;) {
#ifdef ENABLE_TEST_MODE
MeterData test_sample = {};
uint32_t now_ms = millis();
if (!generate_test_meter_sample(now_ms, test_sample)) {
vTaskDelay(pdMS_TO_TICKS(5));
continue;
}
MeterSampleEvent event = {};
event.data = test_sample;
event.rx_ms = now_ms;
meter_queue_push_latest(event);
continue;
#endif
const char *frame = nullptr;
size_t frame_len = 0;
if (!meter_poll_frame(frame, frame_len)) {
@@ -438,6 +477,14 @@ static void meter_reader_pump(uint32_t now_ms) {
}
#endif
#ifdef ENABLE_TEST_MODE
MeterData test_sample = {};
if (generate_test_meter_sample(now_ms, test_sample)) {
set_last_meter_sample(test_sample, now_ms);
}
return;
#endif
const char *frame = nullptr;
size_t frame_len = 0;
if (!meter_poll_frame(frame, frame_len)) {
@@ -1498,6 +1545,10 @@ bool SenderStateMachine::begin(const SenderStateMachineConfig &config) {
g_time_acquired = false;
g_sender_faults_reset_after_first_sync = false;
g_sender_faults_reset_hour_utc = UINT32_MAX;
#ifdef ENABLE_TEST_MODE
g_test_meter_last_emit_ms = 0;
g_test_meter_tick = 0;
#endif
update_battery_cache();
sender_transition(SenderPhase::Syncing, "begin");
return true;