Files
wiki/tasks/ha-availability-dashboard/PROJECT.md
2026-04-15 14:50:01 +03:00

132 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HA Availability Dashboard
## Описание
Дашборд доступности устройств в Home Assistant — показывает uptime устройств в % за три периода (24ч / 7д / 30д) с группировкой по комнатам, цветовой индикацией и sparkline.
## Статус
🟡 **В разработке** — бэкенд работает, дашборд не построен
## Ссылки
- **ТЗ:** `TZ.md`
- **Исходники AppDaemon:** `appdaemon/` (локальная копия, деплой → HA)
- **HA:** `https://ha.homenet542.keenetic.pro`
## Архитектура
```
HA History API ──► AppDaemon (availability.py) ──► sensor.avail_* ──► Lovelace Dashboard
├── REST API (supervisor/core/api) — история, states
└── WebSocket (homeassistant:8123) — area/entity/device registry
```
## Файловая структура
### На HA (`/addon_configs/a0d7b954_appdaemon/apps/`)
```
apps/
├── apps.yaml # регистрация: hello_world + availability
├── availability.py # основной модуль (Availability class)
├── availability_utils.py # утилиты (фильтрация, расчёт, форматирование)
└── hello.py # тестовое приложение (оставлено)
```
### Локально (`tasks/ha-availability-dashboard/`)
```
├── TZ.md # полное ТЗ
├── PROJECT.md # этот файл
└── appdaemon/ # локальная копия для редактирования
├── availability.py
├── availability_utils.py
└── apps.yaml
```
## Компоненты
### AppDaemon
- **Версия:** 4.5.13
- **Addon slug:** `a0d7b954_appdaemon`
- **Python:** 3.12.13
- **Конфиг:** `/addon_configs/a0d7b954_appdaemon/appdaemon.yaml`
- **Таймзона:** Europe/Moscow
### availability.py
Класс `Availability(hass.Hass)`:
- **Cold-start:** полный пересчёт через 30 сек после запуска
- **Расписания:** 24ч/5мин, 7д/15мин, 30д/2ч
- **Подписка:** `input_select.avail_period` — пересчёт при переключении
- **REST API:** `http://supervisor/core/api` с SUPERVISOR_TOKEN
- **WebSocket:** `ws://homeassistant:8123/api/websocket` с ha_token из args
Методы:
| Метод | Назначение |
|-------|-----------|
| `_fetch_entities()` | Получение списка устройств + фильтрация |
| `_fetch_areas()` | WebSocket → area/entity/device registry → маппинг |
| `_fetch_history()` | Batch-запросы по 20 entity, пауза 1 сек |
| `_calc_period()` | Полный цикл расчёта для периода |
| `_set_progress()` | Обновление sensor.avail_calc_progress |
### availability_utils.py
| Функция | Назначение |
|---------|-----------|
| `is_excluded()` | Фильтрация entity по правилам исключения |
| `sanitize_entity_id()` | `light.bra``light_bra` |
| `sanitize_area_name()` | `Без комнаты``bez_komnaty` (транслитерация) |
| `compute_availability()` | Расчёт pct, down_count, max_downtime, last_downtime |
| `compute_sparkline()` | Ежедневные точки за N дней |
| `get_color()` | ≥99→green, 95-99→yellow, 90-95→orange, <90→red |
| `calc_trend()` | Сравнение с предыдущим периодом (up/down/stable) |
### Sensors
- `sensor.avail_<entity_id>` — доступность устройства (state = %)
- `sensor.avail_area_<name>` — средняя доступность по комнате
- `sensor.avail_calc_progress` — прогресс расчёта (`"1/2"` или `"idle"`)
### input_select
- `input_select.avail_period` — переключатель периода (24h / 7d / 30d)
## Аутентификация
| Канал | URL | Токен |
|-------|-----|-------|
| REST API | `http://supervisor/core/api` | SUPERVISOR_TOKEN (авто) |
| WebSocket | `ws://homeassistant:8123/api/websocket` | ha_token (Long-Lived Access Token из apps.yaml) |
⚠️ SUPERVISOR_TOKEN **не подходит** для прямого WebSocket к HA — только для REST через supervisor proxy.
## Известные баги / ограничения
1. **Sparkline для 24ч** — даёт 1 точку, а не 7. Нужна логика по часам
2. **Area cache**`_fetch_areas()` запрашивает registry при каждом расчёте. Можно кэшировать
3. **30д тренд** — запрашивает 60д истории, нужен `purge_keep_days ≥ 65`
4. **Новые устройства**`compute_availability` вернёт 100% (нет истории = нет падений). Корректно, но не информативно
5. **`minimal_response`** — HA может не возвращать entity_id в каждой записи. Fallback на первый entity из батча
## Деплой
```bash
# Обновить файлы на HA
SKILL=~/.openclaw/skills/installer/scripts
$SKILL/ssh_exec.sh --host ha --cmd "cat > /addon_configs/a0d7b954_appdaemon/apps/availability.py << 'ENDOFFILE'
$(cat appdaemon/availability.py)
ENDOFFILE"
$SKILL/ssh_exec.sh --host ha --cmd "cat > /addon_configs/a0d7b954_appdaemon/apps/availability_utils.py << 'ENDOFFILE'
$(cat appdaemon/availability_utils.py)
ENDOFFILE"
# Перезапустить AppDaemon
$SKILL/ssh_exec.sh --host ha --cmd "ha addons restart a0d7b954_appdaemon"
```
## TODO
- [ ] Назначить areas устройствам в HA
- [ ] Увеличить purge_keep_days до 35
- [ ] Установить button-card через HACS
- [ ] Построить Lovelace-дашборд
- [ ] Расширить на другие домены (sensor, binary_sensor, climate, ...)
- [ ] Кэшировать area registry (не запрашивать каждый цикл)
- [ ] Исправить sparkline для 24ч (часовые точки вместо дневных)