All my persons in my house have device_trackers with a filled attribute named address. The default sentence/intent can only handle persons and is only looking into the state of the entity. So when I ask for the location of someone, I only get the „at home“ / „not at home“ response. How can i expand the system to respond with the address if available? I think i need a modified sentence, intent and response. But as I am no developer, I am a bit lost.
You could set up a custom intent and response but I would consider the easier route of setting up an automation with the custom sentence as the trigger like this for example:
triggers:
- trigger: conversation
command:
- where is bob
- what is bob's location
- etc etc
conditions: []
actions:
- action: assist_satellite.announce
metadata: {}
data:
message: >-
Bob can currently be found at {{ state_attr('person.bob', 'named_address') }} ## GUESSED ATTRIBUTE - CHANGE TO YOUR OWN ##
target:
entity_id: assist_satellite.home_assistant_voice ## CHANGE TO YOUR OWN ENTITY ID ##
You don’t have to define everything in the intent - you could create a template sensor to manipulate the address attribute into a format of your liking. For example:
Custom sentence:
language: "en"
intents:
CustomWhatTime:
data:
- sentences:
- "(What | What's | What is | Tell me) [the] time [is it]"
In this case sensor.speaking_clock is is a rather unwieldy template that converts now() into colloquial phrases like “half past five”. It makes the intents easier to manage - and of course you can use the same sensor in different sentences.
(script.willow_tts_response just takes tts_sentence and speaks it on a Sonos speaker in whichever room I’m in.)
In both ideas, i need a tts output, how can I modify the idea to also work for any kind of conversation, independent of the final device. So it should also work for a chat. Is there a replacement service call, to the assist_satellite.announce?
This maybe a stupid question but having created something like this to set my thermostat temperatures (as set temp does not appear to be a supported intent at present) I failed to fully grasp why some word are bracketed and some not.
Could not really find any documentation to fully explain it and although I managed to create what I needed and it works I would love to expand on this and understand the above format a little better.
Clearly the starting brackets denote I can start the sentence with any one of those words, but why for example is ‘the’ in square brackets yet ‘time’ is not in any bracket, does that suggest that ‘time’ is a required word for example?
Any pointers or better still links to relevant info much appreciated.
Thought I got it done via blueprint, but the trigger itself seems npt to be able to handle the variables. Any idea?
blueprint:
name: Wo ist
description: Nutzt die Adress Information eines Device Trackers um im Assist die Position wieder zu geben
domain: automation
input:
device_tracker:
name: device_tracker
description: Der Device Tracker der Person
selector:
entity:
filter:
- domain: device_tracker
variables:
device_tracker: !input device_tracker
nick_of_person: '{{ states[device_tracker].attributes.nickname }}'
full_name_of_person: '{{ states[device_tracker].attributes.full_name }}'
address: '{{ states[device_tracker].attributes.address }}'
triggers:
- trigger: conversation
command: 'Wo ist [denn] ({{ nick_of_person }} | {{ full_name_of_person }}) [gerade]'
conditions: []
actions:
- set_conversation_response: >-
{{ nick_of_person }} ist gerade bei {{ address }}
Changed blueprint to use trigger_variables also not working, as it seems, that the command trigger is nit able to use even them
blueprint:
name: Wo ist
description: Nutzt die Adress Information eines Device Trackers um im Assist die Position wieder zu geben
domain: automation
input:
device_tracker:
name: Device Tracker
description: Der Device Tracker der Person
selector:
entity:
filter:
- domain: device_tracker
nick_of_person:
name: Nick Name
description: kurzer Rufname
full_name_of_person:
name: Name
description: Vor und Zuname
trigger_variables:
nick_of_person: !input nick_of_person
full_name_of_person: !input full_name_of_person
variables:
device_tracker: !input device_tracker
address: '{{ states[device_tracker].attributes.address }}'
triggers:
- trigger: conversation
command: 'Wo ist [denn] ({{ nick_of_person }} | {{ full_name_of_person }}) [gerade]'
conditions: []
actions:
- set_conversation_response: >-
{{ nick_of_person }} ist gerade bei {{ address }}
So as all of this is not working, i found the only way, which seems possible with the current version of home assistant.
New intents do not work, as you cant add new intent responses right now
custom intent scripts cant map the selected device to the response text and you would need to query by name alias and so on, which is no way to manage that.
automation or blueprints is also not possible, as the conversation trigger cant handle jinja2 or variables
dirty hack with copying the right response codes into the container, also no option, as these files are only compiled there and not as yaml config
So the way to go is to replace/extend the existing intent HassGetState with your definitions.
Place this file inside the custom_sentances folder (under the right language code)
Also create the replacing response file there:
language: de
responses:
intents:
HassGetState:
address_einzeln: |
{{ slots.name | capitalize }} ist {{ state.state_with_unit | replace(".", ",") if state.state|float(state.state) is number else state.state_with_unit }}
address_einzeln_janein: |
{% if query.matched %}
Ja
{% else %}
Nein
{% endif %}
address_irgendeins: |
{% if query.matched %}
{% set match = query.matched | map(attribute="nickname") | sort | list %}
{% if match | length > 4 %}
Ja, {{ match[:3] | join(", ") }} und {{ (match | length - 3) }} weitere
{%- else -%}
Ja,
{% for name in match -%}
{% if not loop.first and not loop.last %}, {% elif loop.last and not loop.first %} und {% endif -%}
{{ name }}
{%- endfor -%}
{% endif %}
{% else %}
Nein
{% endif %}
address_alle: |
{% if not query.unmatched: %}
Ja
{% else %}
{% set no_match = query.unmatched | map(attribute="nickname") | sort | list %}
{% if no_match | length > 4 %}
Nein, {{ no_match[:3] | join(", ") }} und {{ (no_match | length - 3) }} weitere sind es nicht
{%- else -%}
Nein,
{% for name in no_match -%}
{% if not loop.first and not loop.last %}, {% elif loop.last and not loop.first %} und {% endif -%}
{{ name }}
{%- endfor %} {% if no_match | length == 1 %}ist{% else %}sind{% endif %} es nicht
{% endif %}
{% endif %}
address_welches: |
{% if not query.matched %}
Keins
{% else: %}
{% set match = query.matched | map(attribute="nickname") | sort | list %}
{% if match | length > 4 %}
{{ match[:3] | join(", ") }} und {{ (match | length - 3) }} weitere
{% else %}
{%- for name in match -%}
{% if not loop.first and not loop.last %}, {% elif loop.last and not loop.first %} und {% endif -%}
{{ name }}
{%- endfor -%}
{% endif %}
{% endif %}
address_wie_viele: |
{{ query.matched | length }}
address_wo: |
{% if state.state == "not_home" %}
{{ slots.name | capitalize }} ist gerade bei {{ state.attributes.get('address') }}.
{% else %}
{{ slots.name | capitalize }} ist im Bereich {{ state.state }}.
Das ist bei {{ state.attributes.get('address') }}.
{% endif %}
address_wer: |
{% if not query.matched %}
Niemand
{% else: %}
{% set match = query.matched | map(attribute="nickname") | sort | list %}
{% if match | length > 4 %}
{{ match[:3] | join(", ") }} und {{ (match | length - 3) }} weitere
{% else %}
{%- for name in match -%}
{% if not loop.first and not loop.last %}, {% elif loop.last and not loop.first %} und {% endif -%}
{{ name }}
{%- endfor -%}
{% endif %}
{% endif %}
Now just expose the device_trackers of your choice and all is working fine as expected.