I noticed this note from source.
Doesn’t look like this every really got anything to run async and I was hoping to create a loop that ran on precise intervals.
Is it still a problem to use time.sleep
inside of python_scripts
?
by script do you mean python script or HA script?
If ha script, the service is:
delay: 00:00:30
But you can also use a wait_template
to wait until something happens:
- wait_template: '{{ states("alarm_control_panel.alarm").split("_")[0] != "triggered"}}'
timeout: '00:15:00'
could you explain why you need time.sleep
?
I had an idea which I was looking to get started on but I can’t decide where it best fits. I want to make an intelligent light timer that updates an actionable notification in the ios app. Playing through the scenario for my garage:
- If someone opens the door to the garage and it is dark out and the lights are off then turn on the lights for 5 minutes (i have an automation do this now)
- Update an actionable notification on the ios app that shows the current coutdown and allows a user to:
- sleep (add 5 minutes to the counter)
- disable (don’t do anything else until the user shuts off the light)
- Opening the door while the timer is active will set the timer count to
max(count, 5)
I think this means that I need either a polling loop or some async event handlers tied to a counter.
This seems beyond one or two automations
and scripts
don’t really seem to help that. python_scripts
look like maybe they could do this but there would be a lot of time.sleep()
and that appears to be discouraged. I’m thinking its a custom_component
?
I hadn’t read about the wait template yet, maybe:
- automation 1:
- trigger on door events and update counter to
max(count, 5)
- trigger on door events and update counter to
- automation 2:
- trigger on counter state and wait_template for counter value of -1 (timeout of 1 minute)
- decrement counter and shut off on 0
- automation 3:
- handle ios events to update counter value
Really wanted this to be in a single automation but it doesn’t appear there is branching to support the different triggers.
I seem to have this working now as a script and three automations. Not quite as contained as I’d like as I plan to reuse for other lighting areas around the house.
The script was needed to prevent the automation from firing twice on the wait_interval
light_timer_delay:
description: Timed delay to decrement count
fields:
counter_id:
description: entity_id of counter to modify
expected_state:
description: present state of counter_id
sequence:
# wait one minute to decrement counter unless iOS user changes count
- wait_template: "{{ states(counter_id) != expected_state }}"
timeout: '00:01:00'
- service: input_number.decrement
data_template:
entity_id: "{{ counter_id }}"
Then the automations
- id: garage_light_automation_1
alias: Garage Lights Door Event Handler
description: Update garage_timer_input on door events when it is night
trigger:
- platform: state
entity_id: binary_sensor.garage_door
from: 'off'
to: 'on'
condition:
# only do this when it is dark out
- condition: state
entity_id: sun.sun
state: below_horizon
# don't do this when the timer is disabled (-1) and the garage light is on
- condition: or
conditions:
- condition: numeric_state
entity_id: input_number.garage_timer_input
above: -1
- condition: state
entity_id: light.frst_garage_interior
state: 'off'
action:
- service: input_number.set_value
data_template:
entity_id: input_number.garage_timer_input
value: "{{ [states('input_number.garage_timer_input')|int, 5]|max }}"
- id: garage_light_automation_2
alias: Garage Lights Counter State Handler
description: Decrement garage_timer_input and take actions
trigger:
- platform: state
entity_id: input_number.garage_timer_input
action:
- delay: '00:00:01'
# a value of '-1' indicates that the timer has been disabled by iOS app
- condition: numeric_state
entity_id: input_number.garage_timer_input
above: -1
# a count of '0' means we turn off, otherwise stay on
- service_template: >
{% if states('input_number.garage_timer_input')|int == 0 %}
light.turn_off
{% else %}
light.turn_on
{% endif %}
entity_id: light.frst_garage_interior
# Nothing further to do if the count is 0
- condition: numeric_state
entity_id: input_number.garage_timer_input
above: 0
# update iOS app notification (apns-collapse-id: garge-interior-light)
- service: notify.mobile_app_devans_iphone
data_template:
title: Garage Timer
message: Garage lights will turn off in {{ trigger.to_state.state|int }} minutes.
data:
apns_headers:
apns-collapse-id: garge-interior-light
push:
category: gargetimer
action_data:
entity_id: input_number.garage_timer_input
# call script to wait for timer change (ie disabled) or decrement on interval
- service: script.light_timer_delay
data_template:
counter_id: input_number.garage_timer_input
expected_state: "{{ trigger.to_state.state }}"
- id: garage_light_automation_3
alias: Garage Lights iOS App Event Handler
description: Update garage_timer_input on app events
trigger:
- platform: event
event_type: ios.notification_action_fired
event_data:
action_data:
entity_id: input_number.garage_timer_input
action:
# set timer value based on button pressed in iOS notification
service: input_number.set_value
data_template:
entity_id: input_number.garage_timer_input
value: >
{% if trigger.event.data.actionName == "SLEEP_TIMER" %}
{{ states('input_number.garage_timer_input')|int + 6 }}
{% else %}
-1
{% endif %}
Probably the last piece to share is the notification config:
ios:
push:
categories:
- name: Garage Timer
identifier: 'gargetimer'
actions:
- identifier: 'SLEEP_TIMER'
title: 'Sleep'
activationMode: 'background'
authenticationRequired: false
destructive: false
behavior: 'default'
- identifier: 'DISABLE_TIMER'
title: 'Disable'
activationMode: 'background'
authenticationRequired: false
destructive: false
behavior: 'default'