--- 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