Almost a year ago, I wrote about my J.A.R.V.I.S inspired morning wake-up announcement with CastleOS. Since then, I’ve moved to Home Assistant and sadly, lost my morning announcements.

In December 2016, Home Assistant 0.35 added a new Text-to-Speech component, thanks to Pascal Vizeli. The new component allows Home Assistant to send text-to-speech processed by either Google Translate or VoiceRSS to compatible media players linked to Home Assistant.

So now I have the missing piece to the puzzle. Home Assistant can now speak to me via my Sonos speakers. Brilliant! What’s even better is because Home Assistant is so powerful, I don’t need to write any external windows applications or run a webserver. I’m going to use the information already in Home Assistant, which will make things faster, and I can do it all in YAML. That means there’s nothing else except for Home Assistant installed that you need.

Before I dive in though, I’ve decided I’m going to make my announcement as a Home Assistant script. You could skip the script bit and add the announcement directly to an automation if you wanted, but for testing it’s nice to have a button in Home Assistant we can call to make the announcement.

Initial Setup

Let’s start off by creating a simple script, which we can call from Home Assistant to trigger the Text-To-Speech compontent. I have my Home Assistant setup to include scripts from a folder, so my configuration.yaml file looks like this.

configuration.yaml homeassistant: script: !include_dir_named scripts 1 2 3 homeassistant : script : !include_dir_named scripts

I have a folder named scripts, which I place all my scripts into separately. So, now let’s start off with a simple test script, which I’ll name jarvis_greeting.yaml.

jarvis_greeting.yaml alias: Jarvis Greeting sequence: - service: tts.google_say data: entity_id: media_player.office message: Hello from Home Assistant 1 2 3 4 5 6 7 alias : Jarvis Greeting sequence : - service : tts.google_say data : entity _ id : media_player.office message : Hello from Home Assistant

Be sure to change the media_player to your desired media player’s entity ID. You can find that from the States button in Home Assistant.

When we restart Home Assistant, there should be an option for us to call this script in the UI. If you’ve disabled the default view, you’ll need to add the following to your groups.yaml file somewhere. I’ll just place it on the home screen for now

groups.yaml default_view: view: yes entities: - sun.sun - group.people - script.jarvis_greeting 1 2 3 4 5 6 7 default _ view : view : yes entities : - sun . sun - group . people - script . jarvis _ greeting

Restart Home Assistant, and you should now see the following available in your Home Assistant UI.

Go ahead and press that activate button. When you do, you should hear Home Assistant say Hello from Home Assistant. If you don’t hear it, check you entered the right entity_id in the script, and check your Home Assistant log files for any errors.

So, now that we can hear Home Assistant, and can invoke our script for testing when we need to, let’s start adding some data into our announcement.

Adding Weather

To start off with, I want my announcement to have the same details as my original version for CastleOS. So, let’s use the current weather conditions, and the forecast for today. We can use Home Assistant Components for this. I’m going to use the DarkSky Weather component. Let’s start off with adjusting our configuration.yaml file with what that component needs.

configuration.yaml homeassistant: script: !include_dir_named scripts sensor: - platform: darksky api_key: NOTTELLING monitored_conditions: - summary - temperature - hourly_summary - temperature_max 1 2 3 4 5 6 7 8 9 10 11 12 homeassistant : script : !include_dir_named scripts sensor : - platform : darksky api _ key : NOTTELLING monitored _ conditions : - summary - temperature - hourly _ summary - temperature _ max

The values you put in monitored_conditions: are important, as we’ll need those in our script.

Now we’re going to use Templating. It can be a bit intimidating at first glance, but Home Assistant’s templating is very very powerful. First, we need to tell our script we’re going to be passing template data in our message, so let’s change our script like so.

jarvis_greeting.yaml alias: Jarvis Greeting sequence: - service: tts.google_say data_template: entity_id: media_player.office message: Hello from Home Assistant 1 2 3 4 5 6 7 alias : Jarvis Greeting sequence : - service : tts.google_say data _ template : entity _ id : media_player.office message : Hello from Home Assistant

See how we changed data: to data_template:? That little change will allow us to make our text-to-speech message dynamic when it is called. Now let’s add in our weather data, and original greeting.

jarvis_greeting.yaml alias: Jarvis Greeting sequence: - service: tts.google_say data_template: entity_id: media_player.office message: > Good morning. It's currently {{states.sensor.dark_sky_summary.state}} and {{states.sensor.dark_sky_temperature.state|round}} degrees in Melbourne. Today will be {{states.sensor.dark_sky_hourly_summary.state|replace(".", "")}}, with a high of {{states.sensor.dark_sky_daily_high_temperature.state|round}} degrees. 1 2 3 4 5 6 7 8 alias : Jarvis Greeting sequence : - service : tts.google_say data _ template : entity _ id : media_player.office message : > Good morning . It's currently { { states . sensor . dark _ sky _ summary . state } } and { { states . sensor . dark _ sky _ temperature . state | round } } degrees in Melbourne . Today will be { { states . sensor . dark _ sky _ hourly _ summary . state | replace ( "." , "" ) } } , with a high of { { states . sensor . dark _ sky _ daily _ high _ temperature . state | round } } degrees .

When that’s executed we should now hear something like this.

Good morning. It’s currently mostly cloudy and 21 degrees in Melbourne. Today will be morning showers then mostly clear, with a high of 24 degrees.

So let’s take a quick look at what’s going on here.

{ { states . sensor . dark _ sky _ summary . state } }

round

replace

allows us to access the Dark Sky Weather Components current state for the summary. Home Assistant will keep this updated for us. We do similar things for the temperature, except for the temperature we’re going to useso that temperatures like 27.1 just become 27. I’m also usingon the hourly summary, so that there isn’t a full stop/period added in the middle of the sentence we’re speaking.

So everything is working as intended. I think we could make this a little bit more advanced. What if we press the activate button in the evening or afternoon? We don’t want Home Assistant saying good morning to us. So, let’s use some more templating magic to make Home Assistant give us the right greeting for the right time of day.

jarvis_greeting.yaml alias: Jarvis Greeting sequence: - service: tts.google_say data_template: entity_id: media_player.office message: > {% if now().strftime("%H")|int < 12 %} Good morning. {% elif now().strftime("%H")|int < 18 %} Good afternoon. {% else %} Good evening. {% endif %} It's currently {{states.sensor.dark_sky_summary.state}} and {{states.sensor.dark_sky_temperature.state|round}} degrees in Melbourne. Today will be {{states.sensor.dark_sky_hourly_summary.state|replace(".", "")}}, with a high of {{states.sensor.dark_sky_daily_high_temperature.state|round}} degrees. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 alias : Jarvis Greeting sequence : - service : tts.google_say data _ template : entity _ id : media_player.office message : > { % if now ( ) . strftime ( "%H" ) | int < 12 % } Good morning . { % elif now ( ) . strftime ( "%H" ) | int < 18 % } Good afternoon . { % else % } Good evening . { % endif % } It's currently { { states . sensor . dark _ sky _ summary . state } } and { { states . sensor . dark _ sky _ temperature . state | round } } degrees in Melbourne . Today will be { { states . sensor . dark _ sky _ hourly _ summary . state | replace ( "." , "" ) } } , with a high of { { states . sensor . dark _ sky _ daily _ high _ temperature . state | round } } degrees .

We’re using some if statements and asking Home Assistant what time of day it is. If it is before 12pm, then always say Good Morning. If it’s after 12pm but before 6pm, say Good Afternoon. Otherwise say Good Evening. This looks much better.

Automating The Announcement

Now that our script will say the right greeting for the right time of day, it’s time to tell Home Assistant when we would like the announcement to be made. There’s a ton of ways you could do this. First time someone gets home. When a light turns on or off. At the same time everyday. Home Assistant is powerful like that.

Once you’ve decided on your triggers, all you need to call this script in your automation is

automation.yaml action: - service: homeassistant.turn_on entity_id: script.jarvis_greeting 1 2 3 4 5 action : - service : homeassistant.turn_on entity _ id : script.jarvis_greeting

Bonus Round: Door Status and Commute Time

Home Assistant has a great range of components we can use in our templates. Here’s some ideas for some things you might want in your announcement.

Stock prices using the Yahoo Finance component

Stock prices using the Yahoo Finance component Pricing and ETA information from Uber

Pricing and ETA information from Uber The next event on your Google Calendar

The next event on your Google Calendar The open/closed status of a door (like a Garage Door)

The open/closed status of a door (like a Garage Door) The commute time to get to work using Google Maps

If you’re a bit advanced, you could also setup your own Template Sensors for other bits of information you might want to know. There’s a lot you could add into your own announcement, and everyone will be different. For me, I’m going to concentrate on the last two from my list, whether my Balcony door is open and the commute time to work.

For the Balcony door, I’m using a Fibaro Z-wave door and window sensor. It reports true or false to Home Assistant. Using a Template Sensor, I have setup the door to look like this in my Home Assistant.

So, let’s setup the new sensors we’ll need first.

configuration.yaml homeassistant: script: !include_dir_named scripts sensor: - platform: darksky api_key: NOTTELLING monitored_conditions: - summary - temperature - hourly_summary - temperature_max - platform: template sensors: balcony_door_status: value_template: '{% if states.binary_sensor.fibaro_system_fgk10x_door_opening_sensor_sensor_31_0 %} {% if states.binary_sensor.fibaro_system_fgk10x_door_opening_sensor_sensor_31_0.state == "on" %} Open {% else %} Closed {% endif %} {% else %} n/a {% endif %}' friendly_name: 'Balcony Sliding Door' - platform: google_travel_time api_key: XXXX_XXXXX_XXXXX origin: Melbourne, Australia destination: Sydney, Australia 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 homeassistant : script : !include_dir_named scripts sensor : - platform : darksky api _ key : NOTTELLING monitored _ conditions : - summary - temperature - hourly _ summary - temperature _ max - platform : template sensors : balcony _ door _ status : value _ template : ' { % if states . binary _ sensor . fibaro _ system _ fgk10x _ door _ opening _ sensor _ sensor _ 31 _ 0 % } { % if states . binary _ sensor . fibaro _ system _ fgk10x _ door _ opening _ sensor _ sensor _ 31 _ 0 . state == "on" % } Open { % else % } Closed { % endif % } { % else % } n/a { % endif % } ' friendly_name: ' Balcony Sliding Door' - platform : google_travel_time api _ key : XXXX_XXXXX_XXXXX origin : Melbourne , Australia destination : Sydney , Australia

Now that our configuration has changed, let’s restart Home Assistant so our new settings will load up. Once restarted, we should have access to new sensors which Home Assistant will keep updated for us.

Now I only want to know how long it will take me to get to work in the morning. So, let’s add some more to our message, in a condition block.

jarvis_greeting.yaml alias: Jarvis Greeting sequence: - service: tts.google_say data_template: entity_id: media_player.office message: > {% if now().strftime("%H")|int < 12 %} Good morning. {% elif now().strftime("%H")|int < 18 %} Good afternoon. {% else %} Good evening. {% endif %} It's currently {{states.sensor.dark_sky_summary.state}} and {{states.sensor.dark_sky_temperature.state|round}} degrees in Melbourne. Today will be {{states.sensor.dark_sky_hourly_summary.state|replace(".", "")}}, with a high of {{states.sensor.dark_sky_daily_high_temperature.state|round}} degrees. {% if now().strftime("%H")|int < 9 %} The current drive to Sydney in traffic is {{states.sensor.google_travel_time__driving.attributes.duration_in_traffic}} {% endif %} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 alias : Jarvis Greeting sequence : - service : tts.google_say data _ template : entity _ id : media_player.office message : > { % if now ( ) . strftime ( "%H" ) | int < 12 % } Good morning . { % elif now ( ) . strftime ( "%H" ) | int < 18 % } Good afternoon . { % else % } Good evening . { % endif % } It's currently { { states . sensor . dark _ sky _ summary . state } } and { { states . sensor . dark _ sky _ temperature . state | round } } degrees in Melbourne . Today will be { { states . sensor . dark _ sky _ hourly _ summary . state | replace ( "." , "" ) } } , with a high of { { states . sensor . dark _ sky _ daily _ high _ temperature . state | round } } degrees . { % if now ( ) . strftime ( "%H" ) | int < 9 % } The current drive to Sydney in traffic is { { states . sensor . google _ travel _ time _ _ driving . attributes . duration _ in _ traffic } } { % endif % }

Now if it is a weekend, I don’t want to hear about the time to work. So let’s also check the day of the week. If it is a Saturday or Sunday, don’t tell me the commute time. We’ll once again use the Python strftime() function. 0 is Sunday and 6 is Saturday.

jarvis_greeting.yaml alias: Jarvis Greeting sequence: - service: tts.google_say data_template: entity_id: media_player.office message: > {% if now().strftime("%H")|int < 12 %} Good morning. {% elif now().strftime("%H")|int < 18 %} Good afternoon. {% else %} Good evening. {% endif %} It's currently {{states.sensor.dark_sky_summary.state}} and {{states.sensor.dark_sky_temperature.state|round}} degrees in Melbourne. Today will be {{states.sensor.dark_sky_hourly_summary.state|replace(".", "")}}, with a high of {{states.sensor.dark_sky_daily_high_temperature.state|round}} degrees. {% if now().strftime("%H")|int < 9 and now().strftime("%w")|int > 0and now().strftime("%w")|int < 6 %} The current drive to Sydney in traffic is {{states.sensor.google_travel_time__driving.attributes.duration_in_traffic}} {% endif %} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 alias : Jarvis Greeting sequence : - service : tts.google_say data _ template : entity _ id : media_player.office message : > { % if now ( ) . strftime ( "%H" ) | int < 12 % } Good morning . { % elif now ( ) . strftime ( "%H" ) | int < 18 % } Good afternoon . { % else % } Good evening . { % endif % } It's currently { { states . sensor . dark _ sky _ summary . state } } and { { states . sensor . dark _ sky _ temperature . state | round } } degrees in Melbourne . Today will be { { states . sensor . dark _ sky _ hourly _ summary . state | replace ( "." , "" ) } } , with a high of { { states . sensor . dark _ sky _ daily _ high _ temperature . state | round } } degrees . { % if now ( ) . strftime ( "%H" ) | int < 9 and now ( ) . strftime ( "%w" ) | int > 0and now ( ) . strftime ( "%w" ) | int < 6 % } The current drive to Sydney in traffic is { { states . sensor . google _ travel _ time _ _ driving . attributes . duration _ in _ traffic } } { % endif % }

So now we will only be told about our commute time if it is between Monday and Friday, and before 9am.

Finally, let’s add a message if my balcony door has been left open. You can apply the same logic for a garage door, or a lock etc. Thanks to the Template Sensor I created above, this should be pretty easy.

jarvis_greeting.yaml alias: Jarvis Greeting sequence: - service: tts.google_say data_template: entity_id: media_player.office message: > {% if now().strftime("%H")|int < 12 %} Good morning. {% elif now().strftime("%H")|int < 18 %} Good afternoon. {% else %} Good evening. {% endif %} It's currently {{states.sensor.dark_sky_summary.state}} and {{states.sensor.dark_sky_temperature.state|round}} degrees in Melbourne. Today will be {{states.sensor.dark_sky_hourly_summary.state|replace(".", "")}}, with a high of {{states.sensor.dark_sky_daily_high_temperature.state|round}} degrees. {% if now().strftime("%H")|int < 9 and now().strftime("%w")|int > 0and now().strftime("%w")|int < 6 %} The current drive to Sydney in traffic is {{states.sensor.google_travel_time__driving.attributes.duration_in_traffic}} {% endif %} {% if is_state('sensor.balcony_door_status', 'Open') %} Heads up: The balcony door has been left open {% endif %} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 alias : Jarvis Greeting sequence : - service : tts.google_say data _ template : entity _ id : media_player.office message : > { % if now ( ) . strftime ( "%H" ) | int < 12 % } Good morning . { % elif now ( ) . strftime ( "%H" ) | int < 18 % } Good afternoon . { % else % } Good evening . { % endif % } It 's currently {{states.sensor.dark_sky_summary.state}} and {{states.sensor.dark_sky_temperature.state|round}} degrees in Melbourne. Today will be {{states.sensor.dark_sky_hourly_summary.state|replace(".", "")}}, with a high of {{states.sensor.dark_sky_daily_high_temperature.state|round}} degrees. {% if now().strftime("%H")|int < 9 and now().strftime("%w")|int > 0and now().strftime("%w")|int < 6 %} The current drive to Sydney in traffic is {{states.sensor.google_travel_time__driving.attributes.duration_in_traffic}} {% endif %} {% if is_state(' sensor . balcony _ door _ status ', ' Open' ) % } Heads up : The balcony door has been left open { % endif % }

Tying it all in together, here’s the message we should now get in the morning if the balcony door is open.

Good morning. It’s currently mostly cloudy and 21 degrees in Melbourne. Today will be morning showers then mostly clear, with a high of 24 degrees. The current drive to Sydney is 8 hours 42 mins. Heads up: The balcony door has been left open

The Latest In Your Inbox Enter your email address below to receive my latest blog posts and videos about Home Automation in your Inbox

Where to from here?

This is just a small sample of what you can do with the new Text-to-Speech component combined with Home Assistant’s templating syntax. You can apply the same logic to notifications sent to your phone, or even responses sent back to your Amazon Echo if you’re using your own Alexa service.

If you want to see what else you can do with templating in Home Assistant, I recommend you check out the following pages on the Home Assistant website.

When creating your own templates, be sure to check your syntax with the Templates section inside Home Assistant. It’s the second last option on the menu (near the help/about icon).