- Introduced multivent ventilation configuration for managing multiple zones. - Added PID heating batteries configuration for temperature control. - Created relay GPIO switch configuration for controlling relays. - Implemented RGBW LED strip configuration for lighting control. - Added Modbus CO2 sensor configuration for environmental monitoring. - Introduced Sonoff S26 humidity controller example for humidity management. - Created sprinkler irrigation configuration for garden management. - Added thermostat on/off relay configuration for heating and cooling control. - Implemented ventilation fan monitoring configuration for performance tracking. - Added core concepts documentation for LightHub, detailing items, commands, and execution objects.
26 KiB
LightHub: Модули управления и конфигурация
Описание реальных параметров модулей, загружаемых кодом. Основано исключительно на анализе исходных файлов C++.
Типы модулей (numbers в JSON)
| Type | Модуль | Класс | Описание |
|---|---|---|---|
| 0 | DMX | out_dmx | DMX512 управление освещением |
| 3 | PWM | out_pwm | Широтно-импульсная модуляция |
| 4 | Modbus Dimmer | out_Modbus | AC-диммер через Modbus RTU (legacy) |
| 6 | Реле | out_relay | Управление электромагнитным реле |
| 10 | AC | out_AC | Управление кондиционером (Haier, UART) |
| 11 | SPI LED | out_SPILed | Адресуемые светодиоды WS2812/APA102 |
| 12 | Мотор | out_Motor | Управление моторами с обратной связью |
| 13 | PID | out_pid | PID-регулятор |
| 14 | Modbus | out_Modbus | Modbus устройства (general) |
| 15 | UART Bridge | out_UARTbridge | UART-мост между портами |
| 16 | RELAYX | out_relay | Медленный PWM через реле |
| 18 | Multivent | out_Multivent | Многозональная вентиляция |
| 19 | Лифт | out_Elevator | Управление лифтом (UART) |
| 20 | Счётчик | out_counter | Счётчик импульсов |
| 21 | Увлажнитель | out_humidifier | Форсуночное увлажнение |
| 22 | Меркурий | out_Mercury | Счётчик электроэнергии Меркурий |
| 23 | Полив | out_sprinkler | Система полива |
1. out_counter — Счётчик
Конфигурация (Type 20)
"pumpctr": [20, [0.02, 1.2]], // режим 2: автоинкремент (моторчасы)
"gasctr": [20, 0] // режим 1: внешние импульсы (газ)
Два режима работы
Режим 1 — внешние импульсы ([20], [20, вес] или [20, 0]):
канал держит показание, вход контроллера добавляет к нему вес импульса
командой %X в /set:
"waterctr": [20, 0],
...
"in": {
"41": { "item": "waterctr/set", "scmd": "%0.01", "rcmd": "" }
}
Режим 2 — автоинкремент старт-стоп ([20, [импульс, период_сек]]):
команды ON/OFF стартуют/останавливают таймер, каждые период
секунд добавляется импульс. Типичное применение — наработка
оборудования; старт/стоп привязывается через execObj (например,
motorExecObj увлажнителя вызывает {"item": "pumpctr"} с ON/OFF
при включении/выключении насоса).
Параметры массива (режим 2)
| Индекс | Тип | Описание | Пример |
|---|---|---|---|
| [0] | float | Импульс — приращение за период | 0.02 (1 «минута» моторчасов) |
| [1] | float | Период накопления (сек) | 1.2 сек |
Логика работы (по коду, out_counter.cpp)
ON-подобная команда (ON,HEAT,COOL,AUTO,FAN,DRY,HEATCOOL) или ненулевое/setзапускают таймер (I_EXT= метка времени);OFFили/set 0останавливают- По истечении периода к значению канала (I_VAL, хранится в «десятых»)
добавляется
импульс × 100 - Обновлённое значение публикуется в MQTT (
/set)
Пример (реальная конфигурация, контроллер air)
{
"items": {
"hum": [21, [
[22, 29, 61, 200, 600, 11, 20, 50],
{ "bedr3": { "N": 1, "pin": 30 } },
{ "item": "pumpctr" }
]],
"pumpctr": [20, [0.02, 1.2]],
"waterctr": [20, 0],
"gasctr": [20, 0]
},
"in": {
"41": { "item": "waterctr/set", "scmd": "%0.01", "rcmd": "" },
"39": { "item": "gasctr/set", "scmd": "%0.1", "rcmd": "" }
}
}
2. out_relay — Электромагнитное реле (Type 6)
Конфигурация
"pump": [6, [pin, period_сек]]
Параметры
| Индекс | Тип | Описание | Диапазон |
|---|---|---|---|
| [0] | int | GPIO пин (отрицательное = инвертировать) | 0-54 |
| [1] | float | Период цикла (сек), для RELAYX (16) | любой > 0 |
Логика
- HIGH (или LOW если инвертировано) = ON
- LOW (или HIGH если инвертировано) = OFF
- Если pin < 0, используется инверсия логики
Примеры
"relay_normal": [6, 33],
"relay_inverted": [6, -33],
"relay_with_period": [16, [32, 5]]
3. out_Motor — Управление моторами (Type 12)
Конфигурация
"roller_blind": [12, [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 |
Логика работы
- Модуль сравнивает targetPos (из команды 0-255) с curPos (из обратной связи)
- Если разница > POS_ERR (10):
- Если targetPos < curPos → движение вниз (pinDown)
- Если targetPos > curPos → движение вверх (pinUp)
- При достижении targetPos или maxOnTime мотор останавливается
- Защита от перегрузки: одновременно работают макс. MOTOR_QUOTE моторов (обычно 2)
Примеры
"blind_motor": [12, [32, 33, 36, 0, 1023, 120000]],
"gate_motor": [12, [-10, -11, 12, 100, 900, 60000]]
Управление
Команда: CMD_ON → движение вверх до конца
Команда: CMD_OFF → движение вниз до конца
Значение 0-255 → позиция (0=полностью открыто, 255=полностью закрыто)
4. out_PID — PID-регулятор (Type 13)
Конфигурация
"heater": [13, [
[Kp, Ki, Kd, dT, alarmTO, alarmVal, outMin, outMax],
{output_execObj},
{cascade_execObj}
], setpoint]
Параметры массива [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 = период опроса в секундах
Примеры
"room_temperature": [
13,
[
[1.0, 0.05, 0.02, 5.0],
{"item": "heater"},
null
],
21.5
]
5. out_PWM — ШИМ управление (Type 3)
Конфигурация
"led_brightness": [3, [pin0, pin1, ...]]
Параметры
| Индекс | Тип | Описание |
|---|---|---|
| [0] | int | GPIO пин (1 канал) или массив пин |
Число пин задаёт тип: 3 → RGB, 4 → RGBW, 5 → RGBWW. Частота PWM настраивается в коде, не в конфиге.
Примеры
"pwm_led": [3, 5],
"pwm_fan": [3, 6],
"pwm_rgbw": [3, [11, 12, 13, 14]]
6. out_relay (Type 6) — детально
Загружаемые параметры (getConfig)
pin = item->getArg(0); // основной параметр
if (pin < 0) {
pin = -pin;
inverted = true; // инвертировать логику
}
period = item->getFloatArg(1) * 1000.0; // период из конфига в СЕКундах → мс
if (!period) period = 5000UL; // по умолчанию 5 сек
Вывод: модуль загружает ровно 2 параметра; тот же драйвер используется для RELAYX (Type 16), где период определяет цикл ШИМ
7. out_counter (Type 20) — детально
Загружаемые параметры (Poll)
uint32_t impulse = item->getFloatArg(0) * TENS_BASE; // [0] массива аргументов
uint32_t period = item->getFloatArg(1) * 1000.0; // [1] в мс
Оба параметра читаются только в режиме автоинкремента
([20, [импульс, период]]); при скалярном аргументе автоинкремент
отключён (period = 0) и канал работает как накопитель внешних
импульсов (%X в /set).
Логика (out_counter.cpp):
- Пока таймер не запущен (
getExt() = 0), Poll ничего не делает - Команда
ON(или HEAT/COOL/AUTO/FAN/DRY/HEATCOOL), а также ненулевое/set, записывают вI_EXTметку времени старта;OFFили/set 0обнуляют её - По истечении period к значению (I_VAL, в «десятых») добавляется impulse, метка времени сдвигается на период
- Публикуется обновлённое значение (FLAG_PARAMETERS)
8. out_Motor (Type 12) — детально
Загружаемые параметры (getConfig)
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 мс
Обработка отрицательных значений
if (pinUp < 0) {
pinUp = -pinUp;
inverted = true;
}
if (pinDown < 0) {
pinDown = -pinDown;
inverted = true;
}
9. out_PID (Type 13) — детально
Загружаемые параметры (getConfig)
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
}
Использование вторых параметров
store->setpoint = item->itemVal->valuefloat; // Установка из JSON value
11. out_humidifier (Type 21) — Форсуночное увлажнение
Конфигурация
"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 | опционально |
Параметры зон (объект)
Каждая зона — это объект с полями:
"zone_name": {
"N": 1, // номер зоны для балансировки нагрузки
"pin": 24 // GPIO пин электромагнитного клапана форсунки
}
| Поле | Тип | Описание |
|---|---|---|
N |
int | Номер группы (1-4) для ограничения одновременно открытых клапанов |
pin |
int | GPIO пин клапана (отрицательное = инвертировать логику) |
set |
float | Требуемый уровень влажности (создаётся автоматически) |
cmd |
int | Статус команды (создаётся автоматически) |
Счётчик импульсов
{"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 | Отказ насоса |
Логика работы
- Инициализация: модуль ждёт команду включения или когда уровень влажности > startLevel
- Подготовка: открывает клапаны форсунок, ждёт достижения давления
- Работа: включает насос, поддерживает давление в диапазоне [MIN_OPERATION_PRESSURE, MAX_OPERATION_PRESSURE]
- Балансировка: одновременно открыто не более
capacityфорсунок из группыN - Очистка: периодическая промывка при давлении FLUSH_PRESSURE
- Контроль: отключение при падении давления ниже MIN_OPERATION_PRESSURE
Примеры конфигурации
Простая система увлажнения
{
"items": {
"humidifier": [21, [
[22, 23, 54, 255, 2500, 4, 10, 20],
{
"bedroom": {"N": 1, "pin": 24},
"living": {"N": 2, "pin": 25}
},
{"item": "waterctr"}
]]
}
}
Многозональная система (из официального примера)
{
"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) — Счётчик электроэнергии
Конфигурация
"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 | Дополнительные параметры |
Примеры
"electricity_meter": [22, [
1,
9600,
"8N1",
2,
[0x01, 0x02, 0x03, 0x04, 0x05, 0x06],
60000,
{}
]]
13. out_AC (Type 10) — Управление кондиционером
Конфигурация
"ac": [10, portNum],
"ac": [10, [
portNum, // [0] номер UART порта
{callbacks} // [1] объект колбэков: fan / set / temp / cmd
]]
Загружаемые параметры
portNum = item->getArg(0); // 0=Serial, 1=Serial1, 2=Serial2, 3=Serial3
Проприетарный UART-протокол Haier (9600 baud), не Modbus; modbus-шаблонов для AC нет.
Поддерживаемые команды
Модуль работает с 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 устройства
Конфигурация общая
"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
"device_instance": [14, [
96, // [0] modbus-адрес устройства (обязательно)
"device_name", // [1] имя шаблона (строка)
{
"power": {"emit": "home/ac/power"},
"temp": {"emit": "home/ac/temp"}
}
]]
Загружаемые параметры
// 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 | ×0.1 (сырое значение / 10) |
| 100 | ×0.01 (сырое значение / 100) |
Параметры в "par"
"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 18) — Многозональная вентиляция
Конфигурация
itemArg — объект с зонами (не массив), рабочая форма [[18, нач_значение], {зоны}]:
"vac": [[18, 5],
{
"": { // AC-узел: привязка к AC item
"item": "ac_2"
},
"zone1": { // зона 1
"pid": [490, 100, 9879, 40],
"set": 21.0,
"fan": 0,
"cmd": 14,
"item": "ac_zone1/set"
}
}
]
Параметры зоны
| Параметр | Тип | Описание |
|---|---|---|
pid |
[kP, kI, kD, dT] | Коэффициенты PID (массив ≥3) |
set |
float | Уставка температуры (число) |
fan |
int (0-255) | Текущий процент открытия |
cmd |
int | Текущая команда |
item |
string | Привязка к другому item |
V |
int | Номинальный объём (для балансировки) |
AlarmTime |
int | Время срабатывания аварии, деф 120 |
AlarmValue |
float | Значение аварии, деф 0 |
Практические примеры конфигурации
Система со счётчиками
{
"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": ""}
]
}
Система с реле и мотором
{
"items": {
"pump": [6, 33],
"blind": [12, [32, 33, 36, 0, 1023, 120000]]
}
}
PID регулятор
{
"items": {
"heater": [13, [
[1.0, 0.05, 0.02, 5.0],
{"item": "heater_output"},
null
], 22.0]
}
}
Ключевые правила конфигурации
- Инверсия логики: отрицательное значение пина = инвертировать логику
- Единицы времени:
- counter/relay: float конвертируется в миллисекунды (* 1000)
- mercury: миллисекунды напрямую
- Параметры по умолчанию:
- relay period = 5000 мс
- motor maxOnTime = 10000 мс
- modbus baud = 9600
- modbus polling = 1000 мс
- Массивы переменной длины: PID и Mercury поддерживают опциональные параметры
Документ основан на анализе C++ кода без домыслов
Версия: 1.0
Дата: 2026-01-21