Rework test mode to use normal LoRa batching and ACK flow
This commit is contained in:
19
src/main.cpp
19
src/main.cpp
@@ -11,7 +11,6 @@
|
||||
#include "receiver_pipeline.h"
|
||||
#include "sd_logger.h"
|
||||
#include "sender_state_machine.h"
|
||||
#include "test_mode.h"
|
||||
#include "time_manager.h"
|
||||
#include "web_server.h"
|
||||
#include "wifi_manager.h"
|
||||
@@ -136,24 +135,6 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#ifdef ENABLE_TEST_MODE
|
||||
if (g_role == DeviceRole::Sender) {
|
||||
test_sender_loop(g_short_id, g_device_id);
|
||||
display_tick();
|
||||
watchdog_kick();
|
||||
delay(50);
|
||||
} else {
|
||||
test_receiver_loop(g_receiver_shared.sender_statuses, NUM_SENDERS, g_short_id);
|
||||
mqtt_loop();
|
||||
web_server_loop();
|
||||
display_set_receiver_status(g_receiver_shared.ap_mode, wifi_is_connected() ? wifi_get_ssid().c_str() : "AP", mqtt_is_connected());
|
||||
display_tick();
|
||||
watchdog_kick();
|
||||
delay(50);
|
||||
}
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (g_role == DeviceRole::Sender) {
|
||||
g_sender_state_machine.loop();
|
||||
} else {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "display_ui.h"
|
||||
#include "json_codec.h"
|
||||
#include "lora_transport.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "payload_codec.h"
|
||||
@@ -77,6 +78,18 @@ static uint8_t bit_count32(uint32_t value) {
|
||||
return count;
|
||||
}
|
||||
|
||||
static bool mqtt_publish_sample(const MeterData &data) {
|
||||
#ifdef ENABLE_TEST_MODE
|
||||
String payload;
|
||||
if (!meterDataToJson(data, payload)) {
|
||||
return false;
|
||||
}
|
||||
return mqtt_publish_test(data.device_id, payload);
|
||||
#else
|
||||
return mqtt_publish_state(data);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct BatchRxState {
|
||||
bool active;
|
||||
uint16_t batch_id;
|
||||
@@ -470,7 +483,7 @@ static void receiver_loop() {
|
||||
|
||||
web_server_set_last_batch(static_cast<uint8_t>(sender_idx), samples, count);
|
||||
for (size_t s = 0; s < count; ++s) {
|
||||
mqtt_publish_state(samples[s]);
|
||||
mqtt_publish_sample(samples[s]);
|
||||
}
|
||||
g_sender_statuses[sender_idx].last_data = samples[count - 1];
|
||||
g_sender_statuses[sender_idx].last_update_ts_utc = samples[count - 1].ts_utc;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user