[2026-09-14] eagle: family/plans/t610-home-automation.md
This commit is contained in:
@@ -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 <slave> 03 <addr_hi> <addr_lo> 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 <script> root@192.168.2.176:/tmp/ && ssh -i ~/.ssh/id_rsa root@192.168.2.176 'bash /tmp/<script>'`.
|
||||
> ⚠️ Секреты в скриптах — только через обходных путей из §8 (маскировщик ломает литералы). Здесь секретов нет, использовался готовый `/tmp/curl.auth`.
|
||||
**На t610:** `/config/automations.yaml.bak-*` (последний: `.bak-20260914-131541` — перед снятием `not_from`), `/config/configuration.yaml.bak-http-*`, `/config/.storage/http.bak-*`, `/addons/modbus-bridge/*.bak-hex-*`.
|
||||
|
||||
**Бэкапы (Mac):** `~/tmp-t610/backups/config-t610-20260914-115034.tar.gz`, `truenas-ha-backup-20260913-215043.tar.gz`.
|
||||
@@ -619,6 +692,19 @@ docker restart caddy
|
||||
|
||||
> 📌 **Причина такой свалки (вывод на будущее):** каждая сессия дописывала блок «добавлено в конце» **сверху**, не убирая устаревшее и не сводя дубли. Итог — противоречивые утверждения в одном файле. **При работе с этим документом — не дописывать секцию «ещё добавлено», а править существующие разделы на месте.**
|
||||
|
||||
### 2026-09-14 (сессия диагностики Modbus, только чтение)
|
||||
|
||||
**Найдены три реальные причины 44 `unavailable`** (см. §5). Прежняя формулировка «шина РАБОТАЕТ → дело в таймауте» **уточнена**: шина живая, но нестабильная, плюс два конфигурационных слоя.
|
||||
1. **Шторм ~28 параллельных TCP-коннектов** HA (`ModbusBaseEntity.async_local_update`) при `mbusd maxconn: 8` → отвал по таймауту. Доказательство: `netstat` → `TIME_WAIT` c `172.30.33.0` (контейнер HA Core).
|
||||
2. **Регистры отвечают через раз** (`EXC 0x0B`) — в этот замер reg 7/12:5 ✅, а reg 11:5/11:8/12:1 ❌ (в прошлый замер наоборот). Не таймаут — шинная нестабильность.
|
||||
3. **`verify` не может сойтись**: HA пишет 256/512, читает тот же регистр и ждёт `1`/`0`, а в живом лежит `0x640001`.
|
||||
|
||||
**Ключевое открытие про конфиг:** в `configuration.yaml` **все `sensors:` закомментированы**, `switches:` активны только для slave 11. `sensor.fan_at2_*` — сироты.
|
||||
|
||||
**Ничего не менялось** (только чтение: опции аддонов, конфиг, логи, прямой опрос). План фикса ждёт ОК Alex.
|
||||
|
||||
> ⚠️ **Питфолл записи в этот документ:** правка через `mcp_obsidian_patch_note` с большим `newString` **портит документ** (вставляла контент в середину строки, тело размножилось 4×, 21KB→50KB). Для крупных вставок — читать целиком и `write_file`/локальный `patch`. Мелкие точечные правки с уникальным контекстом — можно patch.
|
||||
|
||||
---
|
||||
|
||||
## Связанные заметки
|
||||
|
||||
Reference in New Issue
Block a user