Files
obsidian-vault/family/tech/kitchen-hood-fan-template.md
T

229 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "🍳 Вытяжка кухни — смена домена light → fan (`fan.kitchen_hood`, 3 скорости)"
aliases:
- kitchen hood
- kitchen_hood
- вытяжка домен
- вытяжка категория свет
- TS0003 fan
- hood light to fan
- fan.kitchen_hood
- kitchen-hood-domain-conversion
- kitchen-hood-fan-template
created: '2026-09-16'
updated: '2026-09-16 — ✅ ВЫПОЛНЕНО: `fan.kitchen_hood` создан Template-хелпером поверх трёх Zigbee-реле ZHA, свет скрыт, проверено живым прогоном 33/66/100 %'
type: tech
namespace: family
status: 🟢 РАБОТАЕТ. `fan.kitchen_hood` (3 скорости, `speed_count: 3`) поверх `light.kitchen_hood_light[,_2,_3]`. Три света скрыты (`hidden_by: user`). Проверено фактом 2026-09-16. ⚠️ Порядок скоростей ждёт физической проверки — §6.
tags:
- family
- tech
- smarthome
- home-assistant
- t610
- haos
- zigbee
- zha
- template
related:
- '[[family/how-to/home-automation]]'
- '[[family/how-to/ha-automations]]'
- '[[family/tech/zigbee-t610-z2m-i-zha]]'
- '[[family/tech/ha-registry-operations]]'
- '[[family/documents/home-automation-wishlist]]'
---
# 🍳 Вытяжка кухни — смена домена (light → fan)
> **Задача Alex (2026-09-16):** «можно всё-таки кухонную вытяжку перевести из категории свет в другую?» → ответ: прямого способа нет; сделан `fan.kitchen_hood` Template-хелпером поверх трёх реле, свет спрятан.
>
> **Единственная дока по вытяжке.** Раньше было две (`kitchen-hood-domain-conversion` — исследование, `kitchen-hood-fan-template` — реализация) — сведены сюда 2026-09-16. Оба имени оставлены в `aliases`.
## 1. Ответ на исходный вопрос: «никак нельзя»
**Прямого способа сменить домен `light.` → `switch.`/`fan.` у существующей сущности в HA НЕТ.** Проверено по всем трём путям:
| Путь | Результат |
|---|---|
| **UI «Показать как»** (`device_class`) | ❌ Домена не меняет. Для `light` вообще не применимо |
| **Реестр сущностей** (`config/entity_registry/update` + `new_entity_id`) | ❌ Домен менять нельзя, только имя внутри домена. ⚠️ Питфолл 4 в [[family/tech/zigbee-t610-z2m-i-zha]]: «Переименование `light.``switch.` запрещено HA» |
| **`switch_as_x`** (офиц. хелпер «Change device type of a switch») | ❌ **Источник — только `switch`.** Конвертирует в Light/Cover/Fan/Lock/Siren/Valve, но `light` на вход НЕ принимает. Для ZHA-вытяжки бесполезен |
| **Кастомный quirk в `zhaquirks`** | ⚠️ Технически возможно (подменить Light-cluster на Switch), но ломается при каждом обновлении HA + переименование сущностей рвёт все ссылки. Отвергнуто |
| **`homeassistant: customize:`** (device_class/icon override) | ❌ Меняет только атрибуты, **не домен**. `light.` останется `light.` |
> 📄 `switch_as_x` — https://www.home-assistant.io/integrations/switch_as_x/
> Ключевая цитата доки: «lets you convert any Home Assistant **switch** into a Home Assistant Light, Cover, Fan, Lock, Siren, or Valve».
**Работает только обход:** Template-хелпер создаёт **новую** сущность рядом, оригинальные прячутся.
> ⚠️ **Почему Template работает там, где `switch_as_x` пасует:** у Template-сущности блок `action:` может звать **любой** сервис (`light.turn_on`), тогда как `switch_as_x` жёстко ограничен источником-`switch`. Это и есть обход ограничения домена.
### Варианты, которые рассматривались
| # | Что | Итог |
|---|---|---|
| **A** | Template `fan` поверх **одного** `light_2` | промежуточный; отвергнут — не даёт 3 скоростей |
| **B** | Template `switch` (без `percentage`) | если скорость не нужна, нужен просто «не свет» |
| **C** | Три `fan`/`switch` + автоматизация взаимоблокировки / `input_select` | ⭐ **не понадобился**`set_percentage` с `choose` дал то же самое в одной сущности |
## 2. Железо и что отдаёт ZHA
**Устройство:** `kitchen_hood` · IEEE `a4:c1:38:07:b6:4c:7f:d4` · `_TZ3000_odzoiovu` · **TS0003** (3-gang реле) · Router · зона `kitchen` · device_id `200ea4fb25daaa907279045e47a330b5`
**ZHA отдаёт реле как `light`, не `switch`:**
| Сущность | Роль | Состояние до работ |
|---|---|---|
| `light.kitchen_hood_light` | скорость 1 (33 %) | `on` |
| `light.kitchen_hood_light_2` | скорость 2 (66 %) | `off` |
| `light.kitchen_hood_light_3` | скорость 3 (100 %) | `off` |
Все три: `supported_color_modes: ["onoff"]`, `supported_features: 8`, платформа `zha`.
> 🔑 **`supported_features: 8` + `supported_color_modes: ["onoff"]` = чистое реле без яркости.** Именно поэтому HA-логика «это лампа» здесь ложная, а переклассификация в `fan` осмысленна.
**Прочие сущности того же устройства** (не тронуты): `select.kitchen_hood_indicator_mode` (`LightWhenOn`), `select.kitchen_hood_power_outage_memory` (`Off`), `sensor.kitchen_hood_power` / `_voltage` / `_current` / `_energy` (все `0.0`), `button.kitchen_hood_identify`, `update.kitchen_hood_firmware`, `sensor.kitchen_hood_lqi` / `_rssi`.
> 🔴 **`sensor.kitchen_hood_lqi` / `_rssi` → HTTP **404** через `/api/states`.** Это **норма**: `disabled_by: integration` — сущности в реестре есть, в runtime их нет. **Не считать поломкой.**
> 🔑 **Ключевое для понимания:** TS0003 — это **три независимых реле**, а «3 скорости вытяжки» на железе = три провода, из которых активен ровно один. Поэтому HA изначально показала их как три света, а не как одну вентиляционную сущность. Один `fan` с процентами склеивает их логически.
## 3. Что сделано (2026-09-16)
### 3.1. Бэкап
```
/config/configuration.yaml.bak-fanhood-20260916-081926 (30108 байт)
```
### 3.2. Новый блок `template:` в `/config/configuration.yaml`
Добавлен **16-м** блоком `template:` (после `fan_3`), перед `- cover:`. `speed_count: 3` → шаг 33 % в UI.
```yaml
- fan:
- name: Kitchen hood
unique_id: kitchen_hood_fan
default_entity_id: fan.kitchen_hood
speed_count: 3
state: >
{{ is_state('light.kitchen_hood_light','on')
or is_state('light.kitchen_hood_light_2','on')
or is_state('light.kitchen_hood_light_3','on') }}
percentage: >
{% if is_state('light.kitchen_hood_light_3','on') %}100
{% elif is_state('light.kitchen_hood_light_2','on') %}66
{% elif is_state('light.kitchen_hood_light','on') %}33
{% else %}0
{% endif %}
turn_on:
- action: light.turn_on
target:
entity_id: light.kitchen_hood_light
turn_off:
- action: light.turn_off
target:
entity_id:
- light.kitchen_hood_light
- light.kitchen_hood_light_2
- light.kitchen_hood_light_3
set_percentage:
- action: light.turn_off
target:
entity_id:
- light.kitchen_hood_light
- light.kitchen_hood_light_2
- light.kitchen_hood_light_3
- choose:
- conditions:
- condition: template
value_template: "{{ percentage | int(0) > 0 and percentage | int(0) <= 33 }}"
sequence:
- action: light.turn_on
target:
entity_id: light.kitchen_hood_light
- conditions:
- condition: template
value_template: "{{ percentage | int(0) > 33 and percentage | int(0) <= 66 }}"
sequence:
- action: light.turn_on
target:
entity_id: light.kitchen_hood_light_2
- conditions:
- condition: template
value_template: "{{ percentage | int(0) > 66 and percentage | int(0) <= 100 }}"
sequence:
- action: light.turn_on
target:
entity_id: light.kitchen_hood_light_3
```
**Логика:** `set_percentage` сначала гасит **все три** реле, затем зажигает одно нужное → **взаимоисключение гарантировано**, состояние «две скорости одновременно» невозможно by design.
> 🔴 **ИСПРАВЛЕНО 2026-09-16 (было ошибочно в первой версии доки):** ранняя версия утверждала, что «Template-fan с `percentage` не даст настоящую скорость — он включит одно реле». **Факт опроверг:** один Template-fan с `set_percentage` + `choose` **даёт полноценные 3 скорости** — 33/66/100 % выбирают нужное реле, `percentage` читается обратно из состояния. Взаимоблокировку обеспечивает `set_percentage` (гасит все три перед включением), отдельная автоматизация и `input_select` **не нужны**. Проверено живым прогоном — §4.
>
> TS0003 = **3 независимых реле**; «скорость 1/2/3» = три контакта, включаемых **по одному**. Именно поэтому один `fan` с процентами корректно склеивает их логически.
### 3.3. Скрытие света
Три сущности скрыты через WS `config/entity_registry/update` с `hidden_by: "user"`.
Скрипт: `~/tmp-t610/hood_hide.py` (возврат — тот же скрипт с `--unhide`).
## 4. ✅ Проверка на живом железе
| Шаг | `fan.kitchen_hood` | light_1 | light_2 | light_3 |
|---|---|---|---|---|
| baseline | `off / 0` | off | off | off |
| `set_percentage 33` | `on / 33` | **on** | off | off |
| `set_percentage 66` | `on / 66` | off | **on** | off |
| `set_percentage 100` | `on / 100` | off | off | **on** |
| `turn_off` | `off / 0` | off | off | off |
`fan.kitchen_hood`: `supported_features: 49` = TURN_ON | TURN_OFF | SET_SPEED ✅
> ️ `speed_count` **не отдаётся** как атрибут состояния — HA его не публикует. Шаги ползунка считаются из `percentage_step`. Это норма, не дефект.
## 5. Питфоллы
| # | Питфолл | Обход |
|---|---|---|
| 1 | **`switch_as_x` не принимает `light`** | Источник только `switch`. Для ZHA-light бесполезен — нужен Template |
| 2 | **Домен сущности сменить нельзя** | Только Template-хелпер рядом + скрыть оригинал |
| 3 | **`!include` ломает `yaml.safe_load`** при локальной проверке | Заглушка: `L.add_multi_constructor('!', ...)` — иначе проверка конфига локально невозможна |
| 4 | 🔴 **`check_config` через сервис отдаёт `[]`** | Это **не** ошибка — сервис не возвращает тело. Проверять `GET /api/config``.state` или `/api/template` |
| 5 | **`_1`/`_2`/`_3` ≠ порядок скоростей автоматически** | ZHA нумерует по endpoint'ам, не по физической скорости. ⚠️ **Требует физической проверки** — см. §6 |
| 6 | **Template `turn_on` без аргумента** | `fan.turn_on` без `percentage` → скорость 1 (33 %). Задано явно |
| 7 | 🔴 **Правка `configuration.yaml` требует `restart` HA Core** | `automation reload` тут **не** поможет — новый template-блок не подхватится |
| 8 | 🔴 **REST `POST` без `-H "Content-Type: application/json"` → пустой ответ** | Всегда ставить заголовок |
| 9 | 🔴 **Заголовок авторизации рвётся маскировщиком Hermes** в скриптах | Собирать по частям либо Python + `urllib` (пример — `hood_scan.py`, `hood_hide.py`) |
| 10 | **`sensor.kitchen_hood_lqi` / `_rssi` → 404 в `/api/states`** | `disabled_by: integration` — норма, не поломка |
## 6. ⚠️ ОТКРЫТО — требует проверки Alex
1. 🔴 **Порядок скоростей не подтверждён физически.** Принято как `_1`=33 / `_2`=66 / `_3`=100, но какое **реле** = какая **скорость** — не проверялось. Нужно встать у вытяжки: поставить 33 % и 100 %, убедиться что низкая/высокая. **Если перепутано — правка трёх строк** в `percentage` и `set_percentage`.
2. ⚠️ **`light.kitchen_hood_light` мог быть лампой подсветки, а не скоростью.** До работ он был `on` (горел), после рестарта HA стал `off`. Если это **лампа подсветки вытяжки** — вынести отдельно, фан её не должен гасить. Уточнить у Alex.
> 📌 **Проверка для будущей сессии (одной командой):** поставить `fan.set_percentage` на 33 и на 100 и сравнить, какое реле зажглось и **что физически слышно**. Маппинг в коде — три строки в `percentage` и три ветки `choose` в `set_percentage`.
## 6.1. Роадмап вентиляции
[[family/documents/home-automation-wishlist]] §2 п.1 ожидает **«Kitchen Hood»** как конечный узел алгоритма вентиляции по CO₂ (Node-RED: `Demand Aggregator → Intake Allocation → Discretization → Damper Outputs → Exhaust Arbitration → Fans → Kitchen Hood`). Ранее узел был мёртв вместе с контуром AT2 — теперь у вытяжки есть **рабочая сущность `fan.kitchen_hood`**, на которую можно вешать автоматику. Ждёт решения по slave 10 (AT2 снят Alex'ом).
## 7. Не тронуто
- **`fan.fan_3` «Вытяжка Кухня»** — существовавшая сущность (`unique_id: fan_3`, `default_entity_id: fan.fan_3`), источник — `switch.fan_3_low/medium/high` (slave 10, AT2/modbus). Эти свитчи **закомментированы** в `configuration.yaml` (строки 60–84) — контур AT2 отключён Alex'ом. Ссылается на несуществующий `script.set_fan_3_speed`. **Мёртвая, но оставлена как есть** по выбору Alex (вариант «Новый»).
## 8. Артефакты
| Файл | Назначение |
|---|---|
| `~/tmp-t610/configuration.yaml.current` | рабочая копия конфига (с новым блоком) |
| `~/tmp-t610/hood_scan.py` | read-only скан: devices + entities + device_class + show_as + area + states |
| `~/tmp-t610/hood_hide.py` | скрыть/показать три `light.*` (`--unhide`) |
## Связанные
- [[family/how-to/home-automation]] — топология, t610, Zigbee, команды, питфоллы
- [[family/tech/zigbee-t610-z2m-i-zha]] — ZHA, реестры, переименование, питфолл «домен менять нельзя»
- [[family/how-to/ha-automations]] — автоматизации, справочник