Rhasspy TTS from HASS

I’m a relative noob when it comes to rhasspy, as I only recently got it working to turn on a light switch. My next project is to try and get it to return some sort of value through tts to me when I ask for something (A value from a home assistant sensor). I have found a few things around the internet, and have made it almost to the finish line, with one more hurdle.

I have this for my command code, that I’m (for now) triggering manually through a home assistant automation.

rest_command:
  rhasspy_speak:
    url: 'http://10.77.77.11:12101/hermes/tts/say'
    method: 'POST'
    content_type: text/plain
    payload: 'test'

I know this at least partially works, because it is able to communicate with Rhasspy, but only to tell it a command has happened. This is what is in my logs in Rhasspy.

[DEBUG:2022-06-29 00:30:06,985] rhasspyserver_hermes: Handling TtsSayFinished (topic=hermes/tts/sayFinished, id=e9f33930-3671-42cd-85ee-34beb6b32f29)
[DEBUG:2022-06-29 00:30:06,958] rhasspyserver_hermes: Handling AudioPlayBytes (topic=hermes/audioServer/default/playBytes/b2b5f4f2-d45e-4ebf-821b-1be909504b56, id=e9f33930-3671-42cd-85ee-34beb6b32f29)
[DEBUG:2022-06-29 00:30:06,940] rhasspyserver_hermes: Publishing 125 bytes(s) to hermes/tts/say
[DEBUG:2022-06-29 00:30:06,940] rhasspyserver_hermes: -> TtsSay(text='', site_id='default', lang=None, id='b2b5f4f2-d45e-4ebf-821b-1be909504b56', session_id='', volume=1.0)
[DEBUG:2022-06-29 00:30:06,939] rhasspyserver_hermes: TTS timeout will be 30 second(s)

I mainly see this post most often Rhasspy demo with HassIO but have come across others that say to use /hermes/tts/say or whatever, but to no avail. Is it something simple that I’m missing? I can see the TtsSay is missing the text field, but I have no idea where I could get that from. Thanks for any help!

I think the wiki on github will help you a lot

Welcome to the forum Jracon! Give this a try:
Change your configuration.yaml in HA:

rest_command:
  rhasspy_speak:
    url: http://10.77.77.11:12101/api/text-to-speech
    method: POST
    headers:
      content_type: 'text/plain'
    payload: '{{ payload }}'

Then create an automation in HA:

- id: '1609448776116'
  alias: RhasspyTTSGoodMorning
  description: ''
  trigger:
  - platform: time
    at: 08:10
  condition: []
  action:
  - service: rest_command.rhasspy_speak
    data:
      payload: good morning it is ten after eight

This is an automation that goes off at ten after eight. This will confirm HA and Rhasspy are happy, and talking to each other. Then as romkabouter said start reviewing the wiki, you’ll need to understand “events” and “intents” in the context of Rhasspy/HA to set up you first question, and answer via tts. Let me know if you need any help.

1 Like

So that worked, all I have left to do is to pass through a home assistant value and get it to speak that. I have some xiaomi plant sensors connected through esphome, but I cannot get the payload to work with

      payload: sensor.pothos_illuminance

I have tried encasing it in double curly brackets, adding a

| string

to the end, encasing the double curly brackets in single quotes, removing the brackets, etc, etc.

Okay, you’ve make the first step! You’re going to need to template the sensor data. e.g something like this:

{{states("sensor.simple_time")}}

Use the “Developer Tools” Template to get the syntax for the data you want from the xiaomi sensor.

1 Like

I think I understand the example given in the template section of Developer Tools, but I still don’t quite understand how I’m supposed to use this to get the data I want from my sensor.

{% set my_test_json = {
  "temperature": 25,
  "unit": "°C"
} %}

I see this in the example, and it makes sense, but do I have to do the same thing, only with my sensor variables as the values? Do I have to make a new template myself, or do I just need to use the variables like this?

The temperature is {{ my_test_json.temperature }} {{ my_test_json.unit }}.

Or is it the attributes I see under the States tab in Developer Tools? Here I see

state_class: measurement
unit_of_measurement: lx
device_class: illuminance
friendly_name: Pothos Illuminance

As attributes for the sensor.pothos_illuminance entity. Can I just use those as the attribute for payload? Like

payload: sensor.pothos_illuminance.state_class

?

You’re almost there. From your second post, something like this (no guarantee, really tired and heading off to bed).

payload_template: '{"text": "My Sensor Says Illuminance is ({{states("sensor.pothos_illuminance.state_class")}}) now" }'
1 Like

Pretty much perfect, figured out it works with just the sensor.pothos_illuminance. Thank you so much for your help!

Take a look here, I wrote up some things to take note of:

Most importantly, you should make use of “sessions”, as these are kind of necessary. :slight_smile:

If you have further questions, just ask in the guide. :slight_smile:

EDIT:
On a side note, there is a fundamental difference between asking Rhasspy something and get an answer vs. letting Rhasspy say something without you asking first.

In the above automation the timing is made by an automation (08:10am), because Rhasspy should say something. What you asked about in your first post is asking Rhasspy something and get an answer. :wink:

As I said, sessions are important, and one should use them. :slight_smile: For now, everything will work as you wanted it to, but without sessions you will run into problems along the way, eg. if you want to use satellites for Rhasspy (more than one mic and/or speaker), or you want to enhance one command with different questions (eg. adding a calendar entry or such things).

Please have a look at the dialogueManager endSession topic and not the ttsSay
The ttSay will cause timeout errors on the session in Rhasspy

1 Like

Well actually it does not. Rhasspy is not happy with api/text-to-speech because there is no session to close if you do it this way :slight_smile:

1 Like

Jracon, I defer to those who know better, please follow romkabouter & paddy0174’s advice! :slight_smile: Thanks for jumping in romkabouter, I didn’t want to lead anyone astray, just trying to help. But to clarify, I know that it isn’t a good idea to use hermes/tts/say (although I have some really old stuff that goes back to Snips that I still have in my environment and it doesn’t really seem to cause any issues other that the log entries on session timeouts) but I thought it was okay to use the rest_command in the HA configuration.yaml and to call the service in an automation as I originally described. Am I wrong here too?? :worried:

There is not really right or wrong here. But if you want to have interaction with Rhasspy, it is nicer to close a session from your intentHandler (aka HA). That does not lead to timeouts and in the end will lead to a more responsive Rhasspy.

If you just want some text to be spoken, I’d use ttsSay most probably since there is no session (aka interaction) needed

In this specific case, I just need rhasspy to speak something when I ask it a question, but I will surely look into sessions and see how they could be applicable in the future. Thank you for your advice and help!

@JeffC Did my post come up like a bad critic to you? If so, I can only appologize, sorry! :slight_smile: Surely wasn’t my intention! :slight_smile:

As @romkabouter already said, there is no right or wrong here, it is just good practice and will lead to a better user experience. That’s all! As long as it works, it’s ok! :rofl:

And to answer your question, there is one very simple question you should ask yourself before you use one of the methods: If the message spoken from Rhasspy is originating without a question and an answer from you? Than use the rest_command. If you want to do it with some flowers and chocolate, it will be with a session.
But if you asked a question to Rhasspy, or you want to answer the text Rhasspy said, than you have to use a session for good practice and various other reasons, mainly easy of use later on and a clean and smooth running Rhasspy.

Let me give an example: If i have Rhasspy alert me about the open garage door, I just use the rest_command with something like “Attention! Take a look, the garage door is open!”.

If I have to leave for an appointment, Rhasspy remembers me, I have five minutes left to leave and asks me about some things it could do to speed up the process. :wink: “You have to leave for your barber shop in five minutes! Should I enable the AC at 21°C?”. Now I have to answer eg. with “yes” or “no” and that’s where Rhasspy needs to have a session. :slight_smile: You can even spin this further and let Rhasspy ask you a list of things to do that you can answer. Without a session it will slow your installation down and you will likely run into problems along the way. :slight_smile:

@Jracon
In that case, use a session! :slight_smile: As I said above. :slight_smile:

But not to overstate this, it is not that much of a hassle, in principle you can just copy & paste this automation and change it to your needs. :slight_smile:

  - id: Rhasspy GetDate
    alias: Rhasspy GetDate
    mode: single
    trigger: 
      - platform: event
        event_data: {}
        event_type: rhasspy_GetDate
    action:
      - service: mqtt.publish
        data:
          topic: hermes/dialogueManager/endSession
          payload_template: '{"sessionId": "{{ trigger.event.data._intent.sessionId }}", "text": "Today is {{ states.sensor.date.state }}"}'

Oh no paddy0174, I didn’t take your comment that way! I’m a huge fan of Rhasspy/HA, and want to help when I can. I felt very bad about leading Jracon astray, and your explanation of why to use sessions actually cleared things up for me, and I hope helps him as well. Going forward (and I’ll be cleaning up some of my old stuff) I’ll use the rest for announcements, and switch to sessions for interactive. thank you for being so helpful by providing the example!

1 Like

Hello, I think the easiest way to talk to Hassio or Homeassistant from Rhasspy is to use the topic: hermes/intent/yourintent … which Rhasspy will always publish when it detects the intent “yourintent” .

for instance, if you put in Rhasspy’s sentence.ini file :

[bonjour]
bonjour
tu es là

then, when Rhasspy detects the intent “bonjour” or “tu es la”, it will publish this to the topic hermes/intent/bonjour .

In Homeassistant you can then make an automation like this one:

automation:

alias: bonjour
trigger:
    platform: mqtt
    topic: hermes/intent/bonjour
    action:
    service: mqtt.publish
    data:
    topic: hermes/tts/say
    payload: “{“text”:” bonjour mon cher maître ! “,“siteId”:”{{ trigger.payload_json[‘siteId’] }}"}"

That last part about “siteId” is how you detect which satellite to talk to if you have many (I have 3). Otherwise use the siteId name you gave to your MQTT, or just leave it like it is …

After reading a lot of comments in the forum, I still think this is the easiest and simplest way to have Rhasspy and Hassio communicate.

have fun !
jrb

1 Like