Интеграция сенсора времени работы сервера теперь возможна только через пользовательский интерфейс

@510510510g
510510510g

changed the title
This integration is not configurable through the UI. If you are clicking on the link from the Home Assistant website, make sure you are running the latest version of Home Assistant.

This integration does not support configuration via the UI. If you followed this link from the Home Assistant website, make sure you run the latest version of Home Assistant.

Jul 16, 2022

Мониторить показатели сервера умного дома внутри самой системы умного дома? Почему бы и нет.

В этой статье я расскажу о том, как настроить мониторинг сервера Home Assistant внутри самого Home Assistant при помощи нескольких стандартных интеграций.

Содержание

  • 1 Добавляем интеграции
    • 1.1 Updater
    • 1.2 Raspberry Pi Power Supply Checker
    • 1.3 System Monitor и Version
  • 2 Настраиваем карточку с информацией
  • 3 Заключение

Добавляем интеграции

Для реализации используемого мной мониторинга можно воспользоваться следующими интеграциями:

  • Updater — проверяет наличие доступных обновлений для Home Assistant
  • Version — выводит номер текущей версии Home Assistant
  • Raspberry Pi Power Supply Checker — проверяет достаточность питания для Raspberry Pi
  • System Monitor — выводит различные показатели системы

Если ваш Home Assistant установлен не на Raspberry Pi, то интеграцию Raspberry Pi Power Supply Checker можно не включать. Все остальные интеграции универсальны и не зависят от железа.

Updater

Бинарный сенсор Updater активен в Home Assistant по умолчанию с момента установки. Его добавлять не нужно.

Raspberry Pi Power Supply Checker

Интеграцию с этим сенсором, проверяющим «малинку» на наличие предупреждений о недостаточности питания (значок молнии на экране) активируем в веб-интерфесе Home Assistant:

Настройки → Интеграции → Добавить интеграцию → Raspberry Pi Power Supply Checker

System Monitor и Version

Эти интеграции дописываем в файл configuration.yaml:

sudo nano /home/homeassistant/.homeassistant/configuration.yaml

(Если Home Assistant устанавливался по моей инструкции, то путь к файлу будет таким)

Код для configuration.yaml:

sensor:
  - platform: systemmonitor
    resources:
      - type: disk_use_percent
        arg: /
      - type: memory_use_percent
      - type: processor_temperature
      - type: ipv4_address
        arg: wlan0
      - type: processor_use
      - type: last_boot

  - platform: version

В данном случае у нас будут доступны следующие сенсоры от System Monitor: disk_use_percent (объем занятого дискового пространства в процентах), memory_use_percent (объем занятой оперативной памяти в процентах), processor_temperature (температура CPU), ipv4_adress (IP-адрес устройства в локальной сети, wlan0 для беспроводного подключения или eth0 для Ethernet), processor_use (нагрузка на процессор в процентах), last_boot (время с последней перезагрузки устройства).

После чего перезагружаем Home Assistant, чтобы он «увидел» новые сенсоры:
Настройки → Сервер → Перезапустить

Это важно

Home Assistant очень чувствителен к отступам в строках. Замена пробелов табуляцией, хотя бы один лишний или недостающий пробел — и вместо перезапуска сервера в уведомлениях появится сообщение об ошибке.

Настраиваем карточку с информацией

Теперь добавляем новую карточку и выводим в нее появившиеся сенсоры:
Изменить панель → Добавить карточку → Объекты.

Я использую карточку типа «Объекты» (Entities), но можно взять зайдействовать другой вид оформления. Например, разнести сенсоры по отдельным карточкам с разным представлением информации.

Код для карточки:

type: entities
entities:
  - entity: sensor.processor_temperature
    name: Температура CPU
    icon: 'mdi:temperature-celsius'
  - entity: sensor.processor_use_percent
    name: Загрузка CPU
  - entity: sensor.memory_use_percent
    name: Загрузка RAM
  - entity: sensor.disk_use_percent
    name: Заполненность HDD
  - entity: binary_sensor.rpi_power_status
    name: Статус питания
  - entity: sensor.ipv4_address_wlan0
    name: IP-адрес (Wi-Fi)
  - entity: sensor.last_boot
    name: Последняя перезагрузка
  - entity: sensor.current_version
    name: Версия Home Assistant
    icon: 'mdi:home-assistant'
  - entity: binary_sensor.updater
    name: Обновление HA доступно
title: Статус системы

В данном случае мы добавляем кастомные иконки к сенсорам с температурой процессора и текущей установленной версией Home Assistant. Также каждому сенсору присваивается удобное для восприятия название.

Получившаяся карточка в веб-интерфейсе:
Мониторинг сервера Home Assistant внутри Home Assistant

Заключение

Вот таким образом можно мониторить состояние сервера Home Assistant внутри самой системы умного дома.

На данный момент мой сервер Home Assistant работает на базе Raspberry Pi 4 с 4 Гб оперативной памяти. В следующих статьях цикла я опишу другие используемые мной интеграции.

Время на прочтение
11 мин

Количество просмотров 110K

Home Assistant — это популярная система умного дома, которая автоматизирует привычные бытовые процессы и работает на YAML файлах. В этой статье я расскажу, как настроить Home Assistant (далее HA), и что конкретно я использую в повседневной жизни. Это поможет вам избежать ошибок и быстрее продвинуться в изучении HA.

На Хабре уже есть статьи о HA (раз, два, три), но здесь я хочу рассказать об установке и настройке системы от начала до конца. От первого запуска сервера до полноценно работающей системы, которую потом можно улучшать и дорабатывать для себя.

Основной единицей в HA является интеграция — логика, которая описывает взаимодействие с умным устройством или внешним сервисом. Большая часть полезной нагрузки HA ориентировано на связку: умное устройство + интеграция или внешнее API + интеграция.


Набор моих интеграций

Железо, участвующее в статье:

  • Микроконтроллер Esp8266, а также датчик температуры и влажности DHT11;
  • Лампа Xiaomi Desk Lamp;
  • Raspberry Pi 4B в 2GB версии, как сервер для HA (в дальнейшем буду ее называть малинкой);
  • Xiaomi Router 4A .

Сервисы, которые будем использовать:

  • OpenWeatherMap для получения погоды, температуры, влажности на улице и других метеопараметров;
  • Telegram для создания системы уведомлений;
  • Google drive для создания бекапов;
  • SpeedTest для замеров скорости;
  • А также OpenUV для замеров ультрафиолетового излучения и др.

Установка

Установка HA предельно проста:

  1. Записать образ HA на SD карточку (подробная инструкция с ссылками на скачивание для разных версий Raspberry Pi тут).
  2. Подключить питание и Ethernet к малинке
  3. Подождать несколько минут, пока система развернется в локальной сети на <ip адрес малинки>:8123.

Также можно установить на уже имеющуюся систему с помощью Docker-compose:

version: '3'
services:
  homeassistant:
    container_name: homeassistant
    image: homeassistant/raspberrypi4-homeassistant:stable
    volumes:
      - /PATH_TO_YOUR_CONFIG:/config
      - /etc/localtime:/etc/localtime:ro
    restart: unless-stopped
    network_mode: host

А теперь разберем несколько сценариев использования.

Отслеживание устройств

Начнем с отслеживания устройств, с помощью которого мы можем фиксировать вход и выход носителей из дома.
Я предлагаю 2 способа отслеживания:

  • с помощью роутера (у меня в наличии Xiaomi Router Mi4A),
  • с помощью GPS.

В системе доступно много производителей роутеров. Для старых и не перечисленных в списке моделей можно использовать nmap (более подробно тут).
Если установить на телефон официальное приложение, HA по умолчанию создаст интеграцию, и в системе появится дополнительное устройство, которое можно отследить.

С помощью Xiaomi Router Mi4A

Плюсы

  • Не требует никаких действий на устройстве, отслеживает всех в локальной сети.

Минусы

  • Если устройство не подключено к домашней сети, то устройство пропадает в пустоту, и на картах мы его не увидим.
  • Иногда может сработать триггер выхода/входа из зоны, когда фактически девайс не покидает зону (можно попробовать решить расширением зоны).

С помощью GPS

Плюсы

  • Точность работы сравнима с GPS трекером в телефоне.
  • О телефоне можно узнать: процент заряда аккумулятора, заряжается устройство или нет, а также показатель состояния аккумулятора.

  • Можно контролировать устройства (пользователей) не только на вход домой, но и на вход в любую из кастомных зон.

Минусы

  • Активно тратит заряд.
  • Требует подключение Интернета.
  • Для точного трекинга необходимо настроить SSL, чтобы телефон мог отправлять данные о местоположении из вне локальной сети.
  • Требует дополнительных прав доступа к GPS, возможна утечка данных третьей стороне в будущем.
  • На бюджетных телефонах, которые имеют свойство неожиданно менять местоположение GPS, возможны проблемы с выпадением из зоны.

Создание системы отслеживания через роутер

Трекинг через локальную сеть роутера требует настройки, в отличие от GPS отслеживания. Два вида трекинга можно комбинировать для повышения точности. Ниже можно заметить, что в моем случае отслеживание через роутер работает лучше, чем через GPS. Зеленая зона значит, что телефон внутри зоны, красная — вне зоны.


Результаты работы отслеживания (сверху — роутер, снизу — GPS)

Редактирование конфигурационных файлов через VSCode

Можно подключиться через плагин SSH в VS Code, но получить доступ к проводнику в данный момент мне было удобнее. Поэтому, добавим сетевое расположение.

Нажмем обзор, найдем каталог config (мы в основном будем редактировать его) и выберем его как сетевую папку.

Дальше мы можем перейти в созданную папку и открыть ее через редактор.

router_device_tracker.yaml

platform: xiaomi
host: 192.168.31.1
password: !secret xiaomi_router_password
configuration.yaml
device_tracker: !include configs/router_device_tracker.yaml

После перезагрузки HA мы можем увидеть, что у нас появился новый глобальный объект device_tracker и наши устройства в нем.


Трекинг устройств через роутер

Освещение

Теперь, когда мы умеем отслеживать пользователя, мы можем включать и выключать определенные лампочки с учетом информации о его местоположении.

Для этого необходимо произвести действие по определенному событию. В этом нам помогут автоматизации.

automation/phone_tracker

- alias: Entering home
  trigger:
    platform: state
    to: home
    entity_id: device_tracker.mi9lite
  action:
    - service: light.turn_on
      data:
        entity_id: light.midesklamp1s_f86f
        brightness: 35
        color_temp: 350

- alias: Leaving home
  trigger:
    platform: state
    to: not_home
    entity_id: device_tracker.mi9lite
  action:
    - service: light.turn_off
      entity_id: light.midesklamp1s_f86f

Теперь импортируем в наш основной файл весь каталог automation — так нам будет удобнее при написании следующих автоматизаций.

configuration.yaml

automation: !include_dir_merge_list automation

Пример работы:
https://www.youtube.com/watch?v=Sii4rBtXYVw

Для того, чтобы получить адаптивное освещение в зависимости от времени суток, нужно настроить цветовую температуру. Это удобно сделать внутри блока switch. Тут важно понимать, что пока данный switch включен, изменить параметры температуры будет невозможно (через interval минус время_с_прошлого_обновления лампа примет старые параметры).

Здесь вы найдете больше про динамическую цветовую температуру (flux в терминологии HA). А если вам интересна тема адаптивного освещения, на Хабре есть отличная статья по этому поводу.

configuration.yaml

switch:
  - platform: flux
    lights:
      - light.midesklamp1s_f86f
    name: Fluxer
    start_time: '9:00'
    stop_time: '0:00'
    start_colortemp: 5000
    sunset_colortemp: 3200
    stop_colortemp: 2800
    brightness: 25.5
    disable_brightness_adjust: true # яркость будет константой
    mode: mired # для не rgb ламп
    transition: 30
    interval: 30```

<!--</spoiler>-->
# Погода
По умолчанию в HA уже присутствует интеграция с погодным API от [Meteorologisk institutt](https://www.home-assistant.io/integrations/met/) (Норвежский метеорологический институт), но мы можем легко создать другую прямо через UI.

## Создание новой интеграции OpenWeatherMap
Переходим в config / Integration на UI , нажимаем на Add integration, и выбираем из списка OpenWeatherMap.

![](https://habrastorage.org/webt/wk/q5/gu/wkq5guripld3x0rlvuuvrh6us-8.png)

Вводим api_key, полученный на их сайте и нажимаем Submit. В итоге получим 19 сущностей, которые можем использовать для своих целей в автоматизациях.

![](https://habrastorage.org/webt/l1/dj/ps/l1djps20zhxaghdhbfrxzcm7tac.png)
*Сущности OWM (на скриншот попали не все 19)*

Таким же образом через UI можно создать интеграции к другим сервисам вроде SpeedTest, или OpenUV.

# Уведомления
Для настройки уведомлений можно использовать стандартные оповещения HA, отображаемые в боковом меню, уведомления на конкретных устройствах (нужно установленное приложение на девайсе), а также оповещения в сторонние сервисы.

![](https://habrastorage.org/webt/vw/lo/uk/vwloukneshhkvd6sklfjojnsvrc.png)
*persistent_notification*

Альтернативный способ уведомлений - это уведомления в сторонние сервисы, например Telegram. Для начала нужно создать бота, получить его api_key (при создании отправят ключ) и chat_id, который можно найти в ответе внутри `result.chat.id` после запроса на https://api.telegram.org/bot{api_key}/getUpdates .

<!--<spoiler title="Ответ с Telegram API приходит пустой">-->

Такое иногда случается по разным причинам. 
В таких случаях подходит другой способ получения chat_id - написать @getmyid_bot  боту и скопировать себе user ID.
<br>
![](https://habrastorage.org/webt/h_/em/a_/h_ema_sk04ldd4xsfkdzdthaml4.png)

<!--</spoiler>-->
Простейшая настройка Telegram бота:

<!--<spoiler title="notification/telegram_bot.yaml">-->

  • platform: polling
    api_key: !secret telegram_api
    allowed_chat_ids:

    • !secret telegram_chat_id

Для того, чтобы не разглашать всем секретные данные, создадим еще secrets.yaml. Туда мы сложим все данные, которые не должны попасть в публичный доступ. Для использования переменных из этого файла используем !secret.

Пример секретов:

secrets.yaml

telegram_api: %api_key%
telegram_chat_id: %chat_id%

configuration.yaml

telegram_bot: !include notification/telegram_bot.yaml

В итоге у нас имеется Telegram бот, готовый к отправке сообщений.

Утренние (или нет) погодные оповещения

Теперь, когда у нас есть настроенный сервис уведомлений и погодная интеграция, мы можем сделать утренние оповещения о погоде.

Создаем новый файл автоматизации, и начинаем писать логику.

Пишем переменную, которая будет отвечать за срабатывание оповещений только по будням. Если он true — то в выходные оповещений не будет.

input_boolean.yaml

alarmweekday:
  name: Weekdays Only
  initial: off
  icon: mdi:calendar

И подключаем в основном конфиг файле.

configuration.yaml

input_boolean: !include input_boolean.yaml

automation/morning_alarm.yaml

- alias: 'Wake Me Up'
  trigger:
    platform: time
    at: input_datetime.weather_notification
  condition:
    condition: or
    conditions:
      - condition: and
        conditions:
          - condition: state
            entity_id: input_boolean.alarmweekday # оповещение в выходные
            state: 'on'
          - condition: time
            weekday:
              - mon
              - tue
              - wed
              - thu
              - fri
      - condition: and
        conditions:
          - condition: state
            entity_id: input_boolean.alarmweekday
            state: 'off'

  action:
    service: telegram_bot.send_message
    data: # тут
      message: "{% if now().strftime('%H')|int < 7 %} 
        Доброй ночи,
        {% elif now().strftime('%H')|int < 12 %}
        Доброе утро,
        {% elif now().strftime('%H')|int < 18 %}
        Хорошего дня,
        {% else %}
        Хорошего вечера,
        {% endif %}
         сейчас на улице {{states('sensor.openweathermap_temperature')}}°C. "

Пример работы:
https://www.youtube.com/watch?v=vSmSbSd_f-Q

Добавим blueprints

Теперь небольшое лирическое отступление в виде рассказа о написании blueprints на примере уведомлений.

В данном случае я бы перевел blueprints не как чертежи, а как шаблоны или заготовки. Их удобнее использовать, если нужно написать несколько похожих автоматизаций, а основную логику оставить нетронутой.

Например, можно упростить создание уведомлений о начинающихся осадках.

blueprints/precipitation_start.yaml

blueprint:
  name: Fallout start notification
  domain: automation
  input:  # аргументы шаблона
    precipitation:
      name: Precipitation level
      selector:
        entity:
          domain: sensor # только для ui, поможет создать автоматизацию, предоставляя только сенсоры в выпадающем списке
    message_start:
      name: Telegram message
      default: "No message"

trigger: # условия срабатывания
  - platform: numeric_state  
    entity_id: !input precipitation
    above: 0.9
    for: 
         minutes: "{{ states('input_number.minimum_time_for_stable_value')|int }}"

action:
  - service: telegram_bot.send_message
    data:
      message: !input message_start 

“for” — это время, в котором должен оставаться выбранный параметр, чтобы сработал триггер на превышение уровня осадков.

input_number.yaml

minimum_time_for_stable_value:
  name: Minimum time for stable value
  initial: 1
  min: 0
  max: 59
  step: 1

Теперь, когда есть blueprint, мы можем написать автоматизацию с меньшим количеством логики.
Создадим уведомления о начале осадков.

automation/rain_start.yaml

- alias: 'Rainy is started'
  use_blueprint:
    path: homeassistant/fallout_start_notification.yaml
    input:
      precipitation: sensor.openweathermap_rain
      message_start: "Похоже, дождь начинается. Уже накапало {{states('sensor.openweathermap_rain')}}мм."
automation/snow_start.yaml

- alias: 'Snow is started'
  use_blueprint:
    path: homeassistant/fallout_start_notification.yaml
    input:
      precipitation: sensor.openweathermap_snow
      message_start: "Пошел снежок. Уже навалило {{states('sensor.openweathermap_snow')}}мм."

Мы смогли вынести часть функциональности в отдельный файл. В подобных случаях, когда со временем появляется похожий код, можно выносить часть логики в отдельный файл.

Для большей полезности можно изменить шаблон и поменять action на повышение яркости для света в доме или закрытие штор.

Бэкапы

В бэкап попадает весь каталог /config, а также все установленные расширения. С любого бекапа можно восстановить состояние системы на момент его создания.

Можно настроить создание резервных копий в Google Drive:

  1. Скопировать ссылку https://github.com/sabeechen/hassio-google-drive-backup и зайти в HA (также можно прочитать подробную инструкцию в ReadMe репозитория по ссылке)
  2. Добавить ссылку как кастомный репозиторий в Supervisor’е через UI.

  3. Открыть его (Open Web UI) и следовать инструкциям по аутентификации с Google Drive

После этих манипуляций мы получаем регулярное создание бекапов, важность которых сложно переоценить.

Интерфейс бекапов

ESP


NodeMCU

Так как умного градусника у меня нет, а температуру измерять хочется, воспользуемся ESP8266.
Сначала установим интеграцию ESPHome из официального списка интеграций.

Для каждого микроконтроллера, используемого в системе, требуется создать файл с подобным содержанием.

esphome/home_params.yaml

Проинициализируем контроллер.

esphome:
  name: home_params
  platform: ESP8266
  board: nodemcuv2

logger:
api:
ota:

Подключимся к WiFi

wifi:
  ssid: !secret xiaomi_router_ssid
  password: !secret xiaomi_router_password

По умолчанию используются секреты только от ESPHome. А для того, чтобы подгрузить секреты из HA, можно создать отдельный файл, где мы заинклудим эти секреты.

Теперь подключим data pin (обычно это средняя нога) термометра к D2 порту, дадим на него питание и землю. Потом создаём сам термометр (DHT11) и две переменные, которые будем отслеживать в HA.

sensor:
  - platform: dht
    model: DHT11
    pin: D2
    temperature:
      name: "Living Room Temperature"
    humidity:
      name: "Living Room Humidity"
    update_interval: 60s

Дальше нужно скомпилировать прошивку и загрузить на контроллер. Если он подключен напрямую к Raspberry Pi, то мы увидим его на /dev/ttyUSB0 и сможем загрузить прошивку в первый раз. Все последующие обновления можно загружать по воздуху. А если в списке устройства не видно, то можно скачать прошивку и воспользоваться ESPHome-Flasher.

Загружаем прошивку.

Если все заработало, то в Developer Tools мы увидим созданные переменные.

Developer Tools

Немного оптимизации

По умолчанию в HA используется SQLite, и сброс данных на диск происходит часто (каждую секунду). Это может привести в скором времени к выходу из строя SD карточки на малинке (если сервер стоит на ней). Чтобы продлить срок службы карточки, скажем HA, что нужно записывать на диск раз в commit_interval и исключить некоторые сущности, которые мы не хотим отслеживать на длинном временном промежутке (или вообще не хотим отслеживать).

configs/recorder.yaml

commit_interval: 1500
purge_keep_days: 7
exclude:
  domains:
    - updater
    - automation
  entity_globs:
    - sensor.miwifi_router*
  entities:
    - sensor.date
    - sensor.date_time
    - sensor.time
    - sensor.openweathermap_forecast_time

configuration.yaml

recorder: !include  configs/recorder.yaml

Если мы хотим использовать СУБД, отличную от SQLite, то можно сделать один из следующих пунктов на выбор:

  1. Установить соответствующий аддон для перехода на MariaDB.
  2. Использовать существующую реляционную базу данных на удаленной машине, если указать строку для подключения в параметр db_url.

Отслеживание системных параметров

Чтобы отслеживать остаток свободной памяти, загруженность процессора или скорость Интернет соединения, мы можем добавить мониторинг показателей системы.

sensors/system_monitor.yaml

- platform: systemmonitor
  resources:
    - type: disk_use_percent
      arg: /
    - type: memory_free
    - type: memory_use_percent
    - type: processor_use
    - type: processor_temperature
    - type: disk_free
      arg: /

При желании можем создать автоматизацию, которая при критических показателях будет отправлять уведомление о необходимости принятия мер.

Также мы можем посмотреть Uptime сервера.

sensors/uptime.yaml

- platform: uptime
  name: Time Online

configuration.yaml

sensor: !include_dir_merge_list sensors

Вариант представления на UI

Заключение

Плюсы HA

  • Простая установка и настройка, не требующая знания программирования.
  • Большое коммьюнити — вопросов на форуме много, ответов тоже хватает.
  • Огромное количество готовых интеграций со сторонними сервисами — скорее всего не придется писать свою интеграцию руками.

Минусы HA

  • Достаточно сложно отлаживать систему. Если action можно запустить программно в обход триггера, то триггер тестировать уже сложнее.

В итоге мы создали несложную систему умного дома, которую каждый может расширить покупкой новых устройств или написанием своих продуманных и продвинутых автоматизаций. По этой ссылке можно найти полную версию моих автоматизаций дома.


Главный экран

Что дальше? Можно добавить HACS (сборник UI компонентов и даже целых интеграций от коммьюнити, пригодится при использовании Яндекс Станции) и установить несколько UI элементов. Можно интегрировать умную колонку или телевизор и включать их по определенному условию. Вариантов апгрейда бесконечное множество.

Успехов в автоматизации!

Литература

  • Документация HA

Создание композитных приложений из повторно используемых компонентов — важная методика в программной инженерии и управлении данными.

Создание композитных приложений из повторно используемых компонентов — важная методика в программной инженерии и управлении данными.

Разработка пользовательского интерфейса (User Interface, UI) — один из наиболее ресурсоемких этапов создания, тестирования и поддержки приложения, поэтому совершенно естественно, что повторное использование компонентов UI столь же важно, как и повторное использование логики приложений [1]. Но, даже несмотря на то, что существуют платформы (такие, как Java Swing), помогающие в современных разработках UI, интеграция отдельных компонентов и, возможно, автономных приложений на уровне UI так и не получила должного внимания.

В этой статье анализируется проблема интеграции графического пользовательского интерфейса, т. е. интеграции компонентов за счет объединения их внешнего представления, а не логики или схем данных самих приложений. В этом случае компонентами являются автономные модули или приложения. Цель заключается в том, чтобы использовать UI отдельных компонентов для создания более функциональных композитных приложений. Необходимость в подобной интеграции очевидна. Приложения, которые накладывают информацию о зданиях на карты Google Maps, приборные панели, ведущие мониторинг различных аспектов производительности компьютерных систем, или операционные Web-среды, которые поддерживают координированные взаимодействия с различными приложениями на одной и той же Web-странице. Все эти примеры требуют координации пользовательских интерфейсов приложений. Увеличение масштаба карты, например, означает, что накладываемая информация о домах, выставленных на продажу, тоже должна измениться.

Уровни интеграции

Для того чтобы описать различные виды интеграции, мы используем простой, но конкретный пример, в основу которого положена разработка реальных приложений в компании Hewlett-Packard. Рассмотрим набор приложений, ведущих мониторинг производительности и качества систем, сетей, сервисов и бизнес-процессов. В рамках этого примера инструментарий системного мониторинга регистрирует параметры (такие, как загрузка центрального процессора) для набора машин и посылает уведомления в том случае, если значения этих параметров превышают определенные пороговые величины, а приложение мониторинга процессов анализирует выполнение бизнес-процессов и сообщает об основных показателях производительности, таких как продолжительность процесса или скорость его реализации. Как и большинство современных приложений, все перечисленные делятся на три уровня: презентация, приложение (также называемое уровнем бизнес-логики) и данные.

Исторически сложилось так, что разработчики ведут мониторинг приложений независимо, но все чаще возникает потребность оценить их в совокупности. Это полезно для анализа коренных причин (чтобы понять, какие системные проблемы вызвали задержку на уровне процессов), а также для анализа влияния на бизнес (чтобы понять, как ошибка или снижение производительности в базовой системе отражаются на уровне процессов, и в целом иметь общее представление об управляемых системах ИТ). В качестве простого примера интеграции предположим, что интегрированное приложение мониторинга формируют два компонента: инструментарий мониторинга бизнес-процессов и инструментарий мониторинга системы. В интегрированном приложении, когда пользователь хочет отобразить конкретный процесс в инструментарии мониторинга, данные о состоянии и статусе готовности его вспомогательных систем должны появиться в приложении системного мониторинга. Давайте посмотрим, как это можно сделать.

При интеграции данных [2] композитные приложения имеют свои собственные уровни презентации и приложения, в то время как уровень данных — это интеграция источников данных, которые компонентные приложения могут поддерживать независимо, как это показано на рисунке. В нашем примере различные приложения мониторинга собирают данные в свои локальные хранилища, не зная о том, что они являются объектами интеграции. Уровень интеграции объединяет вместе источники данных и формирует общее, гомогенное представление для композитного приложения. Уровень интеграции может быть физическим или оставаться виртуальным.

При интеграции данных возникает несколько задач, от разрешения несоответствий между моделями данных компонентов (например, когда одни и те же термины имеют разные значения) до создания и поддержки виртуальных схем и установки соответствия запросов между глобальной и локальной схемой. Это требует определенного «сотрудничества» от компонентных приложений: мы всегда можем обратиться к базам данных приложений с помощью SQL-запросов или технологий интеграции информации предприятия (Enterprise Information Integration, EII). Недостаток этого подхода заключается в том, что такое решение требует значительных усилий для того, чтобы разобраться в моделях данных, проанализировать семантические разнородности и поддерживать композитную схему с учетом изменений в схемах данных компонентов [3].

В последние 30 лет выполнено множество исследований в области интеграции приложений, в результате которых были созданы такие технологии, как удаленный вызов процедур, брокеры объектов и Web-сервисы [4]. При интеграции композитное приложение имеет свой собственный пользовательский интерфейс, но уровень бизнес-логики формируется за счет интеграции функций, предоставляемых компонентными приложениями, как показано на рисунке (б). В нашем примере мониторинга приложения могут предоставлять API, которые позволяют клиентам извлекать данные о производительности определенных систем или получать уведомления о случаях снижения этого показателя. Композитное приложение использует эти API для того, чтобы получать информацию, согласовывать ее между различными приложениями мониторинга и отображать консолидированное представление на свой графический пользовательский интерфейс. Когда такое возможно (т. е., когда такие API существуют), эта модель интеграции имеет несколько преимуществ, в том числе:

  • детальность функций, которые предоставляют компонентные приложения, как правило, хорошо подходит для высокоуровневой интеграции (например, мы можем потребовать от приложения начать мониторинг машины xyz, не обращая внимания на то, как эта деятельность повлияет на базу данных интегрированного приложения);

  • стабильность, поскольку приложение-компонент знает об интеграции (оно предоставляет API) и будет пытаться стабилизировать интерфейс между версиями.

Интеграция UI, как показано на рисунке (в), должна служить для объединения приложений на уровне презентации, оставляя управление данными и бизнес-логикой каждому из компонентов. Интеграция UI в первую очередь имеет смысл, когда интеграция приложений или данных невозможна (например, приложения не предоставляют API бизнес-уровня) или разрабатывать новый пользовательский интерфейс «с нуля» достаточно дорого (например, в том случае, если компонентное приложение быстро меняется или его пользовательский интерфейс слишком сложен).

Задача интеграции пользовательского интерфейса

Исследователи определили четыре класса задач, возникающих при интеграции данных и приложений, которые также являются основными и при интеграции UI. Они затрагивают следующие аспекты:

  • модели и языки для выбранных компонентов;

  • модели и языки для композиции выбранных компонентов;

  • виды связи, с помощью которых компоненты могут взаимодействовать;

  • механизмы обнаружения и связывания для выявленных компонентов (возможно, используемые во время исполнения).

В идеале модели и спецификации должны быть достаточно простыми для того, чтобы пользователи могли их понять и легко адаптировать, достаточно формальными, для того чтобы приложения и инструментарии могли их анализировать, и достаточно выразительными, чтобы моделировать широкий круг проблем.

Рассмотрим эти четыре аспекта и введем пятый, связанный собственно с задачей интеграции UI.

Компонентная модель

При интеграции приложений компоненты, по существу, характеризуются API и, возможно, компонентной моделью (такой, как в CORBA). При интеграции данных схемы источников данных описывают компоненты, но лишь недавно внешние спецификации стали использоваться при интеграции UI. Действительно, интеграция UI была главным образом предназначена для повторного использования библиотек классов, но выполнение интеграции на уровне презентации тоже требует компонентной модели, которая может поддерживать сложные взаимодействия и координацию. Для каждого отдельного компонента в нашем примере управления, например, мы должны описать:

  • программный интерфейс для компонентов, используемых при интеграции;

  • пользовательский интерфейс компонента, который позволяет с ним взаимодействовать.

Мы можем выделить несколько «степеней интероперабельности», которые допускает пользовательский интерфейс компонента.

Только графический пользовательский интерфейс. Аналогично традиционному монолитному настольному приложению, все взаимодействия с компонентами, поддерживающими коммуникации только на уровне графического пользовательского интерфейса, осуществляются через логику пользовательского интерфейса каждого из компонентов. Единственный способ интегрировать компонентное приложение — это хорошо разобраться в его UI, иметь возможность отслеживать позицию мыши или клавиши, нажимаемые пользователем, и, таким образом, понять, что показывает UI компонента и, возможно, даже выполнять действия, которые вызывают изменения UI (например, создать композитное приложение для того, чтобы имитировать нажатия клавиш мыши или клавиатуры). В этом случае интеграция превращается в очень сложную задачу.

Скрытый интерфейс. Во многих Web-приложениях компонент имеет интерфейс, который дает возможность пользователям контролировать его UI, но для этого интерфейса нет общедоступного описания. При взаимодействии с Web-приложением, например, мы можем получать доступ к контенту и манипулировать им, посылая запросы HTTP и отображая ответы. Такие приложения подчиняются общему протоколу взаимодействия между клиентами (UI) и приложениями, но выяснить формулировку этого протокола может оказаться непросто, поскольку изначально не предполагалось, что он будет программным образом использоваться клиентами.

Опубликованный интерфейс. В этом идеальном случае компонент предоставляет открытое описание своего UI и API для того, чтобы им можно было манипулировать во время исполнения. На низком уровне API может позволить управлять отдельными элементами UI, такими как кнопка или текстовое поле. Высокоуровневый API будет предоставлять набор элементов, т. е. наблюдаемых и управляемых объектов, таких как «система» или «сеть» в случае с мониторингом, а также операции для того, чтобы изменить статус элемента, например, «показать статус системы xyz».

Язык композиции

При интеграции данных композиция часто осуществляется через представления SQL, которые позволяют дизайнерам данных описывать глобальную схему как набор представлений над локальными схемами [2]. При интеграции приложений композиция реализуется либо с помощью языка программирования общего назначения, такого как Java, либо с помощью специализированных языков интеграции приложений, таких как языки композиции потоков работ или сервисов (www.oasis-open.org). Хотя для интеграции UI в этом направлении было сделано мало, мы уверены, что аналогичный подход можно применять и в данном случае. Мы выделяем два вида языков композиции.

Языки программирования общего назначения. Разработчики могут использовать языки третьего поколения для композиции приложений. Такие языки очень гибкие, но в них отсутствуют абстракции для достаточно крупных компонентов (например, механизмы для обнаружения и связывания компонентов или примитивы высокого уровня для синхронизации того, какие компоненты UI отображать).

Специализированные языки композиции. С другой стороны, языки высокого уровня, как правило, используются вместе с синтаксисом XML, адаптированным для композиции компонентов пользовательского интерфейса на уровне абстрактных/внешних описаний. Основное преимущество таких языков — это программирование композиции более высокого уровня, при котором используются характеристики компонентной модели. Если компонентная модель поддерживает, например, понятие элементов, язык композиции будет предоставлять примитивы для работы напрямую с этими концепциями (такие, как изменение отображаемого элемента).

Стиль коммуникаций

В нашем примере с мониторингом мы хотим знать, как контролируемые компоненты обмениваются событиями UI, чтобы получить инструкции, указывающие, что отображать или как уведомлять другие компоненты о любых действиях пользователя, значимых для композитного приложения (например, пользователь перенес фокус на другую систему, поэтому для всех компонентов UI необходимо также изменить фокус).

При интеграции данных компоненты, как правило, пассивны и не инициируют взаимодействия с интегрированным приложением. Такая ситуация типична и для интеграции приложений, при которой центральный элемент (композитное приложение) вызывает компоненты по мере необходимости, хотя полностью распределенные взаимодействия становятся все популярнее (например, когда продавец, покупатель и производитель общаются без центрального координатора).

При интеграции UI также можно различать коммуникации через центрального координатора и прямые взаимодействия. В первом случае в композитном приложении есть центральный координатор, который получает события от компонентов и выдает инструкции для манипулирования пользовательскими интерфейсами компонентов. При прямых взаимодействиях между компонентами, когда композитное приложение — это «коалиция» отдельных компонентов, ни одно высокоуровневое приложение эту деятельность не координирует. Следует также отметить еще одно важное различие между взаимодействием в стиле удаленного вызова процедур, при котором компоненты обмениваются информацией с помощью вызовов методов и возврата данных, и взаимодействием по принципу «публикации и подписки» [5], при котором приложения взаимодействуют слабо, обмениваясь сообщениями через брокеров сообщений. В последнем случае брокер распространяет сообщения с учетом контента или темы.

Обнаружение и связывание

В конечном итоге интеграция UI должна определить, какие компоненты интегрировать и как получить на них ссылку (например, уникальный идентификатор ресурса, URI). Это можно делать статически (во время проектирования или установки) или динамически (во время исполнения). В нашем примере с мониторингом необходимо определить, как композитное приложение обнаруживает, а затем связывается с соответствующими контролируемыми приложениями.

При интеграции данных и приложений связывание между различными источниками данных, как правило, осуществляется во время проектирования, когда мы определяем глобальную схему данных. Несмотря на то что интеграция программного обеспечения промежуточного слоя поддерживает динамическое обнаружение и связывание [4], эта гибкость, как правило, не используется из-за сложности взаимодействия с вновь обнаруженными компонентами, особенно в тех случаях, когда их предоставляет другая компания (сомнение вызывает их надежность). Во многих случаях приложения перегруппировываются для того, чтобы объединить статическое и динамическое связывание, при котором разработчик приложений определяет и тестирует набор потенциальных компонентов, а пользователь затем выбирает их подмножество во время исполнения, в зависимости от своей задачи. Такое решение называют гибридным связыванием, при котором обнаружение выполняется статически, но мы получаем ссылку во время исполнения. То же самое возможно и при интеграции UI.

Визуализация компонентов

Так кто именно отвечает за отображение компонентов UI? Сам компонент или композитное приложение? В нашем примере с мониторингом мы хотим знать, будут ли компоненты отображать свою собственную панель мониторинга или композитное приложение получает код разметки UI от компонентов и отображает его.

Визуализация разметки требует интерпретации со стороны механизма рендеринга (такого, как браузер или приложение в архитектуре тонкого клиента) для того, чтобы преобразовать описания в графические элементы. Спецификации разметки, как правило, описывают статические свойства UI, в то время как языки скриптов обеспечивают динамические. Кроме того, можно описывать разметку с помощью ориентированных на документы языков (таких как XHTML и Wireless Markup Language [WML; www.openmobilealliance.org]), либо языков UI, которые моделируют сложные интерфейсы приложений (такие, как eXtensible Application Markup Language [XAML; msdn2.microsoft.com]; XML User Interface Language [XUL; www.mozilla.org]; User Interface Markup Language [UIML; www.uiml.org]; eXtensible Interface Markup Language [XIML; www.ximl.org]).

Применительно к визуализации мы выделяем два различных пользовательских интерфейса.

Пользовательский интерфейс, отображаемый компонентами. В этом случае компонент отвечает за рендеринг и отображение UI, и, таким образом, композитное приложение представляет собой набор пользовательских интерфейсов своих компонентов. Так происходит в случае с классическими настольными приложениями, которые используют исполняемые компоненты присоединенных графических библиотек.

Пользовательский интерфейс на базе разметки. В этом случае компонент возвращает код UI и делегирует финальный рендеринг UI либо композитному приложению, либо среде, в которой это композитное приложение работает. Композитное приложение должно, таким образом, иметь возможность интерпретировать код UI своих компонентов и резервировать необходимое пространство на дисплее для рендеринга компонентов. В этом случае при взаимодействии пользователя с композитным приложением генерируются события UI, которые компонент может обрабатывать напрямую с помощью соответствующего скрипта, встроенного в разметку компонента, либо композитное приложение может перехватывать сгенерированные события UI и передавать их компоненту для интерпретации.

Технологии композиции UI

В таблице сравниваются различные технологии UI, которые мы рассматриваем в контексте композиции UI.

Компоненты UI настольных приложений

Впервые композиция UI рассматривалась применительно к настольным приложениям. Создание компонентных технологий в конечном итоге привело к появлению среды, в которой приложения, написанные с помощью гетерогенных языков, могут взаимодействовать друг с другом. Типичный тому пример — ActiveX, в котором используется технология Microsoft COM для интеграции полного UI приложения в хостовые приложения. Другими примерами могут служить OpenDoc (developer.apple.com) и Bonobo (developer.gnome.org), которые для поддержки интероперабельности во многом полагаются на базовую операционную систему или компонентное программное обеспечение промежуточного уровня. С другой стороны, Composite UI Application Block (CAB; msdn2.microsoft.com) — это оболочка для композиции UI в Microsoft .Net с помощью контейнерного сервиса, который позволяет разработчикам создавать приложения из загружаемых или подключаемых модулей. Компоненты CAB могут использоваться с любым языком .Net для создания композитных контейнеров и выполнения коммуникаций между компонентами и контейнерами. Затем CAB предоставляет брокер событий для слабосвязанных межкомпонентных коммуникаций «многие ко многим» на основе модели событий времени исполнения, опирающейся на механизм публикации и подписки.

Проект Rich Client Platform (RCP; www.eclipse.org) в рамках Eclipse предоставляет аналогичную платформу, но включает в себя оболочку приложений с такими механизмами UI, как меню и инструментальные панели. Он также предлагает API на базе модулей, которые позволяют разработчикам создавать приложения на основе этой оболочки. Кроме того, Eclipse позволяет разработчикам настраивать и расширять компоненты UI (или подключаемые модули) через так называемые «точки расширения», сочетание Java-интерфейсов и разметок XML, которые определяют интерфейсы компонентов и поддерживают их слабое связывание.

Компоненты UI для настольных приложений, как правило, используют для интеграции компонентов языки программирования общего назначения (например, C# для CAB и Java для RCP), поскольку интерфейсы компонентов — это зависящие от языка API. Компоненты выполняют рендеринг своих UI, и они могут поддерживать гибкие стили связи, в том числе централизованно управляемые коммуникации через посредника или непосредственно между компонентами. Кроме того, поддерживается связывание как во время проектирования, так и во время исполнения, причем в последнем случае используются механизмы установки соответствия, специфические для данного языка.

Многие из технологий, применяемых для реализации компонентов UI для настольных приложений, зависят от операционной системы. Несмотря на то, что CAB и RCP напрямую от операционной системы не зависят, они используют свои соответствующие среды исполнения. Из-за отсутствия не зависящих от технологии декларативных интерфейсов добиться интероперабельности между компонентами, реализованными с помощью различных технологий, крайне сложно.

Подключаемые компоненты в браузере

При использовании интерфейсов на базе разметки можно реализовать разнообразные возможности UI с помощью встроенных компонентов UI, таких как апплеты Java, элементы управления ActiveX и Macromedia Flash.

Внешний интерфейс таких компонентов очень прост и обычно требует только корректных конфигурационных параметров при добавлении компонентов в код разметки (который представляет язык композиции). Подключаемые компоненты обеспечивают свой собственный рендеринг с небольшими последующими взаимодействиями между компонентами и содержащей их Web-страницей либо между самими компонентами. Web-дизайнер определяет связывание компонентов при создании страницы, а во время исполнения браузер загружает и создает экземпляры компонентов.

Встроенные компоненты UI легко использовать, но отсутствие в них платформы для поддержки регулярных взаимодействий является серьезным ограничением. Они могут взаимодействовать с помощью специализированных макросов JavaScript, но этот подход нельзя назвать универсальным. Однако данное ограничение во многом является следствием механизма поддержки «песочниц», используемого браузером для работы подключаемых модулей, чем самой по себе компонентной модели.

Web-коллажи

Коллажи (mashup) в Web — это Web-ресурсы, которые упаковывают и повторно используют сторонний Web-контент. Первые коллажи не могли использовать API, поскольку поставщики оригинального контента даже не знали о том, что их Web-сайты используются в других приложениях. Например, в Google Maps первые коллажи появились еще до официального выпуска Google Maps API. Создание этих API стало ответом Google на все большее число случаев нелегитимной интеграции своих карт, когда разработчики соответствующих приложений загружали весь код AJAX для карт и получали необходимую функциональность.

Общедоступные API для коллажей по-прежнему крайне редки, но их число растет — большинство из них формируются из скрытых интерфейсов. Разработчик, таким образом, выполняет интеграцию по мере необходимости за счет использования того языка программирования, который предоставляет источник контента либо на стороне клиента, либо на стороне сервера. Как правило, поставщики контента предоставляют контент в виде кода разметки, а разработчики коллажей интегрируют его с помощью механизма центрального координатора. Поскольку контент базируется на разметке, рендеринг компонентов обычно выполняет композитное приложение (работающее в браузере). Отсутствие инфраструктуры усложняет коммуникации между компонентами и позволяет связывать компоненты только статически.

Поскольку интерфейсы компонентов могут быть нестабильными, большая часть усилий при разработке коллажей уходит на тестирование вручную. Из-за отсутствия поддержки на уровне платформы изоляция кода не гарантируется, поэтому могут возникать конфликты между компонентами UI. Создание Web-коллажей — трудоемкая и требующая много времени задача.

Web-порталы и портлеты

Разработка Web-порталов четко разделяется на компоненты UI (портлеты) и композитные приложения (порталы) и, по-видимому, сейчас является самым передовым подходом к композиции UI (термин «портлеты» появился от Java Portlet, но впоследствии о портлетах стали говорить и применительно к ASP.Net Web Parts). Портлеты — это полнофункциональные подключаемые компоненты Web-приложений. Они генерируют фрагменты разметки документов, которые подчиняются определенным правилам, тем самым поддерживают агрегацию контента в портальных серверах для того, чтобы в конечном итоге формировать композитные документы.

Аналогично Java-сервлетам портлеты реализуют конкретный Java-интерфейс для стандартного API портлетов, который, как предполагалось, должен помочь разработчикам создавать портлеты, способные подключаться к любому удовлетворяющему стандартам портальному серверу. Например, JSR-168 определяет среду времени исполнения для портлетов и Java API. Что касается Java-портлетов, то портальные приложения базируются на языке программирования Java, в то время как в случае с Web Parts разработчик Web создает приложения в .Net. Портальное приложение объединяет разметки своих портлетов и управляет коммуникациями через механизм центрального координатора. Кроме того, портлеты поддерживают как статическое, так и динамическое связывание. Во время исполнения портальное приложение может предоставлять доступ к портлетам и реестру, где пользователи могут их выбирать и позиционировать.

JSR-168 не предоставляет механизм коммуникаций между портлетами, но сейчас в этой области ведутся активные исследования. Web Parts поддерживают коммуникации между компонентами с помощью разделяемых структур данных, но в силу этого Web Parts тесно связаны друг с другом, — возможно, более подходящим здесь был бы механизм поддержки событий на основе технологии публикации и подписки.

Несмотря на то что портлеты и Web Parts имеют сходные цели и архитектуры, они не поддерживают интероперабельность друг с другом. Web Services for Remote Portlets (WSRP; www.oasis-open.org) решает эту проблему на уровне протокола за счет предоставления удаленных портлетов в виде Web-сервисов, а коммуникации между портальным сервером (потребитель WSRP) и портлетами (производитель WSRP) осуществляются через SOAP. Это означает, что разработчики могут создавать портал и портлеты с помощью различных языков и оболочек времени исполнения. WSRP 1.0 не поддерживает коммуникации между портлетами, но в WSRP 2.0 будет предложен механизм распространения событий.

***

Интеграция UI начнет широко применяться только после проведения эффективной стандартизации, аналогичной стандартизации сервисных интерфейсов.

При разработке UI возникает множество трудностей, в том числе связанных с вопросами программной инженерии и человеко-машинного интерфейса. Возможным решением может стать интеграция повторно используемых компонентов, но она напрямую сказывается на сложности и разнообразии пользовательских интерфейсов, которые мы можем создать при заданных затратах. Исследования в этой интересной и сложной области только начинаются [6].

Литература

  1. B.A. Myers, M.B. Rosson, Survey on User Interface Programming. Proc. SIGCHI Conf. Human Factors in Computing Systems, ACM Press, 1992.

  2. M. Lenzerini, Data Integration: A Theoretical Perspective. Proc. 21st ACM SIGMOD-SIGACT-SIGART Symp. Principles of Database Systems, ACM Press, 2002.

  3. A. Halevy et al., Enterprise Information Integration: Successes, Challenges and Controversies. Proc. 2005 ACM SIGMOD Intl Conf. Management of Data, ACM Press, 2005.

  4. G. Alonso et al., Web Services: Concepts, Architectures, and Applications. Springer, 2004.

  5. P.T. Eugster et al., The Many Faces of Publish/Subscribe. ACM Computing Surveys, vol. 35, no. 2, 2003.

  6. J. Yu et al., A Framework for Rapid Integration of Presentation Components. To be published in Proc. 16th Int’l World Wide Web Conf., ACM Press, 2007.

Флориан Дениэль (daniel@elet.polimi.it) и Мариселла Матера (matera@elet.polimi.it) — сотрудники Политехнического университета Милана (Италия). Джин Ю (jyu@cse.unsw.edu.au) и Реджис Сен-Поль (regiss@cse.unsw.edu.au) — сотрудники Университета Южного Уэльса (Австралия). Булем Бенаталлах (boualem@cse.unsw.edu.au) — доцент Университета Южного Уэльса (Австралия). Фабио Касати (casati@dit.unitn.it) — профессор Университета Тренто (Италия).


Florian Daniel, Maristella Matera, Jin Yu, Boualem Benatallah, Regis Saint-Paul, Fabio Casati. Understanding UI Integration. A Survey of Problems, Technologies, and Opportunities. IEEE Internet Computing, May/June 2007. IEEE Computer Society, 2007. All rights reserved. Reprinted with permission.

Подключение датчика Xiaomi LYWSD03MMC с стоковой прошивкой к Home Assistant.

Градусник купить можно тут: http://ali.pub/58qrm4

В прошлой статье я описал, как прошить данный градусник LYWSD03MMC, как изменить его некоторые отображаемые параметры и как его добавить в Home Assistant с альтернативной прошивкой.

В этой статье добавим данный датчик на стоковой прошивке и разберем какие плюсы она имеет и какие минусы.

Итак ну приступим сразу к делу. Так как данный датчик у нас отправляет шифрованные послания на стоковой прошивке, нам необходим ключ для дешифрации данных. Чтоб получить данный ключ, нам необходимо:

  1. Зайти на сайт: https://atc1441.github.io/TelinkFlasher.html
  2. На данном сайте нажать кнопку “Connect” и найти в списке наше устройство, оно будет называться LYWSD03MMC.
  3. После подключения, необходимо нажать кнопку “Do Activation”. И появится следующее:

Вот нас какраз интересует Mi Bind Key. Копируем его.

Теперь переходим в Home Assistant.

Заходим в HACS. (Если не знаете что такое HACS и как его установить, то в этой статье я попытался описать данный процесс. Статья: http://psenyukov.ru/%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0-hacs-%d0%b2-home-assistant/)

В HACS заходим в Integrations, далее нажимаем на “+” и в открывшемся окне ищем “Xiaomi passive BLE monitor sensor platform” И устанавливаем его. После установки в меню HACS->Integrations появится данная интеграция:

Теперь необходимо перезагрузить сервер. Настройки->Сервер->Перезагрузить.

После перезагрузки заходим в Configuration.yaml и Пишем следующее:

Это первое значение: блютуз мак адрес нашего датчика. Второе значение это какраз ключ шифрования который мы получили с сайта и записали ранее.

Так как после добавления устройства, когда оно появится в системе Home Assistant у нее будет имя по mac адресу. Это не очень удобно. Поэтому блок ниже и служит, для того чтоб удобно описать наши датчики. В данном случае датчику присвоено имя “Балкон”

Все после прописи датчика в configuration.yaml и перезапуска системы. Примерно через 10 минут наш датчик должен появиться в системе и называться как mi temperature Балкон и mi humidity Балкон. Все датчики добавленные через интеграцию “Xiaomi passive BLE monitor sensor platform” Будут начинаться на “mi“.

Какие же всетаки плюсы и минусы данного метода добавления устройства.

Плюс безусловно это то, что данные датчики смогут по прежнему работать в системе умного дома Mi Home параллельно с системой умного дома Home Assistant.

А минус это пожалуй то, что данные мы будем получать примерно один раз в 10 минут и если нам необходимо отслеживать температуру с меньшим интервалом во времени чем 10 минут, то такой способ нам не подойдет. Ну или я просто не знаю как сделать так чтоб на стоковой прошивке датчик отправлял данные чаще чем приблизительно оди н раз в 10 минут.

У меня таких 3 датчика. И сейчас 2 из них на стоковой прошивке, а один на альтернативной с интервалом показаний раз в 5 минут. Вот теперь я за ними понаблюдаю и выясню сильно ли частота изменения показаний влияет на разряд батарейки.

Данный способ интеграции в Home Assistant и разбор самого датчика до винтиков я постарался показать в данном видео:

Источник

Датчик открытия Xiaomi Mijia с сенсором света и Bluetooth, интеграция в Home Assistant

В последнее время все больше устройств умного дома экосистемы Xiaomi — стало оснащаться интерфейсом Bluetooth 5.0 — BLE. В этом конечно имеется некий смысл — например в отличии от Zigbee устройств которые привязаны только к одному zigbee шлюзу, BLE датчики обнаруживаются всеми bluetooth шлюзами системы. А их сейчас куда только не встраивают — в светильники, будильники, розетки, мониторы качества воздуха, увлажнители и очистители. Кроме этого уровень энергопотребления BLE датчиков, уже сопоставим с Zigbee.

А героем этого обзора будет вторая версия датчика открытия Xiaomi с Bluetooth интерфейсом.

Содержание

Купить на Aliexpress — цена на момент публикации $ 8.95

Параметры

  • Модель — MCCGQ02HL
  • Тип датчика — геркон и магнит
  • Интерфейс — BLE 5.1
  • Питание — Элемент CR2032
  • Диапазон рабочих температур -10 + 50С
  • Размер — 34 х 32,7 х 14,5 мм

Поставка

Поставляется датчик в экосистемной белой коробочке с своим изображением на фронтальной части. Но в отличии от прошлых моделей в дизайне нового датчика появились цвета.

Датчик надежно закреплен в центре коробки в картонном держателе, что защищает его от превратностей дальней пересылки.

Конструкция

Датчик состоит из двух частей — большой, в которой находится геркон, сенсор света, электроника и элемент питания и маленькой — это магнит, который при приближении замыкает геркон. Есть еще запасной комплект двустороннего скотча.

На фронтальной части находится маленькое окошко — через него видно индикатор светодиода, и по все видимости его же использует сенсор света. Сбоку находится кнопка синхронизации.

На задней части датчика, обеих его частей, уже наклеен двусторонний скотч, это кроме того, что дополнительно идет в комплекте. Он нужен для установки датчика на дверь или окно.

Задняя крышка датчика снимается — под ней находится элемент питания. При пересылке, батарейка — тут используется CR2032, защищена от разряда специальной вкладкой, которую следует достать перед использованием.

Сравнение

В качестве сравнения — коробка героя обзора и первой версии датчика открытия Xiaomi с интерфейсом Zigbee. Размер практически идентичен, а за счет применения цветов — пусть даже только в логотипах, новинка выглядит наряднее.

Размер самих датчиков — тоже сопоставим. Основной модуль новинки шире, но чуть короче, а магнит наоборот — уже и длиннее.

Mihome

Так как датчик Bluetooth — первое подключение идет непосредственно к телефону, поэтому датчик нужно располагать рядом. После того как будет удален предохранитель батареи, датчик включится и обнаружится в списке доступных устройств. Выбираем его и подтверждаем соединение нажав на 3 секунды на боковую кнопку.

Далее идут стандартные шаги — выбор локации, установка названия для устройства и возможность поделится с другими пользователями. Данные о датчике будут переданы в облако, после чего все BLE шлюзы системы смогут получать от него данные.

Рассмотрим главное окно плагина датчика. Сверху, сразу под его названием указывается тип подключение — либо прямое с телефона, либо через Bluetooth шлюз. Благодаря шлюзам датчик доступен из любой точки мира и может участвовать в автоматизациях.

В центральной части — статусы сенсоров. Сверху — сенсор света, он может иметь только два состояния — ярко и тускло, никаких люменов. И самым крупным шрифтом — статус датчика открытия — Включено, значит магнит не воздействует на геркон, Выключено — магнит рядом и Не закрыто — это состояние включено в течении заданного в параметре таймаут времени, о нем чуть дальше.

В окошке датчика в общем режиме просмотра всех устройств, отображается только состояние геркона, датчик света не показывается.

Меню настроек. Первый чекбокс управляет датчиком света — его при желании можно отключить. Следующая опция — таймаут, от 10 секунд до 5 минут. Это и есть тот промежуток времени, по истечении которого статус включенного, то есть открытого датчика изменится на статус Не закрыто.

Еще тут есть возможность обновить прошивку устройства, но мне приехало уже с актуальной версией. А в меню информации — виден статус батареи, уровень сигнала к датчику, тип батарейки и МАС адрес.

В автоматизациях датчик может служить только триггером, что естественно. Всего есть 5 вариантов статусов, на момент выхода обзора они все были на китайском, даже если переключить mihome на английский язык. Два первых статуса — относятся к сенсору света, а три оставшихся к сенсору открытия. Таким образом статусы открыто и не закрыто — могут быть триггерами для разных действий.

В логе датчика сохраняется история изменений статуса и датчика открытия и датчика света. А в общем журнале приложения хранятся статусы когда дверь открыта на время большее чем указано в параметре таймаут.

Как я и сказал, Bluetooth шлюзы являются составляющими многих устройств, при необходимости можно даже купить его отдельно, но это не очень рационально, есть например умные розетки с такой функцией. Для меня наиболее важным было то, чтобы датчик был виден шлюзом xiaomi третьей версии — которые имеет на борту и wi-fi и bluetooth mesh и zigbee 3.

Home Asisstant

А все потому, что благодаря замечательной интеграции Xiaomi Gateway 3 от AlexxIT — все подключенные к нему устройства, и bluetooth и zigbee — автоматически прописываются в Home Assiastant. Подробнее —

Устройство состоит из трех cущностей — сенсор уровня заряда батареи, сенсор открытия и света. Тут нет таймаута, но его очень легко реализовать при помощи автоматизации, причем гибче чем в штатном приложении михоум.

Причем именно сенсор — только уровень заряда, то есть он может принимать любые значения, в данном случае от 0 до 100. А вот открытие и свет — это бинарные сенсоры, у них только по два состояния — открыто и закрыто, и светло и темно.

Что касается применения — удобство этого устройства как раз и состоит в тандеме из двух датчиков, что позволяет разделить например такие условия — дверь закрыта и в помещении горит свет, и дверь закрыта и в помещении света нет. Что дает возможности делать автоматизации более гибкими.

Видео версия обзора

Источник

Zigbee-датчик открытия Sonoff SNZB-04: возможности, интеграция в Home Assistant

Сегодня мы с вами рассмотрим один из беспроводных датчиков для умного дома, выпускаемых под брендом Sonoff. Эта продукция хорошо известна всем энтузиастам — не в последнюю очередь благодаря своей бюджетности. И герой сегодняшнего обзора — датчик открытия Sonoff SNZB-04 — не является исключением из этого правила.

Содержание

Официальный магазин на Aliexpress — цена на момент публикации $8.49

Параметры

  • Модель — Sonoff SNZB-04
  • Интерфейс — Zigbee 3
  • Питание — батарейка CR2032
  • Диапазон температур — -10 + 40С
  • Вес — сенсор 18 гр. магнит 5,3 гр
  • Размер — сенсор 47х27х13,5 мм, магнит 32х15,6х13

Поставка

Фирменный цвет коробок продуктов Sonoff — изменяется с течением времени. С синего на морской зеленый, который сейчас уже стал оранжевым. Коробка минимально возможного размера, с указанием модели и основных параметров.

В комплекте поставки — сенсор с магнитом, комплект наклеек из двухстороннего скотча и небольшой буклет с инструкцией. Также в коробку вложена отметка о прохождении контроля качества.

Все записи в инструкции сделаны на 7 языках включая русский. Тут кстати упоминается версия Zigbee — третья, хотя в характеристиках этого прямо не указано.

Конструкция

Конструктивно, сенсоры такого вида состоят из двух частей — большей, собственно самого сенсора, со всей электронной частью и элементом питания и меньшей — магнитом. Принцип работы состоит в реакции на магнит.

Форма у разных производителей может быть разной, Sonoff выбрал прямоугольную — кирпичик. Небольшие повреждения внизу, которые видны на этом слайде, это уже результат моих тестов, из коробки — все целое.

Задняя сторона. Эти крышки съемные, скоро мы заглянем под них. При использовании предполагается что двусторонний скотч будет наклеен именно сюда.

Сравнительно с аналогичным датчиком из экосистемы xiaomi mijia. Продукт Xiaomi компактнее и аккуратнее, но он и дороже. Хотя по своей сути он ничего не отличается от героя обзора.

Разборка

Посмотрим что внутри устройства. В маленькой части все просто — тут находится небольшой цилиндрический магнит.

В большой части — находится сенсор, причем плата имеет закругленные края, аналогично упомянутому датчику от Xiaomi. Элемент питания от разряда в при пересылке защищает изоляционная пленка, которую следует достать перед использованием.

В этом датчике применен стандартный и известный многим — модуль CC2530 с внутренней антенной. Поэтому не удивлюсь если для него будут разработаны и сторонние прошивки. В качестве сигнального элемента тут использован геркон MEDER-B J 1/8 от Standex-Meder Electronics.

В целом к сборке вопросов нет, за исключением контактной пластины для батарейки. Она припаяна явно вручную, и, по крайней мере в моем варианте, не очень уверенно держит батарейку. Мне пришлось приколхозить кусок резинки сверху, чтобы пластина прижалась еще и крышкой корпуса.

Принцип действия

Итак — принцип действия устройства заключается в том, что магнит воздействует на контакты внутри геркона — которые могут быть замкнуты и разомкнуты. Вот максимальное расстояние, с которого начинает действовать магнитное поле.

Еще раз, но уже без корпуса — геркон находится в нормально разомкнутом состоянии. Это значит что когда магнита рядом нет — геркон разрывает электрическую цепь. Когда магнит рядом — геркон замыкается. Таким образом датчик относится к классу бинарных сенсоров — он имеет два состояния — закрыто — замкнуто, и открыто — разомкнуто.

Вместо магнита контакт можно замыкать и любым другим способом — даже просто отрезком провода. Это дает широкие возможности к кастомизации сенсора. Например подключать внешние датчики влаги, давления, механические выключатели и кнопки.

Подключение

Для перевода датчика в режим сопряжение — понадобится скрепка. Ее нет в комплекте, но можно использовать скрепку от смартфона — ту, что открывает лоток с сим картами, либо просто канцелярскую.

Как обычно — я стараюсь рассмотреть как можно больше вариантов подключения обозреваемого устройства. И тут не буду отходить от этого. В своих закромах я нашел даже родной Sonoff шлюз, и начну тестирование с него.

Кстати шлюз попал ко мне довольно давно, не менее года назад, еще в предрелизе — в совершенно белой коробочке без опознавательных знаков. Прошивка на нем тоже древняя, к сожалению все мои попытки обновить ее остались безуспешны, поэтому на свежих прошивках допускаю какие-то непринципиальные изменения.

Ewelink

Логическую часть начнем с родного приложения Ewelink. Заходим в плагин шлюза, нажимаем добавить устройство — что переводит шлюз на 60 секунд в режим подключения, в это время нажимаем скрепкой на кнопку сопряжения датчика, пока сквозь корпус не моргнет три раза красный светодиод. Вслед за этим шлюз обнаружит и добавит новое устройство.

Датчик появится в общем списке и перечне устройств шлюза. Плагина как такового у него нет — есть только журнал срабатываний. Справа вверху — меню настроек, в котором можно указать имя и локацию, включить пуш уведомления и удалить устройство.

Датчик может участвовать в автоматизациях — к разделе условий ЕСЛИ. И имеет два состояния — открыто, когда магнита рядом нет и закрыто — когда геркон действует магнит.

Соответственно эти состояния и служат условиями сценариев. Сами же сценарии могут работать как постоянно так и в строго указанное время и дни недели. Например, при использовании в офисе, можно отключить срабатывание в рабочее время, мониторя активность только ночью и на выходные.

Home Assistant

Способы интеграции в Home Assistant начну прямо с родного шлюза. Он поддерживается аддоном Sonoff LAN от AlexxIT. Аддон входит в стандартный перечень интеграций HACS. После подключения — датчик автоматически пробросится в систему как бинарный сенсор. Класс устройства по умолчанию указан как датчик двери, при необходимости его можно сменить через раздел кастомизации.

Zigbee2mqtt

Устройство поддерживается и в интеграции zigbee2mqtt. Сразу скажу что у меня все стики включая тестовый — работают на прошивках zstack 3. Включаем режим подключения и скрепкой активируем сопряжение на датчика.

Весь процесс занимает примерно секунд 30, после чего датчик проходит интервью и подключается к системе.

Определился совершенно корректно — от производителя и модели, до изображения. Так как датчик использует автономное питание — он является конечным устройством и не умеет передавать через себя сообщения от других датчиков.

В этой интеграции датчик отдает целых 5 параметров. Три из которых — бинарные и имеют состояния правда или ложь. Сюда входит contact — это состояние геркона, battery_low — он включится когда заряд батарейки станет низким и тампер — в теории он должен включаться когда датчик снимают с места, но по факту он выключен даже если датчик полностью разобрать и вынуть из корпуса.

Еще два — это фактический уровень заряда батарейки и качества сигнала.

В новой версии zigbee2mqtt, в разделе настроек, теперь можно указывать параметр retain. Он отвечает за сохранения топиков состояния датчиков в mqtt. Если параметр не установлен, при перезагрузке Home Assistant — состояние датчика будет неизвестно, так как топик сохранятся не будет.

А если установить — то каждое изменение будет сохранятся, тем самым после перезагрузки вы увидите последнее, пришедшее от датчика состояние, даже если оно было перед перезагрузкой. Лично я устанавливают его для всех своих устройств.

Обновления по воздуху через zigbee2mqtt — на дату выхода этого обзора — не поддерживается. Посмотрим как будет дальше.

В Home Assistant устройство пробрасывается через интеграцию MQTT — с пятью сущностями, про которые я только что рассказал. По умолчанию — датчик имеет класс дверь, что можно изменить через раздел кастомизации.

Пример отображения датчика на карте сети. Здесь он построил маршрут через роутер, роль которого выполняет розетка — переходник Blitzwolf SHP — 13

SLS Gateway

При использовании SLS шлюзов — тоже никаких проблем не возникает. На шлюзе запускаем режим подключения, а на датчике нажимаем скрепкой пока светодиод не моргнет три раза красным. При запросу — возможно придется еще дополнительно нажать на кнопку сопряжения для продолжения интервью.

Датчик определяется и добавляется совершенно корректно. Естественно тоже как конечное устройство.

В отличии от zigbee2mqtt — SLS шлюз выведет все сущности только по факту их первого изменения. С начала тут только уровень сигнала. Передвинув магнит — создаем и сущность контакт. Остальное появится само позже.

В Home Assistant сущности устройства также попадают через интеграцию mqtt. Количество сущностей увеличится по мере получения данных от них. По умолчанию датчик тоже определяется как сенсор двери.

Видеоверсия обзора

Вывод

В ходе тестирования, иногда мне казалось что датчик меняет состояние с небольшой задержкой. Возможно конечно я придираюсь, но ощущение такое сложилось. К плюсам этого устройства можно отнести его бюджетность, к минусам — конструкцию корпуса, не очень качественную пластину контакта, тугие задние крышки — открывать датчик все равно придется, а пластик легко повредить.

Думаю что наиболее вероятный кейс использования — как раз DIY по принципу замыкания контактов, возможно даже без корпуса. Его переделывать не так жалко как сенсор Xiaomi или Aqara.

Источник

Эта статья является логическим продолжением моей предыдущей статьи, в которой изложены базовые сведения о сущностях и их состояниях, а также основы шаблонизации, на базе разработки сенсора состояний заряда батарей датчиков.

Как известно, в Home Assistant все устройства «дробятся» на сущности (объекты), с которыми в дальнейшем и работает система. Их «object_id», как правило, одинаково начинается с упоминания родительского устройства.

Типовые сущности разных устройств

При недоступности родительского устройства, становятся недоступны и все дочерние объекты. А их колличество, порой, может переваливать за десяток, и при выводе их всех в интерфейс, присутствует некая избыточность информации. Мне подумалось, что было бы удобным отображать просто названия устройств.

Кроме того, некоторые устройства сезонные и это надо учесть. Для автоматизаций и сценариев у меня в системе созданы объекты input_boolean для каждого такого устройства, с соответствующими условиями (conditions) в автоматизациях. Увлажнитель убрал, «input_boolean.humidifier_connected» перевел в «false» — автоматизация не сработает. На таком же принципе датчик будет отслеживать недоступность устройств.

Ещё в процессе изучения вопроса выяснилось, что удобно создать постоянную группу с объектами, которые будут игнорироваться этим датчиком.

Техзадание:

  • вывести в интерфейс удобочитаемую информацию о недоступных устройствах (не сущностях);
  • исключить из списка отключенные мною устройства (я на лето убираю увлажнитель);
  • исключить объекты, которые вводят в заблуждение при формировании списка устройств;
  • при необходимости, полная информация о недоступных сущностях;
  • не использовать сторонние интеграции для интерфейса (используем Markdown).

Устройства  ( DEVICES )

В разделе «Templating» инструкции к HA есть раздел «DEVICES». За него и зацепимся.

В системе каждому устройству (и службе) присваивается идентификатор «device_id» (32-значное HEX-число). Его, кстати, можно увидеть  в конце адресной строки браузера, когда находишься на странице устройства. Дальше приведу несколько примеров работы с device_id на примере бесперебойника фирмы APC с соответствующей интеграцией:

  {

{{ device_id('sensor.ups_transfer_to_battery') }}

-> e46086d4e8bb0c2eb3ebcc0e67d68da5

  {

{{ device_entities('e46086d4e8bb0c2eb3ebcc0e67d68da5') }}

-> ['binary_sensor.ups_online_status', 'sensor.ups_input_voltage', 'sensor.ups_battery_timeout',

'sensor.ups_battery_shutdown', 'sensor.ups_time_left', 'sensor.ups_transfer_from_battery',

'sensor.ups_daemon_info', 'sensor.ups_status_data', 'sensor.ups_status', 'sensor.ups_time_on_battery',

'sensor.ups_name', 'sensor.ups_hostname', 'sensor.ups_model', 'sensor.ups_status_date', 'sensor.ups_load',

'sensor.ups_cable_type', 'sensor.ups_shutdown_time', 'sensor.ups_battery', 'sensor.ups_mode',

'sensor.ups_startup_time', 'sensor.ups_driver', 'sensor.ups_transfer_to_battery'] { {{ device_attr('e46086d4e8bb0c2eb3ebcc0e67d68da5', 'manufacturer') }} -> APC { {{ is_device_attr('sensor.ups_transfer_to_battery', 'manufacturer', 'APC') }} -> True { {{ device_attr('sensor.ups_transfer_to_battery', 'name') }} -> None { {{ device_attr('sensor.ups_transfer_to_battery', 'name_by_user') }} -> Back-UPS ES 525

Кроме того, у многих устройств можно узнать: hw_version — версия железа;
sw_version — версия программного обеспечения;
model — ну вы поняли;
и другие, иногда индивидуальные, аттрибуты.

Хочу уточнить, что названия устройств будут считываться из аттрибута «name_by_user», а если он пустует , то из аттрибута «name», то есть, если шаблон не найдет имени устройства, заданного пользователем, то будет использоваться имя системное. Поэтому стоит назвать свои устройства так, чтобы удобно было это потом воспринимать. Делается это как раз на странице устройства. В верхнем правом углу нажимаем на карандаш и переименовываем. Название устройства здесь же, но в левом углу.

При этом не надо соглашаться на переименовывание идентификаторов объектов, если только вы не хотите переписать все изменившиеся сущности в автоматизациях и пр. !

Жмём «Нет» !

Прежде чем начать описывать датчик, уточню:

  1.  У меня для каждого сезонного устройства есть свой input_bulean , которым я блокирую срабатывание автоматизаций, если устройство отключено. Этот логический переключатель будет учитываться в сенсоре.
  2. Я заранее создал ещё один  input_bulean «input_boolean.visible_unav_ent», который будет отвечать за отображение списка недоступных сущностей в карточке Markdown.
  3. В ходе экспериментов выяснилось, что датчик бесперебойника «sensor.ups_transfer_to_battery» (время последнего перехода на работу от батареи), после перезагрузки HA становится недоступным, что не влияет на работу самого бесперебойника и HA, поэтому для подобных проблемных сенсоров я создал группу игнорируемых недоступных объектов «group.ignored_unavailable_entities», которая просматривается во время формирования списка недоступных устройств.

Датчик

Решено было сделать датчик на основе интеграции «Template», в состоянии (state) которого будет количество недоступных сущностей, и, дополнительно, в нем будет словарь с тремя аттрибутами: кол-во недоступных устройств, список недоступных устройств и список недоступных сущностей.

Сенсор (колличество недоступных сущностей):

    {
    {

{% set nm = namespace(list_unav_ent = [] ) %}   

    {
    {

{% set domains = ['light', 'switch', 'sensor', 'binary_sensor'] %}

    {
    {

{% for domain in domains -%}     
  
    {
    {
    {
    {

{% for state1 in states[domain] if ((state1.state | lower == "unavailable") 
and not (( is_state('input_boolean.humidifier_connected', 'off')            
and  (state1.object_id.startswith("humidifier"))))) %}                     
         
    {
    {
                                                                
{% set nm.list_unav_ent = nm.list_unav_ent + [state1.entity_id] %}

    {
      
{% endfor %} 

    {
    
{% endfor %} 

    {
  
{{ nm.list_unav_ent | list | length }}

Аттрибуты:

Аттрибут — список недоступных сущностей ( то же самое, но без подсчёта элементов списка, а сам список ): 

{% set nm = namespace(list_unav_ent = [] ) %}
{% set domains = ['light', 'switch', 'sensor', 'binary_sensor'] %}
  {% for domain in domains -%}
    {% for state1 in states[domain] if ((state1.state | lower == "unavailable")
    and not (( is_state('input_boolean.humidifier_connected', 'off') 
    and  (state1.object_id.startswith("humidifier"))))) %}
      {% set nm.list_unav_ent = nm.list_unav_ent + [state1.entity_id] %}
    {% endfor %} 
  {% endfor %} 
{{ nm.list_unav_ent }}

Аттрибут — список недоступных устройств:

    {# Как и в предыдущем случае, создаем глоб. переменные NAMESPACE #}
    {# но в этот раз одну для сущностий и одну для устройств #}

{% set nm = namespace(list_unav_ent = [] ) %}
{% set nm1 = namespace( list_unav_dev = []) %}

    {# Как и в коде выше, формируем список недоступных сущностей #}

{% set domains = ['light', 'switch', 'sensor', 'binary_sensor'] %}
  {% for domain in domains -%}
    {% for state1 in states[domain] if ((state1.state | lower == "unavailable")) %}
    
    {# В этот раз будем проверять наличие объекта в группе игнорируемых #}
    {# Переменной "ignored" присваивается состояние аттрибута "entity_id" группы #}
    {# Значение этого аттрибута - список внесенных в него игн. сущностей #}
    
      {% set ignored = state_attr('group.ignored_unavailable_entities','entity_id') %}
      
    {# Проверяем, находится ли наш очередной объект в этом списке #}
      
      {% if state1.entity_id not in ignored %}
      
    {# Если нет, добавляем его в список недоступных сущностей #}
      
        {% set nm.list_unav_ent = nm.list_unav_ent + [state1.entity_id] %}
      {% endif %}
    {% endfor %} 
  {% endfor %} 
  
    {# Список сущностей, с отсеиванием игнорируемых, составили #} 
    {# Теперь, на основе списка формируем список устройсв #}  
    {# Переменной unav_ent будет присваиваться каждый объект списка #}    
  
{% for unav_ent in nm.list_unav_ent  -%}
  
    {# Тест: Если аттрибут "name_by_user" родительского устройства = "ничего" #}
  
{% if (device_attr(unav_ent, "name_by_user") is none) %}
    
    {# Вписываем в переменную "nav_dev" имя из аттрибута "name" #}
    
{% set unav_dev = device_attr(unav_ent, "name") %}
      
    {# Иначе #}
      
{% else %}
    
    {# Вписываем в переменную "nav_dev" имя из аттрибута "name_by_user" #}
    
{% set unav_dev = device_attr(unav_ent, "name_by_user") %}
      
    {# Конец проверки аттрибутов и выбора имени устройству #}
      
{% endif %}
    
    {# Наполняем наш список недоступных устройств, добавив один объект #}
    
{% set nm1.list_unav_dev = nm1.list_unav_dev + [unav_dev] %}
    
    {# Переходим к следующему элементу списка "nm.list_unav_ent" #}
    
{% endfor %}
  
    {# формируем фильтр "Увлажнитель". #}
    {# Присваиваем переменной "ignore_1" пустоту #}
  
{% set ignore_1 = "" %}

    {# Если "input_boolean.humidifier_connected"  выключен (увлажнитель убран) #}

{% if is_state("input_boolean.humidifier_connected", "off") %}

    {# Переприсваиваем переменной "ignore_1" значение "Увлажнитель" #}

{% set ignore_1 = "Увлажнитель" %}
  
    {# Конец проверки #}
  
{% endif %}

    {# Вывод списка недоступных устройств. При этом используем фильтры: #}
    {# "| unique" отрежет все повторяющиеся названия, оставив одно #}
    {# "| reject("==", ignore_1)" удалит из списка слово "Увлажнитель", при условии, что он убран #}
    {# "| list"  собственно, список #}

{{ nm1.list_unav_dev
| unique
| reject("==", ignore_1)
| list
}}

Аттрибут — колличество недоступных устройств

    {# Кроме альтернативно расположенных проверок сущностей на наличие в группе #}
    {# и принадлежности к увлжнителю, код повторяет предыдущие #}

{% set nm = namespace(list_unav_ent = [] ) %}
{% set nm1 = namespace( list_unav_dev = []) %}
{% set domains = ['light', 'switch', 'sensor', 'binary_sensor'] %}
  {% for domain in domains -%}
    {% for state1 in states[domain] if ((state1.state | lower == "unavailable")
    and not (( is_state('input_boolean.humidifier_connected', 'off') 
    and  (state1.object_id.startswith("humidifier"))))) %}
      {% set ignored = state_attr('group.ignored_unavailable_entities','entity_id') %}
      {% if state1.entity_id not in ignored %}
        {% set nm.list_unav_ent = nm.list_unav_ent + [state1.entity_id] %}
      {% endif %}
    {% endfor %} 
  {% endfor %} 
  {% for unav_ent in nm.list_unav_ent  -%}
    {% if (device_attr(unav_ent, "name_by_user") is none) %}
      {% set unav_dev = device_attr(unav_ent, "name") %}
    {% else %}
      {% set unav_dev = device_attr(unav_ent, "name_by_user") %}
    {% endif %}
    {% set nm1.list_unav_dev = nm1.list_unav_dev + [unav_dev] %}
  {% endfor -%}
{{ nm1.list_unav_dev
| unique
| list
| length 
}} 

Полный код датчика

- trigger:
    - platform: homeassistant
      event: start
    - platform: time_pattern
      minutes: "/20"
    - platform: state
      entity_id: input_boolean.visible_unav_ent
      to:
    - platform: state
      entity_id: input_boolean.humidifier_connected
      to:
  sensor:
    - name: unavailable entities
      unit_of_measurement: entities
      state: >
            {% set nm = namespace(list_unav_ent = [] ) %}
            {% set domains = ['light', 'switch', 'sensor', 'binary_sensor'] %}
              {% for domain in domains -%}
                {% for state1 in states[domain] if ((state1.state | lower == "unavailable")
                and not (( is_state('input_boolean.humidifier_connected', 'off') 
                and  (state1.object_id.startswith("humidifier"))))) %}
                  {% set nm.list_unav_ent = nm.list_unav_ent + [state1.entity_id] %}
                {% endfor %} 
              {% endfor %} 
            {{ nm.list_unav_ent | list | length }}
            
      attributes:
      
        list_of_unavailable_entities: >
            {% set nm = namespace(list_unav_ent = [] ) %}
            {% set domains = ['light', 'switch', 'sensor', 'binary_sensor'] %}
              {% for domain in domains -%}
                {% for state1 in states[domain] if ((state1.state | lower == "unavailable")
                and not (( is_state('input_boolean.humidifier_connected', 'off') 
                and  (state1.object_id.startswith("humidifier"))))) %}
                  {% set nm.list_unav_ent = nm.list_unav_ent + [state1.entity_id] %}
                {% endfor %} 
              {% endfor %} 
            {{ nm.list_unav_ent }}
            
        list_of_unavailable_devices: >
            {% set nm = namespace(list_unav_ent = [] ) %}
            {% set nm1 = namespace( list_unav_dev = []) %}
            {% set domains = ['light', 'switch', 'sensor', 'binary_sensor'] %}
              {% for domain in domains -%}
                {% for state1 in states[domain] if ((state1.state | lower == "unavailable")) %}
                  {% set ignored = state_attr('group.ignored_unavailable_entities','entity_id') %}
                  {% if state1.entity_id not in ignored %}
                    {% set nm.list_unav_ent = nm.list_unav_ent + [state1.entity_id] %}
                  {% endif %}
                {% endfor %} 
              {% endfor %} 
              {% for unav_ent in nm.list_unav_ent  -%}
                {% if (device_attr(unav_ent, "name_by_user") is none) %}
                  {% set unav_dev = device_attr(unav_ent, "name") %}
                {% else %}
                  {% set unav_dev = device_attr(unav_ent, "name_by_user") %}
                {% endif %}
                {% set nm1.list_unav_dev = nm1.list_unav_dev + [unav_dev] %}
              {% endfor %}
            {% set ignore_1 = "" %}
            {% if is_state("input_boolean.humidifier_connected", "off") %}
              {% set ignore_1 = "Увлажнитель" %}
            {% endif %}
            {{ nm1.list_unav_dev
            | unique
            | reject("==", ignore_1)
            | list
            }}
            
        count_unavailable_devices: >
            {% set nm = namespace(list_unav_ent = [] ) %}
            {% set nm1 = namespace( list_unav_dev = []) %}
            {% set domains = ['light', 'switch', 'sensor', 'binary_sensor'] %}
              {% for domain in domains -%}
                {% for state1 in states[domain] if ((state1.state | lower == "unavailable")
                and not (( is_state('input_boolean.humidifier_connected', 'off') 
                and  (state1.object_id.startswith("humidifier"))))) %}
                  {% set ignored = state_attr('group.ignored_unavailable_entities','entity_id') %}
                  {% if state1.entity_id not in ignored %}
                    {% set nm.list_unav_ent = nm.list_unav_ent + [state1.entity_id] %}
                  {% endif %}
                {% endfor %} 
              {% endfor %} 
              {% for unav_ent in nm.list_unav_ent  -%}
                {% if (device_attr(unav_ent, "name_by_user") is none) %}
                  {% set unav_dev = device_attr(unav_ent, "name") %}
                {% else %}
                  {% set unav_dev = device_attr(unav_ent, "name_by_user") %}
                {% endif %}
                {% set nm1.list_unav_dev = nm1.list_unav_dev + [unav_dev] %}
              {% endfor -%}
            {{ nm1.list_unav_dev
            | unique
            | list
            | length 
            }}    

Вывод датчика в интерфейс. Markdown

Здесь расположены:

  1. Переключатель «input_boolean.visible_unav_ent», который отвечает за видимость списка недоступных сущностей.
  2. Карта Mrcdown с этим самым списком, видимость которой зависит от переключателя.
    Каждая сущность списка проверяется на принадлежность к группе со списком игнорируемых, и, положительно проходящие тест, для удобства, помечаются «игнор.»
  3. Неубираемая карта Markdown, которая, в случае отсутствия недоступных устройств, выводит надпись: «Список пуст».
cards:

   - type: entities
     entities:
       - entity: input_boolean.visible_unav_ent
  
   - type: conditional
     conditions:
       - entity: input_boolean.visible_unav_ent
         state: "on"
     card:
       type: markdown
       content: >-
         <font color=Black size=2><center>  <h3>Недоступные объекты
         </center>
         
         {% for entity in state_attr('sensor.unavailable_entities','list_of_unavailable_entities') -%}
         {% set ignored = state_attr('group.ignored_unavailable_entities','entity_id') %}
         {% if entity in ignored %}
         * {{ entity ~ '&emsp; (игнор.) n'}}
         {% else %}
         * {{ entity ~ 'n'}}
         {% endif -%} 
         {% endfor %}
         
         </font>
       
   - type: markdown
     content: >-
       <font color=Black size=2><center>  <h3>Недоступные устройства
       </center><center>
       
       {% if state_attr('sensor.unavailable_entities','count_unavailable_devices') > 0 %}
       
       {% for device in state_attr('sensor.unavailable_entities','list_of_unavailable_devices') %}
       {{ device ~ 'n'}}
       {% endfor %}
       
       {% else %}
       Список пуст
       
       {% endif %}
       
       </center></font>

Как это выглядит?

Список скрыт, увлажнитель и его input_boolean выключены

Список раскрыт, увлажнитель убран, но его input_boolean не отключен

Заключение

У меня получилась очередная огромная простыня. Хотел укоротить, прошелся по ней и немного добавил. Разумеется, здесь представлен, наверняка, не лучший вариант, но я ещё учусь. Если подобного рода идея кого-нибудь заинтересует, буду рад.

Понравилась статья? Поделить с друзьями:

Другие крутые статьи на нашем сайте:

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии