[2026-09-15] Zigbee: единые ID 23 устройств, 12 алертов батарей, virtual Modbus slave 105-112, fix slave 100

This commit is contained in:
Alexey Martemyanov
2026-09-15 22:50:55 +06:00
parent e295905de3
commit ddba016d43
3 changed files with 153 additions and 34 deletions
+143 -28
View File
@@ -1,10 +1,10 @@
---
title: "Zigbee на t610 — ZHA (справочник)"
created: '2026-09-15'
updated: '2026-09-15'
updated: '2026-09-15 (поздний вечер: +7 новых TS0201 тёплых полов, ЕДИНООБРАЗИЕ ID у 23 устройств, 12 алертов батарей, виртуальные Modbus slave 105112)'
type: tech
namespace: family
status: 🟢 РАБОТАЕТ. ZHA: 17 записей (16 устройств + координатор), `unavailable` = 0. 14 автоматизаций: 13 `on`, 1 `off` намеренно (`Ventilation automation on`).
status: 🟢 РАБОТАЕТ. ZHA: 24 записи (23 устройства + координатор), `unavailable` = 0. Все устройства с читаемыми ID в едином виде, все в зонах. 26 автоматизаций: 25 `on`, 1 `off` намеренно. Bridge: 9 Zigbee-температур отдаются ZONT'у (slave 100112).
tags:
- t610
- haos
@@ -42,26 +42,54 @@ related:
---
## 2. Устройства (16 + координатор)
## 2. Устройства (23 + координатор)
| IEEE | Имя | modelId | Тип |
|---|---|---|---|
| `a4c13862d39377e6` | `office_temperature_sensor` | TS0201 | EndDevice (батарея) |
| `a4c138f8da8bc478` | `recirculation_pump` | TS011F | Router — на нём висит `modbus-bridge` (relay slave 104) |
| `84fd27fffed9e137` | `night_light_shower_2` | TS0001 | Router |
| `a4c1386d40ddb67b` | `light_sensor_stairs` | TS0222 | EndDevice (батарея) |
| `a4c1381186ed1a32` | `smart_light_office` | TS0012 | EndDevice |
| `a4c13873b5c1575b` | `office_table_light_switch` | TS0002 | Router |
| `a4c13807b64c7fd4` | `kitchen_hood` | TS0003 | Router |
| `a4c1386d0839706a` | `light_stairs` | TS0002 | Router |
| `a4c138eb6fbe9d19` | `heating_cable_plug` | TS011F | Router |
| `a4c1384fbe0b3a6b` | `sauna` (`_TZ3210_nhqka112`) | TS011F | Router |
| `a4c138b0f9e674a5` | `wireless_light_switch_bed` | TS0041 | EndDevice (батарея) |
| `a4c13882a4b42db0` | `bed_dimmer` (`_TZ3000_ooc8illt`) | TS0052 | Router |
| `a4c138c4a94a6a31` | `shower_2_presence_sensor` | TS0601 | Router (mmWave) |
| `a4c1381694217e10` | `boiler_controller_power` | TS011F | Router |
| `a4c1383d5fcaa063` | `boiler_water_leak` | TS0207 | EndDevice |
| `a4c138c650636cf6` | `toilet_1_floor_temperature` | TS0201 | EndDevice |
> 🗓 **2026-09-15 (поздний вечер): +7 новых TS0201 (тёплые полы), проведено ЕДИНООБРАЗИЕ ID.** Все 23 устройства имеют читаемые `name_by_user`; все сущности — вид `<device>_<role>` (`_temperature`, `_humidity`, `_battery`, `_lqi`, `_rssi`, `_identify`, `_firmware`). Все устройства в зонах, «без зоны» — нет.
| IEEE | Имя | modelId | Тип | Зона |
|---|---|---|---|---|
| `a4c13862d39377e6` | `kabinet_temperature` (бывш. `office_temperature_sensor`) | TS0201 | EndDevice (батарея) | kabinet |
| `a4c138f8da8bc478` | `recirculation_pump` | TS011F | Router — на нём висит `modbus-bridge` (relay slave 101/1) | kotelnaia |
| `84fd27fffed9e137` | `night_light_shower_2` | TS0001 | Router | dushevaia |
| `a4c1386d40ddb67b` | `light_sensor_stairs` | TS0222 | EndDevice (батарея) | lestnitsa |
| `a4c1381186ed1a32` | `smart_light_office` | TS0012 | EndDevice | kabinet |
| `a4c13873b5c1575b` | `office_table_light_switch` | TS0002 | Router | kabinet |
| `a4c13807b64c7fd4` | `kitchen_hood` | TS0003 | Router | kitchen |
| `a4c1386d0839706a` | `light_stairs` | TS0002 | Router | lestnitsa |
| `a4c138eb6fbe9d19` | `heating_cable_plug` | TS011F | Router | kotelnaia |
| `a4c1384fbe0b3a6b` | `sauna` (`_TZ3210_nhqka112`) | TS011F | Router | tualet |
| `a4c138b0f9e674a5` | `wireless_light_switch_bed` | TS0041 | EndDevice (батарея) | bedroom |
| `a4c13882a4b42db0` | `bed_dimmer` (`_TZ3000_ooc8illt`) | TS0052 | Router | bedroom |
| `a4c138c4a94a6a31` | `shower_2_presence_sensor` | TS0601 | Router (mmWave) | dushevaia |
| `a4c1381694217e10` | `boiler_controller_power` | TS011F | Router | kotelnaia |
| `a4c1383d5fcaa063` | `boiler_water_leak` | TS0207 | EndDevice (батарея) | kotelnaia |
| `a4c138c650636cf6` | `toilet_1_floor_temperature` | TS0201 | EndDevice (батарея) | tualet |
| `a4c13827ea585609` | `living_room_floor_temperature` | TS0201 | EndDevice (батарея) | living_room |
| `a4c1382ac15720dd` | `severnaia_floor_temperature` | TS0201 | EndDevice (батарея) | severnaia |
| `a4c1382dac5e10e2` | `kabinet_floor_temperature` | TS0201 | EndDevice (батарея) | kabinet |
| `a4c13837021f5298` | `kitchen_floor_temperature` | TS0201 | EndDevice (батарея) | kitchen |
| `a4c13867875ee7d3` | `vannaia_floor_temperature` | TS0201 | EndDevice (батарея) | vannaia |
| `a4c138cde6eed013` | `prikhozhaia_floor_temperature` | TS0201 | EndDevice (батарея) | prikhozhaia |
| `a4c13865e226312d` | `dushevaia_floor_temperature` | TS0201 | EndDevice (батарея) | dushevaia |
> 🔴 **`sauna` = зона `tualet` (Туалет 1) — ЭТО ПРАВИЛЬНО, подтверждено Alex.** Не путать с `bed_dimmer` (Спальня).
> 📌 **Единый вид сущностей:** `sensor.<device>_temperature` / `_humidity` / `_battery` / `_lqi` / `_rssi`, `button.<device>_identify`, `update.<device>_firmware`. Для реле: `sensor.<device>_power` / `_voltage` / `_current` / `_energy`, `select.<device>_indicator_mode` / `_power_outage_memory`.
> 📌 **Прихожая** ранее имела ошибочный префикс `tualet_` — исправлено на `prikhozhaia_floor_temperature`.
> 📌 **Координатор** `Inswift ZBP-MG21` — 45 диагностических сущностей, все `disabled_by: integration`.
### 2.1. 🔴 Как переименовывать (проверенный рецепт 2026-09-15)
**Смена `name_by_user` у устройства НЕ переименовывает `entity_id`** — HA перегенерирует их только у новых сущностей. Обязательны два шага:
```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"}
```
> ⚠️ **После переименования проверить ссылки в `automations.yaml`** — старые `entity_id` рвутся молча. Проверка: вытащить все `entity_id:` из YAML, сверить со списком `/api/states`.
> ⚠️ Записи автоматизаций со старым `device_id`/`entity_id` остаются в реестре как сироты `unavailable` → удалять через WS `config/entity_registry/remove`. Если падает с `id_reuse: Identifier values have to increase` — сначала `update` c `disabled_by: user`, затем `remove`.
> ⚠️ Переименование сущности **не меняет `area_id`**; но удаление `device_id` — сбрасывает (питфолл 3).
> 🔴 **`sauna` = `_TZ3210_nhqka112` TS011F (реле), `bed_dimmer` = `_TZ3000_ooc8illt` TS0052 (диммер).** Источник истины — `database.db` (IEEE + modelId + manufName в одной строке).
> ⚠️ `shower_2_presence_sensor` (`_TZE204_qasjif9e`, TS0601, Mains) — mmWave-радар присутствия, не датчик климата.
@@ -90,7 +118,89 @@ light_sensor_stairs
---
## 4. Кнопка спальни и диммер — рабочая связка
## 4. Батарейные устройства и оповещения (12 автоматизаций)
**Батарейных Zigbee-устройств — 11** (All TS0201 ×8, TS0222, TS0207, TS0041 → итого 11):
| Сущность заряда | Место |
|---|---|
| `sensor.toilet_1_floor_temperature_battery` | Туалет 1 (тёплый пол) |
| `sensor.light_sensor_stairs_battery` | Лестница (освещённость) |
| `sensor.dushevaia_floor_temperature_battery` | Душевая (тёплый пол) |
| `sensor.boiler_water_leak_battery` | Котельная (протечка) |
| `sensor.kabinet_temperature_battery` | Кабинет (температура) |
| `sensor.living_room_floor_temperature_battery` | Гостиная (тёплый пол) |
| `sensor.severnaia_floor_temperature_battery` | Серая (тёплый пол) |
| `sensor.kabinet_floor_temperature_battery` | Кабинет (тёплый пол) |
| `sensor.kitchen_floor_temperature_battery` | Кухня (тёплый пол) |
| `sensor.vannaia_floor_temperature_battery` | Ванная (тёплый пол) |
| `sensor.prikhozhaia_floor_temperature_battery` | Прихожая (тёплый пол) |
| `sensor.wireless_light_switch_bed_battery` | Спальня (кнопка) |
### Единый шаблон автоматизации (id `8800000000000`…`8800000000011`)
```yaml
- id: '8800000000000'
alias: 'Батарея: <место>'
triggers:
- 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:
- choose:
- conditions: [{condition: trigger, id: low}]
sequence:
- action: persistent_notification.create # уведомление в UI
- action: notify.mobile_app_sm_s931b # push на телефон
- conditions: [{condition: trigger, id: ok}]
sequence:
- action: persistent_notification.dismiss
mode: single
```
> 🔴 **Порог 20 %, выдержка 2 ч.** Выдержка обязательна: батарейные TS0201 под нагрузкой дают кратковременные просадки, без `for:` прилетают ложные алерты.
> 🔴 **Двойной канал:** `persistent_notification` (видно в UI) + `notify.mobile_app_sm_s931b` (push). При возврате заряда выше порога уведомление гасится автоматически (`notification_id: bat_<slug>`).
> 📌 **Предыдущие 2 автоматизации удалены** (`1773451323415`, `1773459663218`) — были с порогом 10 и без push, заменены единым видом.
> 📌 **Границы:** `automations.yaml` генерировать целиком, старый YAML со старыми `device_id` не патчится (питфолл 9).
---
## 5. Виртуальные Modbus-датчики (bridge, slave 100112)
Температурные Zigbee-датчики отдаются ZONT'у через `modbus-bridge` как виртуальные slave'ы, регистр **100**, `int16`, `divider: 10`.
| Slave | HA-сущность | Имя в конфиге |
|---|---|---|
| **100** | `sensor.kabinet_temperature_temperature` | Room temp (исторический, был `office_temperature_sensor`) |
| 101 | снифф `dining_temperature` + запись `switch.recirculation_pump` | Dining temp / Socket 1 |
| 102 | снифф `kids_temperature` | Kids Temperature |
| 103 | снифф `bedroom_temperature` | Bedroom Temperature |
| 104 | `switch.boiler_controller_power` | Boiler controller power (Zigbee relay) |
| 105 | `sensor.living_room_floor_temperature_temperature` | Living room floor temp |
| 106 | `sensor.severnaia_floor_temperature_temperature` | Severnaia (grey room) floor temp |
| 107 | `sensor.kabinet_floor_temperature_temperature` | Kabinet floor temp |
| 108 | `sensor.kitchen_floor_temperature_temperature` | Kitchen floor temp |
| 109 | `sensor.vannaia_floor_temperature_temperature` | Vannaia floor temp |
| 110 | `sensor.prikhozhaia_floor_temperature_temperature` | Prikhozhaia floor temp |
| 111 | `sensor.dushevaia_floor_temperature_temperature` | Dushevaia floor temp |
| 112 | `sensor.toilet_1_floor_temperature_temperature` | Toilet 1 floor temp |
> 📌 **Свободно: `113+`.** У 100/102/103 — только регистры ≠ 100.
> 🔴 **`rebuild` аддона ОБЯЗАТЕЛЕН** после правки `data/config.template.tmpl` — шаблон впекается в образ (`Dockerfile: COPY data/config.template.tmpl`).
> 🔴 **Проверка работоспособности slave'а:** bridge отвечает только на запросы ZONT'а. Проверять **двумя** признаками:
> 1. `ha apps logs local_modbus-bridge | grep "HA poll -> sensor.<entity>"` — bridge поллит HA и кэширует.
> 2. `... | grep -A3 "Slave: 100"` → `Response: ... (ha:sensor.<entity>) = <val> [<hex>]`.
> ⚠️ Если сущность переименована, а маппинг ссылается на старое имя → slave отдаёт **`0`** молча. Симптом именно такой: `= 0 [00 00]`. Проверять после любого переименования.
---
## 6. Кнопка спальни и диммер — рабочая связка
**Кнопка** `wireless_light_switch_bed` (`TS0041`, `_TZ3000_kccruoi`) — сущности `event.*` у неё **нет**, она шлёт **`zha_event`**:
@@ -113,7 +223,7 @@ command press_type, args: [0]
---
## 5. Свет лестницы и подсветка
## 7. Свет лестницы и подсветка
```
light.light_stairs_left / light.light_stairs_right
@@ -136,7 +246,7 @@ actions: [{action: light.turn_off, target: {entity_id: [light.light_stairs_left
---
## 6. Миграция Z2M → ZHA (воспроизведение)
## 8. Миграция Z2M → ZHA (воспроизведение)
**Принцип:** сеть живёт в **NVRAM стика**, не в файлах. Перепаривание не требуется — ZHA поднимает ту же сеть и сама принимает устройства.
@@ -197,7 +307,7 @@ curl -s -X POST -H "$H" -H "$CT" \
---
## 7. ZHA WebSocket API — рабочие команды
## 9. ZHA WebSocket API — рабочие команды
| Задача | Команда |
|---|---|
@@ -227,7 +337,7 @@ cd ~/tmp-t610 && grep -o 'eyJ[A-Za-z0-9._-]*' ha_token.txt | head -1 > /tmp/.hat
---
## 8. Доступ к HA API на t610
## 10. Доступ к HA API на t610
| Параметр | Значение |
|---|---|
@@ -243,7 +353,7 @@ cd ~/tmp-t610 && grep -o 'eyJ[A-Za-z0-9._-]*' ha_token.txt | head -1 > /tmp/.hat
---
## 9. Snapshot / бэкап
## 11. Snapshot / бэкап
```bash
curl -s -X POST -H "$HDR" -H "Content-Type: application/json" \
@@ -257,7 +367,7 @@ curl -s -H "$HDR" http://supervisor/backups | jq
---
## 10. Питфоллы
## 12. Питфоллы
| # | Питфолл | Обход |
|---|---|---|
@@ -277,6 +387,11 @@ curl -s -H "$HDR" http://supervisor/backups | jq
| 14 | **`sqlite3` в аддоне нет** | `database.db` читать через `strings` |
| 15 | **Перепутанные IEEE при переименовании вслепую** | Источник истины — `database.db`, не производные карты |
| 16 | **После переноса часть устройств — EndDevice (батарея), они спят** | Разбудить нажатием паринг-кнопки; это НЕ перепаривание |
| 17 | 🔴 **`name_by_user` НЕ переименовывает `entity_id`** | HA меняет entity_id только у новых сущностей. Переименовывать **и устройство, и каждую сущность** отдельно (`device_registry/update` + `entity_registry/update`) |
| 18 | 🔴 **После переименования рвутся ссылки в `automations.yaml`** | Молча → автоматизация ссылается на призрак. Проверять: все `entity_id:` из YAML сверить со `/api/states` |
| 19 | 🔴 **Сирота-автоматизация: `unavailable`, но YAML чист** | Тело удалено из `automations.yaml`, запись в реестре осталась → `config/entity_registry/remove`. Если `id_reuse: Identifier values have to increase` — сначала `update` c `disabled_by: user`, затем `remove` |
| 20 | 🔴 **Modbus slave отдаёт `0 [00 00]` после переименования HA-сущности** | Маппинг ссылается на старое имя. Проверять `HA poll -> sensor.<entity>` в логе bridge. Реальная поломка 2026-09-15: slave 100 отдавал 0, после фикса — 23.97 |
| 21 | **Проверить slave bridge без ZONT нельзя** | Bridge — serial-slave: отвечает только на запрос. Признаки работы: `HA poll -> <entity> = <val>` (поллер) и `Response: ... = <val> [<hex>]` (ответ ZONT'у) |
---