Have you ever wanted to send Text-to-Speech (TTS) notifications with Home Assistant and Node-RED? In the sections below I’m going to be using Amazon Alexa Media Player Integration to send TTS notifications. Please note you can easily switch out the TTS integration to the one of your choosing and still use this Subflow (with a few tweaks).
This is one of my favorite Subflows as it can be used easily in a lot of automations. I use it in my automations to announce:
- Friendly state change notifications for accessibility (e.g., motion detected in room abc, lights turning on in the current room, the garage door was unlocked).
- General announcements (e.g., welcome to our home, it’s bedtime).
- Weather related announcements and warnings.
If you are new to Node-RED, I’d recommend checking out this awesome YouTube Node-RED playlist to get up to speed!
Alexa Media Player Custom Component
If you haven’t done so already, install the Alexa Media Player Custom Component if you are using Alexa, otherwise skip this section.
This addon is amazing as it normalizes all of your Alexa enabled devices such
as the
Amazon Echo
or ecobee Switch+
into a media_player
that can be used by Home Assistant. Once configured you
can simply verify the device you want to send a message is working by calling
the notify.alexa_media
service with the payload:
message: "Text-to-Speech is easy"
data:
type: "tts"
target: ["media_player.amazon_echo_plus"]
If you don’t hear anything after calling this service, stop and check the logs. This will help diagnose why you are not getting TTS notifications before continuing.
Input Boolean to control automations
I highly recommend adding an Input Boolean
that controls if audible notifications occur. It could get pretty annoying if
you are constantly hearing notifications for automations that are running
unless it’s desired. Here is my input_boolean
that I use for this automation.
If you choose a different name, be sure to update the code below.
automation_notifications:
name: Notify when an automation is triggered
icon: mdi:home-automation
Send Automation Speech Notification Subflow
Lets open Node-RED and create a new Subflow with a
Status Node,
Input Node
and Output Node
. I really like using the Status Node
to capture
all statuses as it allows for a better experience using Subflows by showing you
a visual indication of the current status. Also, I like specifying an
Output Node
as it allows a node to be part of a series when the Subflow has
completed. It’s worth noting that this Output Node
will only be called if the
notification is sent.
Let’s break down the Subflow. The incoming message gets passed to the
Check For Overrides
node. This node simply checks to see if the
msg.payload.announcement
is set to true
. If true
, then it will always send
the TTS notification. Otherwise it will call the Speech Notifications?
Current State Node
to see if the input_boolean.automation_notifications
is
true
. To recap, we will only call Set Speech Payload
if it an announcement
is true
or our input_boolean.automation_notifications
is true
.
The Set Speech Payload
node will return a new payload that the
Send Speech Notification
Service Call Node
is expecting. If you are not
using the alexa_media_player
Home Assistant addon, you’ll want to update
both of these nodes for the correct payload and service call.
You can then trigger this Subflow by passing a message object with the following payload. I recommend using a Inject Node to test this out.
{
"announcement": true,
"entity_id": "media_player.amazon_echo_plus",
"message": "test"
}
When triggering this Subflow it’s a good idea to pick the closest speaker to where the automation is occurring.
Here is the exported Node-RED subflow.
[
{
"id": "7a62a2d3.c0f4a4",
"type": "subflow",
"name": "Send Automation Speech Notification",
"info": "",
"category": "",
"in": [
{
"x": 60,
"y": 100,
"wires": [
{
"id": "87411254.a6ed18"
}
]
}
],
"out": [
{
"x": 1120,
"y": 100,
"wires": [
{
"id": "d44cc51a.be0668",
"port": 0
}
]
}
],
"status": {
"x": 220,
"y": 40,
"wires": [
{
"id": "aef53056.742438",
"port": 0
}
]
}
},
{
"id": "89300b1.595bcf8",
"type": "function",
"z": "7a62a2d3.c0f4a4",
"name": "Set Speech Payload",
"func": "const entity = flow.get(\"$parent.speech_entity_id\") || (msg.payload && msg.payload.entity_id) || \"media_player.amazon_echo_plus\";\nconst message = (msg.payload && msg.payload.message) || \"Automation provided no message\";\n\nnode.status({ fill: \"green\", shape: \"dot\", text: \"TTS message:\" + message });\nreturn {\n payload:{\n data: {\n message: message,\n data: { type: \"tts\" },\n target: [entity]\n }\n }\n};",
"outputs": 1,
"noerr": 0,
"x": 700,
"y": 100,
"wires": [
[
"d44cc51a.be0668"
]
]
},
{
"id": "d44cc51a.be0668",
"type": "api-call-service",
"z": "7a62a2d3.c0f4a4",
"name": "Send Speech Notification",
"server": "61956bd4.93df44",
"version": 1,
"debugenabled": false,
"service_domain": "notify",
"service": "alexa_media",
"entityId": "",
"data": "",
"dataType": "json",
"mergecontext": "",
"output_location": "payload",
"output_location_type": "msg",
"mustacheAltTags": false,
"x": 950,
"y": 100,
"wires": [
[]
]
},
{
"id": "6add9bc6.4c3624",
"type": "api-current-state",
"z": "7a62a2d3.c0f4a4",
"name": "Speech Notifications?",
"server": "61956bd4.93df44",
"version": 1,
"outputs": 2,
"halt_if": "true",
"halt_if_type": "bool",
"halt_if_compare": "is",
"override_topic": false,
"entity_id": "input_boolean.automation_notifications",
"state_type": "habool",
"state_location": "",
"override_payload": "none",
"entity_location": "",
"override_data": "none",
"blockInputOverrides": false,
"x": 440,
"y": 140,
"wires": [
[
"89300b1.595bcf8"
],
[]
],
"outputLabels": [
"",
"enabled"
]
},
{
"id": "aef53056.742438",
"type": "status",
"z": "7a62a2d3.c0f4a4",
"name": "",
"scope": null,
"x": 100,
"y": 40,
"wires": [
[]
]
},
{
"id": "87411254.a6ed18",
"type": "function",
"z": "7a62a2d3.c0f4a4",
"name": "Check for overrides",
"func": "const alwaysSpeak = msg.payload && msg.payload.announcement\nif (alwaysSpeak) {\n return [msg, null];\n} else {\n return [null, msg];\n}",
"outputs": 2,
"noerr": 0,
"x": 210,
"y": 100,
"wires": [
[
"89300b1.595bcf8"
],
[
"6add9bc6.4c3624"
]
],
"outputLabels": [
"Bypass notification",
"Check for notifications"
]
},
{
"id": "61956bd4.93df44",
"type": "server",
"z": "",
"name": "Home Assistant",
"legacy": false,
"addon": true,
"rejectUnauthorizedCerts": true,
"ha_boolean": "y|yes|true|on|home|open",
"connectionDelay": true
}
]
Conclusion
I hope this article inspired you to create your own reusable Subflows that you can use in your various automations. I’ve found this Subflow to be super useful, let me know how it works out for you!
Share this post
Twitter
Facebook
Reddit
LinkedIn
Email