diff --git a/family/how-to/gitea-config.md b/family/how-to/gitea-config.md index b6fdf691..6d657570 100644 --- a/family/how-to/gitea-config.md +++ b/family/how-to/gitea-config.md @@ -63,7 +63,7 @@ git push -u origin main | `git_admin/nolvu-landing` | private | | `git_admin/obsidian-vault` | **public** (единственный) | | `git_admin/reflect-app` | private | -| `git_admin/HA-ZONT-Modbus` | private (создан 2026-09-14, см. `[[family/how-to/home-automation]]` §5-кватер-Е) | +| `git_admin/HA-ZONT-Modbus` | private (создан 2026-09-14, см. `[[family/how-to/home-automation]]` §5-кватер-Е) · документация конвертеров конфига ZONT: [[family/how-to/zont-config-compiler]] | ## Питфоллы diff --git a/family/how-to/home-automation.md b/family/how-to/home-automation.md index 6db645fc..3077dcbc 100644 --- a/family/how-to/home-automation.md +++ b/family/how-to/home-automation.md @@ -621,6 +621,8 @@ curl -s -H @/tmp/h1 "$B/api/config/automation/config/" > /tmp/aut_.json ### Правило адресов +> ⚙️ **Конфиг самого ZONT правится конвертерами `.txt ⇄ .yml`** (`/Users/admin/Automation/HA-ZONT-Modbus`): [[family/how-to/zont-config-compiler]] · справочник типов объектов — [[family/tech/zont-config-object-types]] + - **Реальные 485:** `1–99` (датчики 1/2/3, AT2 = 10, relay 11/12/13/14, газ-котёл вкл = 20). - **Виртуальные (bridge):** `100–112` — `100` **гардеробная** (исторический датчик, был `office_temperature_sensor` → `kabinet_temperature`), `101/102/103` Гостиная/Детская/Спальня (рег. 100), `104:1` Zigbee-реле котла, **`105–112` температурные Zigbee-датчики тёплых полов** (гостиная/серая/кабинет/кухня/ванная/прихожая/душевая/туалет). - **Свободно:** `113+`; у 100/102/103 — только регистры ≠ 100. `104:2+` свободны. diff --git a/family/how-to/zont-config-compiler.md b/family/how-to/zont-config-compiler.md new file mode 100644 index 00000000..0d4f2fb2 --- /dev/null +++ b/family/how-to/zont-config-compiler.md @@ -0,0 +1,197 @@ +--- +title: ⚙️ ZONT Config Compiler — конвертеры .txt ⇄ .yml +aliases: + - ZONT config compiler + - config-to-yml + - yml-to-config + - HA-ZONT-Modbus + - ZONT конфиг конвертеры +tags: + - family + - how-to + - zont + - modbus + - homeautomation +created: '2026-09-17' +updated: '2026-09-17' +type: how-to +namespace: family +related: + - '[[family/tech/zont-config-object-types]]' + - '[[family/how-to/home-automation]]' + - '[[family/how-to/gitea-config]]' +--- + +# ⚙️ ZONT Config Compiler — конвертеры конфига (.txt ⇄ .yml) + +> **Что это:** двусторонние конвертеры между форматом конфига контроллера **ZONT** (`.txt`) и читаемым **YAML**. Позволяют править конфиг руками (имена реле, адреса Modbus, датчики), не лазя в UI контроллера. +> **Справочник типов объектов:** [[family/tech/zont-config-object-types]] +> **Контекст (ZONT в общем контуре, slave ID, регистры):** [[family/how-to/home-automation]] §6 +> **Repo (private):** `https://git.mallexxx.duckdns.org/git_admin/HA-ZONT-Modbus` — [[family/how-to/gitea-config]] + +--- + +## 1. Где лежит + +| | | +|---|---| +| **Локальный путь (Mac)** | `/Users/admin/Automation/HA-ZONT-Modbus` | +| **Git remote** | `https://git.mallexxx.duckdns.org/git_admin/HA-ZONT-Modbus.git` (private) | +| **Скрипты** | `config-to-yml.py` (TXT → YAML), `yml-to-config.py` (YAML → TXT) | +| **README конвертеров** | `README_converters.md` в корне проекта | +| **Рабочие конфиги** | `zont_config/` (свежие), `zont_config/archive/` (историчные `H2000_PRO_config_actual-*`) | +| **Инфраструктурный контекст проекта** | `INFRASTRUCTURE.md` в корне — **описывает старый стек на TrueNAS** (docker-контейнеры `homeassistant`/`modbus-bridge`/`mbusd` там уже погашены, автоматизация переехала на t610). Актуальный контур — [[family/how-to/home-automation]] | + +> ⚠️ `INFRASTRUCTURE.md` + `docker-compose.yml` + `docker run.txt` в репозитории — **исторические** (TrueNAS-стек). Не использовать как инструкцию по текущей инфраструктуре. +> 🔴 `zont_config/*.yml` в репозитории частично удалены/пересозданы — `git status` в проекте грязный (6 удалений + новые файлы незакоммичены). + +--- + +## 2. Как работает + +### Формат конфига ZONT + +Текстовый файл, по одной записи на строку, **CRLF**, кодировка **windows-1251** (fallback чтения — UTF-8): + +``` +#Z=,<поле>,<поле>,... +#S=<значение> +``` + +- `#Z…` — объекты конфигурации (реле, датчики, сценарии, Modbus-устройства и т.д.). Порядок строк значим — сохраняется. +- `#S…` — системные настройки (`#S7=` модель, `#S202=` серийник, `#S217=` MQTT-URL и пр.). +- Тип объекта — **числом первым полем**: `#Z12=14,'Спальня левый',...` = объект id 12, тип 14 (реле). +- Специальные записи-маркеры: `#Z=*`. +- Значения в `'одинарных кавычках'`; списки — `[...]`; числа — как есть. + +### Идентификаторы объектов + +| Префикс | Смысл | В YAML | +|---|---|---| +| `#Z` | объект конфигурации | разложен по секциям (`relays`, `modbus_devices`, …) | +| `#S` | системная настройка | секция `system_settings` (сохраняется как `id` + `raw_payload`) | + +### Что делает `config-to-yml.py` + +1. Читает файл, определяет кодировку (UTF-8 → windows-1251). +2. Парсит строки по регекспу `^#([ZS])(\d+)=(.*)$` — **хвостовые пробелы в payload сохраняются**. +3. `split_payload()` — разбирает payload с учётом вложенности `[…` и кавычек (запятые внутри кавычек/скобок не разделяют). +4. `parse_atom()` — `''`/пусто → `None`, `'строка'` → строка, `[список]` → список, иначе int → float → строка. +5. Раскладывает объекты по секциям YAML, вложенные объекты прячет под родителя (регистры типа 52 → внутрь Modbus-устройства типа 51). +6. `system_settings` выносит **в начало** файла — чтобы было видно при правке. + +### Что делает `yml-to-config.py` + +1. Загружает YAML. +2. Едет обратно по секциям **в порядке типов** и собирает строки `#Z=…`. +3. Форматирование: числа — без кавычек, строки — в `'…'`, bool → `0/1`, пустая строка → `''`, списки → `[…]`. +4. Восстанавливает вложенное: регистры типа 52 пишутся отдельными строками после своего устройства. +5. `validate_config()` — проверяет структуру **до вывода**; при ошибках печатает `❌ VALIDATION ERRORS`, exit code **4**, файл не отдаётся. +6. Вывод: **windows-1251** (`errors='replace'`), строки через **CRLF**, финальный перевод строки — как в оригинале. + +### Коды возврата + +| Скрипт | Код | Значение | +|---|---|---| +| `yml-to-config.py` | 1 | файл не найден | +| | 2 | `ConversionError` (нет `raw`, неизвестный тип) | +| | 3 | прочее исключение | +| | 4 | ❌ ошибки валидации | +| `config-to-yml.py` | 1 | неверное число аргументов | +| | 2 | `ParseError` (неизвестный формат строки, неразбираемое значение) | + +--- + +## 3. Как пользоваться + +### Зависимости + +- `python3` +- `PyYAML` (`import yaml`). Проверить: `python3 -c 'import yaml; print(yaml.__version__)'` + +### ⚠️ Правильный обход (важно: имена файлов и каналы) + +Оба скрипта **пишут в stdout**, а `yml-to-config.py` **отдаёт windows-1251** — редирект через `>` в терминале Mac сохранит байты как надо, но копипаст из терминала кодировку убьёт. + +```bash +cd /Users/admin/Automation/HA-ZONT-Modbus + +# 1. Снять текущий конфиг с контроллера → положить в zont_config/ +# (файлы вида config___.txt) + +# 2. TXT → YAML +python3 config-to-yml.py zont_config/config_XXXX.txt > /tmp/zont.yml + +# 3. Правка YAML (имена, адреса, пороги) +# ⚠️ НЕ добавлять/удалять объекты с новыми id без нужды — порядок и id значимы + +# 4. YAML → TXT +python3 yml-to-config.py /tmp/zont.yml > /tmp/zont_new.txt + +# 5. Сверить: число строк #Z и #S до/после +grep -c '^#Z' /tmp/zont_new.txt + +# 6. Только после сверки — загружать zont_new.txt в контроллер +``` + +### Разделение «сырое» ↔ «человеческое» + +Часть полей в YAML декодирована (адрес, интервал опроса, регистры), часть остаётся как `raw` / `raw_params` / `raw_field_N` — это **страховка**. `yml-to-config.py` при пустом `raw` подставит дефолты (для типа 0 — жёстко зашитый набор, для типа 36 — `[],[],[],10,0`), и такие объекты **потеряют исходные значения**. + +> 🔴 **Правило: правь декодированные поля, `raw` не трогай вообще.** Если поле не декодировано — правка возможна только с пониманием исходного формата. + +### Поддерживаемые типы объектов (по README) + +Типы: `1, 3, 4, 5, 6, 7, 9, 10, 11, 14, 16, 20, 24, 25, 27, 28, 42, 46, 49, 51, 52, 53, 57` +➕ фактически обрабатываются ещё **`0`** (дискретные датчики — индикаторы состояния реле) и **`36`** (конфиги дискретных датчиков, вытащенные из вложенной структуры). +Полная таблица — [[family/tech/zont-config-object-types]]. + +Неизвестный тип → скрипт **падает с ошибкой**, а не молча теряет объект. Это сделано намеренно, чтобы не портить конфиг. + +--- + +## 4. Round-trip (проверка целостности) + +Заявлено в `README_converters.md`: **round-trip 130/130 объектов, TXT → YAML → TXT идентичен**. + +> ⚠️ **Не воспроизводил** — при подготовке этой доки прогон не выполнялся. Относиться как к заявлению README, а не как к проверенному факту. + +Команда для самостоятельной проверки (безопасна, работает в `/tmp`): + +```bash +cd /tmp && rm -rf zont-rt && mkdir zont-rt && cd zont-rt +SRC=/Users/admin/Automation/HA-ZONT-Modbus/zont_config/<файл>.txt +python3 /Users/admin/Automation/HA-ZONT-Modbus/config-to-yml.py "$SRC" > a.yml +python3 /Users/admin/Automation/HA-ZONT-Modbus/yml-to-config.py a.yml > b.txt +tr -d '\r' < "$SRC" > A.txt; tr -d '\r' < b.txt > B.txt +diff A.txt B.txt # пустой вывод = round-trip чистый +grep -c '^#Z' A.txt B.txt +``` + +> 📌 **Нюанс:** источник бывает в UTF-8, а вывод `yml-to-config.py` — всегда windows-1251. При diff кириллица в именах даст различия на уровне байтов. Сравнивать по структуре (`#Z` / `#S` + числовые поля), либо предварительно нормализовать кодировку с обеих сторон. + +--- + +## 5. Питфоллы + +| # | Питфолл | Обход | +|---|---|---| +| 1 | 🔴 **`yml-to-config.py` пишет windows-1251**, не UTF-8 | Редирект в **файл** (`> out.txt`), не копипаст. Файл загружать байтами, не через текстовый редактор с перекодировкой | +| 2 | 🔴 **CRLF-переводы строк** обязательны | Скрипт сам ставит `\r\n`. Не «нормализовать» вывод | +| 3 | 🔴 **Потеря `raw` → подстановка дефолтов** | Не трогать `raw*`-поля. Пустой `raw` у типа 0/36 → жёсткие дефолты в скрипте | +| 4 | **`#S`-настройки сохраняются как `raw_payload`** | Править их руками в YAML бессмысленно/опасно — только через UI контроллера | +| 5 | **Кодировка чтения автоопределяется** (UTF-8 → windows-1251) | Не пересохранять исходник в редакторе — можно уехать в другую кодировку | +| 6 | **Неизвестный тип объекта = exit 2, а не тихий пропуск** | Читать stderr; файл не создаётся | +| 7 | **`validate_config` отдаёт exit 4 без вывода файла** | При `❌ VALIDATION ERRORS` смотреть список; вывод пустой — это норма | +| 8 | **`INFRASTRUCTURE.md` в проекте описывает мёртвый TrueNAS-стек** | Актуальное — [[family/how-to/home-automation]]. Не искать docker-контейнеры `modbus-bridge`/`mbusd` на TrueNAS | +| 9 | **Изменённый конфиг загружать в ZONT руками (UI/облако), не скриптом** | Скрипты только конвертируют. Проверку результата делает Alex | +| 10 | **`jsonschema`/`ruamel` НЕ нужны** | Только `pyyaml` | + +--- + +## 6. Связанные заметки + +- [[family/tech/zont-config-object-types]] — таблица типов объектов (1…57, 0, 36) +- [[family/how-to/home-automation]] — общий контур автоматизации, ZONT, Modbus slave ID и регистры (§6) +- [[family/how-to/gitea-config]] — Gitea, креды, создание репо +- [[family/how-to/ha-automations]] — автоматизации HA diff --git a/family/tech/zont-config-object-types.md b/family/tech/zont-config-object-types.md new file mode 100644 index 00000000..67c933aa --- /dev/null +++ b/family/tech/zont-config-object-types.md @@ -0,0 +1,119 @@ +--- +aliases: + - ZONT типы объектов + - ZONT object types + - ZONT config types +created: '2026-09-17' +namespace: family +related: + - '[[family/how-to/zont-config-compiler]]' + - '[[family/how-to/home-automation]]' +tags: + - family + - tech + - zont + - modbus + - reference +title: "\U0001F9E9 ZONT Config — типы объектов" +type: reference +updated: '2026-09-17' +--- + +# 🧩 ZONT Config — типы объектов + +> Справочник по типам объектов конфига ZONT (первое поле в `#Z=,…`). +> **Инструкция по конвертерам:** [[family/how-to/zont-config-compiler]] +> **Источник:** `config-to-yml.py` / `yml-to-config.py` в `/Users/admin/Automation/HA-ZONT-Modbus`, `README_converters.md` +> ⚠️ Таблица ниже — по README; колонка «Что реально делает скрипт» — по коду. Расхождения помечены. + +--- + +## 1. Таблица типов + +| Тип | Объект | Декодируемые поля | Секция в YAML | +|---|---|---|---| +| **0** | Дискретные датчики (индикаторы состояния реле) | `register_ref`, `name`, `config` | `discrete_sensors` | +| 1 | Виртуальные датчики | `address`, `name`, `register_id`, пороги, гистерезис, калибровка | `virtual_sensors` | +| 3 | SMS-уведомления | `name` | `sms_notifications` | +| 4 | Контакты пользователей | `name`, `phones` | `user_contacts` | +| 5 | Действия (actions) | `name`, `output_ref`, `value`, `raw_params` | `actions` | +| 6 | Адаптеры | `address`, `name` | `adapters` | +| 7 | Радиомодули | `address`, `name` | `radio_modules` | +| 9 | MQTT-команды (кнопка GUI → управление реле) | `name`, `target_relay`, `value` | `relay_commands` | +| 10 | GUI-переключатели | `name` | `gui_switches` | +| 11 | Сценарии | `name`, `when`, `do` — **парсятся полностью, человекочитаемо** | `scenarios` | +| 14 | Реле | `name`, `address`, `state` | `relays` | +| 16 | Отопительные контуры | `name` | `heating_circuits` | +| 20 | Режимы отопления | `name` | `heating_modes` | +| 24 | Сопроцессоры | `address`, `name` | `coprocessors` | +| 25 | Отопительные кривые | `name` | `heating_curves` | +| 27 | Датчики температуры | `address`, `name` | `temperature_sensors` | +| 28 | Таблицы сопротивлений | *(raw)* | `resistance_tables` | +| **36** | Конфиги дискретных датчиков (вытащены из вложенной структуры типа 0) | `raw` | вложено в `discrete_sensors[].config` | +| 42 | GUI-вкладки | `name` | `gui_tabs` | +| 46 | Шаги сценариев | *(raw; помечаются как уже разобранные)* | внутри `scenarios` | +| 49 | Условия сценариев | *(raw; помечаются как уже разобранные)* | внутри `scenarios` | +| 51 | Modbus-устройства | `slave_id`, `name`, `poll_interval`, `timeout`, `registers`, `raw_params` | `modbus_devices` | +| 52 | Modbus-регистры | `name`, `register`, `bit_width`, `repeat_period`, `num_vars`, `raw_params` | **вложены в своё устройство 51** | +| 53 | Аналоговые выходы | `name`, `min`, `max`, `value`, `offset`, `scale`, `flags`, `address` | `analog_outputs` | +| 57 | MQTT-топики | `topic`, `sensors` | `mqtt_topics` | + +--- + +## 2. Что реально важно знать + +### 2.1. `#S`-объекты — системные настройки + +Идут не по типам, а по id: `#S=…`. В YAML — секция `system_settings` **первой**, каждый как `{id, raw_payload}`. + +Примеры (из живого конфига H2000_PRO): + +| Ключ | Значение (пример) | Смысл | +|---|---|---| +| `#S7` | `H2000_PRO 723 678` | модель + версии ПО | +| `#S200` | `s1.zont.online,s2.zont.online` | серверы ZONT | +| `#S202` | `0FA7C33CC89F <пароль>` | серийник + учётка облака | +| `#S217` | `mqtt://zont:…@192.168.0.10:1883` | MQTT-брокер | +| `#S218` | `'zont','qwertyui'` | логин/пароль MQTT | +| `#S221` | `homeassistant` | префикс discovery | +| `#S124` | `1,9600,0,0` | параметры шины (slave, baud) | + +> 🔴 `raw_payload` **не декодируется** и при обратной сборке пишется как есть. Правки `#S` через YAML — только если точно знаешь формат; безопаснее через UI контроллера. + +### 2.2. Вложенность 51 → 52 + +Modbus-регистры (тип 52) в конфиге — **отдельные строки**, но в YAML вкладываются внутрь своего устройства (тип 51). `yml-to-config.py` при сборке выводит их обратно отдельными строками в порядке id. + +⚠️ Если регистр ссылается на устройство, которого нет — `config-to-yml.py` предупреждает в stderr (`WARNING: … references non-existent …`), но не падает. Аналогично для аналоговых выходов (53). + +### 2.3. Сценарии (11 + 46 + 49) + +Тип 11 парсится **целиком** — `when` (условия) и `do` (действия) собираются в человекочитаемый вид, включая шаги (46) и условия (49). Сами 46/49 при разборе помечаются как «уже вложенные» — в YAML отдельными секциями их нет. + +### 2.4. `*`-маркеры + +Специальные записи вида `#Z=*` — «пустой» / унаследованный объект. Обрабатываются отдельным блоком; в YAML сохраняются как маркер. + +### 2.5. Дискретные датчики (0 + 36) + +`#Z=0,…` — индикатор состояния (например, показ статуса реле в GUI). Внутри него — **вложенный конфиг**, который в конфиге ZONT лежит отдельной строкой **типа 36** с собственным id, а в YAML живёт как `config` внутри объекта. + +🔴 **Питфолл.** При сборке, если у объекта 36 нет `raw`, скрипт подставляет дефолт `[],[],[],10,0`; если у объекта 0 нет `raw` — жёстко зашитый набор из 16 полей. Оба случая = **потеря исходных настроек**. Не чистить `raw` у 0/36. + +### 2.6. Коды возврата / падения + +| Ситуация | Поведение | +|---|---| +| Неизвестный формат строки (не `#Z`/`#S`) | `ParseError` → exit 2 (**до** вывода) | +| Значение не парсится (`literal_eval` падает) | `ParseError` → exit 2 | +| Неизвестный тип объекта | `ConversionError` → exit 2 | +| Ошибки валидации при сборке | `❌ VALIDATION ERRORS` → exit 4, файл не отдаётся | +| Ссылка на несуществующее устройство | WARNING в stderr, конвертация продолжается | + +--- + +## 3. Связанные заметки + +- [[family/how-to/zont-config-compiler]] — как пользоваться конвертерами, питфоллы, обход +- [[family/how-to/home-automation]] §6 — карта slave ID, регистры AT2/реле/заслонок в HA +- [[family/tech/t610-hang-investigation]] — расследование зависаний хоста (не связано напрямую, но тот же контур)