From 44a0050cf1fcea40c459ee46322bce098bd48981 Mon Sep 17 00:00:00 2001 From: jgruen Date: Sun, 28 Jan 2024 18:39:50 -0800 Subject: [PATCH] Handle time going backwards, and net consumption never going decreasing (#11) * Add W_consumed and W_returned Sensors for solar If a solar customer is not yet on _net metering_, then the kWh_net Sensor will never decrease (i.e., meter does _not_ run backwards). This means that kWh_returned will always be zero, even though power _is_ flowing back to the grid (though the customer is not being credited for it). For visualizing in e.g. Home Assistant's Energy dashboard, we therefore export the Watts flowing in either direction (to or from the grid) so that integral helpers/sensors/entities can be used to show the _actual_ energy flow to and from the grid (again, even though the customer is not being credited (yet?) on the meter / bill). * disambiguate `time()` if e.g. using the ESPHome `time` component * handle time jumping backwards --- src/emporia_vue_utility.h | 26 +++++++++++++++++++++++-- src/vue-utility-solar.yaml | 40 +++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/emporia_vue_utility.h b/src/emporia_vue_utility.h index 729afb4..50e63ac 100644 --- a/src/emporia_vue_utility.h +++ b/src/emporia_vue_utility.h @@ -47,7 +47,9 @@ class EmporiaVueUtility : public Component, public UARTDevice { Sensor *kWh_net = new Sensor(); Sensor *kWh_consumed = new Sensor(); Sensor *kWh_returned = new Sensor(); - Sensor *W = new Sensor(); + Sensor *W = new Sensor(); + Sensor *W_consumed = new Sensor(); + Sensor *W_returned = new Sensor(); const char *TAG = "Vue"; @@ -428,6 +430,13 @@ class EmporiaVueUtility : public Component, public UARTDevice { last_reading_has_error = 1; } else { W->publish_state(watts); + if (watts > 0) { + W_consumed->publish_state(watts); + W_returned->publish_state(0); + } else { + W_consumed->publish_state(0); + W_returned->publish_state(-watts); + } } return(watts); } @@ -555,7 +564,20 @@ class EmporiaVueUtility : public Component, public UARTDevice { byte inb; msg_len = read_msg(); - now = time(&now); + now = ::time(&now); + + /* sanity checks! */ + if (next_meter_request > + now + (INITIAL_STARTUP_DELAY + METER_REJOIN_INTERVAL)) { + ESP_LOGD(TAG, + "Time jumped back (%lld > %lld + %lld); resetting", + (long long) next_meter_request, + (long long) now, + (long long) (INITIAL_STARTUP_DELAY + + METER_REJOIN_INTERVAL)); + next_meter_request = next_meter_join = 0; + } + if (msg_len != 0) { msg_type = input_buffer.data[2]; diff --git a/src/vue-utility-solar.yaml b/src/vue-utility-solar.yaml index 737d0be..0bf5852 100644 --- a/src/vue-utility-solar.yaml +++ b/src/vue-utility-solar.yaml @@ -42,7 +42,7 @@ sensor: lambda: |- auto vue = new EmporiaVueUtility(id(emporia_uart)); App.register_component(vue); - return {vue->kWh_consumed, vue->kWh_returned, vue->W, vue->kWh_net}; + return {vue->kWh_consumed, vue->kWh_returned, vue->W_consumed, vue->W_returned, vue->W, vue->kWh_net}; sensors: - name: "kWh Consumed" id: kWh_consumed @@ -88,6 +88,44 @@ sensor: lambda: |- ESP_LOGI("Vue", "kWh = %0.3f", x); + - name: "Watts consumed" + id: watts_consumed + unit_of_measurement: "W" + accuracy_decimals: 0 + state_class: measurement + device_class: power + # Report every 5 minutes or when +/- 20 watts + filters: + - or: + - throttle: 5min + - delta: 20 # <- watts + - lambda: |- + if (id(fast_reporting)) return(x); + return {}; + on_raw_value: + then: + lambda: |- + ESP_LOGI("Vue", "Watts consumed = %0.3f", x); + + - name: "Watts returned" + id: watts_returned + unit_of_measurement: "W" + accuracy_decimals: 0 + state_class: measurement + device_class: power + # Report every 5 minutes or when +/- 20 watts + filters: + - or: + - throttle: 5min + - delta: 20 # <- watts + - lambda: |- + if (id(fast_reporting)) return(x); + return {}; + on_raw_value: + then: + lambda: |- + ESP_LOGI("Vue", "Watts returned = %0.3f", x); + - name: "Watts" id: watts unit_of_measurement: "W"