diff --git a/family/plans/t610-home-automation.md b/family/plans/t610-home-automation.md index e4359c3a..98df91d8 100644 --- a/family/plans/t610-home-automation.md +++ b/family/plans/t610-home-automation.md @@ -24,7 +24,8 @@ | Что | Состояние | |---|---| -| **44 сущности `unavailable`** | ~32 заслонки (`switch.intake_damper_*`, `exhaust_damper_*`) + вентиляторы (`switch.fan_3_*`, `sensor.fan_at2_*`). **Шина при этом живая** — см. §5. Причина не в железе, разбираться в логе HA (`homeassistant.components.modbus`). Рабочая гипотеза: короткий `timeout 1000 мс` в mbusd для медленных реле-модулей | +| **44 сущности `unavailable`** | ~32 заслонки (`switch.intake_damper_*`, `exhaust_damper_*`) + вентиляторы (`switch.fan_3_*`, `sensor.fan_at2_*`). **Причина НАЙДЕНА 2026-09-14 (поздняя), три слоя — см. §5 «ТРИ реальные причины»:** ① шторм ~28 параллельных TCP-коннектов HA при `mbusd maxconn: 8`; ② регистры отвечают нестабильно (`EXC 0x0B` через раз); ③ `verify` с `state_on: 1`/`state_off: 0` не может сойтись с живым `0x640001`. План фикса согласован, **не применён**. | +| **`sensor.fan_at2_*` — сироты** | В `configuration.yaml` **все `sensors:` закомментированы** → эти сущности физически не могут получать данные. Разобраться с происхождением (2026-09-14 поздняя) | | `switch.sauna` = `unknown` | Розетка физически отключена (`lastSeen` 8+ ч) — не баг | | ZONT не перенаправлен | MQTT-редирект GPON-роутера ещё смотрит на TrueNAS | | Камера | Контейнер был на TrueNAS, остановлен при восстановлении пула. В Caddy остался мёртвый upstream `192.168.2.197:8090`. Разбираться отдельно | @@ -289,6 +290,76 @@ nc -w 5 192.168.2.176 502 < /tmp/mbreq.bin | xxd **Что осталось:** выяснить, почему HA держит 44 `unavailable`, хотя mbusd отдаёт данные. **Смотреть лог HA** (`homeassistant.components.modbus`, `pymodbus`), не лог mbusd. +### 🔴 ДИАГНОСТИКА 2026-09-14 (поздняя): ТРИ реальные причины `unavailable` + +Гипотеза «короткий `timeout 1000 мс`» подтвердилась лишь частично. Лог HA вскрыл **шторм параллельных коннектов**, а прямой опрос — **нестабильность регистров** и **неверный `verify`**. + +**Причина 1 — 🔴 ШТОРМ параллельных TCP-коннектов HA (главная).** +В логе HA при старте: `Something is blocking Home Assistant from wrapping up the start up phase` + **~28 одновременных задач** `ModbusBaseEntity.async_local_update()` (файл `/usr/src/homeassistant/homeassistant/components/modbus/entity.py:114`, `call_later 15.0`). +Следствие: HA открывает **новое TCP-соединение на каждый опрос сущности**, все параллельно, и сразу бросает. +Подтверждение — `netstat -an` на t610: **5 соединений в `TIME_WAIT`** с `172.30.33.0:*` (адрес контейнера HA Core) → `192.168.2.176:502`. +При `mbusd maxconn: 8` и ~28 опросах параллельно — **соединения упираются в лимит и отваливаются по таймауту**. +Признак в логе mbusd — **пачки рваных сессий**: `conn_open` → мгновенный `conn_close`, по 20+ подряд с интервалом 1–4 с. +> ⚠️ **ВАЖНО:** источник коннектов в логе mbusd = `192.168.2.157` (роутер Rasputin, NAT — см. §2), НЕ `192.168.2.176`. Это **нормально**, не «посторонний клиент». Но `netstat` внутри t610 показывает реального клиента — `172.30.33.0` = контейнер HA Core. +> 📌 **Различие коннектов:** успешный коннект HA держит соединение (без `conn_close`); при шторме — мгновенные `close`. Но и при здоровой работе HA может открывать/закрывать по опросу — судить по НАЛИЧИЮ `Time_WAIT`-пачек и загрузке `maxconn`, не по одному `conn_close`. + +**Причина 2 — 🔴 Регистры отвечают НЕСТАБИЛЬНО (не таймаут).** +Прямой опрос 2026-09-14 (поздняя), `nc` + `printf`-запрос: +``` +slave 11 reg 5 -> … 0b 83 0b ← ❌ EXC 0x0B (GATEWAY TARGET DEVICE FAILED TO RESPOND) +slave 11 reg 7 -> … 03 02 640001 ← ✅ OK +slave 11 reg 8 -> … 0b 83 0b ← ❌ EXC 0x0B +slave 12 reg 1 -> … 0c 83 0b ← ❌ EXC 0x0B +slave 12 reg 5 -> … 03 02 640001 ← ✅ OK +``` +**Каждый раз отвечают РАЗНЫЕ регистры** (в прошлый замер 2026-09-14 было наоборот: reg 5 ✅, reg 8 ❌). Устройство на шине отвечает через раз → это **аппаратная/шинная нестабильность реле-модулей**, а не конфиг. +> ⚠️ Формат сырого запроса (`printf '\x…'` + `nc`): MBAP `00 01 00 00 00 06 03 00 01`. +> ⚠️ Питфолл bash: `printf '\\x…'` внутри скрипта, отправляемого через `scp` + `bash` — экранирование `\x` **удваивается** при передаче в одинарных кавычках. Проверять вывод `xxd -p`, а не доверять «красивой» команде из доки. + +**Причина 3 — 🔴 `verify` в `configuration.yaml` физически не может сойтись.** +Конфиг (строки 96–…, `configuration.yaml`): +```yaml +switches: + - name: intake_damper_dining_right_0 + unique_id: intake_damper_dining_right_0 + slave: 11 + address: 5 + write_type: holding + command_on: 256 + command_off: 512 + verify: + input_type: holding + address: 5 + state_on: 1 # ⚠️ HA ждёт ровно 1 + state_off: 0 # ⚠️ HA ждёт ровно 0 +``` +HA **пишет** 256/512 в reg 5, а **читает** из того же reg 5 и ждёт `1`/`0`. Но в живом регистре лежит `0x640001` (не `1`), либо приходит `EXC 0x0B`. +**Следствие: `verify` не сходится НИКОГДА → сущность `unavailable` навсегда, даже при живом регистре.** +> 📌 Untested fix-варианты: ① убрать `verify` вовсе (доверять команде, не перечитывать); ② выставить `state_on`/`state_off` под реальное значение регистра; ③ `verify` только по «изменилось/нет» без сверки с 1/0. Выбирать после стабилизации шины (причина 1+2). + +**Состояние блока `configuration.yaml` (строки 16+):** +- `modbus:` → `rtu_bus`, `type: tcp`, `host: 192.168.2.176`, `port: 502`. +- **`sensors:` — ВСЁ закомментировано** (slave 10 AT2 fans ×4 + `temp_3`/slave 102). +- **`switches:` — активны только заслонки slave 11** (адреса 5,7,8,9,11,12,13,14,…); **весь блок slave 10 (Fan 3 High/Medium/Low) закомментирован** строкой `# slave 10 (AT2 fans) not responding on vent bus — commented out to unblock damper polling`. +> ⚠️ **Активных `sensors:` в `modbus:` НЕТ ВООБЩЕ.** Значит сущности `sensor.fan_at2_*` в реестре — «сироты» от старого конфига/другого источника, они не могут получить данные по определению. Проверить их происхождение (возможно, template-сенсоры или остатки `modbus.sensor`). + +**Опции `local_mbusd` (на момент диагностики):** +```json +{"device":"/dev/serial/by-path/pci-0000:00:12.0-usb-0:4:1.0-port0","speed":9600,"mode":"8n1", + "trx_control":"addc","maxconn":8,"wait":500,"pause":100,"retries":3,"timeout":1000} +``` + +**ПЛАН ФИКСА (согласован, НЕ применён — ждём ОК Alex):** + +| # | Правка | Зачем | Риск | +|---|---|---|---| +| 1 | `timeout 1000 → 3000`, `retries 3 → 1` | Дать медленным реле ответить (причина 2) | обратимый | +| 2 | `maxconn 8 → 16` | Снять лимит при ~28 параллельных опросах (причина 1) | обратимый | +| 3 | Разобраться с `verify` (убрать/смягчить) | Иначе `unavailable` не уйдёт даже при живом регистре (причина 3) | требует проверки на живом | + +**Порядок:** ① бэкап текущих опций аддона → ② правка `timeout`/`retries`/`maxconn` через Supervisor API (§8) → ③ `ha apps restart local_mbusd` → ④ проверка ухода `unavailable` → ⑤ только потом трогать `verify`. +> ⚠️ Правки в `/config/configuration.yaml` — через **HA stop → правка → HA start** (или `ha core check` перед стартом). Бэкап обязателен. + ### ZONT (шина на CH340 #1) ZONT (`192.168.0.10`) — Modbus master на RS-485 `ttyZONT`. 485-датчики: Гостиная=1, Детская=2, Спальня=3. `modbus-bridge` сниффит их и подставляет виртуальные slaves 101/102/103 → ZONT опрашивает как внешние датчики. **Если modbus-bridge не слушает шину → ZONT показывает датчики «недоступными».** @@ -569,7 +640,7 @@ curl -s -X POST -H "$HDR" -H "Content-Type: application/json" \ | # | Задача | Кто | |---|---|---| -| 1 | **Разобраться с 44 `unavailable`** (заслонки + вентиляторы). Шина живая → смотреть лог HA `homeassistant.components.modbus`. Попробовать поднять `timeout` mbusd (1000 → 3000 мс), `retries` 3 → 1 | я | +| 1 | **Фикс 44 `unavailable`** — диагноз готов (§5 «ТРИ реальные причины»). План: ① `mbusd timeout 1000→3000`, `retries 3→1`; ② `maxconn 8→16`; ③ разобраться с `verify` (не сходится с `0x640001`). Правки опций — через Supervisor API, бэкап до. **Ждёт ОК Alex** | я | | 2 | Раскомментировать slave 10 (AT2 fans) в `configuration.yaml` — был закомментирован «not responding on bus» | я | | 3 | `sensor.*_summary` — добавить `\|default(0)` в template-сенсоры (косметика, самоизлечится) | — | | 4 | **Камера** — найти образ/папку, поднять на t610, поправить upstream в Caddy | отдельно | @@ -599,6 +670,8 @@ docker restart caddy ## 10. Рабочие файлы и скрипты **На Mac:** `~/tmp-t610/` — `stage3/out/`, `backups/`, `ha_token.txt`, `addons/`, `etap3-fix/` (`automations.fixed.yaml`, `set_all_areas.jq`, `devid_mapping.json`, `mbtest.sh`), скрипты `*.sh`/`*.py`. +**Диагностика modbus (2026-09-14 поздняя, только чтение):** `~/tmp-t610/mbdiag1.sh` … `mbdiag4.sh` — снятие опций аддонов, блока `modbus:` из `configuration.yaml`, лога mbusd, лога HA по modbus, прямого опроса регистров. Запуск: `scp -i ~/.ssh/id_rsa