Add sender queue display and batch timing
This commit is contained in:
@@ -11,6 +11,8 @@ void display_set_sender_statuses(const SenderStatus *statuses, uint8_t count);
|
|||||||
void display_set_last_meter(const MeterData &data);
|
void display_set_last_meter(const MeterData &data);
|
||||||
void display_set_last_read(bool ok, uint32_t ts_utc);
|
void display_set_last_read(bool ok, uint32_t ts_utc);
|
||||||
void display_set_last_tx(bool ok, uint32_t ts_utc);
|
void display_set_last_tx(bool ok, uint32_t ts_utc);
|
||||||
|
void display_set_sender_queue(uint8_t depth, bool build_pending);
|
||||||
|
void display_set_sender_batches(uint16_t last_acked_batch_id, uint16_t current_batch_id);
|
||||||
void display_set_last_error(FaultType type, uint32_t ts_utc, uint32_t ts_ms);
|
void display_set_last_error(FaultType type, uint32_t ts_utc, uint32_t ts_ms);
|
||||||
void display_set_receiver_status(bool ap_mode, const char *ssid, bool mqtt_ok);
|
void display_set_receiver_status(bool ap_mode, const char *ssid, bool mqtt_ok);
|
||||||
void display_power_down();
|
void display_power_down();
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ static uint32_t g_last_read_ts = 0;
|
|||||||
static uint32_t g_last_tx_ts = 0;
|
static uint32_t g_last_tx_ts = 0;
|
||||||
static uint32_t g_last_read_ms = 0;
|
static uint32_t g_last_read_ms = 0;
|
||||||
static uint32_t g_last_tx_ms = 0;
|
static uint32_t g_last_tx_ms = 0;
|
||||||
|
static uint8_t g_sender_queue_depth = 0;
|
||||||
|
static bool g_sender_build_pending = false;
|
||||||
|
static uint16_t g_sender_last_acked_batch_id = 0;
|
||||||
|
static uint16_t g_sender_current_batch_id = 0;
|
||||||
static FaultType g_last_error = FaultType::None;
|
static FaultType g_last_error = FaultType::None;
|
||||||
static uint32_t g_last_error_ts = 0;
|
static uint32_t g_last_error_ts = 0;
|
||||||
static uint32_t g_last_error_ms = 0;
|
static uint32_t g_last_error_ms = 0;
|
||||||
@@ -111,6 +115,16 @@ void display_set_last_tx(bool ok, uint32_t ts_utc) {
|
|||||||
g_last_tx_ms = millis();
|
g_last_tx_ms = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void display_set_sender_queue(uint8_t depth, bool build_pending) {
|
||||||
|
g_sender_queue_depth = depth;
|
||||||
|
g_sender_build_pending = build_pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_set_sender_batches(uint16_t last_acked_batch_id, uint16_t current_batch_id) {
|
||||||
|
g_sender_last_acked_batch_id = last_acked_batch_id;
|
||||||
|
g_sender_current_batch_id = current_batch_id;
|
||||||
|
}
|
||||||
|
|
||||||
void display_set_last_error(FaultType type, uint32_t ts_utc, uint32_t ts_ms) {
|
void display_set_last_error(FaultType type, uint32_t ts_utc, uint32_t ts_ms) {
|
||||||
g_last_error = type;
|
g_last_error = type;
|
||||||
g_last_error_ts = ts_utc;
|
g_last_error_ts = ts_utc;
|
||||||
@@ -195,7 +209,13 @@ static void render_sender_status() {
|
|||||||
display.printf("Read %s %lus ago", g_last_read_ok ? "OK" : "ERR", static_cast<unsigned long>(age_seconds(g_last_read_ts, g_last_read_ms)));
|
display.printf("Read %s %lus ago", g_last_read_ok ? "OK" : "ERR", static_cast<unsigned long>(age_seconds(g_last_read_ts, g_last_read_ms)));
|
||||||
|
|
||||||
display.setCursor(0, 36);
|
display.setCursor(0, 36);
|
||||||
display.printf("TX %s %lus ago", g_last_tx_ok ? "OK" : "ERR", static_cast<unsigned long>(age_seconds(g_last_tx_ts, g_last_tx_ms)));
|
display.printf("TX %s %lus Q%u%s A%u C%u",
|
||||||
|
g_last_tx_ok ? "OK" : "ERR",
|
||||||
|
static_cast<unsigned long>(age_seconds(g_last_tx_ts, g_last_tx_ms)),
|
||||||
|
g_sender_queue_depth,
|
||||||
|
g_sender_build_pending ? "+" : "",
|
||||||
|
g_sender_last_acked_batch_id,
|
||||||
|
g_sender_current_batch_id);
|
||||||
|
|
||||||
#ifdef ENABLE_TEST_MODE
|
#ifdef ENABLE_TEST_MODE
|
||||||
if (strlen(g_test_code) > 0) {
|
if (strlen(g_test_code) > 0) {
|
||||||
|
|||||||
@@ -183,6 +183,8 @@ bool meterBatchToJson(const MeterData *samples, size_t count, uint16_t batch_id,
|
|||||||
doc["sender"] = sender_label;
|
doc["sender"] = sender_label;
|
||||||
doc["batch_id"] = batch_id;
|
doc["batch_id"] = batch_id;
|
||||||
doc["t0"] = samples[0].ts_utc;
|
doc["t0"] = samples[0].ts_utc;
|
||||||
|
doc["t_first"] = samples[0].ts_utc;
|
||||||
|
doc["t_last"] = samples[count - 1].ts_utc;
|
||||||
uint32_t dt_s = METER_SAMPLE_INTERVAL_MS / 1000;
|
uint32_t dt_s = METER_SAMPLE_INTERVAL_MS / 1000;
|
||||||
doc["dt_s"] = dt_s > 0 ? dt_s : 1;
|
doc["dt_s"] = dt_s > 0 ? dt_s : 1;
|
||||||
doc["n"] = static_cast<uint32_t>(count);
|
doc["n"] = static_cast<uint32_t>(count);
|
||||||
@@ -247,6 +249,8 @@ bool jsonToMeterBatch(const String &json, MeterData *out_samples, size_t max_cou
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t t0 = doc["t0"] | 0;
|
uint32_t t0 = doc["t0"] | 0;
|
||||||
|
uint32_t t_first = doc["t_first"] | t0;
|
||||||
|
uint32_t t_last = doc["t_last"] | t_first;
|
||||||
uint32_t dt_s = doc["dt_s"] | 1;
|
uint32_t dt_s = doc["dt_s"] | 1;
|
||||||
JsonArray energy = doc["energy_wh"].as<JsonArray>();
|
JsonArray energy = doc["energy_wh"].as<JsonArray>();
|
||||||
JsonArray p_w = doc["p_w"].as<JsonArray>();
|
JsonArray p_w = doc["p_w"].as<JsonArray>();
|
||||||
@@ -268,7 +272,13 @@ bool jsonToMeterBatch(const String &json, MeterData *out_samples, size_t max_cou
|
|||||||
snprintf(data.device_id, sizeof(data.device_id), "dd3-0000");
|
snprintf(data.device_id, sizeof(data.device_id), "dd3-0000");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count > 1 && t_last >= t_first) {
|
||||||
|
uint32_t span = t_last - t_first;
|
||||||
|
uint32_t step = span / static_cast<uint32_t>(count - 1);
|
||||||
|
data.ts_utc = t_first + static_cast<uint32_t>(idx) * step;
|
||||||
|
} else {
|
||||||
data.ts_utc = t0 + static_cast<uint32_t>(idx) * dt_s;
|
data.ts_utc = t0 + static_cast<uint32_t>(idx) * dt_s;
|
||||||
|
}
|
||||||
data.energy_total_kwh = static_cast<float>((energy[idx] | 0)) / 1000.0f;
|
data.energy_total_kwh = static_cast<float>((energy[idx] | 0)) / 1000.0f;
|
||||||
data.total_power_w = static_cast<float>(p_w[idx] | 0);
|
data.total_power_w = static_cast<float>(p_w[idx] | 0);
|
||||||
data.phase_power_w[0] = static_cast<float>(p1_w[idx] | 0);
|
data.phase_power_w[0] = static_cast<float>(p1_w[idx] | 0);
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ static uint8_t g_last_battery_percent = 0;
|
|||||||
static uint32_t g_last_battery_ms = 0;
|
static uint32_t g_last_battery_ms = 0;
|
||||||
static uint16_t g_batch_id = 1;
|
static uint16_t g_batch_id = 1;
|
||||||
static uint16_t g_last_sent_batch_id = 0;
|
static uint16_t g_last_sent_batch_id = 0;
|
||||||
|
static uint16_t g_last_acked_batch_id = 0;
|
||||||
static uint8_t g_batch_retry_count = 0;
|
static uint8_t g_batch_retry_count = 0;
|
||||||
static bool g_batch_ack_pending = false;
|
static bool g_batch_ack_pending = false;
|
||||||
static MeterData g_inflight_samples[METER_BATCH_MAX_SAMPLES];
|
static MeterData g_inflight_samples[METER_BATCH_MAX_SAMPLES];
|
||||||
@@ -542,6 +543,8 @@ void setup() {
|
|||||||
static void sender_loop() {
|
static void sender_loop() {
|
||||||
watchdog_kick();
|
watchdog_kick();
|
||||||
uint32_t now_ms = millis();
|
uint32_t now_ms = millis();
|
||||||
|
display_set_sender_queue(g_batch_count, g_build_count > 0);
|
||||||
|
display_set_sender_batches(g_last_acked_batch_id, g_batch_id);
|
||||||
|
|
||||||
if (now_ms - g_last_sample_ms >= METER_SAMPLE_INTERVAL_MS) {
|
if (now_ms - g_last_sample_ms >= METER_SAMPLE_INTERVAL_MS) {
|
||||||
g_last_sample_ms = now_ms;
|
g_last_sample_ms = now_ms;
|
||||||
@@ -589,6 +592,7 @@ static void sender_loop() {
|
|||||||
uint16_t ack_receiver = read_u16_le(&rx.payload[4]);
|
uint16_t ack_receiver = read_u16_le(&rx.payload[4]);
|
||||||
if (ack_sender == g_short_id && ack_receiver == rx.device_id_short &&
|
if (ack_sender == g_short_id && ack_receiver == rx.device_id_short &&
|
||||||
g_batch_ack_pending && ack_id == g_last_sent_batch_id) {
|
g_batch_ack_pending && ack_id == g_last_sent_batch_id) {
|
||||||
|
g_last_acked_batch_id = ack_id;
|
||||||
finish_inflight_batch();
|
finish_inflight_batch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user