Files
obsidian-vault/family/plans/t610-zigbee-ids-battery-freshsensors-modbus.md
T

22 KiB
Raw Blame History

title, created, updated, type, namespace, status, tags, related
title created updated type namespace status tags related
План и результат: читаемые ID Zigbee, алерты батарей, виртуальные Modbus-датчики 2026-09-15 2026-09-16 (ночь: добавлены этапы 5–6 — снос призраков реестра, починка плана этажей и H2000_PRO) plan family 🟢 ВЫПОЛНЕНО 2026-09-16. Шаги 14 закрыты 2026-09-15; 5–6 (вычистка призраков + починка UI) закрыты 2026-09-16 ночью. Всё проверено фактами.
t610
zigbee
zha
modbus
battery
family/tech/zigbee-t610-z2m-i-zha
family/how-to/home-automation
family/how-to/ha-automations

План и результат: читаемые ID, алерты батарей, виртуальные Modbus-датчики

Задача от Alex (2026-09-15): 1) убедиться, что у всех Zigbee-устройств читаемые ID; 2) каждому батарейному — оповещение о низком заряде; 3) каждый температурный Zigbee-датчик прописать как виртуальное устройство Modbus в bridge; 4) обновить доку.

Всё выполнено в тот же вечер. Ниже — план И фактический результат.


0. Исходная точка (снимок до работ)

Пришло +7 новых TS0201 (датчики тёплых полов). ZHA: 24 записи (23 устройства + координатор), было 17.

IEEE Исходное name_by_user Модель Зона
a4c13827ea585609 Темп теплый пол гостиная TS0201 living_room
a4c1382ac15720dd Температура серая TS0201 severnaia
a4c1382dac5e10e2 Темп теплый пол кабинет TS0201 kabinet
a4c13837021f5298 Темп теплый пол кухня TS0201 kitchen
a4c13867875ee7d3 Темп теплый пол ванная TS0201 vannaia
a4c138cde6eed013 Темп теплый пол прихожая TS0201 prikhozhaia
a4c13865e226312d Темп теплый пол душевая TS0201 dushevaia

0.1. 🔴 Дефекты ID, найденные при проверке

# Дефект Пример Итог
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 исправлено

0.2. Исходная занятость Modbus-адресов bridge

Slave Что Регистр
100 sensor.office_temperature_sensor_temperature (Room temp) 100
101 снифф dining_temperature + запись switch.recirculation_pump 100 / 1
102 снифф kids_temperature 100
103 снифф bedroom_temperature 100
104 Zigbee-реле switch.boiler_controller_power 1

Свободно: 105+. Оповещений о низком заряде не было ни у одного батарейного.


1. РЕЗУЛЬТАТ — Шаг 1: единый вид ID (23 устройства)

Формат: <устройство>_<роль>. Для датчиков _temperature / _humidity / _battery / _lqi / _rssi, плюс button.<dev>_identify и update.<dev>_firmware. Для реле _power / _voltage / _current / _energy, select.<dev>_indicator_mode / _power_outage_memory.

Было Стало
Темп теплый пол гостиная 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

Масштаб: 140 переименований (8 устройств + 68 + 16 + 56 + 2 сущностей). Все 23 устройства в зонах, «без зоны» — нет.

1.1. 🔴 Механика — name_by_user НЕ переименовывает entity_id

HA перегенерирует entity_id только у новых сущностей. Нужны два шага:

# Шаг 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"}

1.2. Команды (воспроизведение)

# Полный аудит: устройства + сущности + зоны
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_batareiasensor.kabinet_temperature_battery

Проверка (обязательна после любого переименования):

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 под saunaselect.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). При возврате заряда выше порога уведомление гасится само.

- id: '8800000000000'          # …8800000000011 — 12 штук
  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
        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

Покрытие (12 сущностей): туалет 1 · лестница · душевая · котельная (протечка) · кабинет (воздух) · гостиная · серая · кабинет (пол) · кухня · ванная · прихожая · спальня (кнопка).

3.1. Заменённые старые

Две прежние автоматизации (1773451323415, 1773459663218) удалены — были с порогом 10 и без push.

3.2. 🔴 Сироты: unavailable при чистом YAML

Тело удалено из automations.yaml, запись в реестре осталась → unavailable. Удаление:

# Если 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}                           # потом это

Скрипты: ~/tmp-t610/{add_battery_autos,rm_orphans,rm_orphan2,rm_orphan3}.py

3.3. Границы

sensor.wireless_light_switch_bed_battery = unknown — кнопка спальни спит. Автоматизация создана, но триггера не будет, пока датчик не проснётся (лечится нажатием кнопки).


4. РЕЗУЛЬТАТ — Шаг 4: виртуальные Modbus-датчики (slave 100 + 105112)

Добавлены в /addons/modbus-bridge/data/config.template.tmpl, int16, divider: 10:

Slave HA-сущность
100 sensor.garderobnaia_temperature_temperature (исторический «Room temp»; был office_temperature_sensorkabinet_temperature)
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

Итого в шаблоне 14 маппингов. Свободно: 113+.

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. Команды

# правка шаблона → 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


4bis. ПОСЛЕ ПЛАНА — датчик перенесён в Гардеробную (2026-09-15, 22:5423:56)

Задача Alex (вне исходного плана): «Переименуй этот датчик в датчик гардеробная и перемести в нее и обнови конфиг моста» → «Кабинет который» (т.е. исторический office_temperature_sensor).

Контекст: в UI датчик не находился под старым именем (office_temperature_sensor) — потому что был переименован в kabinet_temperature шагом 1. Именно он и был перенесён.

Что Было Стало
Имя устройства kabinet_temperature garderobnaia_temperature
Зона kabinet garderobnaia
Сущности (7) sensor.kabinet_temperature_* sensor.garderobnaia_temperature_*
Bridge slave 100 sensor.kabinet_temperature_temperature sensor.garderobnaia_temperature_temperature
Автоматизация батареи «Кабинет (температура)», bat_kabinet_temperature «Гардеробная (температура), bat_garderobnaia_temperature`
entity_id автоматизации automation.batareia_kabinet_temperatura automation.batareia_garderobnaia_temperatura

Проверено фактом: Response: 1 register(s) from 100 (ha:sensor.garderobnaia_temperature_temperature) = 24.61 [00 F6].

🔴 Питфолл: id_reuse: Identifier values have to increase

При переименовании сущностей 6 из 7 упали с этой ошибкой (хотя целевые entity_id были свободны). Это внутренний счётчик реестра, не поломка.

Обход (проверен, 6/6 успешно): переименовать в промежуточное имя, затем из него в целевое.

# entity_id → dom.tmp_xxx → dom.новое_имя
{"type":"config/entity_registry/update","entity_id": old, "new_entity_id": tmp}
{"type":"config/entity_registry/update","entity_id": tmp, "new_entity_id": new}
# при провале second step — откат на old

📌 Тот же приём уже применялся для сироты-автоматизации (§3.2, disabled_by + remove). Общее правило: любая операция реестра с id_reuse лечится промежуточным состоянием.

🔴 Питфолл: HA сам перегенерировал entity_id автоматизаций

После automation/reload автоматизации получили новые entity_id по alias: automation.datchik_protechki_kotelnaia_batareiaautomation.batareia_kotelnaia_datchik_protechki. Проверять автоматизации по attributes.id, а не по entity_id.

Аудит автоматизаций (запрошен Alex: «убедись что автоматизация вся корректная»)

Метрика Значение
Всего 24
on 23
off 1 — Ventilation automation on (намеренно)
unavailable 0
Битых ссылок 0 (22 проверено)
Батарейных 12, все on

Бэкапы этого этапа: /config/automations.yaml.bak-gard-20260915-225404, /addons/modbus-bridge/data/config.template.tmpl.bak-gard-20260915-225404, реестры в ~/tmp-t610/backup-gard-20260915-225404.json.

Скрипты: ~/tmp-t610/{gard_step1,gard_step2,gard_step2b,gard_fix,fix_aut_entid}.py. Коммит vault: db20bb8.

ЗАКРЫТО (2026-09-16, ночь): «Office temperature sensor battery недоступно»

Alex: «Office temperature sensor battery — HA ругается что у устройства нет уникального id и оно недоступно», затем «light.smart_light_stairs_l1 — тоже недоступен».

Причина найдена — записи лежали в архиве реестра, а не в runtime: core.entity_registry → data.deleted_entities. Поэтому /api/states, WS-реестр и repairs/list_issues их не видели, а UI «Обслуживание» — видел.

Решение: контролируемый снос скриптом ~/tmp-t610/ghost_purge.sh (исключает живое + вентиляцию, dry-run по умолчанию).

  • Снято 185 записей: 6 точечно (office_temperature_sensor_* ×5 + smart_light_stairs_l1) + 179 пачкой.
  • Архив реестра 360 → 175. Живых 572 — не тронуто.
  • На dry-run поймано 3 живых switch_as_x-записи (light.night_light_shower_2, light.smart_light_office_left/right) — исключены.

Сопутствующее (этап 6):

  • План этажей (home-plan) ругался «недоступно» — ссылался на снесённого light.smart_light_stairs_l1. Исправлено на light.light_stairs_left. Все 29 ссылок валидны.
  • H2000_PRO отдавал °F — ручной override sensor.private.suggested_unit_of_measurement: "°F". Сброшено через WS с options_domain: "sensor.private" (⚠️ через "sensor"success: true, но НЕ меняет). Стало 12.9 / 28.2 / 30.2 °C.

Бэкапы: core.entity_registry.bak-ghostpurge-20260916-002503, .bak-purge-20260916-000530, .bak-ghosts-20260916-000329, lovelace.home_plan.bak-fixplan-20260916-003231.

Детали: family/tech/zigbee-t610-z2m-i-zha §13, family/tech/ha-registry-operations.


4a. ЭТАП 6 — починка UI после сноса призраков (2026-09-16)

Проблема Причина Фикс
План этажей: «недоступно» на карте state-icon → снесённый light.smart_light_stairs_l1 light.light_stairs_left
H2000_PRO: °F вместо °C override sensor.private.suggested_unit_of_measurement сброс через options_domain: "sensor.private"

Правило: после сноса призраков — проверять ссылки дашбордов. План этажей жалуется «недоступно» из-за мёртвой ссылки, а не из-за поломки устройства.

Скрипты: fix_plan_stairs.sh (ссылки плана), fix_h2000_all.py (единицы). Коммит vault: ee86207.


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
8 id_reuse: Identifier values have to increase — штатная ошибка реестра, обходится промежуточным именем (old → tmp → new)
9 HA перегенерирует entity_id автоматизаций по alias при reload — искать по attributes.id
10 Датчик, «не находимый в UI», может быть переименован — искать по IEEE в реестре, а не по старому имени

Связанные заметки