In order to track my power consumption and be able to properly display it in the Energy Configuration I have a sensor, provided by IotaWatt that gives me the power reading in Wh
for each phase in my house i.e. Red, Yellow, Blue.
This reading is a total
value and can hence be negative and positive. To correctly be displayed in the Energy Tab the import and export values must be positive, so I have templated each phase into two sensors based on the state change of the Main <phase>.wh
sensor.
As per below:
- trigger:
- trigger: state
entity_id:
- sensor.main_r_wh
not_from:
- unknown
- unavailable
- trigger: time
at: "00:00:00"
sensor:
- name: "Main R Export.wh"
unique_id: sensor.main_r_export_wh
state_class: total_increasing
device_class: energy
icon: "mdi:lightning-bolt"
unit_of_measurement: "Wh"
state: >
{% set last_state = this.state | float(0) %}
{% if trigger.platform == 'time' %}
{% set last_state = 0 %}
{% elif not is_number(last_state) %}
{% set trigger_seconds = int(as_timestamp(trigger.to_state.last_updated + timedelta(8/24))) % 86400 %}
{% set last_state = states.sensor.sql_main_r_export_wh.state | float(0) %}
{% endif %}
{% set to_state = trigger.to_state.state | float(0) %}
{% set from_state = trigger.from_state.state | float(0) %}
{% if trigger_seconds > 20 and is_number(to_state) %}
{% set delta = to_state - from_state %}
{% endif %}
{{ last_state + delta | abs if is_number(delta) and delta < 0 else last_state | float(0) }}
- name: "Main R Import.wh"
unique_id: sensor.main_r_import_wh
state_class: total_increasing
device_class: energy
icon: "mdi:lightning-bolt"
unit_of_measurement: "Wh"
state: >
{% set last_state = this.state | float(0) %}
{% if trigger.platform == 'time' %}
{% set last_state = 0 %}
{% elif not is_number(last_state) %}
{% set trigger_seconds = int(as_timestamp(trigger.to_state.last_updated + timedelta(8/24))) % 86400 %}
{% set last_state = states.sensor.sql_main_r_export_wh.state | float(0) %}
{% endif %}
{% set to_state = trigger.to_state.state | float(0) %}
{% set from_state = trigger.from_state.state | float(0) %}
{% if trigger_seconds > 20 and is_number(to_state) %}
{% set delta = to_state - from_state %}
{% endif %}
{{ last_state + delta | abs if is_number(delta) and delta >= 0 else last_state | float(0) }}
This works more or less ok. some filtering was needed around the midnight point to avoid the Main x export.wh
value to give an excessive reading when the trigger state is reset to 0 at midnight, but it works.
What is ‘strange’ is that I have to copy the same state
logic 3 times, once for each phase. Is there an option to do this with a function call?
i.e. something like the below in -more or less- JS, but then in Home Assistant
function getState(state: state, trigger: trigger, sqlState: state = null): number {
let delta: number = 0;
let last_state = state ?? 0
if (trigger.platform == 'time') {
last_state = 0
}
else if not (is_number(last_state)) {
trigger_seconds = int(as_timestamp(trigger.to_state.last_updated + timedelta(8/24))) % 86400
last_state = sqlState.state ?? 0
}
to_state = trigger.to_state.state
from_state = trigger.from_state.state
if (trigger_seconds > 20 && is_number(to_state)) {
delta = to_state - from_state
}
return (is_number(delta) && delta < 0) ? last_state + Math.abs(delta) : last_state;
That way you only have the state
logic once (or twice in this case, once for < 0
and once for >= 0
)
Then the logic for the template would be much cleaner;
- trigger:
- trigger: state
entity_id:
- sensor.main_r_wh
not_from:
- unknown
- unavailable
- trigger: time
at: "00:00:00"
sensor:
- name: "Main R Export.wh"
unique_id: sensor.main_r_export_wh
state_class: total_increasing
device_class: energy
icon: "mdi:lightning-bolt"
unit_of_measurement: "Wh"
state: >
{{ getState(this.state, trigger, states.sensor.sql_main_r_export_wh)