zont: круг 46 — set_contour_target отделён от objcmd, Кельвин только цель 16, дубль 8817 (HEAD 75f46f3)

This commit is contained in:
Alexey Martemyanov
2026-09-17 23:58:43 +06:00
parent b44e948d7c
commit a0c7fd6397
+99 -3
View File
@@ -3688,7 +3688,7 @@ Alex отверг форму `objcmd: <имя>` («и почему objcmd: set_s
**Инструмент:** правки энкодера внесены идемпотентным скриптом `/tmp/fix_encoder_objcmd.py`
(6 замен с проверкой `count == 1`, печатает OK/SKIP) — не sed, не инлайн-питон в шелле.
### 26.6. ⏳ СЛЕДУЮЩЕЕ — тип 9 в ту же форму («имя действия — ключ»)
### 26.6. ✅ ВЫПОЛНЕНО (круг 46, коммит `75f46f3`) — тип 9 в форме «имя действия — ключ»
Запрос Alex в конце круга 45: привести тип 9 (`relay_commands`) к тому же виду, что `set_var`.
@@ -3707,8 +3707,43 @@ Alex отверг форму `objcmd: <имя>` («и почему objcmd: set_s
Ключ надо выводить **из значения** (`true`/`false` → вкл/выкл, число → сетпойнт).
`descr` при этом **обязан остаться внутри** — иначе 45 подписей исчезнут из YAML.
**Ждём от Alex:** имя ключа (`set_relay` / `set_output` / `relay_cmd`) и подтверждение, что `descr`
остаётся полем. Форма типа 9 — последний незакрытый пункт формы.
#### 🔴 Ключевое открытие: `set_contour_target` `set_contour_temp`
Alex: *«`8817` и `10379` — разные objcmd форматы (установить целевую температуру x для контура y
против установить целевую температуру для контура отопления x в значение y)»*.
| id | тип | строка | ключ | значение | смысл |
|---|---|---|---|---|---|
| `8817` | **9** | `#Z8817=9,'descr',10034,'2782'` | `set_contour_target` | `5.2` (число) | уставка ЧИСЛОМ |
| `10379` | **59** | `#Z10379=59,'objcmd 8669 ",,,%0";#h',9146,0,0` | `set_contour_temp` | `{id: 9146, type: var}` | значение ИСТОЧНИКОМ |
**Раньше оба действия носили одно имя** `set_contour_temp` → непонятно, какое из двух имеется
в виду, и тексты команд схлопывались. Два разных действия = два разных имени, ключи не пересекаются:
- **тип 9** (команда, поле 4 — уставка/код): `set_relay` · `set_contour_target` · `activate_mode`
- **тип 59** objcmd (поле 3 — объект-источник либо литерал): `set_sensor` · `set_analog_output` · `set_contour_temp`
#### Формула Кельвина — ТОЛЬКО при цели типа 16
Различие целей внутри типа 9: `2782` у контура (16) — уставка `5.2 °C`, а `8574` у режима (20) —
это **id режима отопления**, не температура. Раньше формула применялась ко всем числам >1000,
и `activate_mode` с `8574` превращался в `584.4 °C`. Правка: декодировать только когда
`_tgt_type == 16` **и** значение не является id объекта типа 20.
**Три места, где это чинилось (питфолл «две точки входа»):**
1. `dump_step` (ветка тип 9 в шаге сценария);
2. секция `relay_commands` (свой обход `Z`, своя копия логики);
3. `_build_type9_line` в энкодере — читает тело **через `_action9_in`**, а не с плоского узла.
#### Устранение дубля id `8817`
`8817` — единственный тип 9, который лежит **и** в сценарии (шагом), **и** объектом в секции.
Оба эмитили строку → validation: `Duplicate ID 8817`. Плюс тело `set_contour_target` перехватывалось
веткой objcmd (одно имя!) и собиралось как `#Z8817=59,'objcmd 10034 ",,,%0";#h',...`.
Лечение: ключи разведены (`set_contour_target` отсутствует в `_OBJCMD_MASKS`) — конфликт снят.
`_register_action9` возвращает управление, если запись с таким id **уже пришла из YAML-секции**:
шаг ссылается на объект, тело живёт в секции (одна строка на один id).
### 26.5. 🔴 ПИТФОЛЛ 92 — форма согласована ≠ в код внесена
@@ -3719,3 +3754,64 @@ Alex третий раз видел `args` у `objcmd` при том, что ф
---
## 27. ✅ Круг 46 (2026-09-18) — `set_contour_target`, Кельвин, дубль `8817`
**HEAD после круга: `75f46f3`.** Круг **9/9 зелёный, 759 → 759**, YAML валиден.
### 27.1. Что сделано
1. **`set_contour_target` (тип 9) отделён от `set_contour_temp` (objcmd тип 59)** — два разных
действия, два имени, ключи не пересекаются.
2. **Кельвин только при цели типа 16** и только если значение не id объекта типа 20.
3. **Секция `relay_commands` получила ключ действия** — читается так же, как шаг сценария.
4. **`_build_type9_line` читает тело через `_action9_in`**, а не с плоского узла.
5. **Дубль id `8817` устранён**`_register_action9` уступает, если id уже пришёл из секции.
### 27.2. Итоговые формы (проверены в артефакте)
```yaml
relay_commands:
- id: 8470
activate_mode: # значение = id режима, НЕ температура
descr: Активировать режим отопления Режим отопления для Контур ГВС
target: 8669
value: '8574'
- id: 8817
set_contour_target: # тип 9: уставка ЧИСЛОМ
descr: Установить целевую температуру 5.2 для контура Спальня
target: 10034
value: 5.2
```
```yaml
- id: 10379
set_contour_temp: # тип 59 objcmd: значение ИСТОЧНИКОМ
target: 8669
value: {id: 9146, type: var}
- id: 10381
set_contour_temp:
target: 9339
value: {id: 10380, type: objstate, object: 9841}
```
### 27.3. 🔴 ПИТФОЛЛ 96 — одно имя на два разных действия = схлопывание текстов команд
Оба действия звались `set_contour_temp`. Ветка objcmd перехватывала тело типа 9, и `8817`
собирался как `#Z8817=59,'objcmd 10034 ",,,%0";#h',5.2,0,1` вместо `#Z8817=9,'...',10034,'2782'`.
**Признак той же природы, что питфоллы 92–95:** форма живёт в двух словарях — сверять пересечение
имён ключей при каждом переименовании (`_ACTION9_KEYS``_OBJCMD_MASKS`).
### 27.4. 🔴 ПИТФОЛЛ 97 — артефакт-`.yml` в репо ≠ свежий вывод
`zont_config/*.yml` в репо — это **выход прошлого прогона**, он же вход для круга. Пока не
перегенерён, он показывает старую форму (тут: плоскую секцию `relay_commands` и Кельвин в `8470`).
**Порядок приёмки:** гнать декодер в ЦЕЛЕВОЙ файл (`> zont_config/<имя>.yml`), затем открывать
глазами. `test_roundtrip.py` пишет в temp и целевой артефакт не обновляет.
### 27.5. Открыто на после круга 46
- 5 `objcmd`-орфанов (`8669`, `8382`, `11907` и др.) — форма не согласована;
- поле 4 = `2` у `expr` (`10077``10085`) — имени нет;
- авто-id (`_resolve_id` + аллокатор `max+1`, 17 точек) — план есть, код не написан;
- push `75f46f3` в Gitea — по команде.