[2026-09-15] eagle: family/how-to/ha-automations.md family/plans/t610-zigbee-ids-battery-freshsensors-modbus.md

This commit is contained in:
Alexey Martemyanov
2026-09-15 22:56:12 +06:00
parent ddba016d43
commit b954d3e289
2 changed files with 304 additions and 134 deletions
@@ -1,5 +1,5 @@
---
title: "План: читаемые ID Zigbee, алерты батарей, виртуальные Modbus-датчики"
title: "План и результат: читаемые ID Zigbee, алерты батарей, виртуальные Modbus-датчики"
created: '2026-09-15'
updated: '2026-09-15'
type: plan
@@ -17,55 +17,39 @@ related:
- '[[family/how-to/ha-automations]]'
---
# План: читаемые ID, алерты батарей, виртуальные Modbus-датчики
# План и результат: читаемые ID, алерты батарей, виртуальные Modbus-датчики
> Задача от Alex (2026-09-15): 1) убедиться, что у **всех** Zigbee-устройств читаемые ID; 2) каждому **батарейному** — оповещение о низком заряде; 3) каждый **температурный** Zigbee-датчик прописать как виртуальное устройство Modbus в bridge; 4) обновить доку.
>
> ✅ **Всё выполнено в тот же вечер.** Ниже — план И фактический результат.
## 0. Что установлено фактами (снимок 2026-09-15)
---
### 0.1. Новые устройства (8 всего, +1 был в доке)
ZHA: **24 записи** (23 устройства + координатор). Было 17.
## 0. Исходная точка (снимок до работ)
| # | Устройство (name_by_user) | IEEE | Модель | Зона | Батарея |
|---|---|---|---|---|---|
| 1 | `Темп теплый пол гостиная` | `a4c13827ea585609` | TS0201 | living_room | ✅ |
| 2 | `Температура серая` | `a4c1382ac15720dd` | TS0201 | severnaia | ✅ |
| 3 | `Темп теплый пол кабинет` | `a4c1382dac5e10e2` | TS0201 | kabinet | ✅ |
| 4 | `Темп теплый пол кухня` | `a4c13837021f5298` | TS0201 | kitchen | ✅ |
| 5 | `Темп теплый пол ванная` | `a4c13867875ee7d3` | TS0201 | vannaia | ✅ |
| 6 | `Темп теплый пол прихожая` | `a4c138cde6eed013` | TS0201 | prikhozhaia | ✅ |
| 7 | `Темп теплый пол душевая` | `a4c13865e226312d` | TS0201 | dushevaia | ✅ (был ранее) |
| 8 | `shower_2_presence_sensor` | `a4c138c4a94a6a31` | TS0601 | dushevaia | ❌ mains |
Пришло **+7 новых TS0201** (датчики тёплых полов). ZHA: 24 записи (23 устройства + координатор), было 17.
Все 12 TS0201 — **батарейные EndDevice**, сущность `Батарея` есть у каждого.
### 0.2. 🔴 Дефекты ID, найденные при проверке
| # | Дефект | Пример | Оценка |
| IEEE | Исходное `name_by_user` | Модель | Зона |
|---|---|---|---|
| D1 | **Имя устройства по-русски** (HA транслитерирует) | `Темп теплый пол гостиная``sensor.temp_teplyi_pol_gostinaia_temperatura` | 🔴 громоздко, ломает консистентность |
| D2 | **Перепутан префикс: `tualet_` при зоне `prikhozhaia`** | `sensor.tualet_temp_teplyi_pol_prikhozhaia_temperatura` | 🔴 прямая ошибка в имени |
| D3 | **Дубли `_2` / `_3` у LQI/RSSI** (остатки миграции) | `sensor.tz3000_gjnozsaz_ts011f_lqi_2`, `_3` | 🟡 косметика, `disabled_by=integration` |
| D4 | `sauna`**зона `tualet`**, хотя это реле | `switch.sauna` в зоне ТУАЛЕТ | 🔴 неверная зона |
| D5 | `select`-сущности `sauna` названы `bed_dimmer_*` | `select.bed_dimmer_power_on_behavior` под устройством `sauna` | 🟡 ошибка выбора при переименовании |
| `a4c13827ea585609` | `Темп теплый пол гостиная` | TS0201 | living_room |
| `a4c1382ac15720dd` | `Температура серая` | TS0201 | severnaia |
| `a4c1382dac5e10e2` | `Темп теплый пол кабинет` | TS0201 | kabinet |
| `a4c13837021f5298` | `Темп теплый пол кухня` | TS0201 | kitchen |
| `a4c13867875ee7d3` | `Темп теплый пол ванная` | TS0201 | vannaia |
| `a4c138cde6eed013` | `Темп теплый пол прихожая` | TS0201 | prikhozhaia |
| `a4c13865e226312d` | `Темп теплый пол душевая` | TS0201 | dushevaia |
Остальные 16 устройств (реле, свет, кнопки, диммер) — ID читаемые ✅.
### 0.1. 🔴 Дефекты ID, найденные при проверке
### 0.3. Батарейные устройства и их сущности (7 шт.)
| # | Дефект | Пример | Итог |
|---|---|---|---|
| D1 | **Имя устройства по-русски** (HA транслитерирует) | `Темп теплый пол гостиная``sensor.temp_teplyi_pol_gostinaia_temperatura` | ✅ исправлено |
| D2 | **Перепутан префикс: `tualet_` при зоне `prikhozhaia`** | `sensor.tualet_temp_teplyi_pol_prikhozhaia_temperatura` | ✅ исправлено |
| D3 | **Дубли `_2` / `_3` у LQI/RSSI** (остатки миграции) | `sensor.tz3000_gjnozsaz_ts011f_lqi_2`, `_3` | ✅ исправлено |
| D4 | `sauna` — зона `tualet` | `switch.sauna` в зоне ТУАЛЕТ | ⛔ **НЕ дефект** — Alex: «Её зона туалет 1». Оставлено |
| D5 | `select`-сущности `sauna` названы `bed_dimmer_*` | `select.bed_dimmer_power_on_behavior` | ✅ исправлено |
| Устройство | Сущность батареи | Текущий заряд |
|---|---|---|
| `toilet_1_floor_temperature` | `sensor.toilet_1_floor_temperature_battery` | 100.0 |
| `light_sensor_stairs` | `sensor.light_sensor_stairs_battery` | 100.0 |
| `Темп теплый пол душевая` | `sensor.shower_2_floor_battery` | 100.0 |
| `boiler_water_leak` | `sensor.boiler_water_leak_battery` | 100.0 |
| `wireless_light_switch_bed` | `sensor.tz3000_kccru4oi_ts0041_batareia` | ? |
| `office_temperature_sensor` | `sensor.tz3000_akqdg6g7_ts0201_batareia` | ? |
| 6 × новых TS0201 | `sensor.*_batareia` | ? |
**Оповещений о низком заряде — НЕТ ни у одного** (проверено: автоматизаций на `battery` нет).
### 0.4. Modbus-bridge — занятость адресов
### 0.2. Исходная занятость Modbus-адресов bridge
| Slave | Что | Регистр |
|---|---|---|
@@ -75,116 +59,219 @@ ZHA: **24 записи** (23 устройства + координатор). Б
| 103 | снифф `bedroom_temperature` | 100 |
| 104 | Zigbee-реле `switch.boiler_controller_power` | 1 |
**Свободно: `105+`** (у 100/102/103 — регистры ≠ 100).
Свободно: **105+**. Оповещений о низком заряде не было ни у одного батарейного.
---
## 1. План действий
## 1. ✅ РЕЗУЛЬТАТ — Шаг 1: единый вид ID (23 устройства)
### Шаг 1. Переименовать устройства в читаемые ID (ZHA)
Живой конфиг bridge — **не трогать** до подтверждения имён.
**Формат: `<устройство>_<роль>`.** Для датчиков `_temperature` / `_humidity` / `_battery` / `_lqi` / `_rssi`, плюс `button.<dev>_identify` и `update.<dev>_firmware`. Для реле `_power` / `_voltage` / `_current` / `_energy`, `select.<dev>_indicator_mode` / `_power_outage_memory`.
Предлагаемая схема имён (единый стиль `<зона>_floor_temperature`):
| Было | Стало |
|---|---|
| `Темп теплый пол гостиная` | `living_room_floor_temperature` |
| `Температура серая` | `severnaia_floor_temperature` |
| `Темп теплый пол кабинет` | `kabinet_floor_temperature` |
| `Темп теплый пол кухня` | `kitchen_floor_temperature` |
| `Темп теплый пол ванная` | `vannaia_floor_temperature` |
| `Темп теплый пол прихожая` | `prikhozhaia_floor_temperature` |
| `Темп теплый пол душевая` | `dushevaia_floor_temperature` |
| `office_temperature_sensor` | `kabinet_temperature` |
| `light.night_light_shower_2` | `light.dushevaia_night_light` |
| `binary_sensor.tz3000_hy6ncvmw_ts0222` | `binary_sensor.light_sensor_stairs` |
| Текущее | Предлагаемое | Итоговые сущности |
|---|---|---|
| `Темп теплый пол гостиная` | `living_room_floor_temperature` | `sensor.living_room_floor_temperature_temperature` |
| `Температура серая` | `severnaia_floor_temperature` | `sensor.severnaia_floor_temperature_temperature` |
| `Темп теплый пол кабинет` | `kabinet_floor_temperature` | `sensor.kabinet_floor_temperature_temperature` |
| `Темп теплый пол кухня` | `kitchen_floor_temperature` | `sensor.kitchen_floor_temperature_temperature` |
| `Темп теплый пол ванная` | `vannaia_floor_temperature` | `sensor.vannaia_floor_temperature_temperature` |
| `Темп теплый пол прихожая` | `prikhozhaia_floor_temperature` | `sensor.prikhozhaia_floor_temperature_temperature` |
| `Темп теплый пол душевая` | `dushevaia_floor_temperature` | `sensor.dushevaia_floor_temperature_temperature` |
| `office_temperature_sensor` | `kabinet_temperature` | `sensor.kabinet_temperature_temperature` |
**Масштаб:** **140 переименований** (8 устройств + 68 + 16 + 56 + 2 сущностей). Все 23 устройства в зонах, «без зоны» — нет.
> ⚠️ **Переименование душевой затронет уже используемые ID** `sensor.shower_2_floor_temperature/humidity/battery` — их надо либо оставить как есть, либо обновить все ссылки. **Требует решения Alex.**
### 1.1. 🔴 Механика — `name_by_user` НЕ переименовывает `entity_id`
Механика: ZHA **не читает** `friendly_name` из Z2M → задавать через `config/device_registry/update` (WS) с `name_by_user`.
⚠️ Питфолл: удаление `device_id` сбрасывает `area_id`; переименование не сбрасывает, но проверять `area_id` после каждой операции.
HA перегенерирует `entity_id` только у **новых** сущностей. Нужны **два** шага:
### Шаг 2. Починить зону `sauna` (D4) и `select`-имена (D5)
- `sauna` → зона `kotelnaia` (уточнить у Alex: сауна или котельная?)
- `select.bed_dimmer_*` под `sauna` → переименовать в `sauna_*`
```python
# Шаг 1 — имя устройства
{"type":"config/device_registry/update","device_id": D, "name_by_user": "living_room_floor_temperature"}
# Шаг 2 — КАЖДАЯ сущность отдельно
{"type":"config/entity_registry/update","entity_id":"sensor.old_name","new_entity_id":"sensor.new_name"}
```
### Шаг 3. Оповещения о низком заряде (7 батарейных)
На каждое устройство — автоматизация:
### 1.2. Команды (воспроизведение)
```bash
# Полный аудит: устройства + сущности + зоны
cd ~/tmp-t610 && python3 zha_devs.py
# Переименование устройств (WS)
python3 rename_step1.py
# Переименование сущностей пакетом
python3 gen_rename_all.py # → /tmp/rename_all_plan.json (защита от конфликтов)
python3 apply_rename_all.py
# Аудит остатка нечитаемых
python3 audit_rest.py
```
**Скрипты:** `~/tmp-t610/{zha_devs,rename_step1,gen_rename_all,apply_rename_all,audit_rest,rename_ents,fix_last}.py`
### 1.3. 🔴 Побочный эффект: рвутся ссылки в автоматизациях
После переименования **молча** сломались 2 ссылки в `automations.yaml`:
- `light.night_light_shower_2` (×2) → `light.dushevaia_night_light`
- `sensor.tz3000_akqdg6g7_ts0201_batareia``sensor.kabinet_temperature_battery`
**Проверка (обязательна после любого переименования):**
```bash
curl -s -H @/tmp/h1 "$B/api/states" | jq -r '[.[].entity_id]' > /tmp/all_ents.json
ssh -i ~/.ssh/id_rsa root@192.168.2.176 'cat /config/automations.yaml' \
| grep -oE 'entity_id: [a-z_]+\.[a-zA-Z0-9_]+' | awk '{print $2}' | sort -u \
| while read e; do jq -e --arg e "$e" 'index($e)' /tmp/all_ents.json >/dev/null || echo "BROKEN: $e"; done
```
---
## 2. ✅ РЕЗУЛЬТАТ — Шаг 2: чиста наследия миграции
- `select.bed_dimmer_power_on_behavior` / `_switch_type` под `sauna``select.sauna_power_on_behavior` / `_switch_type`
- Все дубли `_2`/`_3` у LQI/RSSI/energy/identify приведены к `<device>_<role>`
- `sauna` в зоне `tualet`**оставлено** (не дефект, подтверждено Alex)
---
## 3. ✅ РЕЗУЛЬТАТ — Шаг 3: 12 автоматизаций контроля батарей
**Порог 20 %, выдержка 2 ч, двойной канал:** `persistent_notification` (видно в UI) + `notify.mobile_app_sm_s931b` (push). При возврате заряда выше порога уведомление гасится само.
```yaml
- id: <N>
alias: "Батарея: <устройство> разряжена"
- id: '8800000000000' # …8800000000011 — 12 штук
alias: 'Батарея: <место>'
triggers:
- trigger: numeric_state
entity_id: sensor.<entity>_battery
below: 20
for: "02:00:00"
- trigger: numeric_state
entity_id: sensor.<device>_battery
below: 20
for: '02:00:00'
id: low
- trigger: numeric_state
entity_id: sensor.<device>_battery
above: 20
id: ok
actions:
- action: persistent_notification.create
data:
title: "🔋 Батарея разряжена"
message: "<устройство>: {{ states('sensor.<entity>_battery') }}%"
- choose:
- conditions: [{condition: trigger, id: low}]
sequence:
- action: persistent_notification.create
data: {title: '🔋 Батарея разряжена', notification_id: 'bat_<slug>'}
- action: notify.mobile_app_sm_s931b
- conditions: [{condition: trigger, id: ok}]
sequence:
- action: persistent_notification.dismiss
data: {notification_id: 'bat_<slug>'}
mode: single
```
Порог **20 %**, выдержка **2 ч** (защита от просадки под нагрузкой).
⚠️ Домен триггера в ZHA — `battery``battery_level`. Проверять имена сущностей (`_battery` vs `_batareia`).
Способ доставки: `persistent_notification` — обсуждаемо (могут быть мобильные нотификации).
**Покрытие (12 сущностей):** туалет 1 · лестница · душевая · котельная (протечка) · кабинет (воздух) · гостиная · серая · кабинет (пол) · кухня · ванная · прихожая · спальня (кнопка).
### Шаг 4. Виртуальные Modbus-датчики в bridge
Добавить в `data/config.template.tmpl` секцию `mappings`:
### 3.1. Заменённые старые
| Slave | Источник (HA entity) | Регистр | Имя |
|---|---|---|---|
| 105 | `sensor.living_room_floor_temperature_temperature` | 100 | Living room floor temp |
| 106 | `sensor.severnaia_floor_temperature_temperature` | 100 | Severnaia floor temp |
| 107 | `sensor.kabinet_floor_temperature_temperature` | 100 | Kabinet floor temp |
| 108 | `sensor.kitchen_floor_temperature_temperature` | 100 | Kitchen floor temp |
| 109 | `sensor.vannaia_floor_temperature_temperature` | 100 | Vannaia floor temp |
| 110 | `sensor.prikhozhaia_floor_temperature_temperature` | 100 | Prikhozhaia floor temp |
| 111 | `sensor.dushevaia_floor_temperature_temperature` | 100 | Dushevaia floor temp |
| 112 | `sensor.toilet_1_floor_temperature_temperature` | 100 | Toilet 1 floor temp |
Две прежние автоматизации (`1773451323415`, `1773459663218`) **удалены** — были с порогом 10 и без push.
Формат (по образцу существующего):
```yaml
- name: "Living room floor temp"
source: "ha"
entity_id: "sensor.living_room_floor_temperature_temperature"
slave_id: 105
register_address: 100
register_count: 1
data_type: "int16"
divider: 10
### 3.2. 🔴 Сироты: `unavailable` при чистом YAML
Тело удалено из `automations.yaml`, запись в реестре осталась → `unavailable`. Удаление:
```python
# Если config/entity_registry/remove падает с id_reuse:
# "Identifier values have to increase"
{"type":"config/entity_registry/update","entity_id": E, "disabled_by": "user"} # сначала это
{"type":"config/entity_registry/remove","entity_id": E} # потом это
```
⚠️ **Проверить свободно ли 105+** по двум источникам: эта карта + сам шаблон (сделано ✅).
⚠️ **`rebuild` обязателен** — шаблон впекается в образ.
⚠️ Только температурные. `dining/kids/bedroom` — уже есть (сниффы).
**Скрипты:** `~/tmp-t610/{add_battery_autos,rm_orphans,rm_orphan2,rm_orphan3}.py`
### Шаг 5. Обновить доку
- `family/tech/zigbee-t610-z2m-i-zha.md` — карта устройств 16 → 23, новые TS0201, дефекты ID.
- `family/how-to/home-automation.md` §6 — карта slave'ов 100112.
- `family/how-to/ha-automations.md` — 7 новых автоматизаций батарей.
### 3.3. Границы
`sensor.wireless_light_switch_bed_battery` = `unknown` — кнопка спальни спит. Автоматизация создана, но триггера не будет, пока датчик не проснётся (лечится нажатием кнопки).
---
## 2. Вопросы к Alex (до начала работ)
## 4. ✅ РЕЗУЛЬТАТ — Шаг 4: виртуальные Modbus-датчики (slave 100 + 105112)
1. **Схема имён** — устраивает `living_room_floor_temperature` / `severnaia_floor_temperature`? Или другой стиль?
2. **Переименовывать ли `office_temperature_sensor`**`kabinet_temperature`? (затронет slave 100 в bridge)
3. **Душевая:** оставить `shower_2_floor_*` или переименовать в `dushevaia_floor_temperature_*`? (переименование = правка ссылок)
4. **`sauna` в зоне «Туалет»** — куда правильно: котельная?
5. **Порог/доставка алертов:** 20 %, 2 ч, `persistent_notification` — или мобильные push?
6. **Нужны ли в Modbus влажность/CO2**, или только температура?
Добавлены в `/addons/modbus-bridge/data/config.template.tmpl`, `int16`, `divider: 10`:
## 3. Порядок выполнения и риски
| Slave | HA-сущность |
|---|---|
| **100** | `sensor.kabinet_temperature_temperature` (исторический «Room temp») |
| 105 | `sensor.living_room_floor_temperature_temperature` |
| 106 | `sensor.severnaia_floor_temperature_temperature` |
| 107 | `sensor.kabinet_floor_temperature_temperature` |
| 108 | `sensor.kitchen_floor_temperature_temperature` |
| 109 | `sensor.vannaia_floor_temperature_temperature` |
| 110 | `sensor.prikhozhaia_floor_temperature_temperature` |
| 111 | `sensor.dushevaia_floor_temperature_temperature` |
| 112 | `sensor.toilet_1_floor_temperature_temperature` |
| Шаг | Риск | Откат |
|---|---|---|
| 1. Переименование | Средний — меняются entity_id, ломаются ссылки в автоматизациях/дашбордах | Бэкап `core.entity_registry` + список старых ID |
| 2. Зона/select | Низкий | Вернуть `area_id` |
| 3. Автоматизации | Низкий | Бэкап `automations.yaml` |
| 4. Modbus mappings | Средний — rebuild аддона, возможен RCU/нагрузка | Бэкап `config.template.tmpl`, `rollback` |
Итого в шаблоне **14 маппингов**. Свободно: `113+`.
**Обязательно перед началом:**
- Бэкап `/config/.storage/core.entity_registry`, `core.device_registry`, `core.restore_state`
- Бэкап `/config/automations.yaml`
- Бэкап `/addons/modbus-bridge/data/config.template.tmpl` (новый `.bak-idmodbus-<дата>`)
- Снять снапшот HA (`POST /backups/new/full`)
### 4.1. 🔴 НАЙДЕНА И ИСПРАВЛЕНА РЕАЛЬНАЯ ПОЛОМКА: slave 100 отдавал `0`
Slave 100 ссылался на **старое** имя `sensor.office_temperature_sensor_temperature` — после переименования сущность стала `kabinet_temperature_temperature`. Bridge молча возвращал `0 [00 00]`.
```
ДО: → Response: 1 register(s) from 100 (ha:sensor.kabinet_temperature_temperature) = 0 [00 00]
ПОСЛЕ: → Response: 1 register(s) from 100 (ha:sensor.kabinet_temperature_temperature) = 23.97 [00 F0]
```
> 📌 **ПРАВИЛО: переименовал HA-сущность → проверь маппинг в `config.template.tmpl` + `rebuild`.**
> 📌 **Проверка slave'а без ZONT'а невозможна** — bridge это serial-slave, отвечает только на запрос. Признаки работы:
> 1. `ha apps logs local_modbus-bridge | grep "HA poll -> sensor.<entity>"` — поллер кэширует HA-значение.
> 2. `... | grep -A3 "Slave: 100"` → `Response: ... = <val> [<hex>]`.
### 4.2. Дубликат slave 113 — убран
При правке добавился «Kabinet air temp» (113) на ту же сущность, что slave 100. Удалён как дубль.
### 4.3. Команды
```bash
# правка шаблона → rebuild ОБЯЗАТЕЛЕН (Dockerfile: COPY data/config.template.tmpl)
scp config.template.tmpl root@192.168.2.176:/addons/modbus-bridge/data/config.template.tmpl
ssh root@192.168.2.176 'ha apps rebuild local_modbus-bridge && ha apps start local_modbus-bridge'
```
**Скрипты:** `~/tmp-t610/{add_modbus_temps,dedup_slave113,fix_slave100}.py`
---
## 5. ✅ РЕЗУЛЬТАТ — Шаг 5: дока обновлена
- `family/tech/zigbee-t610-z2m-i-zha.md` — карта 16 → 23 устройств, §2.1 «как переименовывать», §4 батареи, §5 виртуальные Modbus, питфоллы 1721.
- `family/how-to/home-automation.md` — шапка, §1 итог, §6 карта slave'ов 100112.
- `family/how-to/ha-automations.md` — карта автоматизаций 14 → 26, батарейные.
- Коммит vault: **`ddba016`**.
---
## 6. Бэкапы, снятые перед работами (2026-09-15 22:34)
| Что | Где |
|---|---|
| Снапшот HA (full) | `23a119f4.tar` в `/backup/` на t610 |
| Реестры (entities/devices/areas) | `~/tmp-t610/backup-preids-20260915-223427/registries-before.json` |
| Реестры (на t610) | `/config/.storage.bak-preids-20260915-223427/` |
| `automations.yaml` | `/config/automations.yaml.bak-preids-20260915-223427` |
| `config.template.tmpl` | `/addons/modbus-bridge/data/config.template.tmpl.bak-preids-20260915-223427` |
---
## 7. Ключевые уроки
| # | Урок |
|---|---|
| 1 | `name_by_user` и `entity_id`**разные вещи**, менять оба |
| 2 | Переименование рвёт ссылки в `automations.yaml` **молча** — проверять всегда |
| 3 | Переименование рвёт маппинг bridge → slave отдаёт `0` **молча** |
| 4 | Сирота-автоматизация (`unavailable` при чистом YAML) → `remove`, а при `id_reuse` — сначала `disabled_by: user` |
| 5 | Bridge нельзя проверить без ZONT'а иначе, чем через `HA poll ->` в логе |
| 6 | `rebuild` (не `restart`) после правки `data/config.template.tmpl` |
| 7 | Русские имена устройств → HA транслитерирует в мусорные `entity_id` |
## Связанные заметки
- [[family/tech/zigbee-t610-z2m-i-zha]] — справочник ZHA: устройства, рецепт переименования, батареи, Modbus slave'ы
- [[family/how-to/home-automation]] — топология, аддоны, Modbus §6
- [[family/how-to/ha-automations]] — логика автоматизаций