Timer - Execute and Action from Lovelace UI

I thought this was pretty cool so I thought I’d share. Here is a timer that you can set to perform an automation from the Lovelace UI. It could be built out to do just about anything, but as it stands it can turn_off, turn_on, or toggle something after a custom delay. I have tested it with switches, lights, and automations.

Here is the configuration information. You’ll need to add lines to configuration.yaml, automation.yaml, scripts.yaml, customize.yaml, add a python script, and update your lovelace config. To get the custom text in the markdown card in lovelace, you’ll need to install lovelace-markdown-mod.

########### configuration.yaml ###########

input_text:
  # for ui input
  timer_string:
    name: "Time (hr:min:sec)"
    pattern: '\d\d:[0,6]\d:[0,6]\d'
    initial: '00:00:00'
  # for storing action
  timer_0_task:
    name: "Timer_0 Task"
    initial: "None"
  timer_1_task:
    name: "Timer_1 Task"
    initial: "None"
  timer_2_task:
    name: "Timer_2 Task"
    initial: "None"
  timer_3_task:
    name: "Timer_3 Task"
    initial: "None"
  timer_4_task:
    name: "Timer_4 Task"
    initial: "None"
    
timer:
  # timers
  timer_0:
  timer_1:
  timer_2:
  timer_3:
  timer_4:
  
input_select:
  # list of timers for ui
  timer_list:
    name: Timers
    options:
      - timer_0
      - timer_1
      - timer_2
      - timer_3
      - timer_4
  # action options for ui
  timer_to_state:
    name: "Timer: To State"
    options:
      - 'turn_on'
      - 'turn_off'
      - 'toggle'
  # list of entities for ui - list populated in automation at boot
  timer_entity_id:
    name: "Timer: Entity ID"
    options:
      - "run 'python_script.populate_timer_entity_id' to populate"
      
########### automation.yaml ###########

# on boot, compile list of items to have as options for ui
- alias: '[HA] Timer - Load entity ids on boot'
  trigger:
  - platform: homeassistant
    event: start
  condition: []
  action:
  - service: python_script.populate_timer_entity_id
  initial_state: 'on'

# timer finished - perform recorded action from ui
- alias: '[HA] Timer X'
  trigger:
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.timer_0
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.timer_1
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.timer_2
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.timer_3
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.timer_4
  condition: []
  action:
  - service: script.timer_x_execute
    data_template:
      timer: '{{trigger.event.data.entity_id}}'
      
########### script.yaml ###########

timer_x_init:
  sequence:
  # record action to be done when timer finished
  - service: script.timer_x_update_task_message
  # start timer
  - service: timer.start
    data_template:
      entity_id: >-
        {{-"timer."-}}{{- states("input_select.timer_list") -}}
      duration: >-
        {{(states('input_text.timer_string'))}}

timer_x_execute:
  sequence:
  # execute recorded action
  - service_template: >-
      {%- if not timer -%}
        {%- set timer = 'timer.timer_1' -%}
      {%- endif -%}
      {%- set domain_name = timer.split('.') -%} 
      {%- set read_action = 'input_text.'+domain_name[1] + '_task' -%}
      {%- set action = states(read_action).split(' ') -%}
      {% set domain_name = action[1].split('.') %}
      {{- domain_name[0] -}} {{-'.'-}} {{- action[0] -}}
    data_template:
      entity_id: >-
        {%- if not timer -%}
          {%- set timer = 'timer.timer_0' -%}
        {%- endif -%}
        {%- set domain_name = timer.split('.') -%} 
        {%- set read_action = 'input_text.' + domain_name[1] + '_task' -%}
        {%- set ent_id = states(read_action).split(' ') -%}
        {{-ent_id[1]-}}
  # clear stored action
  - service: input_text.set_value
    data_template:
        entity_id: >-
          {%- if not timer -%}
            {%- set timer = 'timer.timer_0' -%}
          {%- endif -%}
          {%- set domain_name = timer.split('.') -%} 
          {{"input_text."}}{{ domain_name[1] }}{{"_task"}}
        value: 'unknown'

timer_x_cancel:
  sequence:
  # cancel timer
  - service: timer.cancel
    data_template:
      entity_id: >-
        {{-"timer."-}}{{- states("input_select.timer_list") -}}
  # clear stored action
  - service: input_text.set_value
    data_template:
        entity_id: >-
          {%- if not timer -%}
            {%- set timer = 'timer.timer_0' -%}
          {%- endif -%}
          {%- set domain_name = timer.split('.') -%} 
          {{"input_text."}}{{ domain_name[1] }}{{"_task"}}
        value: 'unknown'

timer_x_update_task_message:
  sequence:
  # read action to perform at end of timer
  - service: input_text.set_value
    data_template:
        entity_id: '{{"input_text."}}{{ states("input_select.timer_list") }}{{"_task"}}'
        value: '{{states("input_select.timer_to_state")}}{{" "}}{{ states("input_select.timer_entity_id") }}'
        
########### python_scripts/populate_timer_entity_id.py ###########

# pull all entities in the group group.lights
group_entities = hass.states.get('group.lights').attributes['entity_id']
timer_entities = []
for e in group_entities:
    timer_entities.append(e)
timer_entities.append('climate.upstairs')
timer_entities.append('script.party_time_is_over_go_home')
service_data = {'entity_id': 'input_select.timer_entity_id',
                'options': timer_entities}
hass.services.call('input_select', 'set_options', service_data)


########### lovelace ###########
  - badges: []
    cards:
      - cards:
          - entities:
              - entity: input_select.timer_list
              - entity: input_text.timer_string
              - entity: input_select.timer_entity_id
              - entity: input_select.timer_to_state
              - entity: script.timer_x_init
            show_header_toggle: false
            title: Timer - Change state in x time
            type: entities
          - card:
              entities:
                - entity: timer.timer_0
              type: entities
            conditions:
              - entity: timer.timer_0
                state_not: idle
            type: conditional
          - card:
              entities:
                - entity: timer.timer_1
              type: entities
            conditions:
              - entity: timer.timer_1
                state_not: idle
            type: conditional
          - card:
              entities:
                - entity: timer.timer_2
              type: entities
            conditions:
              - entity: timer.timer_2
                state_not: idle
            type: conditional
          - card:
              entities:
                - entity: timer.timer_3
              type: entities
            conditions:
              - entity: timer.timer_3
                state_not: idle
            type: conditional
          - card:
              entities:
                - entity: timer.timer_4
              type: entities
            conditions:
              - entity: timer.timer_4
                state_not: idle
            type: conditional
        type: vertical-stack
      - content: |-
          ### Timer 0
          state: [[ timer.timer_0 ]]
          total duration: [[ timer.timer_0.attributes.duration ]]
          task: [[ input_text.timer_0_task ]]
          ### Timer 1
          state: [[ timer.timer_1 ]]
          total duration: [[ timer.timer_1.attributes.duration ]]
          task: [[ input_text.timer_1_task ]]
          ### Timer 2
          state: [[ timer.timer_2 ]]
          total duration: [[ timer.timer_2.attributes.duration ]]
          task: [[ input_text.timer_2_task ]]
          ### Timer 3
          state: [[ timer.timer_3 ]]
          total duration: [[ timer.timer_3.attributes.duration ]]
          task: [[ input_text.timer_3_task ]]
          ### Timer 4
          state: [[ timer.timer_4 ]]
          total duration: [[ timer.timer_4.attributes.duration ]]
          task: [[ input_text.timer_4_task ]]
        title: Timer Status
        type: markdown
    icon: 'mdi:timer'
    title: Timer
    
########### customize.yaml ###########

script.timer_x_init:
  friendly_name: Run Timer
  icon: mdi:timer

script.timer_x_cancel:
  friendly_name: Cancel Timer
  icon: mdi:cancel

Let me know if you need any help implementing.

14 Likes

Hello, this is just where i was looking for!
Maybe you can help me out a little.
This is what i did:

  • Installed lovelace-markdown-mod (get the raw data from the github, create the markdown-mod.js), and put it in the www folder. Did i have to do more with the files on that github?
  • Copy everything to the configuration, script, automation and customize.
  • Addes python_scripts: to configuration
  • Created populate_timer_entity_id.py with the your data and put the file in config/python_scripts
  • Created group.lights filled with entities i want to control

After doing this i get the following screen:


I can’t select the entities and the input on the right panel isn’t oke?

What am i missing?

Thanks!

Sorry for the late reply. My power has been out for the last 2 days and is still out. I got to look at my configuration. I forget how I installed the markdown mod. It was my first custom card in lovelace, so I don’t remember. I’ll get back to you if I get juiced up.

It does look like from your screenshot that you still need to run the python script to populate your entity ID list. You can run it from the services menu. If it still doesn’t populate, then there is something wrong in your configuration.

The markdown looks like that because the markdown mod is not taking over the built in markdown card. If you set it up correctly, you might just require a reboot of HA. I think it installs a python library when you first boot up and then you need to reboot to use it.

The worst thing that can happen to us :slight_smile: .

Like this on the picture and then call the service?
After a reboot there isn’t changing anything.
run%20script

Next week i’m going to reinstall the markdown mod, maybe i did it to quick :wink:

You’re telling me. My smart home gets pretty dumb without power. Power is still out… We’re hoping in the next day or so :roll_eyes:

Yes, that is how you run the script. You may need to edit it to assign the group(s) that you want to populate. By default, it’s set to group.lights Though, you mentioned that you have created that group already.

I included an automation that runs the python script on boot… So something is not right. Did you get any errors in your log? Did you confirm that the group exists in the dev panel? I might need to see your config to help you troubleshoot it.

@gremblin, how can I modify the python script to display 2 groups.
I am currently giving group.all_lights and would still like to add group.all_switches.

But otherwise it works very well with many thanks for that!

Kind regards

complement:

or should i make a group with all_light and all_switches?

@Johann_Edelmuller append the timer_entities list. In the example, I show you how to append single items, but if you want to add another group you could do something like this using python’s list extend function.

group_entities = hass.states.get('group.lights').attributes['entity_id']
group_entities.extend(hass.states.get('group.switches').attributes['entity_id'])
2 Likes

thx for this

1 Like

When i run the script, there isn’t happening anyhthing, have entity’s in the group.light…
Don’t know whats going wrong…

You got to give me more information.

When you run the script, it should populate the list for your drop down menu input_select.timer_entity_id. Did you check your logs?

Can you share your config entries?

hi there. im pretty new to home assistant and yaml. can you please be a bit more specific about how to go about populating the timer entity id section? i have also looked at the python scripts section on the HA website but it makes absoloutley no sense to me. i am running hassbian so i only have terminal to work with and i will say now that i will need instrustions on how to carry out basic commands like creating a folder in a specific path for example… please help. i would really like to implement this timer but i can only get it to the point where i can see the ui, but no entities etc are in the drop box. thanks.

a step by step tutorial would really be helpful for people like me who dont have much of a backround with writing scripts

It sounds like your issue is with navigating a linux command line… This is outside of home assistant, this is basic linux command line stuff. You might be happier using HASSIO since it sounds like you don’t have much experience at the command line. Either that or stick with what you got and enjoy the learning experience. Maybe find an online class for the basics of linux command line. How to navigate through directories, make directories, etc. A third option might be to set up SMB (samba share) so that you can navigate your config folder from a Windows or Mac remotely. Do some googling to find the commands to do that. That will probably give you most of what you need to set up your config files.

That said, I will try to answer your question:

  • Create a folder in the same directory as your config.yaml called python_scripts (at the command line cd into that directory and mkdir python_scripts).

  • Add a line in your config.yaml with

    python_script:

    That will enable the service to be able to call python scripts from automations or from the developer tools page.

I hope this helps. If not, please be a little bit more specific with what you need help with. Welcome to home assistant and to the forums!

having an issue running the python script. Any ideas

Error executing script: 'NoneType' object is not subscriptable
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/python_script/__init__.py", line 195, in execute
    exec(compiled.code, restricted_globals, local)
  File "populate_timer_entity_id.py", line 2, in <module>
  File "/usr/local/lib/python3.7/site-packages/RestrictedPython/Eval.py", line 35, in default_guarded_getitem
    return ob[index]
TypeError: 'NoneType' object is not subscriptable

Did you properly edit the python script? It looks like you are trying to add an entity that does not exist.

Hi Gremblin
I have issue relate Lovelace
I don’t know this step, is create new file?
Thanks

########### customize.yaml ###########

script.timer_x_init:
  friendly_name: 'Run Timer'
  icon: mdi:timer
  
script.timer_x_init:
  friendly_name: 'Cancel Timer'
  icon: mdi:cancel

Yes. customize.yaml is a new file in your config directory. You will need to add the following line to your config.yaml to load it:

customize: !include customize.yaml

Looks like I had a typo in there. The file should look like this: I just updated it in the original post. Thanks for drawing attention to it :+1:

########### customize.yaml ###########

script.timer_x_init:
  friendly_name: Run Timer
  icon: mdi:timer

script.timer_x_cancel:
  friendly_name: Cancel Timer
  icon: mdi:cancel

Here is some additional information about customizing: Customizing entities - Home Assistant

You could also accomplish this in the Lovelace UI. These lines just give the entities a nice name and an icon: Customizing entities - Home Assistant

1 Like

Thanks so much! This worked really well until v0.104 where they got rid of group.all_*
I’m afraid I don’t know Python or HA well enough to come up with a quick fix. Could you please propose one? Thank you!

I’m working on a fix that should work with 0.105 (I’m working in the dev branch) . So far it’s looking good. Probably need a week to get to a solution. Don’t have much time to work on it. This won’t work with 0.104 though. So it won’t be a solution until then anyway.

Github has been updated. Note, that this is for HA v0.105 and is not compatible with previous versions. You’ll have to wait for the release or attempt to install the dev version (which I don’t recommend).

This update is to make it compatible with 0.105 and allows for timers > 24 hours.