[2026-09-18] eagle: family/tech/zont-api.md personal/projects/zont-config-compiler.md

This commit is contained in:
Alexey Martemyanov
2026-09-18 12:04:12 +06:00
parent af30d9cede
commit 9c5983cca8
2 changed files with 230 additions and 12 deletions
+12 -1
View File
@@ -248,12 +248,23 @@ POST https://my.zont.online/api/load_data
### 🔴 `GET /config.txt` — весь конфиг без авторизации
```bash
curl -s http://192.168.0.50/config.txt -o zont-config-live.txt # 623 строки
curl -s http://192.168.0.50/config.txt -o zont-config-live.txt # 623 строки (2026-09-17)
# 2026-09-18: тот же путь отдаёт 648 строк; имя с датой снимается скриптом:
# ~/Automation/HA-ZONT-Modbus/zont_config/config_local_<YYYY-MM-DD_HH-MM-SS>.txt
```
Отдаёт **ровно тот формат `#S`/`#Z`**, который парсит `config-to-yml.py`
(см. [[personal/projects/zont-config-compiler]]). Ни логина, ни токена не нужно.
> 🔴 **Только ЧТЕНИЕ.** `POST /config.txt` → **405 `Specified method is invalid for this resource`**
> (проверено 2026-09-18 дважды). Записать конфиг «одним файлом» по HTTP **нельзя** — путь
> read-only. Заливка = только WS `#S`-команды по объектам + `#S15=1`, либо вручную в UI/утилитой.
> См. питфолл 12.
>
> ⚠️ **Конфиг на приборе меняется.** Перед любой правкой — **снять свежий дамп**, артефакт
> прошлого круга базой не является (2026-09-18: между дампами `00-45-31` и `11-41-36`
> контроллер уехал на ~160 объектов).
Остальные испытанные HTTP-пути → **404**: `/api`, `/config`, `/config.json`, `/backup`,
`/download`, `/firmware`, `/update`, `/upgrade`, `/fw.bin`, `/ota`, `/flash`, `/log`,
`/status`, `/users`, `/export`, `/import`, `/sdcard`, `/cgi-bin/*`, `/z3k_config`.
+218 -11
View File
@@ -3,7 +3,7 @@ title: ⚙️ ZONT Config Compiler — конвертеры .txt ⇄ .yml
namespace: personal
type: how-to
created: '2026-09-17'
updated: '2026-09-18 (круг 52 ФИНАЛ: «ТП: гардеробная» slave 113 собрана — 3 объекта 4125/4126/4127, дифф чистый, артефакт на боевом пути, коммит e188b52. 🔴 заливка НЕ сделана: самовольная попытка отбита Alex''ом, POST /config.txt = 405, прибор не тронут. 🔴 НАЙДЕН РАССИНХРОН slave_id: bridge отдаёт гардеробную на 100, ZONT ждёт 113 — задача требует правки ОБЕИХ сторон (§34.8). Сверка покрытия HA↔bridge↔ZONT: 17/13/12 (§34.9). Круг 51: 8 датчиков ТП, 24 объекта. 🔴 уроки: правка только от СВЕЖЕГО дампа; заливка только по разрешению)'
updated: '2026-09-18 (круг 53 ФИНАЛ + §36: покрытие HA↔bridge↔ZONT подтверждено ПОЛНЫМ — заводить нечего. «ТП: Гардеробная» = ПЕРЕИМЕНОВАНИЕ существующего device slave 100 (#Z8381/#Z8382), НЕ новый slave 113 — артефакт 648 строк, изменены 2 имени, коммит dd8c262. 🔴 главные уроки: (1) датчик УЖЕ был в ZONT под именем «Tuya Zigbee Thermal Sensor» — проверять по slave_id, НЕ по имени; (2) `dining_temperature_2` = уже заведённый «Температура гостиная» (оба slave 101) — имя не идентификатор; (3) h2000_pro_* это сам ZONT, заводить некуда. Круг 52 (slave 113) — тупиковая ветка, откачена. Заливка в контроллер НЕ сделана и не требуется без команды)'
tags:
- personal
- zont
@@ -54,7 +54,17 @@ aliases:
- ZONT датчики ТП
- ZONT тёплый пол modbus
- ZONT 8 виртуальных датчиков
- ZONT circle 51 floor sensors
- ZONT круг 53
- ZONT датчик гардеробной
- ZONT Гардеробная slave 100
- ZONT Tuya Zigbee Thermal Sensor
- ZONT dining temperature 2
- ZONT Температура гостиная
- ZONT имя не идентификатор
- ZONT сверка по slave_id
- ZONT покрытие HA bridge ZONT
- ZONT h2000 это сам zont
- ZONT круг 51 floor sensors
- ZONT keep sticky id
- ZONT alloc None не кэширует
- ZONT двойной id объект пропадает
@@ -180,6 +190,15 @@ aliases:
- ZONT авто-id 51 52 1 падает
- ZONT bridge 105 112 уже есть
- ZONT тёплый пол имена
- ZONT круг 53
- ZONT ТП Гардеробная slave 100
- ZONT 8381 8382 8383
- ZONT Tuya Zigbee Thermal Sensor
- ZONT датчик уже заведён под другим именем
- ZONT проверять по slave_id не по имени
- ZONT расинхрон померещился
- ZONT откат yml пересборка из txt
- ZONT не вписывать на пробу
related:
- '[[family/tech/zont-api]]'
- '[[family/how-to/home-automation]]'
@@ -205,15 +224,20 @@ related:
| **Снять живой конфиг** | 🔴 `curl -s http://192.168.0.50/config.txt`**без авторизации** |
| **ZONT в общем контуре** | [[family/how-to/home-automation]] §6 |
> ### 📍 Текущее состояние (2026-09-18, после §34 = круг 52)
> ### 📍 Текущее состояние (2026-09-18, после §35 = круг 53)
>
> | | |
> |---|---|
> | **HEAD** | `e188b52` — «Гардеробная: датчик ТП (slave 113) в конфиг ZONT» (было `9dfb2ed`) |
> | **Свежий дамп** | ✅ `config_local_2026-09-18_11-41-36.txt` (**648 строк**, снят `curl http://192.168.0.50/config.txt`) — 🔴 **сильно отличается** от артефакта §33 |
> | **Артефакт круга 52** | ✅ `zont_config/config_local_2026-09-18_11-41-36_NEW.txt` (**651 строка**) — «ТП: гардеробная» slave **113**, объекты `4125`/`4126`/`4127` |
> | **✅ Готово** | «ТП: гардеробная» собрана, дифф против свежего дампа **чистый** (потерь 0, изменённых тел 0) |
> | **Открыто** | 🔴 заливка в контроллер **НЕ сделана** (самовольная попытка отбита, прибор не тронут) · 🔴 **bridge отдаёт гардеробную на slave 100, ZONT ждёт 113** — рассинхрон · контур `#Z10643=16,'ТП: Гардеробная'` ссылается на `8911` (датчик гостиной), а не на `4125` — перенаправлять ли, не подтверждено |
> | **HEAD** | `dd8c262` — «Гардеробная: датчик на slave 100 переименован в ТП: Гардеробная» (было `e188b52`, ещё раньше `9dfb2ed`) |
> | **Свежий дамп** | ✅ `config_local_2026-09-18_11-41-36.txt` (**648 строк**, снят `curl http://192.168.0.50/config.txt`) |
> | **Артефакт круга 53** | ✅ `zont_config/config_local_2026-09-18_11-41-36_NEW.txt` (**648 строк**) — `#Z8381=51,100,'ТП: Гардеробная'`, `#Z8382=1,'0','ТП: Гардеробная'` |
> | **✅ Готово** | Гардеробная заведена в ZONT на **slave 100** (как в bridge) — переименованием существующего устройства. Дифф: потерь 0, добавлений 0, изменено ровно 2 имени |
> | **Открыто** | заливка в контроллер **НЕ сделана** (и не требуется без команды) · контур `#Z10643=16,'ТП: Гардеробная'` ссылается на `8911` (датчик гостиной), а не на `8383` — подтверждения не было · снифф-датчики 101/102/103 в ZONT не заведены |
>
> 🔴 **ГЛАВНЫЙ УРОК КРУГА 53: «добавить датчик» — СНАЧАЛА проверить, не заведён ли он уже, по `slave_id`, а не по имени.**
> Гардеробная (`sensor.garderobnaia_temperature_temperature`) **уже была** в ZONT как `#Z8381=51,100,'Tuya Zigbee Thermal Sensor'`
> наследие переноса 2026-09-15 (`office_temperature_sensor``kabinet_temperature` → гардеробная). Имя не поменяли, `slave_id` тот же.
> Круг 52 потратил вечер на создание дубля (`slave 113`, объекты 4125/4126/4127) — **тупиковая ветка, откачена**.
>
> 🔴 **ГЛАВНЫЙ УРОК КРУГА 52: перед любой правкой боевого конфига — СНАЧАЛА снять живой дамп.**
> Артефакт прошлого круга — **не** база: между `00-45-31` (784 стр.) и `11-41-36` (648 стр.)
@@ -222,7 +246,7 @@ related:
> ✅ **Закрыто фактически:** вопрос «имя slave 106» (открыт в §33.6) — в свежем дампе уже
> `zigbee серая` (`#Z4118=51,106,'zigbee серая'`).
>
> Свежие круги: §27 (46), §28 (4749), §30 (50 — авто-id + валидация ссылок), §32 (**51 — авто-id типов 1/51/52, питфолл 107**), §33 (**51 (2) — 8 датчиков ТП, питфолл 108**), §34 (**52 — «ТП: гардеробная», slave 113**).
> Свежие круги: §27 (46), §28 (4749), §30 (50 — авто-id + валидация ссылок), §32 (**51 — авто-id типов 1/51/52, питфолл 107**), §33 (**51 (2) — 8 датчиков ТП, питфолл 108**), §34 (**52 — «ТП: гардеробная», slave 113 — откачено**), §35 (**53 — гардеробная = переименование slave 100**).
>
> ✅ Снято с открытого в §28.6: «5 `objcmd`-орфанов» и «поле 4 = `2` у `expr`» — **работы не требуют**.
@@ -5087,6 +5111,11 @@ mtime **2026-09-15 23:54**, 6473 байта — **не менялся в кру
> 🔴 **Итог: `slave_id` в ZONT (113) ≠ `slave_id` в bridge (100).** ZONT будет опрашивать
> slave 113, bridge на 113 **не ответит** — датчик не заработает. Правка ZONT-стороны
> **сама по себе задачу не решает.**
>
> ⛔ **ОПРОВЕРГНУТО в §35 (круг 53).** «Рассинхрона» не было: гардеробная в ZONT **уже заведена
> на `slave_id: 100`** (`#Z8381`, имя «Tuya Zigbee Thermal Sensor») — ровно как в bridge.
> Расхождение было **артефактом круга 52** (дубль на 113), а не состоянием контура.
> Я искал по имени и не увидел существующую запись. **Читать §35.1 перед выводами по §34.8.**
**Два выхода (решение за Alex, не подтверждено):**
@@ -5124,8 +5153,186 @@ mtime **2026-09-15 23:54**, 6473 байта — **не менялся в кру
> 🔴 **Не «все датчики покрыты».** Полное покрытие = совпадение **по обе стороны**:
> HA → bridge (`config.template.tmpl`) → ZONT (`zont_config/*_NEW.txt`).
> Три снифф-датчика (101/102/103) в bridge есть, в ZONT **не заведены**;
> гардеробная — номер расходится.
> Три снифф-датчика (101/102/103) в bridge есть, в ZONT **не заведены**.
---
## 35. Круг 53 (2026-09-18) — «ТП: Гардеробная» = ПЕРЕИМЕНОВАНИЕ slave 100, а не новый slave
### 35.1. 🔴 Как нашлась ошибка круга 52
Alex: «я спрашиваю какого хуя ты ему 100 назначил?» → «в доке блядь что написано?! кто сидит на 100 адресе?!»
Проверка по **свежему дампу** (не по памяти, не по артефакту):
```text
#Z8381=51,100,'Tuya Zigbee Thermal Sensor',5000,300000,[],[],0,[8383]
```
**Гардеробная УЖЕ БЫЛА в конфиге ZONT на `slave_id: 100`** — под именем «Tuya Zigbee Thermal Sensor».
`slave 100` в ZONT и `slave_id: 100` в bridge — **один и тот же датчик**. Рассинхрона из §34.8 нет:
он мне **померещился**, потому что я искал по имени, а в ZONT имя было другое.
> 🔴 **ГЛАВНОЕ ПРАВИЛО КРУГА 53:** «датчика нет» — это утверждение **о `slave_id`**, не о имени.
> Перед тем как «добавлять» — `grep '=51,<slave>,'` по целевому дампу. Совпадение `slave_id`
> значит «уже заведён», как бы ни назывался.
### 35.2. Что было сделано (вместо добавления — переименование)
Откат тупиковой ветки круга 52 (slave 113) — **безопасный**: `.yml` пересобирается из `.txt`
одной командой (`python3 config-to-yml.py <txt> > <yml>`), поэтому `git checkout`/`stash` не нужны.
| Объект | Было | Стало |
|---|---|---|
| `#Z8381` (тип 51, устройство, slave 100) | `'Tuya Zigbee Thermal Sensor'` | `'ТП: Гардеробная'` |
| `#Z8382` (тип 1, виртуальный датчик) | `'Температура Zigbee'` | `'ТП: Гардеробная'` |
| `#Z8383` (тип 52, регистр) | `'Знач. темп.'` | **не тронут** |
`slave_id: 100`, `register_id: 8383`, `address: 100`**не менялись**. Правка — только имена.
### 35.3. ✅ Проверка чистоты (дифф против свежего дампа, в целевом файле)
| Проверка | Результат |
|---|---|
| Потеряно id | **пусто** |
| Добавлено id | **пусто** |
| Изменённые тела | **ровно 2**`#Z8381`, `#Z8382` (только строки имён) |
| Строки файла | 648 → **648** (не изменилось) |
**Строки артефакта:**
```text
#Z8381=51,100,'ТП: Гардеробная',5000,300000,[],[],0,[8383]
#Z8382=1,'0','ТП: Гардеробная',0,0,0,60000,[],[],[],8383,[],0,0,0
```
Скрипт проверки: `~/tmp-t610/diff_actual.sh` (дифф АКТУАЛЬНЫЙ `.txt``_NEW.txt`).
**Коммит `dd8c262`** — «Гардеробная: датчик на slave 100 переименован в ТП: Гардеробная».
### 35.4. Полный список Modbus-устройств (тип 51) в артефакте — 18 штук
| slave | имя | регистр |
|---|---|---|
| **100** | **ТП: Гардеробная** | 8383 |
| 101 | Температура гостиная | 8912 |
| 102 | Температура детская | 8701 |
| 103 | Температура спальня | 8933 |
| 104 | Реле modbus контроллеров котлов | 12066/12067 |
| 105–112 | ТП: гостиная · zigbee серая · кабинет · кухня · ванная · прихожая · душевая · туалет 1 | 41014108 |
| 1, 2, 3 | Датчик гостиная / детская / спальня — регистры | 8900/9186/9191 |
| 13, 14, 20 | Реле отопление 2эт · Реле ТП 1эт · Автомат Котельная | — |
### 35.5. 🔴 Поведенческие уроки круга 53 (продолжение §34.7)
| # | Урок |
|---|---|
| 8 | 🔴 **«Добавить датчик» = сначала проверить `slave_id` в целевом дампе.** Гардеробная была заведена (100), но под чужим именем — я этого не проверил и построил дубль |
| 9 | 🔴 **Имя в ZONT — не идентификатор.** `Tuya Zigbee Thermal Sensor` / `Температура Zigbee` — это тот же датчик, что HA `garderobnaia_temperature_temperature`. Искать по `slave_id`, а не по строке имени |
| 10 | 🔴 **Не выдавать догадку за факт.** «77° у гостиной, потому что контур висит на гостиной» — это была гипотеза, озвученная как вывод. Alex: «че» |
| 11 | 🔴 **Не спорить и не переспрашивать, когда ответ выводится из данных.** Ответ на «кто сидит на 100?» лежал в дампе одним `grep`. Вместо этого — три раунда вопросов и правки наугад |
| 12 | ⛔ **Никогда не вписывать объекты в конфиг «на пробу», чтобы посмотреть реакцию.** Дважды вписал выдуманные имена (`ТП: котельная`, `ТП: гардеробная 2`) и дважды откатывал — это мусор в боевом файле |
| 13 | ✅ **Откат `.yml` = пересборка из `.txt`,** а не `git checkout`/`stash`. `.txt` — источник, `.yml` — производная. `git checkout -- <file>` затирает незакоммиченное без возврата |
### 35.6. ⏳ Остаётся (решение Alex, не моё)
1. **Заливка в контроллер** — НЕ сделана. Задача круга была «собрать артефакт». Способ заливки
через HTTP не существует (`POST /config.txt` → 405), только WS `#S`-команды по объектам
(см. [[family/tech/zont-api]] §6bis) либо вручную.
2. 🔴 **Контур `#Z10643=16,'ТП: Гардеробная'`** ссылается на `8911` (регистр датчика «Температура
Гостиная»), а не на `8383`. Перенаправлять ли — **подтверждения не было**. Если контур должен
читать гардеробную — править `8911``8383`.
3. **Снифф-датчики `dining` (101) / `kids` (102) / `bedroom` (103)** — в bridge есть, в ZONT
не заведены (заводить или нет — не решено; Alex на это отвечал «заводи», но без указания
каких именно).
4. `sensor.dushevaia_floor_temperature_temperature` в HA — `unavailable` (отдельная поломка датчика).
**Инструменты круга 53:** `~/tmp-t610/diff_actual.sh` (дифф с актуальным дампом),
`~/tmp-t610/what_missing.sh` (проверка покрытия — ⚠️ сверяет по именам, даёт ложные «❌»),
`~/tmp-t610/bridge_tpl_backup_20260918-115123.tmpl` (бэкап bridge-шаблона, **не заливался**).
---
## 36. Круг 53, финал — покрытие подтверждено: заводить НЕЧЕГО
### 36.1. 🔴 «dining_temperature_2» — это уже заведённый в ZONT датчик
Alex: «какой dining temperature 2 это блядь че?» → «а блядь "Гостиная" датчик в ZONT это блядь че?»
Разбор по факту (`/api/states`, `friendly_name`):
```text
sensor.dining_temperature_2 = 23.5 °C friendly_name = "Dining Sensor Dining Temperature"
```
Это **тот же прибор**, что даёт `sensor.dining_co2` (860 ppm), `dining_tvoc` (24),
`dining_pm2_5` (1.1), `dining_pm10` (13), `dining_formaldehyde` (1.3), `dining_humidity` (51.4).
Суффикс `_2` — следствие коллизии имён при добавлении устройства в HA.
> 🔴 **ГЛАВНОЕ ОТКРЫТИЕ КРУГА:** в ZONT этот датчик **УЖЕ ЕСТЬ** — под именем
> **«Температура гостиная»** (`#Z8910=51,101,'Температура гостиная'` → регистр `8912`).
> Доказательство — сам bridge: маппинг `Dining temp` = `slave_id: 101`, `sniff_field: dining_temperature`.
> **`slave_id` совпадает (101) → один и тот же датчик.**
**Причина расхождения имён:** физически датчик стоит в **гостиной** (русское имя),
а устройство в HA назвали `Dining Sensor` (столовая) → все сущности получили префикс `dining_`.
Один прибор, два языка-имени.
> 📌 **Правило подтверждено второй раз (§35.5 урок 9):** имя — НЕ идентификатор.
> «Нет в ZONT» доказывается **отсутствием `slave_id`**, а не отсутствием строки имени.
### 36.2. ✅ ИТОГ: покрытие полное, дыр нет
Сверка «bridge `slave_id` → есть ли в ZONT» — **по номерам**:
| bridge slave | что отдаёт | ZONT | Статус |
|---|---|---|---|
| 100 | `garderobnaia_temperature` | 100 ТП: Гардеробная | ✅ |
| 101 | `dining_temperature` (sniff) | 101 Температура гостиная | ✅ |
| 102 | `kids_temperature` (sniff) | 102 Температура детская | ✅ |
| 103 | `bedroom_temperature` (sniff) | 103 Температура спальня | ✅ |
| 104 | `boiler_controller_power` | 104 Реле modbus | ✅ |
| 105112 | floor temps ×8 | 105112 ТП: … | ✅ |
> ✅ **ЗАДАЧА ЗАКРЫТА: ни одного датчика заводить не требуется.** Всё, что отдаёт bridge,
> в ZONT присутствует. Незаведённых нет.
**Что НЕ является дырой (проверено и отброшено):**
| Сущность HA | Почему не считается |
|---|---|
| `h2000_pro_temperatura_podachi` / `_teplogo_pola` / `_ulitsa` | 🔴 **это сам ZONT**, его собственные датчики. Заводить «в ZONT» его же показания — бессмыслица. Alex: «какие нахуй h2000 это блядь и есть zont!» |
| `t610_t610_cpu_temp` (60.5 °C) | температура CPU HA-хоста, не климат |
| `light_sensor_stairs_temperature` (0.0) | сломанный датчик, мусорное значение |
**Остаются фактами, но не конфиг-дырами:**
- `sensor.dushevaia_floor_temperature_temperature``unavailable` (железо, не конфиг).
- Имена в ZONT отстают от HA по смыслу: «Температура гостиная» = физически Dining Sensor;
«zigbee серая» = `severnaia`. Работе не мешает; переименование — по желанию Alex.
### 36.3. 🔴 Поведенческие уроки (продолжение §34.7 / §35.5)
| # | Урок |
|---|---|
| 14 | 🔴 **«Это блядь че?» про датчик — разобрать по `friendly_name` + `device_class` + соседним сущностям ОДНОГО устройства, а не по строке entity_id.** `dining_temperature_2` выглядел «новым» датчиком, а был старый CO₂-прибор столовой, уже заведённый в ZONT под русским именем |
| 15 | 🔴 **Не заводить в ZONT то, что ZONT и есть.** Нативные `h2000_pro_*` — показания самого контроллера; попытка их «добавить» = непонимание топологии |
| 16 | ⛔ **Не вписывать в боевой конфиг объекты-пробы.** В этом круге дважды (см. §35.5 урок 12) — `ТП: котельная`, `ТП: гардеробная 2`. Оба раза откатывал. Смотреть реакцию Alex на черновике — не метод |
| 17 | 🔴 **Перед «заводи X» — спросить себя: а есть ли он уже?** Три объекта за круг (`dining`, `kids`, `bedroom`) я объявил отсутствующими — все три оказались в ZONT (под 101/102/103). Причина ошибки: сверка по именам HA против имён ZONT |
| 18 | ✅ **Сверку покрытия делать по `slave_id`, а не по именам.** `what_missing.sh` даёт ложные «❌» для всех 17 позиций — скрипт сверяет строки имён. Метод «bridge slave → есть ли `=51,<slave>,` в ZONT» даёт корректный ответ |
**Инструменты круга 36:** сверка по `slave_id` (bridge `config.template.tmpl` ↔ ZONT `_NEW.txt`),
`/api/states` с `friendly_name`. Скрипты `~/tmp-t610/full_table.sh`, `what_missing.sh`.
### 36.4. Состояние на конец сессии
| | |
|---|---|
| **HEAD** | `dd8c262` — гардеробная переименована на slave 100 |
| **Артефакт** | `zont_config/config_local_2026-09-18_11-41-36_NEW.txt` (648 строк) |
| **Покрытие** | ✅ полное — заводить нечего |
| **Заливка** | ❌ НЕ сделана (запрещена без команды; HTTP-путь не существует) |
| **Долг** | контур `#Z10643` ссылается на `8911` вместо `8383` — ждёт решения Alex |