[2026-09-14] eagle: family/plans/t610-home-automation.md
This commit is contained in:
@@ -24,9 +24,9 @@
|
|||||||
|
|
||||||
| Что | Состояние |
|
| Что | Состояние |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **10 сущностей `unavailable`** (было 44) | **✅ ОСНОВНОЕ РЕШЕНО 2026-09-14 (финал): аддоны стояли на перепутанных гнёздах — поменяны местами → ушли ВСЕ 32 заслонки** (см. §5 «✅✅ РЕШЕНИЕ»). Рабочая привязка: `mbusd` = гнездо 3 (вентиляция), `modbus-bridge` = гнездо 4 (**ZONT 485**). **Остались 10:** `switch.fan_3_high/medium/low` + `sensor.fan_at2_*` (slave 10 закомментирован в `configuration.yaml` — задача №2) + `sensor.dining_summary`/`dining_air_summary` (нужен `\|default(0)`) + `todo.shopping_list` (системная) |
|
| **10 сущностей `unavailable`** (было 44) | **✅ ОСНОВНОЕ РЕШЕНО 2026-09-14 (финал): аддоны стояли на перепутанных гнёздах — поменяны местами → ушли ВСЕ 32 заслонки** (см. §5 «✅✅ РЕШЕНИЕ»). Рабочая привязка: `mbusd` = гнездо 3 (вентиляция), `modbus-bridge` = гнездо 4 (**ZONT 485**). **Остались 10** (не наши задачи, отдельные известные вещи — см. §9): `switch.fan_3_high/medium/low` + `sensor.fan_at2_*` (slave 10 закомментирован в `configuration.yaml`) + `sensor.dining_summary`/`dining_air_summary` (нужен `\|default(0)`) + `todo.shopping_list` (системная) |
|
||||||
| ~~`verify` как причина~~ | **ОПРОВЕРГНУТО как причина:** при верной привязке шин заслонки ожили при том же `verify` (`state_on:1`/`state_off:0`). Причина была в перепутанных шинах, не в `verify` |
|
| ~~`verify` как причина~~ | **ОПРОВЕРГНУТО как причина:** при верной привязке шин заслонки ожили при том же `verify` (`state_on:1`/`state_off:0`). Причина была в перепутанных шинах, не в `verify` |
|
||||||
| **`sensor.fan_at2_*` / `switch.fan_3_*` — сироты** | В `configuration.yaml` **весь блок slave 10 (AT2 fans) закомментирован** → эти сущности физически не могут получать данные. Раскомментировать (задача №2) либо почистить реестр |
|
| **`sensor.fan_at2_*` / `switch.fan_3_*` — сироты** | В `configuration.yaml` **весь блок slave 10 (AT2 fans) закомментирован** → эти сущности физически не могут получать данные. Не задача — просто известный факт состояния конфига |
|
||||||
| `switch.sauna` = `unknown` | Розетка физически отключена (`lastSeen` 8+ ч) — не баг |
|
| `switch.sauna` = `unknown` | Розетка физически отключена (`lastSeen` 8+ ч) — не баг |
|
||||||
| ZONT не перенаправлен | MQTT-редирект GPON-роутера ещё смотрит на TrueNAS |
|
| ZONT не перенаправлен | MQTT-редирект GPON-роутера ещё смотрит на TrueNAS |
|
||||||
| Камера | Контейнер был на TrueNAS, остановлен при восстановлении пула. В Caddy остался мёртвый upstream `192.168.2.197:8090`. Разбираться отдельно |
|
| Камера | Контейнер был на TrueNAS, остановлен при восстановлении пула. В Caddy остался мёртвый upstream `192.168.2.197:8090`. Разбираться отдельно |
|
||||||
@@ -300,20 +300,20 @@ nc -w 5 192.168.2.176 502 < /tmp/mbreq.bin | xxd
|
|||||||
|
|
||||||
**✅ ВЫЯСНЕНО (2026-09-14, финал):** причина `unavailable` — **аддоны стояли на ПЕРЕПУТАННЫХ гнёздах** (`mbusd` на гнезде 4 = ZONT-шина, `modbus-bridge` на гнезде 3 = вентиляция). После обмена привязок заслонки ожили: **44 → 10 `unavailable`**. См. §5 «✅✅ РЕШЕНИЕ».
|
**✅ ВЫЯСНЕНО (2026-09-14, финал):** причина `unavailable` — **аддоны стояли на ПЕРЕПУТАННЫХ гнёздах** (`mbusd` на гнезде 4 = ZONT-шина, `modbus-bridge` на гнезде 3 = вентиляция). После обмена привязок заслонки ожили: **44 → 10 `unavailable`**. См. §5 «✅✅ РЕШЕНИЕ».
|
||||||
|
|
||||||
### 🔴 ДИАГНОСТИКА 2026-09-14 (поздняя): ТРИ реальные причины `unavailable`
|
### 🟡 ДИАГНОСТИКА 2026-09-14 (поздняя): ОШИБОЧНЫЕ ГИПОТЕЗЫ (сохранены как урок)
|
||||||
|
|
||||||
Гипотеза «короткий `timeout 1000 мс`» подтвердилась лишь частично. Лог HA вскрыл **шторм параллельных коннектов**, а прямой опрос — **нестабильность регистров** и **неверный `verify`**.
|
> 🔴 **ВАЖНО: три «причины» ниже (шторм, нестабильные регистры, `verify`) — НЕ причина `unavailable`. Финал: причина одна — ПЕРЕПУТАННЫЕ ГНЁЗДА аддонов** (см. выше стр. 301 и §5 «✅✅ РЕШЕНИЕ»). Гипотезы оставлены, потому что содержат ценные питфоллы диагностики (замер при живом HA, `maxconn`, форма сырого запроса). **Не принимать их за действующее объяснение.**
|
||||||
|
|
||||||
**Причина 1 — 🔴 ШТОРМ параллельных TCP-коннектов HA (главная).**
|
**❌ Гипотеза A (опровергнута) — «ШТОРМ параллельных 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 при старте: `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-соединение на каждый опрос сущности**, все параллельно, и сразу бросает.
|
Следствие (как считалось): HA открывает **новое TCP-соединение на каждый опрос сущности**, все параллельно, и сразу бросает.
|
||||||
Подтверждение — `netstat -an` на t610: **5 соединений в `TIME_WAIT`** с `172.30.33.0:*` (адрес контейнера HA Core) → `192.168.2.176:502`.
|
Подтверждение — `netstat -an` на t610: **5 соединений в `TIME_WAIT`** с `172.30.33.0:*` (адрес контейнера HA Core) → `192.168.2.176:502`.
|
||||||
При `mbusd maxconn: 8` и ~28 опросах параллельно — **соединения упираются в лимит и отваливаются по таймауту**.
|
При `mbusd maxconn: 8` и ~28 опросах параллельно — **соединения упираются в лимит и отваливаются по таймауту**.
|
||||||
Признак в логе mbusd — **пачки рваных сессий**: `conn_open` → мгновенный `conn_close`, по 20+ подряд с интервалом 1–4 с.
|
Признак в логе 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.
|
> ⚠️ **ВАЖНО:** источник коннектов в логе 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`.
|
> 📌 **Различие коннектов:** успешный коннект HA держит соединение (без `conn_close`); при шторме — мгновенные `close`. Но и при здоровой работе HA может открывать/закрывать по опросу — судить по НАЛИЧИЮ `Time_WAIT`-пачек и загрузке `maxconn`, не по одному `conn_close`.
|
||||||
|
|
||||||
**Причина 2 — 🔴 Регистры отвечают НЕСТАБИЛЬНО (не таймаут).**
|
**❌ Гипотеза B (опровергнута) — «Регистры отвечают НЕСТАБИЛЬНО».**
|
||||||
Прямой опрос 2026-09-14 (поздняя), `nc` + `printf`-запрос:
|
Прямой опрос 2026-09-14 (поздняя), `nc` + `printf`-запрос:
|
||||||
```
|
```
|
||||||
slave 11 reg 5 -> … 0b 83 0b ← ❌ EXC 0x0B (GATEWAY TARGET DEVICE FAILED TO RESPOND)
|
slave 11 reg 5 -> … 0b 83 0b ← ❌ EXC 0x0B (GATEWAY TARGET DEVICE FAILED TO RESPOND)
|
||||||
@@ -322,11 +322,11 @@ slave 11 reg 8 -> … 0b 83 0b ← ❌ EXC 0x0B
|
|||||||
slave 12 reg 1 -> … 0c 83 0b ← ❌ EXC 0x0B
|
slave 12 reg 1 -> … 0c 83 0b ← ❌ EXC 0x0B
|
||||||
slave 12 reg 5 -> … 03 02 640001 ← ✅ OK
|
slave 12 reg 5 -> … 03 02 640001 ← ✅ OK
|
||||||
```
|
```
|
||||||
**Каждый раз отвечают РАЗНЫЕ регистры** (в прошлый замер 2026-09-14 было наоборот: reg 5 ✅, reg 8 ❌). Устройство на шине отвечает через раз → это **аппаратная/шинная нестабильность реле-модулей**, а не конфиг.
|
**Каждый раз отвечают РАЗНЫЕ регистры** (в прошлый замер 2026-09-14 было наоборот: reg 5 ✅, reg 8 ❌). Позже выяснилось: это **артефакт замера при живом HA** (`nc` конкурировал с опросом HA за ту же шину через mbusd), а не нестабильность реле.
|
||||||
> ⚠️ Формат сырого запроса (`printf '\x…'` + `nc`): MBAP `00 01 00 00 00 06 <slave> 03 <addr_hi> <addr_lo> 00 01`.
|
> ⚠️ Формат сырого запроса (`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`, а не доверять «красивой» команде из доки.
|
> ⚠️ Питфолл bash: `printf '\\x…'` внутри скрипта, отправляемого через `scp` + `bash` — экранирование `\x` **удваивается** при передаче в одинарных кавычках. Проверять вывод `xxd -p`, а не доверять «красивой» команде из доки.
|
||||||
|
|
||||||
**Причина 3 — 🔴 `verify` в `configuration.yaml` физически не может сойтись.**
|
**❌ Гипотеза C (опровергнута) — «`verify` физически не может сойтись».**
|
||||||
Конфиг (строки 96–…, `configuration.yaml`):
|
Конфиг (строки 96–…, `configuration.yaml`):
|
||||||
```yaml
|
```yaml
|
||||||
switches:
|
switches:
|
||||||
@@ -343,9 +343,8 @@ switches:
|
|||||||
state_on: 1 # ⚠️ HA ждёт ровно 1
|
state_on: 1 # ⚠️ HA ждёт ровно 1
|
||||||
state_off: 0 # ⚠️ HA ждёт ровно 0
|
state_off: 0 # ⚠️ HA ждёт ровно 0
|
||||||
```
|
```
|
||||||
HA **пишет** 256/512 в reg 5, а **читает** из того же reg 5 и ждёт `1`/`0`. Но в живом регистре лежит `0x640001` (не `1`), либо приходит `EXC 0x0B`.
|
HA **пишет** 256/512 в reg 5, а **читает** из того же reg 5 и ждёт `1`/`0`. В живом регистре лежит `0x640001` (не `1`).
|
||||||
**Следствие: `verify` не сходится НИКОГДА → сущность `unavailable` навсегда, даже при живом регистре.**
|
**Но `verify` НЕ причина `unavailable`** — это доказано финалом: при верной привязке гнёзд все 32 заслонки **ожили при том же самом `verify`** (`state_on:1`/`state_off:0`). Гипотеза «`verify` не сходится НИКОГДА → `unavailable` навсегда» — **ОПРОВЕРГНУТА**.
|
||||||
> 📌 Untested fix-варианты: ① убрать `verify` вовсе (доверять команде, не перечитывать); ② выставить `state_on`/`state_off` под реальное значение регистра; ③ `verify` только по «изменилось/нет» без сверки с 1/0. Выбирать после стабилизации шины (причина 1+2).
|
|
||||||
|
|
||||||
**Состояние блока `configuration.yaml` (строки 16+):**
|
**Состояние блока `configuration.yaml` (строки 16+):**
|
||||||
- `modbus:` → `rtu_bus`, `type: tcp`, `host: 192.168.2.176`, `port: 502`.
|
- `modbus:` → `rtu_bus`, `type: tcp`, `host: 192.168.2.176`, `port: 502`.
|
||||||
@@ -385,7 +384,7 @@ HA **пишет** 256/512 в reg 5, а **читает** из того же reg 5
|
|||||||
30 запросов подряд, slave 11 reg 7 → OK=7 FAIL=23 (76% потерь, EXC 0x0B)
|
30 запросов подряд, slave 11 reg 7 → OK=7 FAIL=23 (76% потерь, EXC 0x0B)
|
||||||
30 запросов подряд, slave 11 reg 5 → OK=7 FAIL=23
|
30 запросов подряд, slave 11 reg 5 → OK=7 FAIL=23
|
||||||
```
|
```
|
||||||
и среди ответов попался **чужой ответ на запрос, которого я не слал** (`…060b 01 00000001`) — признак, что **на шине есть второй мастер/источник трафика**.
|
и среди ответов попался **чужой ответ на запрос, которого я не слал** (`…060b 01 00000001`) — тогда это приняли за признак «второго мастера/источника трафика» (гипотеза опровергнута ниже; в реальности — артефакт замера при живом HA).
|
||||||
|
|
||||||
**❌ ГИПОТЕЗА «два Modbus-мастера на одной RS-485» — ОПРОВЕРГНУТА (2026-09-14, позднейшая).**
|
**❌ ГИПОТЕЗА «два Modbus-мастера на одной RS-485» — ОПРОВЕРГНУТА (2026-09-14, позднейшая).**
|
||||||
Alex подтвердил: **адаптеры физически переключены в t610**, TrueNAS от шины отключён. Значит второго мастера нет — ниши TrueNAS-HA/TrueNAS-mbusd не висят на паре A/B. Проверено дополнительно: `192.168.2.197:502` (TrueNAS mbusd) — **CLOSED**, TrueNAS-mbusd не отвечает.
|
Alex подтвердил: **адаптеры физически переключены в t610**, TrueNAS от шины отключён. Значит второго мастера нет — ниши TrueNAS-HA/TrueNAS-mbusd не висят на паре A/B. Проверено дополнительно: `192.168.2.197:502` (TrueNAS mbusd) — **CLOSED**, TrueNAS-mbusd не отвечает.
|
||||||
@@ -401,8 +400,8 @@ Alex подтвердил: **адаптеры физически переклю
|
|||||||
|
|
||||||
**Сверка построчная (2026-09-14 позднейшая):** `intake_damper_*` (dining right/left, kids, bedroom, office, north) + `exhaust_damper_*` (kitchen, bathroom, office, toilet_1, shower_2) — **32 записи, slave/address/`verify` СОВПАДАЮТ ВСЕ**. Закомментированная slave 10 (AT2 fans) — тоже идентична.
|
**Сверка построчная (2026-09-14 позднейшая):** `intake_damper_*` (dining right/left, kids, bedroom, office, north) + `exhaust_damper_*` (kitchen, bathroom, office, toilet_1, shower_2) — **32 записи, slave/address/`verify` СОВПАДАЮТ ВСЕ**. Закомментированная slave 10 (AT2 fans) — тоже идентична.
|
||||||
|
|
||||||
> ✅ **ВЫВОД: конфиг при миграции перенесён КОРРЕКТНО. Расхождений в `modbus:` между TrueNAS и t610 НЕТ.** Значит причина `unavailable` — **НЕ конфиг**. На TrueNAS работало при том же конфиге → разница только в транспорте/шине (два мастера).
|
> ✅ **ВЫВОД: конфиг при миграции перенесён КОРРЕКТНО. Расхождений в `modbus:` между TrueNAS и t610 НЕТ.** Причина `unavailable` — **НЕ конфиг** (и, как выяснилось позже, **не «два мастера»**, а перепутанные гнёзда аддонов — см. §5 «✅✅ РЕШЕНИЕ»).
|
||||||
> 📌 **Ключевая разница хостов:** на TrueNAS HA бил в **свой локальный mbusd** по `192.168.2.197:502`; на t610 HA (`172.30.32.1`) ходит в `192.168.2.176:502` (порт на хосте). Плюс **только один кабель** на физическую шину → возможны два мастера.
|
> 📌 **Ключевая разница хостов (транспорт, НЕ причина):** на TrueNAS HA бил в **свой локальный mbusd** по `192.168.2.197:502`; на t610 HA (`172.30.32.1`) ходит в `192.168.2.176:502` (порт на хосте).
|
||||||
|
|
||||||
**Как снять эталон (команды):**
|
**Как снять эталон (команды):**
|
||||||
```bash
|
```bash
|
||||||
@@ -444,7 +443,7 @@ ZONT (`192.168.0.10`) — Modbus master на RS-485 `ttyZONT`. 485-датчик
|
|||||||
|
|
||||||
Задача от Alex была конкретная: **видит ли `modbus-bridge` данные с ZONT-шины / идут ли запросы от ZONT?**
|
Задача от Alex была конкретная: **видит ли `modbus-bridge` данные с ZONT-шины / идут ли запросы от ZONT?**
|
||||||
|
|
||||||
**Результат: НЕТ. Ни то, ни другое.**
|
**Результат оказался ошибочным — см. блок ✅ выше: шина была не пуста, агент слушал не то гнездо.** Ниже — что именно наблюдалось тогда (сохранено как урок диагностики):
|
||||||
|
|
||||||
| Проверка | Как делалось | Результат |
|
| Проверка | Как делалось | Результат |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -456,11 +455,7 @@ ZONT (`192.168.0.10`) — Modbus master на RS-485 `ttyZONT`. 485-датчик
|
|||||||
|
|
||||||
> 🔴 **ПИТФОЛЛ ДИАГНОСТИКИ: `cat /dev/ttyUSB0` при работающем `modbus-bridge` покажет ПУСТО — bridge держит порт, и `cat` его не получит.** Чтобы слушать шину сырьём, bridge надо остановить (`ha apps stop local_modbus-bridge`), послушать, потом вернуть. **Но `cat` всё равно не отличает «ZONT молчит» от «порт занят»** — надёжнее смотреть, что bridge ПУБЛИКУЕТ в MQTT (если ZONT-запросы идут, bridge отдаёт `modbus/sensors/...`).
|
> 🔴 **ПИТФОЛЛ ДИАГНОСТИКИ: `cat /dev/ttyUSB0` при работающем `modbus-bridge` покажет ПУСТО — bridge держит порт, и `cat` его не получит.** Чтобы слушать шину сырьём, bridge надо остановить (`ha apps stop local_modbus-bridge`), послушать, потом вернуть. **Но `cat` всё равно не отличает «ZONT молчит» от «порт занят»** — надёжнее смотреть, что bridge ПУБЛИКУЕТ в MQTT (если ZONT-запросы идут, bridge отдаёт `modbus/sensors/...`).
|
||||||
|
|
||||||
**Вывод:** запросов от ZONT на шине нет. Причины (обе — физика/настройка ZONT, не код t610; из t610 дальше не различаются):
|
**Вывод того момента (❌ ОШИБОЧНЫЙ):** «запросов от ZONT на шине нет». Причина на самом деле — агент слушал **не то гнездо** (гнездо 3 = вентиляция вместо гнезда 4 = ZONT). Ни «ZONT не подключён», ни «ZONT не мастер» — **не подтвердилось**: после обмена привязок bridge сразу поймал ZONT-трафик. См. блок ✅ выше и «ГЛАВНОЕ ОТКРЫТИЕ» ниже.
|
||||||
1. RS-485 от ZONT физически **не подключён** к гнезду 3 t610 (переткнуты CH340-адаптеры, но сам ZONT-контроллер остался на старой линии).
|
|
||||||
2. Подключён, но **ZONT не является мастером** на этой линии (сбит/выключен Modbus-master после отключения TrueNAS).
|
|
||||||
|
|
||||||
> 📌 Проверить, какая из двух — можно **только с энкодера ZONT** или прозвоном линии. С хоста t610 это неразличимо. **Alex не просил идти на ZONT конфигурировать.**
|
|
||||||
|
|
||||||
> ⏳ ZONT ещё не перенаправлен на MQTT t610 — редирект GPON-роутера смотрит на TrueNAS.
|
> ⏳ ZONT ещё не перенаправлен на MQTT t610 — редирект GPON-роутера смотрит на TrueNAS.
|
||||||
|
|
||||||
@@ -487,7 +482,7 @@ ch341 1-4:1.0: device disconnected
|
|||||||
> - Агент смотрел лог `mbusd` и звал это «вентиляцией» → он опрашивает **ZONT-шину** (там реле 11/12 — да, они на линии ZONT/485).
|
> - Агент смотрел лог `mbusd` и звал это «вентиляцией» → он опрашивает **ZONT-шину** (там реле 11/12 — да, они на линии ZONT/485).
|
||||||
> - `modbus-bridge` «ничего не публиковал» → потому что на гнезде 3 сидит **вентиляция**, а не ZONT.
|
> - `modbus-bridge` «ничего не публиковал» → потому что на гнезде 3 сидит **вентиляция**, а не ZONT.
|
||||||
>
|
>
|
||||||
> ⚠️ **НЕ подтверждено до конца:** какой именно шнур Alex считает «ZONT-шнуром» — надо уточнить у него. Но объективный факт `dmesg` (отключилось гнездо 4) — железный.
|
> ✅ **Подтверждено (финал):** `modbus-bridge` = **ZONT-шина** (гнездо 4), `mbusd` = **вентиляция** (гнездо 3). Подтверждено ДВАЖДЫ: объективным `dmesg` гнезда 4 и описанием схемы аддона «ZONT 485 bus». Привязки обменяны — см. §5 «✅✅ РЕШЕНИЕ».
|
||||||
> ⏳ ~~Сразу после теста гнездо 4 осталось ОТКЛЮЧЕННЫМ~~ — **ЗАКРЫТО, см. §5 «✅ РЕШЕНИЕ».** Шнур воткнут, гнездо 4 вернулось (`usb 1-4 → ttyUSB1`, симлинк `...usb-0:4...` снова есть).
|
> ⏳ ~~Сразу после теста гнездо 4 осталось ОТКЛЮЧЕННЫМ~~ — **ЗАКРЫТО, см. §5 «✅ РЕШЕНИЕ».** Шнур воткнут, гнездо 4 вернулось (`usb 1-4 → ttyUSB1`, симлинк `...usb-0:4...` снова есть).
|
||||||
|
|
||||||
#### ✅✅ РЕШЕНИЕ (2026-09-14, финал): АДДОНЫ ПОМЕНЯНЫ МЕСТАМИ — ЗАСЛОНКИ ОЖИЛИ, `unavailable` 44 → 10
|
#### ✅✅ РЕШЕНИЕ (2026-09-14, финал): АДДОНЫ ПОМЕНЯНЫ МЕСТАМИ — ЗАСЛОНКИ ОЖИЛИ, `unavailable` 44 → 10
|
||||||
@@ -530,10 +525,10 @@ Raw RTU: 14 01 00 00 00 01 FF 0F
|
|||||||
|
|
||||||
> ✅ **ГЛАВНЫЙ ВЫВОД СЕССИИ: причина 44 `unavailable` была НЕ `verify`, НЕ таймаут mbusd, НЕ «два мастера», НЕ конфиг — а ПЕРЕПУТАННЫЕ ШИНЫ У АДДОНОВ.** Пока `mbusd` (обслуживающий заслонки) висел на гнезде с ZONT-линией, HA опрашивал не ту шину → `unavailable` навсегда. Обмен привязок — и всё ожило.
|
> ✅ **ГЛАВНЫЙ ВЫВОД СЕССИИ: причина 44 `unavailable` была НЕ `verify`, НЕ таймаут mbusd, НЕ «два мастера», НЕ конфиг — а ПЕРЕПУТАННЫЕ ШИНЫ У АДДОНОВ.** Пока `mbusd` (обслуживающий заслонки) висел на гнезде с ZONT-линией, HA опрашивал не ту шину → `unavailable` навсегда. Обмен привязок — и всё ожило.
|
||||||
|
|
||||||
**Остались 10 `unavailable` (не связаны с обменом шин):**
|
**Остались 10 `unavailable` (не связаны с обменом шин, и НЕ являются задачами):**
|
||||||
| Сущность | Причина |
|
| Сущность | Причина |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `switch.fan_3_high/medium/low` | slave 10 — **закомментирован** в `configuration.yaml` (задача №2) |
|
| `switch.fan_3_high/medium/low` | slave 10 — блок закомментирован в `configuration.yaml` (факт состояния, не задача) |
|
||||||
| `sensor.fan_at2_1_pwm_raw` / `fan_at2_2_pwm_raw` / `fan_at2_1_run_raw` / `fan_at2_2_run_raw` | то же, slave 10 |
|
| `sensor.fan_at2_1_pwm_raw` / `fan_at2_2_pwm_raw` / `fan_at2_1_run_raw` / `fan_at2_2_run_raw` | то же, slave 10 |
|
||||||
| `sensor.dining_summary` / `sensor.dining_air_summary` | template-сенсоры, нужен `\|default(0)` (косметика, задача №3) |
|
| `sensor.dining_summary` / `sensor.dining_air_summary` | template-сенсоры, нужен `\|default(0)` (косметика, задача №3) |
|
||||||
| `todo.shopping_list` | системная, не наша |
|
| `todo.shopping_list` | системная, не наша |
|
||||||
@@ -843,10 +838,10 @@ curl -s -X POST -H "$HDR" -H "Content-Type: application/json" \
|
|||||||
|
|
||||||
| # | Задача | Кто |
|
| # | Задача | Кто |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 1 | **Фикс 44 `unavailable`** — ~~опции mbusd~~ **ОТМЕНЁН (`maxconn` ломает аддон, откатано)**. ~~Гипотеза двух мастеров~~ **ОПРОВЕРГНУТА** (адаптеры в t610, TrueNAS от шины отключён; `.197:502` CLOSED). Эталон TrueNAS идентичен → причина **НЕ конфиг и НЕ второй мастер**. **Что осталось выяснить:** доходит ли опрос HA до реле — смотреть лог HA по `homeassistant.components.modbus` при живом реле (шина отвечает при остановленном HA). Возможный виновник — `verify` (задача 1b) + конкуренция за шину с mbusd `maxconn 8` при 28 параллельных опросах | я |
|
| ~~1~~ | ~~Фикс 44 `unavailable`~~ — **✅ РЕШЕНО 2026-09-14 (финал): причина — перепутанные гнёзда аддонов. Обмен привязок → `unavailable` 44→10.** Все вложенные гипотезы (опции mbusd, `timeout`, «два мастера», `verify`, шторм коннектов) — **опровергнуты**. См. §5 «✅✅ РЕШЕНИЕ». | — |
|
||||||
| 1b | **`verify` в заслонках** — `state_on: 1`/`state_off: 0` не сходится с живым `0x640001`. **Главный неотработанный кандидат на причину `unavailable`** | я |
|
| ~~1b~~ | ~~`verify` в заслонках~~ — **✅ ОПРОВЕРГНУТО:** заслонки ожили при том же `verify`. Не причина. | — |
|
||||||
| 1c | **🔴 ZONT-шина: ПРИБОРЫ СИДЯТ НА ДРУГИХ ГНЁЗДАХ, ЧЕМ ЗАПИСАНО В ДОКЕ** (см. §5 «ГЛАВНОЕ ОТКРЫТИЕ»). Физический тест Alex'а: выдернул ZONT-шнур → отвалилось **гнездо 4** → **ZONT = гнездо 4**, **вентиляция = гнездо 3**. Значит `mbusd` (гнездо 4) фактически обслуживает **ZONT-шину**, а `modbus-bridge` (гнездо 3) — **вентиляцию**. **Разобраться:** ① подтвердить у Alex, какой шнур он считает ZONT-шнуром; ② решить, менять ли привязку аддонов/доку или физику. | я + Alex |
|
| ~~1c~~ | ~~ZONT-шина на других гнёздах~~ — **✅ СДЕЛАНО:** физический тест доказал (ZONT = гнездо 4, вентиляция = гнездо 3), привязки аддонов обменяны, док приведён в соответствие. Осталась только проверка «① подтвердить у Alex» — **закрыто**: он сам это и тестировал. | — |
|
||||||
| 2 | Раскомментировать slave 10 (AT2 fans) в `configuration.yaml` — был закомментирован «not responding on bus» | я |
|
| ~~2~~ | ~~Раскомментировать slave 10 (AT2 fans)~~ — **СНЯТО с плана (Alex 2026-09-14): задачи по slave 10 НЕ БЫЛО.** | — |
|
||||||
| 3 | `sensor.*_summary` — добавить `\|default(0)` в template-сенсоры (косметика, самоизлечится) | — |
|
| 3 | `sensor.*_summary` — добавить `\|default(0)` в template-сенсоры (косметика, самоизлечится) | — |
|
||||||
| 4 | **Камера** — найти образ/папку, поднять на t610, поправить upstream в Caddy | отдельно |
|
| 4 | **Камера** — найти образ/папку, поднять на t610, поправить upstream в Caddy | отдельно |
|
||||||
| 5 | **Этап 4:** Caddy upstream → t610, GPON-редирект → t610, перенаправить ZONT на MQTT t610 | — |
|
| 5 | **Этап 4:** Caddy upstream → t610, GPON-редирект → t610, перенаправить ZONT на MQTT t610 | — |
|
||||||
@@ -926,13 +921,14 @@ docker restart caddy
|
|||||||
**Ссылки на них починены** в: [[family/how-to/home-automation]], [[family/how-to/truenas-infrastructure]], [[family/how-to/truenas-access]].
|
**Ссылки на них починены** в: [[family/how-to/home-automation]], [[family/how-to/truenas-infrastructure]], [[family/how-to/truenas-access]].
|
||||||
|
|
||||||
> 📌 **Причина такой свалки (вывод на будущее):** каждая сессия дописывала блок «добавлено в конце» **сверху**, не убирая устаревшее и не сводя дубли. Итог — противоречивые утверждения в одном файле. **При работе с этим документом — не дописывать секцию «ещё добавлено», а править существующие разделы на месте.**
|
> 📌 **Причина такой свалки (вывод на будущее):** каждая сессия дописывала блок «добавлено в конце» **сверху**, не убирая устаревшее и не сводя дубли. Итог — противоречивые утверждения в одном файле. **При работе с этим документом — не дописывать секцию «ещё добавлено», а править существующие разделы на месте.**
|
||||||
|
> ✅ **2026-09-14: вычистка противоречий ВЫПОЛНЕНА** (см. запись ниже) — опровергнутые гипотезы переведены в статус «❌ опровергнуто», док сведён к актуальному состоянию. Правило действует и впредь.
|
||||||
|
|
||||||
### 2026-09-14 (сессия диагностики Modbus, только чтение)
|
### 2026-09-14 (сессия диагностики Modbus, только чтение)
|
||||||
|
|
||||||
**Найдены три реальные причины 44 `unavailable`** (см. §5). Прежняя формулировка «шина РАБОТАЕТ → дело в таймауте» **уточнена**: шина живая, но нестабильная, плюс два конфигурационных слоя.
|
**Найдены три кандидата-причины 44 `unavailable`** (см. §5) — **❌ все три позже ОПРОВЕРГНУТЫ финалом: причина была в перепутанных гнёздах аддонов.** Замеры ниже сохранены как урок диагностики, **не как объяснение**.
|
||||||
1. **Шторм ~28 параллельных TCP-коннектов** HA (`ModbusBaseEntity.async_local_update`) при `mbusd maxconn: 8` → отвал по таймауту. Доказательство: `netstat` → `TIME_WAIT` c `172.30.33.0` (контейнер HA Core).
|
1. **Шторм ~28 параллельных TCP-коннектов** HA (`ModbusBaseEntity.async_local_update`) при `mbusd maxconn: 8` → отвал по таймауту. ~~Доказательство: `netstat` → `TIME_WAIT` c `172.30.33.0`~~ — надёжного подтверждения не получил.
|
||||||
2. **Регистры отвечают через раз** (`EXC 0x0B`) — в этот замер reg 7/12:5 ✅, а reg 11:5/11:8/12:1 ❌ (в прошлый замер наоборот). Не таймаут — шинная нестабильность.
|
2. **Регистры отвечают через раз** (`EXC 0x0B`) — **артефакт замера при живом HA**, а не нестабильность шины.
|
||||||
3. **`verify` не может сойтись**: HA пишет 256/512, читает тот же регистр и ждёт `1`/`0`, а в живом лежит `0x640001`.
|
3. **`verify` не может сойтись** — **опровергнуто**: заслонки ожили при том же `verify`.
|
||||||
|
|
||||||
**Ключевое открытие про конфиг:** в `configuration.yaml` **все `sensors:` закомментированы**, `switches:` активны только для slave 11. `sensor.fan_at2_*` — сироты.
|
**Ключевое открытие про конфиг:** в `configuration.yaml` **все `sensors:` закомментированы**, `switches:` активны только для slave 11. `sensor.fan_at2_*` — сироты.
|
||||||
|
|
||||||
@@ -940,6 +936,34 @@ docker restart caddy
|
|||||||
|
|
||||||
> ⚠️ **Питфолл записи в этот документ:** правка через `mcp_obsidian_patch_note` с большим `newString` **портит документ** (вставляла контент в середину строки, тело размножилось 4×, 21KB→50KB). Для крупных вставок — читать целиком и `write_file`/локальный `patch`. Мелкие точечные правки с уникальным контекстом — можно patch.
|
> ⚠️ **Питфолл записи в этот документ:** правка через `mcp_obsidian_patch_note` с большим `newString` **портит документ** (вставляла контент в середину строки, тело размножилось 4×, 21KB→50KB). Для крупных вставок — читать целиком и `write_file`/локальный `patch`. Мелкие точечные правки с уникальным контекстом — можно patch.
|
||||||
|
|
||||||
|
### 2026-09-14 (вычистка противоречий документа — только текст, без изменений в железе)
|
||||||
|
|
||||||
|
**Задача (Alex, жёстко): док ОБЯЗАН всегда держать актуальное состояние; устаревшие слои — моя вина, не его.** План (`family/plans/t610-home-automation.md`) содержал само-противоречия: §5 описывал опровергнутые гипотезы как «реальные причины `unavailable`», хотя финал (обмен гнёзд) уже был записан в §1 и §5 «✅✅ РЕШЕНИЕ».
|
||||||
|
|
||||||
|
**Что сделано (13 правок, только текст):**
|
||||||
|
|
||||||
|
| Место | Было | Стало |
|
||||||
|
|---|---|---|
|
||||||
|
| §5 заголовок | «ТРИ реальные причины `unavailable`» | «ОШИБОЧНЫЕ ГИПОТЕЗЫ (сохранены как урок)» + дисклеймер |
|
||||||
|
| §5 | «Причина 1 — ШТОРМ (главная)» | «❌ Гипотеза A (опровергнута)» |
|
||||||
|
| §5 | «Причина 2 — регистры НЕСТАБИЛЬНЫ» | «❌ Гипотеза B (опровергнута)» + «артефакт замера при живом HA» |
|
||||||
|
| §5 | «Причина 3 — `verify` не сходится» | «❌ Гипотеза C (опровергнута)» |
|
||||||
|
| §5 | «`verify` не сходится НИКОГДА → `unavailable` навсегда» + untested-фиксы | «`verify` НЕ причина — заслонки ожили при том же `verify`» |
|
||||||
|
| §5 «76% потерь» | «признак второго мастера» | «тогда приняли за… (опровергнуто)» |
|
||||||
|
| §5 эталон TrueNAS | «разница в транспорте → два мастера» | «транспорт, НЕ причина»; причина — гнёзда |
|
||||||
|
| §5 ZONT пустая | «Результат: НЕТ» / «ZONT не подключён, не мастер» | «❌ ошибочный — агент слушал не то гнездо» |
|
||||||
|
| §5 «ГЛАВНОЕ ОТКРЫТИЕ» | «НЕ подтверждено, какой шнур ZONT» | «✅ подтверждено дважды (dmesg + схема аддона)» |
|
||||||
|
| §9 задачи 1/1b/1c | «осталось выяснить» / «главный кандидат» | ✅ РЕШЕНО / ОПРОВЕРГНУТО / СДЕЛАНО |
|
||||||
|
| §9 задача 2 | «Раскомментировать slave 10» | ~~СНЯТО: задачи по slave 10 НЕ БЫЛО~~ (Alex) |
|
||||||
|
| §11 запись сессии | «Найдены три реальные причины» | «❌ все три опровергнуты» |
|
||||||
|
| §1/§2/§5 «сироты» | «(задача №2)» | «известный факт состояния конфига, не задача» |
|
||||||
|
|
||||||
|
**Результат:** актуальное состояние дока читается однозначно — **причина 44 `unavailable` одна: перепутанные гнёзда аддонов; решено (44→10)**. Питфоллы сохранены (`maxconn` не трогать, `.157`=NAT, `cat` при живом bridge, `ha core stop`) как уроки, но помечены как «не причина».
|
||||||
|
|
||||||
|
**Проверка:** `search_files` по маркерам `ТРИ реальные|Причина 1..3|unavailable навсегда|главный неотработанный|задача №2|раскомментировать slave 10` → **0 совпадений**.
|
||||||
|
|
||||||
|
> ✅ **Вывод на будущее (правило работы с доком):** при появлении финального объяснения — **сразу переписывать промежуточные гипотезы в статус «опровергнуто с причиной»**, не оставлять их в утвердительном тоне рядом с финалом. §11 — журнал, а не второй источник истины: устаревшие выводы в нём тоже помечать.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Связанные заметки
|
## Связанные заметки
|
||||||
|
|||||||
Reference in New Issue
Block a user