You could use an event trigger that watches for state_changed events. Then use a condition that requires old_state to be none, and entity_id to start with geo_location.lightning_strike_.
How does it look in the code to set wildcards for entity IDs?
Something like this:
- trigger:
platform: event
event_type: state_changed
condition:
condition: template
value_template: >
{{ trigger.old_state is none and
trigger.entity_id.startswith('geo_location.lightning_strike_') }}
action:
...
Thanks, will give a shot. Have to wait for the next storm to test!
Why not just create a temporary entity on the States page? You can enter whatever you want at the top and click SET STATE. It will just create an entry in the state machine, which is what the automation will react to. Next time you restart HA that entry will be gone.
So here is the automation I am testing:
- alias: Lightning Timer Start
initial_state: 'on'
trigger:
platform: event
event_type: state_changed
condition:
condition: template
value_template: >
{{ trigger.old_state is none and
trigger.entity_id.startswith('geo_location.lightning_strike_') }}
action:
- service: input_boolean.turn_on
data:
entity_id: input_boolean.lightning_state
I create an entity “geo_location.lightning_strike_3694317” with a state of “10” - it appears on my state list correctly, but this boolean doesn’t turn on.
Sorry, my bad. Try this:
- alias: Lightning Timer Start
initial_state: 'on'
trigger:
platform: event
event_type: state_changed
condition:
condition: template
value_template: >
{{ trigger.event.data.old_state is none and
trigger.event.data.entity_id.startswith('geo_location.lightning_strike_') }}
action:
- service: input_boolean.turn_on
data:
entity_id: input_boolean.lightning_state
Ok, that works, thanks.
do you have the same with the end of the lightning show in the sky ?
With this automation, any way to have the state of this wildcard entity in a message?
{{ states.sensor.startswith(‘geo_location.lightning_strike_’).state }} or similar?
Sorry for taking so long to respond. If you want to add a step to the action part of the automation, then yes, use this:
{{ trigger.event.data.new_state.state }}
Just to complicate things - I didn’t want to be notified about every strike, so I tried to come up with a system to only get notified by the first one, and if there had been no strikes for 30 minutes, to re-enable notifications. This puts the notification action in a different automation than the initial strike detection. Can you think of a way to add the state of the lightning strike entity to the annoucement, which occurs in a different automation? Set a variable equal to it?
Here’s what I have so far:
- alias: Lightning Timer Start
initial_state: 'on'
trigger:
platform: event
event_type: state_changed
condition:
condition: template
value_template: >
{{ trigger.event.data.old_state is none and
trigger.event.data.entity_id.startswith('geo_location.lightning_strike_') }}
action:
- service: timer.cancel
data:
entity_id: timer.lightning_timer
- service: timer.start
data:
entity_id: timer.lightning_timer
duration: '00:30:00'
- service: input_boolean.turn_on
data:
entity_id: input_boolean.lightning_state
- alias: Lightning Alarm
initial_state: 'on'
trigger:
platform: state
entity_id: input_boolean.lightning_state
from: 'off'
to: 'on'
action:
- service: notify.email3
data_template:
message: 'Skynet reports lightning strike.'
- service: notify.alexa_media
data_template:
message: 'Skynet reports lightning strike within 30 miles.'
data:
type: announce
target: [media_player.kitchen_echo_2,media_player.jason_s_spot]
- alias: Lightning Reset
initial_state: 'on'
trigger:
platform: event
event_type: timer.finished
event_data:
entity_id: timer.lightning_timer
action:
- service: input_boolean.turn_off
data:
entity_id: input_boolean.lightning_state
- service: timer.cancel
data:
entity_id: timer.lightning_timer
I think you can make this much simpler:
- alias: Lightning Timer Start
initial_state: 'on'
trigger:
platform: event
event_type: state_changed
condition:
- condition: template
value_template: >
{{ trigger.event.data.old_state is none and
trigger.event.data.entity_id.startswith('geo_location.lightning_strike_') }}
- condition: state
entity_id: timer.lightning_timer
state: idle
action:
- service: timer.start
data:
entity_id: timer.lightning_timer
duration: '00:30:00'
- service: input_boolean.turn_on
data:
entity_id: input_boolean.lightning_state
- service: notify.email3
data_template:
message: 'Skynet reports lightning strike.'
- service: notify.alexa_media
data_template:
message: 'Skynet reports lightning strike within 30 miles.'
data:
type: announce
target: [media_player.kitchen_echo_2,media_player.jason_s_spot]
- alias: Lightning Reset
initial_state: 'on'
trigger:
platform: event
event_type: timer.finished
event_data:
entity_id: timer.lightning_timer
action:
- service: input_boolean.turn_off
data:
entity_id: input_boolean.lightning_state
Not sure where you want to use {{ trigger.event.data.new_state.state }}
, but now you can.
I assume you’re using input_boolean.lightning_state
for another reason, but if not, you can simplify this even more by removing it and the second automation.
Very nice. The one thing this doesn’t do that my original code does is “reset” the timer if a new strike occurs. My initial idea was if there was a strike every 15 minutes, it would only give a single warning, even if this happened all day long. It was only after 30 minutes of no strikes would it allow another announcement. I think your code would allow a new announcement every 30 minutes, even if there was an ongoing storm. That’s why I had the extra booleans in there.
the state of each new entity has the # of miles from your house to the strike, so I wanted that to be included in the announcement, like this:
- alias: Lightning Timer Start
initial_state: 'on'
trigger:
platform: event
event_type: state_changed
condition:
- condition: template
value_template: >
{{ trigger.event.data.old_state is none and
trigger.event.data.entity_id.startswith('geo_location.lightning_strike_') }}
- condition: state
entity_id: timer.lightning_timer
state: idle
action:
- service: timer.start
data:
entity_id: timer.lightning_timer
duration: '00:30:00'
- service: notify.email3
data_template:
message: 'Skynet reports lightning strike within {{ trigger.event.data.new_state.state }} miles.'
- service: notify.alexa_media
data_template:
message: 'Skynet reports lightning strike within {{ trigger.event.data.new_state.state }} miles.'
data:
type: announce
target: [media_player.kitchen_echo_2,media_player.jason_s_spot]
What would be even better would be if I could save the state in a variable (the # of miles from the strike) and only re-announce if there was one closer (within that 30 minute period).
Ok, I think you can implement the first idea this way. This first automation simply starts, or restarts, the timer whenever there is a new lightning strike. It also saves the state for use in the second automation. (Of course, you need to define input_text.last_strike
. I suppose you could also use an input_number
instead of an input_text
.)
- alias: Lightning Timer Start
initial_state: 'on'
trigger:
platform: event
event_type: state_changed
condition:
- condition: template
value_template: >
{{ trigger.event.data.old_state is none and
trigger.event.data.entity_id.startswith('geo_location.lightning_strike_') }}
action:
- service: input_text.set_value
data_template:
entity_id: input_text.last_strike
value: "{{ trigger.event.data.new_state.state }}"
# This will start, or restart, the timer.
- service: timer.start
data:
entity_id: timer.lightning_timer
duration: '00:30:00'
This second automation triggers only when the timer starts (i.e., timer.start
is called while the timer is idle.) I haven’t tested this, but according to the docs, if timer.start
is called while the timer is active, it should fire the timer.restarted
event instead of timer.started
.
- alias: Lightning Announce
initial_state: 'on'
trigger:
# Trigger only when timer starts (i.e., not when it restarts.)
platform: event
event_type: timer.started
event_data:
entity_id: timer.lightning_timer
action:
- service: notify.email3
data_template:
message: 'Skynet reports lightning strike within {{ states('input_text.last_strike') }} miles.'
- service: notify.alexa_media
data_template:
message: 'Skynet reports lightning strike within {{ states('input_text.last_strike') }} miles.'
data:
type: announce
target: [media_player.kitchen_echo_2,media_player.jason_s_spot]
Looks good, thanks!
Could I use two variables, input_text.last_strike and closest_strike, and make an extra announcement automation if the last_strike is closer than the closest_strike, and then set closest_strike to be equal to last_strike?
The message line is giving this error:
in “/config/automations.yaml”, line 33, column 7
expected , but found ‘’
Oops, my bad. Try:
message: "Skynet reports lightning strike within {{ states('input_text.last_strike') }} miles."
Testing this automation - it’s announcing every new strike. From what I can tell, the timer.started trigger is firing every time the timer is reset with the timer.start service. It’s not registering it as a timer.restarted trigger if timer.start is acting on an active timer.
Sorry about that. Looking at the code I discovered the timer.restarted
event is only fired if the timer was paused. Now that I look again, the docs say the same thing:
Starting a timer triggers a started event unless the timer is paused, in that case, it triggers a restarted event.
That’s unfortunate, because starting a timer that is running does restart it.
Anyway, maybe you can change the first automation to first pause the timer (which does nothing if it isn’t running.)
- service: timer.pause
data:
entity_id: timer.lightning_timer
- service: timer.start
data:
entity_id: timer.lightning_timer
duration: '00:30:00'
So if the timer isn’t running, the first step does nothing, and the second step should cause a timer.started
event. But if the timer is running, the first step will pause it, causing the second step to restart it as before, but now it will fire a timer.restarted
event.