I run home-assistant to give me central control of many of my smart home items. One of the integrations available via home-assistant is to expose your various tools to google assistant. Unfortunately because of limitations with what google will allow, this only works with a subset of integrations including lights, switches and climate devices. As a result of this if you want to use voice to control or query other devices you need a different solution. In this post, I will explain how to make an input select device available via Google home and IFTTT using an appdaemon script.
Input Select
An input select allows a list of user defined values to be make available as a drop down list. In this example I will be using an input select that maps the state of the dishes in my dishwasher. To create the input select add the following to your configuration.yaml:
1234567input_select:
dishwasher:
name: Dishwasher State
options:
-
clean
-
dirty
icon: mdi:cup
-
water
This lets me set if there are clean
or dirty
dishes in the dishwasher, and gives it a specific material design icon.
AppDaemon
AppDaemon allows you to write python scripts which can interact with home-assistant. The interactions can include:
- Notifications about state changes
- Notifications about events
- Change State
- Fire events
- Call services on home-assistant
For this post you can add the following script to your appdaemon folder:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071import
appdaemon.plugins.hass.hassapi as hass
#
# App to take events from ifttt and change an input_select
#
#
# Args:
#
# input_select: Input select to trigger
# change_event: Name of the event that will trigger it
# say_event: Name of the event that will trigger it
# say_message: Message to say when an event was called
# media_player: The media player to use to post your message
#
class
InputSelectChecker(hass.Hass):
def
initialize(
self
):
if
'input_select'
in
self
.args:
self
.input_select
=
self
.args[
"input_select"
]
else
:
self
.log(
"No input_select specified, doing nothing"
)
return
if
'change_event'
in
self
.args:
self
.change_event
=
self
.args[
"change_event"
]
else
:
self
.change_event
=
None
self
.log(
"No change_event specified"
)
if
'say_event'
in
self
.args:
self
.say_event
=
self
.args[
"say_event"
]
else
:
self
.say_event
=
None
self
.log(
"No say_event specified"
)
if
self
.change_event:
self
.change_handle
=
self
.listen_event(
self
.change_event_cb, event
=
self
.change_event)
self
.log(
"{} handler setup for {}"
.
format
(
self
.change_event,
self
.input_select))
if
self
.say_event:
self
.say_handle
=
self
.listen_event(
self
.say_event_cb, event
=
self
.say_event)
self
.log(
"{} handler setup for {}"
.
format
(
self
.say_event,
self
.input_select))
self
.message
=
self
.args[
'say_message'
]
self
.media_player
=
self
.args[
'media_player'
]
def
change_event_cb(
self
, event_name, data, kwargs):
select_state
=
self
.get_state(entity
=
self
.input_select)
self
.log(
"change event select state = {}"
.
format
(select_state))
self
.log(
self
.get_state()[
self
.input_select][
'attributes'
])
all_options
=
self
.get_state()[
self
.input_select][
'attributes'
][
'options'
]
self
.log(
"{}"
.
format
(all_options))
if
'option'
in
data:
self
.log(
"Change to {}"
.
format
(data))
change_to
=
data[
'option'
].lower()
for
o
in
all_options:
if
change_to
=
=
o.lower():
self
.select_option(
self
.input_select, o)
return
self
.log(
"Invalid option {}"
.
format
(data))
def
say_event_cb(
self
, event_name, data, kwargs):
select_state
=
self
.get_state(entity
=
self
.input_select)
self
.log(
"say select state for {} = {}"
.
format
(
self
.input_select, select_state))
self
.log(
self
.message)
self
.call_service(
"tts/google_say"
, entity_id
=
self
.media_player,
message
=
self
.message.
format
(select_state
=
select_state))
This script will allow you to listen for configurable events and then either change the configured input select option, or say a TTS message over a configured media player. The message must be in the following format optional start of message {select_state} optional rest of message
, where {select_state}
is where you want the state of your input select to be added to the message.
Note: If you want to use a different TTS service, then you can rename it in the script or make it available as an argument.
To configure this add the following to your apps.yaml
:
12345678dishwasher_state:
module: ifttt_input_select_handler
class
: InputSelectChecker
input_select: input_select.dishwasher
change_event: CHANGE_INPUT_SELECT_DISHWASHER
say_event: SAY_INPUT_SELECT_DISHWASHER
media_player: media_player.kitchen
say_message:
'The dishwasher has {select_state} dishes'
If you only want to support one of either "change status", or "say status", then you should only configure the event for that handler.
IFTTT
If this then that (IFTTT) allows you to receive an event from one service and then call another service. In this example I make 2 IFTTT applets. Each applet will receive an event from the Google assistant service and then call a web-hook to call home-assistant.
The first one to get the status is If you say "What's the status of the dishwasher?" Then "make a web request"
The second to change the status is If you say "Change the dishwasher to $" Then "make a web request"
Say status applet
Screenshots of creating the say status applet are below:
Step 0: Select this
.
Step 1: Choose Say a simple phrase
as the trigger.
Step 2: Choose your trigger phrases and what will be the response from Google.
Step 3: Choose that
.
Step 4: Setup the web-hook to call your home assistant instance. This will trigger the event SAY_INPUT_SELECT_DISHWASHER
, which is the event we configured when setting up our appdaemon app.
Change status applet
The change status applet is very similar to the above. The differences are:
- In step 1, choose
say a phrase with a text ingredient
- In step 2, the trigger phrases must include a
$
in the place where you want to have our custom input. For exampleChange the dishwasher to $
, where $ should beclean
ordirty
. - In step 2, set the response to
Setting the dishwasher to $
- In step 4, for the web-hook will be to
https://[HA_URL]/api/events/CHANGE_INPUT_SELECT_DISHWASHER
and the post data will be{"option": "{{TextField}}"}
.
These changes will allow you to send your text back to home-assistant and if that matches your input_select option it will be selected.
Conversation
The conversation you have with Google are below.
Change Status:
User: "Hey Google, Change the dishwasher to dirty"
Google: "Setting the dishwasher to dirty"
Check Status:
User: "Hey Google, what is the status of the dishwasher?"
Google: "Checking"
Google: "The dishwasher has dirty dishes"
Limitations
The limitations of this are:
- You have to setup the IFTTT trigger and appdaemon app for each input select in home assistant.
- When checking the status there is a 2 stage response. First saying "Checking" and then maybe 2 seconds later saying the status response.
- You must manually set the speaker that you respond to.
No comments:
Post a Comment