35. YAML для чайника. Синтаксис, шаблоны
В предыдущей статье был разобран пример по умолчанию, выдаваемый инструментом редактирования шаблонов. Пришло время рассмотреть более жизненные и практические примеры.
Начнём без лишних предисловий.
В первую очередь определимся с понятиями выражений(states) и утверждений (statements).
Выражения начинаются и заканчиваются парой фигурных скобок: {{ выражение }}.
Утверждения же, используют фигурную скобку и знак процента {% утверждение %}.
И в том и в другом случае всё указывается через пробел.
Какая разница между ними?
Выражение отображает данные выдаваемые объектом.
Утверждение отображает указанные в нём данные, на основании условий указанных относительно объекта.
Иногда новичку не понятно почему в одних случаях используется оператор if states , а в других - if is_state.
Кстати, если обратить внимание на вывод, то видно что между строчками пропущена больше чем одна строка, пропущенная в коде. Это происходит потому, что каждая строка шаблона заканчивается на символ перехода на новую строку.
---
Строка вида {{ states('имя_объекта') }} показывает состояние которое в данный момент имеется в статусе объекта.
---
Строка вида {{ is_state('binary_sensor.имя_объекта','on') }} работает, когда выбранный бинарный сенсор будет во включенном положении.
---
Строка вида {{ state_attr('имя_объекта','атрибут') }} будет выводить значение атрибута объекта.
Пример выражений:
Сейчас не утро.
Сенсор определяющий это находится в выключенном состоянии.
Атрибут отвечающий за следующее изменение статуса показывает данные.
Пример утверждений:
Если объект в состоянии ВКЛ - отобразить слово "Утро".
Ещё если объект в состоянии ВЫКЛ - отобразить "Не утро".
Оператор {% else %} отвечает за вывод данных, если состояние объекта не перечислено в условиях.
В случае утверждений, интерпретатор языка проверяет каждую строку на предмет соответствия условиям, и останавливается там, где выражение удовлетворяет условиям.
Важно заметить, что при использовании логических операторов типа ЕСЛИ (о них чуть ниже), обязательно нужно указать конец определения условий выбора с помощью оператора {% endif %}.
Важно заметить, что при использовании логических операторов типа ЕСЛИ (о них чуть ниже), обязательно нужно указать конец определения условий выбора с помощью оператора {% endif %}.
Логика у этого выражения очень простая.
Множественное число применяется к объектам, у которых состояние может принимать много значений.
Единственное число применяется к объектам, у которых набор состояний ограничен доменом самого объекта.
Например сенсор температуры может принимать самое разное значение. А бинарный сенсор или переключатель могут иметь только одно - ON/OFF или TRUE/FALSE.
Кстати, если обратить внимание на вывод, то видно что между строчками пропущена больше чем одна строка, пропущенная в коде. Это происходит потому, что каждая строка шаблона заканчивается на символ перехода на новую строку.
Знак "-" (минус) после открывающихся скобок в строке кода, убирает переход на новую строку в выводе результата gперед текстом. Этот же знак перед закрывающимися скобками в коде, убирает переход на новую строку после текста вывода.
Тот же код что и раньше, но с минусами. Вывод на экран отличается:
---
Логические операторы: И, ИЛИ, НЕТ, ЕСЛИ, ИНАЧЕ ЕСЛИ.
НЕТ: {{ not is_state('binary_sensor.device1', 'on') }}. Вернёт состояние TRUE когда устройство ВЫКЛЮЧЕНО. И наоборот - FALSE если включено.
И: {{ is_state('binary_sensor.device1', 'on') and is_state('binary_sensor.device2', 'on') }}. Вернёт состояние TRUE только если состояния обоих объектов удовлетворяют указанным значениям.
ИЛИ: {{ is_state('binary_sensor.device1', 'on') or is_state('binary_sensor.device2', 'on') }}. Вернёт состояние TRUE если состояние любого из объектов удовлетворяет указанным значениям.
ЕСЛИ: Объект -{% if is_state('light.lamp1', 'on') %} Включен {% else %} Выключен{% endif %}. Отобразит результат вида: Объект - Состояние. В зависимости от состояния указанного объекта. Данный пример работает по принципу - если статус объекта находится в указанном положении, то показать одну надпись. Иначе - другую.
ИНАЧЕ ЕСЛИ: Используется когда надо вывести одно из условий
{% if states('sensor.device1') | float > 10 %} 10+
{% elif states('sensor.device2') | float < 10 %} 10-
{% endif %}
Если показания устройства в числовом виде имеют значение больше 10, то выводится +10. Если меньше, 10-.
---
Преобразование отображаемых данных в число с плавающей запятой: |float. Даже если выводится цифровое значение, для компьютера это значение является текстовым. Т.е. если ему явно не определить что вот это вот цифры и относись к ним как цифрам, то математические действия будут невозможны. Эти числа используют только точку как разделитель, не запятую.
---
Округление знаков после запятой: |float(0). Цифра в скобках указывает до какого знака после запятой необходимо округлить желаемое значение. 0 знаков - будет целое число, 1 знак - десятые доли, 2 - сотые, и т.д. Важно заметить, что производится именно округление, а не отсечение всех остальных знаков.
---
Определение целого числа: |int. Обрабатывается языком по аналогии с float.
---
Для сложения показаний двух устройств, данные с каждого объекта переводим в числовой вид. При этом каждый объект заключён в скобки со всем тем, что к нему относится. Только тогда между объектами ставится знак плюс. {{(states('имя_объекта1')|float) + (states('имя_объекта2')|float)) }}
---
Умножение. Сначала определяем что значение является числовым, и выполняем действие. В качестве примера: Датчик атмосферного давления на улице показывает давление в гектопаскалях, а человеку этот параметр более понятен когда он в миллиметрах ртутного столба. {{ (states('sensor.pogoda_davlenie')|float * 0.7500637)|round(2) }}. Так же здесь указан ещё один способ округления результата, т.к. оператор float уже занят умножением.
Пример создания сенсора:
- sensor:
- name: Погода давление мм.рт.ст.
icon: mdi:gauge
unit_of_measurement: "mm"
state: >
{{ (states('sensor.pogoda_davlenie')|float * 0.7500637)|round(2) }}
---
Определение целого числа: |int. Обрабатывается языком по аналогии с float.
---
Операторы сравнения: == равно, != не равно, > больше, >= больше или равно, < меньше, <= меньше или равно.
пример работы операторов сравнения.
Пример создания бинарного сенсора на основе показаний мощности розетки:
- binary_sensor:
- name: "Устройство"
{{ states('sensor.rozetka_power')|float(0) > 10}}
Когда у обычного сенсора значение будет больше 10 ватт, будет известно что телевизор работает. В данном случае нужно обязательно указать дефолтное значение 0 ватт. Т.к. отключенная розетка розетка будет выдавать именно его. И если устройство подключенное в розетку находится в выключенном состоянии, то ХА выдаст ошибку.
---
Операторы времени.
Преобразование данных в объект даты и времени: | as_datetime.---Время сейчас: {{ now()}}. Возвращает данные в формате UTC 2022-10-15 22:28:05.534419+03:00.---Время в формате Unix: {{ as_timestamp(now())}}. Возвращает данные в виде секунд прошедших с 00:00:00 UTC 1 января 1970 года.---
---
Время в формате Unix: {{ as_timestamp(now())}}. Возвращает данные в виде секунд прошедших с 00:00:00 UTC 1 января 1970 года.
---
Перевод в обычные часы минуты и секунды: {{ as_timestamp(now())| timestamp_custom("%H:%M:%S")}}.---Перевод времени из UTC в местное:{{ (as_timestamp(states('sensor.device123')) | timestamp_custom("%H:%M")) }}---Число, день недели, номер недели в году, номер месяца, год:{{ now().day }}, {{ now().weekday }}, {{ now().strftime("%W") }}, {{ now().month }}, {{ now().year }}
Перевод в обычные часы минуты и секунды: {{ as_timestamp(now())| timestamp_custom("%H:%M:%S")}}.
{{ (as_timestamp(states('sensor.device123')) | timestamp_custom("%H:%M")) }}
Пример перевода данных из секунд в дни, часы и минуты:
Некое устройство передаёт время своей работы в секундах.
Обозначаем переменную и переводим значение сенсора в целое число.
Форматируем вывод переводя секунды в минуты, часы и дни. Параллельно с этим используем отображение по блокам: в первом блоке переменная указывает на количество секунд в сутках. Во втором - вычисляем количество секунд в часе, и в третьем - в минуте.
{% set s = states("sensor.device_uptime") | int %}
{{ '{:d} дней {:02d} часов {:02d} минут'.format (s // 86400, s % 86400 // 3600, s % 3600 // 60) }}
Результат этого кода:
Если делать сенсор с таким кодом, то важно обозначить класс устройства:
device_class: duration.
Пример отображения оставшегося времени.
Есть сенсор посудомойки отображающий время, через которое будет завершено мытьё посуды, в формате: 2022-10-16T23:53:35+00:00.
Задача: отобразить понятное значение оставшегося времени до завершения мытья посуды.
Что надо сделать:
1. Обозначить показания сенсора как объект даты и времени.
2. Вычесть из него текущее время включая секунды.
3. Отобразить результат как часы и минуты
{{ ((states('sensor.pm_rpt') | as_datetime) - now()).total_seconds() | timestamp_custom('%H:%M', false) }}
Результат этого кода:
---
Как уже было сказано ранее, в одной статье невозможно, да и нет смысла описывать все возможности языка. Равно как и нет возможности предугадать какой код и для какого случая может кому-то понадобиться. Вполне вероятно что данная статья ещё будет пополняться примерами. Но главная её цель - объяснить и показать возможности языка и платформы, для дальнейшего самостоятельного воплощения своих идей.
Комментарии
Отправить комментарий