Constructing sentences for TTS

I would like to be able to run an automation when people get home that basically runs through a checklist and constructs a single sentence that can then be fed to the TTS engine and then played on the Google Home.

What I’d like to do in HA, is for example read out the temperature, and if that temperature is below or above a certain mark, turn on the aircon (and say thats what its doing. I also want to read out whether the alarm is on or off, (and again announce it is turning it off, if it is on). Whether any motion was detected and if so, how many times today. Etc.

This may turn out to be something like “Welcome home , the indoor temperature is 15C, turning the house airconditioner on. The house alarm is now turned off, and there were no motion detections today. The dishwasher has completed while you are out and needs to be emptied” This would change depending on whether an action also occurred, e.g. if temp is between 18C and 26C, it wont turn on the aircon and hence not mention that. Washer, dryer and dishwasher completion etc.

This would be simple in code if else blocks and $string = $string + " blah blah blah" and rinse repeat. Any tips how I would do this in HA? I started with a lot of different automations and heaps of conditions, but that isn’t scalable and multiple automations timed one after the other don’t sound terribly coherent and tend to run over the top of each other.

Thanks,

check how i’ve built m good morning script, it should give you some ideas:

1 Like

I’ve been struggling (conceptually) with this for a long time. I have a couple of posts of my own on this subject too and so far have not found any way to make TTS as useful as I think it could (should?) be.

You are right, HA could really use some flow control such as if/then/else or do while/until etc. some of which, to be fair, can be crudely replicated.

It could also do with some kind of queuing system so that messages didn’t either get garbled or fail to be announced because the script is already running. Again some crude work arounds are possible in some cases.

There are a couple of other things that I have wished I could do. Have an input_text longer than 256 chars and create the actual mp3 without playing it and then being able to play them within my control.

As usual with HA, some people here like @lolouk44 have done same clever stuff with TTS and I have borrowed a lot of their ideas but so far everything I have tried requires the sentences to be always spoken in the same order. And as cool as it is it does get a bit samey to always here the same announcements in the same order. (I’ve kept my morning announcement interesting by adding a random one line joke at the end. Even my wife is amused by that :slight_smile: )

I am surprised no one has created a fully featured custom component of some sort for TTS but unfortunately it is well beyond my current novice python skill level.

But I will watch this post with interest.

1 Like

you can add some more level of randomness by indeed having a few different ways of saying things with the | random filter, e.g.["Good morning","Howdy","Greetings Sir"] | random
I’m actually working on a way to iterate randomly through a list so that you could have a table (input_select) of announcements and TTS service would read through all announcements in a random order…
follow this post if you’re interested:

1 Like

I do have randomisation in my announcements but I’m not entirely happy with the way I’ve implemented it. It is modular and new phrases can be added easily but the whole thing is a bit klunky.

Which is a long way to say, yes I am interested and will be following that post!

question for you @lolouk44 … do the last_triggered attributes persist after a restart?

Right now, I have a lot of long running “timers”. Like, when I feed the dog, I want to be notified to feed him again 10 hours later. So, when that automation runs, I store a timestamp in a input_text and then consult it in the automation that tells me “hey! feed the dog!”. I can use a state trigger with a “for” setting, because that doesn’t persist a restart. So if I feed the dog at 8am, then I should get a notification at 6pm. But if I restart Home Assistant at 1pm, then I won’t get that notification until 11pm, which isn’t desired… and I restart Home Assistant a lot.

I could avoid the step of setting the input_text to a timestamp if the last_triggered attribute will persist a restart.

I checked a few automations that I know trigger before my last restart and haven’t triggered since and they all say “null”. But, my last restart was also one of those that … and I still don’t know why it does this … causes all of my stored states to be lost and all of my automations to be in the “off” state.

Annoying isn’t it?
I don’t know if you know but this will turn all automations on at system start.

homeassistant:
  customize_domain:
    automation:
      initial_state: 'on'

That’s not a bad idea. I have some automations that need to be off until certain conditions, etc, etc. And some that need to be on only in certain conditions. But… at least for the ones that are always on, that would work.

This doesn’t always work, annoyingly. No idea why, but I had several restarts with all my automations being off in spite of this.

I’ve gone back to adding initial_state: on to every automation individually, which is faultless.

It looks like the last_triggered is now persistent, but I think it’s a recent thing (maybe as late as 0.76.2 which I’m on).
I say looks like because in the past I would see never for last triggered after a restart, but I’ve just checked some automation that were triggered before my last restart and the last_triggered attribute still shows :slight_smile:

1 Like

if you turn an automation off, it’s likely its state will persist through reboots.
I don’t have any initial_state: on, only initial_state: off for those that I don’t want enabled at start and they always are on, but I have very few, if any automations/scripts that turn automations on/off

Thanks, will give this a go, looks like what you’ve done there should suit, I will just use much less fixed things, and more if/elif/endif (no else cases as I only want stuff to trigger off if it has occurred/triggered).

Hi, i am using your configuration as it is (changing only the sensors i use and some triggers), but i always get the same error:

2018-08-30 15:14:03 ERROR (MainThread) [homeassistant.helpers.service] Error rendering data template: UndefinedError: 'None' has no attribute 'state'

This is my changed automation:

- alias: Buongiorno Umani
  trigger:
    - platform: time
      at: '15:33:00'
    - platform: state
      entity_id: input_boolean.mauhome
      to: 'on'
    - platform: state
      entity_id: binary_sensor.motion_sensor_158d0001a92ca1
      to: 'on'
  condition:
    - condition: time
      after: '08:30'
      before: '10:00'
    - condition: template
      # Only run if more than 6 hours (21,600 sec) since it last ran 
      value_template: '{{(as_timestamp(now()) - as_timestamp(states.automation.buongiorno_umani.attributes.last_triggered | default(0)) | int > 21600 )}}'
  action:
    - service: media_player.volume_set
      data_template:
        entity_id: media_player.googlehome0461
        volume_level: 0.60 
    - service: tts.google_say
      data_template:
        entity_id: media_player.googlehome0461
#        message: "Buongiorno umani! Il tempo è {{ states.sensor.pws_weather_1h_2.state }}, con una temperatura di {{ states.sensor.pws_temp_c_2.state | round}} gradi, il vento soffia a {{ states.sensor.pws_wind_1d_kph_2.state | round}} kilometri per ora.  Ti auguro una splendida giornata!"  
        message: |
          Buongiorno. Oggi è
          {{as_timestamp(now()) | timestamp_custom('%A')}}, {% set day = (as_timestamp(now()) | timestamp_custom('%d')) |int-%}
          {{day}}{%- if day >= 4 and day <= 20 or day >= 24 and day <= 30 -%}th
          {%- elif day == 1 or day == 21 or day == 31-%}st
          {%- elif day == 2 or day == 22 -%}nd
          {%- elif day == 3 or day == 23 -%}rd
          {%- endif %} {{as_timestamp(now()) | timestamp_custom('%B')}}
          Ora è {{states.sensor.dark_sky_summary.state}} con {{states.sensor.dark_sky_temperature.state|round}} gradi.
          Oggi sarà {{states.sensor.dark_sky_hourly_summary.state|replace(".", "")}},
          highs: {{states.sensor.dark_sky_daytime_high_temperature.state|round}},
          lows: {{states.sensor.dark_sky_overnight_low_temperature.state|round}}.
          Venti {{states.sensor.pws_wind_dir.state
          |replace("N","Nord ")
          |replace("S","Sud ")
          |replace("E","Est ")
          |replace("O","Ovest ")
          }} a {{states.sensor.pws_wind_1d_kph.state}} con raffiche fino a {{states.sensor.pws_wind_gust_1d_kph.state}} km/h.
          Possibilità di pioggia: {{states.sensor.pws_precip_1d.state | int(0)}}%.
          {% if as_timestamp(now()) | timestamp_custom('%Y-%m-%d') == (states.calendar.contacts.attributes.start_time).split(" ")[0] and states.calendar.contacts.attributes.all_day != True %} Your next appointment is: {{states.calendar.contacts.attributes.message}} at {{(states.calendar.contacts.attributes.start_time).split(" ")[1].split(":")[0]}} {%if (states.calendar.contacts.attributes.start_time).split(" ")[1].split(":")[1] != '00'%}{{(states.calendar.contacts.attributes.start_time).split(" ")[1].split(":")[1]}} {%endif%} {%endif%}
          {% if as_timestamp(now()) | timestamp_custom('%Y-%m-%d') == (states.calendar.contacts.attributes.start_time).split(" ")[0] and states.calendar.contacts.attributes.all_day == True %} Today is : {{states.calendar.contacts.attributes.message|replace("/","and")}}{%endif%}
    - delay: "00:00:10"
    - service: script.turn_on
      entity_id: script.accendi_radio_googlehome_mini

Can you tell me where is the error?

best is to copy the message in the template editor and check each entity one by one until you find the culprit
It’s most likely that you’ve copied the whole message but you’re not tracking the sensor that I’m tracking…

Yes, you’re right i checked all the sensors and found some typo errors…
Another question… How to have the date translated into italian names?

More: why i have empty result with these:

  {% if as_timestamp(now()) | timestamp_custom('%Y-%m-%d') == (states.calendar.contacts.attributes.start_time).split(" ")[0] and states.calendar.contacts.attributes.all_day != True %} Your next appointment is: {{states.calendar.contacts.attributes.message}} at {{(states.calendar.contacts.attributes.start_time).split(" ")[1].split(":")[0]}} {%if (states.calendar.contacts.attributes.start_time).split(" ")[1].split(":")[1] != '00'%}{{(states.calendar.contacts.attributes.start_time).split(" ")[1].split(":")[1]}} {%endif%} {%endif%}
  {% if as_timestamp(now()) | timestamp_custom('%Y-%m-%d') == (states.calendar.contacts.attributes.start_time).split(" ")[0] and states.calendar.contacts.attributes.all_day == True %} Today is : {{states.calendar.contacts.attributes.message|replace("/","and")}}{%endif%}

what happens if you try this: {{as_timestamp(now()) | timestamp_custom('%A',1)}}

For the calendar, you need to have an event that takes place today and in the future (e.g. later this afternoon or tonight, not this morning) else it doesn’t show anything.

I get “Thursday”

I tested the automation but after this part of the automation:

  Buongiorno. Oggi è
  {{as_timestamp(now()) | timestamp_custom('%A')}}, {% set day = (as_timestamp(now()) | timestamp_custom('%d')) |int-%}
  {{day}}{%- if day >= 4 and day <= 20 or day >= 24 and day <= 30 -%}th
  {%- elif day == 1 or day == 21 or day == 31-%}st
  {%- elif day == 2 or day == 22 -%}nd
  {%- elif day == 3 or day == 23 -%}rd
  {%- endif %} {{as_timestamp(now()) | timestamp_custom('%B')}}
  Ora è {{states.sensor.dark_sky_summary.state}} con {{states.sensor.dark_sky_temperature.state|round}} gradi.

my google home stops to talk and the automation goes to the next action… maybe is the indentation of the template that causes the stop?

I get this in the template editor:

Buongiorno. Oggi è
          Thursday, 30th August
          Ora è Nubi Sparse con 25 gradi.
          Oggi sarà Poco nuvoloso fino a stasera,
          temperatura massima: 26 gradi,
          temperatura minima: 13 gradi.
          Venti da Sud Ovest  a 5 km/h con raffiche fino a 17.7 km/h.
          Possibilità di pioggia: 30%.

is your HA and your OS setup to Italian locale?

so have you linked a google calendar to your HA and do you have an appointment later on today or one that’s all day?