New user of Home Assistant and ESPHome as of yesterday. Previously many many years of Openhab and used to work on ESP32 IDF based products as a day job.
I have a question about best practice, because what I have come up with based upon documentation and forum posts that I can find, seems wrong.
For context, I have made a home energy monitor, using and ESP32devkit and two current clamps (one on my consumer unit, one on solar output). The whole device only measure current, and assumes voltage is a constant. Based on this we can calculate power, energy, import, export, etc. The only real measurement is current (and voltage, by this construction where one day I might measure this) and this is deterministic based upon update_interval
.
However, in all the examples I found, the other calculations are also on update_interval
whereas it seems to me like they should be only executed when current has an update?
I notice in the logs that current and energy get executed before the current measurement, so are always (roughly) one time step behind.
Note; I am using the inbuilt energy dashboard as the frontend configured as follows:
- Grid consumption: “Import Energy”
- Return to grid: “Export Energy”
- Solar production: “Solar Energy Used”
Question:
What’s the best practice for calculating a sensor value X (using Y), when sensor value Y gets an update?
substitutions:
update_time: 10s
voltage_assumed: 243.7f
esphome:
name: esphome-energy-mains
esp32:
board: esp32dev
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable OTA
ota:
# Enable Homeassistant API
api:
# Enable Logging
logger:
# Enable Timing (dependency from total_daily_energy)
time:
- platform: homeassistant
id: homeassistant_time
# Output Hardware
output:
- platform: gpio
pin: 14
id: gpio_led_red
- platform: gpio
pin: 12
id: gpio_led_green
- platform: gpio
pin: 13
id: gpio_led_blue
# Input Sensors
sensor:
- platform: wifi_signal
name: WiFi Signal
update_interval: 60s
# Source sensor hardware connection
- platform: adc
pin: GPIO35
id: current_clamp_consumer_unit_raw
attenuation: 11db
- platform: adc
pin: GPIO34
id: current_clamp_solar_raw
attenuation: 11db
# Consumer Unit Current Measured to Amps
- platform: ct_clamp
id: cu_current_measured
sensor: current_clamp_consumer_unit_raw
name: Consumer Unit Current Measured
sample_duration: 200ms
update_interval: ${update_time}
filters:
- multiply: 5.85
# - calibrate_linear:
# - 0.005 -> 0
# - 0.18176 -> 1.0628
unit_of_measurement: A
# Solar Production Sensor to Amps
- platform: ct_clamp
id: solar_current_measured
sensor: current_clamp_solar_raw
name: Solar Production Current Measured
sample_duration: 200ms
update_interval: ${update_time}
filters:
- multiply: 5.85
# - calibrate_linear:
# - 0 -> 0
# - 1.25544 -> 7.38
unit_of_measurement: A
# Consumer Unit Volts
- platform: template
name: Consumer Unit Volts
id: cuVolts
lambda: return ${voltage_assumed};
accuracy_decimals: 2
unit_of_measurement: V
device_class: voltage
update_interval: ${update_time}
# Consumer Unit Amps
- platform: template
name: Consumer Unit Amps
id: cuAmps
lambda: return id(current_clamp_consumer_unit_raw).state;
accuracy_decimals: 2
unit_of_measurement: A
device_class: current
update_interval: ${update_time}
# Consumer Unit Watts
- platform: template
name: Consumer Unit Watts
id: cuWatts
lambda: return id(cuVolts).state * id(cuAmps).state ;
accuracy_decimals: 1
unit_of_measurement: W
device_class: power
update_interval: ${update_time}
# Consumer Unit Energy
- platform: total_daily_energy
name: Consumer Unit Energy
power_id: cuWatts
filters:
- multiply: 0.001
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
# Solar Generated Volts
- platform: template
name: Solar Volts
id: solarVolts
lambda: return ${voltage_assumed};
accuracy_decimals: 2
unit_of_measurement: V
device_class: voltage
update_interval: ${update_time}
# Solar Generated Amps (50A Clamp)
- platform: template
name: Solar Amps
id: solarAmps
lambda: return id(solar_current_measured).state;
accuracy_decimals: 2
unit_of_measurement: A
device_class: current
update_interval: ${update_time}
# Solar Generated Watts
- platform: template
name: Solar Watts
id: solarWatts
lambda: return id(solarVolts).state * id(solarAmps).state ;
accuracy_decimals: 1
unit_of_measurement: W
device_class: power
update_interval: ${update_time}
# Import Watts
- platform: template
name: Import Watts
id: importWatts
lambda: >-
const float dJ = id(cuWatts).state - id(solarWatts).state;
return dJ > 0.0f ? dJ : 0.0f;
accuracy_decimals: 1
unit_of_measurement: W
device_class: power
update_interval: ${update_time}
# Export Watts
- platform: template
name: Export Watts
id: exportWatts
lambda: >-
const float dJ = id(cuWatts).state - id(solarWatts).state;
return dJ > 0.0f ? 0.0f : abs(dJ);
accuracy_decimals: 1
unit_of_measurement: W
device_class: power
update_interval: ${update_time}
# Solar Generated Energy
- platform: total_daily_energy
name: Solar Energy
power_id: solarWatts
filters:
- multiply: 0.001
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
# Solar Consumed Watts
- platform: template
name: Solar Watts Used
id: solarConsumedWatts
lambda: >-
const float solar = id(solarWatts).state;
const float house = id(cuWatts).state;
return house > solar ? solar : house;
accuracy_decimals: 1
unit_of_measurement: W
device_class: power
update_interval: ${update_time}
# Import Energy
- platform: total_daily_energy
name: Import Energy
power_id: importWatts
filters:
- multiply: 0.001
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
# Export Energy
- platform: total_daily_energy
name: Export Energy
power_id: exportWatts
filters:
- multiply: 0.001
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
# Solar Consumed Energy
- platform: total_daily_energy
name: Solar Energy Used
power_id: solarConsumedWatts
filters:
- multiply: 0.001
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing