[2026-09-15] eagle: family/how-to/home-automation.md family/tech/zigbee-t610-z2m-i-zha.md

This commit is contained in:
Alexey Martemyanov
2026-09-15 20:13:20 +06:00
parent e93739803b
commit 51d0051e86
2 changed files with 167 additions and 21 deletions
+5 -5
View File
@@ -2,7 +2,7 @@
title: "🏠 Домашняя автоматизация"
aliases: [Умный дом, Home automation, HA, Zigbee, Modbus, вентиляция, t610, RCU stall, USB reset]
tags: [family, how-to, smarthome]
updated: 2026-09-15 (ночь-11: Zigbee — переезд в ZHA НЕ состоялся, ZHA удалена прерванным откатом, Z2M работает; дом в исходном рабочем состоянии)
updated: 2026-09-15 (ночь-12: Zigbee — переезд на ZHA ИДЁТ, ZHA сама приняла 12/16 устройств без перепаривания; Z2M остановлен, данные целы)
---
# 🏠 Домашняя автоматизация
@@ -41,9 +41,9 @@ updated: 2026-09-15 (ночь-11: Zigbee — переезд в ZHA НЕ сост
> 🔴 **Камера сейчас на xHCI (`USB3-1`), Zigbee — на OHCI (`USB1-2`).** Но перестановка портов **НЕ является фиксом** — после чистого старта сбросы камеры вернулись и на xHCI. Причину RCU stall см. §3.1, ограничения диагностики — §3.4, §3.5.
> **ZIGBEE: РАБОТАЕТ НА Z2M (2026-09-15, финал).** Попытка переезда Z2M → ZHA **не состоялась**: ZHA была создана (`reuse_settings`, сеть взята со стика, устройства отвечали), но затем **удалена прерванным скриптом откатa**, а **Z2M запущен заново**. Сейчас: `zigbee2mqtt` **started**, 19 устройств в сети, имена на месте, 16 автоматизаций целы, `modbus-bridge` получает данные. **Потерь нет.**
> 🟡 **ZIGBEE: ИДЁТ ПЕРЕЕЗД НА ZHA (2026-09-15, ночь-12).** ZHA создана повторно (`reuse_settings`, сеть со стика) и 🔑 **САМА приняла 12 из 16 устройств — без перепаривания, без «Add device»**. Z2M **остановлен** (не удалён, данные целы). Осталось: переименовать сущности (блокер — старые id заняты мёртвыми Z2M-двойниками) + разбудить 4 батарейных.
>
> 📌 **Переезд в ZHA — НЕ терминальная задача.** После `reuse_settings` каждое устройство заводится руками в UI («Add device»), 6 батарейных — с кнопкой в руках; REST не отдаёт список устройств ZHA (только WebSocket). Детали, рецепт, разбор ошибок — [[family/tech/zigbee-t610-z2m-i-zha]].
> 📌 **Перепаривание НЕ нужно — подтверждено фактом.** Устройства отвечают координатору, ZHA их принимает по NVRAM-сети. Имена даёт технические (`light.tz3000_*`), т.к. `friendly_name` из Z2M не читает. Рецепт, карта переименования, питфоллы — [[family/tech/zigbee-t610-z2m-i-zha]].
---
@@ -127,7 +127,7 @@ ssh -i ~/.ssh/id_rsa root@192.168.2.176 '<команда>' # аддон core_
|---|---|---|---|---|
| Terminal & SSH | `core_ssh` | SSH | 22 | ✅ started |
| Mosquitto broker | `core_mosquitto` | MQTT | 1883 | ✅ started |
| Zigbee2MQTT | `45df7312_zigbee2mqtt` | Zigbee v2.14.1 | 8485 | ✅ started |
| Zigbee2MQTT | `45df7312_zigbee2mqtt` | Zigbee v2.14.1 | 8485 | **stopped** (2026-09-15 ночь-12 — освобождён стик под ZHA) |
| Node-RED | `a0d7b954_nodered` | вентиляция CO₂ | ingress | ⏸ **stopped** (2026-09-15) |
| mbusd | `local_mbusd` | шлюз Modbus RTU→TCP | 502 | ✅ started |
| modbus-bridge | `local_modbus-bridge` | снифф ZONT-шины | — | ✅ started |
@@ -140,7 +140,7 @@ ssh -i ~/.ssh/id_rsa root@192.168.2.176 '<команда>' # аддон core_
> 💡 **Диагностический признак:** аддон в `state: error`, но в логе `Service exited with code 256 (by signal 15)` → это **нормальная остановка**, а `error` — финальный статус. Читать лог, а не только `state`.
> 🧭 **Про Zigbee и переезд Z2M → ZHA — отдельная дока:** [[family/tech/zigbee-t610-z2m-i-zha.md]]. Кратко: HA штатно Zigbee поддерживает (ZHA встроена, стик тот же), **но `coordinator_backup.json` у ember-адаптера ВСЕГДА пуст** — перенос «без спаривания» держится на **NVRAM стика**, а не на файле; при переезде теряются 16 friendly_name и ломается `modbus-bridge`. **Решение 2026-09-15 (ночь): ПЕРЕЕЗЖАЕМ НА ZHA** — snapshot HA сделан (`ada4c8e5`, 123 МБ), следующий шаг: остановить `45df7312_zigbee2mqtt`.
> 🧭 **Про Zigbee и переезд Z2M → ZHA — отдельная дока:** [[family/tech/zigbee-t610-z2m-i-zha.md]]. Кратко: HA штатно Zigbee поддерживает (ZHA встроена, стик тот же); **`coordinator_backup.json` у ember-адаптера ВСЕГДА пуст** — перенос «без спаривания» держится на **NVRAM стика**, а не на файле. 🔑 **ZHA сама принимает устройства после `reuse_settings`** — «Add device» и окно спаривания НЕ нужны (проверено: 12 из 16 подхватились без действий). Ручного остаётся: **переименовать сущности** (ZHA даёт технические имена `light.tz3000_*`) + **разбудить 4 батарейных**. **Статус на 2026-09-15 ночь-12: Z2M остановлен, ZHA создана, переезд идёт.**
**Опции аддонов** меняются только через Supervisor API (не `ha apps`, который умеет лишь start/stop/rebuild). Для PATCH нужен **ПОЛНЫЙ набор опций**, иначе 400.
+162 -16
View File
@@ -1,10 +1,10 @@
---
title: "Zigbee на t610 — переезд Z2M → ZHA (в работе, 2026-09-15)"
created: '2026-09-15'
updated: '2026-09-15 (ночь-11: ПЕРЕЕЗД НЕ СОСТОЯЛСЯ — ZHA снесена прерванным откатом, Z2M поднят заново и работает. Дом в рабочем состоянии)'
updated: '2026-09-15 (ночь-13: 📋 ПЛАН УТОЧНЁН — три слоя мусора (mqtt / switch_as_x / ZHA), полная карта переименования построена по IEEE, ждём ответа Alex на 3 вопроса)'
type: tech
namespace: family
status: ПЕРЕЕЗД ОТМЕНЁН ФАКТИЧЕСКИ — Z2M работает, ZHA удалена. Дома Zigbee живёт на Z2M, как и было. Дока = рецепт + разбор ошибок, НЕ выполненный план.
status: 🟡 ПЕРЕЕЗД ИДЁТ — ZHA создана, 12 из 16 устройств приняты автоматически. Блокер: entity_id заняты мёртвыми Z2M-двойниками. План из 4 шагов составлен, ожидает подтверждения на удаление мёртвых сущностей.
tags:
- t610
- haos
@@ -21,11 +21,16 @@ related:
- '[[family/plans/t610-backup-to-truenas]]'
---
# Zigbee на t610 — переезд Z2M → ZHA (НЕ СОСТОЯЛСЯ, рецепт сохранён)
# Zigbee на t610 — переезд Z2M → ZHA (история + рабочий рецепт)
> 🚦 **ИТОГОВОЕ СОСТОЯНИЕ (2026-09-15, ФИНАЛ):** переезд **НЕ состоялся**. ZHA была создана (`reuse_settings`, сеть взята со стика — техника подтверждена рабочей), но затем **удалена прерванным скриптом откатa**, а **Z2M запущен заново и работает**. Дом в исходном рабочем состоянии: 19 устройств, имена на месте, 16 автоматизаций целы, `modbus-bridge` получает данные. **Потерь данных нет.**
>
> 🔴 **ЧИТАТЬ ДАЛЬШЕ КАК РЕЦЕПТ И РАЗБОР ОШИБОК, А НЕ КАК ОТЧЁТ О ВЫПОЛНЕННОЙ РАБОТЕ.** Ниже подробно описано, как ZHA поднимается через config flow (`reuse_settings`) — техника рабочая и проверенная. Но переезд **не завершён** и в текущем состоянии **не делается из терминала**: см. §«Почему переезд не доводится из CLI».
> 🚦 **СОСТОЯНИЕ НА 2026-09-15 (ночь-12) — ПЕРЕЕЗД ИДЁТ:**
> - ZHA создана **повторно** (`entry_id` `01M2JP57Y2FGSD17P829HFV44N`, `reuse_settings`), сеть взята со стика.
> - 🔑 **ZHA САМА подхватила 12 из 16 устройств** — **без «Add device», без окна спаривания, без перепаривания**. Это главный факт сессии: перепаривание не нужно вообще.
> - Имена, которые дала ZHA: **технические** (`light.tz3000_5gey1ohx_ts0002_osveshchenie`), потому что `friendly_name` из Z2M она не читает.
> - **Блокер:** старые `entity_id` **заняты мёртвыми Z2M-двойниками** (`unavailable`) → переименовать нельзя, пока они на месте.
> - ⚠️ Z2M **остановлен**, не удалён. Данные целы.
> 🔴 **ЧИТАТЬ ДАЛЬШЕ И КАК РЕЦЕПТ, И КАК РАЗБОР ОШИБОК.** Ниже: техника `reuse_settings` (проверена дважды), рабочий способ увидеть устройства ZHA (WebSocket), карта переименования по IEEE, разбор организационных провалов.
> ❓ **Вопрос Alex (2026-09-15):** «HA штатно поддерживает Zigbee без Z2M? Что нужно, чтобы перенести всё в HA **без заново спаривания**?»
@@ -248,17 +253,144 @@ curl -s -X POST -H "$HDR" -H "Content-Type: application/json" \
---
## 🔴 Почему переезд НЕ доводится из терминала (главный вывод сессии)
## 🔑 ГЛАВНЫЙ ФАКТ СЕССИИ (ночь-12): ZHA САМА подхватывает устройства
Проверка фактом прошла все шаги: snapshot ✅ → stop Z2M ✅ → ZHA `reuse_settings` ✅ → устройства отвечают ✅. **Техника работает.** Переезд всё равно не состоялся, и вот по какой причине:
**Это опровергает вывод предыдущей ночи.** Было записано «нужно заводить каждое устройство через UI → значит не терминальная задача». **Неверно.**
| # | Стена | Суть |
**Проверено фактом** через WebSocket-реестры (`config/entity_registry/list`): после `reuse_settings` ZHA **сама** приняла **12 из 16** устройств, без «Add device», без `zha.permit`, без окна спаривания.
```
light.tz3000_5gey1ohx_ts0002_osveshchenie = off ← office_table_light_switch
light.tz3000_5gey1ohx_ts0002_osveshchenie_3 = on ← light_stairs
light.tz3000_odzoiovu_ts0003_osveshchenie = off ← kitchen_hood
light.tz3000_0e6uvexf_ts0012_osveshchenie = on ← smart_light_office
light.tz3000_3a9beq8a_ts0001 = off ← night_light_shower_2
light.tz3210_nhqka112_ts011f = off ← bed_dimmer
switch.tz3000_gjnozsaz_ts011f = ? ← boiler_controller_power
switch.tz3000_gjnozsaz_ts011f_2 = ? ← recirculation_pump
binary_sensor.zbeacon_ts0207 = ? ← boiler_water_leak
binary_sensor.tze204_qasjif9e_ts0601 = ? ← shower_2_presence_sensor
```
> ⛔ **ОТМЕНЕНО ПРЕЖНЕЕ УТВЕРЖДЕНИЕ «без «Add device» не подхватится».** Подхватилось. Устройства отвечают координатору, ZHA их принимает по NVRAM-сети.
> ⛔ **ОТМЕНЕНО ПРЕЖНЕЕ «переезд — ручная операция в UI».** Ручного заведения **не требуется**. Требуются только: **пробуждение батарейных** и **переименование**.
### Почему подхватилось (механика)
```
стик хранит сеть в NVRAM (ключ, PAN, канал)
ZHA стартует на том же стике, reuse_settings
устройства УЖЕ в сети, ключи совпали → отвечают координатору
ZHA их принимает и создаёт сущности — сама, без спаривания
имена даёт ТЕХНИЧЕСКИЕ (modelId_manufName), friendly_name из Z2M не читает
```
### Кто НЕ подхватился — 4 устройства, все батарейные (спят)
| IEEE | friendly_name | Почему нет |
|---|---|---|
| 1 | **Интервью = физическая работа** | После `reuse_settings` ZHA слышит устройства, но не знает их IEEE. Каждое заводится через UI: **«Add device»**, а 6 батарейных `EndDevice`**разбудить кнопкой в руках**. Из терминала не делается вообще. |
| 2 | **REST не даёт увидеть результат** | `device_registry` и сервисы ZHA — **только WebSocket**. Через REST видны лишь `/api/states` (сущности) и `/api/config/config_entries/*` (сама интеграция). Проверить «сколько устройств подхватилось» из CLI невозможно. |
| 3 | **Имена и автоматизации переносятся руками** | 16 friendly names живут в `database.db` (Z2M-формат), ZHA их не читает. Все ссылки вида `switch.0xa4c138f8da8bc478` в 16 автоматизациях и в `modbus-bridge` сломаются и требуют переписывания. |
| `0xa4c13862d39377e6` | office_temperature_sensor | EndDevice, спит |
| `0xa4c1386d40ddb67b` | light_sensor_stairs | EndDevice, спит |
| `0xa4c13882a4b42db0` | bed_dimmer | давно молчит (Router, но не отчитался) |
| `0xa4c138b0f9e674a5` | wireless_light_switch_bed | EndDevice, спит |
> 🔴 **Следствие: переезд Z2M → ZHA — НЕ терминальная задача, а ручная операция в UI.** Агент может подготовить (snapshot, стоп Z2M, config flow, диагностика логов), но **не может довести**. Планировать как «полчаса в CLI» нельзя — это час-два у клавиатуры с кнопками в руках.
> 📌 Разбудить кнопкой — **это не перепаривание**, сети они уже принадлежат. 12 из 16 подхватились вообще без действий.
---
## 🔴 БЛОКЕР (ночь-12): старые `entity_id` заняты мёртвыми двойниками
ZHA создала **новые** сущности **рядом** со старыми, а не вместо них:
```
light.smart_light_office ← СТАРАЯ (Z2M), unavailable, мусор
light.tz3000_0e6uvexf_ts0012_osveshchenie ← НОВАЯ (ZHA), работает
```
Оба набора висят одновременно. Автоматизации и `modbus-bridge` ссылаются на **старые** → бьют в пустоту.
**Переименовать нельзя:** при попытке `config/entity_registry/update``new_entity_id` маркируется **[СТАРОЕ ЗАНЯТО]`** (9 из 16 позиций).
> 🔴 **Порядок обязателен: сначала удалить мёртвые Z2M-сущности, потом переименовывать ZHA-сущности в освободившиеся id.**
> ⚠️ Удаление сущностей **необратимо** — только по явной команде Alex.
### Карта переименования (составлена по IEEE, готова к применению)
| ZHA entity_id (текущий) | → целевой (= старый Z2M) |
|---|---|
| `light.tz3000_3a9beq8a_ts0001` | `light.night_light_shower_2` |
| `light.tz3000_0e6uvexf_ts0012_osveshchenie` | `light.smart_light_office_left` |
| `light.tz3000_0e6uvexf_ts0012_osveshchenie_2` | `light.smart_light_office_right` |
| `light.tz3000_5gey1ohx_ts0002_osveshchenie` | `light.office_table_light_switch_l1` |
| `light.tz3000_5gey1ohx_ts0002_osveshchenie_2` | `light.office_table_light_switch_l2` |
| `light.tz3000_5gey1ohx_ts0002_osveshchenie_3` | `light.smart_light_stairs_l1` |
| `light.tz3000_5gey1ohx_ts0002_osveshchenie_4` | `light.smart_light_stairs_l2` |
| `light.tz3000_odzoiovu_ts0003_osveshchenie` | `light.kitchen_hood_l1` |
| `light.tz3000_odzoiovu_ts0003_osveshchenie_2` | `light.kitchen_hood_l2` |
| `light.tz3000_odzoiovu_ts0003_osveshchenie_3` | `light.kitchen_hood_l3` |
| `switch.tz3000_gjnozsaz_ts011f_2` | `switch.recirculation_pump` |
| `switch.tz3210_nhqka112_ts011f` | `light.bed_dimmer` |
| `switch.tz3000_gjnozsaz_ts011f_3` | `switch.heating_cable_plug` |
| `switch.tz3000_gjnozsaz_ts011f` | `switch.boiler_controller_power` |
| `binary_sensor.zbeacon_ts0207` | `binary_sensor.boiler_water_leak_water_leak` |
| `binary_sensor.tze204_qasjif9e_ts0601` | `binary_sensor.shower_2_presence_sensor_presence` |
> ⚠️ **Сопоставление по IEEE, не по названию!** Три устройства имеют одинаковый `manufName _TZ3000_gjnozsaz` / `modelId TS011F` (`recirculation_pump`, `heating_cable_plug`, `boiler_controller_power`) — различить можно **только по IEEE**. Суффиксы `_2`/`_3` у ZHA не означают «второй канал» — это сквозная нумерация конфликтующих имён.
**Скрипт:** `~/tmp-t610/rename.py` (WS API, есть `--apply`), карта — `~/tmp-t610/rename-map.json`, построение по IEEE — `~/tmp-t610/map-full.py`.
---
## 🔑 Рабочий способ УВИДЕТЬ устройства ZHA (WebSocket, не REST)
> 🔴 **REST НЕ ДАЁТ реестры:** `GET /api/config/device_registry/list` и `/api/config/entity_registry/list` → **`404 Not Found`**. Это **WebSocket**-методы. Предыдущий вывод «из CLI не увидеть, сколько подхватилось» — **следствие этой ошибки**, а не ограничение.
**Рабочий скрипт** (`~/tmp-t610/ws-mac.py` + `map-ids.py`) — запускать **на Mac**, не на t610:
```python
# ~/tmp-t610/ws-mac.py
import json, websocket
TOKEN = open("/Users/admin/tmp-t610/ha_token.txt").read().strip()
URL = "ws://192.168.2.176/api/websocket" # 🔴 порт 80, БЕЗ :8123
ws = websocket.create_connection(URL, timeout=30)
ws.recv() # auth_required
ws.send(json.dumps({"type": "auth", "access_token": TOKEN}))
assert json.loads(ws.recv()).get("type") == "auth_ok"
ws.send(json.dumps({"id": 1, "type": "config/entity_registry/list"}))
entities = json.loads(ws.recv())
ws.send(json.dumps({"id": 2, "type": "config/device_registry/list"}))
devices = json.loads(ws.recv())
json.dump({"entities": entities, "devices": devices},
open("/Users/admin/tmp-t610/registries.json", "w"), ensure_ascii=False)
```
Результат: `entities: 624`, `devices: 52`.
> 🔴 **`python3` на t610 НЕТ** (`python3: command not found`). Скрипты реестров запускать **на Mac**.
> 🔴 **Нужен пакет `websocket-client`:** `/usr/bin/python3 -m pip install websocket-client` (HA-шный `websockets` может отсутствовать).
> 🔴 **HA WebSocket — порт 80:** `ws://192.168.2.176/api/websocket`. С `:8123` → ошибка соединения.
### Как сопоставить ZHA-устройство со старым именем (по IEEE)
```python
# device_registry → identifiers вида [["zha", "a4:c1:38:0e:6u:ve:xf:..."]] ← двоеточия!
for d in devices:
for dom, val in (d.get("identifiers") or []):
if dom == "zha":
key = str(val).lower().replace(":", "").replace("0x", "")
```
> 🔴 **IEEE в реестре — с двоеточиями** (`a4:c1:38:...`), в Z2M-конфиге — `0xa4c138...`. Нормализовать обязательно, иначе сопоставление даёт 0 совпадений.
### Отозвано: «режим спаривания поможет»
`zha.permit` **не нужен** и не помогает — устройства уже в сети, они не «подключаются», их принимает координатор. **Не открывать окно спаривания** для этой задачи.
---
### 🔴 Что пошло не так организационно (разбор ошибок, читать перед повтором)
@@ -296,11 +428,11 @@ unavailable: 8 — и НИ ОДНА не Zigbee:
| 2 | **Все автоматизации с `switch.0xa4c138f8da8bc478` и подобными** | `entity_id` в ZHA будут другие → переписать все ссылки |
| 3 | **`modbus-bridge`** | жёстко завязан на Zigbee-сущность `switch.0xa4c138f8da8bc478` (relay slave 104) — сломается |
**Решение 2026-09-15 (НОЧЬ, ФИНАЛЬНОЕ): переезд на ZHA НЕ СОСТОЯЛСЯ.** Alex задачу ставил прямо: «заменить Z2M на ZHA, устройства не спаривать заново». Техника была отработана и подтверждена (`reuse_settings` → сеть со стика → устройства отвечают), **но переезд не доведён**: ZHA удалена прерванным откатом, Z2M работает.
**Решение 2026-09-15 (НОЧЬ-12, текущее): ПЕРЕЕЗД ИДЁТ.** Alex задачу поставил прямо: «заменить Z2M на ZHA, устройства не спаривать заново» + «БЕЗ ПОТЕРЬ». Техника отработана, **12 из 16 устройств приняты ZHA автоматически**, перепаривание не потребовалось вообще. Осталось: переименовать сущности (блокер — мёртвые двойники) и разбудить 4 батарейных.
> ⚠️ **Статус: ОТКРЫТЫЙ ВОПРОС, не «отменено».** Дом живёт на Z2M. Вернуться к ZHA можно, но только как ручная операция в UI — см. §«Почему переезд не доводится из терминала». Перед повтором обязательно прочитать §«Что пошло не так организационно».
> ⚠️ **Статус: В РАБОТЕ.** Z2M **остановлен**, не удалён — данные целы как страховка. Перед продолжением обязательно прочитать §«Что пошло не так организационно».
> ✅ **ФАКТ (проверено):** переезд без перепаривания **технически возможен**. ZHA создана стратегией `reuse_settings`, сеть поднята со стика, устройства **отвечали** (`Unknown device AddrModeAddress` в логе — ключи совпали). Ни одно устройство не спаривалось заново. Стена — не в технике, а в объёме ручной работы после.
> ✅ **ФАКТ (проверено дважды):** переезд без перепаривания **работает**. ZHA создана стратегией `reuse_settings`, сеть поднята со стика, **12 устройств приняты автоматически** с техническими именами. Ни одно устройство не спаривалось заново. Блокер — не техника, а **занятые entity_id**.
> ❌ **Отменено прежнее решение «Z2M остаётся, выигрыш 0»** — Alex его отверг: HA штатно поддерживает Zigbee, и он хочет убрать Z2M как отдельный слой. Причина переезда — архитектурная, не функциональная.
@@ -372,6 +504,12 @@ state.json MD5 20bfb775cbab002e59d1be31a15db9e6
| `restore-z2m.sh` | ✅ `start` аддона Z2M + проверка `state` + лог |
| `check-final.sh` | ✅ итоговая проверка: unavailable, modbus-bridge, Z2M-публикации |
| `state-now.sh`, `diag2.sh`, `diag3.sh`, `zha-recreate-1.sh` | диагностика состояния |
| `mig-1-stop-z2m.sh` | ✅ повторный стоп Z2M (ночь-12) |
| `mig-2-zha.sh`, `mig-3-zha.sh` | ✅ повторный config flow ZHA → `reuse_settings` (ночь-12), entry `01M2JP57Y2FGSD17P829HFV44N` |
| **`ws-mac.py`** | 🔑 **Windows-скрипт реестров HA по WebSocket — запускать на MAC.** Пишет `registries.json` (624 сущности, 52 устройства) |
| **`map-full.py`** | 🔑 построение карты по IEEE: ZHA entity ↔ старое Z2M-имя → `rename-map.json` |
| **`rename.py`** | 🔑 переименование сущностей через `config/entity_registry/update`. **Dry-run по умолчанию, `--apply` для применения.** Карта зашита в скрипт |
| `zha-l1.sh`, `zha-reg.sh`, `zha-reg2.sh` | ⚠️ диагностика (часть даёт 404 — REST не отдаёт реестры) |
> 🔴 **ПИТФОЛЛ ПРЕРЫВАНИЯ (главный урок сессии):** `rollback.sh` был прерван на середине **дважды** — один раз успел выполнить `DELETE` config entry ZHA (снёс интеграцию), но не дошёл до `start` Z2M. Система оказалась в подвешенном состоянии. **Правило: скрипты, меняющие состояние, писать с проверкой состояния на входе и идемпотентно** — чтобы повторный запуск после прерывания доделывал, а не ломал.
>
@@ -399,6 +537,14 @@ state.json MD5 20bfb775cbab002e59d1be31a15db9e6
12. 🔴 **`POST` без `-H "Content-Type: application/json"`** → пустой ответ, выглядит как «молчание сервера».
13. ✅ **`Unknown device AddrModeAddress(NWK, 0x…)` в логе zigpy — ПОЛОЖИТЕЛЬНЫЙ сигнал**, не ошибка: сеть поднята, ключи совпали, идёт интервью.
14. ⛔ **В мастере ZHA НИКОГДА не выбирать `form_new_network`** — создаст новую сеть и осиротит все 16 устройств. Только **`reuse_settings`**.
15. 🔑 **ZHA САМА принимает устройства после `reuse_settings`** — «Add device» и `zha.permit` **НЕ НУЖНЫ**. 12 из 16 подхватились без единого действия. НЕ открывать окно спаривания.
16. 🔴 **REST `GET /api/config/device_registry/list` и `/api/config/entity_registry/list` → `404`.** Только WebSocket (`config/entity_registry/list`). Раньше из этого делался ложный вывод «проверить из CLI нельзя».
17. 🔴 **HA WebSocket — порт 80:** `ws://192.168.2.176/api/websocket`. С `:8123` не соединяется. Пакет `websocket-client` (не `websockets`).
18. 🔴 **`python3` на t610 НЕТ.** Скрипты реестров/переименования запускать **на Mac**.
19. 🔴 **IEEE в `device_registry` — с двоеточиями** (`a4:c1:38:…`), в Z2M-конфиге — `0xa4c138…`. Нормализовать (`.replace(":", "").replace("0x", "")`), иначе 0 совпадений.
20. 🔴 **`config/entity_registry/update` не переименует в занятый `entity_id`.** Пока мёртвые Z2M-сущности на месте — 9 из 16 переименований заблокированы. Порядок: удалить мёртвые → переименовать.
21. ⚠️ **Суффиксы `_2`/`_3` у ZHA — не «второй канал», а сквозная нумерация конфликтующих имён.** Три разных устройства с `_TZ3000_gjnozsaz`/`TS011F` различаются **только по IEEE**.
22. ⚠️ **`zha.permit` для этой задачи бесполезен** — устройства уже в сети, они не «подключаются».
---