[2026-09-15] eagle: family/tech/zigbee-t610-z2m-i-zha.md
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
---
|
||||
title: "Zigbee на t610 — переезд Z2M → ZHA (выполнен, 2026-09-15)"
|
||||
created: '2026-09-15'
|
||||
updated: '2026-09-15 (ночь-15: найдена причина «кнопка не свитчит диммер» — `select.bed_dimmer_*` висят на чужом устройстве `sauna`; `light.bed_dimmer` не существует; `database.db` подтверждён как первоисточник)'
|
||||
updated: '2026-09-15 (ночь-15, доп. 2: ✅ `light_sensor_stairs` ДОБАВИЛСЯ — ZHA 17 устройств, 16/16; сущности датчика переименованы; 🔴 обнаружены ещё 2 битых автоматизации диммера с `triggers: []` и чужой `device_id`; `event.*` кнопки спальни — так и не появился при 90-секундном слушании шины)'
|
||||
type: tech
|
||||
namespace: family
|
||||
status: 🟡 ZHA работает, 15/16 устройств. Найден и разобран корень «кнопка спальни не свитчит диммер» (имена ушли не тем устройствам). Осталось: фикс имён (`light.bed_dimmer`) + 4 автоматизации + `light_sensor_stairs`.
|
||||
status: 🟢 ZHA работает, 16/16 устройств, ВСЕ батарейные подхвачены. Имена `light.bed_dimmer`/`switch.sauna` исправлены, сущности датчика лестницы переименованы. Осталось: `event.*` кнопки спальни (нажатие не долетело), 2 автоматизации диммера с пустыми триггерами + чужими entity_id, косметика `select.bed_dimmer_*`.
|
||||
tags:
|
||||
- t610
|
||||
- haos
|
||||
@@ -23,16 +23,24 @@ related:
|
||||
|
||||
# Zigbee на t610 — переезд Z2M → ZHA (история + рабочий рецепт)
|
||||
|
||||
> 🚦 **СОСТОЯНИЕ НА 2026-09-15 (ночь-15) — ZHA РАБОТАЕТ, ИДЁТ ДОЧИСТКА ИМЁН:**
|
||||
> - ✅ **Три слоя мусора удалены:** 127 сущностей `platform=mqtt` + 18 устройств-призраков Z2M. Реестр: 624 → 493 сущности, 52 → 34 устройства.
|
||||
> 🚦 **СОСТОЯНИЕ НА 2026-09-15 (ночь-15, ФИНАЛ) — ZHA РАБОТАЕТ, 16/16 УСТРОЙСТВ:**
|
||||
|
||||
```
|
||||
a4c1386d40ddb67b light_sensor_stairs EndDevice last_seen 20:46:51 ← ✅ ДОБАВИЛСЯ
|
||||
ZHA devices: 17 (16 + координатор)
|
||||
```
|
||||
> - ✅ **`light_sensor_stairs` ДОБАВИЛСЯ** — Alex поставил датчик в режим спаривания **несколько раз**, на третьей попытке устройство долетело. `device_id f33b36fbaec7b1eabca7a7e496be89f4`, `name_by_user=light_sensor_stairs`, зона `lestnitsa`. Шлёт данные потоком: освещённость 3…440 lx, батарея 100%. См. §Факт 6 (ОБНОВЛЁН).
|
||||
> - ✅ **Сущности датчика переименованы** в человеческие id: `sensor.light_sensor_stairs_illuminance`, `_battery`, `_temperature`, `_humidity` (все `success: true`).
|
||||
> - ✅ **Дополнительно найдены и подтверждены 2 битых автоматизации диммера** — `Toggle Dimmer bed` и `Dimmer bed cycle` с `triggers: []` (пустые!). См. §Факт 9.
|
||||
> - 🔴 **`event.*` кнопки спальни ТАК И НЕ ПОЯВИЛСЯ.** Слушал шину HA (`subscribe_events`: `zha_event` + `state_changed`) 90 секунд после просьбы нажать кнопку — **ни одного события**. Нажатие не долетело до координатора. См. §Факт 5.
|
||||
> - 🟡 **Три слоя мусора удалены:** 127 сущностей `platform=mqtt` + 18 устройств-призраков Z2M. Реестр: 624 → 493 сущности, 52 → 34 устройства.
|
||||
> - ✅ **13 modbus-датчиков СОХРАНЕНЫ** (проверено фактом: пишут данные) — они тоже `platform=mqtt`, но живые.
|
||||
> - ✅ **51 операция переименования сущностей:** 42 выполнены, 8 отбиты (`light`→`switch` запрещён HA), 1 пропущена.
|
||||
> - ✅ **12/13 устройств переименованы** — в UI больше нет `_TZ3000_5gey1ohx TS0002`. Это то, что Alex видел руками. (13-е, `office_temperature_sensor`, проснулось и переименовано отдельно.)
|
||||
> - ✅ **13 устройств получили ЗОНЫ обратно** (11 зон целы, все ZHA-устройства были без зоны).
|
||||
> - ✅ **Автоматизации: 12 из 16 живых** — пересобраны на ZHA `device_id` + `entity_id`.
|
||||
> - 🔴 **НОЧЬ-15 — найдена причина «кнопка в спальне не свитчит диммер»:** `select.bed_dimmer_*` привязаны к **чужому** устройству (`sauna`, `700e14b7…`), а `light.bed_dimmer` **не существует** — ZHA дала `light.tz3000_ooc8illt_ts0052`. См. §НОЧЬ-15.
|
||||
> - 🔴 **НОЧЬ-15 — `light_sensor_stairs` ОТОЗВАЛ вывод «не подхватился»:** устройство **в сети и привязано к координатору ZHA** (`iasCieAddr 0x0ceff6fffe9339f2`, `lastSeen` после миграции). Сущностей нет — EndDevice спит, значение освещённости не менялось.
|
||||
> - ⏳ **Осталось:** фикс имён кнопки спальни; 4 автоматизации на 2 батарейных.
|
||||
> - ✅ **13/13 устройств переименованы** — в UI больше нет `_TZ3000_5gey1ohx TS0002`.
|
||||
> - ✅ **13 устройств получили ЗОНЫ обратно** + `light_sensor_stairs` → `lestnitsa`.
|
||||
> - ✅ **Имена исправлены фактом:** `light.tz3000_ooc8illt_ts0052` → **`light.bed_dimmer`**, `switch.tz3210_nhqka112_ts011f` → **`switch.sauna`** (оба `success: true`, проверены чтением состояния).
|
||||
> - 🔴 **ИСПРАВЛЕНА НЕВЕРНАЯ ЗАПИСЬ ЭТОГО ДОКА:** полсуток было записано наоборот, что `700e14b7…` = `bed_dimmer`. **Верно: `700e14b7…` = `sauna` (`_TZ3210_nhqka112 TS011F`), `e230c12e…` = `bed_dimmer` (`_TZ3000_ooc8illt TS0052`).** См. §Факт 7.
|
||||
> - ⏳ **Осталось:** `event.*` кнопки спальни (нажатие не долетело до координатора — разбираться с кнопкой физически); 2 автоматизации диммера (`triggers: []` + чужой `device_id`); `Вкл/Выкл ночной свет душевая` (чужой `device_id fd52114b…`); 2 battery-автоматизации со старыми id; косметика `select.bed_dimmer_*`.
|
||||
> - ⚠️ Z2M **остановлен**, не удалён. Данные целы в `/config/zigbee2mqtt/`.
|
||||
|
||||
> 🔴 **ЧИТАТЬ ДАЛЬШЕ И КАК РЕЦЕПТ, И КАК РАЗБОР ОШИБОК.** Ниже: техника `reuse_settings` (проверена дважды), рабочий способ увидеть устройства ZHA (WebSocket), карта переименования по IEEE, разбор организационных провалов.
|
||||
@@ -81,7 +89,7 @@ bedroom bed_dimmer, wireless_light_switch_bed kitchen kitchen_hood
|
||||
| `0xa4c13862d39377e6` | office_temperature_sensor |
|
||||
| `0xa4c138f8da8bc478` | recirculation_pump |
|
||||
| `0x84fd27fffed9e137` | night_light_shower_2 |
|
||||
| `0xa4c1386d40ddb67b` | light_sensor_stairs — ❌ НЕ подхвачен ZHA |
|
||||
| `0xa4c1386d40ddb67b` | light_sensor_stairs — ✅ **ПОДХВАЧЕН** (ночь-15, 3-я попытка режима спаривания) |
|
||||
| `0xa4c1381186ed1a32` | smart_light_office |
|
||||
| `0xa4c13873b5c1575b` | office_table_light_switch |
|
||||
| `0xa4c13807b64c7fd4` | kitchen_hood |
|
||||
@@ -95,7 +103,7 @@ bedroom bed_dimmer, wireless_light_switch_bed kitchen kitchen_hood
|
||||
| `0xa4c1381694217e10` | boiler_controller_power |
|
||||
| `0xa4c138c650636cf6` | toilet_1_floor_temperature |
|
||||
|
||||
> ✅ **Сверка 2026-09-15 (ночь-15): 15 из 16 устройств в HA совпадают с истинной картой, `mismatches: 0`.** Отсутствует только `light_sensor_stairs` (батарейный, спит).
|
||||
> ✅ **Сверка 2026-09-15 (ночь-15, финал): 16 из 16 устройств в HA — ВСЕ на месте.** `light_sensor_stairs` добавлен последним (3-я попытка режима спаривания, §Факт 6). ZHA: **17 записей = 16 устройств + координатор**.
|
||||
|
||||
### Зоны (первоначальная выдача)
|
||||
|
||||
@@ -106,15 +114,18 @@ bedroom bed_dimmer, wireless_light_switch_bed kitchen kitchen_hood
|
||||
**Работают** (пересобраны на ZHA `device_id` + `entity_id`):
|
||||
циркуляция ГВС вкл/выкл (по времени), office_pass_switch_table/main, ночной свет душевая вкл/выкл, протечка котельная, датчик протечки батарея, Zigbee T sensor батарея, toggle dimmer bed, increase dimmer bed brightness, ventilation automation.
|
||||
|
||||
**Ждут пробуждения устройств (4 шт.):**
|
||||
| Автоматизация | Нужно устройство |
|
||||
|---|---|
|
||||
| `svetlo_vykl_osveshchenie_lestnitsy` | `light_sensor_stairs` |
|
||||
| `temno_vkl_podsvetku_lestnitsy` | `light_sensor_stairs` |
|
||||
| `datchik_osveshchennosti_lestnitsa_batareia` | `light_sensor_stairs` |
|
||||
| `light_switch_bed_batareia` | `wireless_light_switch_bed` |
|
||||
**Ждут пробуждения устройств (ОБНОВЛЕНО ночь-15, финал — осталось 1):**
|
||||
| Автоматизация | Нужно устройство | Статус |
|
||||
|---|---|---|
|
||||
| `svetlo_vykl_osveshchenie_lestnitsy` | `light_sensor_stairs` | 🟢 устройство ЕСТЬ → проверить, ожила ли |
|
||||
| `temno_vkl_podsvetku_lestnitsy` | `light_sensor_stairs` | 🟢 устройство ЕСТЬ → проверить |
|
||||
| `datchik_osveshchennosti_lestnitsa_batareia` | `light_sensor_stairs` | 🟢 устройство ЕСТЬ → проверить |
|
||||
| `light_switch_bed_batareia` | `wireless_light_switch_bed` | 🔴 всё ещё `unavailable` — кнопка не срабатывает (§Факт 5-бис) |
|
||||
|
||||
> 📌 Разбудить кнопкой (паринг-кнопка 1 сек) — подхватятся сами. Это НЕ перепаривание.
|
||||
> ✅ **ОБНОВЛЕНО ночью-15 (финал):** `light_sensor_stairs` **добавлен**, три автоматизации лестницы разблокированы. Замер после добавления: **11 из 16 автоматизаций `on`**, 4 `unavailable`. Проверить `last_triggered` у лестничных после следующего изменения освещённости.
|
||||
> 📌 **Разбудить кнопкой (паринг-кнопка 1 сек)** — подхватятся сами. Это НЕ перепаривание.
|
||||
> 🔴 **УТОЧНЕНО ночью-15:** `wireless_light_switch_bed` **в ZHA есть** (16 устройств), но нажатие **не долетает** (слушали шину 90 с — ноль событий, §Факт 5-бис). Нужно доставить до координатора режимом спаривания.
|
||||
> 🔴 **Для `toggle_dimmer_bed` / `increase_dimmer_bed_brightness`:** они триггерятся от кнопки. Пока `event.*` не появился — мертвы, даже если `light.bed_dimmer` существует и переименован.
|
||||
|
||||
#### Как пересобирались автоматизации (рабочий рецепт)
|
||||
|
||||
@@ -427,14 +438,16 @@ ZHA их принимает и создаёт сущности — сама, б
|
||||
имена даёт ТЕХНИЧЕСКИЕ (modelId_manufName), friendly_name из Z2M не читает
|
||||
```
|
||||
|
||||
### Кто НЕ подхватился — 4 устройства (ночь-13, уточнено)
|
||||
### Кто НЕ подхватился — 4 устройства (ночь-13; ✅ ВСЕ ПОДХВАЧЕНЫ к ночи-15 финалу)
|
||||
|
||||
| IEEE | friendly_name | Почему нет |
|
||||
|---|---|---|
|
||||
| `0xa4c13862d39377e6` | office_temperature_sensor | EndDevice, спит |
|
||||
| `0xa4c1386d40ddb67b` | light_sensor_stairs | EndDevice, спит |
|
||||
| `0xa4c13882a4b42db0` | **sauna** | Router, но давно молчит |
|
||||
| `0xa4c138b0f9e674a5` | wireless_light_switch_bed | EndDevice, спит |
|
||||
> ✅ **ИТОГ ночь-15 (финал): ВСЕ 16 устройств в ZHA.** Ниже — историческая таблица «кто отставал». `office_temperature_sensor`, `sauna` и `light_sensor_stairs` подхватились позже; `wireless_light_switch_bed` в реестре есть, но **нажатие не долетает** (§Факт 5-бис).
|
||||
|
||||
| IEEE | friendly_name | Почему нет (ночь-13) | Итог |
|
||||
|---|---|---|---|
|
||||
| `0xa4c13862d39377e6` | office_temperature_sensor | EndDevice, спит | ✅ подхвачен |
|
||||
| `0xa4c1386d40ddb67b` | light_sensor_stairs | EndDevice, спит | ✅ подхвачен (3-я попытка режима спаривания) |
|
||||
| `0xa4c13882a4b42db0` | **bed_dimmer** | Router, но давно молчит | ✅ подхвачен (`light.bed_dimmer`) |
|
||||
| `0xa4c138b0f9e674a5` | wireless_light_switch_bed | EndDevice, спит | ⚠️ в реестре есть, нажатие НЕ проходит |
|
||||
|
||||
> 🔴 **ИСПРАВЛЕНО ночью-13.** В ночи-12 здесь ошибочно стоял `bed_dimmer` как «Router, но не отчитался». **Неверно:** `bed_dimmer` (`0xa4c1384fbe0b3a6b`) **подхватился** — в ZHA он `switch.tz3210_nhqka112_ts011f` с 7 сущностями. А вот **`sauna`** (`0xa4c13882a4b42db0`) действительно отсутствует, хотя в инвентаре числится Router'ом.
|
||||
> ⚠️ Урок: тип «Router/EndDevice» в инвентаре выше — из Z2M-конфига и **не гарантирует присутствие**. Проверять фактом (WebSocket-реестр), а не по типу.
|
||||
@@ -497,7 +510,8 @@ ZHA их принимает и создаёт сущности — сама, б
|
||||
| `switch.tz3000_gjnozsaz_ts011f_2` | `switch.recirculation_pump` | `a4c138f8da8bc478` | ✅ 🔴 **на нём modbus-bridge** |
|
||||
| `switch.tz3000_gjnozsaz_ts011f_3` | `switch.heating_cable_plug` | `a4c138eb6fbe9d19` | ✅ |
|
||||
| `switch.tz3000_gjnozsaz_ts011f` | `switch.boiler_controller_power` | `a4c1381694217e10` | ✅ |
|
||||
| `switch.tz3210_nhqka112_ts011f` | `light.bed_dimmer` | `a4c1384fbe0b3a6b` | ✅ ⚠️ класс switch→light |
|
||||
| `switch.tz3210_nhqka112_ts011f` | `switch.sauna` | `a4c1384fbe0b3a6b` | ✅ 🔴 **исправлено ночью-15** (ранее ошибочно `light.bed_dimmer`) — IEEE `4fbe0b3a6b` = **sauna** |
|
||||
| `light.tz3000_ooc8illt_ts0052` | `light.bed_dimmer` | `a4c13882a4b42db0` | ✅ 🔴 **исправлено ночью-15** (ранее ошибочно `switch.tz3210_nhqka112_ts011f`) — IEEE `82a4b42db0` = **bed_dimmer** |
|
||||
| `binary_sensor.zbeacon_ts0207` | `binary_sensor.boiler_water_leak_water_leak` | `a4c1383d5fcaa063` | ✅ |
|
||||
| `binary_sensor.tze204_qasjif9e_ts0601` | `binary_sensor.shower_2_presence_sensor_presence` | `a4c138c4a94a6a31` | ✅ |
|
||||
|
||||
@@ -576,7 +590,8 @@ ZHA их принимает и создаёт сущности — сама, б
|
||||
| `4540b3e9bbb43d90f2ff4f62fa09804e` | `_TZ3000_5gey1ohx TS0002` | `office_table_light_switch` |
|
||||
| `200ea4fb25daaa907279045e47a330b5` | `_TZ3000_odzoiovu TS0003` | `kitchen_hood` |
|
||||
| `c18eb99f487691cb7244cd520bfbcde8` | `_TZ3000_5gey1ohx TS0002` | `light_stairs` |
|
||||
| `700e14b7d1710526b00f098b8506826d` | `_TZ3210_nhqka112 TS011F` | `bed_dimmer` |
|
||||
| `700e14b7d1710526b00f098b8506826d` | `_TZ3210_nhqka112 TS011F` | `sauna` — 🔴 **исправлено ночью-15** (было ошибочно `bed_dimmer`) |
|
||||
| `e230c12e6cb45492408ddba6456b6444` | `_TZ3000_ooc8illt TS0052` | `bed_dimmer` — 🔴 **исправлено ночью-15** (было ошибочно `sauna`) |
|
||||
| `c9d62c9d04a231c4642c705088633121` | `_TZE204_qasjif9e TS0601` | `shower_2_presence_sensor` |
|
||||
| `39771e837372d488a1145ab7316fbd23` | `Zbeacon TS0207` | `boiler_water_leak` |
|
||||
| `dc5f276b6d5f6e4564a3a4ddc1b7a1c9` | `_TZ3000_gjnozsaz TS011F` | `heating_cable_plug` |
|
||||
@@ -604,7 +619,7 @@ ZHA их принимает и создаёт сущности — сама, б
|
||||
| `kotelnaia` Котельная | recirculation_pump, boiler_controller_power, heating_cable_plug, boiler_water_leak |
|
||||
| `kabinet` Кабинет | office_table_light_switch, smart_light_office |
|
||||
| `dushevaia` Душевая | night_light_shower_2, shower_2_presence_sensor |
|
||||
| `lestnitsa` Лестница | light_stairs |
|
||||
| `lestnitsa` Лестница | light_stairs, **light_sensor_stairs** ✅ (добавлен ночь-15) |
|
||||
| `tualet` Туалет | toilet_1_floor_temperature |
|
||||
| `bedroom` Спальня | bed_dimmer |
|
||||
| `kitchen` Кухня | kitchen_hood |
|
||||
@@ -789,9 +804,10 @@ unavailable: 8 — и НИ ОДНА не Zigbee:
|
||||
| `0xa4c13873b5c1575b` | office_table_light_switch | TS0002 | Router |
|
||||
| `0xa4c13807b64c7fd4` | kitchen_hood | TS0003 | Router |
|
||||
| `0xa4c1386d0839706a` | light_stairs | TS0002 | Router |
|
||||
| `0xa4c138eb6fbe9d19` | **sauna** (в ZHA ✅ есть, `switch.tz3210_nhqka112_ts011f`) | TS011F | Router |
|
||||
| `0xa4c138b0f9e674a5` | wireless_light_switch_bed | TS0041 | EndDevice (батарея) |
|
||||
| `0xa4c13882a4b42db0` | **bed_dimmer** (в ZHA ✅ есть, `light.tz3000_ooc8illt_ts0052`) | TS0052 | Router |
|
||||
| `0xa4c138eb6fbe9d19` | heating_cable_plug | TS011F | Router |
|
||||
| `0xa4c1384fbe0b3a6b` | **sauna** (в ZHA ✅ `switch.sauna`, `700e14b7…`) | TS011F | Router — 🔴 `_TZ3210_nhqka112` |
|
||||
| `0xa4c138b0f9e674a5` | wireless_light_switch_bed | TS0041 | EndDevice (батарея) — 🔴 **нет `event.*`, кнопка не свитчит** |
|
||||
| `0xa4c13882a4b42db0` | **bed_dimmer** (в ZHA ✅ `light.bed_dimmer`, `e230c12e…`) | TS0052 | Router — 🔴 `_TZ3000_ooc8illt` |
|
||||
| `0xa4c138c4a94a6a31` | shower_2_presence_sensor (TS0601 = mmWave присутствие ✅) | TS0601 | Router (mmWave) |
|
||||
| `0xa4c1381694217e10` | boiler_controller_power | TS011F | Router |
|
||||
| `0xa4c1383d5fcaa063` | boiler_water_leak | TS0207 | EndDevice |
|
||||
@@ -891,6 +907,11 @@ state.json MD5 20bfb775cbab002e59d1be31a15db9e6
|
||||
39. 🔴 **`ha_ws.py` падает с `FileNotFoundError: /tmp/.hatok`** — токен там не переживает очистку `/tmp`. Восстановление: `grep -o 'eyJ[A-Za-z0-9._-]*' ha_token.txt | head -1 > /tmp/.hatok`.
|
||||
40. ⚠️ **`ha_ws.py find <подстрока>`** — рабочий способ найти `device_id` + список сущностей устройства по IEEE без двоеточий. Быстрее, чем гонять полные реестры.
|
||||
41. 🔴 **`config/entity_registry/update` может ответить успехом, не применив значение** — после каждой правки **читать реестр обратно**. (Общий питфолл HA REST/WS — тот же, что у automation config.)
|
||||
42. 🔴 **Кнопка, переехавшая с Z2M на ZHA, ТЕРЯЕТ механизм нажатия.** В Z2M кнопка TS0041 отдавала `action` в MQTT-топик → автоматизация триггерилась по `platform: mqtt`. В ZHA нажатие приходит как `zha_event`, и HA создаёт из него сущность **`event.*`** — **при первом событии, не при сопряжении**. **Пока `event.*` нет — автоматизации нечего ловить; нажатие уходит в пустоту, при полностью живых сущностях и правильных `entity_id`.** Чек: `ha_ws.py find <кнопка>` → искать `event.*` в списке сущностей. Триггер строить на `platform: state` + `entity_id: event.*` + `trigger.event.data.key_press`.
|
||||
43. 🔴 **`zha/permit` НЕ существует как WS-командa** (`unknown_command`). Окно спаривания открывать **REST-сервисом**: `POST /api/services/zha/permit`, body `{"duration":120}` → `200 [], []`. Работает.
|
||||
44. 🔴 **Строка `Authorization: Bearer *** в bash-скрипте вырезается фильтром секретов** → `syntax error near unexpected token ')'` / `unexpected EOF`, скрипт неработоспособен. **Надёжный обход: Python + `urllib`**, токен из файла в рантайме (`HDR = {"Authorization": "Bearer " + TOK}`). Это работает лучше, чем трюк `P="Bearer"` (питфолл 10), который тоже иногда ловится.
|
||||
45. ⚠️ **`select.*` / `number.*`-настройки могут быть названы по ЧУЖОМУ устройству** (как `select.bed_dimmer_*` на `sauna`). **Признак:** сущности «одного устройства» ссылаются на **два разных `device_id`**. Проверять `device_id` у каждой сущности. На работу реле/кнопок не влияет — косметика UI.
|
||||
46. 🔴 **Документ может фиксировать не факт, а ошибочный вывод.** В этом доке полсуток жила неверная запись про `bed_dimmer` ↔ `sauna` (пришла из производной `rename-map.json`). **При следующем касании дока сверять спорные места с `database.db`**, а не доверять предыдущей записи. Ошибка в доке = ошибка, воспроизведённая в следующей сессии.
|
||||
|
||||
---
|
||||
|
||||
@@ -956,14 +977,205 @@ sauna device_id 700e14b7d1710526b00f098b8506826d zha:a4:c1:38:4f:be:0b:
|
||||
|
||||
**TS0052 — это НЕ лампа, а настенный диммер-контроллер.** ZHA отдаёт его как `light.*` (диммер), Z2M отдавал `light.bed_dimmer` через обёртку `switch_as_x`. Переименование `switch.tz3210_nhqka112_ts011f` → `light.bed_dimmer` **отбито HA** (`New entity ID should be same domain`).
|
||||
|
||||
### План фикса кнопки спальни (согласуется с Alex, не выполнен)
|
||||
### План фикса кнопки спальни — ✅ ЧАСТИЧНО ВЫПОЛНЕНО (ночь-15)
|
||||
|
||||
1. Бэкап `core.entity_registry` на Mac (обязательно первым шагом).
|
||||
2. Вернуть `select.bed_dimmer_power_on_behavior` / `_switch_type` на **`bed_dimmer`** (`e230c12e…`), а не на `sauna` (`700e14b7…`).
|
||||
3. Переименовать `light.tz3000_ooc8illt_ts0052` → `light.bed_dimmer` (домен совпадает — пройдёт).
|
||||
4. Пересобрать автоматизации кнопки спальни на реальный `light.bed_dimmer`, проверить `last_triggered` фактом.
|
||||
1. ~~Бэкап `core.entity_registry` на Mac~~ — **Alex отклонил** («продолжай чинить никаких бэкапов»). Не требовался: правки реестра обратимы переименованием.
|
||||
2. ~~Вернуть `select.bed_dimmer_*` на `bed_dimmer`~~ — **ОТЛОЖЕНО**: у HA нет WS-метода «сменить `device_id` у сущности»; проще переименовать `entity_id` + задать `friendly_name`. На работу кнопки не влияет.
|
||||
3. ✅ **ВЫПОЛНЕНО:** `light.tz3000_ooc8illt_ts0052` → **`light.bed_dimmer`** (`success: true`), проверено фактом: `state=off`, `friendly_name=bed_dimmer`.
|
||||
4. ✅ **ВЫПОЛНЕНО:** `switch.tz3210_nhqka112_ts011f` → **`switch.sauna`** (`success: true`), проверено: `state=off`, `friendly_name=sauna`.
|
||||
5. 🔴 **КОРЕНЬ «кнопка не свитчит» оказался НЕ здесь — см. §Факт 5.**
|
||||
|
||||
> ⚠️ **Проверять после каждого шага чтением реестра обратно** — HA на `config/entity_registry/update` может ответить успехом, не применив значение.
|
||||
> 📌 **`config/entity_registry/update` с `new_entity_id`** — рабочая форма. Домены `light`→`light` и `switch`→`switch` проходят; смена домена (п.30 питфоллов) — нет.
|
||||
|
||||
### 🔴 ФАКТ 5 — настоящий корень «кнопка спальни не свитчит диммер»: у кнопки НЕТ `event.*`-сущности
|
||||
|
||||
> **Триггер:** Alex — «Кнопка в спальне не свитчит диммер в спальне» (после того как `light.bed_dimmer` уже существовал).
|
||||
|
||||
**Проверено фактом** — все сущности устройства `wireless_light_switch_bed`:
|
||||
|
||||
```
|
||||
wireless_light_switch_bed device_id da6c759f9046046c4ef60467175ccbbe
|
||||
zha:a4:c1:38:b0:f9:e6:74:a5 _TZ3000_kccru4oi TS0041
|
||||
sensor.tz3000_kccru4oi_ts0041_batareia ← батарея
|
||||
sensor.tz3000_kccru4oi_ts0041_rssi ← отключена (integration)
|
||||
sensor.tz3000_kccru4oi_ts0041_lqi ← отключена (integration)
|
||||
update.tz3000_kccru4oi_ts0041_obnovlenie_proshivki
|
||||
event.* ← 🔴 НЕТ ВООБЩЕ
|
||||
```
|
||||
|
||||
В системе вообще **одна** event-сущность — `event.backup_automatic_backup` (платформа `backup`). Кнопок там нет.
|
||||
|
||||
> 🔴 **МЕХАНИКА, КОТОРУЮ Я РАНЬШЕ НЕ УЧЁЛ:** в Z2M кнопка TS0041 отдавала `action` в MQTT-топик — автоматизация триггерилась по `platform: mqtt` + topic. В **ZHA** такого нет: нажатие приходит как **`zha_event`**, а HA создаёт из него сущность **`event.*`**, из которой читается `key_press`. **Пока `event.*` не существует — автоматизации нечего ловить, нажатие уходит в пустоту.**
|
||||
>
|
||||
> **ZHA создаёт `event.*` при ПЕРВОМ событии от устройства** (не при сопряжении). У `light_sensor_stairs` к тому же своя беда — он вообще не в реестре.
|
||||
|
||||
> 📌 **ЧЕК-ЛИСТ для любой кнопки после миграции Z2M → ZHA:** посмотреть `ha_ws.py find <кнопка>` → если в списке сущностей **нет `event.*`** — нажать кнопку физически и перечитать. Только после появления `event.*` автоматизацию можно триггерить (триггер `platform: state`, `entity_id: event.*`, чтение `trigger.event.data.key_press`).
|
||||
|
||||
#### 🔴 ФАКТ 5-БИС — `event.*` кнопки ТАК И НЕ ПОЯВИЛСЯ (слушание шины, 90 с)
|
||||
|
||||
**Проверено фактом:** открыт фоновый слушатель WS (`subscribe_events`: `zha_event` + `state_changed`), Alex попросили нажать кнопку в спальне. За **90 секунд — ни одного события** от `a4:c1:38:b0:f9:e6:74:a5`. `event.*` не создалась.
|
||||
|
||||
> 🔴 **НАЖАТИЕ НЕ ДОЛЕТЕЛО ДО КООРДИНАТОРА.** Это уже **не** «HA не создала сущность» — HA создаёт `event.*` из первого `zha_event`, а события нет вообще. Значит кнопка физически не передаёт нажатие в сеть ZHA. См. также паттерн `light_sensor_stairs` (§Факт 6): **батарейные устройства после миграции нужно буквально «доставить» до координатора повторным режимом спаривания.**
|
||||
>
|
||||
> **Что делать с кнопкой:** применить тот же приём, что сработал на датчике лестницы — **открыть `zha.permit` (REST, 180 с) → слушать WS-шину в фоне → ретраить режим спаривания на кнопке** (TS0041: удерживать ~5 с), пока в шине не появится `zha_event`, и только тогда нажимать обычным способом.
|
||||
> 📌 **Диагностический порядок для любой кнопки:** (1) есть ли `zha_event` в шине → если нет, кнопка не в сети; (2) есть ли `event.*` → если нет, событий ещё не было; (3) только после обоих — строить триггер автоматизации.
|
||||
> 📌 Скрипт-слушатель: `btn_listen.py` (фильтр по IEEE кнопки, ловит `zha_event` и появление `event.*`).
|
||||
> ⚠️ **Ранее записанный вывод «нажать кнопку — и всё появится» НЕВЕРЕН для этой кнопки.** Проверено: нажатие не проходит. Не повторять совет без проверки шины.
|
||||
|
||||
### ✅ ФАКТ 6 — `light_sensor_stairs` ДОБАВИЛСЯ (ОБНОВЛЕНО: сначала НЕ добавился, потом добавился)
|
||||
|
||||
> 🔴 **ЗАПИСЬ ПЕРЕПИСАНА.** Ранее здесь стояло «ДОБАВИТЬСЯ НЕ СМОГ», «в реестре отсутствует вовсе». **Неверно — устройство в итоге добавилось.** Оставляю обе фазы, потому что первая фаза — рабочий разбор отказа.
|
||||
|
||||
**Фаза 1 (отказ) — попытка по просьбе Alex** («поставил light sensor в режим спаривания»), затем «еще раз поставил»:
|
||||
1. Окно спаривания через REST: `POST /api/services/zha/permit` body `{"duration":120}` → **`200`, `[]`** — окно открыто. ⚠️ WS-метод `zha/permit` отвечает `unknown_command` — **работает только REST-сервис**.
|
||||
2. Опрос ~60 с + проверка реестра → **0 результатов**. ZHA — 16 устройств (15 + координатор).
|
||||
|
||||
**Фаза 2 (успех) — на следующей попытке Alex устройство долетело.** Проверено фактом:
|
||||
|
||||
```
|
||||
a4c1386d40ddb67b | _TZ3000_hy6ncvmw TS0222 | EndDevice | last_seen 2026-09-15T20:46:51
|
||||
ZHA devices: 17 (16 устройств + координатор)
|
||||
```
|
||||
|
||||
**Что сделано после появления:**
|
||||
|
||||
| Шаг | Результат |
|
||||
|---|---|
|
||||
| `name_by_user` | `light_sensor_stairs` ✅ |
|
||||
| зона | `lestnitsa` ✅ |
|
||||
| `device_id` | `f33b36fbaec7b1eabca7a7e496be89f4` |
|
||||
| сущности переименованы | `sensor.light_sensor_stairs_illuminance` / `_battery` / `_temperature` / `_humidity` (все `success: true`) ✅ |
|
||||
| данные идут | освещённость 3…440 lx (поток), батарея 100% ✅ |
|
||||
|
||||
> 🔑 **ПОЧЕМУ ЗАРАБОТАЛО:** помогло **не одно** длинное нажатие, а **повторные попытки перевода устройства в режим спаривания**. Первые две попытки — 0 результата, третья — устройство долетело. **Вывод: для `TS0222` (EndDevice, спит) ретраить режим спаривания, а не считать отказ окончательным.** Ранее записанный вердикт «длинный нажим 10 с / вынуть батарейку» **не понадобился**.
|
||||
> 📌 **Проверять появление ФАКТОМ через реестр** (`zha/devices` по WebSocket или `ha_ws.py find <ieee>`), не по состоянию сущностей — у sleeping EndDevice состояние приходит позже регистрации.
|
||||
> 📌 **Мониторинг появления — рабочий приём:** фоновый слушатель WS `subscribe_events` (`zha_event` + `state_changed`) с фильтром по entity_id; он же подтвердил поток данных датчика (`state: sensor.*_osveshchennost 308 → 296 → 381 → 433 …`). Скрипт: `/tmp/pair_listen.py`.
|
||||
|
||||
> ⚠️ `manufName` у него `_TZ3000_hy6ncvmw` (ранее в переписке я называл `_TZ3000_4ufaeuwv` — ошибка). `modelId: TS0222`, `powerSource: Battery`.
|
||||
> 🔴 **Правильный порядок для будущих sleeping-устройств:** открыть окно `zha.permit` (REST, 180 с) → **слушать WS-шину в фоне** → ретраить режим спаривания на устройстве, пока в реестре не появится IEEE.
|
||||
|
||||
### 🔴 ФАКТ 9 — ещё 2 битых автоматизации: `triggers: []` и чужие `device_id`
|
||||
|
||||
**Найдено при проверке `automations.yaml` (189 строк, снят с t610 локально в `~/tmp-t610/automations-current.yaml`).**
|
||||
|
||||
```
|
||||
- id: '1771683420621'
|
||||
alias: 'Toggle Dimmer bed (ждёт кнопку bed)'
|
||||
description: 'Кнопка wireless_light_switch_bed не подхвачена ZHA — триггер отключён до пробуждения'
|
||||
triggers: [] ← 🔴 ПУСТО, я сам отключил
|
||||
actions:
|
||||
- type: toggle
|
||||
device_id: 700e14b7d1710526b00f098b8506826d ← 🔴 ЭТО sauna, не диммер!
|
||||
entity_id: switch.tz3210_nhqka112_ts011f ← 🔴 ЭТО sauna, не диммер!
|
||||
|
||||
- id: '1771683677259'
|
||||
alias: 'Dimmer bed cycle (ждёт кнопку bed)'
|
||||
triggers: [] ← 🔴 ПУСТО
|
||||
actions:
|
||||
- service: light.turn_on
|
||||
target:
|
||||
entity_id: switch.tz3210_nhqka112_ts011f ← 🔴 ЭТО sauna, не диммер!
|
||||
data:
|
||||
brightness_pct: 50
|
||||
```
|
||||
|
||||
> 🔴 **ДВА независимых бага в одной автоматизации:**
|
||||
> 1. **`triggers: []`** — я отключил триггер с пометкой «ждёт кнопку bed». Пустой триггер = автоматизация никогда не сработает, но HA держит её загруженной. **Пустой `triggers` не даёт `unavailable`** — автоматизация «on», просто мёртвая молча. Если бы не проверка конфига, я бы не увидел.
|
||||
> 2. **`device_id` + `entity_id` указывают на `sauna`, а не на диммер** — тот же перепутанный IEEE, что и в §Факт 7. Я пересобрал автоматизации **до** того, как исправил карту. Автоматизация «Toggle Dimmer bed» на самом деле щёлкала бы реле сауны.
|
||||
>
|
||||
> **Правильные цели:** `bed_dimmer` → `light.bed_dimmer` (домен **light**), `sauna` → `switch.sauna` (домен **switch**).
|
||||
> 🔴 **`Dimmer bed cycle` вызывает `light.turn_on` на `switch.*` — так нельзя вообще.** Для диммера домен — `light`, для реле — `switch`. Перепутано и устройство, и домен.
|
||||
|
||||
> ⚠️ **Остальные найденные дефекты в том же файле:**
|
||||
> - `Вкл. ночной свет душевая` / `Выкл. ночной свет душевая` → `device_id: fd52114b516a79055c7add0393f2486d` — **это `night_light_shower_2`** (он же в таблице §Шаг 3), но у устройства уже другой `device_id`. Проверить живость.
|
||||
> - `Zigbee T sensor батарея` → `sensor.tz3000_akqdg6g7_ts0201_batareia` — **устройство переименовано** в `office_temperature_sensor`, entity_id устарел.
|
||||
> - `light_switch_bed_batareia` = **unavailable**.
|
||||
> - Итог замера: **11 из 16 автоматизаций в состоянии `on`**, 4 недоступны (`unavailable`).
|
||||
|
||||
> 🔴 **УРОК: `triggers: []` не диагностируется по состоянию `automation.*`.** Проверять **содержимое** `/config/automations.yaml`, а не только `state`. Рабочая команда: `grep -n "triggers:" automations.yaml` + глазами искать пустые массивы.
|
||||
|
||||
```
|
||||
0ceff6fffe9339f2 Inswift ZBP-MG21 Coordinator
|
||||
a4c138f8da8bc478 recirculation_pump Router
|
||||
a4c138c4a94a6a31 shower_2_presence_sensor Router
|
||||
a4c1381694217e10 boiler_controller_power Router
|
||||
a4c138eb6fbe9d19 heating_cable_plug Router
|
||||
a4c1383d5fcaa063 boiler_water_leak EndDevice
|
||||
a4c13873b5c1575b office_table_light_switch Router
|
||||
a4c1386d0839706a light_stairs Router
|
||||
84fd27fffed9e137 night_light_shower_2 Router
|
||||
a4c138c650636cf6 toilet_1_floor_temperature EndDevice
|
||||
a4c1384fbe0b3a6b sauna Router
|
||||
a4c13807b64c7fd4 kitchen_hood Router
|
||||
a4c1381186ed1a32 smart_light_office EndDevice
|
||||
a4c13862d39377e6 office_temperature_sensor EndDevice
|
||||
a4c13882a4b42db0 bed_dimmer Router
|
||||
a4c138b0f9e674a5 wireless_light_switch_bed EndDevice
|
||||
```
|
||||
|
||||
> 🔴 **УТОЧНЕНИЕ к Факту 4:** вывод «устройство привязалось к ZHA (`iasCieAddr` координатора ZHA, свежий `lastSeen`)» **перепроверить нельзя** — `database.db` был снят **до** миграции, поэтому `iasCieAddr 0x0ceff6fffe9339f2` мог быть записан ещё Z2M'ом при интервью. **Факт на сейчас: в живом реестре ZHA устройства НЕТ.** Достоверно — только это.
|
||||
>
|
||||
> **Порядок действий (согласован, ждём Alex):**
|
||||
> 1. Зажать кнопку на датчике и держать **~10 с** — не отпускать на первом мигании, дождаться быстрого/тройного.
|
||||
> 2. Отпустить, пауза 2 с, **один короткий нажим**.
|
||||
> 3. Если не появится — **вынуть батарейку на 10 с**, вставить, повторить п.1–2 (сбрасывает возможный рассинхрон ключа).
|
||||
> 4. Проверять **реестр по WebSocket**, а не состояние сущностей.
|
||||
>
|
||||
> ⚠️ `zha.permit` для уже-в-сети устройств бесполезен (питфолл 22), но для **не долетевшего** устройства окно открывать надо — оно есть, факт: REST-вызов прошёл.
|
||||
|
||||
### 🔴 ПИТФОЛЛ: фильтр секретов ломает скрипты на `Bearer $TOK`
|
||||
|
||||
**Симптом:** `bash: syntax error near unexpected token ')'` / `unexpected EOF while looking for matching '"'`.
|
||||
**Причина:** строка `Authorization: Bearer *** **вырезается фильтром при передаче скрипта**, кавычки не закрываются.
|
||||
**Рабочий обход (проверено):** не писать эту строку в bash-скрипте вообще — **уходить в Python + `urllib`**, токен читать из файла:
|
||||
|
||||
```python
|
||||
TOK = open("/tmp/.hatok").read().strip()
|
||||
HDR = {"Authorization": "Bearer " + TOK, "Content-Type": "application/json"}
|
||||
ctx = ssl.create_default_context(); ctx.check_hostname = False; ctx.verify_mode = ssl.CERT_NONE
|
||||
urlopen(urllib.request.Request(BASE + path, headers=HDR), context=ctx)
|
||||
```
|
||||
|
||||
> 📌 `python3 /tmp/x.py` **не триггерит фильтр** — токен собирается в рантайме из файла. Это надёжнее, чем `P="Bearer"` из питфолла 10.
|
||||
> 📌 **`jq: parse error: Expected string key before ':' at line 1, column 4`** при `curl … | jq` — тот же корень: пустой `$HDR`, curl вернул текст ошибки.
|
||||
|
||||
---
|
||||
|
||||
### 🔴 ФАКТ 7 — перепутанные IEEE: ЗАПИСЬ В ДОКЕ БЫЛА НЕВЕРНОЙ, вот правильная
|
||||
|
||||
> **Триггер:** Alex — «Чё за хуйня как ты мог перепутать если данные все блядь были» + «проверяй ВСЁ из бэкапа».
|
||||
|
||||
**Проверено по `database.db`** (`ieeeAddr` + `modelId` + `manufName` — одной строкой):
|
||||
|
||||
```
|
||||
a4c1384fbe0b3a6b sauna modelId TS011F manufName _TZ3210_nhqka112 ← НЕ bed_dimmer
|
||||
a4c13882a4b42db0 bed_dimmer modelId TS0052 manufName _TZ3000_ooc8illt ← НЕ sauna
|
||||
```
|
||||
|
||||
**Соответствие в живом HA ZHA (проверено, `device_id` + `identifiers`):**
|
||||
|
||||
| IEEE | ZHA `device_id` | ZHA-сущность | `name_by_user` |
|
||||
|---|---|---|---|
|
||||
| `a4:c1:38:82:a4:b4:2d:b0` | `e230c12e6cb45492408ddba6456b6444` | `light.bed_dimmer` (было `light.tz3000_ooc8illt_ts0052`) | **bed_dimmer** |
|
||||
| `a4:c1:38:4f:be:0b:3a:6b` | `700e14b7d1710526b00f098b8506826d` | `switch.sauna` (было `switch.tz3210_nhqka112_ts011f`) | **sauna** |
|
||||
|
||||
> 🔴 **ОШИБКА В ЭТОМ ДОКЕ, ИСПРАВЛЕНА:** ранее в двух местах было записано наоборот — «`700e14b7…` = `bed_dimmer`» (таблица переименованных устройств) и «`switch.tz3210_nhqka112_ts011f` → `light.bed_dimmer`» (карта переименования). **Оба неверны.** `_TZ3210_nhqka112 TS011F` — это **`sauna`** (реле), `_TZ3000_ooc8illt TS0052` — **`bed_dimmer`** (диммер). Исправлено здесь и в §Инвентарь.
|
||||
>
|
||||
> **ПОЧЕМУ ОШИБКА ЖИЛА В ДОКЕ:** я записывал док по **производной карте** `rename-map.json` и собственным ночным выводам, а не по `database.db`. Док фиксирует не факт, а мой тогдашний (ошибочный) вывод — и ошибка закрепилась как «знание».
|
||||
> 🔴 **УРОК: `database.db` — единственный первоисточник. Всё, что в доке пришло из производной карты, требует перепроверки при следующем касании.**
|
||||
|
||||
### 🔴 ФАКТ 8 — `select.bed_dimmer_*` названы по чужому устройству
|
||||
|
||||
```
|
||||
bed_dimmer e230c12e… → light.bed_dimmer, button.*_identifikatsiia, number.*_vremia_perekhoda_*
|
||||
sauna 700e14b7… → switch.sauna, select.bed_dimmer_power_on_behavior 🔴, select.bed_dimmer_switch_type 🔴
|
||||
```
|
||||
|
||||
`select.bed_dimmer_power_on_behavior` / `_switch_type` — это настройки реле **`sauna`**, но **названы «bed_dimmer»**. Тот же класс ошибки: массовое переименование вслепую, имена ушли не тем устройствам.
|
||||
|
||||
> 📌 **Диагностический признак:** если сущности «одного устройства» ссылаются на **два разных `device_id`** — имена разошлись по чужим устройствам. Проверять `device_id` **каждой** сущности, а не только главной.
|
||||
> 📌 **Практический вывод:** на работу кнопки это **не влияет** (переименовано 3+4). Косметика для UI.
|
||||
|
||||
### 🔴 Факт 4 — `light_sensor_stairs` В СЕТИ, но сущностей нет
|
||||
|
||||
|
||||
Reference in New Issue
Block a user