[2026-09-14] eagle: family/how-to/home-automation.md family/plans/t610-home-automation.md

This commit is contained in:
Alexey Martemyanov
2026-09-14 15:33:52 +06:00
parent b8aadd9bd8
commit 865cac30c0
2 changed files with 54 additions and 7 deletions
+5 -4
View File
@@ -25,7 +25,7 @@ related:
>
> **✅ ZONT MQTT — ПЕРЕНАПРАВЛЕН 2026-09-14:** на роутере `192.168.2.2` (OpenWrt) DNAT-правила `redirect[0]` (name `MQTT`) и `rule[3]` (name `allow-1883`) переключены `dest_ip` `192.168.2.197` → **`192.168.2.176`**. ZONT теперь пишет в mosquitto-**аддон на t610** (живой поток `modbus/sensors/kids/*`, `bedroom/*`). В настройках ZONT ничего не менялось — адрес `mqtt://zont:…@192.168.0.10:1883` остался тот же (`192.168.0.10` = wan-интерфейс самого роутера `192.168.2.2`). Бэкап правил: `/root/firewall.bak-20260914-092555`. Детали и откат — [[family/plans/t610-home-automation]] §5-кватер-Д. Также `/etc/config/dhcp`: `list address '/mallexxx.duckdns.org/192.168.0.10'` — внутренний DNS-пин для ZONT-сети.
>
> **🔌 ZONT 485 спит на гнезде 4** (`/dev/serial/by-path/pci-0000:00:12.0-usb-0:4:1.0-port0`), вентиляция — гнездо 3. `modbus-bridge` (аддон на t610) сниффит ZONT-шину и публикует в MQTT топики `modbus/sensors/<комната>/<параметр>`. **Публикуются только `kids` и `bedroom`** (temperature/co2/humidity) **`dining/*` ZONT не публикует вообще, ни в один брокер** (проверено 2026-09-14 вечер-3 после перенаправления DNAT). ⚠️ **Прежняя версия «датчик отвечает 0» — ОПРОВЕРГНУТА:** на брокере TrueNAS по столовой висели **retained**-значения (co2 780, temp 24.2 °C) — то есть данные когда-то были валидными, датчик исправен. Причина в **ZONT-стороне** (регистрация/конфигурация датчика столовой в ZONT), не в маршруте MQTT и не в t610. Задача не ставилась Alex'ом.
> **🔌 ZONT 485 спит на гнезде 4** (`/dev/serial/by-path/pci-0000:00:12.0-usb-0:4:1.0-port0`), вентиляция — гнездо 3. `modbus-bridge` (аддон на t610) сниффит ZONT-шину и публикует в MQTT топики `modbus/sensors/<комната>/<параметр>`. **Публикуются только `kids` и `bedroom`** (temperature/co2/humidity). **Причина по `dining/*` — НАЙДЕНА 2026-09-14 (финал): это BRIDGE, не ZONT.** `modbus-bridge` — **виртуальный slave-прокси**: снифит реальные 485-датчики ZONT (slave 2 детская, slave 3 спальня) и **отдаёт их ZONT'у под виртуальными адресами 101/102/103** (Гостиная=101, Детская=102, Спальня=103). По гостиной bridge **ни разу не снифил** реальный датчик (в логе `Sniff:` только `kids_*`/`bedroom_*`) → отдаёт ZONT'у **`0`** → в MQTT `dining/*` не публикуется (0 невалиден). ⚠️ **Прежние версии ОПРОВЕРГНУТЫ:** ① «нужен `|default(0)`» — враньё; ② «датчик отвечает 0» — датчик исправен (на TrueNAS валидные 24.2 °C как retained); ③ «ZONT сам не публикует» — тоже неверно, дело в mapping bridge. **Что делать:** разобрать mapping `modbus-bridge` (`/addons/modbus-bridge/`, `modbus_ha_bridge.py`). Детали — [[family/plans/t610-home-automation]] §5-кватер-Д.
## AT2 — калибровка PWM
@@ -214,9 +214,10 @@ ZONT relays
[8: Конвектор котельная - н.п.]
```
> **ℹ️ Про «виртуальные sensor 101/102/103» и «недоступные датчики в ZONT»:**
> 101/102/103 — это **виртуальные Modbus-slaves**, которые контейнер `modbus-bridge` на TrueNAS подставляет на шине `ttyZONT`: реальные 485-датчики **Гостиная=1, Детская=2, Спальня=3** сниффятся и их температуры выдаются ZONT'у как датчики 101/102/103 (регистр 100). ZONT (Modbus master) опрашивает их как внешние датчики.
> Если `modbus-bridge` не запущен/не слушает `ttyZONT` → ZONT показывает эти датчики **«недоступные»**. Известная первопричина — гонка docker/udev после рестарта TrueNAS. Подробности и план защиты: `[[family/how-to/truenas-infrastructure.md#Проблема-modbus-bridge/mbusd-после-рестарта-TrueNAS-гонка-с-udev]]` и `[[family/plans/zont-modbus-bridge-udev-race-protection]]`. (Заметка обновлена 2026-08-25: добавлено пояснение про 101/102/103, ZONT relays не менялись.)
> **ℹ️ Про «виртуальные sensor 101/102/103» — механика (уточнено 2026-09-14):**
> 101/102/103 — это **виртуальные Modbus-slaves**, которые контейнер `modbus-bridge` подставляет на шине: реальные 485-датчики **Гостиная=1, Детская=2, Спальня=3** сниффятся, и их значения выдаются ZONT'у как датчики 101/102/103 (регистр 100). ZONT (Modbus master) опрашивает их как внешние датчики.
> **🔑 Уточнение 2026-09-14 (по логу, см. [[family/plans/t610-home-automation]] §5-кватер-Д):** bridge работает **двусторонне** — он не только публикует в MQTT, но и **отвечает ZONT'у** под адресами 101/102/103. В логе это видно явно: `Slave: 101 → sniff:dining_temperature = 0 [00 00]`, `Slave: 102 → sniff:kids_temperature = 25.26`, `Slave: 103 → sniff:bedroom_temperature = 25.12`. **По гостиной (101) bridge отдаёт `0`**, потому что реальный датчик гостиной он **не снифит** (в логе `Sniff:` только `kids_*`/`bedroom_*`; `Slave: 1` у ZONT читает 7 регистров с адреса 2 — это внутренние параметры, не датчик). **Поэтому** `modbus/sensors/dining/*` не публикуется и `sensor.dining_*` в HA = `unknown`.
> Если `modbus-bridge` не запущен/не слушает шину → ZONT показывает эти датчики **«недоступные»**. На TrueNAS известная первопричина была гонка docker/udev после рестарта (см. `[[family/plans/zont-modbus-bridge-udev-race-protection]]`); **на t610 неактуально** — Supervisor сам ждёт устройство.
## Карта регистров контроллера вентиляторов
+49 -3
View File
@@ -92,7 +92,8 @@ ha supervisor logs | tail -60 # диагностика сборки local add-
|---|---|---|
| `192.168.2.2` (OpenWrt, основной) | SSH root, пароль `1316261` | DHCP-аренды: `cat /tmp/dhcp.leases`. **🔑 Его интерфейс `wan` = `192.168.0.10/24`** (шлюз `192.168.0.1`), маршрут `192.168.0.0/24 dev wan`. **Поэтому «`192.168.0.10`» в настройках ZONT — это ОН САМ**, а не отдельный GPON-роутер. На нём же живут DNAT-правила для внешних сервисов (`uci show firewall`): `caddy_http/https` (80/443→TrueNAS 8088/8443), `HomeAssistant` (8123, disabled), `MQTT` (1883 из 192.168.0.0/24), `TrueNas-SSH`, transmission, syncthing, xray |
| `192.168.6.1` («Rasputin», OpenWrt aarch64) | SSH root | eth0 `192.168.2.157/24` — видит сеть 192.168.2.x |
| `192.168.0.1` (GPON) | — | Шлюз wan-интерфейса роутера `192.168.2.2`. ZONT приходит в брокер TrueNAS **с адреса `.0.1`** |
| `192.168.0.1` (GPON-шлюз) | — | Шлюз wan-интерфейса роутера `192.168.2.2` (`58:f8:5c:47:1c:9f`, REACHABLE). ZONT приходит в брокер **с адреса `.0.1`** (через него) |
| **ZONT** `192.168.0.50` | Web UI `http://192.168.0.50/` (порт 80, «ZONT LOCAL») — **доступен ТОЛЬКО с роутера `192.168.2.2`** (с Mac — таймаут) | MAC **`f8:b3:b7:d8:46:f3`** (по ARP на wan роутера). Совпадает с MQTT-клиентом `zont_0FA7C33CC89F_f8:b3:b7:d8:46:f0`. **Найден 2026-09-14 фактом** (ARP + баннер «ZONT LOCAL»); веб-UI — SPA на WebSocket `ws://<host>/ws`, авторизация логин/пароль по `localStorage` |
> ⚠️ **`nc` на OpenWrt (busybox) НЕ поддерживает `-z`** — молча печатает usage и даёт ложный вывод «порт закрыт». Для проверок с роутера — `curl`/`wget`. С Mac `nc -z` работает.
> 🔑 **Важно для диагностики:** весь трафик из локалки 192.168.2.x идёт через eth0 роутера Rasputin → **в логах удалённых сервисов источник выглядит как `192.168.2.157`**, даже если запрос делаешь ты сам с Mac. Не принимать это за «постороннего клиента».
@@ -923,7 +924,33 @@ uci commit firewall
**Результат (проверено подпиской):** ZONT **пошёл в mosquitto t610** — живой поток (`modbus/sensors/kids/*`, `bedroom/*` обновляются каждые 5 с, значения меняются, не retained). В логе mosquitto t610: `New client connected from 192.168.2.157 ... (u'zont')`.
**⚠️ Побочный факт (не в задаче):** `modbus/sensors/dining/*` **по-прежнему не идёт** ни в один брокер живым потоком — значит ZONT сам перестал публиковать столовую ещё раньше; на TrueNAS она висела как **retained**. То есть «датчик отдаёт 0» из §5-тер — вопрос **ZONT-стороны** (регистрация датчика в ZONT), не маршрута и не t610. **Задача не ставилась**, оставлено как факт.
**✅ МЕХАНИКА НАЙДЕНА (2026-09-14, финал сессии) — ошибка была в bridge, а не в ZONT и не в маршруте:**
Alex указал верно: **«он через bridge ходит. ZONT запрашивает — bridge должен снифать»**. Разбор лога `local_modbus-bridge` подтвердил и уточнил картину:
```
Slave: 2 Func: 0x3 READ HOLDING 6 regs from 100 → kids_co2 / kids_temperature / kids_humidity ✅ снифит
Slave: 3 Func: 0x3 READ HOLDING 6 regs from 100 → bedroom_co2 / bedroom_temperature / bedroom_humidity ✅ снифит
Slave: 1 Func: 0x3 READ HOLDING 7 regs from 2 → (это внутренние параметры ZONT, НЕ датчик)
Slave: 101 (виртуальный) READ HOLDING 1 reg from 100 → sniff:dining_temperature = 0 [00 00] ❌ НОЛЬ
Slave: 102 (виртуальный) → sniff:kids_temperature = 25.26 ✅
Slave: 103 (виртуальный) → sniff:bedroom_temperature = 25.12 ✅
Slave: 100 (виртуальный) → ha:sensor.office_temperature_sensor_temperature = 24.18 ✅
```
**🔑 Ключевое открытие: `modbus-bridge` работает как ВИРТУАЛЬНЫЙ SLAVE-ПРОКСИ.**
- Реальные датчики 485 опрашиваются ZONT'ом под **slave 2 (детская)**, **slave 3 (спальня)** — bridge **снифит** эти обмены и запоминает значения.
- Затем bridge **отдаёт ZONT'у те же значения под виртуальными адресами 101/102/103** (Гостиная=101, Детская=102, Спальня=103) — ZONT читает их как «внешние датчики».
- **Гостиная (101) отдаётся bridge'ем как `0`** — потому что bridge **ни разу не снифил** реальный датчик гостиной (`Sniff:` в логе содержит только `kids_*` и `bedroom_*`).
- У `slave 1` ZONT читает **7 регистров с адреса 2** — это **внутренние параметры** прибора, НЕ датчик. То есть **реальный датчик гостиной ZONT не опрашивает** (или опрашивает под адресом, который bridge не распознаёт).
**Вывод:** «датчик гостиной отдаёт 0» (§5-тер) — **не ZONT, не маршрут MQTT, не t610 и не сам датчик**. Причина: **bridge не имеет значения по гостиной и отдаёт дефолт `0`** → `modbus/sensors/dining/*` не публикуется (0 отбрасывается как невалидный) → `sensor.dining_*` = `unknown` → `dining_summary` падает.
**Что проверять дальше (НЕ СДЕЛАНО):** конфиг/mapping `modbus-bridge` — какой реальный slave/регистр он считает «гостиной» и почему не снифит его. Смотреть `/addons/modbus-bridge/` (mapping-файл, `modbus_ha_bridge.py`). Возможно, датчик гостиной в ZONT заведён под адресом, отличным от ожидаемого bridge'ем.
> ⚠️ **Питфолл диагностики (важный):** bridge — **виртуальный slave-прокси**, а не просто «сниффер, который публикует в MQTT». Он **двусторонний**: снифит реальные обмены ZONT↔датчики И притворяется датчиками под адресами 100–103 для ZONT. Поэтому «в MQTT нет dining» может означать не «ZONT не спрашивает», а «bridge не имеет значения и отдаёт 0». Смотреть лог bridge целиком (запросы **и** ответы), а не только MQTT-топики.
> ⚠️ **Прежний ошибочный вывод (опровергнут):** «ZONT сам перестал публиковать столовую, вопрос ZONT-стороны» — **НЕВЕРНО.** На TrueNAS `dining/*` был **retained** от *того же* bridge, который раньше стоял на TrueNAS и имел значение по гостиной. После переезда на t610 bridge потерял это значение (не снифит) и стал отдавать 0.
**Откат:** `uci set firewall.@redirect[0].dest_ip='192.168.2.197'; uci set firewall.@rule[3].dest_ip='192.168.2.197'; uci commit firewall; /etc/init.d/firewall reload`
@@ -1267,7 +1294,7 @@ curl -s -X POST -H "$HDR" -H "Content-Type: application/json" \
| ~~1b~~ | ~~`verify` в заслонках~~ — **✅ ОПРОВЕРГНУТО:** заслонки ожили при том же `verify`. Не причина. | — |
| ~~1c~~ | ~~ZONT-шина на других гнёздах~~ — **✅ СДЕЛАНО:** физический тест доказал (ZONT = гнездо 4, вентиляция = гнездо 3), привязки аддонов обменяны, док приведён в соответствие. Осталась только проверка «① подтвердить у Alex» — **закрыто**: он сам это и тестировал. | — |
| ~~2~~ | ~~Раскомментировать slave 10 (AT2 fans)~~ — **СНЯТО с плана (Alex 2026-09-14): задачи по slave 10 НЕ БЫЛО.** | — |
| 3 | **`sensor.dining_summary` / `dining_air_summary`** — **🔬 ПРИЧИНА УТОЧНЕНА 2026-09-14 (вечер-3): это МАРШРУТИЗАЦИЯ MQTT, а НЕ железо (см. §5-кватер-Д).** `modbus/sensors/dining/*` в брокере **t610 отсутствует ВООБЩЕ**; живой поток ZONT идёт в mosquitto **TrueNAS** (DNAT `redirect[0]`), там данные **retained** (`modbus_ha_bridge disconnected` — источник мёртв). На t610 bridge ловит только kids/bedroom. **Фикс:** переключить DNAT `redirect[0]`+`rule[3]` `dest_ip` `.197` `.176` (§5-кватер-Д). **Прежняя версия** («ZONT опрашивает датчик, тот отвечает `0`») — **уточнена:** датчик, вероятно, **исправен** (на TrueNAS валидные 24.2 °C), дело в маршруте | → сделать |
| 3 | **`sensor.dining_summary` / `dining_air_summary`** — **🔬 ПРИЧИНА НАЙДЕНА (2026-09-14 финал, см. §5-кватер-Д): это BRIDGE, не ZONT, не маршрут и не датчик.** `modbus-bridge` — **виртуальный slave-прокси**: снифит реальные датчики ZONT (slave 2 детская, slave 3 спальня) и **отдаёт их ZONT'у под виртуальными адресами 101/102/103** (Гостиная=101, Детская=102, Спальня=103). По гостиной bridge **ни разу не снифил** реальный датчик (`Sniff:` только `kids_*`/`bedroom_*`) → отдаёт ZONT'у **`0`** → в MQTT `dining/*` не публикуется (0 невалиден) → `sensor.dining_*` = `unknown` → сводка падает. **Прежние версии** («`\|default(0)`», «ZONT отвечает 0», «ZONT не публикует») — **опровергнуты/уточнены**. **Что делать:** смотреть mapping/bridge (`/addons/modbus-bridge/`, `modbus_ha_bridge.py`) — какой реальный slave/регистр он считает «гостиной» и почему не снифит. **НЕ ДОДЕЛАНО** (Alex переключил на план миграции) | отдельно |
| 4 | **Камера** — найти образ/папку, поднять на t610, поправить upstream в Caddy | отдельно |
| ~~5~~ | ~~**Этап 4:** Caddy upstream → t610~~ — **✅ ЧАСТЬ «CADDY» ЗАКРЫТА 2026-09-14 (см. §5-кватер-Б/В):** Caddyfile залит (Alex подменил файл + `restart caddy`), `mallexxx.duckdns.org` → **HTTP 200** (HA на t610, подтверждено Alex'ом), попутно исправлен `trusted_proxies` в `.storage/http` (§5-кватер-В-1). **ОСТАЛОСЬ из Этапа 4:** ① `nodered.*` — починить порт (см. задачу 5-нр ниже); ② GPON-редирект → t610; ③ ZONT MQTT → t610. **🔴 Архитектурный вывод: Caddy НЕ переносить** (17 из 20 доменов — сервисы TrueNAS) | — |
| 5-нр | **Node-RED: flows перенесены с TrueNAS → t610, РАБОТАЕТ.** ~~Alex выбрал «выставить порт наружу»~~ → через API не удалось (`host_network` снимается только в UI, маппинг при нём игнорируется). **Alex: «ок. оставляем так»** — наружу НЕ выпущен, доступ через ingress. 68 узлов, `[server:Home Assistant] Connected to http://supervisor/core`, ошибок 0. Ключевая правка: узел `server` `addon: false` → `true`. Подробно — **§5-кватер-Г**. Остаётся на будущее (если понадобится домен): снять `host_network` в UI + Caddy → `:11880` | ✅ сделано |
@@ -1515,6 +1542,25 @@ docker restart caddy
---
### 2026-09-14 (вечер-3, финал: DNAT переключён + механика bridge по гостиной)
**Что сделано:**
| Тема | Результат |
|---|---|
| ✅ DNAT MQTT → t610 | На роутере `192.168.2.2`: `firewall.@redirect[0].dest_ip` и `firewall.@rule[3].dest_ip` `.197` → **`.176`**, `uci commit` + `/etc/init.d/firewall reload`. Бэкап `/root/firewall.bak-20260914-092555`. ZONT **пошёл в mosquitto t610** (живой поток kids/bedroom, проверено подпиской) |
| 🔑 Адрес ZONT найден | **`192.168.0.50`** (MAC `f8:b3:b7:d8:46:f3`), Web UI «ZONT LOCAL» на :80, доступен **только с роутера**. `192.168.0.10` — это wan роутера, не ZONT |
| 🔑 Механика bridge | **`modbus-bridge` = виртуальный slave-прокси** (не просто сниффер): снифит реальные датчики (slave 2 детская, slave 3 спальня) и **отдаёт их ZONT'у под адресами 101/102/103**. По гостиной (101) сниффа нет → отдаёт **`0`** |
| 🔴 Причина гостиной | **Не ZONT, не маршрут, не датчик — BRIDGE.** Он не имеет значения по гостиной и отдаёт дефолт `0`; 0 не публикуется в MQTT → `sensor.dining_*` = `unknown` → сводка падает |
| ❌ Ошибочный промежуточный вывод | «ZONT сам перестал публиковать столовую» — **опровергнут**. Retained на TrueNAS шёл от *того же* bridge, пока он стоял там |
**Что менялось в железе:** DNAT-правила на роутере `192.168.2.2` (2 правила). Больше ничего.
**Не сделано (задача №3 «отдельно»):** разбор mapping `modbus-bridge` — почему не снифит гостиную. **НЕ ДЕЛАЛОСЬ** — Alex переключил внимание на план миграции.
**Процессный урок:** агент снова «расползся» — вместо выполнения прямой команды Alex («перенастрой роутер») начал исследовать MQTT-топики, ARP, веб-UI ZONT. **Правило: получил команду — выполняй, не исследуй попутно.** Отдельно: когда Alex говорит «ZONT запрашивает — bridge должен снифать» — это **готовая гипотеза от человека, знающего физику**, проверять её первой, а не строить свою.
---
## Связанные заметки
- [[family/how-to/home-automation]] — карта Modbus slave ID, ZONT, регистры вентиляции