From 64afa8621e7cd8ccd3f6444caf632f1b8c272f82 Mon Sep 17 00:00:00 2001 From: acidburns Date: Fri, 13 Feb 2026 10:46:58 +0100 Subject: [PATCH] Remove auto-reboot and make timezone configurable --- README.md | 10 +++++++++- include/config.h | 1 + src/main.cpp | 14 -------------- src/time_manager.cpp | 22 ++++++++++++---------- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 4a76f01..9586a76 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,9 @@ Firmware for LilyGO T3 v1.6.1 (`ESP32 + SX1276 + SSD1306`) that runs as either: - Single codebase, role selected at boot via `detect_role()` (`include/config.h`, `src/config.cpp`). - LoRa link uses explicit CRC16 frame protection in firmware (`src/lora_transport.cpp`). - Sender batches up to `30` samples and retries on missing ACK (`BATCH_MAX_RETRIES=2`, retry policy `Keep`). +- Sender meter parsing is decoupled from LoRa ACK waits using a dedicated FreeRTOS reader task + queue (`src/main.cpp`). - Receiver uses STA mode when config is valid, otherwise AP fallback with web config. +- No debug auto-reboot timer is active in normal firmware loops. ## LoRa Frame Protocol (Current) @@ -54,12 +56,18 @@ Only after valid ACK time is received: This blocks pre-threshold timestamps from MQTT/SD paths. +Timezone handling: +- Local time rendering uses `TIMEZONE_TZ` from `include/config.h`. +- Default value is `CET-1CEST,M3.5.0/2,M10.5.0/3` and can be changed at compile time. + ## Sender Meter Path Implemented in `src/meter_driver.cpp` + sender loop in `src/main.cpp`: - UART: `Serial2`, RX pin `GPIO34` (`PIN_METER_RX`), `9600 7E1` -- Frame detection: starts at `'/'`, ends at `'!'`, timeout protection included +- ESP32 RX buffer is enlarged to `8192` bytes to survive long LoRa blocking sections. +- Frame detection: starts at `'/'`, ends at `'!'`, timeout protection included (`METER_FRAME_TIMEOUT_MS=20000`). +- Parsing runs in a dedicated sender task and is handed to the main sender loop via queue. - Parsed OBIS values: - `1-0:1.8.0` (total energy) - `1-0:16.7.0` (total power) diff --git a/include/config.h b/include/config.h index 3fff7ab..22fcb51 100644 --- a/include/config.h +++ b/include/config.h @@ -79,6 +79,7 @@ constexpr uint16_t SD_HISTORY_MAX_DAYS = 30; constexpr uint16_t SD_HISTORY_MIN_RES_MIN = 1; constexpr uint16_t SD_HISTORY_MAX_BINS = 4000; constexpr uint16_t SD_HISTORY_TIME_BUDGET_MS = 10; +constexpr const char *TIMEZONE_TZ = "CET-1CEST,M3.5.0/2,M10.5.0/3"; constexpr const char *AP_SSID_PREFIX = "DD3-Bridge-"; constexpr const char *AP_PASSWORD = "changeme123"; constexpr bool WEB_AUTH_REQUIRE_STA = true; diff --git a/src/main.cpp b/src/main.cpp index 3543549..e7f3163 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,8 +29,6 @@ static char g_device_id[16] = ""; static SenderStatus g_sender_statuses[NUM_SENDERS]; static bool g_ap_mode = false; static WifiMqttConfig g_cfg; -static uint32_t g_boot_ms = 0; -static bool g_debug_forced_reboot_done = false; static FaultCounters g_sender_faults = {}; static FaultCounters g_receiver_faults = {}; static FaultCounters g_receiver_faults_published = {}; @@ -121,7 +119,6 @@ static constexpr uint32_t METER_READER_TASK_STACK_WORDS = 4096; static constexpr UBaseType_t METER_READER_TASK_PRIORITY = 2; static constexpr BaseType_t METER_READER_TASK_CORE = 0; #endif -static constexpr uint32_t DEBUG_FORCED_REBOOT_INTERVAL_MS = 3UL * 60UL * 60UL * 1000UL; enum class TxBuildError : uint8_t { None = 0, @@ -937,7 +934,6 @@ void setup() { #endif watchdog_init(); - g_boot_ms = millis(); g_role = detect_role(); init_device_ids(g_short_id, g_device_id, sizeof(g_device_id)); display_set_role(g_role); @@ -1364,16 +1360,6 @@ receiver_loop_done: } void loop() { - if (SERIAL_DEBUG_MODE && !g_debug_forced_reboot_done && - (millis() - g_boot_ms >= DEBUG_FORCED_REBOOT_INTERVAL_MS)) { - g_debug_forced_reboot_done = true; - serial_debug_printf("debug: force reboot after %lu ms uptime", - static_cast(millis() - g_boot_ms)); -#ifdef ARDUINO_ARCH_ESP32 - delay(50); - esp_restart(); -#endif - } #ifdef ENABLE_TEST_MODE if (g_role == DeviceRole::Sender) { test_sender_loop(g_short_id, g_device_id); diff --git a/src/time_manager.cpp b/src/time_manager.cpp index 72f620b..6f0144c 100644 --- a/src/time_manager.cpp +++ b/src/time_manager.cpp @@ -1,4 +1,5 @@ #include "time_manager.h" +#include "config.h" #include static bool g_time_synced = false; @@ -12,15 +13,20 @@ static void note_last_sync(uint32_t epoch) { g_last_sync_utc = epoch; } +static void ensure_timezone_set() { + if (g_tz_set) { + return; + } + setenv("TZ", TIMEZONE_TZ, 1); + tzset(); + g_tz_set = true; +} + void time_receiver_init(const char *ntp_server_1, const char *ntp_server_2) { const char *server1 = (ntp_server_1 && ntp_server_1[0] != '\0') ? ntp_server_1 : "pool.ntp.org"; const char *server2 = (ntp_server_2 && ntp_server_2[0] != '\0') ? ntp_server_2 : "time.nist.gov"; configTime(0, 0, server1, server2); - if (!g_tz_set) { - setenv("TZ", "CET-1CEST,M3.5.0/2,M10.5.0/3", 1); - tzset(); - g_tz_set = true; - } + ensure_timezone_set(); } uint32_t time_get_utc() { @@ -40,11 +46,7 @@ bool time_is_synced() { } void time_set_utc(uint32_t epoch) { - if (!g_tz_set) { - setenv("TZ", "CET-1CEST,M3.5.0/2,M10.5.0/3", 1); - tzset(); - g_tz_set = true; - } + ensure_timezone_set(); struct timeval tv; tv.tv_sec = epoch; tv.tv_usec = 0;