diff --git a/family/documents/home-automation-wishlist.md b/family/documents/home-automation-wishlist.md index adc79b1e..1dd3abcf 100644 --- a/family/documents/home-automation-wishlist.md +++ b/family/documents/home-automation-wishlist.md @@ -70,7 +70,7 @@ related: ### 7. Энергетика — что реально жрёт ZONT-реле котлов уже дают статусы; 2 Zigbee-розетки с мониторингом есть (`recirculation_pump`, `heating_cable_plug`). **Добавить:** токовые клещи (Zigbee) на ввод/котёл → видно, где деньги. -> ✅ **УТОЧНЕНО 2026-09-16:** `0 Вт / 0 кВт·ч` — **норма, а не поломка**: `switch.heating_cable_plug` = `off`, поэтому нагрузка не потребляет, при этом `voltage = 223 В` (розетка жива). `sauna` в `state.json` = `null`. Полный разбор железа и **расчёт порогов включения греющего кабеля** — [[family/tech/heating-cable-water-inlet]]. +> ✅ **УТОЧНЕНО 2026-09-16:** `0 Вт / 0 кВт·ч` — **норма, а не поломка**: `switch.heating_cable_plug` = `off`, поэтому нагрузка не потребляет, при этом `voltage = 223 В` (розетка жива). `sauna` в `state.json` = `null`. ### 8. Дашборд + алерты в Telegram Без этого автоматика «невидима». Один экран + пуш на всё критичное. Частично уже в вишлисте UI (см. §4). diff --git a/family/how-to/ha-automations.md b/family/how-to/ha-automations.md index 81358a46..0eb209ab 100644 --- a/family/how-to/ha-automations.md +++ b/family/how-to/ha-automations.md @@ -2,30 +2,17 @@ > **Справочник логики автоматизаций** (`automations.yaml` на t610). Топология/команды/Modbus — [[family/how-to/home-automation]]. -> 🟢 **АКТУАЛЬНО 2026-09-16: 25 АВТОМАТИЗАЦИЙ — 24 `on`, 1 `off` (`Ventilation automation on`, намеренно), `unavailable` = 0.** Zigbee работает на ZHA. +> 🟢 **25 АВТОМАТИЗАЦИЙ — 24 `on`, 1 `off`** (`Ventilation automation on`, намеренно), `unavailable` = 0. Zigbee работает на ZHA. > -> **➕ 2026-09-16: добавлена `Греющий кабель: управление`** (`automation.greiushchii_kabel_upravlenie`, id `heating_cable_ctl_0001`) — управление вводом воды по `min(ZONT-улица, прогноз met.no 24ч)`, пороги −8/−3 °C (выдержка 12 ч) + аварийный −20 °C + fail-safe. Расчёт обоснования порогов — §7.1. +> **Состав:** 12 контроля батарей (§5) + 2 циркуляция ГВС + 2 свет кабинета + 2 подсветка лестницы + 2 ночной свет душевой + 2 диммер спальни + 1 протечка котельная + 1 вентиляция + **1 греющий кабель ввода воды (§7)**. > -> 📌 **Сверка счёта:** в §1 ниже упоминается «26» — это счёт **включая 2 удалённые батарейные**, которые ещё числились сиротами в реестре. После чистки реестра было **24**, после 2026-09-16 — **25**. Брать 25. +> **Ключевые факты:** +> - 🔴 **`entity_id` автоматизаций HA перегенерирует по alias** — искать по `attributes.id`, не по `entity_id`. +> - 🔴 **REST `GET/POST /api/config/automation/config/` использует поля во множественном числе** — `triggers`/`conditions`/`actions` (в файле — единственное). Ошибка молча уходит в пустоту: POST → `200 ok`, значения НЕ меняются. **Всегда читать обратно.** +> - ⚠️ **Кнопка спальни** шлёт `remote_button_short_press` только после `zha/devices/reconfigure`. > -> **➕ Добавлено в этот вечер: 12 автоматизаций контроля батарей** (id `8800000000000`…`8800000000011`, все `on`). Порог **20 %**, выдержка **2 ч**, двойной канал: `persistent_notification` + push `notify.mobile_app_sm_s931b`; при возврате заряда уведомление гасится (`notification_id: bat_`). Детали — §5. -> ⛔ **Удалены 2 прежние батарейные** (`1773451323415`, `1773459663218`) — были с порогом 10 и без push. Их осиротевшие записи в реестре вычищены (питфолл §5.1). -> 🔄 **Переименованы** ссылки после единообразия ID: `light.night_light_shower_2` → `light.dushevaia_night_light`, `sensor.tz3000_akqdg6g7_ts0201_batareia` → `sensor.kabinet_temperature_battery` → `sensor.garderobnaia_temperature_battery` (датчик перенесён в Гардеробную). -> 🔴 **`entity_id` автоматизаций HA перегенерировал по alias** — искать автоматизацию по `attributes.id`, не по `entity_id`. Пример: `automation.datchik_protechki_kotelnaia_batareia` → `automation.batareia_kotelnaia_datchik_protechki`. -> 📄 Полный отчёт о работах: [[family/plans/t610-zigbee-ids-battery-freshsensors-modbus]]. -> -> Переезд Zigbee Z2M → ZHA выполнен. Автоматизации были сломаны не по `entity_id`, а глубже — они ссылались на `device_id` + внутренний `entity_id`-UUID, а устройства Z2M удалены. **Пересобраны заново** на ZHA-шные `device_id` + актуальные `entity_id`. -> -> **Что доделано после первичной пересборки:** -> - ✅ **4 «призрака»-автоматизации УДАЛЕНЫ** из `core.entity_registry` (тела не существовало: `GET /api/config/automation/config/` → 404). Файл: 12 блоков vs 16 сущностей. -> - ✅ **2 сценария подсветки лестницы ПЕРЕСОЗДАНЫ** на `sensor.light_sensor_stairs_illuminance` (`light.light_stairs_left`/`_right`), оба `on`. -> - ✅ **`Toggle Dimmer bed` / `Dimmer bed cycle` — залиты и `on`**: триггер от кнопки, действия на `light.bed_dimmer` (было — реле сауны). -> - ⚠️ **Кнопка спальни:** события `remote_button_short_press` идут **только после `zha/devices/reconfigure`**. Дамп кластеров ДО reconfigure вводит в заблуждение. -> -> **Итог на 2026-09-15 (поздний вечер): 26 автоматизаций, `unavailable` = 0.** -> -> **Бэкап:** `/config/automations.yaml.bak-dimmer-fix` (последняя правка) + `.bak-before-autofix-20260915-212636` + `.bak-zha-20260915-211613` ✅ -> **Рецепт пересборки + питфоллы — [[family/tech/zigbee-t610-z2m-i-zha]].** +> **Бэкапы перед правками:** `automations.yaml.bak-cable3-20260915-*` (кабель), `.bak-preids-*`, `.bak-gard-*` (единообразие ID). Локальные копии в `~/tmp-t610/`. +> 📄 Рецепт пересборки после Z2M→ZHA и питфоллы — [[family/tech/zigbee-t610-z2m-i-zha]]. > > 🔴 **ПИТФОЛЛЫ, найденные при починке:** > 1. **`device`-триггер батареи — тип `battery_level`, НЕ `battery`.** Иначе `Automation ... failed to setup triggers and has been disabled`. @@ -36,9 +23,8 @@ ## 1. Где живёт - **Файл:** `/config/automations.yaml` в HA Core на t610. -- **Всего:** **25 автоматизаций — 24 `on`, 1 `off`** (`Ventilation automation on`, намеренно, `last_triggered` 12 марта), **`unavailable` = 0**. Файл = 780 строк (650 + 130 новой автоматизации кабеля). -- **Бэкапы перед правками 2026-09-16 (кабель):** `/config/automations.yaml.bak-cable-20260915-234837`, `.bak-cable2-*`, `.bak-cable3-*`; локально — `~/tmp-t610/bak-cable-20260915-234837/automations.yaml`. -- **Бэкапы перед правками 2026-09-15 (поздний вечер):** `/config/automations.yaml.bak-preids-20260915-223427`, `/config/automations.yaml.bak-gard-20260915-225404` (перед переносом датчика в Гардеробную); рабочая копия — `~/tmp-t610/autfix-20260915-223427/automations.yaml` (плюс `.pre-bat` — до добавления батарейных). +- **Всего:** **25 автоматизаций — 24 `on`, 1 `off`** (`Ventilation automation on`, намеренно), **`unavailable` = 0**. Файл = 780 строк. +- **Бэкапы перед правками:** `automations.yaml.bak-cable3-` (кабель, 2026-09-16), `.bak-preids-*`, `.bak-gard-*`; локально — `~/tmp-t610/bak-cable-20260915-234837/automations.yaml`. - **Удалены 4 «призрака»** (записи в реестре без тела): `svetlo_vykl_osveshchenie_lestnitsy`, `temno_vkl_podsvetku_lestnitsy`, `datchik_osveshchennosti_lestnitsa_batareia`, `light_switch_bed_batareia`. Тела не было (`config/automation/config/` → 404) — лестничные сценарии **пересозданы заново** с теми же id. - **Локальная копия:** `~/tmp-t610/automations/automations.yaml`; после пересборки — `~/tmp-t610/automations-new.yaml`, `~/tmp-t610/automations-fixed.yaml`. - **Читать живьём через API** (не по памяти): @@ -285,8 +271,8 @@ actions: > ⚠️ **WS `render_template` возвращает `null`** даже для `{{ 2 + 2 }}` — шаблоны проверять только через REST `POST /api/template`. > ⚠️ **`automation.trigger` через WS не обновляет `last_triggered`** — прогон подтверждать иначе (значения в `variables`, лог HA). -📄 **План: [[family/plans/t610-heating-cable-automation]]** -🧰 **Инструменты:** `~/tmp-t610/ha_ws.py forecast `, `verify_cable.py`, `rest_tpl.sh`, `verify_calc.sh`. +📄 **План (выполнен):** `family/plans/t610-heating-cable-automation.md` +🧰 **Инструменты:** `~/tmp-t610/ha_ws.py forecast `, `verify_cable.py`, `verify_calc.sh`, `rest_tpl.sh`. ### ⚠️ Не проверено физически diff --git a/family/how-to/home-automation.md b/family/how-to/home-automation.md index 10712bf9..3e56af07 100644 --- a/family/how-to/home-automation.md +++ b/family/how-to/home-automation.md @@ -2,13 +2,13 @@ title: "🏠 Домашняя автоматизация" aliases: [Умный дом, Home automation, HA, Zigbee, Modbus, вентиляция, t610, RCU stall, USB reset] tags: [family, how-to, smarthome] -updated: 2026-09-16 (греющий кабель ввода воды автоматизирован — `automation.greiushchii_kabel_upravlenie`, пороги −8/−3 °C / 12 ч, прогноз через `action: weather.get_forecasts`; автоматизаций 25. §2. H2000_PRO: единицы °F→°C через `options_domain: sensor.private`; питфолл доступа к API с Mac — только через SSH. Справочник кабеля: [[family/tech/heating-cable-water-inlet]]) +updated: 2026-09-16 (греющий кабель ввода воды автоматизирован — `automation.greiushchii_kabel_upravlenie`, пороги −8/−3 °C / 12 ч, прогноз через `action: weather.get_forecasts`; автоматизаций 25. §2. H2000_PRO: единицы °F→°C через `options_domain: sensor.private`; питфолл доступа к API с Mac — только через SSH) --- # 🏠 Домашняя автоматизация > **Единственный справочник по домашней автоматизации.** Всё: топология, железо, Zigbee, Modbus, доступ, команды, сценарии, питфоллы. -> **Автоматизации** (16 шт., логика, дефекты) — [[family/how-to/ha-automations]]. +> **Автоматизации** (25 шт., логика, дефекты) — [[family/how-to/ha-automations]]. > 📄 Правка этой доки не появится на телефоне после `git push` — нужен прогон sync-петли: [[family/how-to/vault-sync-pipeline]]. > 🧰 Локальные скрипты диагностики: `~/tmp-t610/diag.sh`, `diag2.sh`, `diag3.sh`, `diag4.sh`, `stats.sh` (снимаются на t610 через `scp` + `sh /tmp/…`). @@ -154,20 +154,20 @@ ssh -i ~/.ssh/id_rsa root@192.168.2.176 '<команда>' # аддон core_ |---|---|---|---|---| | Terminal & SSH | `core_ssh` | SSH | 22 | ✅ started | | Mosquitto broker | `core_mosquitto` | MQTT | 1883 | ✅ started | -| Zigbee2MQTT | `45df7312_zigbee2mqtt` | Zigbee v2.14.1 | 8485 | ⏸ **stopped** (2026-09-15 ночь-12 — освобождён стик под ZHA) | +| Zigbee2MQTT | `45df7312_zigbee2mqtt` | Zigbee v2.14.1 | 8485 | ⏸ **stopped** (2026-09-15 — освобождён стик под ZHA) | | Node-RED | `a0d7b954_nodered` | вентиляция CO₂ | ingress | ⏸ **stopped** (2026-09-15) | | mbusd | `local_mbusd` | шлюз Modbus RTU→TCP | 502 | ✅ started | | modbus-bridge | `local_modbus-bridge` | снифф ZONT-шины | — | ✅ started | | ustreamer (кастомный) | `local_ustreamer` | камера: JPEG раз в N сек | 8090 | ✅ started | -> 🔴 **2026-09-15 (ночь-4): `go2rtc` и `go2rtc-hardware` УДАЛЕНЫ** (`stop` + `uninstall` через Supervisor API). Оба были источником RCU stall (§3.6). -> 🗑 **2026-09-15 (ночь-6): `core_configurator` (File editor) УДАЛЁН.** Веб-редактор `/config` не использовался, зато **писал `GET /` каждые 30 с** и на каждый запрос логировал `502 Bad Gateway` (HA Core лежал) → цикл ретраев + запись лога = постоянная I/O-нагрузка на слабом хосте. -> ⏸ **2026-09-15 (ночь-6): `a0d7b954_nodered` ОСТАНОВЛЕН** (не удалён) — жирный процесс на 1.4 ГБ RAM, для камеры не нужен. +> 🔴 **`go2rtc` и `go2rtc-hardware` УДАЛЕНЫ** (2026-09-15, `stop` + `uninstall` через Supervisor API). Оба были источником RCU stall (§3.6). +> 🗑 **`core_configurator` (File editor) УДАЛЁН.** Веб-редактор `/config` не использовался, зато **писал `GET /` каждые 30 с** и на каждый запрос логировал `502 Bad Gateway` (HA Core лежал) → цикл ретраев + запись лога = постоянная I/O-нагрузка на слабом хосте. +> ⏸ **`a0d7b954_nodered` ОСТАНОВЛЕН** (не удалён) — жирный процесс на 1.4 ГБ RAM, для камеры не нужен. > ✅ **Текущий список — 7 аддонов** (проверен `GET /addons`): `core_ssh`, `core_mosquitto`, `a0d7b954_nodered` (**stopped**), `45df7312_zigbee2mqtt`, `local_mbusd`, `local_modbus-bridge`, `local_ustreamer`. > 💡 **Диагностический признак:** аддон в `state: error`, но в логе `Service exited with code 256 (by signal 15)` → это **нормальная остановка**, а `error` — финальный статус. Читать лог, а не только `state`. -> 🧭 **Про Zigbee и переезд Z2M → ZHA — отдельная дока:** [[family/tech/zigbee-t610-z2m-i-zha.md]]. Кратко: HA штатно Zigbee поддерживает (ZHA встроена, стик тот же); **`coordinator_backup.json` у ember-адаптера ВСЕГДА пуст** — перенос «без спаривания» держится на **NVRAM стика**, а не на файле. 🔑 **ZHA сама принимает устройства после `reuse_settings`** — «Add device» и окно спаривания НЕ нужны (проверено: 12 из 16 подхватились без действий). Ручного остаётся: **переименовать сущности** (ZHA даёт технические имена `light.tz3000_*`) + **разбудить 4 батарейных**. **Статус на 2026-09-15 ночь-12: Z2M остановлен, ZHA создана, переезд идёт.** +> 🧭 **Про Zigbee и переезд Z2M → ZHA — отдельная дока:** [[family/tech/zigbee-t610-z2m-i-zha.md]]. Кратко: HA штатно Zigbee поддерживает (ZHA встроена, стик тот же); **`coordinator_backup.json` у ember-адаптера ВСЕГДА пуст** — перенос «без спаривания» держится на **NVRAM стика**, а не на файле. 🔑 **ZHA сама принимает устройства после `reuse_settings`** — «Add device» и окно спаривания НЕ нужны (проверено: 12 из 16 подхватились без действий). Ручного остаётся: **переименовать сущности** (ZHA даёт технические имена `light.tz3000_*`) + **разбудить 4 батарейных**. **Опции аддонов** меняются только через Supervisor API (не `ha apps`, который умеет лишь start/stop/rebuild). Для PATCH нужен **ПОЛНЫЙ набор опций**, иначе 400. @@ -189,70 +189,52 @@ ha apps restart local_modbus-bridge > ⚠️ Два CH340 **без серийников** → by-id идентичен. Только **by-path**. > `uart: true` в конфиге аддона — udev-алиасы не нужны. В аддоне нет `udevadm`, `/etc/udev/rules.d`. -### 3.1. RCU stall + смерть хоста — что установлено и что ОПРОВЕРГНУТО +### 3.1. RCU stall — причина найдена и устранена -> 🔴 **СТАТУС КАНОНА (2026-09-15, ночь-4):** первопричина RCU stall **НАЙДЕНА И УСТРАНЕНА**. Это **ffmpeg-транскод камеры в go2rtc**: `[exec] timeout` — ffmpeg не укладывается в таймаут, каждый запрос стрима рождал процесс, который жрёт CPU и читает `/dev/video0` с медленного HDD. Именно это (а не камера сама по себе и НЕ память) укладывало хост. **Оба аддона go2rtc удалены**, вместо них `local_ustreamer` (одиночный JPEG по запросу). Детали — §3.6. -> ⛔ Версия «камера на EHCI/USB2 → порт виноват, лечится перестановкой в xHCI» — **ОПРОВЕРГНУТА**: после чистого старта сбросы камеры вернулись и на xHCI (`usb 3-1: reset high-speed ... using xhci_hcd`, t=113 и t=126). -> ⛔ Версия «носитель деградировал» — **ОПРОВЕРГНУТА** (ложный замер, см. §3.4). -> ⛔ Версия «Memory pressure → OOM» — **ОПРОВЕРГНУТА**: `MemFree` падает как **следствие** I/O-шторма, не как причина. +**Первопричина:** ffmpeg-транскод камеры в `go2rtc`. Каждый запрос стрима рождал процесс ffmpeg, который молотил CPU на 2 слабых ядрах и читал `/dev/video0` с HDD 5400 rpm. Не укладывался в таймаут → `[exec] timeout` → процессы копились → load 9.73 на 2 ядрах, `pressure/io 92%`, `MemFree 16 МБ` → RCU grace period не проходит → stall. -**Что доказано фактами:** +**Решение:** оба аддона go2rtc удалены, вместо них `local_ustreamer` (одиночный JPEG по запросу). Детали — §3.6. + +**Что опровергнуто фактами:** + +| Версия | Почему неверна | +|---|---| +| «Порт виноват (EHCI→xHCI)» | После чистого старта сбросы вернулись и на xHCI | +| «Носитель деградировал» | Ложный замер — `find`/`du` сам создаёт I/O-шторм (§3.4) | +| «Memory pressure → OOM» | `MemFree` падает как **следствие** I/O-шторма, не причина | +| «`OOM is now expected behavior` = кончилась память» | Это голодание kthread, не OOM | + +**Что доказано:** | Наблюдение | Значение | |---|---| -| `sda` = **WDC WD2500BEVT** (250 ГБ, 5400 rpm, `rotational=1`) | Носитель — ноутбучный **HDD**, не SD/eMMC и не SSD | -| Load 4.47 → `% io 90`, `% sirq 10` в момент приступа | Нагрузка **прерыванийная**, не вычислительная | -| Камера `046d:0825` сбрасывалась на EHCI (USB2-1) **и** на xHCI (USB3-1) | Порт — не причина сбросов | -| `runtime_suspended_time` 124 с на EHCI, 108 с на xHCI | Камера **засыпает и не просыпается** на обоих контроллерах | -| `bMaxPower = 500 mA` | Версия «нехватка питания» остаётся живой, не проверена | +| `sda` = WDC WD2500BEVT, 5400 rpm, `rotational=1` | Носитель — HDD, не SD/eMMC | +| Load 4.47 → `% io 90`, `% sirq 10` | Нагрузка прерыванийная, не вычислительная | +| Камера сбрасывалась и на EHCI, и на xHCI | Порт — не причина | +| `bMaxPower = 500 mA` | Версия «нехватка питания» не проверена | -> ⚠️ **Строка «OOM is now expected behavior» — НЕ диагноз OOM.** Это стандартное предупреждение ядра о голодании kthread. Память тут ни при чём. +**Почему 2 ядра не спасают:** RCU grace period требует quiescent state на **всех** CPU. Залипло одно — второй тоже не прогрессирует. Контейнерные лимиты бесполезны: hardirq обрабатывает ядро. -**Почему 2 ядра не спасают:** нагрузка не вычислительная, а прерыванийная. RCU grace period требует прохождения quiescent state на **ВСЕХ** CPU; залипло одно — второй тоже не может прогрессировать, и htop показывает 100% на обоих. Контейнерные лимиты бесполезны: hardirq обрабатывается ядром. `rcu_preempt` — ядровой kthread, он starved не потому что его «съели», а потому что планировщик не может его разбудить. +### 3.6. go2rtc → local_ustreamer: почему -### 3.6. ✅ ПЕРВОПРИЧИНА RCU stall — ffmpeg-транскод go2rtc +**Механизм поломки:** `go2rtc` не отдаёт MJPEG напрямую — он запускал внешний `ffmpeg` для транскода MJPEG → H.264. На t610 `libx264` в реальном времени не успевает: +1. Каждый запрос стрима рождает новый процесс ffmpeg. +2. Процесс молотит CPU и читает `/dev/video0` с медленного HDD. +3. `[exec] timeout` → поток не отдаётся → `broken pipe`. +4. При шторме процессов load 9.73 на 2 ядрах → RCU stall. -**Установлено 2026-09-15 (вечер-3)** по логу аддона `a889bffc_go2rtc`: +**Замеры шторма:** -``` -[exec] timeout source="exec:ffmpeg -hide_banner -v error -f v4l2 -input_format mjpeg \ - -i /dev/video0 -c:v libx264 -g 50 -profile:v high -level:v 4.1 -preset:v superfast \ - -tune:v zerolatency -pix_fmt:v yuv420p -an -vf \"transpose=1\" ... -f rtsp rtsp://127.0.0.1:8554/" -WRN [rtsp] error="streams: exec: timeout" stream=usb_camera_h264 -ERR mjpeg.go:126 > error="write tcp ...:1984->...: broken pipe" -``` - -**Механизм:** `go2rtc` не отдаёт MJPEG напрямую, а **запускает внешний `ffmpeg`** для транскода MJPEG → H.264. На t610 (2 слабых ядра + HDD 5400 rpm) `libx264` в реальном времени **не успевает**: - -1. Каждый запрос стрима (открытие камеры в HA UI на телефоне) рождает **новый процесс ffmpeg**. -2. ffmpeg молотит CPU и читает `/dev/video0` с медленного HDD. -3. Не укладывается в таймаут → `[exec] timeout` → поток не отдаётся. -4. Клиент (телефон) отваливается → `broken pipe`. -5. При шторме запросов процессы ffmpeg копятся → load 9.73 на 2 ядрах, `pressure/io 92%`, `pressure/memory 57%`, `MemFree 16 МБ` → RCU grace period не проходит → **RCU stall**. - -> 🔴 **Итог: камера роняет хост не «железом», а транскодом.** Порт, EHCI/xHCI, автосон, 500 мА — всё это **следствия или второстепенное**. Виновник — CPU-bound транскод на неподходящем железе. - -**Замеры шторма (2026-09-15):** - -| Метрика | Норма (чистый фон) | В шторме | +| Метрика | Норма | В шторме | |---|---|---| | `load average` | 0.75–1.7 | **9.73** | -| `pressure/io some avg10` | ~16 % | **92.27 %** | -| `pressure/memory some avg10` | ~0 % | **57.18 %** | +| `pressure/io some avg10` | ~16 % | **92 %** | +| `pressure/memory some avg10` | ~0 % | **57 %** | | `MemFree` | 332 МБ | **16 МБ** | -| `% io` в top | 0 % | **50–66 %** | -**Как починено (✅ ПРИМЕНЕНО 2026-09-15, ночь-4):** +**Решение:** оба аддона go2rtc удалены, вместо них `local_ustreamer` — Python-сервер на `/frame` поднимает ffmpeg только по запросу клиента и снимает **один кадр**. H.264 нет вообще. Результат: load 0.76, `pressure/io` 3.26 %. -1. ⭐ **Транскод убран полностью.** Оба аддона go2rtc **удалены** (`stop` + `uninstall`). Вместо них — собственный аддон **`local_ustreamer`** v2.0.0: Python-сервер на `/frame` поднимает `ffmpeg` **только по запросу клиента**, снимает **один кадр** с `/dev/video0`, поворачивает и отдаёт JPEG. H.264 нет вообще → CPU не тратится в фоне. Детали — §4 «Данные камеры». -2. **Оставлен один потребитель камеры** вместо двух (`go2rtc` + `go2rtc-hardware` — оба снесены). -3. Альтернатива «облегчить ffmpeg» (`-preset ultrafast`, 320×240, `-r 10`) — **не понадобилась**: реалтайм-транскода больше нет. - -**Результат:** load вернулся к 0.76, `pressure/io` 3.26 %, 100 % idle. Хост больше не укладывается при обращении к камере. - -> ⚠️ **Осиротевший `/config/go2rtc.yaml`** (1085 байт) остался на месте — go2rtc удалён, конфиг читать нечем. Судьба ждёт решения Alex. -> ⛔ Раньше конфиг жил в опциях аддона `a889bffc_go2rtc` (`.data.options` через `/info`); после удаления аддона опции исчезли. -> ⚠️ Транскод-строка с `-vf \"transpose=1\"` = поворот на 90° (`#rotate=90`), см. §4 «Данные камеры». +> ⚠️ **Осиротевший `/config/go2rtc.yaml`** (1085 байт) остался — go2rtc удалён, конфиг читать нечем. ### 3.7. 🔴 Watchdog аддонов ВЫКЛЮЧЕН по умолчанию — упавший аддон не поднимется сам @@ -284,41 +266,17 @@ curl -s -X POST -H "$H" -H "$CT" -d '{"watchdog":true}' \ | `local_mbusd` | ✅ true | | `local_modbus-bridge` | ✅ true | | `a0d7b954_nodered` | ✅ true | -| ~~`a889bffc_go2rtc`~~ | ⛔ аддон удалён 2026-09-15 (ночь-4) | +| ~~`a889bffc_go2rtc`~~ | ⛔ аддон удалён 2026-09-15 | > ⚠️ Для `local_ustreamer` watchdog **не включался** — проверить, если камера должна подниматься сама. > 📌 Эндпоинт: **`POST /addons//options`** с `{"watchdog":true}`. Отдаёт `{"result":"ok","data":{}}`. Для PATCH нужен ПОЛНЫЙ набор опций (питфолл 15), но `watchdog` в одиночку проходит. -### 3.8. 🔴 Zigbee2MQTT — падение на MQTT-подключении при старте (баг логгера) +### 3.8. Zigbee2MQTT — остановлен -**Симптом (лог аддона):** -``` -z2m: Connected to MQTT server -z2m: MQTT failed to connect, exiting... (write after end) -NodeError: write after end - at writeAfterEnd (.../readable-stream/lib/_stream_writable.js:264) - ... winston/lib/winston/logger.js ... -Node.js v24.18.1 -``` -Затем процесс умирает → аддон в `state: error`. +Z2M **остановлен** с 2026-09-15 (стик отдан ZHA), данные целы в `/config/zigbee2mqtt/`. Всё, что ниже относилось к его падениям, — история. -**Это НЕ проблема serial-порта.** В логе Mosquitto видно, что Z2M **подключился** и сам закрыл соединение через 3 с: -``` -19:16:49 New client connected from 172.30.33.4 as mqttjs_250063e1 (u'zont') -19:16:52 Client mqttjs_250063e1 disconnected: connection closed by client -``` - -**Причина:** внутренний баг Z2M (v2.14.1-1) — падение в `winston`-логгере при записи в уже закрытый поток. Триггерится, когда MQTT-брокер отвечает с задержкой (параллельный старт: Z2M в 19:16, Mosquitto в 19:08 ещё дорегистрировался). - -**Что НЕ надо проверять (проверено, всё исправно):** -- `serial.port` в `/config/zigbee2mqtt/configuration.yaml` = `by-id/usb-Inswift_Zigbee_ZBP-MG21_535A000001-if00` — **by-id, не by-path**, поэтому перестановка USB-портов его **не ломает**. Ссылка резолвится в `ttyACM0` ✅. -- `mqtt.server: mqtt://core-mosquitto:1883`, user `zont` — верны. -- Стик `1a86:55d4` на `USB1-2` → `ttyACM0` — на месте. - -**Фикс:** `ha apps restart 45df7312_zigbee2mqtt` (или `ha addons restart`), после того как Mosquitto стабилен. Плюс включён watchdog (§3.7) — теперь поднимется сам. - -> ⚠️ Если при рестарте ответ `Error: Another job is running for job group app_` — предыдущий рестарт ещё идёт, **подождать**, не долбить повторно. +> 📌 На будущее, если Z2M понадобится снова: он падает при старте с `MQTT failed to connect, exiting... (write after end)` в `winston`. **Это не serial-порт** — в логе Mosquitto видно, что Z2M подключился и сам закрыл соединение через 3 с. Причина — баг логгера Z2M v2.14.1 при задержке ответа брокера. Лечится рестартом после стабилизации Mosquitto. Проверено: `serial.port` = `by-id/...` (перестановка USB его не ломает). **Диагностика при «HA не отвечает» — порядок:** 1. Пинг + ARP хоста (`/sbin/ping`, `/usr/sbin/arp -an`) — жив ли вообще. `ARP no entry` = L2-ответа нет. @@ -473,7 +431,7 @@ IEEE-адреса — источник истины `/config/zigbee2mqtt/configu **Logitech `046d:0825`** (счётчик газа BK-G4T), отдаёт только MJPEG. -> 🔴 **АРХИТЕКТУРА СМЕНИЛАСЬ (2026-09-15, ночь-4) — go2rtc БОЛЬШЕ НЕТ.** +> 🔴 **АРХИТЕКТУРА СМЕНИЛАСЬ — go2rtc БОЛЬШЕ НЕТ.** > Оба аддона go2rtc **удалены**. Камера теперь обслуживается **собственным аддоном `local_ustreamer`** (порт **8090**): > ``` > GET http://192.168.2.176:8090/frame → JPEG 480×640, ~19 КБ, ~4.7 с @@ -481,7 +439,7 @@ IEEE-адреса — источник истины `/config/zigbee2mqtt/configu > **Принцип:** Python HTTP-сервер на `/frame` запускает `ffmpeg` **только когда есть клиент**, снимает **один кадр**, поворачивает (`transpose`) и отдаёт JPEG. Никакого H.264, никакого реалтайм-транскода, никакого постоянного процесса — снимает и CPU-жор, и RCU stall. > > ⚠️ **ОРИЕНТАЦИЯ — НЕ ЗАКРЫТО:** сейчас в фильтре `transpose=1` (90° по часовой), счётчик ложится на бок. Нужен **`transpose=2`** (90° против часовой). Правка в `/addons/ustreamer/` + rebuild аддона. -> ⚠️ **ПОДКЛЮЧЕНИЕ К HA — ДИАГНОЗ ГОТОВ, ПРАВКА НЕ ВНЕСЕНА (2026-09-15, ночь-5).** +> ⚠️ **ПОДКЛЮЧЕНИЕ К HA — ДИАГНОЗ ГОТОВ, ПРАВКА НЕ ВНЕСЕНА.** > Сущность в HA уже есть — `camera.192_168_2_176`, но она **не обновляется**, потому что интеграция **Generic Camera** (не YAML!) настроена на мёртвые адреса. Полные опции entry: > ```json > entry_id: 01M2FX50K72X2RSYY549QSG3XP domain: generic title: 192_168_2_176 @@ -797,7 +755,7 @@ bedroom_co2: correction_offset: -495 → 589.5 − 495 = 94.5 ❌ (в HA **Сырой float32 УЖЕ в ppm** — 846.9 ppm для детской и 589.5 ppm для спальни правдоподобны. Обе коррекции — **мусор от старых попыток парсинга** (подбирались, когда парсер читал мало байт). Температура/влажность работают правильно, потому что их `correction_offset: -4.5` подобран верно. -### ✅ ФИКС ВЫПОЛНЕН (2026-09-15, ночь-22:19–22:25) — подтверждён фактом +### ✅ ФИКС ВЫПОЛНЕН — подтверждён фактом 1. ✅ Бэкап: `data/config.template.tmpl.bak-co2fix-20260915-221932` 2. ✅ Удалены **обе строки целиком** (awk-скрипт, не perl — **на хосте t610 perl НЕТ**, `perl: command not found`): @@ -839,36 +797,47 @@ ssh root@192.168.2.176 'ha apps logs local_modbus-bridge | grep -E "Raw RTU|→ ## 8. Текущее состояние -> 🕐 Обновлено **2026-09-16** — автоматизация греющего кабеля ввода воды загружена и работает; баг CO2 закрыт (§9), Zigbee переехал на ZHA, камера на `local_ustreamer`. +> 🕐 Обновлено **2026-09-16**. -- ✅ **ГРЕЮЩИЙ КАБЕЛЬ ВВОДА ВОДЫ АВТОМАТИЗИРОВАН (2026-09-16):** `automation.greiushchii_kabel_upravlenie` (id `heating_cable_ctl_0001`), `on`. Пороги по `eff = min(ZONT-улица, прогноз met.no 24ч)`: ВКЛ `≤ −8 °C` (выдержка 12 ч), ВЫКЛ `≥ −3 °C` (12 ч), аварийный `≤ −20 °C` (без выдержки), fail-safe при отвале датчика, алерт обрыва при `power < 5 W`. Прогноз — `action: weather.get_forecasts` + `response_variable` (в Jinja недоступен). Обоснование порога: `d_fn = 0,23·√63,9 = 1,84 м` (суглинок), труба на 4 м не замерзает — опасна только бетонная подушка 30 см. Полный расчёт: [[family/tech/heating-cable-water-inlet]]. **Автоматизаций стало 25** (24 `on`). ⚠️ Физически не проверено: розетка ни разу не включалась (`off`, `0 W`). -- ✅ **MODBUS CO2 ПОЧИНЕН (2026-09-15, ночь-22):** в `data/config.template.tmpl` убраны мусорные `correction_offset: -925` (kids_co2) и `-495` (bedroom_co2); `rebuild` + `start` аддона. Было **−76 / 94**, стало **848 / 599 ppm**. Все три slave (dining/kids/bedroom) публикуют каждые ~10 с, значения правдоподобны. Бэкап `.bak-co2fix-20260915-221932`. Детали — §9. -- ✅ **Сводки `sensor.*_summary` ИСПРАВНЫ** — `dining 24° 519ppm`, `kids 24° 849ppm`, `bedroom 25° 599ppm`, `dining_air 25tvoc 6pm`. Правка `configuration.yaml` **не вносилась** (ложная тревога). ⚠️ Прежняя запись про `TemplateError: round got invalid input 'unknown'` на `sensor.bedroom_summary` — при живых данных не воспроизводится (ошибка была из-за `unavailable` до фикса). +**Работает:** -- ✅ **КАМЕРА ПОЧИНЕНА (архитектурно):** оба аддона go2rtc (обычный + hardware) **удалены** через Supervisor API. Вместо них — собственный аддон **`local_ustreamer`** v2.0.0, порт **8090**: `GET /frame` → JPEG 480×640, ffmpeg поднимается **только при клиенте** и снимает **один кадр**. Реалтайм-транскода H.264 больше нет → причина RCU stall устранена. См. §3.6, §4. -- ✅ **Хост стабилен:** load 0.76, `pressure/io` 3.26 %, 100 % idle. Проверено после сноса. -- ✅ **Все `.bak-*` снесены с t610:** `go2rtc.yaml.bak-*` (3), `/config/*.bak-*` (11), `/config/zigbee2mqtt/*.bak-*` (6) — итого **20 файлов**. Проверено: остатков нет. -- ✅ **Список аддонов после чистки (7):** `core_ssh`, `core_mosquitto`, `a0d7b954_nodered` (⏸ stopped), `45df7312_zigbee2mqtt` (⏸ stopped — стик отдан ZHA), `local_mbusd`, `local_modbus-bridge`, `local_ustreamer`. `core_configurator` удалён (ночь-6); `go2rtc` ×2 удалены (ночь-4). -- 🔴 **ОТКРЫТО, ПЕРВОЕ:** **ориентация кадра неправильная** — в фильтре `/addons/ustreamer/` стоит `transpose=1` (90° по часовой), счётчик лежит на бок. Нужен **`transpose=2`** + rebuild аддона. -- 🔴 **ОТКРЫТО, ВТОРОЕ:** **камера в HA не обновляется — КОРЕНЬ НАЙДЕН, правка НЕ внесена.** Generic Camera (`entry_id 01M2FX50K72X2RSYY549QSG3XP`, сущность `camera.192_168_2_176`) настроена на мёртвые адреса: `still_image_url = http://192.168.2.176:1984/api/frame.jpeg?src=usb_camera_h264` (порт **1984** — удалённый go2rtc) и `stream_source = rtsp://192.168.2.176:8554/usb_camera_h264` (RTSP-сервера нет). Отсюда `404 Not Found` в логе. Менять на `still_image_url: http://192.168.2.176:8090/frame`, `stream_source` — пусто. Опции — в `/config/.storage/core.config_entries`, **не в `configuration.yaml`**. См. §4 -- ⚠️ **ОТКРЫТО:** осиротевший `/config/go2rtc.yaml` (1085 байт) остался — go2rtc удалён, читать нечем. Снести? -- ⚠️ **ОТКРЫТО:** старый мёртвый аддон `/addons/ustreamer/` в файловой системе — новая версия живёт в том же пути, старый код перезаписан. Проверить, что лишних файлов нет. -- ⚠️ **ОТКРЫТО:** watchdog для `local_ustreamer` **не включался** (в отличие от 6 других аддонов, §3.7). -- ✅ **Z2M работает** под watchdog; патология `write after end` — баг логгера, не serial-порт. См. §3.8. -- ✅ **Перестановка USB подтверждена в железе:** камера `USB3-1` (xHCI), Zigbee `USB1-2` (OHCI), CH340 #1 `1-3` → `ttyUSB0`, CH340 #2 `1-4` → `ttyUSB1`. Modbus-пути (`0:3`/`0:4`) не тронуты — **mbusd и modbus-bridge работают, данные идут в MQTT** (проверено: столовая 23.8 °C / 51.6 % / PM2.5 0.8 / TVOC 30.0). -- ❌ **Перестановка порта НЕ лечит сбросы камеры** — при чистом старте `usb 3-1: reset high-speed ... using xhci_hcd` на `t=113` и `t=126`. Порт был не причиной. -- **Метрики шторма (вечер-3):** load **9.73**, `pressure/io some` **92 %**, `pressure/memory some` **57 %**, `MemFree` **16 МБ**, `% io` **50–66 %**. После успокоения: load 0.76, `pressure/io` 3.26 %, 100 % idle. -- **Носитель:** `WDC WD2500BEVT-0`, 250 ГБ HDD 5400 rpm, `rotational=1` — **здоров**, деградации нет (ложный вывод снят, см. §3.4). `disk_free 209.8 / 228.5 ГБ`. -- **Снятие образа `sda` НЕВОЗМОЖНО из аддона** — `Operation not permitted` (§3.5). Тестовый прогон дал 20 байт. Реальные пути: `ha backups new` (не образ) либо физически вынуть носитель. -- **Журнал прошлой загрузки отсутствует** — HAOS пишет в RAM, `journalctl -b -1` пуст. События до падения восстановить нечем; диагноз ставить **до** перезагрузки. -- **Потребление по аддонам (2026-09-15):** Node-RED **197 МБ (13 %)** — крупнейший; HA Core 212 МБ (14 %); Supervisor 77 МБ (5 %); modbus-bridge 20 МБ; Mosquitto 19 МБ; go2rtc ×2 по 3.4 МБ; mbusd 0.8 МБ. -- **HAOS** `18.2`, agent `1.10.0`, ядро `6.18.39-haos`, `online_cpus 2`. `ha host info` из аддона работает. -- **`unavailable` (Zigbee) = 0** после миграции на ZHA. Отдельно, вне Zigbee: 7 на slave 10 (AT2-вентиляторы, блок закомментирован; задача снята) + `todo.shopping_list` (системная). -- ✅ **Zigbee: РАБОТАЕТ НА ZHA (2026-09-15).** Z2M ⏸ stopped (данные целы в `/config/zigbee2mqtt/`), стик отдан ZHA. **ZHA: 17 записей (16 устройств + координатор), `unavailable` = 0, 14 автоматизаций (13 `on`, 1 `off` намеренно).** Кнопка `wireless_light_switch_bed` (TS0041) шлёт `remote_button_short_press` только после `zha/devices/reconfigure`. Полный справочник — [[family/tech/zigbee-t610-z2m-i-zha]]. -- **`toilet_1_floor_temperature`:** ✅ 24.4 °C / 47.7 % / bat 100 %, зона Туалет. -- **Открытый дефект:** свет кабинета мигает при перезагрузке HA (`office_pass_switch_*`, `platform: state` без `to`). Разбор — [[family/how-to/ha-automations]]. +| Контур | Состояние | +|---|---| +| Zigbee | ZHA, 23 устройства, читаемые ID, 0 `unavailable` | +| Батареи | 12 автоматизаций, порог 20 % / 2 ч, push + persistent | +| CO₂ / Modbus | 3 датчика публикуют каждые ~10 с, значения правдоподобны | +| Вентиляция | железо в порядке, контур AT2 отключён (задача снята Alex) | +| Отопление | целиком в ZONT | +| Греющий кабель | `automation.greiushchii_kabel_upravlenie`, `on` (§см. ha-automations §7) | +| Камера | `local_ustreamer` :8090, одиночный JPEG, хост стабилен | +| Хост | load 0.76, `pressure/io` 3.26 %, 100 % idle | + +**Открыто:** + +- 🔴 **Ориентация кадра камеры** — в `/addons/ustreamer/` стоит `transpose=1` (90° по часовой), счётчик лежит на бок. Нужен `transpose=2` + rebuild аддона. +- 🔴 **Камера в HA не обновляется** — Generic Camera (`entry_id 01M2FX50K72X2RSYY549QSG3XP`, `camera.192_168_2_176`) смотрит на мёртвые адреса удалённого go2rtc: `still_image_url = http://192.168.2.176:1984/api/frame.jpeg` и `stream_source = rtsp://192.168.2.176:8554/...`. Менять на `http://192.168.2.176:8090/frame`, `stream_source` — пусто. Живёт в `/config/.storage/core.config_entries`, **не в `configuration.yaml`**. См. §4. +- ⚠️ **Осиротевший `/config/go2rtc.yaml`** (1085 байт) — go2rtc удалён, читать нечем. +- ⚠️ **Watchdog `local_ustreamer` не включён** (в отличие от остальных 6 аддонов, §3.7). +- ⚠️ **Свет кабинета мигает при перезагрузке HA** — `office_pass_switch_*` с `platform: state` без `to`. Разбор — [[family/how-to/ha-automations]] §3. +- ⚠️ **Греющий кабель не проверен физически** — розетка ни разу не включалась. + +**Справочные факты:** + +- **Аддоны (7):** `core_ssh`, `core_mosquitto`, `a0d7b954_nodered` (⏸ stopped), `45df7312_zigbee2mqtt` (⏸ stopped — стик отдан ZHA), `local_mbusd`, `local_modbus-bridge`, `local_ustreamer`. `core_configurator` и `go2rtc` ×2 удалены. +- **USB:** камера `USB3-1` (xHCI), Zigbee `USB1-2` (OHCI) → `ttyACM0`, CH340 #1 `1-3` → `ttyUSB0` (вентиляция/mbusd), CH340 #2 `1-4` → `ttyUSB1` (ZONT/modbus-bridge). +- **Носитель:** `WDC WD2500BEVT-0`, 250 ГБ HDD 5400 rpm — здоров, деградации нет (§3.4). `disk_free 209.8 / 228.5 ГБ`. +- **HAOS** `18.2`, agent `1.10.0`, ядро `6.18.39-haos`, `online_cpus 2`. +- **Потребление:** Node-RED 197 МБ — крупнейший; HA Core 212 МБ; Supervisor 77 МБ; modbus-bridge 20 МБ; Mosquitto 19 МБ; mbusd 0.8 МБ. - **`slave 20`** (газ-котёл): состояние через bridge не читается. - **`H2000_PRO`** — контроллер отопления, не Zigbee, не трогать. -- ✅ **Шум в логах про `TemplateError: round got invalid input 'unknown'` на `sensor.bedroom_summary` — СНЯТ.** При живых данных не воспроизводится: ошибка была следствием `unavailable`-состояния до фикса CO2 (§9). Правка `configuration.yaml` **не требуется**. -- **Локальные скрипты диагностики:** `~/tmp-t610/` — `diag.sh`…`diag4.sh`, `stats.sh`, `who.sh`, `mem.sh`, `boot.sh`, `z2m.sh`, `cam.sh`, `ports.sh`, `watchdog.sh`, `pull-image.sh`, `remove_go2rtc_baks.sh` (снос аддонов go2rtc + всех .bak, 2026-09-15). -- **Как запускать скрипт на t610 (рабочий паттерн):** `scp