I have a sensor with a dictionary in an attribute that gives me the settings for the day to optimise my backup power system given the solar forecast. The details of this isn’t too important, except to say there are two modes: an optimistic and a pessimistic mode. For each mode, there’s a setting for each time slot that sets the battery’s minimum state of charge and whether it’s allowed to charge from the grid. These are just set via number
and switch
entities which then goes to the inverter via MQTT.
TL;DR:
This is the diff that fixes my issue, but I don’t know why. Instead of state_attr('sensor.charge_mode', 'settings')[repeat.index][1]
having the values True
or False
it’s now 'on'
and 'off'
.
While I was able to found forum messages about this error, none of it seemed to have any relation to my case.
What I had which I think causes the issue:
- service: "switch.turn_{{ 'on' if state_attr('sensor.charge_mode', 'settings')[repeat.index][1] else 'off' }}"
What I changed it to:
- service: "switch.turn_{{ state_attr('sensor.charge_mode', 'settings')[repeat.index][1] }}"
In the old case, state_attr('sensor.charge_mode', 'settings')[repeat.index][1]
is the second item of a tuple which was either True
or False
.
In the new case, state_attr('sensor.charge_mode', 'settings')[repeat.index][1]
is either 'on'
or 'off'
.
Full details:
This is what I had that caused an error in the automation:
Old config
template:
- trigger:
- platform: state
entity_id: sensor.average_solar_energy_forecast_today
not_to:
- "unavailable"
- "unknown"
sensor:
name: "Charge Mode"
icon: mdi:tune
device_class: enum
state: >-
{% set forecast = states('sensor.average_solar_energy_forecast_today') | int(0) %}
{# hysteresis #}
{% if forecast >= 8 %}
Optimistic
{% elif forecast <= 7 %}
Pessimistic
{% else %}
{{ this.state }}
{% endif %}
attributes:
settings: >-
{# 1: 01:00-05:00 #}
{# 2: 05:00-08:00 #}
{# 3: 08:00-13:00 #}
{# 4: 13:00-17:00 #}
{# 5: 17:00-21:00 #}
{# 6: 21:00-01:00 #}
{# (int, bool): (battery soc, grid charge allowed) #}
{% set mappings =
{
'optimistic': {
1: (50, True),
2: (45, False),
3: (60, False),
4: (75, False),
5: (85, True),
6: (85, True)
},
'pessimistic': {
1: (50, True),
2: (60, True),
3: (60, True),
4: (75, True),
5: (80, True),
6: (80, True),
}
}
%}
{% set forecast = states('sensor.average_solar_energy_forecast_today') | int(0) %}
{# hysteresis #}
{% if forecast >= 8 %}
{% set mode = 'optimistic' %}
{% elif forecast <= 7 %}
{% set mode = 'pessimistic' %}
{% else %}
{% set mode = this.state %}
{% endif %}
{{ mappings[mode] }}
automation:
- alias: "Set Charge Points"
initial_state: true
trigger:
- platform: time
at: "04:00:00"
- platform: time
at: "10:00:00"
action:
- repeat:
count: "{{ state_attr('sensor.charge_mode', 'settings').keys() | length }}"
sequence:
- service: number.set_value
target:
entity_id: "number.capacity_point_{{ repeat.index }}"
data:
value: "{{ state_attr('sensor.charge_mode', 'settings')[repeat.index][0] }}"
- service: "switch.turn_{{ 'on' if state_attr('sensor.charge_mode', 'settings')[repeat.index][1] else 'off' }}" # THIS LINE SEEMS TO BE THE ISSUE
target:
entity_id: "switch.grid_charge_point_{{ repeat.index }}"
- service: notify.mobile_app_ceres
data:
title: "Backup Power System"
message: >-
{% set mode = states('sensor.charge_mode') | lower %}
{% set forecast = states('sensor.average_solar_energy_forecast_today') | float(0) | round(1) %}
The backup power system's charging map has been set to {{ mode }}. The solar energy production forecast for today is {{ forecast }}kWh.
data:
group: "home-electricity"
url: homeassistant://navigate/lovelace/resources
This caused an HomeAssistantError: "Secrets not supported in this YAML file"
error. There are no secrets used in this file anywhere and the only two uses of a !
are in text message fields.
I then figured it must be an issue with the templating, even though it parses fine and I was able to simulate it all with the developer tools.
I then changed it to the following:
New config
template:
- trigger:
- platform: state
entity_id: sensor.average_solar_energy_forecast_today
not_to:
- "unavailable"
- "unknown"
sensor:
name: "Charge Mode"
icon: mdi:tune
device_class: enum
state: >-
{% set forecast = states('sensor.average_solar_energy_forecast_today') | int(0) %}
{# hysteresis #}
{% if forecast >= 8 %}
Optimistic
{% elif forecast <= 7 %}
Pessimistic
{% else %}
{{ this.state }}
{% endif %}
attributes:
settings: >-
{# 1: 01:00-05:00 #}
{# 2: 05:00-08:00 #}
{# 3: 08:00-13:00 #}
{# 4: 13:00-17:00 #}
{# 5: 17:00-21:00 #}
{# 6: 21:00-01:00 #}
{# (int, bool): (battery soc, grid charge allowed) #}
{% set mappings =
{
'optimistic': {
1: (50, 'on'),
2: (45, 'off'),
3: (60, 'off'),
4: (75, 'off'),
5: (85, 'on'),
6: (85, 'on')
},
'pessimistic': {
1: (50, 'on'),
2: (60, 'on'),
3: (60, 'on'),
4: (75, 'on'),
5: (80, 'on'),
6: (80, 'on')
}
}
%}
{% set forecast = states('sensor.average_solar_energy_forecast_today') | int(0) %}
{# hysteresis #}
{% if forecast >= 8 %}
{% set mode = 'optimistic' %}
{% elif forecast <= 7 %}
{% set mode = 'pessimistic' %}
{% else %}
{% set mode = this.state %}
{% endif %}
{{ mappings[mode] }}
automation:
- alias: "Set Charge Points"
initial_state: true
trigger:
- platform: time
at: "04:00:00"
- platform: time
at: "10:00:00"
action:
- repeat:
count: "{{ state_attr('sensor.charge_mode', 'settings').keys() | length }}"
sequence:
- service: number.set_value
target:
entity_id: "number.capacity_point_{{ repeat.index }}"
data:
value: "{{ state_attr('sensor.charge_mode', 'settings')[repeat.index][0] | int(0) }}"
- service: "switch.turn_{{ state_attr('sensor.charge_mode', 'settings')[repeat.index][1] }}"
target:
entity_id: "switch.grid_charge_point_{{ repeat.index }}"
- service: notify.mobile_app_ceres
data:
title: "Backup Power System"
message: >-
{% set mode = states('sensor.charge_mode') | lower %}
{% set forecast = states('sensor.average_solar_energy_forecast_today') | float(0) | round(1) %}
The backup power system's charging map has been set to {{ mode }}. The solar energy production forecast for today is {{ forecast }}kWh.
data:
group: "home-electricity"
url: homeassistant://navigate/lovelace/resources
Here is my simulated template editor code:
Template editor
New way:
{%- set l = state_attr('sensor.charge_mode', 'settings').keys() | length %}
{%- for i in range(1, l + 1) -%}
{% set repeat = {'index': i} %}
number.capacity_point_{{ repeat.index }}: {{ state_attr('sensor.charge_mode', 'settings')[repeat.index][0] | int(0) }}
switch.turn_{{ state_attr('sensor.charge_mode', 'settings')[repeat.index][1] }}: switch.grid_charge_point_{{ repeat.index }}
{% endfor %}
Old way:
{%- set repeat = {'index': 3} %}
{%- set x = {3: (33, False)} %}
switch.turn_{{ 'on' if x[repeat.index][1] else 'off' }}
And the output:
Output
New way:
number.capacity_point_1: 50
switch.turn_on: switch.grid_charge_point_1
number.capacity_point_2: 45
switch.turn_off: switch.grid_charge_point_2
number.capacity_point_3: 60
switch.turn_off: switch.grid_charge_point_3
number.capacity_point_4: 75
switch.turn_off: switch.grid_charge_point_4
number.capacity_point_5: 85
switch.turn_on: switch.grid_charge_point_5
number.capacity_point_6: 85
switch.turn_on: switch.grid_charge_point_6
Old way:
switch.turn_off