mirror of
https://github.com/anklimov/lighthub
synced 2026-10-28 19:25:01 +00:00
docs: audit references and examples against source code
Cross-checked all channel types, suffixes, commands, JSON config formats, HTTP/MQTT API examples and driver docs with the actual code; fixed the discrepancies (channel numbers 0..23, real command set, real suffix handling, CAN 50 kbit/s, DRY/Freeze sprinkler semantics, AC subitems, multivent zones, Mercury/Motor/Counter configs, etc.)
This commit is contained in:
@@ -0,0 +1,896 @@
|
||||
# Исчерпывающее руководство по настройке системы полива в Home Assistant
|
||||
|
||||
Это руководство шаг за шагом проведёт вас через установку и настройку многоканальной системы полива на базе [lighthub](https://github.com/anklimov/lighthub), интегрированной с Home Assistant через MQTT. В результате вы получите красивую и функциональную панель управления, которая включает:
|
||||
|
||||
- визуализацию уровня воды в баке (пусто / наполовину / полный),
|
||||
- индикацию работы водопровода, дренажного и основного насосов,
|
||||
- управление тремя зонами полива с заданием времени и прогресс-баром,
|
||||
- интерактивную корректировку выполненного времени через проценты,
|
||||
- историю ключевых параметров по клику на иконки.
|
||||
|
||||
---
|
||||
|
||||
## 1. Предварительные требования
|
||||
|
||||
- Установленный и настроенный [Home Assistant](https://www.home-assistant.io/) (любая версия, поддерживающая Lovelace).
|
||||
- Настроенный MQTT-брокер (например, Mosquitto) и интеграция MQTT в Home Assistant.
|
||||
- [HACS](https://hacs.xyz/) (Home Assistant Community Store) – для установки кастомных карт.
|
||||
|
||||
> **Примечание:** Конфигурация MQTT‑датчиков и устройств уже готова и будет приведена ниже. Предполагается, что ваш контроллер lighthub уже отправляет данные в соответствующие топики.
|
||||
|
||||
---
|
||||
|
||||
## 2. Установка кастомных карт через HACS
|
||||
|
||||
Для корректной работы панели необходимо установить следующие карты. Все они доступны в HACS.
|
||||
|
||||
1. Откройте **HACS** → **Frontend** → **Explore & Download Repositories**.
|
||||
2. Поочерёдно найдите и установите каждую из перечисленных ниже карт.
|
||||
3. После установки **обновите страницу** браузера (или перезагрузите интерфейс Home Assistant).
|
||||
|
||||
### Список обязательных карт
|
||||
|
||||
| Название | Репозиторий (для ручного добавления, если не находится) | Назначение |
|
||||
|------------------------------|----------------------------------------------------------|------------|
|
||||
| **Vertical Stack In Card** | `ofekashery/vertical-stack-in-card` | Объединение нескольких карточек в одну с общим фоном |
|
||||
| **Button Card** | `custom-cards/button-card` | Гибкая карточка с динамическими иконками, анимацией и состояниями |
|
||||
| **Bar Card** | `spacerokk/bar-card` (активный форк) | Прогресс-бар для отображения выполнения полива |
|
||||
| **Mushroom Cards** | `piitaya/lovelace-mushroom` | Компактные и стильные карточки для датчиков и переключателей |
|
||||
| **Slider Entity Row** | `thomasloven/lovelace-slider-entity-row` | Ползунок для настройки времени в more‑info окнах (не обязателен, но используется в стандартном окне `number`) |
|
||||
| **Card Mod** | `thomasloven/lovelace-card-mod` | Позволяет добавлять произвольные CSS‑стили к карточкам |
|
||||
|
||||
> **Важно:** Если какая‑то карта не отображается в HACS, добавьте её вручную через **HACS → ⋮ → Пользовательские репозитории**. В поле URL вставьте ссылку на GitHub‑репозиторий, категорию выберите **Lovelace**.
|
||||
|
||||
---
|
||||
|
||||
## 3. Настройка MQTT‑сущностей
|
||||
|
||||
Вся логика обмена данными с контроллером lighthub заложена в MQTT‑конфигурации. Скопируйте приведённый ниже блок в файл `configuration.yaml` (или в отдельный файл, подключённый через `mqtt: !include mqtt.yaml`).
|
||||
|
||||
```yaml
|
||||
# Пример размещения в configuration.yaml
|
||||
mqtt:
|
||||
switch:
|
||||
- name: "Полив"
|
||||
state_topic: "edem/s_out/sprinkler/cmd"
|
||||
command_topic: "edem/air/sprinkler/cmd"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив север"
|
||||
state_topic: "edem/s_out/sprinkler/nord/cmd"
|
||||
command_topic: "edem/air/sprinkler/nord/cmd"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив юг"
|
||||
state_topic: "edem/s_out/sprinkler/south/cmd"
|
||||
command_topic: "edem/air/sprinkler/south/cmd"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив капельный"
|
||||
state_topic: "edem/s_out/sprinkler/trees/cmd"
|
||||
command_topic: "edem/air/sprinkler/trees/cmd"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив розетки"
|
||||
state_topic: "edem/s_out/sprinkler/outlets/cmd"
|
||||
command_topic: "edem/air/sprinkler/outlets/cmd"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
button:
|
||||
- name: "Полив сброс"
|
||||
command_topic: "edem/air/sprinkler/cmd"
|
||||
payload_press: "RESET"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив блокировка"
|
||||
command_topic: "edem/air/sprinkler/cmd"
|
||||
payload_press: "FREEZE"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив разблокировка"
|
||||
command_topic: "edem/air/sprinkler/cmd"
|
||||
payload_press: "UNFREEZE"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив разрешить"
|
||||
command_topic: "edem/air/sprinkler/cmd"
|
||||
payload_press: "ENABLE"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив запретить"
|
||||
command_topic: "edem/air/sprinkler/cmd"
|
||||
payload_press: "DISABLE"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив осушение бака"
|
||||
command_topic: "edem/air/sprinkler/cmd"
|
||||
payload_press: "DRY"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
number:
|
||||
- name: "Полив юг"
|
||||
state_topic: "edem/s_out/sprinkler/south/set"
|
||||
command_topic: "edem/air/sprinkler/south/set"
|
||||
min: 0
|
||||
max: 6000
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив север"
|
||||
state_topic: "edem/s_out/sprinkler/nord/set"
|
||||
command_topic: "edem/air/sprinkler/nord/set"
|
||||
min: 0
|
||||
max: 6000
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив капельный"
|
||||
state_topic: "edem/s_out/sprinkler/trees/set"
|
||||
command_topic: "edem/air/sprinkler/trees/set"
|
||||
min: 0
|
||||
max: 6000
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив юг выполнено"
|
||||
state_topic: "edem/s_out/sprinkler/south/val"
|
||||
command_topic: "edem/air/sprinkler/south/val"
|
||||
min: 0
|
||||
max: 60000
|
||||
mode: slider
|
||||
icon: "mdi:timer-sand"
|
||||
unit_of_measurement: 'sec'
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив север выполнено"
|
||||
state_topic: "edem/s_out/sprinkler/nord/val"
|
||||
command_topic: "edem/air/sprinkler/nord/val"
|
||||
min: 0
|
||||
max: 60000
|
||||
mode: slider
|
||||
icon: "mdi:timer-sand"
|
||||
unit_of_measurement: 'sec'
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив капельный выполнено"
|
||||
state_topic: "edem/s_out/sprinkler/trees/val"
|
||||
command_topic: "edem/air/sprinkler/trees/val"
|
||||
min: 0
|
||||
max: 60000
|
||||
mode: slider
|
||||
icon: "mdi:timer-sand"
|
||||
unit_of_measurement: 'sec'
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
sensor:
|
||||
- name: "Полив бак Макс"
|
||||
state_topic: "edem/s_out/sprinkler/$wMax"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив бак Мin"
|
||||
state_topic: "edem/s_out/sprinkler/$wMin"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив водопровод"
|
||||
state_topic: "edem/s_out/sprinkler/$rVIN"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив дренаж вкл"
|
||||
state_topic: "edem/s_out/sprinkler/$rDren"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив дренаж качает"
|
||||
state_topic: "edem/s_out/sprinkler/$fbDren"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив насос вкл"
|
||||
state_topic: "edem/s_out/sprinkler/$rPump"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив насос качает"
|
||||
state_topic: "edem/s_out/sprinkler/$fbPump"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив состояние"
|
||||
state_topic: "edem/s_out/sprinkler/$state"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив ошибка"
|
||||
state_topic: "edem/s_out/sprinkler/$fault"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Поливаем юг"
|
||||
state_topic: "edem/s_out/sprinkler/south/$state"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Поливаем север"
|
||||
state_topic: "edem/s_out/sprinkler/nord/$state"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Поливаем капельно"
|
||||
state_topic: "edem/s_out/sprinkler/trees/$state"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив розетка статус"
|
||||
state_topic: "edem/s_out/sprinkler/outlets/$state"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив блокировки"
|
||||
state_topic: "edem/s_out/sprinkler/ctrl"
|
||||
availability_topic: "edem/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
```
|
||||
|
||||
> **Пояснение:**
|
||||
> - `switch` – переключатели для запуска/остановки зон и общий переключатель.
|
||||
> - `button` – кнопки для сброса, блокировки, разрешения и осушения бака.
|
||||
> - `number` – задание времени полива (уставки) и выполненное время (с возможностью ручной корректировки).
|
||||
> - `sensor` – датчики состояния поплавков (`$wMax`, `$wMin`), водопровода, насосов, статуса полива, ошибок и т.д.
|
||||
> - **Важно (switch «Полив»):** общий переключатель читает `.../sprinkler/cmd`; в режиме осушения (DRY) контроллер публикует в этот топик значение `DRY` (а не ON/OFF), поэтому тумблер HA может показать нестандартное значение.
|
||||
> - **Важно (sensor «Полив состояние»):** датчик по `$state` принимает значения `OFF`, `DREN_ON`, `DREN_OPERATE`, `DREN_EMPTY`, `VIN`, `FULL`, `DRYING`, `FAULT_VIN`, `FAULT_DREN`, `UNKNOWN`; текущее состояние гарантированно публикуется при старте контроллера.
|
||||
|
||||
После добавления конфигурации **перезагрузите YAML** (Настройки → Сервер → Перезагрузить конфигурацию YAML).
|
||||
|
||||
---
|
||||
|
||||
## 4. Настройка template‑сущностей
|
||||
|
||||
Для работы панели необходимы два типа вычислимых объектов:
|
||||
|
||||
- **Уровень бака в процентах** (на основе поплавков).
|
||||
- **Прогресс полива в процентах** для каждой зоны (с возможностью двусторонней синхронизации: проценты ↔ секунды).
|
||||
|
||||
Добавьте следующий блок в `configuration.yaml` (если у вас уже есть секция `template:`, объедините её с этим содержимым, сохранив правильные отступы):
|
||||
|
||||
```yaml
|
||||
template:
|
||||
# Сенсор уровня бака
|
||||
- sensor:
|
||||
- name: "Полив бак уровень"
|
||||
state: >
|
||||
{% if states('sensor.poliv_bak_maks') == 'ON' %}
|
||||
100
|
||||
{% elif states('sensor.poliv_bak_min') == 'ON' %}
|
||||
50
|
||||
{% else %}
|
||||
0
|
||||
{% endif %}
|
||||
|
||||
# Числовые шаблоны прогресса (проценты)
|
||||
- number:
|
||||
- name: "Полив юг прогресс"
|
||||
state: >
|
||||
{% set zadanie = states('number.poliv_iug') | float(0) %}
|
||||
{% set vypolneno = states('number.poliv_iug_vypolneno') | float(0) %}
|
||||
{{ ((vypolneno / zadanie * 100) | round(0)) if zadanie > 0 else 0 }}
|
||||
set_value:
|
||||
- service: number.set_value
|
||||
target:
|
||||
entity_id: number.poliv_iug_vypolneno
|
||||
data:
|
||||
value: >
|
||||
{% set zadanie = states('number.poliv_iug') | float(0) %}
|
||||
{{ ((value | float(0)) * zadanie / 100) | round(0) }}
|
||||
min: 0
|
||||
max: 100
|
||||
step: 1
|
||||
unit_of_measurement: "%"
|
||||
icon: mdi:progress-clock
|
||||
|
||||
- name: "Полив север прогресс"
|
||||
state: >
|
||||
{% set zadanie = states('number.poliv_sever') | float(0) %}
|
||||
{% set vypolneno = states('number.poliv_sever_vypolneno') | float(0) %}
|
||||
{{ ((vypolneno / zadanie * 100) | round(0)) if zadanie > 0 else 0 }}
|
||||
set_value:
|
||||
- service: number.set_value
|
||||
target:
|
||||
entity_id: number.poliv_sever_vypolneno
|
||||
data:
|
||||
value: >
|
||||
{% set zadanie = states('number.poliv_sever') | float(0) %}
|
||||
{{ ((value | float(0)) * zadanie / 100) | round(0) }}
|
||||
min: 0
|
||||
max: 100
|
||||
step: 1
|
||||
unit_of_measurement: "%"
|
||||
icon: mdi:progress-clock
|
||||
|
||||
- name: "Полив капельный прогресс"
|
||||
state: >
|
||||
{% set zadanie = states('number.poliv_kapelnyi') | float(0) %}
|
||||
{% set vypolneno = states('number.poliv_kapelnyi_vypolneno') | float(0) %}
|
||||
{{ ((vypolneno / zadanie * 100) | round(0)) if zadanie > 0 else 0 }}
|
||||
set_value:
|
||||
- service: number.set_value
|
||||
target:
|
||||
entity_id: number.poliv_kapelnyi_vypolneno
|
||||
data:
|
||||
value: >
|
||||
{% set zadanie = states('number.poliv_kapelnyi') | float(0) %}
|
||||
{{ ((value | float(0)) * zadanie / 100) | round(0) }}
|
||||
min: 0
|
||||
max: 100
|
||||
step: 1
|
||||
unit_of_measurement: "%"
|
||||
icon: mdi:progress-clock
|
||||
```
|
||||
|
||||
**Как это работает:**
|
||||
- `state` динамически вычисляет процент выполнения на основе заданного времени (`number.poliv_...`) и выполненного (`number.poliv_..._vypolneno`).
|
||||
- `set_value` при ручном изменении процента (через ползунок или ввод) пересчитывает его в секунды и отправляет команду в контроллер через `number.set_value` для выполненного времени. Таким образом, можно вручную скорректировать прогресс, и значение сразу уйдёт в MQTT.
|
||||
- Бак определяется по поплавкам: если активен `$wMax` → 100%, если только `$wMin` → 50%, иначе 0%.
|
||||
|
||||
Снова **перезагрузите YAML‑конфигурацию**.
|
||||
|
||||
---
|
||||
|
||||
## 5. Создание панели управления (Dashboard)
|
||||
|
||||
### 5.1. Создание новой панели
|
||||
|
||||
1. Перейдите в **Настройки** → **Панели** (Dashboards).
|
||||
2. Нажмите **Создать панель** (Add Dashboard).
|
||||
- Название: `💧 Полив`
|
||||
- Режим панели: **Панель (одна карточка)** – *Panel (1 card)*.
|
||||
3. Нажмите **Создать**.
|
||||
|
||||
### 5.2. Переход в редактор YAML
|
||||
|
||||
Сразу после создания панель откроется в графическом редакторе.
|
||||
Нажмите на три точки **⋮** в правом верхнем углу и выберите **Редактор YAML**.
|
||||
|
||||
### 5.3. Вставка финального YAML
|
||||
|
||||
Удалите всё содержимое (обычно там `type: panel\npath: ""\ncards: []`) и вставьте следующий код:
|
||||
|
||||
```yaml
|
||||
views:
|
||||
- type: panel
|
||||
path: ''
|
||||
cards:
|
||||
- type: custom:vertical-stack-in-card
|
||||
title: 💧 Система полива
|
||||
cards:
|
||||
# ── Общее состояние ──
|
||||
- type: horizontal-stack
|
||||
cards:
|
||||
- type: custom:mushroom-entity-card
|
||||
entity: sensor.poliv_sostoianie
|
||||
name: Статус
|
||||
primary_info: state
|
||||
icon: mdi:state-machine
|
||||
- type: custom:mushroom-entity-card
|
||||
entity: sensor.poliv_blokirovki
|
||||
name: Режим
|
||||
primary_info: state
|
||||
icon: mdi:lock
|
||||
|
||||
# ── Бак ──
|
||||
- type: custom:mushroom-template-card
|
||||
primary: Бак воды
|
||||
secondary: |
|
||||
{% set lvl = states('sensor.poliv_bak_uroven') %}
|
||||
{% if lvl == '100' %} Полный
|
||||
{% elif lvl == '50' %} Наполовину
|
||||
{% else %} Пустой {% endif %}
|
||||
icon: mdi:battery
|
||||
icon_color: |
|
||||
{% set lvl = states('sensor.poliv_bak_uroven') %}
|
||||
{% if lvl == '100' %} green
|
||||
{% elif lvl == '50' %} orange
|
||||
{% else %} grey {% endif %}
|
||||
tap_action:
|
||||
action: more-info
|
||||
entity: sensor.poliv_bak_uroven
|
||||
card_mod:
|
||||
style: |
|
||||
ha-card {
|
||||
--mush-icon-size: 24px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
- type: divider
|
||||
|
||||
# ── Водопровод ──
|
||||
- type: custom:mushroom-template-card
|
||||
primary: Водопровод
|
||||
secondary: |
|
||||
{% if states('sensor.poliv_vodoprovod') == 'ON' %} Вкл
|
||||
{% else %} Выкл {% endif %}
|
||||
icon: mdi:water-pump
|
||||
icon_color: |
|
||||
{% if states('sensor.poliv_vodoprovod') == 'ON' %} blue
|
||||
{% else %} grey {% endif %}
|
||||
tap_action:
|
||||
action: more-info
|
||||
entity: sensor.poliv_vodoprovod
|
||||
card_mod:
|
||||
style: |
|
||||
ha-card {
|
||||
--mush-icon-size: 24px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
# ── Насосы ──
|
||||
- type: horizontal-stack
|
||||
cards:
|
||||
- type: custom:mushroom-template-card
|
||||
primary: Дренаж
|
||||
secondary: |
|
||||
{% set pwr = states('sensor.poliv_drenazh_vkl') %}
|
||||
{% set pump = states('sensor.poliv_drenazh_kachaet') %}
|
||||
{% if pwr == 'ON' and pump == 'ON' %} Качает
|
||||
{% elif pwr == 'ON' %} Вкл
|
||||
{% else %} Выкл {% endif %}
|
||||
icon: mdi:pump
|
||||
icon_color: |
|
||||
{% set pwr = states('sensor.poliv_drenazh_vkl') %}
|
||||
{% set pump = states('sensor.poliv_drenazh_kachaet') %}
|
||||
{% if pwr == 'ON' and pump == 'ON' %} red
|
||||
{% elif pwr == 'ON' %} green
|
||||
{% else %} grey {% endif %}
|
||||
tap_action:
|
||||
action: more-info
|
||||
entity: sensor.poliv_drenazh_kachaet
|
||||
card_mod:
|
||||
style: |
|
||||
ha-card {
|
||||
--mush-icon-size: 24px;
|
||||
height: 65px;
|
||||
}
|
||||
|
||||
- type: custom:mushroom-template-card
|
||||
primary: Помпа
|
||||
secondary: |
|
||||
{% set pwr = states('sensor.poliv_nasos_vkl') %}
|
||||
{% set pump = states('sensor.poliv_nasos_kachaet') %}
|
||||
{% if pwr == 'ON' and pump == 'ON' %} Качает
|
||||
{% elif pwr == 'ON' %} Вкл
|
||||
{% else %} Выкл {% endif %}
|
||||
icon: mdi:pump
|
||||
icon_color: |
|
||||
{% set pwr = states('sensor.poliv_nasos_vkl') %}
|
||||
{% set pump = states('sensor.poliv_nasos_kachaet') %}
|
||||
{% if pwr == 'ON' and pump == 'ON' %} red
|
||||
{% elif pwr == 'ON' %} green
|
||||
{% else %} grey {% endif %}
|
||||
tap_action:
|
||||
action: more-info
|
||||
entity: sensor.poliv_nasos_kachaet
|
||||
card_mod:
|
||||
style: |
|
||||
ha-card {
|
||||
--mush-icon-size: 24px;
|
||||
height: 65px;
|
||||
}
|
||||
|
||||
- type: divider
|
||||
|
||||
# ── Управление циклом ──
|
||||
- type: entities
|
||||
title: Управление циклом
|
||||
show_header_toggle: false
|
||||
entities:
|
||||
- entity: switch.poliv
|
||||
name: Полив
|
||||
icon: mdi:sprinkler
|
||||
- entity: switch.poliv_rozetki
|
||||
name: Водяная розетка
|
||||
icon: mdi:pipe-valve
|
||||
- entity: button.poliv_sbros
|
||||
name: Запуск всех зон
|
||||
icon: mdi:play
|
||||
- entity: button.poliv_blokirovka
|
||||
name: Заморозить
|
||||
icon: mdi:snowflake
|
||||
- entity: button.poliv_razblokirovka
|
||||
name: Разморозить
|
||||
icon: mdi:snowflake-melt
|
||||
- entity: button.poliv_zapretit
|
||||
name: Запретить полив
|
||||
icon: mdi:cancel
|
||||
- entity: button.poliv_razreshit
|
||||
name: Разрешить полив
|
||||
icon: mdi:check-circle
|
||||
- entity: button.poliv_osushenie_baka
|
||||
name: Осушение бака
|
||||
icon: mdi:hair-dryer
|
||||
|
||||
- type: divider
|
||||
|
||||
# ── Северная зона ──
|
||||
- type: custom:vertical-stack-in-card
|
||||
title: 🌿 Северная зона
|
||||
cards:
|
||||
- type: horizontal-stack
|
||||
cards:
|
||||
# Выключатель
|
||||
- type: custom:mushroom-entity-card
|
||||
entity: switch.poliv_sever
|
||||
show_name: false
|
||||
show_icon: false
|
||||
show_state: false
|
||||
layout: horizontal
|
||||
# Время
|
||||
- type: custom:mushroom-entity-card
|
||||
entity: number.poliv_sever
|
||||
name: Время
|
||||
icon: mdi:timer-edit
|
||||
layout: horizontal
|
||||
card_mod:
|
||||
style: |
|
||||
ha-card {
|
||||
--mush-icon-size: 24px;
|
||||
height: 48px;
|
||||
flex: 1 1 0;
|
||||
}
|
||||
- type: conditional
|
||||
conditions:
|
||||
- entity: number.poliv_sever
|
||||
state_not: '0'
|
||||
card:
|
||||
type: custom:vertical-stack-in-card
|
||||
title: ''
|
||||
cards:
|
||||
- type: horizontal-stack
|
||||
cards:
|
||||
- type: custom:button-card
|
||||
entity: sensor.polivaem_sever
|
||||
show_name: false
|
||||
show_state: false
|
||||
icon: mdi:sprinkler
|
||||
tap_action:
|
||||
action: more-info
|
||||
entity: sensor.polivaem_sever
|
||||
state:
|
||||
- value: 'ON'
|
||||
color: green
|
||||
styles:
|
||||
icon:
|
||||
- animation: pulse 1.5s infinite
|
||||
- value: 'OFF'
|
||||
color: grey
|
||||
styles:
|
||||
icon:
|
||||
- animation: none
|
||||
styles:
|
||||
card:
|
||||
- height: 40px
|
||||
- width: 40px
|
||||
icon:
|
||||
- width: 24px
|
||||
- height: 24px
|
||||
- type: custom:mushroom-template-card
|
||||
primary: ''
|
||||
secondary: >
|
||||
Выполнено: {{ states('number.poliv_sever_vypolneno')
|
||||
}} / {{ states('number.poliv_sever') }} с
|
||||
icon: ''
|
||||
tap_action:
|
||||
action: more-info
|
||||
entity: number.poliv_sever_progress
|
||||
card_mod:
|
||||
style: |
|
||||
ha-card {
|
||||
height: 40px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
- type: custom:bar-card
|
||||
entities:
|
||||
- entity: number.poliv_sever_progress
|
||||
name: Прогресс
|
||||
icon: mdi:progress-clock
|
||||
max: 100
|
||||
severity:
|
||||
- from: 0
|
||||
to: 25
|
||||
color: red
|
||||
- from: 26
|
||||
to: 75
|
||||
color: orange
|
||||
- from: 76
|
||||
to: 100
|
||||
color: green
|
||||
unit_of_measurement: '%'
|
||||
|
||||
- type: divider
|
||||
|
||||
# ── Южная зона ──
|
||||
- type: custom:vertical-stack-in-card
|
||||
title: 🌿 Южная зона
|
||||
cards:
|
||||
- type: horizontal-stack
|
||||
cards:
|
||||
- type: custom:mushroom-entity-card
|
||||
entity: switch.poliv_iug
|
||||
show_name: false
|
||||
show_icon: false
|
||||
show_state: false
|
||||
layout: horizontal
|
||||
- type: custom:mushroom-entity-card
|
||||
entity: number.poliv_iug
|
||||
name: Время
|
||||
icon: mdi:timer-edit
|
||||
layout: horizontal
|
||||
card_mod:
|
||||
style: |
|
||||
ha-card {
|
||||
--mush-icon-size: 24px;
|
||||
height: 48px;
|
||||
flex: 1 1 0;
|
||||
}
|
||||
- type: conditional
|
||||
conditions:
|
||||
- entity: number.poliv_iug
|
||||
state_not: '0'
|
||||
card:
|
||||
type: custom:vertical-stack-in-card
|
||||
title: ''
|
||||
cards:
|
||||
- type: horizontal-stack
|
||||
cards:
|
||||
- type: custom:button-card
|
||||
entity: sensor.polivaem_iug
|
||||
show_name: false
|
||||
show_state: false
|
||||
icon: mdi:sprinkler
|
||||
tap_action:
|
||||
action: more-info
|
||||
entity: sensor.polivaem_iug
|
||||
state:
|
||||
- value: 'ON'
|
||||
color: green
|
||||
styles:
|
||||
icon:
|
||||
- animation: pulse 1.5s infinite
|
||||
- value: 'OFF'
|
||||
color: grey
|
||||
styles:
|
||||
icon:
|
||||
- animation: none
|
||||
styles:
|
||||
card:
|
||||
- height: 40px
|
||||
- width: 40px
|
||||
icon:
|
||||
- width: 24px
|
||||
- height: 24px
|
||||
- type: custom:mushroom-template-card
|
||||
primary: ''
|
||||
secondary: >
|
||||
Выполнено: {{ states('number.poliv_iug_vypolneno')
|
||||
}} / {{ states('number.poliv_iug') }} с
|
||||
icon: ''
|
||||
tap_action:
|
||||
action: more-info
|
||||
entity: number.poliv_iug_progress
|
||||
card_mod:
|
||||
style: |
|
||||
ha-card {
|
||||
height: 40px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
- type: custom:bar-card
|
||||
entities:
|
||||
- entity: number.poliv_iug_progress
|
||||
name: Прогресс
|
||||
icon: mdi:progress-clock
|
||||
max: 100
|
||||
severity:
|
||||
- from: 0
|
||||
to: 25
|
||||
color: red
|
||||
- from: 26
|
||||
to: 75
|
||||
color: orange
|
||||
- from: 76
|
||||
to: 100
|
||||
color: green
|
||||
unit_of_measurement: '%'
|
||||
|
||||
- type: divider
|
||||
|
||||
# ── Капельная зона ──
|
||||
- type: custom:vertical-stack-in-card
|
||||
title: 🌿 Капельная зона
|
||||
cards:
|
||||
- type: horizontal-stack
|
||||
cards:
|
||||
- type: custom:mushroom-entity-card
|
||||
entity: switch.poliv_kapelnyi
|
||||
show_name: false
|
||||
show_icon: false
|
||||
show_state: false
|
||||
layout: horizontal
|
||||
- type: custom:mushroom-entity-card
|
||||
entity: number.poliv_kapelnyi
|
||||
name: Время
|
||||
icon: mdi:timer-edit
|
||||
layout: horizontal
|
||||
card_mod:
|
||||
style: |
|
||||
ha-card {
|
||||
--mush-icon-size: 24px;
|
||||
height: 48px;
|
||||
flex: 1 1 0;
|
||||
}
|
||||
- type: conditional
|
||||
conditions:
|
||||
- entity: number.poliv_kapelnyi
|
||||
state_not: '0'
|
||||
card:
|
||||
type: custom:vertical-stack-in-card
|
||||
title: ''
|
||||
cards:
|
||||
- type: horizontal-stack
|
||||
cards:
|
||||
- type: custom:button-card
|
||||
entity: sensor.polivaem_kapelno
|
||||
show_name: false
|
||||
show_state: false
|
||||
icon: mdi:watering-can
|
||||
tap_action:
|
||||
action: more-info
|
||||
entity: sensor.polivaem_kapelno
|
||||
state:
|
||||
- value: 'ON'
|
||||
color: green
|
||||
styles:
|
||||
icon:
|
||||
- animation: pulse 1.5s infinite
|
||||
- value: 'OFF'
|
||||
color: grey
|
||||
styles:
|
||||
icon:
|
||||
- animation: none
|
||||
styles:
|
||||
card:
|
||||
- height: 40px
|
||||
- width: 40px
|
||||
icon:
|
||||
- width: 24px
|
||||
- height: 24px
|
||||
- type: custom:mushroom-template-card
|
||||
primary: ''
|
||||
secondary: >
|
||||
Выполнено: {{
|
||||
states('number.poliv_kapelnyi_vypolneno') }} / {{
|
||||
states('number.poliv_kapelnyi') }} с
|
||||
icon: ''
|
||||
tap_action:
|
||||
action: more-info
|
||||
entity: number.poliv_kapelnyi_progress
|
||||
card_mod:
|
||||
style: |
|
||||
ha-card {
|
||||
height: 40px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
- type: custom:bar-card
|
||||
entities:
|
||||
- entity: number.poliv_kapelnyi_progress
|
||||
name: Прогресс
|
||||
icon: mdi:progress-clock
|
||||
max: 100
|
||||
severity:
|
||||
- from: 0
|
||||
to: 25
|
||||
color: red
|
||||
- from: 26
|
||||
to: 75
|
||||
color: orange
|
||||
- from: 76
|
||||
to: 100
|
||||
color: green
|
||||
unit_of_measurement: '%'
|
||||
```
|
||||
|
||||
Нажмите **Сохранить** – панель готова к использованию.
|
||||
|
||||
---
|
||||
|
||||
## 6. Как пользоваться панелью
|
||||
|
||||

|
||||

|
||||
- **Общее состояние:** Отображает статус системы и режим (заморозка/разрешено/запрещено). Ошибка не показывается, но иконка станет красной при неисправности.
|
||||
- **Бак:** Иконка батарейки меняет цвет и текст в зависимости от уровня воды (пусто/наполовину/полный). Нажатие открывает историю уровня.
|
||||
- **Водопровод и насосы:** Показывают текущий статус (Выкл/Вкл/Качает) с цветовой индикацией. Клик – история соответствующего датчика.
|
||||
- **Управление циклом:** Общий переключатель «Полив», кнопки запуска всех зон, заморозки, запрета, осушения бака. Работают как обычные MQTT‑команды.
|
||||
- **Зоны полива:**
|
||||
1. **Включение зоны** – крайний левый переключатель (тумблер).
|
||||
2. **Время** – поле с кнопками +/- для задания уставки полива в секундах.
|
||||
3. Если время > 0, под строкой появятся:
|
||||
- Индикатор полива (спринклер/лейка) – цветной, с анимацией пульсации при работе. Нажатие открывает историю активности зоны.
|
||||
- Строка «Выполнено: X / Y с» – абсолютное значение. Нажатие открывает окно редактирования прогресса в процентах.
|
||||
- Прогресс-бар – визуальное отображение процента выполнения (красный → оранжевый → зелёный).
|
||||
- **Корректировка прогресса:** Кликните на строку «Выполнено…» → появится слайдер 0-100%. Измените процент, и соответствующее количество секунд сразу отправится в контроллер (автоматический пересчёт).
|
||||
|
||||
---
|
||||
|
||||
## 7. Возможные проблемы и их решение
|
||||
|
||||
| Проблема | Вероятная причина | Решение |
|
||||
|----------|-------------------|---------|
|
||||
| Не отображаются прогресс‑бары | Отсутствует `bar-card` или не созданы `template number` | Проверьте HACS, установите карту. Убедитесь, что template‑числа добавлены и конфигурация перезагружена. |
|
||||
| Иконка полива не меняет цвет | Неправильное имя датчика `sensor.polivaem_...` | Проверьте точное название в разделе **Состояния**. Поправьте в YAML панели. |
|
||||
| Тумблер включения зоны не видим | Не установлена карта `mushroom-entity-card` или перекрыт стилями | Убедитесь, что `mushroom-cards` установлены. В нашем финальном YAML тумблер видим всегда. |
|
||||
| Ошибка «expected float» при движении слайдера прогресса | Используется `slider-entity-row` в активном режиме, а динамический `max` задан некорректно | В нашем решении прогресс‑бар только визуальный (`bar-card`), ручная корректировка – через `template number` с собственным `set_value`. Ошибки быть не должно. |
|
||||
| Бак всегда показывает «Пустой» | Неправильно работают поплавки или датчики `$wMax`/`$wMin` не обновляются | Проверьте в MQTT‑топиках фактические значения. Убедитесь, что поплавки подключены и отправляют ON/OFF. |
|
||||
|
||||
---
|
||||
|
||||
## 8. Дополнительная информация
|
||||
|
||||
- Все команды управления (вкл/выкл зон, сброс, заморозка и т.д.) отправляются напрямую в контроллер lighthub через MQTT.
|
||||
- Система использует `availability_topic` для отслеживания связи с контроллером. При пропадании сигнала все элементы станут недоступны (серые).
|
||||
- При желании можно расширить панель новыми зонами, копируя структуру существующих и добавляя соответствующие `number`, `switch` и `sensor` в MQTT‑конфигурацию и `template`.
|
||||
|
||||
---
|
||||
|
||||
## Приложение: полный финальный YAML панели
|
||||
|
||||
Код уже приведён в разделе 5.3. Используйте его как окончательную версию.
|
||||
|
||||
---
|
||||
|
||||
Теперь ваша система полива полностью интегрирована в Home Assistant. Вы можете управлять поливом с мобильного телефона, отслеживать историю и быть уверенными, что всё под контролем!
|
||||
@@ -0,0 +1,375 @@
|
||||
# LightHub: Модуль многоканальной системы полива (out_sprinkler)
|
||||
Данный модуль реализует многозональную систему полива
|
||||
|
||||
## Система состоит из следующих компонент:
|
||||
|
||||
* Накопительный водяной бак. Снабжен двумя поплавками. Максимум воды и минимум воды. Заведены на входы wMax и wMin
|
||||
* Насос полива высокого давления. Запитан из бака. Включается реле, подключенным к выходу rPump. Датчик тока для контроля того, что насос включен, заведен на вход fbPump
|
||||
* Набор клапанов зон полива. Подключены через оптореле к выходам, заданным в параметре pin соответствующей зоны полива.
|
||||
* Клапан налива из водопровода. Подключен через оптореле к выходу vIn
|
||||
* Насос дренажного колодца. Приоритетный источник для наполнения бака полива. Когда система полива находится в ждущем или активном режиме, бак пытается максимально наполнится из дренажного колодца. Насос дренажа имеет поплавковый выключатель, отключающий насос при осушении дренажного колодца. Насос включается реле, которое подключено к выходу rDren. Для контроля того, что насос включен и момента осушения колодца, используется датчик тока, который подключен в входу fbDren
|
||||
* Опциональный водосчетчик. Контакты подключены к входу wCtr
|
||||
|
||||
## Система налива воды реализована при помощи конечного автомата со следующими состояниями:
|
||||
|
||||
* SP\_UNKNOWN
|
||||
* SP\_OFF
|
||||
* SP\_DREN\_ON - дренажный насос включен
|
||||
* SP\_DREN\_OPERATE - дренажный насос работает
|
||||
* SP\_DREN\_EMPTY - дренажный насос выключился встроенным поплавком - колодец пуст
|
||||
* SP\_VIN - включено наполнение из водопровода
|
||||
* SP\_FULL - бак наполнен
|
||||
* SP\_DRYING - режим осушения системы: налив перекрыт, работает насос полива для слива бака (SP\_DRYING=7, out_sprinkler.h:34)
|
||||
|
||||
Строковые значения, публикуемые в топик `$state` (out_sprinkler.cpp:263-308): `OFF`, `DREN_ON`, `DREN_OPERATE`, `DREN_EMPTY`, `VIN`, `FULL`, `DRYING`, `FAULT_VIN`, `FAULT_DREN`, `UNKNOWN`.
|
||||
|
||||
граф переходов конечного автомата системы налива воды
|
||||
|
||||
Состояние SP\_* | Условие перехода | перейти в состояние | выполнить при переходе |
|
||||
|------|--------|-------|---------|
|
||||
INIT | true | OFF | выключить клапана и насосы |
|
||||
OFF | vMax && !FREEZE | FULL | выключить vIN, rDren|
|
||||
OFF | ! vMax && !FREEZE | DREN\_ON|включить rDren|
|
||||
DREN\_ON|fbDren (насос дренажа реально работает)|DREN\_OPERATE|
|
||||
DREN\_ON|таймаут 10 сек|DREN\_EMPTY| насос так и не заработал - видимо в колодце пусто
|
||||
DREN\_EMPTY|включен цикл полива и бак не полон|VIN|включить клапан vIN для набора бака из водопровода|
|
||||
DREN\_OPERATE| ! fbDren (насос дренажа более не работает)|DREN\_EMPTY||
|
||||
VIN|fbDren|DREN\_OPERATE|вылючить клапан vIN для набора бака из водопровода - заработал дренажный насос|
|
||||
VIN, DREN\_OPERATE|vMax|FULL | выключить vIN, rDren - бак полон|
|
||||
VIN|таймаут 1200 сек | FAULT\_VIN| выключить vIN - бак так и не наполнился|
|
||||
DREN\_OPERATE|fbPump (качает основной насос)|DREN\_OPERATE|сброс таймера (@timer = now) — не считать ошибку, пока качает основной насос (L562)|
|
||||
DREN\_OPERATE|таймаут 4000 сек |FAULT_DREN|выключить rDren - не смотря на продолжительную работу насоса бак не наполнен|
|
||||
FULL|! wMax|DREN\_ON|дренаж перезапускается при опустошении бака (L609-617)|
|
||||
FAULT\_VIN, FAULT\_DREN|wMax|FULL|сброс ошибки при наполнении бака (L619-635)|
|
||||
|
||||
|
||||
|
||||
## Конфигурирование:
|
||||
|
||||
|
||||
```
|
||||
|
||||
"items":
|
||||
{
|
||||
"sprinkler":[23,
|
||||
{
|
||||
"":{
|
||||
"vIn":3,
|
||||
"wMax":44,
|
||||
"wMin":46,
|
||||
"rDren":23,
|
||||
"fbDren":63,
|
||||
"rPump":24,
|
||||
"fbPump":62,
|
||||
"wCtr":49
|
||||
},
|
||||
"nord":{"pin":6,"set":60,"cmd":1},
|
||||
"south":{"pin":7,"set":100,"cmd":1},
|
||||
"trees":{"pin":10,"set":60,"cmd":2},
|
||||
"outlets:{}
|
||||
|
||||
}]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
В корневом (`""`) объекте, помимо выходов/входов, можно задать EXEC-объект `onFault` — при срабатывании ошибки автомата налива вместо публикации в `$fault` исполняется он с кодом ошибки аргументом (L260-262, L311-314).
|
||||
|
||||
## Алгоритм работы
|
||||
в настройки зон полива задаем интенсивность для каждой зоны.
|
||||
|
||||
Это можно сделать как в конфиге так динамически, (стандартными механизмами управления по MQTT, HTTP, CAN)
|
||||
|
||||
Рассмотрим на примере MQTT:
|
||||
|
||||
**топик** ```root/name/sprinkler/garden/set -> 60```
|
||||
|
||||
Задаем обьем полива 60 отсчетов счетчика воды (если счетчик не сконфигурирован - 60 секунд)
|
||||
|
||||
Контроллер должен передать это значение в выходной топик ```root/name/s_out/sprinkrer/garden/set``` и оно будет восстановлено при перезагрузке контроллера
|
||||
|
||||
|
||||
отработанный обьем воды или время будет сохраняться в параметре "val" каждой зоны (параметр будет автоматически увеличиваться при работе зоны, передаваться в соответствующий зоне топик для мониторинга и восстановления в случае перезагрузки контроллера)
|
||||
|
||||
**Пример топика:** ```root/s_out/sprinkler/garden/val```
|
||||
|
||||
Когда данный параметр достигнет значения (или времени), заданного в параметре "set" контроллер завершит полив данной зоны и перейдет к следующей.
|
||||
|
||||
Важно: если set=0 (по умолчанию) то время работы зоны не лимитируется. Если такая зона включена - система полива не будет отключаться после окончания полива прочих зон и насос не будет обесточиваться. Это удобно, если в системе полива есть водяная розетка для подключения поливочного шланга, которая всегда должна находиться под давлением. Такую зону конфигурируйте последней в списке.
|
||||
|
||||
Для сброса счетчиков можно использовать как непосредственную установку значения параметра "val" для каждой зоны так и команду RESET, отправленную в нужную зону или в объект sprinkler через суффикс /cmd.
|
||||
|
||||
**Пример:** ```root/name/sprinkler/cmd -> RESET```
|
||||
|
||||
В последнем случае, контроллер итерационно сбросит счетчики в значение 0 для каждой зоны полива.
|
||||
Это инициирует старт программы полива, если система находится в состоянии ON
|
||||
|
||||
Команда RESET не отработает если обьект полива находится в состоянии DISABLE или FREEZE
|
||||
|
||||
Также, в этих режимах, в принципе, не отработает запуск полива какой-либо зоны (команды set/RESET), если для нее задано время/обьем полива.
|
||||
|
||||
Если обьем полива не задан (set==0) - это например водяная розетка для мытья машины, то такая зона запустится даже в режиме DISABLE
|
||||
|
||||
Если в процессе полива придет команда DISABLE (начался дождь) - полив прекратится, программа полива возобновится после ENABLE
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Управление
|
||||
|
||||
### Включение/выключение полива конкретной зоны:
|
||||
|
||||
**Включить** ```root/name/sprinkler/garden/cmd -> ON```
|
||||
|
||||
**Выключить** ```root/name/sprinkler/garden/cmd -> OFF```
|
||||
|
||||
|
||||
|
||||
### Включение/выключение цикла полива:
|
||||
|
||||
**Включить** ```root/name/sprinkler/cmd -> ON```
|
||||
Система начнет или продолжит цикл полива, переходя от зоны к зоне по мере завершения работы с каждой предыдущей зоной. После завершения работы со всеми зонами, sprinkler НЕ перейдет в состояние OFF автоматически, но полив прекратится для тех зон, где показатель val достиг параметра set
|
||||
|
||||
Если не будет ни одной активной зоны - насос обесточится.
|
||||
|
||||
Перед включением полива, система убедится что бак готов: полив стартует при `state==FULL || wMax || wMin || fbPump` (L638) — то есть и при минимальном уровне / работающей помпе, иначе система до-наполнит бак до максимума из водопровода.
|
||||
|
||||
|
||||
|
||||
**Выключить** ```root/name/sprinkler/cmd -> OFF```
|
||||
Система немедленно остановит текущий цикл полива (закроет клапаны зон, выключит насос полива)
|
||||
|
||||
|
||||
Аналогично, будут работать команды XON и XOFF, с одним исключением, что команда XON может быть запрещена и игнорироваться если активирован режим DISABLE. Это базовая функция контроллера и не относится к функционалу данного модуля. Но может быть использована, например, для запрета полива на определенное время после выпадения осадков
|
||||
|
||||
**Пример**
|
||||
|
||||
```
|
||||
root/name/sprinkler/ctrl -> DISABLE
|
||||
root/name/sprinkler/cmd -> XON //Будет проигнорировано
|
||||
|
||||
root/name/sprinkler/ctrl -> ENABLE
|
||||
root/name/sprinkler/cmd -> XON //А вот теперь сработает
|
||||
|
||||
```
|
||||
|
||||
Даже в выключенном состоянии (OFF) , система полива работает в дежурном режиме, поддерживая максимальный уровень воды в баке за счет немедленной перекачки из дренажного колодца
|
||||
|
||||
При попытке включения системы после завершения дневного задания по поливу всех зон (параметр val для всех зон достиг параметра set) авто-перехода в OFF не происходит: item остаётся в состоянии ON и просто простаивает, не запуская активного полива (автоматическое выключение закомментировано, L712-722) — что согласуется с описанием выше: команда ON не переводит систему в OFF автоматически.
|
||||
|
||||
|
||||
|
||||
### Полная блокировка системы полива (в зимнее время)
|
||||
Ддя перевода канала полива в полностью заблокированное состояние и обратно импользуется системная команда FREEZE/UNFREEZE соответственно
|
||||
|
||||
В режиме FREEZE полностью заблокирована обработка всех команд, кроме UNFREEZE, заблокирован автомат пополнения бака из дренажного насоса и выключены насосы и все клапана.
|
||||
|
||||
Если одновременно выставлены флаги FREEZE и DISABLE, то в /ctrl публикуется FREEZE — приоритет над DISABLE (item.cpp:2174-2176).
|
||||
|
||||
Рекомендуется задать флаг FREEZE в конфигурации канала (см документ ...) , чтобы избежать разблокировки при утере значений топика /clrl и перезагрузки системы
|
||||
|
||||
Также, на вход /val обЪекта sprinkler можно подать значение уличной температуры. И если значения будут ниже нуля, система автоматически перейдет в режим FREEZE
|
||||
|
||||
**Пример**
|
||||
|
||||
```
|
||||
root/name/sprinkler/ctrl -> FREEZE
|
||||
root/name/sprinkrer/cmd -> ON //Будет проигнорировано
|
||||
|
||||
root/name/sprinkler/ctrl -> UNFREEZE
|
||||
root/name/sprinkrer/cmd -> ON //А вот теперь сработает
|
||||
|
||||
root/name/sprinkler/val -> -1 //система перейдет в режим FREEZE
|
||||
|
||||
|
||||
```
|
||||
|
||||
Так как команда FREEZE блокирует запуск каких либо насосов и открытие клапанов, это делает невозможным слив системы в процессе подготовки к зиме
|
||||
|
||||
Когда требуется слить систему, необходимо отключить дренажный насос, перекрыть водопроводный кран
|
||||
|
||||
Данный режим реализован при помощи команды DRY
|
||||
|
||||
Дополнительно к перекрытию поступления воды в бак (заблокирован автомат пополнения бака из дренажного насоса и водопровода) данная команда включает помпу.
|
||||
|
||||
- DRY переопределяет ON: если система находится в режиме `@state==SP_DRYING` и приходит команда ON, она исполняется как CMD_DRY, а не ON (out_sprinkler.cpp:837-841).
|
||||
- Режим DRY персистентен: `@state=SP_DRYING` хранится в конфиге и переживает перезагрузку контроллера; реле восстанавливаются из `@lastVals`, после рестарта в топик публикуется `DRYING`.
|
||||
|
||||
Далее, требуется слить бак включением выбранных зон полива или через водяные розетки.
|
||||
Только после осушения бака (насос выключится) - систему необходимо перевести в режим FREEZE
|
||||
Перевод в этот редим сбрасывает режим DRY (а также, состояния ошибки автомата наполнения бака)
|
||||
|
||||
|
||||
### Передача статусных значений
|
||||
|
||||
При старте (первый Poll) контроллер принудительно публикует все ключевые статусы: `$wMax`/`$wMin`/`$fbDren`/`$fbPump`/`$rPump`/`$rDren`/`$rVIN` + `$state`/`$fault` (L474-487). Повторно `$state`/`$fault` публикуются при командах ON/OFF (L842, L848).
|
||||
|
||||
**Ошибки (onFault / $fault):** при каждом переходе состояния публикуется код ошибки в топик `$fault`: 0 — без ошибки, 1 — FAULT_VIN, 2 — FAULT_DREN (L311-315). Вместо публикации в `$fault` можно задать EXEC-объект `onFault` в корневом (`""`) объекте — в этом случае при срабатывании ошибки исполняется он с кодом ошибки аргументом (L260-262, L311-314).
|
||||
|
||||
**Примеры выдачи в топики:**
|
||||
|
||||
```
|
||||
root/s_out/sprinkler/$fbPump - ON/OFF признак того, что включен основной насос (от датчика тока)
|
||||
root/s_out/sprinkler/$fbDren - ON/OFF признак того, что включен дренажный насос (от датчика тока)
|
||||
root/s_out/sprinkler/$state - состояние конечного автомата Системы налива воды
|
||||
root/s_out/sprinkler/$fault - код ошибки: 0 / 1=FAULT_VIN / 2=FAULT_DREN
|
||||
root/s_out/sprinkler/$wMax - ON/OFF достигнут максимум воды в баке (от поплавкового датчика)
|
||||
root/s_out/sprinkler/$wMin - ON/OFF достигнут минимум воды в баке (от поплавкового датчика)
|
||||
root/s_out/sprinkler/$rDren - ON/OFF включено реле дренажного насоса
|
||||
root/s_out/sprinkler/$rPump - ON/OFF включено реле основного насоса
|
||||
root/s_out/sprinkler/set - значение счетчика воды (восстанавливается при перезагрузке из данного топика)
|
||||
root/s_out/sprinkler/$rVIN - ON/OFF - признак открытия клапана налива бака из водопровода
|
||||
|
||||
root/s_out/sprinkler/garden/set - требуемый обьем (или время) полива зоны
|
||||
root/s_out/sprinkler/garden/cmd - ON или OFF - признак включения полива зоны
|
||||
root/s_out/sprinkler/garden/$state - ON или OFF - признак того что зона поливается в настоящее время
|
||||
root/s_out/sprinkler/garden/val - текущее время или обьем полива данной зоны
|
||||
|
||||
```
|
||||
|
||||
### Пример конфигурации Home Assistant
|
||||
```
|
||||
sensor:
|
||||
- name: "Полив бак Макс"
|
||||
state_topic: "root/s_out/sprinkler/$wMax"
|
||||
|
||||
- name: "Полив бак Мin"
|
||||
state_topic: "root/s_out/sprinkler/$wMin"
|
||||
|
||||
- name: "Полив водопровод"
|
||||
state_topic: "root/s_out/sprinkler/$rVIN"
|
||||
|
||||
- name: "Полив дренаж вкл"
|
||||
state_topic: "root/s_out/sprinkler/$rDren"
|
||||
|
||||
- name: "Полив дренаж качает"
|
||||
state_topic: "root/s_out/sprinkler/$fbDren"
|
||||
|
||||
- name: "Полив насос вкл"
|
||||
state_topic: "root/s_out/sprinkler/$rPump"
|
||||
|
||||
- name: "Полив насос качает"
|
||||
state_topic: "root/s_out/sprinkler/$fbPump"
|
||||
|
||||
- name: "Полив состояние"
|
||||
state_topic: "root/s_out/sprinkler/$state"
|
||||
|
||||
- name: "Полив ошибка"
|
||||
state_topic: "root/s_out/sprinkler/$fault"
|
||||
|
||||
- name: "Полив юг выполнено"
|
||||
state_topic: "root/s_out/sprinkler/south/val"
|
||||
|
||||
- name: "Полив север выполнено"
|
||||
state_topic: "root/s_out/sprinkler/nord/val"
|
||||
|
||||
- name: "Полив капельный выполнено"
|
||||
state_topic: "edem/s_out/sprinkler/trees/val"
|
||||
|
||||
- name: "Поливаем юг"
|
||||
state_topic: "root/s_out/sprinkler/south/$state"
|
||||
|
||||
- name: "Поливаем север"
|
||||
state_topic: "root/s_out/sprinkler/nord/$state"
|
||||
|
||||
- name: "Поливаем капельно"
|
||||
state_topic: "root/s_out/sprinkler/trees/$state"
|
||||
|
||||
- name: "Полив розетка статус"
|
||||
state_topic: "root/s_out/sprinkler/outlets/$state"
|
||||
|
||||
- name: "Полив блокировки"
|
||||
state_topic: "root/s_out/sprinkler/ctrl"
|
||||
|
||||
switch:
|
||||
|
||||
- name: "Полив"
|
||||
state_topic: "root/s_out/sprinkler/cmd"
|
||||
command_topic: "root/air/sprinkler/cmd"
|
||||
availability_topic: "root/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив север"
|
||||
state_topic: "root/s_out/sprinkler/nord/cmd"
|
||||
command_topic: "root/air/sprinkler/nord/cmd"
|
||||
availability_topic: "root/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив юг"
|
||||
state_topic: "root/s_out/sprinkler/south/cmd"
|
||||
command_topic: "root/air/sprinkler/south/cmd"
|
||||
availability_topic: "root/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив капельный"
|
||||
state_topic: "root/s_out/sprinkler/trees/cmd"
|
||||
command_topic: "root/air/sprinkler/trees/cmd"
|
||||
availability_topic: "root/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
- name: "Полив розетки"
|
||||
state_topic: "root/s_out/sprinkler/outlets/cmd"
|
||||
command_topic: "root/air/sprinkler/outlets/cmd"
|
||||
availability_topic: "root/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
button:
|
||||
- name: "Полив сброс"
|
||||
command_topic: "root/air/sprinkler/cmd"
|
||||
payload_press: "RESET"
|
||||
|
||||
- name: "Полив блокировка"
|
||||
command_topic: "root/air/sprinkler/cmd"
|
||||
payload_press: "FREEZE"
|
||||
|
||||
- name: "Полив разблокировка"
|
||||
command_topic: "root/air/sprinkler/cmd"
|
||||
payload_press: "UNFREEZE"
|
||||
|
||||
- name: "Полив разрешить"
|
||||
command_topic: "root/air/sprinkler/cmd"
|
||||
payload_press: "ENABLE"
|
||||
|
||||
- name: "Полив запретить"
|
||||
command_topic: "root/air/sprinkler/cmd"
|
||||
payload_press: "DISABLE"
|
||||
|
||||
- name: "Полив осушение бака"
|
||||
command_topic: "root/air/sprinkler/cmd"
|
||||
payload_press: "DRY"
|
||||
#Такую проверку можно добавить везде, при ее наличии обьекты станут недоступными если контроллер оффлайн
|
||||
availability_topic: "root/air/$state"
|
||||
payload_available: "ready"
|
||||
payload_not_available: "disconnected"
|
||||
|
||||
number:
|
||||
|
||||
- name: "Полив юг"
|
||||
state_topic: "root/s_out/sprinkler/south/set"
|
||||
command_topic: "root/air/sprinkler/south/set"
|
||||
min: 0
|
||||
max: 6000
|
||||
|
||||
- name: "Полив север"
|
||||
state_topic: "root/s_out/sprinkler/nord/set"
|
||||
command_topic: "root/air/sprinkler/nord/set"
|
||||
min: 0
|
||||
max: 6000
|
||||
|
||||
- name: "Полив капельный"
|
||||
state_topic: "root/s_out/sprinkler/trees/set"
|
||||
command_topic: "root/air/sprinkler/trees/set"
|
||||
min: 0
|
||||
max: 6000
|
||||
|
||||
|
||||
|
||||
```
|
||||
@@ -0,0 +1,745 @@
|
||||
# LightHub: Модуль многоканального кондиционера и вентиляции (out_Multivent)
|
||||
|
||||
> Документ описывает назначение, архитектуру и конфигурирование модуля управления многозональными системами кондиционирования и вентиляции LightHub.
|
||||
> Предназначен для инженеров HVAC-систем, интеграторов и разработчиков.
|
||||
|
||||
---
|
||||
|
||||
## 1. Назначение модуля
|
||||
|
||||
### 1.1 Область применения
|
||||
|
||||
Модуль `out_Multivent` предназначен для управления системами кондиционирования и вентиляции с **центральной установкой** и **множеством независимых зон/комнат**.
|
||||
|
||||
### 1.2 Типовые сценарии
|
||||
|
||||
#### Сценарий 1: Многозональный кондиционер
|
||||
- Центральная сплит-система или компактная установка (1 компрессор, 1 вентилятор)
|
||||
- Несколько помещений с электромоторными задвижками (воздушными затворами)
|
||||
- Каждое помещение требует своего микроклимата
|
||||
|
||||
#### Сценарий 2: Многозональная приточная вентиляция
|
||||
- Центральная приточная установка с одним вентилятором
|
||||
- Несколько независимых воздуховодов с регулируемыми задвижками
|
||||
- Распределение воздушного потока в зависимости от потребностей зон
|
||||
|
||||
#### Сценарий 3: Комбинированная система (климат + вентиляция)
|
||||
- Центральный кондиционер + приточная вентиляция
|
||||
- Управление как охлаждением/нагревом, так и циркуляцией воздуха
|
||||
|
||||
### 1.3 Ключевые возможности
|
||||
|
||||
✅ **Балансировка воздушного потока** — автоматическое распределение производительности между зонами
|
||||
|
||||
✅ **PID-регулирование температуры** — независимая стабилизация для каждой зоны
|
||||
|
||||
✅ **Интеллектуальное переключение режимов** — автоматическое определение HEAT/COOL по текущей температуре
|
||||
|
||||
✅ **Агрегация команд** — управление центральной установкой на основе суммарного спроса от зон
|
||||
|
||||
✅ **Каскадное управление** — возможность передачи команд на внешние системы (например, отображение режимов на стеновых панеляж управления)
|
||||
|
||||
✅ **Отслеживание прямого управления основным кондиционером** — система понимает, явились ли изменения режима работы основного кондиционера причиной ее управляющих воздействий. И если обнаруживает, что режим поменялся вручную, при помощи пульта управления центральной установкой, принимает это изменение как инструкцию к действию. А именно: при выключении основного блока с пульта - все виртуальные зоны выключаются. (чтобы предотвратить немедленное автоматическое обратное включение) При обратном включении - их состояние восстанавливается. Также, можно определить какую либо из виртуальных зон для управления с пульта главного кондиционера.
|
||||
|
||||
❌ **Ограничения**: ?
|
||||
|
||||
---
|
||||
|
||||
## 2. Архитектура и принцип работы
|
||||
|
||||
### 2.1 Компоненты системы
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────┐
|
||||
│ Центральная установка (AC) │
|
||||
│ (компрессор, вентилятор, датчик temp) │
|
||||
│ │
|
||||
│ Управляется через S_MODE и S_FAN │
|
||||
└──────────────┬─────────────────────────────┘
|
||||
│
|
||||
┌─────┴─────┐
|
||||
│ │
|
||||
┌────▼─────┐ ┌─▼─────────┐
|
||||
│ Зона 1 │ │ Зона N │
|
||||
│ Задвижка1│ │ ЗадвижкаN │
|
||||
│ Датчик1 │ │ ДатчикN │
|
||||
└──────────┘ └───────────┘
|
||||
```
|
||||
|
||||
### 2.2 Логика работы
|
||||
|
||||
#### Фаза 1: Опрос и сбор информации
|
||||
1. Модуль считывает текущий режим центральной установки (`mode`)
|
||||
2. Определяет текущую функцию (HEAT, COOL, FAN)
|
||||
3. Собирает команды от всех зон
|
||||
|
||||
#### Фаза 2: PID-расчёты
|
||||
Если в зоне определён PID-контроллер:
|
||||
- Вход PID: текущая температура зоны (`val`)
|
||||
- Установка: требуемая температура зоны (`set`)
|
||||
- Выход PID: регулировочный сигнал (`po`, от 0 до 255)
|
||||
|
||||
#### Фаза 3: Балансировка
|
||||
```
|
||||
balance = Σ(po_zone) где cmd=HEAT
|
||||
balance = Σ(-po_zone) где cmd=COOL
|
||||
```
|
||||
|
||||
#### Фаза 4: Управление центральной установкой
|
||||
- **|balance| > boost** (по умолчанию 230) → boost: уставка AC принудительно поднимается до 30 °C (HEAT) / опускается до 17 °C (COOL)
|
||||
- **|balance| < 10** (deadband) → активность PID сбрасывается — запрос от активных зон отсутствует (L387-392)
|
||||
- **FAN/AUTO** — отправляются только при запросе зоны и lastACfan > 0, иначе команда AC не шлётся (L401-403)
|
||||
- **else** → OFF
|
||||
|
||||
#### Фаза 5: Распределение производительности
|
||||
Для каждой зоны пересчитывается выходной сигнал задвижки:
|
||||
|
||||
$$out = \frac{(V_{requested} \times 255) \times V_{max}}{V \times P_{max}}$$
|
||||
|
||||
где:
|
||||
|
||||
- $V_{requested}$ — требуемый объём воздуха для зоны
|
||||
- $V$ — номинальный объём воздуха зоны
|
||||
- $V_{max}$ — объём максимально требующей зоны
|
||||
- $P_{max}$ — максимальный процент открытия требующей зоны
|
||||
|
||||
---
|
||||
|
||||
## 3. Структура JSON-конфигурации
|
||||
|
||||
### 3.1 Формат item типа 18 (Multivent)
|
||||
|
||||
```json
|
||||
"item_name": [
|
||||
18,
|
||||
{
|
||||
"zone_1": { ... },
|
||||
"zone_2": { ... },
|
||||
"": { ... }
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
- Объект маршрутизации содержит **именованные зоны** + **пустую строку** `""` для центральной установки и общих настроек
|
||||
|
||||
### 3.2 Структура зоны
|
||||
|
||||
```json
|
||||
"zone_name": {
|
||||
"fan": 0,
|
||||
"cmd": 2,
|
||||
"out": 255,
|
||||
"V": 60,
|
||||
"pid": [1.0, 0.1, 0.05, 5.0],
|
||||
"set": 21.0,
|
||||
"val": 21.0,
|
||||
"cas":{
|
||||
"fan":{"item":"panel1${sfx},"emit":"f_room1${sfx}","map":{"cmd":"fan"}},
|
||||
"set":{"item":"panel1${sfx}},
|
||||
"cmd":{"item":"panel1${sfx}}}}
|
||||
}
|
||||
```
|
||||
|
||||
#### Поля зоны:
|
||||
|
||||
| Поле | Тип | Назначение |
|
||||
|------|-----|-----------|
|
||||
| `fan` | int (0-255) | Текущий запрос в воздухе для зоны. Этот параметр устанавливается как встроенным PID регулятором так и при помощи суффикса /fan данной зоны (изменение запускает процесс пере-балансировки зон, в результате формируется параметр out, который уже подается на задвижки |
|
||||
| `cmd` | int | Текущая команда (OFF/ON/HEAT/COOL и т.д. в числовом виде) |
|
||||
| `out` | int (0-255) | Финальный выходной сигнал задвижки (пересчитанный) |
|
||||
| `V` | int | Номинальный объём воздуха для этой зоны (м³/ч) |
|
||||
| `pid` | массив ≥3 | Коэффициенты PID: [kP, kI, kD, dT(сек)] (позиционные) |
|
||||
| `set` | float | Требуемая температура (установка) |
|
||||
| `val` | float | Текущая температура зоны. Передается через суффикс /val данной зоны |
|
||||
| `cas` | object | Каскадирование полученной команды на другие обьекты. Полезно, если изменение статуса зоны надо, наример, отразить на климатической панели. Или если скорость вентилятора надо преобразовать в дискретный вид (LOW,MEDIUM,HIGH) и передать в отдельный топик (как в примере) для отображения в интерфейсе Home Assistant. У обьекта cas может быть три под-обьекта: fan, set, cmd которые могут отдельно транслировать скорость вентилятора, команду (режим) зоны и уставку температуры. Следует заметить, что даже без использования данной настройки, изменения зоны передаются в статусный топик зоны (для восстановления состояния при перезапуске и отражения в интерфейсе HA, так что дублировать это в данной настройке не требуется. Но данная настройка крайне полезна именно для дублирования состояния на внешние устройства а также на внутренние обьекты контроллера (отрабатывается весь синтаксис EXEC обьекта, включая возможность передачи по MQTT, CAN, локальные items) |
|
||||
|
||||
### 3.3 Центральная установка (пустая зона `""`)
|
||||
|
||||
```
|
||||
"":{"item":"ac_2",
|
||||
"turnbyfan":0,
|
||||
"boost":200,
|
||||
"supress":7,
|
||||
"onextcmd":{"emit":"${sout}/vac/extcmd","item":"vac/zal"}
|
||||
}
|
||||
```
|
||||
|
||||
#### Поля:
|
||||
|
||||
| Поле | Назначение |
|
||||
|------|-----------|
|
||||
|`turnbyfan`|Команда (CMD\_), генерируемая при подаче ненулевого /fan в зону, если зона в CMD\_OFF (L527, L676-683); при /fan=0 зона автоматически переводится в CMD\_OFF (L686-691). 0 — отключено |
|
||||
|`boost`|Порог |balance| (по умолчанию 230, AC\_BOOST\_TRESHOLD). При превышении модуль принудительно поднимает/опускает уставку AC (set) до 30/17 °C, чтобы усилить нагрев/охлаждение (L387-388, L1102-1123) |
|
||||
|`supress`|Битмаска подавления повторной отправки на AC: 1=FAN, 2=SET, 4=CMD (по умолчанию 0xF, AC\_SUPPRESS\_\*). **Прим.: в коде ключ «supress» (одна s)** |
|
||||
|`overridecmd`|Подмена уходящей на AC команды любой другой, кроме CMD\_OFF (L1044-1045) |
|
||||
|`onextcmd`|EXEC-объект, исполняемый при ручном (внешнем) изменении команды/уставки AC с пульта |
|
||||
| `set` | Уставка температуры AC (float); сохраняется при получении /set с AC (L582-591), читается при boost (L1106) |
|
||||
| `val` | Температура воздуха от AC (или текущее состояние) |
|
||||
| `mode` | Текущий режим AC (CMD\_HEAT/CMD\_COOL/CMD\_FAN/CMD\_OFF) |
|
||||
| `@lastCmd` | Последняя отправленная команда (служебное) |
|
||||
| `@lastFan` | Последнее отправленное значение вентилятора AC (служебное) |
|
||||
| `@lastSet` | Последнее отправленное значение уставки AC (служебное) |
|
||||
| `@preCmd` | Режим AC до останова вентилятора, восстанавливается при повторном запуске (L1078-1084) |
|
||||
| `@preset` | Уставка AC, сохранённая перед boost, восстанавливается при resetBoost (L1107, L1118) |
|
||||
| `roomtemp` | Дополнительный датчик комнатной температуры (**не читается** — обработчик S\_TEMP закомментирован, L620-623) |
|
||||
|
||||
---
|
||||
\
|
||||
## 4. Детальная конфигурация компонентов
|
||||
|
||||
### 4.1 PID-контроллер
|
||||
|
||||
#### Включение PID
|
||||
|
||||
```json
|
||||
"pid": [1.0, 0.1, 0.05, 5.0]
|
||||
```
|
||||
|
||||
**Формат**: `[kP, kI, kD, dT]` — массив из ≥3 позиционных элементов (L61-69). Параметры аларма `AlarmTime` (сек, по умолчанию 120) и `AlarmValue` (по умолчанию 0.0) задаются **отдельными полями объекта зоны**, а не внутри `pid` (L71-72).
|
||||
|
||||
- **kP** (пропорциональный коэффициент): 0.5—2.0
|
||||
|
||||
- **kI** (интегральный коэффициент): 0.0—0.2
|
||||
- Устраняет постоянное отклонение
|
||||
|
||||
- **kD** (дифференциальный коэффициент): 0.01—0.1
|
||||
- Снижает колебания
|
||||
|
||||
- **dT** (период сэмплирования, сек): по умолчанию 5 сек
|
||||
|
||||
|
||||
#### Пример для зоны, заданный в виде массива:
|
||||
|
||||
```json
|
||||
"pid": [1.0, 0.05, 0.02, 5.0]
|
||||
```
|
||||
|
||||
#### Пример для зоны, заданный в виде обьекта (AlarmTime/AlarmValue — поля зоны, а не pid):
|
||||
|
||||
```json
|
||||
"zone_name": {
|
||||
"pid": {"kP":-1.0,"kI":0.05,"kD":0.02,"dT":50},
|
||||
"AlarmTime":240,
|
||||
"AlarmValue":128
|
||||
}
|
||||
```
|
||||
|
||||
## 4.2 Объём воздуха (V)
|
||||
|
||||
Указывается в **относительных единицах** (не обязательно м³/ч):
|
||||
|
||||
```json
|
||||
"V": 60
|
||||
```
|
||||
|
||||
Используется для **пропорционального распределения** между зонами.
|
||||
|
||||
**Рекомендуемые значения:**
|
||||
- Спальня: 30—50
|
||||
- Гостиная: 60—100
|
||||
- Офис: 40—80
|
||||
- Кухня: 80—150 (если есть вентиляция)
|
||||
|
||||
### 4.3 Маршрутизация MQTT
|
||||
|
||||
tbd
|
||||
|
||||
### 4.4 Каскадные команды
|
||||
|
||||
Возможность передачи команды на другие устройства (например, открыть задвижку, вывести на панель):
|
||||
|
||||
```json
|
||||
"cas":{
|
||||
"fan":{"item":"panel1${sfx},"emit":"f_room1${sfx}","map":{"cmd":"fan"}},
|
||||
"set":{"item":"panel1${sfx}},
|
||||
"cmd":{"item":"panel1${sfx}}}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Режимы работы модуля
|
||||
|
||||
### 5.1 Режимы команд для зон
|
||||
|
||||
| CMD | Назначение |
|
||||
|-----|-----------|
|
||||
| `OFF` | Задвижка закрыта, зона отключена |
|
||||
| `ON` | Зона активна (используется последний процент) |
|
||||
| `HEAT` | Зона требует нагрева (минимум 30% вентилятора: при fan < 20 принудительно выставляется 30, L805-810) |
|
||||
| `COOL` | Зона требует охлаждения |
|
||||
| `FAN` | Только вентиляция (без нагрева/охлаждения) |
|
||||
| `AUTO` | Пассивный режим (зависит от AC) |
|
||||
| `HEATCOOL` | Автоматическое переключение по PID |
|
||||
| `DRY` | Осушение |
|
||||
| `FREEZE` | Заморозка зоны: блокирует /fan, ON и OFF (L763-769; проверка в L661, L717, L735) |
|
||||
| `UNFREEZE` | Разморозка зоны (L767-769) |
|
||||
| `HIGH`/`MEDIUM`/`LOW` | Уровни вентилятора через /fan: HIGH→255, MEDIUM→128, LOW→64 (L533-546) |
|
||||
|
||||
### 5.2 Режимы работы центральной установки
|
||||
|
||||
Модуль автоматически определяет режим AC по текущей температуре воздуха в канале кондиционера, которую надо направить в /val:
|
||||
|
||||
```
|
||||
AC temp < 15°C → CMD_COOL (переоборудование в холод)
|
||||
15°C ≤ AC temp ≤ 30°C → CMD_FAN (вентиляция)
|
||||
AC temp > 30°C → CMD_HEAT (переоборудование в тепло)
|
||||
```
|
||||
|
||||
Если температура от AC не поступила (NaN), режим берётся из текущего режима AC (`mode`) (L228).
|
||||
|
||||
Важно: при обнаружении холода или тепла автоматичесуки активируются PID регуляторы зон. Их выходы направляются на вход блока балансировки зон. Таким образом, система ререходит в режим нагрева или охлаждения зон с контролем температуры. А прямое управление по входу /fan зон блокируется, (но последее переданное в зону значение запоминается). После того как система обнаруживает переход установки из режима нагрева либо охлаждения в режим вентиляции, она использует последнее полученное на вход /fan зоны значение для балансировки воздушного потока в каждую зону. И система переходит в режим вентиляции. В этом режиме, используются поступающие извне на вход /fan сигналы запросов воздуха в каждую зону (например, от PID регулятора уровня CO2)
|
||||
|
||||
### 5.3 PID-режимы
|
||||
|
||||
#### DIRECT (Kp > 0)
|
||||
- Выход растёт при увеличении отклонения (set > val)
|
||||
- Используется для режима HEAT
|
||||
|
||||
#### REVERSE (Kp < 0)
|
||||
- Выход растёт при уменьшении отклонения (set < val)
|
||||
- Используется для режима COOL
|
||||
|
||||
режим работы регуляторв переключается автоматически в зависимости от температуры воздуха в канале. При нагреве включается прямой режим. При охлаждении - обратный.
|
||||
|
||||
**Автоматическое переключение в режиме CMD_AUTO:**
|
||||
```
|
||||
AC в HEAT → PID в DIRECT
|
||||
AC в COOL → PID в REVERSE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Примеры конфигурации
|
||||
|
||||
### 6.1 Простая двухзональная система
|
||||
|
||||
**Сценарий**: кондиционер на два помещения, каждое с вентилятором и датчиком температуры.
|
||||
|
||||
```json
|
||||
{
|
||||
"mqtt": ["lh1", "192.168.1.10"],
|
||||
"topics": {"root": "home"},
|
||||
|
||||
"items": {
|
||||
"ac_multizone": [
|
||||
[18, 5],
|
||||
{
|
||||
"bedroom": {
|
||||
"fan": {"emit": "home/bedroom/fan"},
|
||||
"cmd": {"emit": "home/bedroom/cmd"},
|
||||
"out": {"emit": "home/bedroom/out"},
|
||||
"V": 40,
|
||||
"pid": [1.0, 0.05, 0.02, 5.0],
|
||||
"set": {"emit": "home/bedroom/setpoint"},
|
||||
"val": {"emit": "home/bedroom/temp"}
|
||||
},
|
||||
"living_room": {
|
||||
"fan": {"emit": "home/living/fan"},
|
||||
"cmd": {"emit": "home/living/cmd"},
|
||||
"out": {"emit": "home/living/out"},
|
||||
"V": 80,
|
||||
"pid": [1.0, 0.05, 0.02, 5.0],
|
||||
"set": {"emit": "home/living/setpoint"},
|
||||
"val": {"emit": "home/living/temp"}
|
||||
},
|
||||
"": {
|
||||
"val": {"emit": "home/ac/indoor_temp"},
|
||||
"mode": {"emit": "home/ac/mode"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 Трёхзональная система с разными объёмами
|
||||
|
||||
```json
|
||||
{
|
||||
"mqtt": ["lh2", "broker.local"],
|
||||
"topics": {"root": "climate"},
|
||||
|
||||
"items": {
|
||||
"ventilation": [
|
||||
[18, 5],
|
||||
{
|
||||
"zone_a": {
|
||||
"fan": {"emit": "climate/a/fan"},
|
||||
"cmd": {"emit": "climate/a/cmd"},
|
||||
"out": {"emit": "climate/a/out"},
|
||||
"V": 50,
|
||||
"pid": [-1.5, 0.08, 0.03, 5.0],
|
||||
"set": 22.0,
|
||||
"val": {"emit": "climate/a/temp"}
|
||||
},
|
||||
"zone_b": {
|
||||
"fan": {"emit": "climate/b/fan"},
|
||||
"cmd": {"emit": "climate/b/cmd"},
|
||||
"out": {"emit": "climate/b/out"},
|
||||
"V": 100,
|
||||
"pid": [-1.5, 0.08, 0.03, 5.0],
|
||||
"set": 24.0,
|
||||
"val": {"emit": "climate/b/temp"}
|
||||
},
|
||||
"zone_c": {
|
||||
"fan": {"emit": "climate/c/fan"},
|
||||
"cmd": {"emit": "climate/c/cmd"},
|
||||
"out": {"emit": "climate/c/out"},
|
||||
"V": 30,
|
||||
"pid": [-1.5, 0.08, 0.03, 5.0],
|
||||
"set": 20.0,
|
||||
"val": {"emit": "climate/c/temp"}
|
||||
},
|
||||
"": {
|
||||
"val": {"emit": "climate/central/temp"},
|
||||
"mode": {"emit": "climate/central/mode"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.3 Система с каскадным управлением задвижками
|
||||
|
||||
```json
|
||||
"zone_main": {
|
||||
"fan": {"emit": "hvac/main/fan"},
|
||||
"cmd": {"emit": "hvac/main/cmd"},
|
||||
"out": {"emit": "hvac/main/out"},
|
||||
"V": 60,
|
||||
"pid": [0.8, 0.04, 0.01, 5.0],
|
||||
"set": {"emit": "hvac/main/setpoint"},
|
||||
"val": {"emit": "hvac/main/temp"},
|
||||
"cas": {
|
||||
"emit": "hvac/main/damper_cmd"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.4 Реальная система: Haier с четырьмя зонами
|
||||
|
||||
**Сценарий**: кондиционер Haier с управлением через Modbus, 4 комнаты с независимыми задвижками и датчиками 1-Wire.
|
||||
|
||||
```json
|
||||
{
|
||||
"mqtt": ["ac", "192.168.1.4"],
|
||||
"syslog": ["192.168.1.4"],
|
||||
"topics": {"root": "home"},
|
||||
|
||||
"ow": {
|
||||
"283A3F81E3503CC8": {"emit": "t_ac2", "item": "vac"},
|
||||
"286C3381E3823CBC": {"emit": "t_zal", "item": "vac/zal"},
|
||||
"28B41581E3563CDE": {"emit": "t_bedr21", "item": "vac/bedr21"},
|
||||
"28C1A581E3563C2D": {"emit": "t_bedr22", "item": "vac/bedr22"}
|
||||
},
|
||||
|
||||
"modbus": {
|
||||
"haier": {
|
||||
"baud": 9600,
|
||||
"serial": "8N1",
|
||||
"poll": {
|
||||
"regs": [[0, 3]],
|
||||
"irs": [[0, 1]],
|
||||
"coils": [0],
|
||||
"delay": 10000
|
||||
},
|
||||
"par": {
|
||||
"pwr": {
|
||||
"coil": 0,
|
||||
"map": {"cmd": [1, ["OFF", 0]], "val": null, "def": "acmode"},
|
||||
"id": 1
|
||||
},
|
||||
"acmode": {
|
||||
"reg": 1,
|
||||
"map": {
|
||||
"cmd": [
|
||||
["FAN_ONLY", 4],
|
||||
["HEAT", 2],
|
||||
["COOL", 1],
|
||||
["DRY", 3],
|
||||
["AUTO", 5]
|
||||
],
|
||||
"val": null
|
||||
},
|
||||
"id": 1
|
||||
},
|
||||
"$temp": {"ir": 0},
|
||||
"set": {"reg": 0, "id": 2},
|
||||
"fan": {
|
||||
"reg": 2,
|
||||
"id": 7,
|
||||
"map": {
|
||||
"cmd": [
|
||||
["LOW", 1],
|
||||
["HIGH", 3],
|
||||
["MEDIUM", 2],
|
||||
["AUTO", 4]
|
||||
],
|
||||
"val": [1, 255, 1, 3]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"items": {
|
||||
"ac_2": [
|
||||
14,
|
||||
[
|
||||
"haier",
|
||||
{
|
||||
"pwr": {"emit": "home/ac/cmd", "item": "vac/mode", "@V": null},
|
||||
"$temp": {"emit": "home/ac/temp", "item": "vac/temp", "@S": null},
|
||||
"set": {"emit": "home/ac/setpoint", "item": "vac/set"},
|
||||
"acmode": {"emit": "home/ac/mode", "@V": null},
|
||||
"fan": {"emit": "home/ac/fan", "@V": null}
|
||||
}
|
||||
]
|
||||
],
|
||||
|
||||
"vac": [
|
||||
[18, 5],
|
||||
{
|
||||
"": {"item": "ac_2"},
|
||||
"zal": {
|
||||
"pid": [490, 100, 9879, 40],
|
||||
"set": 21.0,
|
||||
"fan": 0,
|
||||
"cmd": 14,
|
||||
"item": "acgzal/set"
|
||||
},
|
||||
"bedr21": {
|
||||
"pid": [490, 100, 9879, 40],
|
||||
"set": 21.0,
|
||||
"fan": 0,
|
||||
"cmd": 14,
|
||||
"item": "acgbedr21/set"
|
||||
},
|
||||
"bedr22": {
|
||||
"pid": [490, 100, 9879, 40],
|
||||
"set": 21.0,
|
||||
"fan": 0,
|
||||
"cmd": 14,
|
||||
"item": "acgbedr22/set"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"acgzal": [7, ["ig2", "og1"]],
|
||||
"acgbedr22": [7, ["ig1", "og2"]],
|
||||
"acgbedr21": [7, ["ig4", "og3"]],
|
||||
|
||||
"og1": [12, [4, 33, 58, 629, 289, 5000]],
|
||||
"og2": [12, [5, 32, 59, 631, 296, 5000]],
|
||||
"og3": [12, [6, 31, 60, 627, 289, 5000]],
|
||||
|
||||
"ig1": [12, [8, 29, 62, 623, 286, 5000]],
|
||||
"ig2": [12, [7, 30, 63, 634, 296, 5000]],
|
||||
"ig4": [12, [11, 27, 65, 620, 289, 5000]]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Пояснение примера:**
|
||||
|
||||
- **AC (ac_2)**: контроллер Haier, управляется через Modbus (скорость 9600, опрос каждые 10 сек)
|
||||
- **Зоны** (zal, bedr21, bedr22): каждая имеет PID [490, 100, 9879, 40] — агрессивные коэффициенты для точного контроля
|
||||
- **1-Wire датчики**: подключены четыре датчика температуры
|
||||
- **Задвижки**: управляются через цифровые выходы (og1-og3) с припасовкой через item [12, ...]
|
||||
- **Входы**: чтение датчиков через item [12, ...] для каждой зоны
|
||||
|
||||
---
|
||||
|
||||
## 7. Протокол управления через MQTT
|
||||
|
||||
### 7.1 Отправка значений на контроллер
|
||||
|
||||
#### Установка команды для зоны
|
||||
```
|
||||
Публикуй в: home/bedroom/cmd
|
||||
Сообщение: 1 (CMD_ON)
|
||||
```
|
||||
|
||||
#### Установка процента вентилятора
|
||||
```
|
||||
Публикуй в: home/bedroom/fan
|
||||
Сообщение: 128
|
||||
```
|
||||
|
||||
#### Установка требуемой температуры
|
||||
```
|
||||
Публикуй в: home/bedroom/setpoint
|
||||
Сообщение: 22.5
|
||||
```
|
||||
|
||||
#### Установка текущей температуры (от датчика)
|
||||
```
|
||||
Публикуй в: home/bedroom/temp
|
||||
Сообщение: 21.8
|
||||
```
|
||||
|
||||
### 7.2 Получение значений от контроллера
|
||||
|
||||
#### Выходной сигнал задвижки
|
||||
```
|
||||
Подпишись на: home/bedroom/out
|
||||
Значение: 0—255 (0=закрыто, 255=открыто)
|
||||
```
|
||||
|
||||
#### Режим работы центральной установки
|
||||
```
|
||||
Подпишись на: home/ac/mode
|
||||
Значения: коды команд из itemCmd.h — ON=1, OFF=2, FAN_ONLY=15, HEAT=20, COOL=21; фактические значения в топике зависят от modbus-мапы (пример §6.4: HEAT=2, COOL=1, FAN_ONLY=4, DRY=3, AUTO=5)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Алгоритм балансировки воздушного потока
|
||||
|
||||
### 8.1 Принцип работы
|
||||
|
||||
Модуль обеспечивает **пропорциональное распределение** воздуха между зонами в зависимости от их требований.
|
||||
|
||||
### 8.2 Пример расчёта
|
||||
|
||||
**Исходные данные:**
|
||||
- Зона 1: V=40 м³/ч, fan=100%, po=200 → требуемый поток = 40×100% = 40
|
||||
- Зона 2: V=80 м³/ч, fan=80%, po=180 → требуемый поток = 80×80% = 64
|
||||
- Макс требуемый поток: 64 (зона 2)
|
||||
|
||||
**Расчёт выходов:**
|
||||
- Зона 1: $out_1 = \frac{40 \times 255 \times 80}{40 \times 80} = 255$
|
||||
- Зона 2: $out_2 = \frac{64 \times 255 \times 80}{80 \times 80} = 204$
|
||||
|
||||
**Результат:**
|
||||
- Зона 1: открыта на 255 (100%)
|
||||
- Зона 2: открыта на 204 (80%)
|
||||
|
||||
---
|
||||
|
||||
## 9. Специальные параметры и флаги
|
||||
|
||||
### 9.1 Служебные поля
|
||||
|
||||
```json
|
||||
"@lastCmd": -1, // Последняя отправленная AC команда
|
||||
"roomtemp": 0.0, // Дополнительный датчик комнаты (не читается — S_TEMP закомментирован)
|
||||
"po": -2.0, // Выход PID (внутренне)
|
||||
"fan_in": 0, // Последнее внешнее значение /fan, восстанавливается после выхода из пассивного режима (L667)
|
||||
"@pasv": 0, // Флаг пассивного режима зоны (L284)
|
||||
"@precmd": 15, // Предыдущий режим зоны до OFF, восстанавливается при ON (L723, L736)
|
||||
"@preHaltcmd": 0 // Команда зоны до глобального останова (stopAllzones), восстанавливается при повторном включении AC (L177, L196)
|
||||
```
|
||||
|
||||
### 9.2 Таймаут неактивности
|
||||
|
||||
Если текущая температура от AC не обновлялась 60 секунд, модуль очищает её.
|
||||
|
||||
---
|
||||
|
||||
## 10. Интеграция с внешними системами
|
||||
|
||||
### 10.1 Подключение задвижек
|
||||
|
||||
```json
|
||||
"zone_name": {
|
||||
"out": {
|
||||
"emit": "building/room1/damper_position"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Затем в другом item'е (например, цифровой выход):
|
||||
|
||||
```json
|
||||
"damper": [
|
||||
3,
|
||||
["GPIO_PIN_5", {"emit": "building/room1/damper_position"}]
|
||||
]
|
||||
```
|
||||
|
||||
### 10.2 Подключение датчиков температуры
|
||||
|
||||
```json
|
||||
"zone_name": {
|
||||
"val": {
|
||||
"emit": "sensors/room1/temperature"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 10.3 Управление центральным AC через Modbus
|
||||
|
||||
```json
|
||||
"": {
|
||||
"val": {
|
||||
"emit": "ac_unit/room_temp"
|
||||
},
|
||||
"mode": {
|
||||
"emit": "ac_unit/operation_mode"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. Рекомендации по эксплуатации
|
||||
|
||||
### 11.1 Настройка PID-контроллеров
|
||||
|
||||
1. **Начальные значения:** Kp=1.0, Ki=0.05, Kd=0.02, dT=5сек
|
||||
2. **Тестирование:** постепенно увеличивайте Kp до появления колебаний
|
||||
3. **Стабилизация:** добавляйте Ki для устранения постоянного смещения
|
||||
4. **Демпфирование:** добавляйте Kd для снижения колебаний
|
||||
|
||||
### 11.2 Распределение объёмов (V)
|
||||
|
||||
- Убедитесь, что сумма V соответствует производительности центральной установки
|
||||
- Для равномерного распределения: V ≈ площадь помещения
|
||||
- Для приоритизации: увеличьте V критичным зонам
|
||||
|
||||
### 11.3 Мониторинг системы
|
||||
|
||||
- Отслеживайте `balance` в логах (должен быть близко к нулю в установившемся режиме)
|
||||
- Проверяйте `out` для каждой зоны (не должны быть постоянно на 0 или 255)
|
||||
- Контролируйте переходы режимов (HEAT↔COOL) — не должны быть частыми
|
||||
|
||||
### 11.4 Диагностика проблем
|
||||
|
||||
| Проблема | Причина | Решение |
|
||||
|----------|---------|---------|
|
||||
| Задвижки не реагируют | `out` зоны = 0 | Повысить fan или cmd |
|
||||
| Колебания температуры | PID слишком агрессивен | Снизить Kp |
|
||||
| Не достигается setpoint | PID недостаточен | Увеличить Ki |
|
||||
| AC часто переключается | balance скачет | Увеличить dT в PID |
|
||||
|
||||
---
|
||||
|
||||
## 12. Ограничения и известные особенности
|
||||
|
||||
⚠️ **Важно:**
|
||||
|
||||
1. **Автономный dT:** у каждого PID-регулятора зон свой период сэмплирования dT (L69), задаётся отдельно для каждой зоны через SetSampleTime (L75)
|
||||
2. **Порядок обработки:** сначала зоны, потом центральная установка
|
||||
3. **Гистерезис режимов:** автоматическое переключение AC может быть медленным (до 60 сек при отсутствии данных)
|
||||
4. **Отсутствие истории:** модуль не сохраняет историю команд между перезагрузками
|
||||
|
||||
---
|
||||
|
||||
## 13. Заключение
|
||||
|
||||
Модуль `out_Multivent` предоставляет **промышленную-grade** решение для управления многозональными системами климатизации.
|
||||
|
||||
Ключевые преимущества:
|
||||
|
||||
- ✅ Интеллектуальная балансировка воздушного потока
|
||||
- ✅ Независимое PID-регулирование для каждой зоны
|
||||
- ✅ Автоматическая агрегация команд
|
||||
- ✅ Каскадное управление внешними системами
|
||||
|
||||
---
|
||||
|
||||
**Версия документа:** 1.0
|
||||
**Дата:** 2026-01-21
|
||||
**Статус:** Утверждено
|
||||
Reference in New Issue
Block a user