Hello @zakazak,
thank you for your work on this script. It mainly works, but I stumbled upon a problem or two… maybe you are kind enough to help me out?
First of all, I don’t use a shelly to measure my PV production but I have a Hoymiles microinverter, and I use this custom integration GitHub - suaveolent/ha-hoymiles-wifi: Home Assistant custom component for Hoymiles DTUs and the HMS-XXXXW-2T microinverters to get the value via sensor “sensor.inverter_ac_power”.
Then I had to change the “power consumption” sensor, because most of the time it didn’t include import in the calculations.
So basically that part of the script:
power_consumption:
friendly_name: "Power Consumption"
unit_of_measurement: 'W'
value_template: >-
{% set import_val = states('sensor.power_import') | float(0) %}
{% set export_val = states('sensor.power_export') | float(0) %}
{% set solar_val = (states('sensor.shellypmminig3_5432046f3b24_power') | float(0)) * -1 %}
{% set delta = solar_val - export_val %}
{% set tolerance = 2.0 if solar_val < 100 else 0 %}
{% if delta < -tolerance %}
{{ import_val + solar_val }}
{% elif delta > tolerance %}
{{ delta }}
{% elif abs(delta) <= tolerance %}
{{ 0 }}
{% else %}
{{ import_val + solar_val }}
{% endif %}
now looks like this:
power_consumption:
friendly_name: "Power Consumption"
unit_of_measurement: 'W'
value_template: >-
{% set import_val = states('sensor.power_import') | float(0) %}
{% set export_val = states('sensor.power_export') | float(0) %}
{% set solar_val = states('sensor.inverter_ac_power') | float(0) %}
{% set delta = solar_val - export_val %}
{% set tolerance = 2.0 if solar_val < 100 else 0 %}
{% if delta < -tolerance %}
{{ import_val + solar_val }}
{% elif delta > tolerance %}
{{ delta + import_val }}
{% elif abs(delta) <= tolerance %}
{{ delta + import_val }}
{% else %}
{{ import_val + solar_val }}
{% endif %}
But now I have the problem that as soon as my microinverter stops producing power, all the consumption sensors become “Unavailable”.
Any help is appreciated.
Just for reference, this is the complete script:
########## Sensor ##########
# Shelly 3EM templates for 3-phase Net Import, Export and Consumption (if you have solar generation details)
# This uses the Shelly instantaneous power sensors to achieve the best possible accuracy.
# Shelly Sensors are:
# sensor.shellypro3em_abcd1234_phase_a_active_power,
# sensor.shellypro3em_abcd1234_phase_b_active_power,
# sensor.shellypro3em_abcd1234_phase_c_active_power for the three phases.
# Solar generation in W is used to calculate consumption via sensor.power_solargen
# V1.0 Initial release by Uksa007
# V1.1 Add float(0) to Consumption template to stop log warnings.
# V1.2 Add Friendly names to Utility Meter sensors.
# V1.3 Remove negative spikes from power consumption due to different update timing of solar sensor.
# V1.4 Change round: 2 for small value users.
# M Changelog: My own changes
# M1.0 Set round to 4, integrate PV-Summation_Delivered to be used with sensor.power_solargen, add float for each phase (otherwise error).
# M1.1 Introduce performance and accuracy enhancements:
# - Use of local 'set' variables to minimize repeated state lookups and improve performance.
# - Accurate 'availability_template' using float(none) and is_number validation.
# - Introduce a tolerance threshold (3W) in power_consumption logic to suppress jitter/noise when solar ≈ export.
# - Improve clarity and robustness of export/consumption calculation by avoiding undefined states and false negatives.
# - Remove early rounding in all sensors; final values are left raw to preserve precision for integration processing.
# M1.2 Remove integration of PV-Summation_Delivered and use shellypmminig3_1234abcd_power instead
# M1.3 Make tolerance dynamic but 1,5W at minimum
# M1.4 Make tolerance less dynamic by applying a fixed 2W tolerance but the tolerance only applies when solar generation is < 100W
# - Please make sure if solar_val is being reported as positive or negative value and adapt sensor "power consumption" accordingly
sensor:
- platform: template
sensors:
# Calculates total power import (sum of 3 phases, only if active_power is > 0)
power_import:
friendly_name: "Power Import"
unit_of_measurement: 'W'
value_template: >-
{% set a = states('sensor.shellypro3em_abcd1234_phase_a_active_power') | float(0) %}
{% set b = states('sensor.shellypro3em_abcd1234_phase_b_active_power') | float(0) %}
{% set c = states('sensor.shellypro3em_abcd1234_phase_c_active_power') | float(0) %}
{% set total = a + b + c %}
{{ total if total > 0 else 0 }}
availability_template: >-
{% set sensors = [
states('sensor.shellypro3em_abcd1234_phase_a_active_power') | float(none),
states('sensor.shellypro3em_abcd1234_phase_b_active_power') | float(none),
states('sensor.shellypro3em_abcd1234_phase_c_active_power') | float(none)
] %}
{{ sensors | select('is_number') | list | count == 3 }}
# Calculates total power export (sum of 3 phases, only if active_power is < 0)
power_export:
friendly_name: "Power Export"
unit_of_measurement: 'W'
value_template: >-
{% set a = states('sensor.shellypro3em_abcd1234_phase_a_active_power') | float(0) %}
{% set b = states('sensor.shellypro3em_abcd1234_phase_b_active_power') | float(0) %}
{% set c = states('sensor.shellypro3em_abcd1234_phase_c_active_power') | float(0) %}
{% set total = a + b + c %}
{{ (total * -1) if total < 0 else 0 }}
availability_template: >-
{% set sensors = [
states('sensor.shellypro3em_abcd1234_phase_a_active_power') | float(none),
states('sensor.shellypro3em_abcd1234_phase_b_active_power') | float(none),
states('sensor.shellypro3em_abcd1234_phase_c_active_power') | float(none)
] %}
{{ sensors | select('is_number') | list | count == 3 }}
# Calculates real power consumption including solar generation and export
# Sets a tolerance to try and mitgitate any sensor noise / lags / jitters
# Make solar_val a positive number (the shelly will report the PV power as negative value)
power_consumption:
friendly_name: "Power Consumption"
unit_of_measurement: 'W'
value_template: >-
{% set import_val = states('sensor.power_import') | float(0) %}
{% set export_val = states('sensor.power_export') | float(0) %}
{% set solar_val = states('sensor.inverter_ac_power') | float(0) %}
{% set delta = solar_val - export_val %}
{% set tolerance = 2.0 if solar_val < 100 else 0 %}
{% if delta < -tolerance %}
{{ import_val + solar_val }}
{% elif delta > tolerance %}
{{ delta + import_val }}
{% elif abs(delta) <= tolerance %}
{{ delta + import_val }}
{% else %}
{{ import_val + solar_val }}
{% endif %}
# Sensor for Riemann sum of energy import (W -> Wh)
- platform: integration
source: sensor.power_import
name: energy_import_sum
unit_prefix: k
round: 4
method: left
# Sensor for Riemann sum of energy export (W -> Wh)
- platform: integration
source: sensor.power_export
name: energy_export_sum
unit_prefix: k
round: 4
method: left
# Sensor for Riemann sum of energy consumption (W -> Wh)
- platform: integration
source: sensor.power_consumption
name: energy_consumption_sum
unit_prefix: k
round: 4
method: left
########## Utility Meter ##########
utility_meter:
energy_import_daily:
source: sensor.energy_import_sum
name: Energy Import Daily
cycle: daily
energy_import_monthly:
source: sensor.energy_import_sum
name: Energy Import Monthly
cycle: monthly
energy_export_daily:
source: sensor.energy_export_sum
name: Energy Export Daily
cycle: daily
energy_export_monthly:
source: sensor.energy_export_sum
name: Energy Export Monthly
cycle: monthly
energy_consumption_daily:
source: sensor.energy_consumption_sum
name: Energy Consumption Daily
cycle: daily
energy_consumption_monthly:
source: sensor.energy_consumption_sum
name: Energy Consumption Monthly
cycle: monthly