So one of my biggest gripes with the Home Assistant Voice was that I couldn’t have timer entities in home assistant to use with my dashboard and to be able to set timers on different satellites (or different rooms in my case).
I fixed this now with a rather simple automation and some help from LLM.
Here is how it works:
You need to set up a timer for each area under helpers. So I set up timer.kitchen, timer.living_room and so on.
Here is the automation that is triggered by custom sentences. I have to specify {room} and {duration}. I am using an LLM to have it format the spoken duration into a timedelta string.
Automation:
alias: VA Set Timer to Duration
description: ""
triggers:
- trigger: conversation
command:
- Set {room} timer to {duration}
- Start {duration} timer on {room}
conditions: []
actions:
- choose:
- conditions:
- condition: template
value_template: >-
{{ trigger.slots.room == "kitchen" or trigger.slots.room ==
"Kitchen" }}
sequence:
- alias: Send the request to the LLM
action: conversation.process
data:
text: >-
You are an AI process that transforms a timer command into a
structured timedelta string.
This is the voice command query provided by the user: "{{
trigger.sentence }}"
Here is an example of a structured timedelta string that I
expect in response: 00:30:00 The timedelta string works like
this: the first two numbers represent the hours, the second two
numbers the minutes and the last two numbers the second. So the
example shows 30 Minutes.
This is the duration provided by the voice command: "{{
trigger.slots.duration }}"
Please format this into a timedelta string using the provided
explanation.
IMPORTANT: You must reply with only the timedelta string,
nothing before nor after because your response will be processed
by a action component of a smart home service. So also no code
tags. Only the timedelta string!
agent_id: conversation.chatgpt
response_variable: timedelta
- action: timer.start
metadata: {}
data:
duration: "{{ timedelta.response.speech.plain.speech }}"
target:
entity_id: timer.kitchen
- set_conversation_response: "{{ trigger.slots.room }} timer set to {{ trigger.slots.duration }}"
- conditions:
- condition: template
value_template: >-
{{ trigger.slots.room == "bathroom" or trigger.slots.room ==
"Bathroom" }}
sequence:
- alias: Send the request to the LLM
action: conversation.process
data:
text: >-
You are an AI process that transforms a timer command into a
structured timedelta string.
This is the voice command query provided by the user: "{{
trigger.sentence }}"
Here is an example of a structured timedelta string that I
expect in response: 00:30:00 The timedelta string works like
this: the first two numbers represent the hours, the second two
numbers the minutes and the last two numbers the second. So the
example shows 30 Minutes.
This is the duration provided by the voice command: "{{
trigger.slots.duration }}"
Please format this into a timedelta string using the provided
explanation.
IMPORTANT: You must reply with only the timedelta string,
nothing before nor after because your response will be processed
by a action component of a smart home service. So also no code
tags. Only the timedelta string!
agent_id: conversation.chatgpt
response_variable: timedelta
- action: timer.start
metadata: {}
data:
duration: "{{ timedelta.response.speech.plain.speech }}"
target:
entity_id: timer.bathroom
- set_conversation_response: "{{ trigger.slots.room }} timer set to {{ trigger.slots.duration }}"
- conditions:
- condition: template
value_template: >-
{{ trigger.slots.room == "living room" or trigger.slots.room ==
"Living Room" }}
sequence:
- alias: Send the request to the LLM
action: conversation.process
data:
text: >-
You are an AI process that transforms a timer command into a
structured timedelta string.
This is the voice command query provided by the user: "{{
trigger.sentence }}"
Here is an example of a structured timedelta string that I
expect in response: 00:30:00 The timedelta string works like
this: the first two numbers represent the hours, the second two
numbers the minutes and the last two numbers the second. So the
example shows 30 Minutes.
This is the duration provided by the voice command: "{{
trigger.slots.duration }}"
Please format this into a timedelta string using the provided
explanation.
IMPORTANT: You must reply with only the timedelta string,
nothing before nor after because your response will be processed
by a action component of a smart home service. So also no code
tags. Only the timedelta string!
agent_id: conversation.chatgpt
response_variable: timedelta
- action: timer.start
metadata: {}
data:
duration: "{{ timedelta.response.speech.plain.speech }}"
target:
entity_id: timer.living_room
- set_conversation_response: "{{ trigger.slots.room }} timer set to {{ trigger.slots.duration }}"
- conditions:
- condition: template
value_template: >-
{{ trigger.slots.room == "Office" or trigger.slots.room ==
"office" }}
sequence:
- alias: Send the request to the LLM
action: conversation.process
data:
text: >-
You are an AI process that transforms a timer command into a
structured timedelta string.
This is the voice command query provided by the user: "{{
trigger.sentence }}"
Here is an example of a structured timedelta string that I
expect in response: 00:30:00 The timedelta string works like
this: the first two numbers represent the hours, the second two
numbers the minutes and the last two numbers the second. So the
example shows 30 Minutes.
This is the duration provided by the voice command: "{{
trigger.slots.duration }}"
Please format this into a timedelta string using the provided
explanation.
IMPORTANT: You must reply with only the timedelta string,
nothing before nor after because your response will be processed
by a action component of a smart home service. So also no code
tags. Only the timedelta string!
agent_id: conversation.chatgpt
response_variable: timedelta
- action: timer.start
metadata: {}
data:
duration: "{{ timedelta.response.speech.plain.speech }}"
target:
entity_id: timer.office
- set_conversation_response: "{{ trigger.slots.room }} timer set to {{ trigger.slots.duration }}"
- conditions:
- condition: template
value_template: >-
{{ trigger.slots.room == "bedroom" or trigger.slots.room ==
"Bedroom" }}
sequence:
- alias: Send the request to the LLM
action: conversation.process
data:
text: >-
You are an AI process that transforms a timer command into a
structured timedelta string.
This is the voice command query provided by the user: "{{
trigger.sentence }}"
Here is an example of a structured timedelta string that I
expect in response: 00:30:00 The timedelta string works like
this: the first two numbers represent the hours, the second two
numbers the minutes and the last two numbers the second. So the
example shows 30 Minutes.
This is the duration provided by the voice command: "{{
trigger.slots.duration }}"
Please format this into a timedelta string using the provided
explanation.
IMPORTANT: You must reply with only the timedelta string,
nothing before nor after because your response will be processed
by a action component of a smart home service. So also no code
tags. Only the timedelta string!
agent_id: conversation.chatgpt
response_variable: timedelta
- action: timer.start
metadata: {}
data:
duration: "{{ timedelta.response.speech.plain.speech }}"
target:
entity_id: timer.bedroom
- set_conversation_response: "{{ trigger.slots.room }} timer set to {{ trigger.slots.duration }}"
- conditions:
- condition: template
value_template: >-
{{ trigger.slots.room == "guest room" or trigger.slots.room ==
"Guest Room" }}
sequence:
- alias: Send the request to the LLM
action: conversation.process
data:
text: >-
You are an AI process that transforms a timer command into a
structured timedelta string.
This is the voice command query provided by the user: "{{
trigger.sentence }}"
Here is an example of a structured timedelta string that I
expect in response: 00:30:00 The timedelta string works like
this: the first two numbers represent the hours, the second two
numbers the minutes and the last two numbers the second. So the
example shows 30 Minutes.
This is the duration provided by the voice command: "{{
trigger.slots.duration }}"
Please format this into a timedelta string using the provided
explanation.
IMPORTANT: You must reply with only the timedelta string,
nothing before nor after because your response will be processed
by a action component of a smart home service. So also no code
tags. Only the timedelta string!
agent_id: conversation.chatgpt
response_variable: timedelta
- action: timer.start
metadata: {}
data:
duration: "{{ timedelta.response.speech.plain.speech }}"
target:
entity_id: timer.guest_room
- set_conversation_response: "{{ trigger.slots.room }} timer set to {{ trigger.slots.duration }}"
default:
- set_conversation_response: "{{ trigger.slots.room }} is not a valid area. "
mode: single
The automation checks which room is specified and set with the help of the llm the duration of the timer and starts it.
I have another automation which runs when the timer finishes. I have set up an automation for each timer. Here is the automation for the kitchen timer as an example:
Kitchen timer Finished:
alias: VA Kitchen timer finished
description: ""
triggers:
- event_type: timer.finished
event_data:
entity_id: timer.kitchen
trigger: event
conditions: []
actions:
- repeat:
sequence:
- parallel:
- action: assist_satellite.announce
metadata: {}
data:
message: Kitchen timer is finished
target:
entity_id: assist_satellite.home_assistant_voice_kitchen_assist_satellite
- data:
entity_id: media_player.home_assistant_voice_kitchen_media_player
media_content_id: /local/sounds/alarm-digital-clock-beep.wav
media_content_type: audio/mp3
action: media_player.play_media
- delay:
hours: 0
minutes: 0
seconds: 2
milliseconds: 0
until:
- condition: state
entity_id: assist_satellite.home_assistant_voice_kitchen_assist_satellite
state: listening
mode: single
The automation announces that the timer is finished and plays a mp3 from my local folder. It does this until the satellite changes to listen, so I just have to say “ok nabu” to make it stop, just like with the regular timer.
This actually works really well and I am quite happy with the functionality.
Maybe someone here wants to help me make this into a blueprint?