adjust batch ack timing and rename e_wh field

This commit is contained in:
2026-02-01 21:53:18 +01:00
parent 01f4494f00
commit d27b68c1cc
3 changed files with 40 additions and 4 deletions

View File

@@ -207,7 +207,7 @@ MeterBatch JSON (compressed over LoRa) uses per-field arrays with integer units
"t_last": 1738288030,
"dt_s": 1,
"n": 3,
"energy_wh": [123456700, 123456701, 123456701],
"e_wh": [123456700, 123456701, 123456701],
"p_w": [930, 940, 950],
"p1_w": [480, 490, 500],
"p2_w": [450, 450, 450],

View File

@@ -205,7 +205,7 @@ bool meterBatchToJson(const MeterData *samples, size_t count, uint16_t batch_id,
doc["bat_v"] = serialized(bat_buf);
}
JsonArray energy = doc.createNestedArray("energy_wh");
JsonArray energy = doc.createNestedArray("e_wh");
JsonArray p_w = doc.createNestedArray("p_w");
JsonArray p1_w = doc.createNestedArray("p1_w");
JsonArray p2_w = doc.createNestedArray("p2_w");
@@ -258,7 +258,7 @@ bool jsonToMeterBatch(const String &json, MeterData *out_samples, size_t max_cou
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;
JsonArray energy = doc["energy_wh"].as<JsonArray>();
JsonArray energy = doc["e_wh"].as<JsonArray>();
JsonArray p_w = doc["p_w"].as<JsonArray>();
JsonArray p1_w = doc["p1_w"].as<JsonArray>();
JsonArray p2_w = doc["p2_w"].as<JsonArray>();

View File

@@ -81,6 +81,7 @@ 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 bool g_batch_ack_pending = false;
static uint32_t g_batch_ack_timeout_ms = BATCH_ACK_TIMEOUT_MS;
static MeterData g_inflight_samples[METER_BATCH_MAX_SAMPLES];
static uint8_t g_inflight_count = 0;
static uint16_t g_inflight_batch_id = 0;
@@ -294,6 +295,17 @@ static uint32_t compute_batch_rx_timeout_ms(uint16_t total_len, uint8_t chunk_co
return timeout_ms < 10000 ? 10000 : timeout_ms;
}
static uint32_t compute_batch_ack_timeout_ms(size_t payload_len) {
if (payload_len == 0) {
return 10000;
}
uint8_t chunk_count = static_cast<uint8_t>((payload_len + BATCH_CHUNK_PAYLOAD - 1) / BATCH_CHUNK_PAYLOAD);
size_t packet_len = 5 + BATCH_HEADER_SIZE + (payload_len > BATCH_CHUNK_PAYLOAD ? BATCH_CHUNK_PAYLOAD : payload_len) + 2;
uint32_t per_chunk_toa_ms = lora_airtime_ms(packet_len);
uint32_t timeout_ms = static_cast<uint32_t>(chunk_count) * per_chunk_toa_ms + BATCH_RX_MARGIN_MS;
return timeout_ms < 10000 ? 10000 : timeout_ms;
}
static bool inject_batch_meta(String &json, int16_t rssi_dbm, float snr_db, uint32_t rx_ts_utc) {
DynamicJsonDocument doc(8192);
DeserializationError err = deserializeJson(doc, json);
@@ -423,6 +435,7 @@ static bool send_inflight_batch(uint32_t ts_for_display) {
if (SERIAL_DEBUG_MODE && compress_ms > 200) {
serial_debug_printf("tx: compress took %lums", static_cast<unsigned long>(compress_ms));
}
g_batch_ack_timeout_ms = compute_batch_ack_timeout_ms(compressed_len);
uint32_t send_start = millis();
bool ok = send_batch_payload(compressed, compressed_len, ts_for_display, g_inflight_batch_id);
@@ -668,6 +681,29 @@ static void sender_loop() {
send_meter_batch(last_sample_ts());
}
if (g_batch_ack_pending) {
uint32_t end_ms = millis() + 400;
while (millis() < end_ms) {
LoraPacket ack_pkt = {};
if (!lora_receive(ack_pkt, 0) || ack_pkt.protocol_version != PROTOCOL_VERSION) {
delay(5);
continue;
}
if (ack_pkt.payload_type == PayloadType::Ack && ack_pkt.payload_len >= 6 && ack_pkt.role == DeviceRole::Receiver) {
uint16_t ack_id = read_u16_le(ack_pkt.payload);
uint16_t ack_sender = read_u16_le(&ack_pkt.payload[2]);
uint16_t ack_receiver = read_u16_le(&ack_pkt.payload[4]);
if (ack_sender == g_short_id && ack_receiver == ack_pkt.device_id_short &&
g_batch_ack_pending && ack_id == g_last_sent_batch_id) {
g_last_acked_batch_id = ack_id;
serial_debug_printf("ack: ok batch_id=%u", ack_id);
finish_inflight_batch();
break;
}
}
}
}
LoraPacket rx = {};
if (lora_receive(rx, 0) && rx.protocol_version == PROTOCOL_VERSION) {
if (rx.payload_type == PayloadType::TimeSync) {
@@ -685,7 +721,7 @@ static void sender_loop() {
}
}
if (g_batch_ack_pending && (now_ms - g_last_batch_send_ms >= BATCH_ACK_TIMEOUT_MS)) {
if (g_batch_ack_pending && (now_ms - g_last_batch_send_ms >= g_batch_ack_timeout_ms)) {
if (g_batch_retry_count < BATCH_MAX_RETRIES) {
g_batch_retry_count++;
serial_debug_printf("ack: timeout batch_id=%u retry=%u", g_inflight_batch_id, g_batch_retry_count);