Multi - AC (betta) and some AI generated docs (not fully verefied)

This commit is contained in:
2026-03-01 23:43:40 +03:00
parent 8db9e551ff
commit c5427251fc
32 changed files with 9688 additions and 90 deletions

View File

@@ -0,0 +1,723 @@
# LightHub: Модули управления и конфигурация
> Описание реальных параметров модулей, загружаемых кодом.
> Основано исключительно на анализе исходных файлов C++.
---
## Типы модулей (numbers в JSON)
| Type | Модуль | Класс | Описание |
|------|--------|-------|---------|
| 1 | Реле | out_relay | Управление электромагнитным реле |
| 3 | Мотор | out_Motor | Управление моторами с обратной связью |
| 6 | Счётчик | out_counter | Счётчик импульсов |
| 9 | PWM | out_pwm | Широтно-импульсная модуляция |
| 10 | SPI LED | out_SPILed | Адресуемые светодиоды WS2812/APA102 |
| 11 | DMX | out_dmx | DMX512 управление освещением |
| 14 | Multivent | out_Multivent | Многоканальный кондиционер/вентиляция |
| 17 | PID | out_pid | PID-регулятор |
| 20 | Счётчик v2 | out_counter | Счётчик (улучшенная версия) |
| 21 | Увлажнитель | out_humidifier | Форсуночное увлажнение |
| 22 | Меркурий | out_Mercury | Счётчик электроэнергии Меркурий |
| 50 | Лифт | out_Elevator | Управление лифтом (UART) |
| 55 | UART Bridge | out_UARTbridge | UART-мост между портами |
| 128 | AC | out_AC | Управление кондиционером |
| MBUS | Modbus | out_Modbus | Modbus устройства (general) |
---
## 1. out_counter — Счётчик импульсов
### Конфигурация (Type 20)
```json
"pumpctr": [20, [0.02, 1.2]],
"gasctr": [20, 0]
```
### Параметры массива
| Индекс | Тип | Описание | Пример |
|--------|-----|---------|--------|
| [0] | float | Импульс (накопление за период) | 0.02 л/импульс |
| [1] | float | Период накопления (сек) | 1.2 сек |
### Логика работы
1. Модуль ждёт команду (S_SET или любой CMD)
2. При получении команды с процентом > 0 запускается таймер
3. По истечении периода [1] добавляется значение [0] * TENS_BASE
4. Считанное значение публикуется в MQTT
### Пример использования
```json
{
"items": {
"water_meter": [20, [0.01, 5.0]],
"gas_meter": [20, [0.1, 10.0]]
}
}
```
---
## 2. out_relay — Электромагнитное реле
### Конфигурация
```json
"pump": [1, [pin, period]]
```
### Параметры
| Индекс | Тип | Описание | Диапазон |
|--------|-----|---------|----------|
| [0] | int | GPIO пин (отрицательное = инвертировать) | 0-54 |
| [1] | float | Период (мс) | любой > 0 |
### Логика
- HIGH (или LOW если инвертировано) = ON
- LOW (или HIGH если инвертировано) = OFF
- Если pin < 0, используется инверсия логики
### Примеры
```json
"relay_normal": [1, [33]],
"relay_inverted": [1, [-33]],
"relay_with_period": [1, [32, 5000]]
```
---
## 3. out_Motor — Управление моторами
### Конфигурация
```json
"roller_blind": [3, [pinUp, pinDown, pinFeedback, feedbackOpen, feedbackClosed, maxOnTime]]
```
### Параметры
| Индекс | Тип | Описание | Диапазон | Значение по умолч. |
|--------|-----|---------|----------|-------------------|
| [0] | int | GPIO пин UP (отрицательное = инвертировать) | 0-54 | 32 |
| [1] | int | GPIO пин DOWN | 0-54 | 33 |
| [2] | int | GPIO пин обратной связи (аналоговый) | 0-54 | 0 |
| [3] | int | Значение обратной связи (открыто) | 0-1024 | 0 |
| [4] | int | Значение обратной связи (закрыто) | 0-1024 | 1024 |
| [5] | int | Максимальное время движения (мс) | > 0 | 10000 |
### Логика работы
1. Модуль сравнивает **targetPos** (из команды 0-255) с **curPos** (из обратной связи)
2. Если разница > POS_ERR (10):
- Если targetPos < curPos движение вниз (pinDown)
- Если targetPos > curPos → движение вверх (pinUp)
3. При достижении targetPos или maxOnTime мотор останавливается
4. Защита от перегрузки: одновременно работают макс. MOTOR_QUOTE моторов (обычно 2)
### Примеры
```json
"blind_motor": [3, [32, 33, 36, 0, 1023, 120000]],
"gate_motor": [3, [-10, -11, 12, 100, 900, 60000]]
```
### Управление
```
Команда: CMD_ON → движение вверх до конца
Команда: CMD_OFF → движение вниз до конца
Значение 0-255 → позиция (0=полностью открыто, 255=полностью закрыто)
```
---
## 4. out_PID — PID-регулятор
### Конфигурация
```json
"heater": [17, [
[Kp, Ki, Kd, dT, alarmTO, alarmVal, outMin, outMax],
{"in": {...}, "set": 22.0, "out": {...}}
]]
```
### Параметры массива [0]
| Индекс | Тип | Описание | Обязательный |
|--------|-----|---------|-------------|
| [0] | float | Kp (пропорциональный) | ✓ |
| [1] | float | Ki (интегральный) | ✓ |
| [2] | float | Kd (дифференциальный) | ✓ |
| [3] | float | dT (период сэмплирования, сек) | опционально (5 по умолч.) |
| [4] | int | Timeout будильника (сек) | опционально |
| [5] | float | Порог будильника | опционально |
| [6] | float | Минимум выхода | опционально |
| [7] | float | Максимум выхода | опционально |
### Логика
- **Kp < 0** режим REVERSE (для охлаждения)
- **Kp > 0** → режим DIRECT (для нагрева)
- Выход ограничивается [outMin, outMax]
- dT = период опроса в секундах
### Примеры
```json
"room_temperature": [
17,
[
[1.0, 0.05, 0.02, 5.0],
{
"in": {"emit": "sensors/room/temp"},
"set": 21.5,
"out": {"emit": "hvac/heating"}
}
]
]
```
---
## 5. out_PWM — ШИМ управление
### Конфигурация
```json
"led_brightness": [9, [channel, freq, {}]]
```
### Параметры
| Индекс | Тип | Описание |
|--------|-----|---------|
| [0] | int | Канал / GPIO пин |
| [1] | int | Частота PWM (Hz) |
### Примеры
```json
"pwm_led": [9, [5, 1000]],
"pwm_fan": [9, [6, 500]]
```
---
## 6. out_relay (Type 1) — детально
### Загружаемые параметры (getConfig)
```cpp
pin = item->getArg(0); // основной параметр
if (pin < 0) {
pin = -pin;
inverted = true; // инвертировать логику
}
period = item->getFloatArg(1) * 1000.0; // период в мс
if (!period) period = 5000UL; // по умолчанию 5 сек
```
**Вывод**: модуль загружает ровно 2 параметра
---
## 7. out_counter (Type 20) — детально
### Загружаемые параметры (Poll)
```cpp
uint32_t impulse = item->getFloatArg(0) * TENS_BASE; // [0]
uint32_t period = item->getFloatArg(1) * 1000.0; // [1] в мс
```
**Логика**:
1. Модуль ждёт активации (getExt() = 0)
2. При получении команды ON/HEAT/COOL/etc запускает таймер
3. По истечении period добавляет impulse к накопленному значению
4. Публикует обновлённое значение
---
## 8. out_Motor (Type 3) — детально
### Загружаемые параметры (getConfig)
```cpp
pinUp = item->getArg(0); // [0]
pinDown = item->getArg(1); // [1]
pinFeedback = item->getArg(2); // [2]
feedbackOpen = item->getArg(3); // [3]
feedbackClosed = item->getArg(4); // [4]
maxOnTime = item->getArg(5); // [5], по умолчанию 10000 мс
```
### Обработка отрицательных значений
```cpp
if (pinUp < 0) {
pinUp = -pinUp;
inverted = true;
}
if (pinDown < 0) {
pinDown = -pinDown;
inverted = true;
}
```
---
## 9. out_PID (Type 17) — детально
### Загружаемые параметры (getConfig)
```cpp
aJsonObject * kPIDObj = aJson.getArrayItem(item->itemArg, 0);
// Обрабатывает случаи от 1 до 8 элементов:
// [Kp]
// [Kp, Ki]
// [Kp, Ki, Kd]
// [Kp, Ki, Kd, dT]
// [Kp, Ki, Kd, dT, alarmTO]
// [Kp, Ki, Kd, dT, alarmTO, alarmVal]
// [Kp, Ki, Kd, dT, alarmTO, alarmVal, outMin]
// [Kp, Ki, Kd, dT, alarmTO, alarmVal, outMin, outMax]
if (kP < 0) {
kP = -kP;
direction = REVERSE; // Отрицательный Kp = режим REVERSE
}
```
### Использование вторых параметров
```cpp
store->setpoint = item->itemVal->valuefloat; // Установка из JSON value
```
---
## 11. out_humidifier (Type 21) — Форсуночное увлажнение
### Конфигурация
```json
"hum": [21, [
[pumpPin, flushPin, pressurePin, maxPumpTime, idleTime, capacity, minLevel, startLevel],
{
"zone1": {"N": 1, "pin": 24},
"zone2": {"N": 2, "pin": 33}
},
{"item": "pumpctr"},
255,
2
]]
```
### Параметры конфигурации [0] (массив переменной длины)
| Индекс | Тип | Описание | По умолч. | Обязателен |
|--------|-----|---------|----------|-----------|
| [0] | int | GPIO пин насоса (отрицательное = инвертировать) | 22 | ✓ |
| [1] | int | GPIO пин очистки (отрицательное = инвертировать) | 23 | опционально |
| [2] | int | GPIO пин датчика давления (аналоговый) | 54 | опционально |
| [3] | int | Макс. время работы насоса (сек) | 255 | опционально |
| [4] | int | Время ожидания между циклами (мс) | 2500 | опционально |
| [5] | int | Максимум одновременно открытых форсунок | 4 | опционально |
| [6] | int | Минимальный уровень (%) для включения форсунки | 10 | опционально |
| [7] | int | Пороговый уровень для запуска цикла (%) | 20 | опционально |
### Параметры зон (объект)
Каждая зона — это объект с полями:
```json
"zone_name": {
"N": 1, // номер зоны для балансировки нагрузки
"pin": 24 // GPIO пин электромагнитного клапана форсунки
}
```
| Поле | Тип | Описание |
|------|-----|---------|
| `N` | int | Номер группы (1-4) для ограничения одновременно открытых клапанов |
| `pin` | int | GPIO пин клапана (отрицательное = инвертировать логику) |
| `set` | float | Требуемый уровень влажности (создаётся автоматически) |
| `cmd` | int | Статус команды (создаётся автоматически) |
### Счётчик импульсов
```json
{"item": "pumpctr"} // привязка к счётчику для контроля расхода
```
### Пороги и состояния
Из кода определены константы:
```
PREPARATION_TIME = 10000 мс // подготовка к пуску
PRESSURE_ACHIEVING_TIME = 8000 мс // время достижения давления
MIN_KEEP_TIME = 2500 мс // минимальное время работы форсунки
FLUSH_PRESSURE = 200 // давление очистки
FLUSH_TIMEOUT = 125000 мс // таймаут очистки
MIN_OPERATION_PRESSURE = 400 // минимальное рабочее давление
MAX_OPERATION_PRESSURE = 600 // максимальное рабочее давление
```
### Состояния модуля
| Состояние | Код | Описание |
|-----------|-----|---------|
| H_UNKNOWN | 0 | Неизвестное состояние |
| H_READY | 1 | Готов к работе |
| H_PREPARE_FOR_START | 2 | Подготовка к пуску |
| H_PREPARE_VALVES | 3 | Открытие форсунок |
| H_MOTOR_ON | 4 | Включение насоса |
| H_OPERATE | 5 | В режиме увлажнения |
| H_MOTOR_PAUSE | 6 | Пауза насоса |
| H_MOTOR_OFF | 7 | Выключение насоса |
| H_MOTOR_OFF_OK | 10 | Насос остановлен |
| H_FLUSH | 8 | Промывка системы |
| H_IDLE | 9 | Ожидание |
| H_FAULT_PRESSURE | -1 | Ошибка давления |
| H_FAULT_PRESSURE_KEEP | -2 | Потеря давления во время работы |
| H_FAULT_OVERPRESSURE | -3 | Перепад давления |
| H_FAULT_MOTOR_OFF | -4 | Отказ насоса |
### Логика работы
1. **Инициализация**: модуль ждёт команду включения или когда уровень влажности > startLevel
2. **Подготовка**: открывает клапаны форсунок, ждёт достижения давления
3. **Работа**: включает насос, поддерживает давление в диапазоне [MIN_OPERATION_PRESSURE, MAX_OPERATION_PRESSURE]
4. **Балансировка**: одновременно открыто не более `capacity` форсунок из группы `N`
5. **Очистка**: периодическая промывка при давлении FLUSH_PRESSURE
6. **Контроль**: отключение при падении давления ниже MIN_OPERATION_PRESSURE
### Примеры конфигурации
#### Простая система увлажнения
```json
{
"items": {
"humidifier": [21, [
[22, 23, 54, 255, 2500, 4, 10, 20],
{
"bedroom": {"N": 1, "pin": 24},
"living": {"N": 2, "pin": 25}
},
{"item": "waterctr"}
]]
}
}
```
#### Многозональная система (из официального примера)
```json
{
"items": {
"hum": [21, [
[22, 15, 30, 4, 10, 20],
{
"bedr1": {"N": 1, "pin": 24},
"ktc1": {"N": 1, "pin": 25},
"dinner1": {"N": 1, "pin": 9},
"bedr2m": {"N": 1, "pin": 8},
"bedr21": {"N": 1, "pin": 11},
"bedr22": {"N": 1, "pin": 12},
"zal2": {"N": 2, "pin": 33},
"cab3": {"N": 1, "pin": 32},
"zal3": {"N": 4, "pin": 31},
"bedr3": {"N": 1, "pin": 30}
},
{"item": "pumpctr"},
255,
2
]]
}
}
```
---
## 12. out_Mercury (Type 22) — Счётчик электроэнергии
### Конфигурация
```json
"merc": [22, [
0, // [0] адрес Modbus (обычно на выходе item)
9600, // [1] скорость UART (baud)
"8N1", // [2] параметры кадра
2, // [3] уровень доступа
[2,2,2,2,2,2], // [4] пароль (массив из 6 чисел)
10000, // [5] период опроса (мс)
{} // [6] параметры (обычно пусто)
]]
```
### Параметры массива
| Индекс | Тип | Назначение |
|--------|-----|-----------|
| [0] | int | Адрес устройства (из item->getArg(0)) |
| [1] | int | Скорость UART |
| [2] | string | Параметры (8N1, 8E1, 8O1) |
| [3] | int | Уровень доступа (обычно 2) |
| [4] | array/string | Пароль (6 символов или массив 6 чисел) |
| [5] | int | Интервал опроса (мс) |
| [6] | object | Дополнительные параметры |
### Примеры
```json
"electricity_meter": [22, [
1,
9600,
"8N1",
2,
[0x01, 0x02, 0x03, 0x04, 0x05, 0x06],
60000,
{}
]]
```
---
## 13. out_AC (Type 128) — Управление кондиционером
### Конфигурация
```json
"ac": [128, [
portNum, // [0] номер UART порта (опционально)
{parameters} // параметры управления
]]
```
### Загружаемые параметры
```cpp
portNum = item->getArg(0); // 0=Serial, 1=Serial1, 2=Serial2, 3=Serial3
```
### Поддерживаемые команды
Модуль работает с 37-байтовым протоколом:
| Байт | Назначение |
|------|-----------|
| 13 | Текущая температура |
| 17 | Статус команды |
| 23 | Режим (04=DRY, 01=COOL, 02=HEAT, 00=AUTO, 03=FAN) |
| 25 | Скорость вентилятора |
| 27 | SWING |
| 28 | Блокировка пульта |
| 29 | Питание |
| 31 | Fresh |
| 35 | Установка температуры |
---
## 14. out_Modbus (тип MBUS) — Modbus устройства
### Конфигурация общая
```json
"modbus": {
"device_name": {
"baud": 9600,
"serial": "8N1",
"poll": {
"regs": [[0, 40], [100, 20]],
"irs": [[0, 10]],
"coils": [0, 1],
"dins": [0],
"delay": 5000
},
"par": {
"parameter_name": {
"reg": 0,
"type": "i16",
"id": 1,
"map": {}
}
}
}
}
```
### Items использование Modbus
```json
"device_instance": [14, [
"device_name",
{
"power": {"emit": "home/ac/power"},
"temp": {"emit": "home/ac/temp"}
}
]]
```
### Загружаемые параметры
```cpp
// From template:
baud = baudObj->valueint; // скорость (по умолчанию 9600)
serialParam = str2SerialParam(...); // формат (по умолчанию 8N1)
// Poll strategy:
pollingRegisters = aJson.getObjectItem(pollObj, "regs"); // блоки Holding Reg
pollingIrs = aJson.getObjectItem(pollObj, "irs"); // Input Reg
pollingCoils = aJson.getObjectItem(pollObj, "coils"); // Coil Reg
poolingDiscreteIns = aJson.getObjectItem(pollObj, "dins"); // Discrete In
pollingInterval = delayObj->valueint; // по умолчанию 1000 мс
```
### Типы данных в параметрах
| type | Описание |
|------|---------|
| i16 | int16 |
| i32 | int32 |
| u16 | uint16 |
| u32 | uint32 |
| i8h | старший байт |
| i8l | младший байт |
| u8h | старший байт unsigned |
| u8l | младший байт unsigned |
| x10 | умножить на 10 |
| 100 | умножить на 100 |
### Параметры в "par"
```json
"parameter": {
"reg": 0, // Holding Register номер
"ir": 0, // Input Register номер
"coil": 0, // Coil номер
"type": "i16", // тип данных
"id": 1, // ID команды
"map": { // маппинг значений
"cmd": [["OFF",0], ["ON",1]],
"val": null,
"def": "acmode"
}
}
```
---
## 15. out_Multivent (Type 14) — Многоканальный кондиционер
### Конфигурация
```json
"vac": [14, [
"haier", // имя шаблона Modbus
{
"": { // центральная установка
"val": {"emit": "home/ac/temp"},
"mode": {"emit": "home/ac/mode"}
},
"zone1": { // зона 1
"pid": [490, 100, 9879, 40],
"set": 21.0,
"fan": 0,
"cmd": 14,
"item": "ac_zone1/set"
}
}
]]
```
### Параметры зоны
| Параметр | Тип | Описание |
|----------|-----|---------|
| `pid` | [Kp, Ki, Kd, dT] | Коэффициенты PID |
| `set` | float | Требуемая температура |
| `fan` | int (0-255) | Текущий процент открытия |
| `cmd` | int | Текущая команда |
| `item` | string | Привязка к другому item |
| `V` | int | Номинальный объём (для балансировки) |
---
## Практические примеры конфигурации
### Система со счётчиками
```json
{
"items": {
"pumpctr": [20, [0.02, 1.2]],
"gasctr": [20, 0.1],
"waterctr": [20, 0]
},
"in": [
{"#": 41, "item": "waterctr/set", "scmd": "%0.01", "rcmd": ""},
{"#": 39, "item": "gasctr/set", "scmd": "%0.1", "rcmd": ""}
]
}
```
### Система с реле и мотором
```json
{
"items": {
"pump": [1, [33]],
"blind": [3, [32, 33, 36, 0, 1023, 120000]]
}
}
```
### PID регулятор
```json
{
"items": {
"heater": [17, [
[1.0, 0.05, 0.02, 5.0],
{
"in": {"emit": "sensors/temp"},
"set": 22.0,
"out": {"emit": "heating/power"}
}
]]
}
}
```
---
## Ключевые правила конфигурации
1. **Инверсия логики**: отрицательное значение пина = инвертировать логику
2. **Единицы времени**:
- counter/relay: float конвертируется в миллисекунды (* 1000)
- mercury: миллисекунды напрямую
3. **Параметры по умолчанию**:
- relay period = 5000 мс
- motor maxOnTime = 10000 мс
- modbus baud = 9600
- modbus polling = 1000 мс
4. **Массивы переменной длины**: PID и Mercury поддерживают опциональные параметры
---
**Документ основан на анализе C++ кода без домыслов**
**Версия: 1.0**
**Дата: 2026-01-21**
1. * 1.