Sharing simple HA integration example

Not sure if this is the best way of executing this or of sharing this but I didn’t quite understand how this was supposed to work and thought it could be helpful to share this for others.

I have 41 switches in HA (mostly Kasa tp-link). I wanted to just have a simple “intent” to turn them on or off. I tried to figure out the least amount of code / config necessary to do that and this is what I came up with (please let me know if there was something simpler):

There are basically 3 things that were needed.

  1. Update the sentences.ini with my intent
  2. Create a slots file with the list of switches / lights from HA (using their friendly name)
  3. Create an automation in HA that responded to the intent

sentences.ini:

[ChangeSwitchState]
switch_state = (on | off) {state}

turn <switch_state> [the] ($switches){name}
turn [the] ($switches){name} <switch_state>

In a file called switches in my profile/slots directory:

3D Printer
Back Door Light
Basement Light
Christmas Lights
Dining Room Fan
Dining Room Light
Dining Room Restart
Front Door Light
Garage Charger 1
Garage Charger 2
Garage Light
Gym Lights 1
Gym Lights 2
Kitchen Light
Kitchen Restart
The rest of my 41 switches with the friendly name that is in HA one per line

In my automations in HA:

- alias: Rhasspy Switches
  trigger:
    event_data: {}
    event_type: rhasspy_ChangeSwitchState
    platform: event
  condition: []
  action:
    - service_template: >
        {% if trigger.event.data.state == 'on' %}
          homeassistant.turn_on
        {% else %}
          homeassistant.turn_off
        {% endif %}
      data_template:
        entity_id: >
          {% for entity in states.switch %}
            {%- if entity.name | lower == trigger.event.data.name -%}
              {{ entity.entity_id }}
            {%- endif -%}
          {% endfor %}

I was going to write something that just creates that slots file on a regular basis / on demand, but my list of switches don’t change too often as of now. Hopefully this helps someone else out, but I would also really appreciate any advice / feedback to confirm if what I did made sense or not.

I was attempting to just use a selectattr to match on the name instead of the for loop but I couldn’t figure out how to get it to match on the lower case name. I couldn’t find an case insensitive match (I guess I could have done a regex match instead).

1 Like

As i know, friendly_name is not unique in HA, so I think it would be better to use substitution in sentences.
https://rhasspy.readthedocs.io/en/latest/training/#substitutions

Like this
(Kitchen Lamp):switch.kitchenLamp
So you will have entity id and won’t need for cycle
Also in this case friendly_name in HA and device name in Rhasspy can be different

I wanted to do that way but I couldn’t figure out how to programatically map the friendly name and entity id in rhasspy. I didn’t see any sort of dictionary or other lookup mechanism. Any ideas?

Here is one section of my slots definitions:

    "state_on_off": [
        "off",
        "on"
    ],
    "lights": [
        "(outside lights):group.lights_outdoor",
        "(inside lights):group.lights_indoor",
        "(downstairs lights):group.lights_downstairs",
        "(indoor lights):group.lights_indoor",
        "(bedroom lamp):switch.bedroom_lamp",
        "(dog lamp):switch.living_room_3",
        "(upstairs lights):group.lights_upstairs",
        "(brass lamp):switch.living_room_2",
        "(outdoor lights):group.lights_outdoor",
        "(rabbit lamp):switch.sunroom_rabbit_lamp",
        "(all lights):group.all_lights"
    ],

This is the sentences content that references it:

[ChangeLightState]
light = ($lights) {light}
state = ($state_on_off) {state}
(turn | switch) <state> [the] <light>
(turn | switch) [the] <light> <state>
<light> <state>

and this is the Home Assistant automation that uses them both:

- id: '0991'
  alias: "Rhasspy Turn lights on/off"
  trigger:
    platform: event
    event_type: rhasspy_ChangeLightState
  action:
    service_template: 'switch.turn_{{ trigger.event.data["state"] }}'
    data_template:
      entity_id: '{{ trigger.event.data["light"] }}'

This has allowed me to reduce a LOT of redundant automation script to a single automation.

4 Likes

Thank you very much, now I get it and I just used this in HA to generate a list of my switches in that format in case anyone needs it:

{% for state in states.switch %}
"({{ state.name | lower }}):{{ state.entity_id }}",
{%- endfor -%}
3 Likes

I have to give ALL CREDIT to users @TinyDoT and @frkos for their very generous assistance. I absolutely DID NOT figure this out on my own. :slight_smile:

2 Likes

Thanks for sharing this: can’t wait to try it at home!

Did you know if it’s possible to use substitutions also for the slot “state_onf_off”?
In fact, I will used french words (allume/allumer, éteins/éteindre) in place of “on” and “off” words.
So I could used the same HA automation that the one you share

Yes, you can do this the same way :wink:

Perfect !
I will try to play with my RPI A+ satellite / rhasspy HA add-on to make works together :slight_smile:

Later, I’ll try more complexe sentences for play with HA scenes

Thanks !

1 Like

Yes, definitely. :slight_smile: That’s why I included it in my slots text. I also have a similar slot for the doors with sensors:

    state_open_closed:[
        "open",
        "closed"
    ],

Just to save some more bytes on your HDD :crazy_face:
In HA you can use
trigger.event.data.light
instead of
trigger.event.data["light"]

1 Like

:crazy_face: At least twenty characters?

i played a little with sentences.ini this morning and came up with a config i find quite fun.
It’s in french but i think you’ll get the idea :

[Rules]
articles = (le:0 | la:0 | l:0 | du:0 | (de la):0 | les:1 | des:1)
lights = (lumière | lampe | ampoule | plafonnier):light
rooms = (cuisine:kitchen | salon:livingroom | (chambre du bas):bedroom1)

[ChangeLightState]
(allumer:on | éteindre:off){state} <Rules.articles>{allLights} <Rules.lights> [<Rules.articles>{allRooms}] [<Rules.rooms>{room}]

theoretically doing this would allow to control all lights of all rooms with only one entry in sentences.ini but can it be done in HA?

i saw in another post that one could use {% if %} in data_template, i guess it is also available in service_template but could not test it yet.

Is it a good idea or would it be to complicated HA wise?

as an example, the sentence “allumer la lumière du salon” results in

ChangeLightState
    0 allLights
    0 allRooms
    livingroom room
    1 state 

whereas “allumer les lampe” (without room) results in

ChangeLightState
    1 allLights
    1 state
2 Likes