Yandex Alice says which windows you have not closed

What is it all about?

In my implementation of a smart home, I made a script called “I’m leaving”. As planned, it is called before leaving the house, when no one is left. The script turns off the light and various devices. It can be activated with the phrase “Alice, I’m leaving.”

I then purchased a Zigbee contact sensor and hung it on the window. I wanted Alice to report which rooms have windows open. All the same, there is a cat at home, and the weather conditions are different. When there is only one such sensor, then no problems arise: we check that it is in the “Open” status and reproduce the desired phrase. When there are a lot of such sensors, then you want Alice to say a beautiful sentence about which rooms the windows are open in.

idea

According to my idea, if the window is open only in one room, then Alice should say in which room. If in two, then “there and there.” And if in three or more, then you need to tell, separated by a comma, in which rooms the window is not closed, and play the last one with the prefix AND (there, there and there).

So, let’s get down to implementation.

Implementation

First, let’s define an object (in the Jinja2 templating engine, this is called a dictionary), in which the key is a piece of a phrase with the name of the room, and the value is the state of the window in the form boolean.

{% set window_sensors = {
  "в спальне": is_state("binary_sensor.bedroom_window_contact", "on"),
  "на кухне":  is_state("binary_sensor.kitchen_window_contact", "on"),
  "в гостиной":  is_state("binary_sensor.guestroom_window_contact", "on")
} %}

Then we need to define an array in which we will add pieces of phrases in order to assemble the final sentence using join. This is much easier than displaying text directly in the template and struggling with its formatting.

{% set data = namespace(text=[]) %}

Well, then we just run through the object and, using the condition, take only those sensors that have the “Open” state:

{% for k in window_sensors if window_sensors[k] == true %}
	{% if loop.first %}
	  {% set data.text = data.text + [["Кстати,", "Не забудьте, что", "Напоминаю, что"]|random] + [" у вас"] + [[" открыто", " не закрыто"]|random] + [" окно"] %}
	{% endif %}
	
	{% if not loop.first and not loop.last %}
	  {% set data.text = data.text + [", "] + [k] %}
	{% elif loop.last and not loop.first %}
	  {% set data.text = data.text + [" и "] + [k] %}
	{% else %}
	  {% set data.text = data.text + [" "] + [k] %}
	{% endif %}
{% endfor %}

On the first iteration, I add the beginning of the phrase. As you can see, different phrases are used to give “humanity” to this soulless robot. Next come the conditions. If the iteration is not the first and not the last, then we are in the process of enumeration – we add a comma and the name of the sensor (object key). If the iteration is the last, but not the first (that is, there are definitely more than one open windows), then we add the prefix “AND”, and then the name of the sensor. Otherwise, simply add the name of the sensor separated by a space (i.e., this is the beginning of the enumeration).

The result is an array like this:

['Напоминаю, что', ' у вас', ' открыто', ' окно', ' ', 'в спальне', ' и ', 'в гостиной']

Collecting with join to the line:

{{ data.text|join("") }}

Result: “I remind you that you have a window open in the bedroom and in the living room.”

Ready! It remains only to ask Alice to reproduce the text using a service call media_player.play_media according to AlexxIT/YandexStation documentation.

Final code

service: media_player.play_media
target:
  entity_id: media_player.yandex_station_ # ID вашей станции
data:
  media_content_id: >-
    {% set window_sensors = {
      "в спальне": is_state("binary_sensor.bedroom_window_contact", "on"),
      "на кухне":  is_state("binary_sensor.kitchen_window_contact", "on"),
      "в гостиной":  is_state("binary_sensor.guestroom_window_contact", "on")
    } %}
    
    {% set data = namespace(text=[]) %}
    
    {% for k in window_sensors if window_sensors[k] == true %}
      {% if loop.first %}
        {% set data.text = data.text + [["Кстати,", "Не забудьте, что", "Напоминаю, что"]|random] + [" у вас"] + [[" открыто", " не закрыто"]|random] + [" окно"] %}
      {% endif %}
    
      {% if not loop.first and not loop.last %}
        {% set data.text = data.text + [", "] + [k] %}
      {% elif loop.last and not loop.first %}
        {% set data.text = data.text + [" и "] + [k] %}
      {% else %}
        {% set data.text = data.text + [" "] + [k] %}
      {% endif %}
    {% endfor %}
    
    {{ data.text|join("") }}
  media_content_type: text

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *