From e21d0cee837b03e6f4ef392426cdc14e59724c99 Mon Sep 17 00:00:00 2001 From: jgruen Date: Tue, 7 Jan 2025 00:40:27 -0800 Subject: [PATCH] Avoid using wall time in case it jumps. (#3) Instead, use std::chrono's steady_clock. --- .../emporia_vue_utility.cpp | 26 ++++++------------ .../emporia_vue_utility/emporia_vue_utility.h | 27 ++++++++++++------- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/esphome/components/emporia_vue_utility/emporia_vue_utility.cpp b/esphome/components/emporia_vue_utility/emporia_vue_utility.cpp index b6fa6f3..ca3b1d5 100644 --- a/esphome/components/emporia_vue_utility/emporia_vue_utility.cpp +++ b/esphome/components/emporia_vue_utility/emporia_vue_utility.cpp @@ -24,27 +24,17 @@ void EmporiaVueUtility::update() { } void EmporiaVueUtility::loop() { - static const time_t delayed_start_time = - ::time(nullptr) + INITIAL_STARTUP_DELAY; - static time_t next_expected_meter_request = 0; - static time_t next_meter_join = delayed_start_time + METER_REJOIN_INTERVAL; - static time_t next_version_request = 0; + static const steady_time_point delayed_start_time = + steady_clock::now() + INITIAL_STARTUP_DELAY; + static steady_time_point next_expected_meter_request = min_steady_time_point; + static steady_time_point next_meter_join = delayed_start_time + METER_REJOIN_INTERVAL; + static steady_time_point next_version_request = min_steady_time_point; static uint8_t startup_step = 0; char msg_type = 0; size_t msg_len = 0; msg_len = read_msg(); - now = ::time(nullptr); - - /* sanity checks! */ - if (next_expected_meter_request > - now + (INITIAL_STARTUP_DELAY + METER_REJOIN_INTERVAL)) { - ESP_LOGD(TAG, "Time jumped back (%lld > %lld + %lld); resetting", - (long long)next_expected_meter_request, (long long)now, - (long long)(INITIAL_STARTUP_DELAY + METER_REJOIN_INTERVAL)); - next_meter_join = 0; - next_expected_meter_request = now + update_interval_; - } + now = steady_clock::now(); if (msg_len != 0) { msg_type = input_buffer.data[2]; @@ -52,7 +42,7 @@ void EmporiaVueUtility::loop() { switch (msg_type) { case 'r': // Meter reading led_link(true); - if (now < last_meter_reading + int(update_interval_ / 4)) { + if (now < (last_meter_reading + update_interval_ / 4)) { // Sometimes a duplicate message is sent in quick succession. // Ignoring the duplicate. ESP_LOGD(TAG, "Got extra message %lds after the previous message.", @@ -159,4 +149,4 @@ void EmporiaVueUtility::dump_config() { LOG_UPDATE_INTERVAL(this); } } // namespace emporia_vue_utility -} // namespace esphome \ No newline at end of file +} // namespace esphome diff --git a/esphome/components/emporia_vue_utility/emporia_vue_utility.h b/esphome/components/emporia_vue_utility/emporia_vue_utility.h index f5af6d0..9d16d0c 100644 --- a/esphome/components/emporia_vue_utility/emporia_vue_utility.h +++ b/esphome/components/emporia_vue_utility/emporia_vue_utility.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "driver/gpio.h" #include "esphome/components/sensor/sensor.h" @@ -24,13 +26,13 @@ // How often to attempt to re-join the meter when it hasn't // been returning readings -#define METER_REJOIN_INTERVAL 30 +#define METER_REJOIN_INTERVAL std::chrono::seconds(30) // How often to attempt to re-request the MGM firmware version. -#define MGM_FIRMWARE_REQUEST_INTERVAL 3 +#define MGM_FIRMWARE_REQUEST_INTERVAL std::chrono::seconds(3) // On first startup, how long before trying to start to talk to meter -#define INITIAL_STARTUP_DELAY 10 +#define INITIAL_STARTUP_DELAY std::chrono::seconds(10) // Should this code manage the "wifi" and "link" LEDs? // set to false if you want manually manage them elsewhere @@ -126,9 +128,14 @@ class EmporiaVueUtility : public PollingComponent, public uart::UARTDevice { uint16_t pos = 0; uint16_t data_len; - time_t last_meter_reading = 0; + using steady_time_point = std::chrono::time_point; + static constexpr steady_time_point min_steady_time_point = + steady_time_point::min(); + using steady_clock = std::chrono::steady_clock; + + steady_time_point last_meter_reading = min_steady_time_point; bool last_reading_has_error; - time_t now; + steady_time_point now; // The most recent meter divisor, meter reading payload V2 byte 47 uint8_t meter_div = 0; @@ -139,7 +146,7 @@ class EmporiaVueUtility : public PollingComponent, public uart::UARTDevice { void set_debug(bool enable) { debug_ = enable; } void set_update_interval(uint32_t update_interval) { PollingComponent::set_update_interval(update_interval); - update_interval_ = update_interval / 1000; + update_interval_ = std::chrono::milliseconds(update_interval); } void set_power_sensor(sensor::Sensor *sensor) { power_sensor_ = sensor; } void set_power_export_sensor(sensor::Sensor *sensor) { @@ -311,7 +318,7 @@ class EmporiaVueUtility : public PollingComponent, public uart::UARTDevice { // Extra debugging of non-zero bytes, only on first packet or if // debug_ is true - if ((debug_) || (last_meter_reading == 0)) { + if ((debug_) || (last_meter_reading == min_steady_time_point)) { ESP_LOGD(TAG, "Meter Divisor: %d", meter_div); ESP_LOGD(TAG, "Meter Cost Unit: %d", cost_unit); ESP_LOGD(TAG, "Meter Flags: %02x %02x", mr2->maybe_flags[0], @@ -356,7 +363,7 @@ class EmporiaVueUtility : public PollingComponent, public uart::UARTDevice { // Extra debugging of non-zero bytes, only on first packet or if // debug_ is true - if ((debug_) || (last_meter_reading == 0)) { + if ((debug_) || (last_meter_reading == min_steady_time_point)) { ESP_LOGD(TAG, "Meter Cost Unit: %d", cost_unit); ESP_LOGD(TAG, "Meter Divisor: %d", meter_div); ESP_LOGD(TAG, "Meter Energy Import Flags: %08x", mr7->import_wh); @@ -777,7 +784,7 @@ class EmporiaVueUtility : public PollingComponent, public uart::UARTDevice { private: bool debug_ = false; - uint32_t update_interval_; + steady_clock::duration update_interval_; sensor::Sensor *power_sensor_{nullptr}; sensor::Sensor *power_export_sensor_{nullptr}; sensor::Sensor *power_import_sensor_{nullptr}; @@ -788,4 +795,4 @@ class EmporiaVueUtility : public PollingComponent, public uart::UARTDevice { }; } // namespace emporia_vue_utility -} // namespace esphome \ No newline at end of file +} // namespace esphome