Last active
March 16, 2024 20:13
-
-
Save AndySymons/869e9a34d84c4ddc03fc762a1fc6d88b to your computer and use it in GitHub Desktop.
Calendar Switch Y2. Switches one or more devices based on calendar events
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### ------------------------------------------------------------------------------------------------ | |
### | |
### CALENDAR SWITCH Y2 | |
### ------------------ | |
### | |
### Release 1.0 (5 Mar 2024) | |
### Controls one or more switched devices from a calendar | |
### Allows temporary manual override | |
### Away mode. Turns off (ignores the calendar) | |
### Device battery life saved by transmitting only when there is an actual change. | |
### Sends a notification if a switch is unavailable or not responding to settings. | |
### Has optional logging. | |
### | |
### Minor updates (for robustness) | |
### 05-Mar-2024: 1.0.01 Added detail to the trigger line of the log entries | |
### 08-Mar-2024: 1.0.02 Corrected the trigger line of the log entries when triggers have no entity_id (e.g. calendars) | |
### 08-Mar-2024: 1.0.03 Tidied up logic of ACTION[6] using `choose`, to ensure there is always a log message | |
### 08-Mar-2024: 1.0.04 Improved notifications. Additional unknown and unavailable checks every time a setting is needed. | |
### Notification automatically dismissed when device comes back online (instead of a new | |
### notification). Only ever one notification per device. | |
### 13-Mar-2024: 1.0.05 Added 'continue_on_error' and 'parallel' to device service call, 'continue_on_error' to logs | |
### and notifications, because failure her should not stop the main device switching function | |
### 14-Mar-2924: 1.0.06 Turning away mode on now cancels the manual override timer | |
### | |
### Release 2.0 (14 Mar 2024) | |
### 14-Mar-2924: 2.0.00 Actually just renamed from Y1 to Y2 for alignment with Calendar Switch Y2 and Zone Switch Z2 | |
### 14-Mar-2924: 2.0.01 Added extra unknown and unavailable tests on echoblock timer end | |
### 16-Mar-2024: 2.2.02 Changed logging to use the new script.heating_xyz_logfile_entry (making the code more compact and maintainable) | |
### | |
### OVERVIEW | |
### The main action steps are as follows. | |
### The numbering correspnds to that used by the system log for error messages. | |
### ACTION[0] -- LOG THE TRIGGER. Starts a new log file entry by writing a bank line and the trigger id | |
### ACTIONS[1-3] -- FETCH THE CURRENT AND NEXT CALENDAR EVENTS | |
### Calls calendar.get_events twice, then sets local variables for later use | |
### ACTION[4] -- RESPOND TO TRIGGERS WHERE NECESSARY. A big choose statement on the trigger_id. | |
### ACTION[5] -- DETERMINE THE REQUIRED state ACCORDING TO THE STATE. A big chooose statement on the relevant states variables. | |
### Decides what state is required and why. Sets the 'required state' helper and the 'reason test' helper. | |
### ACTION[6] -- SEND state CHANGE TO THE deviceS | |
### Loops through all the devices for the room. If the required state is | |
### different from the actual one, the service call to change it is invoked and the echoblock (response timerout) timer started. | |
### ACTION[7] -- LOG THE REASON. Writes the last line of the log file entry | |
### | |
### ------------------------------------------------------------------------------------------------ | |
blueprint: | |
name: "Calendar Switch Y2" | |
description: Controls one or more switched devices from a calendar, allows temporary manual override | |
domain: automation | |
### ---------------------------------------------------------------------------------------------- | |
### INPUTS | |
### ---------------------------------------------------------------------------------------------- | |
input: | |
switched_devices: | |
name: DEVICE ENTITIES - The devices to be switched | |
description: One or more switch entities that are to be controlled by this automation | |
selector: | |
entity: | |
filter: | |
domain: switch | |
multiple: true | |
away_mode: | |
name: DEVİCE ENTITY - Away switch, binary sensor or input boolean (if required) | |
description: A switch, input boolean, or binary sensor that switches all devices | |
selector: | |
entity: | |
default: [] | |
device_calendar: | |
name: CALENDAR ENTITY - switch calendar (mandatory) | |
description: The calendar dedicated to scheduling events for this/these device(s) | |
selector: | |
entity: | |
filter: | |
domain: calendar | |
setting_reason: | |
name: HELPER - Setting reason (mandatory) | |
description: The global variable (helper) into which the automation writes the reason for the current setting (for use on a dashboard) | |
selector: | |
entity: | |
filter: | |
domain: input_text | |
required_state: | |
name: HELPER - Required state (mandatory) | |
description: The global boolean variable (helper) to hold the state required | |
selector: | |
entity: | |
filter: | |
domain: input_boolean | |
manual_state: | |
name: HELPER - Manual override state (mandatory) | |
description: The global boolean variable (helper) to hold the state for a manual intervention | |
selector: | |
entity: | |
filter: | |
domain: input_boolean | |
manual_override_timer: | |
name: HELPER - Manual override timer (mandatory) | |
description: The global variable (helper) to hold the timer for a manual intervention | |
selector: | |
entity: | |
filter: | |
domain: timer | |
echoblock_timer: | |
name: HELPER - Echoblock timer (mandatory) | |
description: The timer for use inside the automation to disinguish genuine manual changes of the set state from those set by the automation | |
selector: | |
entity: | |
filter: | |
domain: timer | |
manual_override_period: | |
name: PARAMETER - Manual override period | |
description: The time period for which a manual intervention will override the schedule | |
selector: | |
time: | |
default: "02:00:00" | |
logging_service_name: | |
name: LOGGING - Specify the service for logging | |
description: Enter service name (not filename) as a string | |
default: "" | |
mode: queued # use all triggers but avoid conflicting states | |
## ------------------------------------------------------------------------------------------------- | |
## LOCAL VARİABLES | |
## Constants, and input variable values for use in templates | |
## ------------------------------------------------------------------------------------------------- | |
variables: | |
# Parameters -- hold the actual value | |
local_logging_service_name: !input logging_service_name | |
# Devices and helpers -- hold the entity | |
local_away_mode: !input away_mode | |
local_device_calendar: !input device_calendar | |
local_manual_override_timer: !input manual_override_timer | |
local_manual_state: !input manual_state | |
local_required_state: !input required_state | |
local_setting_reason: !input setting_reason | |
# Handy constants | |
# identifies the source of the log messages | |
log_message_preamble: > | |
{{ this.attributes.friendly_name }} | |
## ------------------------------------------------------------------------------------------------- | |
## TRIGGERS | |
## ------------------------------------------------------------------------------------------------- | |
trigger: | |
- platform: homeassistant | |
event: start | |
id: startup | |
# Calendar event start | |
- platform: calendar | |
event: start | |
offset: "00:00:00" | |
entity_id: !input device_calendar | |
id: calendar_event_start | |
# Calendar event end | |
- platform: calendar | |
event: end | |
offset: "00:00:00" | |
entity_id: !input device_calendar | |
id: calendar_event_end | |
# Switch becomes unavailable | |
- platform: state | |
entity_id: !input switched_devices | |
to: unavailable | |
for: | |
seconds: 60 # not just a glitch | |
id: device_unavailable | |
# Switch becomes available | |
- platform: state | |
entity_id: !input switched_devices | |
from: unavailable | |
for: | |
seconds: 60 # not just a glitch | |
id: device_available | |
# Change in any one of the switches' state | |
- platform: state | |
entity_id: !input switched_devices | |
for: | |
seconds: 5 | |
id: switch_state_change | |
# End of manual override (timer idle, unknown, or unavailable) | |
- platform: state | |
entity_id: !input manual_override_timer | |
from: active | |
id: manual_override_end | |
# Away switch change | |
- platform: state | |
entity_id: !input away_mode | |
id: away_mode_change | |
# Echoblock timer end -- Check whether the switches responded | |
- platform: state | |
entity_id: !input echoblock_timer | |
from: active | |
to: idle | |
id: echoblock_timer_end | |
# - platform: time_pattern | |
# At interval re-checks the state. | |
# Can be used to pick up missed events etc. Should not be necessary | |
# between event_start, calendar on and availability of data | |
# minutes: "/1" | |
# id: catchall_interval | |
action: | |
## ------------------------------------------------------------------------------------------------- | |
## ACTION[0] -- LOG THE TRIGGER | |
## ------------------------------------------------------------------------------------------------- | |
- service: script.heating_xyz_logfile_entry | |
data: | |
notification_service: !input logging_service_name | |
logfile_title: Calendar Switch Y2 | |
message_preamble: "{{ log_message_preamble }}" | |
message_body: --- | |
- service: script.heating_xyz_logfile_entry | |
data: | |
notification_service: !input logging_service_name | |
logfile_title: Calendar Switch Y2 | |
message_preamble: "{{ log_message_preamble }}" | |
message_body: > | |
{% if trigger.id is undefined %} | |
{{ "Run manually." }} | |
{% elif trigger.entity_id is undefined %} | |
{{ "Triggered by: " + trigger.id | string + " (no entity id)" }} | |
{% else %} | |
{{ "Triggered by: " + trigger.id | string + " from '" + state_attr(trigger.entity_id, 'friendly_name') + "', state = " + states(trigger.entity_id) }} | |
{% endif %} | |
## ------------------------------------------------------------------------------------------------- | |
## ACTIONS[1-3] -- FETCH THE CURRENT AND NEXT EVENTS FROM THE CALENDAR | |
## Current event is the one that started last | |
## ------------------------------------------------------------------------------------------------- | |
- service: calendar.get_events | |
target: | |
entity_id: !input device_calendar | |
data: | |
duration: | |
hours: 0 | |
minutes: 0 | |
seconds: 1 | |
response_variable: active_events | |
- service: calendar.get_events | |
target: | |
entity_id: !input device_calendar | |
data: | |
duration: | |
hours: 24 | |
minutes: 0 | |
seconds: 0 | |
response_variable: future_events | |
- variables: | |
any_event_active: > | |
{{ active_events[local_device_calendar].events | count > 0 }} | |
current_event: > | |
{{ active_events[local_device_calendar].events | sort(attribute ='start') | list | last | default("") }} | |
any_future_event: > | |
{{ future_events[local_device_calendar].events | count > 0 }} | |
next_event: > | |
{{ future_events[local_device_calendar].events | sort(attribute ='start') | list | first | default ("") }} | |
## ------------------------------------------------------------------------------------------------- | |
## ACTION[4] -- RESPOND TO TRIGGERS WHERE NECESSARY | |
## (not all triggers require an individual response) | |
## ------------------------------------------------------------------------------------------------- | |
# Each choice responds to a specific trigger (where a response is needed)) | |
- choose: | |
# | |
# ACTION[4]CHOOSE[0] Manual override start | |
# | |
- conditions: | |
- condition: trigger | |
id: switch_state_change | |
sequence: | |
- if: | |
- condition: state | |
entity_id: !input echoblock_timer | |
state: idle | |
then: | |
- service: timer.start | |
target: | |
entity_id: !input manual_override_timer | |
data: | |
duration: !input manual_override_period | |
- if: | |
condition: template | |
value_template: > | |
{{ states(trigger.entity_id) == "on" }} | |
then: | |
- service: input_boolean.turn_on | |
target: | |
entity_id: !input manual_state | |
else: | |
- service: input_boolean.turn_off | |
target: | |
entity_id: !input manual_state | |
else: | |
# log that the trigger is ignored | |
- service: script.heating_xyz_logfile_entry | |
data: | |
notification_service: !input logging_service_name | |
logfile_title: Calendar Switch Y2 | |
message_preamble: "{{ log_message_preamble }}" | |
message_body: > | |
{{ "Set state ignored during echo block period" }} | |
# Stop | |
- stop: "trigger ignored during echoblock" | |
# | |
# ACTION[4]CHOOSE[1] Echoblock timer end | |
# Check whether the switches responded correctly to the new setting | |
# | |
- conditions: | |
- condition: trigger | |
id: echoblock_timer_end | |
sequence: | |
- repeat: | |
for_each: !input switched_devices | |
sequence: | |
- choose: | |
# If the device is unknown | |
- conditions: > | |
{{ states(repeat.item) == 'unknown' }} | |
sequence: | |
# Create a notification | |
- service: persistent_notification.create | |
data: | |
title: "Calendar Switch Y2" | |
message: > | |
{{ " The device '" + state_attr(repeat.item, 'friendly_name') | default("xxxxxx") + "' is unknown" }} | |
notification_id: > | |
{{ repeat.item }} | |
# to prevent duplicate notifications | |
continue_on_error: true | |
# | |
# log the notification | |
- service: script.heating_xyz_logfile_entry | |
data: | |
notification_service: !input logging_service_name | |
logfile_title: Calendar Switch Y2 | |
message_preamble: "{{ log_message_preamble }}" | |
message_body: > | |
{{ "The device '" + state_attr(repeat.item, 'friendly_name') | default("xxxxxx") + "' is unknown" }} | |
# | |
# If the device is unavailable | |
- conditions: > | |
{{ states(repeat.item) == 'unavailable' }} | |
sequence: | |
# Create a notification | |
- service: persistent_notification.create | |
data: | |
title: "Calendar Switch Y2" | |
message: > | |
{{ " The device '" + state_attr(repeat.item, 'friendly_name') | default("xxxxxx") + "' is unavailable" }} | |
notification_id: > | |
{{ repeat.item }} | |
# to prevent duplicate notifications | |
continue_on_error: true | |
# | |
# log the notification | |
- service: script.heating_xyz_logfile_entry | |
data: | |
notification_service: !input logging_service_name | |
logfile_title: Calendar Switch Y2 | |
message_preamble: "{{ log_message_preamble }}" | |
message_body: > | |
{{ "The device '" + state_attr(repeat.item, 'friendly_name') | default("xxxxxx") + "' is unavailable" }} | |
# | |
# The device is not responding to the command | |
- conditions: | |
- condition: template | |
value_template: "{{ states(repeat.item) != states(local_required_state) }}" | |
sequence: | |
# Create a notification | |
- service: persistent_notification.create | |
data: | |
title: "Calendar Switch Y2" | |
message: > | |
{{ "The device '" + state_attr(repeat.item, 'friendly_name') + "' is not responding correctly. Tried to set to " + states(local_required_state) | string + "; actual setting " + states(repeat.item) | string + "." }} | |
notification_id: "{{ repeat.item }}" # to prevent duplicate notifications for same device | |
# log the notification | |
- service: script.heating_xyz_logfile_entry | |
data: | |
notification_service: !input logging_service_name | |
logfile_title: Calendar Switch Y2 | |
message_preamble: "{{ log_message_preamble }}" | |
message_body: > | |
{{ "The device '" + state_attr(repeat.item, 'friendly_name') + "' is not responding correctly. Tried to set to " + states(local_required_state) | string + "; actual setting " + states(repeat.item) | string + "." }} | |
default: # it is OK | |
# Dismiss any notification | |
- service: persistent_notification.dismiss | |
data: | |
notification_id: > | |
{{ repeat.item }} | |
# to prevent duplicate notifications | |
continue_on_error: true | |
# Log entry | |
- service: script.heating_xyz_logfile_entry | |
data: | |
notification_service: !input logging_service_name | |
logfile_title: Calendar Switch Y2 | |
message_preamble: "{{ log_message_preamble }}" | |
message_body: > | |
{{ "The device '" + state_attr(repeat.item, 'friendly_name') + "' is set correctly." }} | |
# | |
# Stop. Otherwise the automation keeps repeating when a device is not responding. | |
# | |
- stop: "No further action after checking the previous setting" | |
# -------------------------------------------------------------------- | |
# | |
# ACTION[4]CHOOSE[2] Manual override timer end | |
# Reset the manual setting helper | |
# | |
- conditions: | |
- condition: trigger | |
id: manual_override_end | |
sequence: | |
- service: input_boolean.turn_off | |
target: | |
entity_id: !input manual_state | |
# | |
# ACTION[3].CHOOSE[3] Away mode on | |
# Reset manual override | |
- conditions: | |
- condition: trigger | |
id: away_mode_change | |
sequence: | |
- service: timer.cancel | |
target: | |
entity_id: !input manual_override_timer | |
- service: input_boolean.turn_off | |
target: | |
entity_id: !input manual_state | |
## | |
## ------------------------------------------------------------------------------------------------- | |
## ACTION[5] -- DETERMINE THE REQUIRED SWITCH STATE | |
## ------------------------------------------------------------------------------------------------- | |
## | |
## Each choice sets the required state and the reason text, for later use | |
## The states are tested in order of their priority over other states | |
- choose: | |
# ACTION[5].CHOOSE[0]. If 'away' switch is on | |
- conditions: | |
- condition: template | |
value_template: "{{ states(local_away_mode) != '' }}" # test whether an away switch was specified | |
- condition: state | |
entity_id: !input away_mode | |
state: "on" | |
sequence: | |
- service: input_boolean.turn_off | |
target: | |
entity_id: !input required_state | |
- service: input_text.set_value | |
data: | |
value: > | |
{% if state_attr(local_setting_reason, 'max') < 255 %} | |
{{ "**Error! Setting reason helper max length must be 255**" }} | |
{% else %} | |
{{ "Turned off because away mode is turned on." }} | |
{% endif %} | |
target: | |
entity_id: !input setting_reason | |
# ACTION[5].CHOOSE[1]. If there is a manual override in operation | |
- conditions: | |
- condition: state | |
entity_id: !input manual_override_timer | |
state: active | |
sequence: | |
- if: | |
condition: state | |
entity_id: !input manual_state | |
state: "on" | |
then: | |
- service: input_boolean.turn_on | |
target: | |
entity_id: !input required_state | |
else: | |
- service: input_boolean.turn_off | |
target: | |
entity_id: !input required_state | |
- service: input_text.set_value | |
data: | |
value: > | |
{% if state_attr(local_setting_reason, 'max') < 255 %} | |
{{ "**Error! Setting reason helper max length must be 255**" }} | |
{% else %} | |
{{ "Set manually to " + states(local_manual_state) + "." }} | |
{% endif %} | |
target: | |
entity_id: !input setting_reason | |
# ACTION[5].CHOOSE[2]. If there is an active calendar event | |
- conditions: | |
- condition: template | |
value_template: "{{ any_event_active }}" | |
sequence: | |
- service: input_boolean.turn_on | |
target: | |
entity_id: !input required_state | |
- service: input_text.set_value | |
data: | |
value: > | |
{% if state_attr(local_setting_reason, 'max') < 255 %} | |
{{ "**Error! Setting reason helper max length must be 255**" }} | |
{% else %} | |
{{ "Turned on by calendar event '" + current_event.summary | trim + "' until " + as_timestamp(current_event.end) | timestamp_custom('%a %d %b %Y at %H:%M') + "." }} | |
{% endif %} | |
target: | |
entity_id: !input setting_reason | |
# ACTION[5].CHOOSE[3]. If there is no active calendar event | |
- conditions: | |
- condition: template | |
value_template: "{{ not any_event_active }}" | |
sequence: | |
- service: input_boolean.turn_off | |
target: | |
entity_id: !input required_state | |
- service: input_text.set_value | |
data: | |
value: > | |
{% if state_attr(local_setting_reason, 'max') < 255 %} | |
{{ "**Error! Setting reason helper max length must be 255**" }} | |
{% else %} | |
{% if any_future_event %} | |
{{ "Turned off because nothing is scheduled. The next event is '" + next_event.summary | trim + "' " + as_timestamp(next_event.start) | timestamp_custom('on %a %d %b %Y at %H:%M', false) }} | |
{% else %} | |
{{ "Turned off because nothing is scheduled. There are no events scheduled in the next 24 hours." }} | |
{% endif %} | |
{% endif %} | |
target: | |
entity_id: !input setting_reason | |
#ACTION[5].CHOOSE[4]. If the calendar state becomes unknown | |
- conditions: | |
- condition: state | |
entity_id: !input device_calendar | |
state: unknown | |
sequence: | |
- service: input_boolean.turn_off | |
target: | |
entity_id: !input required_state | |
- service: input_text.set_value | |
data: | |
value: > | |
{% if state_attr(local_setting_reason, 'max') < 255 %} | |
{{ "**Error! Setting reason helper max length must be 255**" }} | |
{% else %} | |
{{ 'Turned off because the calendar state is unknown' }} | |
{% endif %} | |
target: | |
entity_id: !input setting_reason | |
#ACTION[5].CHOOSE[5]. If the calendar becomes unavailable | |
- conditions: | |
- condition: state | |
entity_id: !input device_calendar | |
state: unavailable | |
sequence: | |
- service: input_boolean.turn_off | |
target: | |
entity_id: !input required_state | |
- service: input_text.set_value | |
data: | |
value: > | |
{% if state_attr(local_setting_reason, 'max') < 255 %} | |
{{ "**Error! Setting reason helper max length must be 255**" }} | |
{% else %} | |
{{ 'Turned off because the calendar is unavailable.' }} | |
{% endif %} | |
target: | |
entity_id: !input setting_reason | |
# ACTION[5].Default - should never happen! | |
default: | |
- service: input_boolean.turn_off | |
target: | |
entity_id: !input required_state | |
- service: input_text.set_value | |
data: | |
value: > | |
{% if state_attr(local_setting_reason, 'max') < 255 %} | |
{{ "**Error! Setting reason helper max length must be 255**" }} | |
{% else %} | |
{{ "Turned off by because device state canot be determined (program error)" }} | |
{% endif %} | |
target: | |
entity_id: !input setting_reason | |
## ------------------------------------------------------------------------------------------------- | |
## ACTION[6] -- SEND STATE CHANGE TO THE SWITCHED DEVICES (BUT ONLY WHEN NECESSARY) | |
## ------------------------------------------------------------------------------------------------- | |
# ACTION[6].SEQUENCE[0]. Check for each device in the input list whether a change to the setting is required | |
- repeat: | |
for_each: !input switched_devices | |
sequence: | |
- choose: | |
# | |
# ACTION[6].SEQUENCE[0].CHOOSE[0] | |
# Device unknown | |
- conditions: > | |
{{ states(repeat.item) == 'unknown' }} | |
sequence: | |
# Create a notification | |
- service: persistent_notification.create | |
data: | |
title: "Calendar Switch Y2" | |
message: > | |
{{ "The device '" + repeat.item | string + "' is unknown!" }} | |
notification_id: "{{ repeat.item }}" | |
# to prevent duplcate notifications | |
# log entry | |
- service: script.heating_xyz_logfile_entry | |
data: | |
notification_service: !input logging_service_name | |
logfile_title: Calendar Switch Y2 | |
message_preamble: "{{ log_message_preamble }}" | |
message_body: > | |
{{ "The device '" + repeat.item | string + "' is unknown" }} | |
# | |
# ACTION[6].SEQUENCE[0].CHOOSE[1] | |
# Device unavailable | |
- conditions: > | |
{{ states(repeat.item) == 'unavailable' }} | |
sequence: | |
# Create a notification | |
- service: persistent_notification.create | |
data: | |
title: "Calendar Switch Y2" | |
message: > | |
{{ "The device '" + state_attr(repeat.item, 'friendly_name') | string + "' is offline" }} | |
notification_id: > | |
{{ repeat.item }} | |
# to prevent duplcate notifications | |
# Log entry | |
- service: script.heating_xyz_logfile_entry | |
data: | |
notification_service: !input logging_service_name | |
logfile_title: Calendar Switch Y2 | |
message_preamble: "{{ log_message_preamble }}" | |
message_body: > | |
{{ "The device '" + state_attr(repeat.item, 'friendly_name') | string + "' is unavailable" }} | |
# | |
# ACTION[6].SEQUENCE[0].CHOOSE[2] | |
# Device is already in the right state | |
- conditions: > | |
{{ states(repeat.item) == states(local_required_state) }} | |
sequence: | |
# dismiss any previous notifiations as the device is now apparently online | |
- service: persistent_notification.dismiss | |
data: | |
notification_id: "{{ repeat.item }}" | |
# Log entry | |
- service: script.heating_xyz_logfile_entry | |
data: | |
notification_service: !input logging_service_name | |
logfile_title: Calendar Switch Y2 | |
message_preamble: "{{ log_message_preamble }}" | |
message_body: > | |
{{ "The device '" + state_attr(repeat.item, 'friendly_name') | string + "' is already set to " + states(local_required_state) | string }} | |
# | |
# ACTION[6].SEQUENCE[0].DEFAULT | |
# Device state needs to be changed | |
default: | |
# parallel ensures completion even if switch.turn_on/off fails | |
- parallel: | |
# dismiss any previous notifications as the device is now apparently online | |
- service: persistent_notification.dismiss | |
data: | |
notification_id: "{{ repeat.item }}" | |
# | |
# Send the command | |
- if: | |
condition: template | |
value_template: > | |
{{ states(local_required_state) == "on" }} | |
then: | |
- service: switch.turn_on | |
continue_on_error: true | |
target: | |
entity_id: > | |
{{ repeat.item }} | |
else: | |
- service: switch.turn_off | |
continue_on_error: true | |
target: | |
entity_id: > | |
{{ repeat.item }} | |
# | |
# log the command | |
- service: script.heating_xyz_logfile_entry | |
data: | |
notification_service: !input logging_service_name | |
logfile_title: Calendar Switch Y2 | |
message_preamble: "{{ log_message_preamble }}" | |
message_body: > | |
{{ "The device '" + state_attr(repeat.item, 'friendly_name') | string + "' is set to " + states(local_required_state) | string }} | |
# | |
# Start the echoblock timer | |
# Only starts if there is a change. It is OK if it starts more than once (only ending triggers this automation). | |
- service: timer.start | |
data: | |
duration: | |
seconds: 30 | |
target: | |
entity_id: !input echoblock_timer | |
# | |
# ACTION[7] log the reason | |
# | |
- service: script.heating_xyz_logfile_entry | |
data: | |
notification_service: !input logging_service_name | |
logfile_title: Calendar Switch Y2 | |
message_preamble: "{{ log_message_preamble }}" | |
message_body: > | |
{{ "New state: " + states(local_setting_reason) | string }} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
N.B. Before upgrading to this version of the blueprint, you need to install the Heating XYZ Log File Entry script