# 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.