[2026-09-17] eagle: family/how-to/zont-config-compiler.md family/tech/zont-scenario-logic-11109.md
This commit is contained in:
@@ -21,7 +21,7 @@ tags:
|
|||||||
- homeautomation
|
- homeautomation
|
||||||
title: ⚙️ ZONT Config Compiler — конвертеры .txt ⇄ .yml
|
title: ⚙️ ZONT Config Compiler — конвертеры .txt ⇄ .yml
|
||||||
type: how-to
|
type: how-to
|
||||||
updated: 2026-09-17l
|
updated: 2026-09-17m
|
||||||
---
|
---
|
||||||
|
|
||||||
# ⚙️ ZONT Config Compiler — конвертеры `.txt ⇄ .yml`
|
# ⚙️ ZONT Config Compiler — конвертеры `.txt ⇄ .yml`
|
||||||
@@ -474,14 +474,37 @@ scenarios:
|
|||||||
| `50`, неизвестные | `raw: […]` | `{id: 8548, raw: [50, 1, 0, 0, 109]}` |
|
| `50`, неизвестные | `raw: […]` | `{id: 8548, raw: [50, 1, 0, 0, 109]}` |
|
||||||
|
|
||||||
**Type 9 — команда (реле / контур / режим).** Формат в конфиге: `[9, '<подпись>', <id цели>, '<значение>']`.
|
**Type 9 — команда (реле / контур / режим).** Формат в конфиге: `[9, '<подпись>', <id цели>, '<значение>']`.
|
||||||
`target` разворачивается в `target_name` + `target_type`; `value` — строка (`'1'`/`'0'` или id-ссылка).
|
`target` разворачивается в `target_name` + `target_type`; `value` — строка (`'1'`/`'0'` или **код уставки**).
|
||||||
Проверено: `9826`→тип 14 (реле), `8641`→тип 16 (контур `Спальня`), `8640`→тип 20 (режим `Режим отопления`),
|
Проверено: `9826`→тип 14 (реле), `8641`→тип 16 (контур `Спальня`), `8640`→тип 20 (режим `Режим отопления`),
|
||||||
`8470`→тип 16 (`Контур ГВС`, значение `'8574'`).
|
`8470`→тип 16 (`Контур ГВС`, значение `'8574'`).
|
||||||
⚠️ **Поле 4 (`'2968'`, `'8574'`, `'1'`) — не значение уставки, а ссылка/код** (напр. `'2968'` при
|
|
||||||
тексте «температуру 23.8»). Семантику поля 4 **Alex не подтверждал** — не выводить её из подписи.
|
🔴 **Поле 4 у команды «установить температуру» — ЗАКОДИРОВАННАЯ УСТАВКА, а не ссылка**
|
||||||
|
(подтверждено 3 точками 2026-09-17):
|
||||||
|
|
||||||
|
```text
|
||||||
|
код = (t_celsius + 273) * 10 обратно: t_celsius = (код - 2730) / 10
|
||||||
|
```
|
||||||
|
|
||||||
|
| Уставка | Код | |
|
||||||
|
|---|---|---|
|
||||||
|
| 22 | 2950 | ✅ |
|
||||||
|
| 23.8 | 2968 | ✅ |
|
||||||
|
| 5.2 | 2782 | ✅ |
|
||||||
|
|
||||||
|
В YAML: `value: '2782'` (источник истины) + `temp_c: 5.2` (раскодировано, **только** при точном
|
||||||
|
совпадении формулы). При `value == '1'/'0'` добавляется `state_on: true/false`.
|
||||||
|
⚠️ Раньше в этой доке было ошибочно записано, что поле 4 — «ссылка, семантику Alex не подтверждал».
|
||||||
|
**Теперь подтверждено.** Подробности — [[family/tech/zont-scenario-logic-11109]] §8.13.
|
||||||
|
|
||||||
**Type 5 — действие над выходом.** Формат: `[5, '<имя>', <output_ref>, <on/off>, …]`.
|
**Type 5 — действие над выходом.** Формат: `[5, '<имя>', <output_ref>, <on/off>, …]`.
|
||||||
`output_id = output_ref >> 4`. Остальные непустые поля → `params`.
|
`output_id = output_ref >> 4` (для `9500`: `145728 >> 4 = 9108`). Остальные непустые поля → `params`.
|
||||||
|
В YAML: `{action, output, output_id, value, params?}`.
|
||||||
|
|
||||||
|
**`objcmd <target> "1 %0"` (type 59)** → в YAML `{script, args, target, target_name, set_value}`,
|
||||||
|
где `set_value = args[0]` — значение, записываемое в объект `target`
|
||||||
|
(напр. `objcmd 8700 …`, arg `14.5` → «Температура Детская = 14.5»).
|
||||||
|
🔴 **Питфолл имён:** у типа 1 имя в **поле 2**, не в поле 1 (`#Z8700=1,'0','Температура Детская',…`).
|
||||||
|
Использовать хелпер `_object_display_name(fields)`, иначе `target_name` = `'0'`.
|
||||||
|
|
||||||
**Операторы type 47 (порядок UI `<, >, =, <=, >=`):** `0`=`<`, `1`=`>`, `2`=`=`, `3`=`<=`, `4`=`>=`.
|
**Операторы type 47 (порядок UI `<, >, =, <=, >=`):** `0`=`<`, `1`=`>`, `2`=`=`, `3`=`<=`, `4`=`>=`.
|
||||||
**Логика type 48:** `0`=`and`, `1`=`or`, `2`=`not`.
|
**Логика type 48:** `0`=`and`, `1`=`or`, `2`=`not`.
|
||||||
@@ -522,6 +545,8 @@ scenarios:
|
|||||||
| 4 | 🔴 **Порядок сценария терялся** | `blocks` первым + `extra_links` голыми id → сценарий = список цифр | **Плоский `steps[]` вместо `blocks`/`extra_links`** |
|
| 4 | 🔴 **Порядок сценария терялся** | `blocks` первым + `extra_links` голыми id → сценарий = список цифр | **Плоский `steps[]` вместо `blocks`/`extra_links`** |
|
||||||
| 5 | 🔴 **Отдал артефакт, не прочитав сам** | Round-trip «байты сходятся» ≠ «читаемо». Alex открыл YAML и увидел в `8456` первым блоком `if`, а до него — список цифр | Читать глазами **главный/сложный кейс**, а не только простые 1-блочные сценарии. Питфолл 21 |
|
| 5 | 🔴 **Отдал артефакт, не прочитав сам** | Round-trip «байты сходятся» ≠ «читаемо». Alex открыл YAML и увидел в `8456` первым блоком `if`, а до него — список цифр | Читать глазами **главный/сложный кейс**, а не только простые 1-блочные сценарии. Питфолл 21 |
|
||||||
| 6 | **Много `raw` в шагах** | type 9/5 рендерились как `raw: [...]` хотя поля прозрачны | Раскрыты (§5c, «Type 9 / Type 5»). raw остался только у SMS (`3`) и непонятных (`50`) |
|
| 6 | **Много `raw` в шагах** | type 9/5 рендерились как `raw: [...]` хотя поля прозрачны | Раскрыты (§5c, «Type 9 / Type 5»). raw остался только у SMS (`3`) и непонятных (`50`) |
|
||||||
|
| 7 | 🔴 **Уставка температуры принята за ссылку** | Поле 4 type 9 (`'2950'`) выглядело как id отсутствующего объекта | Это **уставка в Кельвинах×10**: `код = (t+273)*10`. **Не вшивать формулу на 2 точках** — ждать ≥3 (§8.13) |
|
||||||
|
| 8 | **`target_name` = `'0'`** | У типа 1 имя в **поле 2**, не в поле 1 | Хелпер `_object_display_name(fields)` со спец-случаем типа 1 |
|
||||||
|
|
||||||
**Обязано сохраниться байт-в-байт (сохранено):**
|
**Обязано сохраниться байт-в-байт (сохранено):**
|
||||||
- порядок объектов в файле (45 идёт **после** 11, но **до** 46)
|
- порядок объектов в файле (45 идёт **после** 11, но **до** 46)
|
||||||
@@ -734,13 +759,17 @@ https://lk.zont-online.ru/download/firmwares/H2000_PRO_<HW>__<FW>_<PROFILE>.zip
|
|||||||
|
|
||||||
✅ **Round-trip чистый на 6/6 конфигах** (включая новый локальный с 660 `#Z` и legacy 7-поле `-2`).
|
✅ **Round-trip чистый на 6/6 конфигах** (включая новый локальный с 660 `#Z` и legacy 7-поле `-2`).
|
||||||
|
|
||||||
|
✅ **Уставка температуры раскодирована** — `код = (t °C + 273) × 10`, подтверждено 3 точками
|
||||||
|
(§8.13 в [[family/tech/zont-scenario-logic-11109]]). Type 9/5 и `objcmd` рендерятся читаемо.
|
||||||
|
|
||||||
| Файл | Статус |
|
| Файл | Статус |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `config-to-yml.py` | 🆕 **изменён** — парсер типов 47/48/50/59, плоский `steps[]`, триггер, type 9/5 раскрыты, raw-фоллбэк (§5c). **не закоммичено** |
|
| `config-to-yml.py` | 🆕 **изменён** — парсер типов 47/48/50/59, плоский `steps[]`, триггер, type 9/5 раскрыты, `temp_c`/`state_on`/`set_value`, `_object_display_name`, raw-фоллбэк (§5c). **не закоммичено** |
|
||||||
| `yml-to-config.py` | 🆕 **изменён** — обратные `emit_*`, `emit_step` по типу, новые секции в `TYPE_ORDER` (§5c). **не закоммичено** |
|
| `yml-to-config.py` | 🆕 **изменён** — обратные `emit_*`, `emit_step` по типу, новые секции в `TYPE_ORDER` (§5c). **не закоммичено** |
|
||||||
| `test_roundtrip.py` | ✅ в коммите `199f2b1`, без изменений |
|
| `test_roundtrip.py` | ✅ в коммите `199f2b1`, без изменений |
|
||||||
| `zont_config/config_local_2026-09-17_16-02-18.txt` | 🆕 **34 962 байт, 686 строк** — **ПОСЛЕДНИЙ** конфиг с тестовыми сценариями (Alex пересоздал: контур `Спальня`, режим `Режим отопления`). Снят с `http://192.168.0.50/config.txt`. **не в git** |
|
| `zont_config/config_local_2026-09-17_16-13-28.txt` | 🆕 **34 963 байт** — **ПОСЛЕДНИЙ** конфиг (уставка 5.2 + «Температура Детская» = 14.5). Снят с `http://192.168.0.50/config.txt`. **не в git** |
|
||||||
| `zont_config/config_local_2026-09-17_16-02-18.yml` | 🆕 разобранный YAML (**финальная форма**) — round-trip ✅. **не в git** |
|
| `zont_config/config_local_2026-09-17_16-13-28.yml` | 🆕 разобранный YAML (**финальная форма**), round-trip ✅. **не в git** |
|
||||||
|
| `zont_config/config_local_2026-09-17_16-02-18.txt` / `.yml` | 34 962 байт, 686 строк — предыдущий (контур `Спальня`, режим `Режим отопления`). **не в git** |
|
||||||
| `zont_config/config_local_2026-09-17_14-16-35.yml` | 🆕 разобранный YAML (предыдущий конфиг, 6110 строк). **не в git** |
|
| `zont_config/config_local_2026-09-17_14-16-35.yml` | 🆕 разобранный YAML (предыдущий конфиг, 6110 строк). **не в git** |
|
||||||
| `zont_config/config_local_2026-09-17_14-16-35.txt` | 34 907 байт, 660 `#Z` — предыдущий с тестовыми сценариями. **не в git** |
|
| `zont_config/config_local_2026-09-17_14-16-35.txt` | 34 907 байт, 660 `#Z` — предыдущий с тестовыми сценариями. **не в git** |
|
||||||
| `zont_config/config_0FA7C33CC89F_…_2026-09-17_12-12-28.txt` | 32 689 байт — свежий боевой конфиг, **не в git** |
|
| `zont_config/config_0FA7C33CC89F_…_2026-09-17_12-12-28.txt` | 32 689 байт — свежий боевой конфиг, **не в git** |
|
||||||
@@ -749,7 +778,7 @@ https://lk.zont-online.ru/download/firmwares/H2000_PRO_<HW>__<FW>_<PROFILE>.zip
|
|||||||
| `zont_api_docs/` | ✅ локальная копия доки облачного API (`zont_api_docs.html`, `.txt`, `convert.py`). **не в git** |
|
| `zont_api_docs/` | ✅ локальная копия доки облачного API (`zont_api_docs.html`, `.txt`, `convert.py`). **не в git** |
|
||||||
| `read_scenarios.py` | 🆕 **читаемый дамп сценария** — дерево если/то/иначе с именами. Токенайзер `split_top()`. **не в git** |
|
| `read_scenarios.py` | 🆕 **читаемый дамп сценария** — дерево если/то/иначе с именами. Токенайзер `split_top()`. **не в git** |
|
||||||
| `dump_new_types.py`, `probe_types.py`, `trace_scenarios.py` | 🆕 скрипты разбора сценарных типов. Разбор — [[family/tech/zont-scenario-logic-11109]] §8.8. **не в git** |
|
| `dump_new_types.py`, `probe_types.py`, `trace_scenarios.py` | 🆕 скрипты разбора сценарных типов. Разбор — [[family/tech/zont-scenario-logic-11109]] §8.8. **не в git** |
|
||||||
| `probe_sched.py`, `verify_answers.py`, `check_ops.py`, `audit_8456.py`, `audit2.py`, `chk_extra.py`, `why_raw.py` | 🆕 проверочные скрипты. **не в git** |
|
| `probe_sched.py`, `verify_answers.py`, `check_ops.py`, `audit_8456.py`, `audit2.py`, `chk_extra.py`, `why_raw.py`, `fit_temp.py`, `fit_temp2.py` | 🆕 проверочные скрипты (в т.ч. подбор формулы уставки). **не в git** |
|
||||||
| `~/rasputin-tmp/zont-util/` | ✅ настроечная утилита `H1000 Programmator` 2.8.5, прошивка `.enc`, `extract.py`. Разбор — §5g-2 |
|
| `~/rasputin-tmp/zont-util/` | ✅ настроечная утилита `H1000 Programmator` 2.8.5, прошивка `.enc`, `extract.py`. Разбор — §5g-2 |
|
||||||
| `~/rasputin-tmp/zont-{auth-probe,recon,recon2,ws-probe}.js` | ✅ скрипты разведки локального WS. **не в git** |
|
| `~/rasputin-tmp/zont-{auth-probe,recon,recon2,ws-probe}.js` | ✅ скрипты разведки локального WS. **не в git** |
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ tags:
|
|||||||
- homeautomation
|
- homeautomation
|
||||||
title: 🔁 ZONT — сценарная логика и конструктор (11/46/47/48/49/50/59/45/9/5)
|
title: 🔁 ZONT — сценарная логика и конструктор (11/46/47/48/49/50/59/45/9/5)
|
||||||
type: tech
|
type: tech
|
||||||
updated: 2026-09-17e
|
updated: 2026-09-17f
|
||||||
---
|
---
|
||||||
|
|
||||||
# 🔁 ZONT — сценарная логика и конструктор логики
|
# 🔁 ZONT — сценарная логика и конструктор логики
|
||||||
@@ -579,3 +579,82 @@ scenarios:
|
|||||||
`actions`) рендерятся как YAML-якоря `*id00N` (`8195`, `9500` в `8456`) — читается хуже, но байт-точно.
|
`actions`) рендерятся как YAML-якоря `*id00N` (`8195`, `9500` в `8456`) — читается хуже, но байт-точно.
|
||||||
|
|
||||||
**Артефакт:** `zont_config/config_local_2026-09-17_14-16-35.yml` (6110 строк) — в проекте, не в `/tmp`.
|
**Артефакт:** `zont_config/config_local_2026-09-17_14-16-35.yml` (6110 строк) — в проекте, не в `/tmp`.
|
||||||
|
|
||||||
|
### 8.13. 🔴 УСТАВКА ТЕМПЕРАТУРЫ — формула `код = (t °C + 273) × 10` (подтверждено 3 точками, 2026-09-17)
|
||||||
|
|
||||||
|
**Главное открытие разбора type 9.** Поле 4 команды «Установить целевую температуру» — **не ссылка,
|
||||||
|
а закодированная уставка в Кельвинах ×10** (fixed point):
|
||||||
|
|
||||||
|
```text
|
||||||
|
код = (t_celsius + 273) * 10 обратно: t_celsius = (код - 2730) / 10
|
||||||
|
```
|
||||||
|
|
||||||
|
**Три подтверждённые точки** (Alex менял температуру в UI, я сверял с конфигом):
|
||||||
|
|
||||||
|
| Уставка в UI | Код в конфиге | Проверка |
|
||||||
|
|---|---|---|
|
||||||
|
| `22` | `2950` | `(22 + 273) * 10 = 2950` ✅ |
|
||||||
|
| `23.8` | `2968` | `(23.8 + 273) * 10 = 2968` ✅ |
|
||||||
|
| `5.2` | `2782` | `(5.2 + 273) * 10 = 2782` ✅ (предсказано заранее, совпало) |
|
||||||
|
|
||||||
|
> **Как это выглядит в конфиге:** сам код уставки лежит в поле 4, а **человекочитаемая**
|
||||||
|
> температура — только в текстовой подписи поля 2, которую контроллер собирает сам:
|
||||||
|
> `#Z8817=9,'Установить целевую температуру 5.2 для контура Спальня',10034,'2782'`.
|
||||||
|
> 🔴 **Раньше я ошибочно считал `'2950'`/`'2968'` «ссылкой на отсутствующий объект»** —
|
||||||
|
> это была уставка, просто закодированная.
|
||||||
|
>
|
||||||
|
> ⚠️ **Питфолл метода:** на **двух** точках линейная формула подбирается бесконечно многими
|
||||||
|
> способами. Я нашёл `(t+273)*10` на 22 и 23.8, но **не вшивал её в парсер**, пока Alex не дал
|
||||||
|
> третью точку (5.2). Правило: **≥3 точки, прежде чем кодировать формулу.**
|
||||||
|
|
||||||
|
**Что раскрыто в YAML (type 9):**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- id: 8817
|
||||||
|
command: Установить целевую температуру 5.2 для контура Спальня
|
||||||
|
target: 10034
|
||||||
|
target_name: Спальня # развёрнуто из id (тип 16 = контур)
|
||||||
|
target_type: 16
|
||||||
|
value: '2782' # код как в конфиге (источник истины)
|
||||||
|
temp_c: 5.2 # ← раскодировано, ТОЛЬКО если формула сходится точно
|
||||||
|
- id: 9826
|
||||||
|
command: 'Включить реле «Реле 1: Конвектор кухня»'
|
||||||
|
target: 9263
|
||||||
|
target_name: 'Реле 1: Конвектор кухня'
|
||||||
|
target_type: 14 # 14 = реле
|
||||||
|
value: '1'
|
||||||
|
state_on: true
|
||||||
|
```
|
||||||
|
|
||||||
|
`temp_c` появляется **только** при точном совпадении формулы (`|round(t*10)-(код-2730)| < 0.5`);
|
||||||
|
иначе остаётся голый `value`. `state_on: true/false` — только при `value == '1'/'0'`.
|
||||||
|
|
||||||
|
### 8.14. `objcmd <id> "1 %0"` — запись значения в объект
|
||||||
|
|
||||||
|
Скрипт `#Z<id> = [59, 'objcmd <target> "1 %0"', <значение>, 0, <флаг>]` пишет `<значение>`
|
||||||
|
в объект `<target>`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- id: 8818
|
||||||
|
script: objcmd 8700 "1 %0"
|
||||||
|
args: [14.5, 0, 1]
|
||||||
|
target: 8700
|
||||||
|
target_name: Температура Детская # развёрнуто из id
|
||||||
|
set_value: 14.5 # ← «= 14.5»
|
||||||
|
```
|
||||||
|
|
||||||
|
🔴 **Питфолл имён:** у **типа 1** (виртуальный датчик) имя лежит в **поле 2**, а не в поле 1:
|
||||||
|
`#Z8700=1,'0','Температура Детская',…`. Наивный `fields[1]` даёт `'0'`.
|
||||||
|
Использовать хелпер **`_object_display_name(fields)`** — он знает про это исключение.
|
||||||
|
Проверено: `target_name` был `'0'`, после фикса — «Температура Детская».
|
||||||
|
|
||||||
|
### 8.15. Финальное состояние конвертеров (2026-09-17, вечер)
|
||||||
|
|
||||||
|
| Артефакт | Путь | Состояние |
|
||||||
|
|---|---|---|
|
||||||
|
| Сырой конфиг | `zont_config/config_local_2026-09-17_16-13-28.txt` | 34 963 Б, снят с `http://192.168.0.50/config.txt` |
|
||||||
|
| YAML | `zont_config/config_local_2026-09-17_16-13-28.yml` | в проекте, round-trip ✅ |
|
||||||
|
|
||||||
|
Round-trip чистый на **6/6** конфигах (боевой, 3 архива, `14-16-35`, `16-13-28`).
|
||||||
|
Осталось два `raw`: `8195` (SMS, тело — YAML-якорь `*id002`) и `9500` (type 5, `params` содержит якорь).
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user