Files
wiki/tasks/ha-availability-dashboard/TZ.md
2026-04-15 00:40:01 +03:00

9.7 KiB
Raw Blame History

ТЗ: Дашборд доступности устройств в Home Assistant

Цель

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

Метрика

Доступность = время в статусе «доступен» / общее время периода × 100%

  • «Доступен» — любой статус, кроме unavailable и unknown
  • «Недоступен» — статус unavailable или unknown
  • Результат: процент (0%100%), один знак после точки

Периоды

Период Формула Обновление
День за последние 24 часа каждые 5 мин
Неделя за последние 7 дней каждые 30 мин
Месяц за последние 30 дней каждые 2 часа

Какие устройства отслеживать

Все entity из доменов физических устройств:

  • binary_sensor, sensor, switch, light
  • climate, cover, lock, media_player
  • device_tracker, vacuum, fan, humidifier
  • water_heater, siren, button

Исключения (не показывать на дашборде):

  • Вспомогательные entity Zigbee2MQTT (sensor.*_update_state, update.*, button.zigbee2mqtt_*)
  • Entity с суффиксами _battery_low, _battery, _linkquality, _update, _identify
  • Виртуальные/template сенсоры (без device_id)
  • Автоматически создаваемые Select/Number для Zigbee-устройств (настройки radar_sensitivity и т.п.)

Архитектура решения

1. Вычисление доступности — через长期的 sensor

Для каждого отслеживаемого устройства создать template sensor (или один Python-скрипт через REST), который:

  1. Запрашивает историю из /api/history/period/<start>?filter_entity_id=<id>&minimal_response&no_attributes
  2. Считает суммарное время в unavailable/unknown
  3. Вычисляет процент доступности
  4. Записывает результат как sensor state

2. Варианты реализации

Вариант A: Utility Meter + Template Sensor (нативный HA)

  • На каждое устройство — binary_sensor доступности (доступен/нет)
  • utility_meter считает время в каждом статусе
  • Template sensor вычисляет процент
  • Минус: нужен custom:utility_meter или history_stats — много entity на каждое устройство, сложная конфигурация при 180+ устройствах

Вариант B: Python-скрипт + AppDaemon (рекомендуемый)

  • Один Python-скрипт, работающий по расписанию
  • Читает историю через HA API для всех устройств сразу
  • Вычисляет доступность за все 3 периода
  • Создаёт/обновляет sensor.availability_<entity_id>_<period> через states API
  • Плюсы: один скрипт, легко масштабировать, минимальная нагрузка на HA
  • ⚠️ Требует: AppDaemon или HA Python script / custom component

Вариант C: Custom HA Integration (HACS)

  • Кастомная интеграция, регистрирует sensor-ы через async_setup_platform
  • Берёт данные из recorder напрямую (SQL)
  • Плюсы: максимально нативно, работает через recorder без API
  • ⚠️ Минусы: сложнее разработка, нужен доступ к БД recorder

Вариант D: SQL Sensor + Jinja (самый простой)

  • sql integration — прямые запросы к MariaDB/SQLite recorder
  • Один sensor на устройство×период с SQL-запросом
  • Плюсы: без внешних зависимостей, работает из коробки
  • Минусы: 180 устройств × 3 периода = 540 SQL-запросов по расписанию — нагрузка на БД

Рекомендация: Вариант B (AppDaemon / Python-скрипт)

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

Дашборд

Карточка: таблица доступности

┌──────────────────────────┬────────┬────────┬────────┐
│ Устройство               │ День   │ Неделя │ Месяц  │
├──────────────────────────┼────────┼────────┼────────┤
│ 💡 Бра в спальне        │ 99.8%  │ 98.5%  │ 95.2%  │
│ 🔌 Лесной колодец насос │ 100.0% │ 99.1%  │ 97.8%  │
│ 🌡️ Улица температура   │ 85.3%  │ 92.1%  │ 88.7%  │
│ ...                      │ ...    │ ...    │ ...    │
└──────────────────────────┴────────┴────────┴────────┘

Функциональность:

  • Сортировка по любому столбцу (по умолчанию — по месячной доступности, убывание)
  • Цветовая индикация:
    • 🟢 99-100% — зелёный
    • 🟡 95-99% — жёлтый
    • 🟠 90-95% — оранжевый
    • 🔴 <90% — красный
  • Фильтр по домену (switch, sensor, light...)
  • Обновление: при загрузке дашборда + по расписанию

Карточка: сводка

┌──────────────────────────────────┐
│ 📊 Доступность устройств         │
│                                  │
│ Средняя за день:    97.3%        │
│ Средняя за неделю:  96.1%        │
│ Средняя за месяц:   94.8%        │
│                                  │
│ Устройств <95% (месяц): 5        │
│ Устройств <90% (месяц): 2        │
└──────────────────────────────────┘

Технические детали

Источник данных

  • HA History API: /api/history/period/<start>?filter_entity_id=<ids>&minimal_response&no_attributes
  • Возвращает массив пар (state, last_changed) — достаточно для расчёта времени

Расчёт (алгоритм)

def calc_availability(history_entries, period_start, period_end):
    unavailable_seconds = 0
    for entry in history_entries:
        state = entry['state']
        changed = parse_datetime(entry['last_changed'])
        
        if state in ('unavailable', 'unknown'):
            # Сколько времени устройство было в этом статусе
            # до следующего изменения или до period_end
            next_change = get_next_change(entry) or period_end
            unavailable_seconds += (next_change - changed).total_seconds()
    
    total_seconds = (period_end - period_start).total_seconds()
    availability = (1 - unavailable_seconds / total_seconds) * 100
    return round(availability, 1)

Хранение результатов

  • Каждый результат — sensor.avail_<sanitized_id>_<period>
  • Атрибуты: entity_id, period, availability_%, last_updated
  • Группировка: group.availability_day, group.availability_week, group.availability_month

Нагрузка

  • ~180 устройств
  • History API batch-запрос (можно передать несколько entity_id через запятую)
  • За день: ~180 × 3 = 540 точек данных (при batch — 3 API-вызова)
  • За неделю/месяц: данные уже рассчитаны, обновляются реже

Ограничения

  • purge_keep_days в recorder — по умолчанию 10 дней. Для месячной статистики нужно увеличить до 35 дней
  • Если устройство добавлено недавно — показывать доступность с момента добавления (не с начала периода)
  • Если устройство удалено — перестать показывать на дашборде

Что нужно от Славы

  1. Подтвердить вариант реализации (рекомендую B — AppDaemon/Python)
  2. Увеличить purge_keep_days до 35 (иначе не будет данных за месяц)
  3. Установить AppDaemon (если выбран вариант B) — или подтвердить другой вариант
  4. Подтвердить список исключений (какие entity не отслеживать)