[2026-09-16] eagle: family/how-to/home-automation.md family/tech/kitchen-hood-fan-template.md
This commit is contained in:
@@ -455,7 +455,7 @@ ssh -i ~/.ssh/id_rsa root@192.168.2.176 \
|
|||||||
| `office_table_light_switch` | TS0002 | выключатель стола кабинета | Кабинет |
|
| `office_table_light_switch` | TS0002 | выключатель стола кабинета | Кабинет |
|
||||||
| `smart_light_office` | TS0012 | свет кабинета (left/right) | Кабинет |
|
| `smart_light_office` | TS0012 | свет кабинета (left/right) | Кабинет |
|
||||||
| `light_stairs` | TS0002 | подсветка лестницы | Лестница |
|
| `light_stairs` | TS0002 | подсветка лестницы | Лестница |
|
||||||
| `kitchen_hood` | TS0003 | вытяжка кухни (3 скорости) — ZHA отдаёт как **3 × `light.*`** ⚠️ | Кухня |
|
| `kitchen_hood` | TS0003 | вытяжка кухни (3 скорости) → 🌀 **`fan.kitchen_hood`** (Template, `speed_count: 3`), свет скрыт. Док: [[family/tech/kitchen-hood-fan-template]] | Кухня |
|
||||||
| `sauna` | TS011F | реле сауны | — |
|
| `sauna` | TS011F | реле сауны | — |
|
||||||
| `heating_cable_plug` | TS011F | розетка греющего кабеля ввода воды | Котельная |
|
| `heating_cable_plug` | TS011F | розетка греющего кабеля ввода воды | Котельная |
|
||||||
| `boiler_controller_power` | TS011F | питание контроллера котла | Котельная |
|
| `boiler_controller_power` | TS011F | питание контроллера котла | Котельная |
|
||||||
|
|||||||
@@ -0,0 +1,228 @@
|
|||||||
|
---
|
||||||
|
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]] — автоматизации, справочник
|
||||||
Reference in New Issue
Block a user