[2026-09-16] eagle: family/how-to/ha-automations.md family/plans/t610-zigbee-ids-battery-freshsensors-modbus.md

This commit is contained in:
Alexey Martemyanov
2026-09-16 21:08:33 +06:00
parent 875bb9efda
commit 00af3ee860
2 changed files with 50 additions and 34 deletions
+44 -30
View File
@@ -2,15 +2,15 @@
> **Справочник логики автоматизаций** (`automations.yaml` на t610). Топология/команды/Modbus — [[family/how-to/home-automation]].
> 🟢 **25 АВТОМАТИЗАЦИЙ — 24 `on`, 1 `off`** (`Ventilation automation on`, намеренно), `unavailable` = 0. Zigbee работает на ZHA.
> 🟢 **24 АВТОМАТИЗАЦИИ — 23 `on`, 1 `off`** (`Ventilation automation on`, намеренно), `unavailable` = 0. Zigbee работает на ZHA.
>
> 🔴 **ПАПКА ПРОЕКТА — `~/Automation/HA-ZONT-Modbus`** (git-репозиторий). Файл автоматизаций в проекте: `homeassistant/automations.yaml`. **НЕ** `~/tmp-t610/automations/` — это рабочая свалка скриптов, а не проект. Синхронизировать проект с HA: `scp root@192.168.2.176:/config/automations.yaml ~/Automation/HA-ZONT-Modbus/homeassistant/automations.yaml` → патч → заливка → **коммит в git**.
>
> ✅ **РАБОЧИЙ REST-ПУТЬ К HA НАЙДЕН (2026-09-16, поздний вечер): `https://mallexxx.duckdns.org`.** Отвечает `401` без токена, `200` с токеном. Это единственный подтверждённый транспорт. `192.168.2.176:8123` и `172.30.32.1:8123` — не нужны.
>
> **Состав:** 12 контроля батарей (§5) + 2 циркуляция ГВС + 2 свет кабинета (§2.2, §3) + 2 подсветка лестницы + 2 ночной свет душевой (§4.1–§4.6.2) + 2 диммер спальни + 1 протечка котельная + 1 вентиляция + **1 греющий кабель ввода воды (§7)**.
> **Состав:** 12 контроля батарей (§5) + 2 циркуляция ГВС + 2 свет кабинета (§2.2, §3) + 2 подсветка лестницы + **1 ночной свет душевой (§4.7)** + 2 диммер спальни + 1 протечка котельная + 1 вентиляция + **1 греющий кабель ввода воды (§7)**.
>
> ✅ **ПРИМЕНЕНО 2026-09-16 (поздний вечер): объединение двух автоматизаций душевой в ОДНУ по таблице истинности — см. §4.7.** Один сценарий `1771997851260` (`mode: restart`, 4 триггера, 4 ветки `choose`), вторая `1771997918348` **отключена** (`off`). Залито через REST с внешнего адреса, прочитано обратно, закоммичено. Дрожание радара (§4.6.2) лечится структурно: `mode: restart` гарантирует **ровно одно выполнение** — новый триггер убивает предыдущее ожидание. Отдельный выбор по `fading_time` снят с повестки.
> ✅ **ПРИМЕНЕНО, ПРОВЕРЕНО («Работает!») И ЗАВЕРШЕНО 2026-09-16 (поздний вечер): объединение двух автоматизаций душевой в ОДНУ по таблице истинности — см. §4.7.** Один сценарий `1771997851260` (`mode: restart`, 4 триггера, 4 ветки `choose`). **Старая автоматизация `1771997918348` СНЕСЕНА ПОЛНОСТЬЮ** (не «отключена») — тело удалено через `DELETE /api/config/automation/config/1771997918348` (`200 ok`, затем `GET` → `404`), блок убран из файла проекта (коммит `d019477`). Дрожание радара (§4.6.2) лечится структурно: `mode: restart` гарантирует **ровно одно выполнение** — новый триггер убивает предыдущее ожидание. Отдельный выбор по `fading_time` снят с повестки.
>
> 🔴 **ТРАНСПОРТ К HA НА t610 (§4.7):** `192.168.2.176:8123` **НЕ работает** — это ssh-аддон `core_ssh`, не HA. ✅ **Рабочий путь — `https://mallexxx.duckdns.org`** (см. строку выше и §4.7 «Транспорт»). `172.30.32.1:8123` (Docker-сеть супервизора) отвечает, но практического применения не потребовалось. На t610 **нет `python3`**, только `jq`. Заголовок `Authorization: Bearer <TOKEN>` **нельзя** собирать через `$(cat file)` в ssh-строке/here-doc — рвётся фильтром секретов; читать токен через `read -r T < file` (bash) или `fh.readline().strip()` (python на Mac).
>
@@ -28,11 +28,14 @@
> - 🔴 **Трассировки автоматизаций — ТОЛЬКО WebSocket** (`trace/list` + `trace/get`, `item_id` = **внутренний ID**, не `entity_id`; REST → 404). **Читать трассировку ДО перебора гипотез.** Инструмент: `~/tmp-t610/trace_dump.py` (на t610 python3 НЕТ).
> - 🔴 **`entity_id` автоматизаций HA перегенерирует по alias** — искать по `attributes.id`, не по `entity_id`.
> - 🔴 **REST `GET/POST /api/config/automation/config/<id>` использует поля во множественном числе** — `triggers`/`conditions`/`actions` (в файле — единственное). Ошибка молча уходит в пустоту: POST → `200 ok`, значения НЕ меняются. **Всегда читать обратно.**
> - 🔴 **АДРЕС HA на t610 — `172.30.32.1:8123`, НЕ `192.168.2.176:8123`.** `192.168.2.176` — ssh-аддон `core_ssh`, порт `8123` там закрыт. HA живёт в Docker-сети супервизора (`getent hosts homeassistant`). На t610 **нет `python3`** — только `jq`. Заголовок с токеном **нельзя** собирать через `$(cat tokenfile)` внутри ssh-строки — рвётся фильтром секретов; читать токен `read -r T < file`. Подробно — §4.7 «Транспорт».
> - 🔴 **Не склеивать `automations.yaml` вручную через `awk`.** Трижды в сессии 2026-09-16 потерялась автоматизация из-за отсутствия ведущего `- ` в подставляемом блоке. Перед записью — обязательная сверка `comm -23` по списку `^- id:`. Лучше: REST POST изнутри HA, UI, или python на Mac + `scp`.
> - 🔴 **РАБОЧИЙ АДРЕС HA — `https://mallexxx.duckdns.org`, НЕ `192.168.2.176:8123`.** `192.168.2.176` — ssh-аддон `core_ssh`, порт `8123` там закрыт (`ConnectionRefused`). `172.30.32.1:8123` (Docker-сеть супервизора, `getent hosts homeassistant`) отвечает, но на практике не понадобился. На t610 **нет `python3`** — только `jq`. Заголовок с токеном **нельзя** собирать через `$(cat tokenfile)` внутри ssh-строки — рвётся фильтром секретов; читать токен `read -r T < file`, в python — `fh.readline().strip()`. Подробно — §4.7 «Транспорт».
> - 🔴 **Пустые `triggers: []` НЕ выключают автоматизацию** — после `reload` она остаётся `on`. Нужен явный `POST /api/services/automation/turn_off` с `entity_id`. **Полное удаление — `DELETE /api/config/automation/config/<id>`** (`200 ok`, проверка `GET` → `404`) + `automation/reload` (§4.7).
> - 🔴 **Пайплайн правки (требование Alex):** `scp` файла с HA в проект → **коммит ДО** → патч `patch`-инструментом → заливка REST → чтение обратно → **живая проверка Alex'ом** → **коммит ПОСЛЕ**. Не коммитить результат до проверки (§4.7).
> - 🔴 **Не склеивать `automations.yaml` вручную через `awk`.** Трижды в сессии 2026-09-16 потерялась автоматизация из-за отсутствия ведущего `- ` в подставляемом блоке. **Замена — `patch`-инструмент по якорям** (сработал с первого раза). Перед записью — обязательная сверка `comm -23` по списку `^- id:` + `yaml.safe_load`.
> - ⚠️ **Кнопка спальни** шлёт `remote_button_short_press` только после `zha/devices/reconfigure`.
>
> **Бэкапы сессии 2026-09-16:** `.bak-office-20260916-124244` (кабинет), `.bak-showerdelay-20260916-131126`, `.bak-shower-off-20260916-205245`, `.bak-shower-delay3-20260916-205557`, `.bak-shower-delay5-20260916-205953`, `.bak-shower-final-20260916-211051` (душевая). Локальные копии в `~/tmp-t610/`.
> **Бэкапы сессии 2026-09-16 (все — в `/config` на t610):** `.bak-office-20260916-124244` (кабинет), `.bak-showerdelay-20260916-131126`, `.bak-shower-off-20260916-205245`, `.bak-shower-delay3-20260916-205557`, `.bak-shower-delay5-20260916-205953`, `.bak-shower-final-20260916-211051`, `.bak-shower-merge-20260916-214012` (эталон перед объединением), `.bak-before-restore-20260916-214949`.
> 🔴 **Бэкапы в папке проекта НЕ делать — там git.** Alex: «Нахуя бэкап в папке проекта у тебя гит есть». В проекте `*.bak` покрыт `.gitignore`; страховка боевого HA — только файлы в `/config` на t610.
> 📄 Рецепт пересборки после Z2M→ZHA и питфоллы — [[family/tech/zigbee-t610-z2m-i-zha]].
>
> 🔴 **ПИТФОЛЛЫ, найденные при починке:**
@@ -45,10 +48,12 @@
## 1. Где живёт
- **Файл:** `/config/automations.yaml` в HA Core на t610.
- **Всего:** **25 автоматизаций — 24 `on`, 1 `off`** (`Ventilation automation on`, намеренно), **`unavailable` = 0**. Файл = 780 строк.
- **Бэкапы перед правками:** `automations.yaml.bak-cable3-<ts>` (кабель, 2026-09-16), `.bak-preids-*`, `.bak-gard-*`; локально — `~/tmp-t610/bak-cable-20260915-234837/automations.yaml`.
- **Всего:** **24 автоматизации — 23 `on`, 1 `off`** (`Ventilation automation on`, намеренно), **`unavailable` = 0**.
- **Бэкапы перед правками:** `automations.yaml.bak-cable3-<ts>` (кабель, 2026-09-16), `.bak-preids-*`, `.bak-gard-*`, `.bak-shower-merge-20260916-214012` (эталон 25 автоматизаций перед объединением душевой).
- **Удалены 4 «призрака»** (записи в реестре без тела): `svetlo_vykl_osveshchenie_lestnitsy`, `temno_vkl_podsvetku_lestnitsy`, `datchik_osveshchennosti_lestnitsa_batareia`, `light_switch_bed_batareia`. Тела не было (`config/automation/config/<id>` → 404) — лестничные сценарии **пересозданы заново** с теми же id.
- **Локальная копия:** `~/tmp-t610/automations/automations.yaml`; после пересборки — `~/tmp-t610/automations-new.yaml`, `~/tmp-t610/automations-fixed.yaml`.
- 🔴 **ПРОЕКТ (git, источник правок):** `~/Automation/HA-ZONT-Modbus``homeassistant/automations.yaml`.
**Свалка скриптов (НЕ проект):** `~/tmp-t610/` — там живут рабочие скрипты, бэкапы, `ha_duck.sh`, `trace_dump.py`.
**Синхронизация:** `scp root@192.168.2.176:/config/automations.yaml ~/Automation/HA-ZONT-Modbus/homeassistant/automations.yaml`
- **Читать живьём через API** (не по памяти):
```bash
B="https://mallexxx.duckdns.org"
@@ -130,7 +135,7 @@ action:
| `1771683420621` | Toggle Dimmer bed | кнопка `remote_button_short_press` → `light.toggle light.bed_dimmer` |
| `1771683677259` | Dimmer bed cycle | кнопка `long_press` → `light.turn_on` brightness 50 % на `light.bed_dimmer` |
| `1771997851260` | **Душевая: ночной свет** (объединённый) | `mode: restart`, 4 триггера: `P` (occupied) / `Poff` (not_occupied) / `Llow` (illuminance below 6) / `Lhi` (above 6). 4 ветки `choose`, действие ВНУТРИ ветки: `P`+presence on+lux<6 → вкл; `Llow`+presence on+lux<6 → delay 3 s → вкл; `Poff`+lux<6+свет вкл → delay 10 s → выкл; `Lhi`+lux>6+свет вкл → выкл. ✅ §4.7 |
| `1771997918348` | **ОТКЛЮЧЕНО: Душевая выключение** | ⛔ **Отключена** (`state: off`, `triggers: []`). Логика перенесена в `1771997851260`. ✅ §4.7 |
| `1771997918348` | ~~Выкл. ночной свет душевая~~ | ⛔ **СНЕСЕНА 2026-09-16** — тело удалено из HA (`DELETE` → 200, `GET` → 404), блок убран из файла проекта (коммит `d019477`). Логика перенесена в `1771997851260`. Всего автоматизаций стало **24**. ✅ §4.7 |
| `1773451257968` | Протечка котельная | `moist` → `notify.notify` |
| `8800000000000`…`8800000000011` | **Батарея: 12 шт.** | см. §6 |
| `heating_cable_ctl_0001` | **Греющий кабель: управление** | `time_pattern /15` + `numeric_state ZONT below 8` + отвал датчика → `choose` 5 веток на `switch.heating_cable_plug`. См. §7 |
@@ -617,15 +622,20 @@ mode: single
## 4.7. ✅ ОБЪЕДИНЕНИЕ двух автоматизаций душевой в ОДНУ (2026-09-16, вечер) — ПРИМЕНЕНО И ПРОВЕРЕНО
> **Статус: ✅ ПРИМЕНЕНО И ПРОВЕРЕНО ALEX («Работает!»), 2026-09-16 поздний вечер.** Один сценарий `1771997851260` (`mode: restart`, 4 триггера, 4 ветки `choose`), вторая `1771997918348` отключена. Залито через REST `https://mallexxx.duckdns.org`, прочитано обратно, закоммичено.
> **Статус: ✅ ПРИМЕНЕНО, ПРОВЕРЕНО («Работает!») И ЗАВЕРШЕНО, 2026-09-16 поздний вечер.** Один сценарий `1771997851260` (`mode: restart`, 4 триггера, 4 ветки `choose`). **Старая автоматизация `1771997918348` СНЕСЕНА ПОЛНОСТЬЮ** (не «отключена»): тело удалено из HA через `DELETE /api/config/automation/config/1771997918348` (`200 ok`, затем `GET` → `404`), блок убран из файла проекта. Залито через REST `https://mallexxx.duckdns.org`, закоммичено.
>
> **Итог HA после сноса: 24 автоматизации — 23 `on`, 1 `off`** (вентиляция, намеренно), `unavailable` = 0.
>
> **Коммиты проекта (`~/Automation/HA-ZONT-Modbus`):**
> - `2eaa704` — «Sync automations.yaml from t610 prod (14 → 25 automations)» — коммит **ДО** работ.
> - `0f5924f` — «Merge shower automations: 2 scenarios -> 1 (mode restart, 4-branch truth table)» — коммит **ПОСЛЕ проверки** Alex.
> - `d019477` — «Remove old shower off-automation (1771997918348)» — снос старой автоматизации.
>
> 🔴 **ПОРЯДОК РАБОТЫ, ПОДТВЕРЖДЁННЫЙ ALEX (соблюдать буквально):** синхронизация файла → **коммит ДО** → патч → заливка через API → чтение обратно → **проверка Alex'ом вживую** → **коммит ПОСЛЕ**. Alex: «Я тебе сказал сделать один комит ДО. ВТОРОЙ-ПОСЛЕ ПРОВЕРКИ». Преждевременный второй коммит пришлось откатывать (`git reset --soft`). **Не коммитить результат до его проверки.**
>
> 🔴 **ОТКЛЮЧЕНИЕ ВТОРОЙ АВТОМАТИЗАЦИИ — ДВА ШАГА, не один.** Пустые `triggers: []` в конфиге НЕ выключают автоматизацию: после `reload` она по-прежнему `on`. Нужен явный `POST /api/services/automation/turn_off` с `entity_id`. Проверено: без него вторая висела `on`, после — `off`.
> 🔴 **УДАЛЕНИЕ АВТОМАТИЗАЦИИ — через `DELETE /api/config/automation/config/<id>`**, затем `automation/reload`. Проверено: `DELETE` → `200 {"result":"ok"}`, повторный `GET` → `404`. Только после этого блок убирается из файла проекта.
>
> ⚠️ **Бэкап-файлы в папке проекта НЕ нужны — там git.** Alex: «Нахуя бэкап в папке проекта у тебя гит есть». Бэкапы делать **только в `/config` на t610** (страховка боевого HA). Правило `*.bak` в `.gitignore` репозитория уже покрывает такие файлы.
**Проблема, которую решаем.** Две автоматизации (`1771997851260` ВКЛ + `1771997918348` ВЫКЛ) реагируют на **одни и те же** события presence/lux и тянут свет в противоположные стороны. Одно движение радара = оба сценария подряд. HA **не имеет** взаимной блокировки между автоматизациями: `mode` действует только внутри своей автоматизации (у ВКЛ `single`, у ВЫКЛ `restart`) — запуск одной не останавливает другую. Это и есть источник гонок.
@@ -729,35 +739,39 @@ actions:
7. **Вторая автоматизация выключена явно:** `POST /api/services/automation/turn_off` (`entity_id: automation.vykl_nochnoi_svet_dushevaia`) → `state: off`. После `reload` она оставалась `on` — пустых триггеров недостаточно.
8. **✅ ПРОВЕРЕНО ALEX ВЖИВУЮ: «Работает!»**
9. **Коммит после проверки: `0f5924f`** — «Merge shower automations: 2 scenarios -> 1 (mode restart, 4-branch truth table)» (+ `.gitignore` для бэкапов проекта).
10. **По команде Alex «Сноси» старая автоматизация удалена ПОЛНОСТЬЮ:** `DELETE /api/config/automation/config/1771997918348` → `200 {"result":"ok"}`; повторный `GET` → **404**; блок убран из файла проекта; `reload`.
11. **Коммит `d019477`** — «Remove old shower off-automation (1771997918348)». **Итог HA: 24 автоматизации — 23 `on`, 1 `off`**, `unavailable` = 0.
12. **Убраны два бэкап-файла из папки проекта** (в git вся история — Alex: «Нахуя бэкап в папке проекта у тебя гит есть»). **Исправлен `.gitignore`:** была склеенная строка `project_home.pdfhomeassistant/automations.yaml.bak-*` (ошибка записи) → `project_home.pdf`. Отдельное правило для `.bak-*` удалено — `*.bak` уже покрыто.
⚠️ **Порядок коммитов пришлось исправлять:** я закоммитил результат до проверки Alex, пришлось откатывать (`git reset --soft 2eaa704`) и коммитить заново после подтверждения. **Урок: коммит результата — строго ПОСЛЕ живой проверки Alex.**
**Скрипты:** `~/tmp-t610/ha_duck.sh` (чтение через внешний адрес), скрипты заливки писались на Mac (python3 `urllib`, читать токен через `readline()` — `pathlib.read_text()` рвётся фильтром секретов).
### 🚧 Исторические питфоллы транспорта (первая попытка, провалена)
### 🚧 Историческая заметка: что НЕ работает (не тратить время)
> 🔴 **`192.168.2.176:8123` НЕ работает.** `192.168.2.176` — это **SSH-аддон `core_ssh`** на t610, а не HA. Порты на нём: `22` (ssh), `8099` (ttyd/веб-терминал), `45073`. Порт `8123` закрыт — `ConnectionRefused`.
> ✅ **HA живёт на `172.30.32.1:8123`** внутри Docker-сети супервизора (`getent hosts homeassistant` → `172.30.32.1`, `supervisor` → `172.30.32.2`). Проверено: `curl` на `172.30.32.1:8123` отвечает.
> **API через супервизор:** `http://supervisor/core/api/` доступен изнутри аддона (отвечает `401` без токена — эндпоинт существует).
> 🔴 **`python3` на t610 НЕТ.** Есть только `/usr/bin/jq`. Любая обработка — `jq`, `awk`, `sed` в шелле, либо сборка файла **на Mac** и `scp`.
> **КРИТИЧНЫЙ ПИТФОЛЛ ШЕЛЛА: строку `Authorization: Bearer <TOKEN>` нельзя генерировать через `$(cat tokenfile)` или `$TOKEN` внутри ssh-команды / here-doc / `printf`** — фильтр секретов и парсер рвут конструкцию, в файл попадает `Bearer ***` или строка обрывается, curl получает битый заголовок и молча не пишет файл (`-o` → `No such file or directory`). Рабочий обход — **читать токен через `read -r T < file` и собирать заголовок `printf`-ом на целевой машине**, либо использовать `hermes`-путь через `ha_ws.py`. Классические `TOKEN=$(cat …)` + `-H "Authorization: Bearer $TOKEN"` в одной ssh-строке — **не работают**.
> 🔴 **SSH-туннель к HA:** `ssh -f -N -L 127.0.0.1:18124:127.0.0.1:8123 root@192.168.2.176` — туннель поднимается, но **соединение ресетится** (`ConnectionResetError`), потому что на удалённой стороне порт `8123` не слушается. Туннель к `172.30.32.1:8123` — рабочий вариант, если понадобится.
> 🔴 **Склейка `automations.yaml` через `awk` — ПРОВАЛЕНО трижды.** Границы блоков задаются по `grep -n "^- id:"`; потеря автоматизации происходит из-за отсутствия ведущего `- ` в подставляемом блоке (`id:` вместо `- id:`), из-за чего `grep -c "^- id:"` не считает его. **Обязательная проверка перед записью:** сравнить `comm -23 <(grep "^- id:" bak | sort) <(grep "^- id:" new | sort)` — пустой вывод = ничего не потеряно. Только после этого `cp`.
> 💡 **Вывод на будущее:** ручная склейка YAML ненадёжна. Предпочтительный путь — REST `POST /api/config/automation/config/<id>` из HA-аддона **изнутри** на `172.30.32.1`, либо правка через UI HA, либо python на Mac + `scp` готового файла.
> ✅ **Рабочий транспорт — `https://mallexxx.duckdns.org`** (см. §4.7 «Транспорт»). `172.30.32.1:8123` внутри Docker-сети супервизора отвечает, но на практике не понадобился.
> 🔴 **`python3` на t610 НЕТ.** Есть только `/usr/bin/jq`. Любая обработка — `jq`, `awk`, `sed` в шелле, либо скрипты **на Mac** и `scp`.
> **КРИТИЧНЫЙ ПИТФОЛЛ ШЕЛЛА: строку `Authorization: Bearer <TOKEN>` нельзя генерировать через `$(cat tokenfile)` или `$TOKEN` внутри ssh-команды / here-doc / `printf`** — фильтр секретов и парсер рвут конструкцию, в файл попадает `Bearer ***` или строка обрывается, curl получает битый заголовок и молча не пишет файл (`-o` → `No such file or directory`). Рабочий обход — **писать скрипт файлом на Mac**, читать токен `read -r TOK < file` (bash) или `fh.readline().strip()` (python), запускать `bash script.sh`.
> 🔴 **SSH-туннель к HA:** `ssh -f -N -L 127.0.0.1:18124:127.0.0.1:8123 root@192.168.2.176` — туннель поднимается, но **соединение ресетится** (`ConnectionResetError`), потому что на удалённой стороне порт `8123` не слушается. Не тратить время — внешний адрес решает всё.
> 🔴 **Склейка `automations.yaml` через `awk` — ПРОВАЛЕНО трижды.** Границы блоков задаются по `grep -n "^- id:"`; потеря автоматизации происходит из-за отсутствия ведущего `- ` в подставляемом блоке (`id:` вместо `- id:`), из-за чего `grep -c "^- id:"` не считает его. **Замена — `patch`-инструмент по якорям** (сработал с первого раза). При любом способе перед записью обязательна сверка: `comm -23 <(grep "^- id:" bak | sort) <(grep "^- id:" new | sort)` — пустой вывод = ничего не потеряно, плюс `yaml.safe_load`.
### 🗓 Итог сессии 2026-09-16 (поздний вечер)
### 🗓 Итог сессии 2026-09-16 (поздний вечер) — ✅ ЗАДАЧА ЗАКРЫТА
**Итог:** объединение сценариев душевой **применено в HA и проверено Alex'ом вживую («Работает!»)**. Порядок и подробности — в начале §4.7. Коммиты проекта: `2eaa704` (синхронизация, ДО) и `0f5924f` (результат, ПОСЛЕ проверки).
**Сделано:**
1. Прочитан живой конфиг обеих автоматизаций душевой через ssh-аддон (файл `/config/automations.yaml`, строки 96140 и 141176).
2. Дизайн §4.7 дожат до финала с двумя правками Alex (убраны `wait_for_trigger` и проверки `presence`).
3. Бэкап `automations.yaml.bak-shower-merge-20260916-214012` (25 автоматизаций) — **сделан**.
4. Финальный конфиг собран: `~/tmp-t610/shower_merged_final.yaml` (91 строка, с ведущим `- id:`). Черновик `shower_merged.yaml` (без дефиса) — брак.
1. Прочитан живой конфиг обеих автоматизаций душевой (строки 96140 и 141176 `/config/automations.yaml`).
2. Дизайн §4.7 дожат до финала с правками Alex (убраны `wait_for_trigger` и проверки `presence`).
3. Бэкап `automations.yaml.bak-shower-merge-20260916-214012` (25 автоматизаций).
4. Файл проекта `~/Automation/HA-ZONT-Modbus/homeassistant/automations.yaml` синхронизирован с HA (14 → 25 автоматизаций) и отпатчен.
5. Заливка через `POST /api/config/automation/config/<ID>` → чтение обратно → `reload` → `turn_off` второй → проверка 25/24 `on`/1 `off`/`unavailable` = 0.
6. **Живая проверка Alex'а.** Коммит результата.
**НЕ сделано (применение провалено):**
1. REST-путь к HA не найден: `192.168.2.176:8123` закрыт, `172.30.32.1:8123` доступен но не задействован, ssh-туннель ресетится.
2. Склейка файла через `awk` трижды дала потерю автоматизации (`1771997851260`).
3. **По команде Alex выполнен откат:** `/config/automations.yaml` восстановлен из `bak-shower-merge-20260916-214012`. Предыдущее состояние сохранено в `.bak-before-restore-20260916-214949`. Хэши совпадают: `652f921c9086981b55d994a74d5650f7`.
4. **ХА НЕ перезагружал автоматизации** после отката — HA держит в памяти версию, прочитанную при старте. Требуется `POST /api/services/automation/reload`, чтобы HA перечитал файл. Алекс об этом уведомлён, команды не дал.
**Что узнали по ходу (сохранено как питфоллы):**
1. **Ошибочная попытка №1:** транспорт `192.168.2.176:8123` не работал, `awk`-склейка теряла автоматизацию. По команде Alex выполнен откат из `bak-shower-merge-20260916-214012`; состояние перед откатом — `.bak-before-restore-20260916-214949`. Хэши совпали: `652f921c9086981b55d994a74d5650f7`.
2. **Пустые `triggers: []` НЕ выключают автоматизацию** — после `reload` она остаётся `on`, нужен явный `POST /api/services/automation/turn_off`.
3. **Коммит результата — только после живой проверки Alex'а.** Преждевременный коммит откатывался через `git reset --soft`.
**Бэкапы этой части сессии:**
- `/config/automations.yaml.bak-shower-merge-20260916-214012` — эталон, 25 автоматизаций (состояние **до** всех вечерних попыток).
@@ -1,7 +1,7 @@
---
title: "План и результат: читаемые ID Zigbee, алерты батарей, виртуальные Modbus-датчики"
created: '2026-09-15'
updated: 2026-09-16 (поздний вечер, ФИНАЛ: объединение сценариев душевой применено в HA и проверено Alex'ом — «Работает!». Коммиты проекта `2eaa704` (до) и `0f5924f` (после проверки). Старая автоматизация `1771997918348` отключена, не удалена — как откат)
updated: 2026-09-16 (поздний вечер, ФИНАЛ: объединение сценариев душевой применено в HA и проверено Alex'ом — «Работает!». Коммиты проекта `2eaa704` (до), `0f5924f` (после проверки), `d019477` (снос старой). Старая автоматизация `1771997918348` УДАЛЕНА ПОЛНОСТЬЮ через `DELETE /api/config/automation/config/<id>` — итог 24 автоматизации)
type: plan
namespace: family
status: 🟢 ВЫПОЛНЕНО 2026-09-16. Шаги 14 закрыты 2026-09-15; 5–6 (вычистка призраков + починка UI) — 2026-09-16 ночью; 7–8 (автоматизации кабинета — 2 дефекта; душевая — `fading_time` 10→2, задержка 10 с в ВЫКЛ, ложные включения ВКЛ) — 2026-09-16 днём. Всё проверено фактами. 🟡 Открыт один вопрос — feedback loop по порогам душевой (§4.6 в [[family/how-to/ha-automations]]), правка отклонена Alex.
@@ -476,7 +476,7 @@ python3 ~/tmp-t610/trace_dump.py 14:02:33
**Задача Alex:** убрать гонку двух автоматизаций (`1771997851260` ВКЛ + `1771997918348` ВЫКЛ), реагирующих на одни события presence/lux. HA **не имеет** взаимной блокировки между автоматизациями — `mode` работает только внутри своей.
**Решение (согласовано Alex, дожато до финала):** одна автоматизация `1771997851260`, **4 триггера** (`P`/`Poff`/`Llow`/`Lhi`), **4 ветки `choose`**, `mode: restart`. Вторая (`1771997918348`) — отключена (пустые `triggers`/`actions`), не удалена.
**Решение (согласовано Alex, дожато до финала):** одна автоматизация `1771997851260`, **4 триггера** (`P`/`Poff`/`Llow`/`Lhi`), **4 ветки `choose`**, `mode: restart`. Вторая (`1771997918348`) — **УДАЛЕНА ПОЛНОСТЬЮ** 2026-09-16 по команде Alex «Сноси».
**Правки Alex поверх первой редакции — не откатывать:**
1. `wait_for_trigger` из ветки 3 **убран** («Триггер должен перезапустить сценарий») — `mode: restart` уже убивает текущий запуск при новом триггере.
@@ -498,10 +498,12 @@ python3 ~/tmp-t610/trace_dump.py 14:02:33
5. 🔴 **Вторую пришлось выключать явно** — `POST /api/services/automation/turn_off` (`entity_id: automation.vykl_nochnoi_svet_dushevaia`). **Пустых `triggers: []` НЕДОСТАТОЧНО:** после `reload` автоматизация остаётся `on`. Проверено: без `turn_off` висела `on`.
6. **✅ ПРОВЕРКА ALEX'ОМ ВЖИВУЮ: «Работает!»**
7. **Коммит `0f5924f`** «Merge shower automations: 2 scenarios -> 1 (mode restart, 4-branch truth table)» (+ `.gitignore` для бэкапов проекта).
8. **Снос старой автоматизации (Alex: «Сноси»):** `DELETE /api/config/automation/config/1771997918348` → `200 {"result":"ok"}`, повторный `GET` → **404**; блок убран из файла проекта (816 строк, 24 `^- id:`); `reload`. **Коммит `d019477`** «Remove old shower off-automation».
9. **Бэкап-файлы убраны из папки проекта** — в git вся история; Alex: «Нахуя бэкап в папке проекта у тебя гит есть». **Исправлен `.gitignore`:** склеенная строка `project_home.pdfhomeassistant/automations.yaml.bak-*` → `project_home.pdf` (отдельное правило `.bak-*` снято, `*.bak` уже покрыто).
**Состояние:** HA — `1771997851260` `on` / `1771997918348` `off`, 25 автоматизаций, `unavailable` = 0. Старая автоматизация **отключена, не удалена** (откат доступен правкой; история — в git).
**Состояние (ФИНАЛ):** HA — **24 автоматизации: 23 `on`, 1 `off`**, `unavailable` = 0. Работает только `1771997851260` (`on`). Старая `1771997918348` **удалена** — тело в HA отсутствует (`GET` → 404), блок убран из проекта; вернуть можно только из git-истории.
**Инструменты:** `~/tmp-t610/ha_duck.sh` (рабочее чтение); скрипты заливки писались на Mac (python3 `urllib`), токен читать `fh.readline().strip()` — `pathlib.read_text()` рвётся фильтром секретов.
**Бэкапы:** `~/Automation/HA-ZONT-Modbus/homeassistant/automations.yaml.bak-20260916-205509`; на t610 `.bak-shower-merge-20260916-214012` (эталон 25 автоматизаций), `.bak-before-restore-20260916-214949`.
**Бэкапы (только в `/config` на t610):** `.bak-shower-merge-20260916-214012` (эталон 25 автоматизаций), `.bak-before-restore-20260916-214949`. **В папке проекта бэкапы НЕ хранить — там git.**
**Детали:** [[family/how-to/ha-automations]] §4.7.