docs: import wiki pages into the repo (core/integrations/hardware)

Ported the relevant lazyhome.ru dokuwiki pages to markdown, verified against
the code; each page carries a 'cross-check with code' section where behavior
differs from or extends the wiki.
This commit is contained in:
2026-10-03 00:41:20 +03:00
parent b90325bfef
commit 724224a503
16 changed files with 2548 additions and 0 deletions
+233
View File
@@ -0,0 +1,233 @@
# Аналоговые входы и преобразования map
> Источник: Wiki LightHub (lazyhome.ru), страницы «аналоговые_входы» и «использование_преобразований_map». Снапшот от 2026-10-02.
## Общая информация
На разьем X36 контроллера LightHub выведены 12 аналоговых входов и 4 дискретных.
Аналоговые входы: A0-A11, Дискретные - DA12-DA15
Каждый из данных входов защищен от статического электричества и импульсных помех мощным TWS диодом, защищающий вход процессора как от отрицательного напряжения так и от напряжения более 5В
В случае использования процессорной платы DUE на 3,3 Вольт, автоматически, используется дополнительный диод, ограничивающий потенциал на входе процессора до допустимой величины в 3,5В
При необходимости, каждый из данных входов, может быть использован как слаботочный низковольтный выход.
## Аппаратное конфигурирование
Каждый вход может быть настроен для работы в разных режимах путем запаивания специальных контактных дорожек (перемычек) на плате
Для каждого входа предусмотрено две перемычки: подтяжка к GND и подтяжка к VCC (в зависимости от типа процессора, 5 или 3,3 В)
* Вход 0-10 В: запаяна перемычка GND. В этом случае, образуется делитель, при котором максимум значения ADC соответствует, примерно, 10В входного напряжения. В плавающем режиме на входе низкий уровень.
* Датчик протечки: запаяна перемычка VCC. В плавающем режиме, на входе высокий уровень. Между входом и нулем можно подключить проводной датчик протечки. В случае попадания влаги, на входе образуется низкий уровень.
* Плавающий высокоомный вход или выход: перемычки не запаяны. При этом вход измеряет напряжение от 0 до VCC, при более высоком напряжении - входит в насыщение, оставаясь при этом электрически защищенным от перенапряжения.
Также, к данным входам можно подключать датчики типа DHT22 или внешний CAN адаптер
Максимальное напряжение на входе - 24В (уточнить)
## Программное конфигурирование
Входы настраиваются в секции in конфигурации контроллера
Формат:
```json
"in":{
"pin#": { "T":<type>, "emit":"<emit>", item:"<item>", "scmd": "ON|OFF|TOGGLE|HALT|REST|XON|XOFF", "rcmd": "ON|OFF|TOGGLE|HALT|REST|XON|XOFF", "map":[<in_min>,<in_max>,<out_min>,<out_max>,<noize>]}
}
```
### Типы входов
- pin# - номер входа ([входы-выходы](../hardware/pins_io.md) , столбец "MPU PIN #")
- <type> - целое число, побитно кодирующее тип входа. (значение по-умолчанию 0):
Для *аналоговых входов*, допустимы следующие значения:
* 66 - Аналоговый вход без встроенной подтяжки
* 64 - Аналоговый вход с подключением встроенного подтягивающего резистора
Для *дискретных входов* применимы следующие значения:
* 0 - дискретный вход с подключением встроенного подтягивающего резистора, **низкий** уровень соответствует значению ON
* 2 - дискретный вход без подключения встроенного подтягивающего резистора, **высокий** уровень соответствует значению ON
* 1 - дискретный вход с подключением встроенного подтягивающего резистора, вход меняет значение между ON и OFF по низкому уровню входного напряжения
* 3 - дискретный вход без подключения встроенного подтягивающего резистора,, вход меняет значение между ON и OFF по высокому уровню входного напряжения
* 4 - датчик температуры и влажности DHT22
* 5 - датчик качества воздуха CCS811
* 6 - датчик температуры и влажности HDC1080
* 8 - COUNTER вход
* 16 - UPTIME вход
### Действия при срабатывании входа (старый метод настройки)
- <emit> - имя MQTT топика в который будет выводиться значение при изменениях на входе. Если имя не содержит символа "/",то слева от значения будет автоматически подставлен префикс статусного топика (см. раздел [работа с MQTT](https://www.lazyhome.ru/dokuwiki/doku.php?id=работа_с_mqtt))
- <scmd> - значение, передаваемое в топик при переключении входа в состояние ON (по-умолчанию, ON)
- <rcmd> - значение, передаваемое в топик при переключении входа в состояние OFF (по-умолчанию, OFF)
- <item> - имя канала из секции items которому локально на вход будет передано значение при изменении состояния входа
- <map> - параметр, который позволяет преобразовывать диапазон получаемых значений на аналоговом порту к иному диапазону или к дискретным значениям ON/OFF, подавлять шумы.
Примеры:
```json
"map":[0,850,0,100] - при получении значения 850 преобразование выдаст на выходе число 100
"map":[100,500,0,256,10] - при изменении входного значения от 100 до 500 преобразование выдаст на выходе число от 0 до 256, флуктуации в пределах 10 единиц между замерами (после преобразования) , будут игнорироваться.
При выходе величины изменения между текущим и предыдущим учтенным замером за пределы шумоподавления, шумоподавление отключается для нескольких последовательных замеров.
"map":[100,500] - при понижении значения ниже 100 будет предприняты действия, аналогично дискретному входу, состояние OFF, при повышении значения выше 500 будет предприняты действия, аналогично дискретному входу, состояние ON
```
См. также [несколько кнопок на одном входе](button_presses.md#несколько-кнопок-на-одном-входе)
## Использование преобразований map
Внутри контроллера команды и значения между каналами передаются в унифицированном виде (см itemCmd)
Но для управления реальными устройствами, данные необходимо конвертировать из унифицированного вида в формат, который понимает устройство и наоборот
Для этого существует механизм преобразований, который может производить как конвертацию значений так и переобразования между командами и значениями
Первое место, где используются преобразования - это интеграция Modbus v2. см [настройка modbus](../integrations/modbus_setup.md) это обьясняется тем, что в Modbus все взаимодействие с устройством происходит через регистры, в которые пишутся, либо, из которых считываются числовые значения.
### Типы преобразований
Предусмотрено два типа преобразований - **преобразования команды** и **преобразование значения**
Также, существуют два направления преобразования - **прямое** (когда из унифицированного вида создается значение для записи в устройство) и **обратное** - когда считанное из устройства значение преобразуется в унифицированный вид
Преобразование определяется при помощи JSON обьекта "map" который добавляется в описание регистра устройства в разделе конфигурирования modbus. Разберем на примерах:
```json
"fanspeed" :{"reg":40000,"map":{"val":[1,255,1,5],"cmd":[["OFF",0]]},"id":7},
```
**прямое преобразование:**
При управлении fanspeed (напрямую, в нотации <item>/fanspeed/set или через суффикс №7 (fan) в нотации <item>/fan), сперва произойдет попытка преобразования команды
В случае, если передана команда OFF, в регистр 40000 будет записано значение 0
В противном случае, осуществляется попытка преобразовать переданное значение, конвертировав его из шкалы 1-255 в шкалу 1-5
если в результате преобразований будет получено число - произойдет запись в указанный регистр модбас.
при считывании значения из регистра, будет происходить **обратное преобразование**
При этом, те же правила применяются в обратном направлении.
Сначала производится попытка преобразовать полученное из регистра значение в команду. В случае неуспеха - в число.
В примере выше - если считано значение 0 - оно будет преобразовано в команду OFF
в случае не успешного преобразования в команду будет осуществлено обратное преобразование значения из шкалы 1-5 в шкалу 1-255
Следует отметить, что если преобразование типа "val" не указано, то число, прочитанное из регистра, будет передано на выход без преобразования - именно в том виде, как оно было прочитано из регистра. При этом, преобразование считается выполненным успешно и "сценарий по умолчанию" (def) выполнен не будет.
Данное поведение можно отменить, задав null для преобразования значения, как указано в примере ниже.
Это приведет к тому, что при невозможности преобразовать полученное значение в команду, преобразование в число производиться не будет и отработает "сценарий по умолчанию" (def)
```json
"acon":{"reg":40003,"map":{"cmd":[1,["OFF",0]],"val":null,"def":40001},"id":8},
```
Для этого примера преобразования будут действовать следующим образом:
Прямое:
Команда OFF приведет к записи 0 в регистр 40003
Любая другая команда или значение будут проигнорированы
Обратное:
Если из регистра 40003 считан ноль, он будет преобразован в команду OFF.
любые другие значения будут проигнорированы. Преобразование при этом будет считаться не успешным. и будет выполнен "сценарий по умолчанию", заданный в параметре "def" обьекта "map".
### Сценарии преобразования по умолчанию
Этот параметр (используется только для обратных преобразований modbus) применяется в том случае, если для считанного из регистра значения не удалось применить преобразование. В этом случае, можно использовать значение, считанное из иного регистра.
Параметр def может иметь либо цифровое либо строковое значение. В случае цифрового значения - задается номер регистра. в случае строкового значения - задается имя параметра. Логика работы сценария по умолчанию немного разная для данных двух случаев.
**цифровое значение:**
Контроллер пытается найти считанное из modbus значение в текущем буфере (на тот случай, если данное значение было считано в одном цикле опроса командой чтения нескольких последовательных регистров)
Если значение не было считано, регистр считывается отдельно.
Для примера выше, требуется, чтобы номер регистра (40001), также, был определен. Например, таким образом:
```json
"acmode" :{"reg":40001,"map":{"cmd":[["FAN_ONLY",1],["HEAT",4],["COOL",2],["AUTO",8]]},"id":8},
```
Соответственно, в случае если значение регистра 40003 не нулевое (сработал "сценарий по умолчанию") - будет прочитан регистр 40001, полученное из него значение будет преобразовано к соответствующей команде, результат данного преобразования будет возвращен как результат преобразования первого параметра (acon)
Данное поведение, тем не менее, не отменяет стандартной логики того, что когда произойдет опрос регистра 40001 (если его опрос задан в параметре poll устройства) - будут произведены все преобразования из параметра acmode, которые будут переданы на обработку, если acmode описан в разделе items файла конфигурации.
**строковое значение:**
В этом случае, используется последнее, ранее считанное, значение, сохраненное в параметре, имя которого указано в параметре def. Для данного значения, производятся преобразования, определенные для данного параметра и их результат возвращается как результат преобразования первого параметра.
В примере ниже, если значение coil 0 равно нулю - обратное преобразование сразу вернет команду OFF
Иначе, так как преобразование в число отменено (val=null), преобразование для параметра pwr будет считаться не успешным и контроллер посмотрит ранее считанное значение регистра 1, из параметра описанного в acmode, применит все указанные для регистра acmode преобразования и их результат вернет для параметра pwr
важно: параметр acmode должен быть описан в разделе items, даже если сам по себе он ни для каких действий более не используется. достаточно в данном описании поставить пустой JSON обьект - именно в нем контроллер сохраняет ранее считанные значения)
```json
"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},
```
## Ограничения диапазона при линейном преобразовании значений
В простейшем случае, в параметре val задается массив, содержащий 4 значения
```json
"val":[вход_мин, вход_макс, выход_мин, выход_макс]
```
например
```json
"val":[1, 5, 1, 255]
```
В случае прямого преобразования, числа 1,2,3,4,5 будут преобразованы к 1, 64, 128, 195, 255
В случае обратного - числа из интервала 1-64 к 1, 65-128 к 2, 129-195 к 3, 196-254 к 4 и 255 к 5
NEW
если входное значение не укладывается в указанные границы - преобразование считается не успешным. То есть в примере выше, если на вход преобразования придет число 0 или 6 то оно не сработает.
можно определить значения, которые будут являться результатом преобразования если. входное значение меньше минимума или больше максимума диапазона преобразования
```json
"val":[вход_мин, вход_макс, выход_мин, выход_макс, вход<мин_прямое, вых<мин_обратное, вход>макс_прямое, вых>макс_обратное]
```
соответственно, используя данный синтаксис, можно доработать пример выше таким образом, что значение 0 будет транслироваться в 0 как в прямом так и в обратном направлении
```json
"val":[1, 5, 1, 255, 0, 0]
```
Параметры подставляемые при срабатывании ограничений не обязательны. Если какие-то требуется пропустить - можно указать null
## Предопределенные шаблоны преобразований
### Шаблон "cmd":"fan"
данный шаблон в случае прямого преобразования позволяет провести трансляцию стандартных команд OFF, LOW, MEDIUM, HIGH в значения 0, 20, 128, 255 соответственно
Для обратного преобразования:
Значения 0, 1-127, 128-254, 255 преобразуются в OFF, LOW, MEDIUM, HIGH
```json
"fanspeed":{"reg":42,"type":"u8l","id":7,"map":{"cmd":"fan"}},
```
## Сверка с кодом (2026-10-02)
- Корректно: типы аналоговых входов соответствуют коду: `IN_ANALOG = 64` (вход с встроенной подтяжкой, `INPUT_PULLUP`) и `66 = IN_ANALOG | IN_ACTIVE_HIGH` (вход без подтяжки, обычный `INPUT`) — `lighthub/inputs.h:29,33` и `lighthub/inputs.cpp:255-260`.
- Корректно: дискретные типы 0/1/2/3 (`IN_PUSH_ON`, `IN_PUSH_TOGGLE`, `IN_ACTIVE_HIGH`) — `lighthub/inputs.h:33-34`; типы 4/5/6/8/16 (DHT22, CCS811, HDC1080, COUNTER, UPTIME) обрабатываются в `lighthub/inputs.cpp:262-265,315-321`.
- Корректно: параметр `map` для аналогового входа (линейное преобразование/порог/шумоподавление) обрабатывается в `lighthub/inputs.cpp:875,1095`.
- Корректно: преобразования modbus (`map` с `val`/`cmd`/`def`) реализованы в `lighthub/modules/out_modbus.cpp` (строки 216, 465, 600, 1084); шаблон `"cmd":"fan"` — `lighthub/itemCmd.cpp:1364,1473`.
- Уточнение: в описании «нескольких кнопок на одном входе» и в примерах используется параметр `map` в двух разных смыслах (диапазон ADC для входа и преобразование регистра modbus) — в обоих случаях это разные контексты конфига, в коде они обрабатываются независимо.
+162
View File
@@ -0,0 +1,162 @@
# Двойные, тройные, длительные нажатия
> Источник: Wiki LightHub (lazyhome.ru), страницы «двойные_тройные_длительные_нажатия» и «несколько_кнопок_на_одном_входе». Снапшот от 2026-10-02.
Начиная с [этого коммита](https://github.com/anklimov/lighthub/commit/0044b741ac9f6fb8fc4b1ff8388e47c8bb8efd9b) у прошивки появилась возможность отслеживать одинарные, двойные, тройные, долгие нажатия
Конечный автомат, согласно которому реализован алгоритм, приведен на рисунке
(см. иллюстрацию на [wiki-странице](https://www.lazyhome.ru/dokuwiki/doku.php?id=двойные_тройные_длительные_нажатия))
Фрагмент конфига (раздел in, на примере pin 68), который задает обработчики для нажатий, приведен ниже.
Каждое событие описывается JSON объектом или массивом JSON обьектов.
Внутри объекта, возможны следующие строковые параметры:
## Типы нажатий
* `scmd` - начало первого нажатия
* `rcmd` - конец первого нажатия
* `lcmd` - первое длительное нажатие
* `click` - одиночное нажатие
* `dclick` - двойное нажатие
* `tclick` - тройное нажатие
* `scmd2` - начало двойного нажатия
* `scmd3` - начало тройного нажатия
* `lcmd2` - второе длительное нажатие
* `lcmd3` - третье длительное нажатие
* `rpcmd` - цикл первого длительного нажатия
* `rpcmd2` - цикл второго длительного нажатия
* `rpcmd3` - цикл третьего длительного нажатия
## Параметры обработчика нажатий
* `emit` - MQTT топик в который отправить значение из параметра ecmd (если в параметре отсутствует / он будет дополнен слева префиксом статусного топика)
* `ecmd` - MQTT payload
* `erev` - если параметр задан, значения ecmd и erev будут подставляться попеременно для каждого нажатия. Позволяет обеспечить, например, увеличение и уменьшение яркости лампы одной клавишей.
* `item` - имя локального устройства из items (может содержать суффикс для указания того, какое именно свойство объекта надо изменить. Например: "lamp/hue" или "lamp/sat")
* `icmd` - команда для локального устройства (ON | OFF | HALT | REST | XON | XOFF | INCREASE | DECREASE | %<цифра> и т.д)
* `irev` - если параметр задан, значения icmd и irev будут подставляться попеременно для каждого нажатия. Позволяет обеспечить, например, увеличение и уменьшение яркости лампы одной клавишей.
```json
"68":{"T":0,
"scmd":{"emit":"cmd","ecmd":"scmd"},
"rcmd":{"emit":"cmd","ecmd":"rcmd"},
"lcmd":{"emit":"cmd","ecmd":"lcmd"},
"click":{"emit":"cmd","ecmd":"click","item":"a_bedr","icmd":"TOGGLE"},
"dclick":[{"emit":"myhome/in/bedr","ecmd":"TOGGLE"},{"emit":"myhome/in/bedrspot","ecmd":"TOGGLE"}],
"tclick":{"item":"spi","icmd":"TOGGLE"},
"scmd2":{"emit":"cmd","ecmd":"scmd2"},
"scmd3":{"emit":"cmd","ecmd":"scmd3"},
"lcmd2":{"emit":"cmd","ecmd":"lcmd2"},
"lcmd3":{"emit":"cmd","ecmd":"lcmd3"},
"rpcmd":{"item":"a_bedr","icmd":"INCREASE"},
"rpcmd2":{"item":"a_bedr","icmd":"DECREASE"},
"rpcmd3":{"emit":"cmd","ecmd":"rpcmd3"}
},
```
Еще пример:
* Длительное нажатие через раз увеличивает или уменьшает яркость группы ligth (суффикс set позволяет менять яркость не включая канал, если он выключен)
* Соответственно, длительное нажатие через двойной или тройной клик позволяет так же управлять цветом и насыщенностью
* Двойное и тройное нажатие без удерживания включают/выключают группы kuhktc и gstall соответственно
* Команда %-Х уменьшает параметр на Х пунктов, соответственно %+Х увеличивает
```json
"63":{"T":2,
"click":{"item":"light","icmd":"TOGGLE"},
"rpcmd":{"item":"light/set","icmd":"%+5","irev":"%-5"},
"rpcmd2":{"item":"light/hue","icmd":"%+5","irev":"%-5"},
"rpcmd3":{"item":"light/sat","icmd":"%+5","irev":"%-5"},
"dclick":{"item":"kuhktc/cmd","icmd":"TOGGLE"},
"tclick":{"item":"gstall","icmd":"TOGGLE"}},
```
Еще пара полезных примеров для обычных (не кнопочных) выключателей
В первом - кратковременное выключение выключателя включает белый свет на полную (повторное - включает максимально насыщенный цвет и яркость 30%)
Во втором - совсем упрощенный вариант - для одноцветных ламп - лампа через раз включается на 30 и на 100 процентов яркости
```json
"56":{"T":2,
"scmd":{"item":"bedr","icmd":"ON"},
"scmd2":[{"item":"bedr","icmd":"100","irev":"30"},{"item":"bedr/sat","icmd":"0","irev":"100"}],
"rcmd":{"item":"bedr","icmd":"OFF"}},
"60":{"T":2,
"scmd":{"item":"bedrspot","icmd":"100","irev":"30"},
"rcmd":{"item":"bedrspot","icmd":"OFF"}},
```
## Несколько кнопок на одном входе
Если в обьекте, определяющем вход, обнаружен массив **"act"** и вход является аналоговым, то каждый элемент массива будет рассматриваться как отдельный вход, для которого возможна такая же обработка как для дискретного (то есть определение даблкликов, долгих нажатий и пр)
При этом анализируется параметр **"map**" у каждого элемента массива, и элемент применяется только если значение аналогового входа находится внутри заданного интервала
Это позволяет на один аналоговый вход подключить несколько кнопок через резисторы.
Важно: в параметре "T" не надо указывать аналоговый тип входа. Используются дискретные типы 0 и 2
Пример: Кнопка выкл/уменьшить яркость подключена к опорному напряжению +10В напрямую, кнопка вкл/увеличить яркость - через резистор 2,2 КОм (на плате должен быть активирован шунт - см [аналоговые входы, общая информация](analog_inputs_and_map.md#общая-информация))
```json
"in": {
"54":{"T":0,"act":
[
{
"map":[128,640],
"click":{"item":"gr_gost3","icmd":"ON"},
"dclick":{"item":"lampwc3","icmd":"ON"},
"tclick":{"item":"lampbath3","icmd":"ON"},
"rpcmd":{"item":"gr_gost3","icmd":"%+2"}
},
{
"map":[641,1024],
"click":{"item":"gr_gost3","icmd":"OFF"},
"dclick":{"item":"lampwc3","icmd":"OFF"},
"tclick":{"item":"lampbath3","icmd":"OFF"},
"rpcmd":{"item":"gr_gost3","icmd":"%-2"}
}
]}
}
```
И тот же самый пример, записанный в новой нотации конфигурирования входов, при которой элемент конфигурации in является массивом, а значит, появилась возможность без костылей настраивать входы, не привязанные напрямую к пинам процессора. Номер пина задается в параметре "#" конфигурации:
```json
"in": [
"{"T":0,"#":54, "act":
[
{
"map":[128,640],
"click":{"item":"gr_gost3","icmd":"ON"},
"dclick":{"item":"lampwc3","icmd":"ON"},
"tclick":{"item":"lampbath3","icmd":"ON"},
"rpcmd":{"item":"gr_gost3","icmd":"%+2"}
},
{
"map":[641,1024],
"click":{"item":"gr_gost3","icmd":"OFF"},
"dclick":{"item":"lampwc3","icmd":"OFF"},
"tclick":{"item":"lampbath3","icmd":"OFF"},
"rpcmd":{"item":"gr_gost3","icmd":"%-2"}
}
]}
]
```
Работают обе нотации. Если номер пина прописан сразу в двух местах, приоритет имеет параметр "#"
## Сверка с кодом (2026-10-02)
- Корректно: все ключи нажатий (`click`, `dclick`, `tclick`, `scmd`, `rcmd`, `lcmd`, `scmd2`, `scmd3`, `lcmd2`, `lcmd3`, `rpcmd`, `rpcmd2`, `rpcmd3`) читаются в `lighthub/inputs.cpp` (строки 717–790, конечный автомат `IS_*`).
- Корректно: параметры `emit`/`ecmd`/`erev`/`item`/`icmd`/`irev` обрабатываются в `lighthub/utils.cpp:701-718` (попеременная подстановка `icmd`/`irev` и `ecmd`/`erev` подтверждена).
- Корректно: массив `"act"` и `"map"` для нескольких кнопок на одном аналоговом входе обрабатываются в `lighthub/inputs.cpp` (строки 173, 631, 656, 672, 1248).
- Уточнение: для дискретных нажатий `T` использует типы 0 и 2, как указано в wiki (типы входов: `IN_PUSH_ON=0`, `IN_ACTIVE_HIGH=2` — `lighthub/inputs.h:29-34`).
+79
View File
@@ -0,0 +1,79 @@
# Command Line Interface
> Источник: Wiki LightHub (lazyhome.ru), страница «cli_интерфейс». Снапшот от 2026-10-02.
Иначе, интерфейс командной строки.
Служит для настройки системных параметров контроллера (при необходимости)
Команды можно подать как подключившись к контроллеру на отладочный последовательный порт, так и при помощи MQTT (см [работа с MQTT, служебные топики](https://www.lazyhome.ru/dokuwiki/doku.php?id=работа_с_mqtt#служебные_топики)) или HTTP [API](https://www.lazyhome.ru/dokuwiki/doku.php?id=api)
## Перечень команд
* `help` - this text
* `mac de:ad:be:ef:fe:00` set and store MAC-address in EEPROM
* `ip [ip[,dns[,gw[,subnet]]]]` - set static IP
* `save` - save current config in NVRAM; ON|OFF - enable/disable autosave
* `get` [config addr]' - get config from pre-configured URL and store addr, ON|OFF - enable/disable download on startup
* `load` - load config from NVRAM
* `pwd` - define and store MQTT password
* `otapwd` - define and store HTTP API password
* `log [serial_loglevel] [udp_loglevel]` - define log level (0..7)
* `kill` - test watchdog - в норме, приводит к перезапуску
* `clear` - clear EEPROM
* `search` - search devices on 1-wire bus
* `reboot` - reboot controller
## Подключение по USB
### MAC
Подключаем контроллер USB кабелем к ноутбуку. Открываем эмулятор терминала (например для Макбука использую minicom, который устанавливается через homebrew).
Для улучшения читаемости ответов контроллера в minicom нажимаем комбинацию Esc+U
```
$ minicom -D /dev/tty.usbmodem14201
```
### Windows
Для windows можно использовать putty, терминал, входящий в среду разработки PlatformIO, Arduino IDE
Параметры подключения - 115200 бод, N-8-1
CLI commands must be send via serial port with 115200 baud rate / 8N1 params: 8 data bits, no parity bit, 1 stop bit.
### Пример исполненения команды при помощи Unix shell:
```
> stty -f /dev/cu.usbmodem146101 ispeed 115200 ospeed 115200 -parenb cs8 cstopb
> echo "ip" > /dev/cu.usbmodem146101
> cat /dev/cu.usbmodem146101
```
### также, можно использовать Arduino IDE
(serial monitor). Serial port must be configured (MacOSX config file ~/Library/Arduino15/preferences.txt)
```
serial.databits=8
serial.stopbits=1
serial.parity=N
serial.debug_rate=115200
serial.line_ending=1
```
## Подключение по MQTT
Если контроллер уже успешно подключен к MQTT брокеру, то команду CLI можно направить в топик $command.
см [работа с MQTT, служебные топики](https://www.lazyhome.ru/dokuwiki/doku.php?id=работа_с_mqtt#служебные_топики)
## Подключение по HTTP API
Если контроллер уже успешно подключен к локальной сети, то команду CLI можно направить с помощью http [API](https://www.lazyhome.ru/dokuwiki/doku.php?id=api)
Примечание (2026-10-02): список команд wiki полностью совпадает с реализацией в `lighthub/main.cpp`, функция `setupCmdArduino()` (строки 2854–2876): зарегистрированы `help`, `save`, `load`, `get`, `mac`, `ip`, `otapwd`, `kill`, `pwd`, `clear`, `reboot`, `log`, `search`. Отдельные команды регистрируются условно: `get`, `mac`, `ip`, `otapwd` — только при включенной сети (не `NOIP`), `mac` — кроме сборок `FLASH_64KB`, `search` — кроме сборок с `OWIRE_DISABLE`. В коде есть также закомментированная команда `req` (`cmdFunctionReq`), в wiki она не упомянута. В wiki опечатка в описании `get` (`'get' [config addr]'`), в коде команда принимает URL сервера конфига либо `ON`/`OFF` (`cmdFunctionGet`, main.cpp:1772).
## Сверка с кодом (2026-10-02)
- Корректно: все 13 команд из wiki присутствуют в коде (`lighthub/main.cpp:2854-2876`).
- Уточнение: часть команд (`get`, `mac`, `ip`, `otapwd`) доступна только в сборках с сетевым интерфейсом; `search` — только при включенной поддержке 1-wire.
+43
View File
@@ -0,0 +1,43 @@
# Криптоподпись команды
> Источник: Wiki LightHub (lazyhome.ru), страница «криптоподпись_команды». Снапшот от 2026-10-02.
В том случае, если надо гарантировать, что, даже получив доступ к локальной сети, MQTT брокеру или HTTP API, потенциальный злоумышленник не сможет выполнить критичную команду (например, открытие ворот), можно использовать механизм цифровой подписи команды.
Для задействования режима, необходимо пересобрать прошивку, добавив в приватный файл опций компиляции ([опции компиляции](https://www.lazyhome.ru/dokuwiki/doku.php?id=опции_компиляции)) (пример custom-build-flags/build_flags_lighthub21 для сборки под lighthub21) следующие опции (приведен пример):
```
-D CRYPT
-D PROTECTED_PINS=16,21
-D SHAREDSECRET=big_secret
```
### Как работает режим:
* Каждый контроллер, один раз в 30 секунд, передает в MQTT топик `<mqtt_root>/<controller_name>/$salt` случайное число, полученное с истинного датчика случайных чисел. Данное число (далее `<Salt>`) должно сохраняться авторизованной стороной и использоваться при создании цифровой подписи.
* Авторизованная сторона, желающая выполнить команду, вычисляет SHA256 хэш от строки, содержащей `<Salt><SHAREDSECRET><Команда>`
* при отправке MQTT команды, авторизованная сторона добавляет в MQTT Payload полученный хэш цифровой подписи ДО команды, отделив подпись от тела команды знаком @
* Контроллер, получив команду с подписью, производит аналогичную операцию по вычислению подписи и, если значения совпали, запрос считается авторизованным
* Если команда направлена на управление пином контроллера, из перечня PROTECTED_PINS, заданного при компиляции прошивки, то она будет выполнена только том случае, если является авторизованной
### Ограничения
Если пин входит в перечень, заданный при компиляции в опции PROTECTED_PINS, то для него действуют следующие ограничения, смысл которых в том, чтобы сделать крайне сложным подачу высокого логического уровня на выход контроллера (открытие мощных ключей) не имея физического доступа к самому устройству:
* Он не будет работать на канале типа термостат (THERMO)
* Для канала типа RELAY вывод работает только в не инверсном режиме. То есть, настройками не получится добиться перевода в состояние с высоким уровнем по-умолчанию, не получив подписанной команды. Настройки команды по умолчанию в файле конфигурации, также, будут проигнорированы. требуется цифровая подпись команде для управления таким каналом
* Восстановление значения канала при перезагрузке контроллера из статусных топиков MQTT не будет работать
* Форсуночный увлажнитель не будет инициализирован, если хотя бы один защищенный пин присутствует в его настройках (насос, клапана)
* Данные пины не работают для управления моторизированными воздушными заслонками (канал MOTOR)
* При использовании защищенных пинов в канале типа PWM требуется цифровая подпись команде для управления таким каналом
* Канал типа RELAYPWM на этом pin работать не будет
В качестве дополнительной меры защиты, рекомендуется отключить возможность обновления прошивки по-воздуху (OTA)
## Сверка с кодом (2026-10-02)
- Корректно: механизм реализован под флагом `CRYPT`: ключ `cryptoKey[] = QUOTE(SHAREDSECRET)` (`lighthub/main.cpp:110`), публикация `$salt` в топике устройства — `lighthub/main.cpp:2793-2804` (функция `publishStat()`, вызывается раз в 30 секунд из `thermoLoop()`, период `THERMOSTAT_CHECK_PERIOD=30000`, `lighthub/options.h:147`).
- Корректно: подпись вычисляется как SHA256 от `<Salt><SHAREDSECRET><Команда>` — `checkToken()` в `lighthub/utils.cpp:901-942` (sha256.update: saltStr, cryptoKey, data).
- Корректно: формат payload «подпись@команда» — разбор по символу `@` в `lighthub/item.cpp:752` (`char * authPos = strchr(payload,'@'); //token@command`).
- Корректно: ограничения для PROTECTED_PINS подтверждены в коде: THERMO — `main.cpp:3237`; RELAY — `modules/out_relay.cpp:39,110`; MOTOR — `modules/out_motor.cpp:53,77,102`; PWM требует авторизованную команду — `modules/out_pwm.cpp:129-165`; SPRINKLER (увлажнитель) — `modules/out_sprinkler.cpp:50`. Перечень пинов задается опцией `PROTECTED_PINS` (`lighthub/options.h:390-403`).
+120
View File
@@ -0,0 +1,120 @@
# Как LightHub работает с файлом конфигурации
> Источник: Wiki LightHub (lazyhome.ru), страница «как_lighthub_работает_с_файлом_конфигурации». Снапшот от 2026-10-02.
## Первое включение
По-умолчанию, контроллер получает динамический адрес локальной сети по DHCP
При этом, он записывает его в энергонезависимую память. И если при очередном перезапуске, DHCP сервер не доступен - он будет использовать последний известный IP адрес.
Если надо определить статический адрес (а, также, GW, DNS, NetMask), это можно сделать при помощи команды ip в [cli_интерфейс](cli_interface.md)
Адрес будет сохранен в энергонезависимую память контроллера.
При включении, контроллер сначала проверяет наличие записанного в памяти конфигурационного файла. (У нового контроллера, а также, после перезаливки прошивки, конфигурационный файл отсутствует (кроме mega2560, в случае этого контроллера, конфигурация не утрачивается в процессе перепрошивки)). Затем контроллер поднимает сетевые интерфейсы, подключается к интернету, идет на сайт lazyhome.ru и пытается скачать конфигурационный файл JSON для своего МАС-адреса. (данное поведение можно отключить при помощи cli команды get OFF)
### Создание конфигурационного файла
Для того чтобы начать, можете просто использовать примеры [примеры конфигураций](https://www.lazyhome.ru/dokuwiki/doku.php?id=примеры_конфигураций), а затем доработать их по своему усмотрению
Чтобы загрузить/отредактировать конфигурацию контроллера есть несколько методов:
### Простой метод настройки - через портал lazyhome.ru
Для создания конфигурационного файла заходим на lazyhome.ru в свой аккаунт (после регистрации на сайте) и на странице [Личный Кабинет](https://www.lazyhome.ru/portal) создаем конфигурационный файл для своего контроллера, нажав кнопку "создать" и указав его [MAC-адрес](../hardware/mac_address.md) Тогда контроллер при перезагрузке получит настройку и сможет начать работать в этой конфигурации.
Далее, надо просто подключить контроллер к роутеру, имеющему выход в Интернет. После перезапуска, контроллер загрузит настройки с сайта lazyhome.ru.
Для того, чтобы быстро начать работу, этого достаточно.
В дальнейшем, Автоматическую загрузку конфига можно отменить при помощи команды `get OFF` в [cli_интерфейс](cli_interface.md) или изменив конфиг через web интерфейс контроллера
### Автономный метод настройки - веб интерфейс/плагин браузера
Также, редактировать конфигурацию, управлять режимами, перегружать контроллер можно, зайдя в веб интерфейс на адрес контроллера по http через браузер (рекомендован firefox) или установив плагин браузера Chrome (рекомендуется)
Подробности тут: [интерфейс настройки](web_ui.md)
### Дополнительные возможности
Также можно разместить настройки на своем собственном http сервере, в папке cnf. Формат имени файла: http://MY_CONFIG_SERVER/cnf/12-12-12-12-12-12.config.json (вместо 12-12-12-12-12-12 ваш mac адрес)
После этого выполнить через CLI команду `get <MY_CONFIG_SERVER>`
Контроллер запомнит ваш сервер и далее, будет загружать обновление конфига из этого источника. (на платформах STM, NRF пока не сохраняется)
## Сохранение настроек в постоянную память контроллера
По-умолчанию, успешно загруженный конфиг автоматически сохраняется в энергонезависимую память контроллера.
После этого контроллер готов к автономной работе.
При загрузке конфигурации проверяется наличие изменений - если в памяти сохранен тот же конфиг, что имеется на портале, повторная загрузка и сохранение не происходит.
Данное поведение можно изменить при помощи команды save в [cli_интерфейс](cli_interface.md)
```
save ON - включить автосохранение конфига (по умолчанию)
save OFF - выключить автосохранение конфига
save - сохранить текущий конфиг
```
Есть три способа подключения к контроллеру для управления: по USB, через MQTT и через HTTP [API](https://www.lazyhome.ru/dokuwiki/doku.php?id=api). Рассмотрим их подробнее.
## Подключение по USB
Подключаем контроллер USB кабелем к ноутбуку. Открываем эмулятор терминала (например для Макбука использую minicom, который устанавливается через homebrew).
Для улучшения читаемости ответов контроллера в minicom нажимаем комбинацию Esc+U
```
$ minicom -D /dev/tty.usbmodem14201
```
Для windows можно использовать putty или терминал, входящий в среду разработки PlatfrmIO
Параметры подключения - 115200 бод, N-8-1
После подключения, контроллер отвечает:
```
Got IP address:192.168.88.44, Default config server used: lazyhome.ru
Config URI: http://lazyhome.ru/cnf/de-71-d5-9a-93-96.config.json
HTTP Status code: 404
Config retrieving failed
Loading Config from EEPROM No stored config
```
Видим, что контроллер пытается считать конфиг для своего MAC-адреса de-71-d5-9a-93-96.config.json, и его там не находит (404 ошибка).
После того как мы сформировали конфиг на портале lazyhome.ru, контроллер нам ответит что все хорошо и сохранит конфиг.
## Подключение по MQTT
Если контроллер уже успешно подключен к MQTT брокеру, то команду CLI можно направить в топик $command.
см [работа с MQTT, служебные топики](https://www.lazyhome.ru/dokuwiki/doku.php?id=работа_с_mqtt#служебные_топики)
## Рабочий режим
During normal operation, controller:
* Accepting incoming MQTT message flow and retrieving item name from topic name. For example, /myhome/in/item1 will control "item1"
* Controlling items.
* Most commands, accepted on INTOPIC passed throw to OUTTOPIC after interpretation. Interpretation is converting of high level commands like ON OFF HALT REST to low-level commands with real values. OUTTOPIC publishing uses "persistent" flag to allow retrieving recent status from MQTT broker after restart of controller
* Polling: Normally, Modbus devices and 1-wire thermometers are polled with reasonable interval. Retrieved values are publishing to OUTTOPIC
## Цветовая индикация режимов работы
Контроллер LightHub имеет трехцветный светодиод, который наглядно показывает текущий режим работы контроллера
* красный - отсутствует подключение по локальной сети
* желтый - контроллер подключен к локальной сети но не подключен к MQTT брокеру
* зеленый - контроллер подключен к брокеру
* вспышки синего - получены инструкции по MQTT
* вспышки красного - ошибки в процессе работы (изучить отладотчный лог)
* постоянное свечение - конфигурация не загружена
* мигание с интервалом 2-3 секунды - конфигурация загружена и в работе
То есть, например, мигание красным цветом с интервалом 2-3 секунды означает, что контроллер отключен от локальной сети, но продолжает локальную работу по имеющемуся на борту файлу конфигурации
## Сверка с кодом (2026-10-02)
- Корректно: сервер конфига по умолчанию — `lazyhome.ru` (макрос `CONFIG_SERVER`, `lighthub/options.h:183-186`); переопределение опцией `MY_CONFIG_SERVER` подтверждено, командой `get <server>` задается свой сервер (`systemConfig::setServer`, config.cpp:134; `cmdFunctionGet`, main.cpp:1772-1781), `get ON`/`get OFF` включают/выключают загрузку (`setLoadHTTPConfig`, config.cpp:315).
- Корректно: формат имени файла `http://<сервер>/cnf/xx-xx-xx-xx-xx-xx.config.json` (MAC в шестнадцатеричном, через дефисы) — main.cpp:1889.
- Корректно: автозагрузка и автосохранение конфига: при успешной загрузке `if (configLoaded && sysConf.getSaveSuccedConfig()) cmdFunctionSave(...)` (main.cpp:1949 и др.); проверка изменений — по заголовку `ETag`/`If-None-Match`, код 304 «Config not changed» (main.cpp:1869, 1955), что соответствует описанию «если в памяти сохранен тот же конфиг... повторная загрузка и сохранение не происходит».
- Примечание (2026-10-02): локальное изменение конфига через HTTP (`POST /config.json`) автоматически отключает загрузку с портала — main.cpp:368-374 («Config changed locally, portal disabled»), что согласуется с пунктом «...или изменив конфиг через web интерфейс контроллера».
- Уточнение: оговорка «на платформах STM, NRF пока не сохраняется» (сервер конфига) относится к сохранению `MY_CONFIG_SERVER` в NVRAM, в текущем коде `setServer` доступен на всех платформах с NVRAM-поддержкой; поведение может зависеть от конкретной сборки.
+65
View File
@@ -0,0 +1,65 @@
# OTA — обновление прошивки по воздуху
> Источник: Wiki LightHub (lazyhome.ru), страница «ota_обновление_прошивки_по_воздуху». Снапшот от 2026-10-02.
### OTA
Контроллер имеет возможность обновлять свою прошивку "по воздуху" через http [API](https://www.lazyhome.ru/dokuwiki/doku.php?id=api)
Данная возможность доступна для следующих вариантов прошивки:
* due
* lighthub21
* esp32-wifi
* esp8266-wifi
* mega2560-optiboot
* m5stack
Прошивка должна быть скомпилирована с опцией OTA (предкомпилированные версии прошивок для указанных выше окружений уже скомпилированы с такой опцией)
## Управление размером/опциями прошивки
Чтобы прошивка могла успешно обновиться, она должна занимать строго не более 50% flash памяти. Это не является проблемой для всех архитектур, исключая MEGA2560. Данный контроллер имеет очень скромные характеристики, поэтому приходится ужиматься. В пред-компилированной версии для этой архитектуры отключены почти все опциональные модули (DMX, Modbus, 1-wire). Но перекомпилировав проект, можно подключить нужные опции, пожертвовав чем-то еще (например, MDNS)
См файл build-flags/build_flags_mega2560-optiboot с опциями по умолчанию, которые можно переопределить в custom-build-flags/build_flags_mega2560-optiboot
Подробнее про опции компиляции в разделе [опции компиляции](https://www.lazyhome.ru/dokuwiki/doku.php?id=опции_компиляции)
## OptiBoot
Для того, чтобы Mega2560 имела возможность обновлять сама себе прошивку, необходимо заменить ее штатный кривой бутлоадер на optiboot. Кроме всего прочего, этот загрузчик занимает намного меньше места, чем штатный. Поэтому, если вы зачем-то до сих пор используете Mega - загрузчик лучше обновить (тем более, что у старых штатных загрузчиков не работает watchdog)
Проект Optiboot живет здесь: https://github.com/Optiboot/optiboot
Конкретно вариант для Mega2560 тут: https://github.com/MCUdude/MegaCore
Инструкция для загрузки там имеется. Шить проще всего "штатным" Arduino IDE, используя любую другую AVR Arduino в качестве программатора.
Как ее приспособить для этого, описано тут https://docs.arduino.cc/built-in-examples/arduino-isp/ArduinoISP/
## Где что лежит
Компилированные образы прошивок доступны в папке compiled
Там же размещены примеры скриптов, прошивающих образ (как по кабелю так и OTA)
Тулзы для этого выложены в папке compiled/tools
Пример прошивки по воздуху:
```
arduinoOTA -address 192.168.1.2 -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch
```
В примере приведены username и password по-умолчанию
Пароль необходимо сменить на свой
Задать пароль и сохранить его в NVRAM можно при помощи команды otapwd [cli_интерфейс](cli_interface.md)
для коммита прошивки от 20/05/24 и позднее, можно воспользоваться опциями компиляции DEFAULT_OTA_USERNAME и DEFAULT_OTA_PASSWORD
Примечание (2026-10-02): OTA в актуальных версиях прошивки переделана. Механизм управляется опцией компиляции `OTA_ENABLE` (флаг в `build-flags/build_flags_*` и код под `#ifdef OTA_ENABLE` в `lighthub/main.cpp`), обновление по воздуху для ESP-платформ осуществляется через библиотеку ArduinoOTA (форк https://github.com/anklimov/ArduinoOTA). Для ESP32/ESP8266 в `platformio.ini` задана таблица разделов `board_build.partitions = min_spiffs.csv`, выделенная под обновление прошивка больше не ограничена правилом «строго не более 50% flash» (комментарий в platformio.ini: «>50% space - ok for ESP due spare partition»). Правило 50% flash по-прежнему актуально для AVR-платформ (MEGA2560). Порт OTA по умолчанию 65280 (`OTA_PORT`, `lighthub/options.h:28-29`), для esp32-wifi задан `-DOTA_PORT=80`. В wiki не упомянута сборка esp32c3-wifi, также поддерживающая OTA.
## Сверка с кодом (2026-10-02)
- Корректно: опция `OTA_ENABLE` присутствует в build-flags для due, lighthub21, esp32-wifi, esp8266-wifi, mega2560, mega2560-optiboot, mega2560slim, m5stack и esp32c3-wifi.
- Корректно: `DEFAULT_OTA_USERNAME`/`DEFAULT_OTA_PASSWORD` (по умолчанию `arduino`/`password`) — `lighthub/options.h:394-399`; команда `otapwd` сохраняется пароль в NVRAM — `cmdFunctionOTAPwd` (main.cpp:1761), `systemConfig::setOTAPwd` (config.cpp:107).
- Устарело: утверждение об обязательном ограничении «не более 50% flash» для всех архитектур — для ESP32/ESP8266 теперь используется отдельный раздел flash (`min_spiffs.csv` в `platformio.ini`, строки 142, 205, 282).
- Уточнение: пример с утилитой `arduinoOTA` соответствует `upload_command` из `platformio.ini` (строки 133, 212) — утилита по-прежнему используется в скриптах прошивки.
+88
View File
@@ -0,0 +1,88 @@
# Интерфейс настройки контроллера
> Источник: Wiki LightHub (lazyhome.ru), страница «интерфейс_настройки». Снапшот от 2026-10-02.
### Интерфейс настройки контроллера
Постоянная память контроллера слишком мала, чтобы на ней можно было разместить полноценный интерфейс по его настройке.
Точнее, это можно сделать, но в ущерб функциональности, занимая ценную память и ресурсы для веб содержимого, совершенно бесполезного, когда контроллер уже настроен и просто работает
Поэтому Страница настройки изначально отсутствовала, вместо этого конфигурацию можно задавать через "портал" - https://lazyhome.ru/portal - Это описано тут [как LightHub работает с файлом конфигурации, простой метод настройки - через портал lazyhome.ru](config_file_workflow.md#простой-метод-настройки---через-портал-lazyhomeru)
Но это не единственный способ
После того, как у контроллера появился HTTP API, стало возможным использование браузера для настройки
Для настройки контроллера, можно обратиться на его адрес. Например
* http://192.168.1.55
* http://lighthub.local
контроллер отрабатывая этот запрос, подгрузит страницу управления с публичного ресурса, а уже она будет использовать [API](https://www.lazyhome.ru/dokuwiki/doku.php?id=api) контроллера в вашей локальной сети
* Первый недостаток - адрес надо знать и помнить
* Второй - зависимость от интернета и внешнего ресурса
* Главный недостаток: Начиная с последних версий браузера chrome данный способ перестал работать, так как google ужесточила требования к безопасности и запретила страницам, загруженным из интернета, обращаться к ресурсам локальной сети
Тем не менее, метод продолжает работать на браузере fireFox
Недавно я исследовал еще одну возможность сделать удобной настройку контроллеров в локальной сети - установив плагин для браузера chrome (для fireFox, также, это возможно)
## Плагин для браузера
Преимущества:
* Весь веб-контент лежит внутри плагина, в вашем браузере. Кроме того, что не требуется доступ в интернет, решается и вопрос безопасности - chrome позволяет браузеру использовать [API](https://www.lazyhome.ru/dokuwiki/doku.php?id=api) контроллера в локальной сети
* Появляется возможность поиска контроллеров в вашей локальной сети, так как в них давно реализован протокол MDNS
Недостаток тут только один - надо потратить 5 минут на установку этого плагина.
Так как браузер не имеет прав просканировать локальную сеть на предмет наличия контроллеров, плагин использует утилиту zeroconf_lookup которая была разработана в рамках открытого проекта https://github.com/railduino/zeroconf-lookup
На базе этого проекта, я сделал прототип плагина для конфигурирования контроллеров lighthub
https://github.com/anklimov/zeroconf-lighthub
Плагин состоит из двух частей:
* Собственно плагин браузера
* Утилита поиска zeroconf-lookup
### Скачивание проекта
Скачивание и разархивирование надо сделать перед началом всех последующих действий
- На странице проекта https://github.com/anklimov/zeroconf-lighthub скачиваем архив (нажать зеленую кнопку Code и выбрать download ZIP)
- Разархивируем в какую-либо папку, которую вы в дальнейшем не будете удалять (например \Users\youName\plugin)
- (если вы разработчик - вместо предыдущих двух пунктов, вы, конечно, предпочтете использовать утилиту git) `git clone https://github.com/anklimov/zeroconf-lighthub`
### Как установить плагин:
* Установить из магазина приложений Chrome (чуть позже выложу)
* Установить из папки, скачанной с ГитХаб в режиме разработчика. Это не сильно сложнее, но позволит дорабатывать плагин (очень надеюсь на то, что кто-то будет его дорабатывать, я не веб разработчик).
* Для этого открываем браузер chrome, в меню "расширения" выбираем "управление расширениями".
* Включаем переключатель "режим разработчика",
* нажимаем кнопку"Загрузить распакованное расширение".
* Выбираем папку __zeroconf-lighthub-master/Chrome__ в распакованном на предыдущем этапе архиве
* Расширение устанавливается, заглядываем на страницу его свойств и копируем идентификатор расширения (например gepnlbipogackhpjkojhkonkijdgpgji ) это нам пригодится чуть позже
### Как установить утилиту:
### Windows
- Переходите в каталог __zeroconf-lighthub-master\Windows_Go__
- Из командной строки запускаете - `zeroconf_lookup.exe -i -с gepnlbipogackhpjkojhkonkijdgpgji` (тут укажите ваш идентификатор расширения, скопированный на предыдущем этапе)
- После этого переносить данный файл с этого места или удалять папку нельзя
- Если ставили плагин из магазина приложений - можно при запуске не указывать идентификатор расширения. `zeroconf_lookup.exe -i`
### MacOS
то же самое, только выполнимый файл лежит в директории __zeroconf-lighthub/Apple_Go__
### Использование
Теперь все просто - нажимаем на иконку расширения - оно сканирует сеть и выдает перечень всех контроллеров онлайн в локальной сети (и не только контроллеров - любых устройств, которые заявляют о себе)
Для входа в настройки контроллера надо нажать Edit напротив него в списке
## Сверка с кодом (2026-10-02)
- Корректно: обращение по адресу контроллера (`http://<ip>` / `http://<имя>.local`) приводит к 301-редиректу на страницу управления с публичного ресурса: `httpHandler` в `lighthub/main.cpp:264-286` отвечает `Location: http://<REDIRECTION_URL>?mac=...&ip=...&port=...&name=...`. По умолчанию `REDIRECTION_URL` для esp32-wifi задан как `http://lazyhome.ru/pwa` (`build-flags/build_flags_esp32-wifi`), то есть «портал» подгружается с lazyhome.ru и дальше использует HTTP API контроллера.
- Корректно: MDNS-анонс контроллера реализован (`MDNS.addService("http", "tcp", OTA_PORT)`, main.cpp:650; на STM — `mdns.addServiceRecord`, main.cpp:1332), на этом основан поиск плагина через zeroconf_lookup.
- Корректно: веб-контент не размещается в памяти контроллера — в коде есть только HTTP API: `GET/POST /item/<имя>`, `GET /ram/[<имя>]`, `POST /command/<команда>` (подача CLI-команд по HTTP), `POST /config.json` (локальное изменение конфига отключает загрузку с портала, main.cpp:368-374).
- Примечание: ограничение Chrome на доступ внешних страниц к локальной сети — особенность браузеров, описана верно; рекомендация по fireFox/плагину актуальна.
+215
View File
@@ -0,0 +1,215 @@
# Заливка прошивки
> Источник: Wiki LightHub (lazyhome.ru), страница «заливка_прошивки». Снапшот от 2026-10-02.
## Заливка уже откомпилированной прошивки
В первую очередь необходимо скачать сам проект.
Это можно сделать либо с использованием утилиты git:
`git clone https://github.com/anklimov/lighthub.git`
Либо, если у вас она не установлена - открываем [https://github.com/anklimov/lighthub](https://github.com/anklimov/lighthub)
Далее, нажимаем зеленую кнопку "Clone or download"
Выбираем пункт "Download ZIP", скачиваем и распаковываем архив
Переходим в директорию lighthub-master/compiled/<требуемая_платформа> (список платформ выше)
Подключаете плату USB кабелем к компьютеру (кроме платформы NRF52 - там программирование только при помощи специального устройства JLink, об этом позже)
В диспетчере устройств находите порт, на который села плата (например, com3)
корректируете номер порта в файле upload.bat, который находится в директории, в которую вы вошли
Запускаете файл на выполнение (если выдается запрос "нажмите любую клавишу" - нажимаете)
Прошивка должна загрузиться в ваш контроллер.
## Компиляция и заливка с использованием platformio + Atom или VSC
Проект создан с использование Platformio , аналога Arduino IDE.
Сперва необходимо скачать Visual Studio Code или Atom, установить Platformio в качестве плагина. В интернете много материалов и видеоуроков на эту тему. Скорее всего потребуется установить клиент Git (Для Windows https://git-scm.com/download/win).
Далее, как и в предыдущем случае, необходимо скачать сам проект.
Проект создан с использование Platformio , аналога Arduino IDE.
Это можно сделать либо с использованием утилиты git:
`git clone https://github.com/anklimov/lighthub.git`
Либо, если у вас она не установлена - открываем [https://github.com/anklimov/lighthub](https://github.com/anklimov/lighthub)
Далее, нажимаем зеленую кнопку "Clone or download"
Выбираем пункт "Download ZIP", скачиваем и распаковываем архив
В Atom или VSC выбираем пункт "Открыть директорию" (Open Folder), и указываем директорию lighthub.master (или в директорию lighthub если использовался git)
Далее, выбираем файл platformio.ini и раскомментариваем в нем нужный вам вариант платформы (платы) в пункте env_default (убираем ; перед строкой, содержащей нужную платформу, добавляем - перед строкой, содержащей ненужные платформы)
NEW - если используете среду VSC (рекомендуется) - то можете ничего не комментировать/раскомментировать а просто выбрать нужную платформу в меню "switch PlatformIO Project environment" (нажмите на Default (lighthub) в самом низу экрана)
**Для платформы DUE:** обязательно придется найти фаил variant.cpp по пути
`.platformio/packages/framework-arduinosam/variants/arduino_due_x`
и вставить в него **последней строкой** следующую строку
`void USART0_Handler(void) __attribute__((weak));`
сохранить.
(К сожалению, внести это простое изменение в штатный репозиторий arduino не удалось никому из тех, кто создавал Pull request)
Нажимаем кнопку "Build"
Platformio скачивает все нужные библиотеки и компилирует код. Возможно придется несколько раз повторить эту операцию, так как по непонятным причинам, platformio может выдавать ошибки, не скачав какую-то библиотеку.
Если компиляция прошла успешно, можно подключить плату USB кабелем и нажать кнопку Upload
## Компиляция и заливка с использованием platformio. Вариант командная строка
Для того что бы прошить плату в первую очередь необходимо скачать сам проект [https://github.com/anklimov/lighthub](https://github.com/anklimov/lighthub) и установить Platformio
* Если Вы считатет себя джедаем и не ищете легких путей то работать с платформио можно через командную строку. Для этого нужно:
- установить Python 2.7,
- установить git.
* Модифицировать PATH. идем: мой компьютер->правой кнопокой мыши вызываем контекстное меню->свойства->в появившемся окне "переменные среды"-> в окне "Системные переменные" выбираем переменную Path ->изменить->добавляем строку
`;C:\Python27;C:\Python27\Scripts`
* Установить Platformio открываем командную строку (поиск в "Пуске" cmd.exe) вводим команду
`pip install -U platformio`
Учтите, что Platformio установится по умолчанию в папку пользователя `С:\Пользователи\Имя пользователя\.platformio` Python 2.7 не поддерживает кириллицу, если имя пользователя написано кириллицей, необходимо скопировать папку Platformio в корень диска C:\ и изменить путь к рабочему каталогу в фале platformio.ini (который находится в ранее скачанной папке lighthub-master), указав после строки [platformio] следующую строку: `home_dir = C:\.platformio`
Сохраняем файл.
Открываем папку lighthub-master, в строке отображающей путь вводим cmd и нажимаем enter или же выбираем папку в командной строке любым другим способом.
**Для платформы DUE:** обязательно придется найти фаил variant.cpp по пути
`.platformio/packages/framework-arduinosam/variants/arduino_due_x`
и вставить в него **последней строкой** следующую строку
`void USART0_Handler(void) __attribute__((weak));`
сохранить.
Далее вводим `pio run -e <платформа>`
Вариант <платформа> выберете в зависимости от используемой аппаратной платформы.
```
; Arduino Mega compact build + Ethernet shield Wiznet 5X00, 1-wire, thermostates.
; mega2560slim
; Another Arduino Mega compact build without 1-wire, DMX, but with OTA
; OPTIBOOT bootloader required! https://github.com/MCUdude/MegaCore
; mega2560-optiboot
; Arduino Mega + Ethernet shield Wiznet 5100
; mega2560-5100
; Arduino Mega (Ethernet shield Wiznet 5X00, DMX, Artnet)
; mega2560
; LightHub controller HW revision 2.1 and above (Wiznet 5500 CS on pin 53)
; Если у вас плата LightHub версии 2.1 или более новая + DUE - используйте эту конфигурацию
; **lighthub21**
; Arduino DUE + Ethernet shield Wiznet 5X00
; Предпочтительный вариант для DUE с Ethernet Shield (не для платы LightHub), базированный на универсальном драйвере
; **due**
; ESP 8266
; **esp8266-wifi**
; ESP-32
; **esp32-wifi**
; ESP-32-C3
; **esp32c3-wifi**
; M5Stack core (ESP32 based)
; m5stack
; Controllino
; controllino
; STM32 board + ENC28j60 network
; stm32-enc2860
; STM32 board (olmexino) with WIZNET 5X00 network
; stm32
; STM32 board, no IP (LightSpot)
; stm32-noip
; NRF52 board + Wiznet 5x00 network
; nrf52840
```
> **Примечание (сверка с кодом, 2026-10-02):** в оригинальном тексте wiki список целей в этом блоке был устаревшим — там фигурировали `mega2560slim-5100`, `mega2560-5500`, `due-5100`, `due-5500` и `nrf52840-5500`, а отсутствовали `nrf52840`, `mega2560`, `mega2560-optiboot`, `esp32c3-wifi`, `stm32`, `stm32-noip`. Список выше восстановлен по фактическим окружениям из `platformio.ini`.
Пример: "due" - это плата Arduino DUE + Ethernet Shield на чипе Wiznet-5X00 (универсальный драйвер)
**В общем случае, используйте варианты без указания 5100 или 5500 - в этом случае будет использован универсальный драйвер Wiznet**
Если плата LightHub версии 2.1 или выше то используйте опцию "lighthub21"
Проект должен скомпилироваться без ошибок.
**ЧАСТО Platformio выдает ошибки на ровном месте (не находит какие-либо файлы). В этом случае, повторный запуск компиляции часто решает эту проблему**
Если ошибок нет вводим `pio run -e <платформа> -t upload`
Программа должна залиться в аппаратную платформу.
Если возникли ошибки:
Попробовать очистить папку с библиотеками .piolibdeps и .pioenv удалив все их содержимое
## Использование Arduino IDE для компиляции и заливки прошивки
Это достаточно трудоемкий процесс, который требует, чтобы вы вручную установили массу библиотек в IDE.
platformio - намного более гибкое и профессиональное средство - лучше и проще использовать его.
Если для кого-то будет важно освоить именно этот метод - пишите, мы пополним инструкцию.
Если возникают проблемы - пишите на форуме или в [группу Телеграмм](https://t.me/lighthub)
(Вы, также, можете улучшать эту инструкцию)
---
## Сверка с кодом (2026-10-02)
**Фактические окружения (env) в `platformio.ini`:**
| env | Платформа / описание | Папка в `compiled/` |
|-----|----------------------|---------------------|
| `due` | Arduino DUE, универсальный Wiznet-драйвер | `due/` |
| `lighthub21` | LightHub HW rev 2.1+ (Wiznet 5500, CS на пине 53), DUE | `lighthub21/` |
| `mega2560` | Arduino Mega + Wiznet 5X00, DMX, Artnet | `mega2560/` |
| `mega2560slim` | Mega компактная сборка + Wiznet, 1-wire, термостаты | `mega2560slim/` |
| `mega2560-optiboot` | Mega компактная + OTA (нужен OPTIBOOT) | `Mega2560-optiboot/` |
| `mega2560-5100` | Mega + Ethernet Wiznet 5100 | `mega2560-5100/` |
| `esp8266-wifi` | ESP8266 (Wi-Fi) | `esp8266-wifi/` |
| `esp32-wifi` | ESP32 (Wi-Fi) | `esp32-wifi/` |
| `esp32c3-wifi` | ESP32-C3 (Wi-Fi) | `esp32c3-wifi/` |
| `m5stack` | M5Stack (ESP32) | `m5stack/` |
| `nrf52840` | NRF52840 + Wiznet 5x00 | `nrf52840/` |
| `controllino` | Controllino (AVR) | `controllino/` |
| `stm32` | STM32 (olmexino) + WIZNET 5X00 | `stm32/` |
| `stm32-enc2860` | STM32 + ENC28J60 | `stm32-enc2860/` |
| `stm32-noip` | STM32, без IP-стека (LightSpot) | — (папки нет) |
(Также в `platformio.ini` есть служебные env `Upload_ISP` и `fuses_bootloader` для прошивки OPTIBOOT — они не являются целевыми сборками.)
**Папки в `compiled/`:** `controllino`, `due`, `DUE_16u2_reflash`, `esp32-wifi`, `esp32c3-wifi`, `esp8266-wifi`, `lighthub21`, `m5stack`, `mega2560`, `mega2560-5100`, `Mega2560-optiboot`, `mega2560slim`, `nrf52840`, `nrf52840-5500`, `stm32`, `stm32-enc2860`, `tools`.
**Расхождения wiki ↔ кода:**
- Список целей в wiki устарел: упоминаются несуществующие env `mega2560slim-5100`, `mega2560-5500`, `due-5100`, `due-5500`. В текущем `platformio.ini` их нет — для DUE и Mega используется универсальный Wiznet-драйвер (`due`, `mega2560`). Список в тексте исправлен по факту (см. примечание выше).
- `nrf52840-5500` в wiki указан как env, в `platformio.ini` такого env нет (есть только `nrf52840`), но в `compiled/` папка `nrf52840-5500/` присутствует — вероятно, это отдельная уже скомпилированная сборка, не являющаяся отдельным env.
- `stm32-noip` — есть в `platformio.ini`, но готовой папки в `compiled/` нет.
- `DUE_16u2_reflash/` в `compiled/` — утилита для перепрошивки USB-чипа 16u2, не целевая сборка.
- Замечание о DUE: инструкция про правку `variant.cpp` (добавление `void USART0_Handler(void) __attribute__((weak));`) актуальна — в репозитории собственного `lighthub/variant.cpp` нет, используется вариант DUE из пакета PlatformIO `framework-arduinosam`.
@@ -0,0 +1,69 @@
# LightHub на разном железе
> Источник: Wiki LightHub (lazyhome.ru), страница «lighthub_на_разном_железе». Снапшот от 2026-10-02.
Прошивка может компилироваться и работать на следующих аппаратных платформах:
1. AVR Arduino MEGA 2560 - первая платформа, на которой была реализована. Прошивка оттестирована на этом железе. Но в настоящее время, уже не рекомендуется по причине ограниченной оперативной памяти. (не получится использовать всю периферию, но для небольших инсталляций подойдет)
2. Arduino DUE - в настоящее время, базовая платформа. Используется в контроллерах LightHub. Прошивка тщательно оттестирована на этом железе. Все новые функции изначально внедряются под эту платформу.
3. ESP8266 - Достаточно полнофункциональная стабильная сборка.
4. ESP32 - Достаточно полнофункциональная стабильная сборка.
5. NRF52840 - пилотная сборка, поддерживающая базовый функционал
6. STM32 - сборка с ограниченной функциональностью, является базовой для устройства LightSpot (минимальное LightHub устройство без IP стека, которое взаимодействует с внешним миром через полноценные устройства LightHub по шинне CAN)
Базовые возможности прошивки LightHUB поддерживаются на любом железе. К ним относится:
* Единообразное конфигурирование с использованием JSON
* Поддержка MQTT и интеграция, фактически, с любой системой Умного Дома, поддерживающей данный протокол, включая, сенсоры, выключатели, термостаты(теплые полы), кондиционеры.
* Поддержка всего расширенного набора команд, группы каналов, сохранение цвета/яркости и пр
* Восстановление состояния контроллера и каналов при перезапуске из MQTT
* Локальное управление каналами (даже при отсутствии сетевого соединения)
* Термостаты (до 20-ти, в пределах кол-ва дискретных выходов)
* Гибкая настройка работы с выключателями/кнопками, включая распознавание одинарного, двойного, тройного нажатия, длительного нажатия, кратковременного выключения
Возможности прошивки, зависящие от железа:
| Возможность | Mega2560 | DUE | ESP8266 | ESP32 | NRF52840 | STM32 | CONTROLLINO |
|---|---|---|---|---|---|---|---|
|DMX512 In|+|+|-|-|-|-|-|
|DMX512 Out|+|+|+|+|-|-|-|
|Artnet|+|+|+|-|?|?|+|
|1-Wire software|+|+|+|+|+|?|+|
|1-Wire DS2482-100|+|+|+|+|+|+|+|
|MCP23017 - I2C расширитель портов|+|+|+|?|?|?|?|
|Wiznet 5100 Ethernet|+|+|+|+|-|+|+|
|Wiznet 5500 Ethernet|+|+|+|+|+|+|-|
|Wi-Fi|-|-|+|+|-|-|-|
|Modbus Master|+|+|+|+|+|+|+|
|DHT-22|+|+|+|+|+|?|+|
|CCS811 & HDC1080 - сенсоры влажности и eCO2|+|+|+|+|+|?|+|
|Управление кондиционерами Haier через UART|+|+|+|+|+|+|+|
|Управление задвижками вентиляции с резистором ОС|+|+|+|+|?|?|+|
|SPI-LED адресные ленты|+|+|+|+|+|+|+|
|Watchdog|+|+|?|?|?|?|+|
|Сохранение конфигурации во FLASH|+|+|+|+|-|?|+|
|CAN|-|+|-|+|-|+|-|
|Дискретных входов||||||||
|Аналоговых входов||||||||
|Дискретных выходов||||||||
|PWM выходов||||||||
|OTA|+-Optiboot bootloader|+|+|+|-|-|-|
|Плавное управление DMX|-|+|-|-|-|-|-|
(Легенда: `+` — поддерживается, `-` — не поддерживается, `?` — не проверено / зависит от конкретной реализации.)
---
## Сверка с кодом (2026-10-02)
- Перечень платформ в тексте (Mega2560, DUE, ESP8266, ESP32, NRF52840, STM32) **совпадает** с окружениями `platformio.ini`: `mega2560`/`mega2560slim`/`mega2560-optiboot`/`mega2560-5100`, `due`/`lighthub21`, `esp8266-wifi`, `esp32-wifi`/`esp32c3-wifi`/`m5stack`, `nrf52840`, `stm32`/`stm32-enc2860`/`stm32-noip`, а также `controllino`.
- Текст не упоминает **ESP32-C3** (env `esp32c3-wifi`) и **M5Stack** (env `m5stack`, ESP32-based) — в таблице возможностей у них стоит колонка ESP32; фактически это отдельные сборки.
- **STM32 / LightSpot**: в `platformio.ini` есть `stm32-noip` — сборка без IP-стека (LightSpot), что соответствует описанию в п. 6.
- **CAN**: в таблице отмечен только для DUE и ESP32/STM32. В `lighthub21`/`due` используется библиотека `collin80/due_can` (см. `platformio.ini`), для ESP32 — `anklimov/arduino-CAN`, для STM32 (stm32-noip) — `pazi88/STM32_CAN`. Совпадает.
- **Wi-Fi** только у ESP8266/ESP32 — подтверждается наличием `WIFI_ENABLE`/`WiFiManager` только в ESP-окружениях.
- **Сохранение конфигурации во FLASH** не поддержано у NRF52840 в таблице — в env `nrf52840` используется `NRFFlashStorage`/`d00616/arduino-NVM`, что требует уточнения (в таблице стоит `-`/`?`).
+51
View File
@@ -0,0 +1,51 @@
# MAC-адрес контроллера
> Источник: Wiki LightHub (lazyhome.ru), страница «mac_адрес». Снапшот от 2026-10-02.
Важно, чтобы у вашего контроллера был уникальный MAC адрес.
Это важно не только потому, что в пределах одной локальной сети два контроллера с одинаковыми MAC не могут работать но еще и потому, что при старте, контроллер загружает с сервера конфигураций или с других контроллеров по шине CAN свою настройку, используя MAC как свой уникальный ключ.
У разных аппаратных платформ ситуация с MAC адресами разная:
* ESP8266 и ESP32 и так имеют уникальные адреса, тут ничего мудрить не надо
* DUE и STM имеют уникальный ID каждого чипа, из которого прошивка генерирует уникальный MAC
* Mega2560 не имеет такого ID, но, зато, имеет честный EEPROM, в который при первом запуске этот адрес можно записать и он сохранится на всю жизнь, даже если контроллеру обновлять прошивку
Кроме этого, при компиляции прошивки, можно задать опцию `CUSTOM_FIRMWARE_MAC` - в этом случае, у прошивки будет такой MAC адрес, как вы задали
Также, MAC адрес можно заменить командой `mac DE:22:33:11:22:33`, подключившись к контроллеру через [CLI-интерфейс](../core/cli_interface.md) (вместо DE:22:33:11:22:33 - ваш адрес)
В случае Mega2560 это будет запомнено навсегда, в случае DUE - до следующей загрузки прошивки.
Замену MAC через опцию либо через команду не тестировал на ESP - там это совсем не нужно.
Для того, чтобы самостоятельно сгенерировать MAC - прочитайте [Википедию](https://ru.wikipedia.org/wiki/MAC-адрес#.D0.A1.D1.82.D1.80.D1.83.D0.BA.D1.82.D1.83.D1.80.D0.B0_MAC-.D0.B0.D0.B4.D1.80.D0.B5.D1.81.D0.B0)
Если коротко, то у самой первой цифры, два младших бита должны быть "10", что соответствует не Multicast адресу, отвязанному от производителя
Если лень считать, возьмите первую цифру Макадреса, например, DE или 02, остальное - придумывайте как хотите
Посмотреть MAC адрес вашего контроллера проще всего, подключившись по USB - он будет выведен при перезагрузке контроллера
См. [как LightHub работает с файлом конфигурации — подключение по USB](../core/config_file_workflow.md)
---
## Сверка с кодом (2026-10-02)
Проверено по `lighthub/main.cpp` (функция `setupMacAddress()`, строка 2817) и `lighthub/options.h`.
Логика генерации MAC в `setupMacAddress()` (при отсутствии MAC в NVRAM) выстроена цепочкой условий, что **полностью подтверждает** описание в wiki:
| Платформа | Механизм в коде | Строки | Соответствие wiki |
|---|---|---|---|
| (все) `CUSTOM_FIRMWARE_MAC` | MAC разбирается из build-flag (`parseBytes(macStr, ':', ...)`), затем принудительно: `mac[0] &= 0xFE; mac[0] \|= 2;` (locally-administered, не multicast) | main.cpp:2823-2828 | ✅ «опция CUSTOM_FIRMWARE_MAC» |
| ESP8266/ESP32 (`WIFI_ENABLE`) | Используется штатный MAC чипа: `WiFi.macAddress(sysConf.mac)` | main.cpp:2830-2833 | ✅ «ESP и так имеют уникальные адреса» |
| DUE (`__SAM3X8E__`) / STM32 (`ARDUINO_ARCH_STM32`) | MAC генерируется из серийного номера чипа: `mac[0]=0xDE;` остальные байты = сумма байтов `UniqueID.UID_Byte[]` | main.cpp:2835-2840 | ✅ «DUE и STM имеют уникальный ID чипа» |
| fallback `DEFAULT_FIRMWARE_MAC` | Хардкод `{0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xFF}` | options.h:180 | (доп. fallback, в wiki не описан) |
**Дополнительные подтверждения:**
- **Mega / EEPROM**: MAC хранится в NVRAM и читается в `systemConfig::getMAC()` (`config.cpp:44-47`), область EEPROM описана константой `OFFSET_MAC`/`EEPROM_FIX_PART_LEN` (`options.h:128`). Для Mega запись в EEPROM сохраняется при перепрошивке — согласуется с утверждением «запомнено навсегда».
- **Команда `mac`**: обработчик `cmdFunctionSetMac` (`main.cpp:1820`) парсит адрес формата `de:ad:be:ef:fe:00` и сохраняет его в EEPROM. Команда регистрируется только при `not FLASH_64KB` (`main.cpp:2860`). Подтверждает возможность замены MAC командой.
- **Вывод MAC по USB**: функция `printMACAddress()` (`main.cpp:543`) выводит адрес в `infoSerial` при старте — совпадает с «выведен при перезагрузке контроллера».
**Нюанс (расхождение):** wiki утверждает, что замена MAC командой/опцией «не тестировал на ESP». В коде для ESP32 при старте вызывается `wifi_set_macaddr(STATION_IF, sysConf.mac)` (`main.cpp:1207`) — то есть механизм замены MAC на ESP в коде присутствует, хоть и, вероятно, не всегда применяется на практике.
+240
View File
@@ -0,0 +1,240 @@
# Входы и выходы платы LightHub
> Источник: Wiki LightHub (lazyhome.ru), страница «входы_выходы». Снапшот от 2026-10-02.
## Электропитание
Контроллер имеет на борту DCDC преобразователь, который может обеспечивать питание устройства, а также, воспомогательных приборов от напряжения в диапазоне 12-29В
(Только v2.2) При превышении напряжения 30В, а также, при переполюсовке, сработает защитный TWS диод, замкнув цепь питания, что приведет к отключению самовосстанавливающегося предохранителя контроллера, рассчитанного на ток 1,2А либо к срабатыванию защиты используемого блока питания.
DCDC преобразователь может работать в двух режимах, выбираемых джампером JХ (серый на рисунке ниже)
Если джампер замкнут - выходное напряжение преобразователя составляет 5В, если разомкнут - 7В (на более ранних версиях железа было 9В, но мы уменьшили это значение для меньшего тепловыделения на линейном стабилизаторе устройства)
~~Процессорная плата Ардуино может питаться как с выхода DCDC преобразователя так и непосредственно от входного питания устройства.
Режим питания платы Ардуино выбирается джампером J4 (желто-фиолетовый на рисунке ниже)
В "желтом" режиме, Ардуино питается с выхода DCDC, в фиолетовом - от входного питания.
_Важно: при использовании второго (фиолетового) режима, контроллер следует питать от источника 12В. Использование источника 24В выведет процессорную плату из строя_~~
Внимание: Используйте контроллер версии 2.2 ТОЛЬКО в режиме, когда плата Ардуино питается от DCDC преобразователя. (J4 в Желтом режиме). Испытания показали, что DCDC преобразователь в ином случае работает нестабильно.
Если выбран режим питания Ардуино от DCDC преобразователя, преобразователь должен быть настроен на напряжение 7В (джампер JX разомкнут), так как 5В, в большинстве случаев, недостаточно для стабильной работы Ардуино.
Соответственно, единственное допустимое расположение джамперов: J4 - Желтый режим, JX-разомкнут
В этом режиме напряжение 7В с выхода DCDC преобразователя можно использовать для питания внешних цепей до 2А
~~Режим преобразователя 5В может быть использован для питания внешней нагрузки током до 2,5А подключенной к винтовым клеммам X24 в том случае, если контроллер запитан от внешнего источника 12В~~
В данном режиме, входное напряжение питания контроллера: 12-24В
(рекомендуется 12В для уменьшения нагрузки на линейный стабилизатор опорного напряжения 10В)
~~Возможные конфигурации электропитания
|Входной диапазон |J4 |JX | Макс. ток UEXT 3.3V | Макс. ток UEXT 5V |Примечание|
|---|---|---|---|---|---|
|12-24В| DCDC (желтый)| OPEN (9V)|100mA|600mA|На клеммах X24 напряжение 9В|
|12В| Vin (фиолетовый)| OPEN (9В)|100mA|300mA|На клеммах X24 напряжение 9В|
|12В| Vin (фиолетовый)| CLOSED (5В)|300mA|300mA|На клеммах X24 напряжение 5В|~~
Джампером J2 можно задать напряжение, подаваемое на переферийный разъем стандарта UEXT
Возможны варианты 3,3В (стандартное напряжение UEXT) и 5В (нестандартное, но требуемое для ряда модулей)
См. рисунок ниже.
Контроллер поставляется с перемычками, установленными для работе в диапазоне питающих напряжений 12-24В и UEXT 3,3В
_Внимание: логические уровни сигналов на разъеме UEXT соответствуют применяемой процессорной плате: 5В для MEGA2560 и 3,3В для DUE_
_Подача уровней, превышающие данные значения, могут вывести процессор из строя._
## Версия платы 2.2
### Разьемы и джамперы
(см. иллюстрацию на [wiki-странице](https://www.lazyhome.ru/dokuwiki/doku.php?id=входы_выходы) — `инфографика.pdf`, В PDF)
(см. иллюстрацию на [wiki-странице](https://www.lazyhome.ru/dokuwiki/doku.php?id=входы_выходы) — `lighthub22_pinout.png`)
В этой таблице приведено соответствие физических PIN-ов Arduino Mega/DUE и входов/выходов платы LightHub 2.2
**В конфигурации контроллера пока можно использовать только цифровое значение из столбца MPU PIN**
Выберете по таблице интересующий вход или выход, найдите в таблице номер MPU PIN, его используйте в конфиге
Также, таблица пригодится чтобы преобразовать названия аналоговых каналов в цифровой номер PIN
_Внимание: максимальные уровни сигналов на клеммниках PWM 0-3, PWM 10, и разъеме RJ-45 (UNPROT 0-7) соответствуют применяемой процессорной плате: 5В для MEGA2560 и 3,3В для DUE_
_Подача на данные разъемы напряжений, превышающие данные значения, могут вывести процессор из строя._
_Данные входы не защищены. Подключайте к ним только локальную слаботочную нагрузку_
| Mnemonic | MPU PIN # | Plug | Plug PIN | Gnd | Comment |
|---|---|---|---|---|---|
|A0|54|X36 (IDC)|3|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A1|55|X36 (IDC)|4|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A2|56|X36 (IDC)|5|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A3|57|X36 (IDC)|6|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A4|58|X36 (IDC)|7|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A5|59|X36 (IDC)|8|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A6|60|X36 (IDC)|9|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A7|61|X36 (IDC)|10|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|-|-|X36 (IDC)|17|13,14,15,16|CAN H - (Начиная с V3.0)|
|-|-|X36 (IDC)|18|13,14,15,16|CAN L - (Начиная с V3.0)|
|A8|62|X36 (IDC)|19|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A9|63|X36 (IDC)|20|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A10|64|X36 (IDC)|21|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A11|65|X36 (IDC)|22|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|DA12|66|X36 (IDC)|23|13,14,15,16|Дискретный защищенный вход (слаботочный выход)|
|DA13|67|X36 (IDC)|24|13,14,15,16|Дискретный защищенный вход (слаботочный выход) - не использовать в случае использования CAN (начиная с V3.0)|
|DA14|68|X36 (IDC)|25|13,14,15,16|Дискретный защищенный вход (слаботочный выход) - не использовать в случае использования CAN (начиная с V3.0)|
|DA15|69|X36 (IDC)|26|13,14,15,16|Дискретный защищенный вход (выход)|
|+10V|-|X36 (IDC26)|2|1|Опорное напряжение 10В|
|POUT0|22|X15||X14|Мощный дискретный выход|
|POUT1|23|X16|||Мощный дискретный выход|
|POUT2|24|X17|||Мощный дискретный выход|
|POUT3|25|X18|||Мощный дискретный выход|
|POUT4|9|X19|||Мощный PWM выход. Продублирован слаботочным на X11|
|POUT5|8|X20|||Мощный PWM выход. Продублирован слаботочным на X10|
|POUT6|11|X21|||Мощный PWM выход. Продублирован слаботочным на X12|
|POUT7|12|X22|||Мощный PWM выход. Продублирован слаботочным на X13|
|PWM0|4|X7|||Незащищенный PWM вход/выход |
|PWM1|5|X6|||Незащищенный PWM вход/выход |
|PWM2|6|X8|||Незащищенный PWM вход/выход |
|PWM3|7|X9|||Незащищенный PWM вход/выход |
|PWM10|10|X414|||Незащищенный PWM вход/выход |
|UNPROT0|33|X35 (RJ45)|1|Shield|Незащищенный дискретный вход/выход|
|UNPROT1|32|X35 (RJ45)|2||Незащищенный дискретный вход/выход |
|UNPROT2|31|X35 (RJ45)|3||Незащищенный дискретный вход/выход |
|UNPROT3|30|X35 (RJ45)|4||Незащищенный дискретный вход/выход |
|UNPROT4|29|X35 (RJ45)|5||Незащищенный дискретный вход/выход |
|UNPROT5|28|X35 (RJ45)|6||Незащищенный дискретный вход/выход |
|UNPROT6|27|X35 (RJ45)|7||Незащищенный дискретный вход/выход |
|UNPROT7|26|X35 (RJ45)|8||Незащищенный дискретный вход/выход |
|IN0|42|X27 (IDC26)|14|13|Опторазвязанный вход двухпроводный|
|IN1|44|X27 (IDC26)|12|11|Опторазвязанный вход двухпроводный|
|IN2|46|X27 (IDC26)|10|9|Опторазвязанный вход двухпроводный|
|IN3|48|X27 (IDC26)|8|7|Опторазвязанный вход двухпроводный|
|IN4|43|X27 (IDC26)|6|1|Опторазвязанный вход|
|IN5|45|X27 (IDC26)|5|1|Опторазвязанный вход|
|IN6|47|X27 (IDC26)|4|1|Опторазвязанный вход|
|IN7|49|X27 (IDC26)|3|1|Опторазвязанный вход|
|IN8|34|X27 (IDC26)|22|21|Опторазвязанный вход двухпроводный|
|IN9|36|X27 (IDC26)|20|17|Опторазвязанный вход двухпроводный|
|IN10|38|X27 (IDC26)|18|19|Опторазвязанный вход двухпроводный|
|IN11|40|X27 (IDC26)|16|15|Опторазвязанный вход двухпроводный|
|IN12|35|X27 (IDC26)|26|1|Опторазвязанный вход|
|IN13|37|X27 (IDC26)|25|1|Опторазвязанный вход|
|IN14|39|X27 (IDC26)|24|1|Опторазвязанный вход|
|IN15|41|X27 (IDC26)|23|1|Опторазвязанный вход|
|+10V|-|X27 (IDC26)|2|1|Опорное напряжение 10В|
### Варианты подключения к дискретным входам
Для гальванической развязки дискретных входов, использованы симметричные оптроны. Симметричные - это значит они открываются либо положительным либо отрицательным потенциалом (3-12В).
Это позволяет использовать фактически любые контактные или потенциальные датчики, соединенные как с плюсом питания так и с нулем.
8 из 16-ти оптронов (IN4-IN7, IN12-IN15) соединены одним общим проводом, который выведен на pin1 разьема Х27
Другие 8 оптронов (IN0-IN3, IN8-IN11) выведены обоими контактами на соответствующие выходы разьема X27, согласно таблице выше
Последовательно с входом оптрона установлен токоограничивающий резистор
Опционально, может быть запаян резистор "0 ом" с нижней стороны платы, который соединит Pin1 с общим проводом контроллера, но в стандартной поставке это не делается для сохранения универсальности.
Соответственно:
* Pin1 нужно самостоятельно подключить к общему нулю системы вовне контроллера - тогда входы (IN4-IN7, IN12-IN15) будут активироваться подачей напряжения 3-12В на соответствующие контакты X27 (например, на контакт 6 для активации входа IN4)
* Либо Pin1 можно подключить к источнику опорного напряжения 10В (Pin2) а соответствующий вход активировать соединением его с нулем. (Внимание, сначала при помощи омметра убедитесь что не впаян опциональный резистор, соединяющий Pin0 с нулем контроллера)
Для работы со входами (IN0-IN3, IN8-IN11) обратный контакт этих входов надо, также, подключить либо к нулю либо к опорному напряжению (X27 Pin 13, 11, 9, 7, 21, 17, 19, 15) по аналогии с Pin1
Это можно сделать как при помощи перемычек на клеммнике, так и запаивая специально выведенные джамперы на верхней стороне платы (возле оптронов)
Запаивание джампера подключает обратный вход соответствующего оптрона к Pin1, обьединяя его с общей группой входов
Возможность полностью гальванически изолировать контролируемый сигнал от контура LightHub бывает очень важна для обеспечения безопасности или помехозащищенности. Например, вы контролируете цепи, гальванически связанные с электросетью или удаленные обьекты, обьединение нулевых проводов которых с нулем контроллера крайне нежелательно (концевики ворот, например)
В этом случае, используйте входы (IN0-IN3, IN8-IN11) не подключая обратный контакт входа к цепям контроллера. Используйте два выделенных провода, чтобы подключить вход к контролируемому устройству.
## Версия платы 2.0 (устаревшая)
### Разьемы и джамперы
(см. иллюстрацию на [wiki-странице](https://www.lazyhome.ru/dokuwiki/doku.php?id=входы_выходы) — `lighthub2pinout.jpeg`)
В этой таблице приведено соответствие физических PIN-ов Arduino Mega/DUE и входов/выходов платы LightHub 2.0
**В конфигурации контроллера пока можно использовать только цифровое значение из столбца MPU PIN**
Выберете по таблице интересующий вход или выход, найдите в таблице номер MPU PIN, его используйте в конфиге
Также, таблица пригодится чтобы преобразовать названия аналоговых каналов в цифровой номер PIN
#### Таблица контактов
| Mnemonic | MPU PIN # | Plug | Plug PIN | Gnd | Comment |
|---|---|---|---|---|---|
|A0|54|X36 (IDC)|1|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A1|55|X36 (IDC)|2|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A2|56|X36 (IDC)|3|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A3|57|X36 (IDC)|4|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A4|58|X36 (IDC)|5|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A5|59|X36 (IDC)|6|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A6|60|X36 (IDC)|7|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A7|61|X36 (IDC)|8|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A8|62|X36 (IDC)|19|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A9|63|X36 (IDC)|20|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A10|64|X36 (IDC)|21|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|A11|65|X36 (IDC)|22|13,14,15,16|Аналоговый защищенный вход (слаботочный выход)|
|DA12|66|X36 (IDC)|23|13,14,15,16|Дискретный защищенный вход (слаботочный выход)|
|DA13|67|X36 (IDC)|24|13,14,15,16|Дискретный защищенный вход (слаботочный выход)|
|DA14|68|X36 (IDC)|25|13,14,15,16|Дискретный защищенный вход (слаботочный выход)|
|DA15|69|X36 (IDC)|26|13,14,15,16|Дискретный защищенный вход (выход)|
|POUT0|22|X15||X14|Мощный дискретный выход|
|POUT1|23|X16|||Мощный дискретный выход|
|POUT2|24|X17|||Мощный дискретный выход|
|POUT3|25|X18|||Мощный дискретный выход|
|POUT4|9|X19|||Мощный PWM выход. Продублирован слаботочным на X11|
|POUT5|8|X20|||Мощный PWM выход. Продублирован слаботочным на X10|
|POUT6|11|X21|||Мощный PWM выход. Продублирован слаботочным на X12|
|POUT7|12|X22|||Мощный PWM выход. Продублирован слаботочным на X13|
|PWM0|4|X7|||Незащищенный PWM вход/выход |
|PWM1|5|X6|||Незащищенный PWM вход/выход |
|PWM2|6|X8|||Незащищенный PWM вход/выход |
|PWM3|7|X9|||Незащищенный PWM вход/выход |
|UNPROT0|33|X35 (RJ45)|1|Shield|Незащищенный дискретный вход/выход|
|UNPROT1|31|X35 (RJ45)|2||Незащищенный дискретный вход/выход |
|UNPROT2|32|X35 (RJ45)|3||Незащищенный дискретный вход/выход |
|UNPROT3|30|X35 (RJ45)|4||Незащищенный дискретный вход/выход |
|UNPROT4|29|X35 (RJ45)|5||Незащищенный дискретный вход/выход |
|UNPROT5|28|X35 (RJ45)|6||Незащищенный дискретный вход/выход |
|UNPROT6|27|X35 (RJ45)|7||Незащищенный дискретный вход/выход |
|UNPROT7|26|X35 (RJ45)|8||Незащищенный дискретный вход/выход |
|IN0|42|X27 (IDC26)|12|11|Опторазвязанный вход двухпроводный|
|IN1|44|X27 (IDC26)|10|9|Опторазвязанный вход двухпроводный|
|IN2|46|X27 (IDC26)|8|7|Опторазвязанный вход двухпроводный|
|IN3|49|X27 (IDC26)|6|5|Опторазвязанный вход двухпроводный|
|IN4|43|X27 (IDC26)|4|25,26|Опторазвязанный вход|
|IN5|45|X27 (IDC26)|3|25,26|Опторазвязанный вход|
|IN6|47|X27 (IDC26)|2|25,26|Опторазвязанный вход|
|IN7|48|X27 (IDC26)|1|25,26|Опторазвязанный вход|
|IN8|34|X27 (IDC26)|20|19|Опторазвязанный вход двухпроводный|
|IN9|36|X27 (IDC26)|18|15|Опторазвязанный вход двухпроводный|
|IN10|38|X27 (IDC26)|16|17|Опторазвязанный вход двухпроводный|
|IN11|40|X27 (IDC26)|14|13|Опторазвязанный вход двухпроводный|
|IN12|35|X27 (IDC26)|24|25,26|Опторазвязанный вход|
|IN13|37|X27 (IDC26)|23|25,26|Опторазвязанный вход|
|IN14|39|X27 (IDC26)|22|25,26|Опторазвязанный вход|
|IN15|41|X27 (IDC26)|21|25,26|Опторазвязанный вход|
---
## Сверка с кодом (2026-10-02)
**Поиск variant.cpp / ldscripts (платформа DUE):**
- В репозитории **нет собственного** `lighthub/variant.cpp`. Для DUE используется вариант из пакета PlatformIO `.platformio/packages/framework-arduinosam/variants/arduino_due_x/variant.cpp` (см. [flashing.md](flashing.md) — нужно добавить в него `void USART0_Handler(void) __attribute__((weak));`).
- В каталоге `ldscripts/` есть только лд-скрипты STM32 (`stm32f103rb.ld` и т.п.); **DUE-лд-скриптов в репозитории нет**.
- В исходном коде пины каналов **не заданы фиксированной таблицей** — конфиг ссылается на номера пинов напрямую (цифровое значение столбца «MPU PIN»), поэтому автоматической сверки «wiki ↔ код» по конкретным пинам не проводится. Таблица wiki является эталонной картой пинов платы.
**Соответствие номеров пинов стандартной распиновке DUE:**
- Аналоговые входы `A0`–`A11` → пины **54–65** — **совпадает** со стандартной нумерацией аналоговых пинов Arduino DUE (A0=54 … A15=69). Расхождений нет.
- Остальные пины (POUT 8–25, PWM 4–10, UNPROT 26–33, IN 34–49) — все в диапазоне цифровых пинов DUE (0–53), соответствуют стандартной нумерации.
**Различия между ревизиями платы (2.2 и 2.0):**
- Столбец **MPU PIN # идентичен** в обеих таблицах — номера пинов MCU не менялись между ревизиями.
- Различается столбец **Plug PIN** (физические контакты разъемов X36/X27/X35) — например, в rev 2.2 для `A0`–`A7` это контакты 3–10 X36, а в rev 2.0 — 1–8; раскладка опто-входов IN в X27 тоже отличается. Это изменение именно **реvisions платы**, а не программных пинов — при работе в конфиге всегда используйте столбец **MPU PIN #** (он одинаков).
- В rev 2.2 добавлены контакты CAN H/L (X36 пины 17/18, начиная с V3.0) и вход PWM10 (X414, пин 10), которых нет в rev 2.0.
+101
View File
@@ -0,0 +1,101 @@
# Подключение 1-Wire датчиков
> Источник: Wiki LightHub (lazyhome.ru), страница «подключение_1-wire_датчиков». Снапшот от 2026-10-02.
## Подключение к контроллеру
Подключение производится к клеммам:
- X5 - +5В
- X4 - GND
- X3 - 1wire
(см. иллюстрацию на [wiki-странице](https://www.lazyhome.ru/dokuwiki/doku.php?id=подключение_1-wire_датчиков), файл 1wire.png)
На рисунке снизу вверх черными точками: 5B, gnd, 1wire.
## Конфигурация контроллера
Дополнительная информация по настройке приведена тут [конфигурирование: что такое execobj](https://www.lazyhome.ru/dokuwiki/doku.php?id=конфигурирование#что_такое_execobj)
В корне прописываем:
```json
"ow":{
"АДРЕС_ДАТЧИКА":{"emit":"Temperature01"}
},
```
АДРЕС_ДАТЧИКА в виде: 282DA307D6013C08
## MQTT
Подписываемся на топик "myhome/s_out/Temperature01" и получаем значения температуры.
## Простой релейный термостат (теплый пол)
добавляем
```json
"items":{
"local_termostat":[5,24,33]
}
```
5 - тип релейный термостат
24 - номер пина
33 - (опционально) - температура по-умолчанию
Добавляем связку между термометром и локальным термостатом
```json
"ow":{
"282DA307D6013C08":{"emit":"Temperature01", "item":"local_termostat/val"}
},
```
Настройка завершена
Суффикс /val при передаче температуры локальным обьектам можно не добавлять
Значение температуры, также, может быть принято с внешних систем или иных контроллеров по MQTT c использованием топика формата /myhome/controller-id/local_termostat/val
При отсутствии показаний в течение 10 мин термостат отключается и переходит в аварийный режим, выдавая аварию в топик /alarm
Термостат принимает значение температуры через суффикс /set
Через командный суффикс /cmd принимаются команды
- ON
- OFF
- AUTO
- HEAT
- HALT
- REST
- XON
- XOFF
Подробнее тут [работа с mqtt: команды, применимые для кондиционера и термостата](https://www.lazyhome.ru/dokuwiki/doku.php?id=работа_с_mqtt#команды_применимые_для_кондиционера_и_термостата)
## Поиск устройств на шине
Начиная с v4.3 автоматическое периодическое сканирование шины 1-wire отменено. Датчики опрашиваются последовательно, согласно настройкам в разделе ow
Чтобы просканировать шину и узнать адреса вновь подключенных устройств, можно выдать команду search в [CLI интерфейс](../core/cli_interface.md)
Результаты сканирования будут выданы в лог
## Сверка с кодом (2026-10-02)
Сверено с `lighthub/owTerm.cpp`, `lighthub/owTerm.h`, `lighthub/main.cpp`.
- Раздел `"ow"` в корне конфигурации подтвержден: `owArr = aJson.getObjectItem(root, "ow")` (main.cpp:1491).
- Формат записи — имя датчика (16-значный шестнадцатеричный адрес, например `282DA307D6013C08`) → execobj с действиями: в коде имя объекта используется как адрес (`SetBytes(dev, 8, addrstr)`, `SetAddr`, owTerm.cpp:102-104, 196), объект передается в `executeCommand` (owTerm.cpp:69), т.е. `emit`/`item` поддерживаются.
- Передача значения — через суффикс `/val` (`itemCmd(currentTemp).setSuffix(S_VAL)`, owTerm.cpp:69), что согласуется с wiki (суффикс можно не добавлять — он подставляется сам).
- Автоматическое периодическое сканирование шины действительно отменено: `owUpdate()` (сканирование) вызывается только из `owSearch()`, который привязан к CLI-команде `search` (main.cpp:2875, owTerm.cpp:39-42); в цикле `sensors_loop` периодический вызов закомментирован (owTerm.cpp:259).
- Результаты сканирования выводятся в лог (`infoSerial`, owTerm.cpp:96-114) — подтверждено.
- Опрашиваются последовательно только датчики из раздела `ow` (обход `owArr` в `sensors_loop`, owTerm.cpp:256-288) — подтверждено.
- Пин шины задается опцией компиляции `USE_1W_PIN` (owTerm.cpp:134); возможно также использование моста DS2482-100 по I2C (`DS2482_100_I2C_TO_1W_BRIDGE`) — в wiki не описано.
+363
View File
@@ -0,0 +1,363 @@
# Интеграция с Home Assistant
> Источник: Wiki LightHub (lazyhome.ru), страница «интеграция_с_homeassistant». Снапшот от 2026-10-02.
Контроллер LightHub прекрасно интегрируется в систему Home Assistant с использованием MQTT
В настоящее время, реализованы и используются следующие интеграции:
- Реле и дискретные выключатели
- Диммируемые одноцветные светильники
- Диммируемые цветные светильники (RGB/RGBW/RGBWW)
- Термостаты теплого пола, помещений
- Кондиционер
- Увлажнитель
- Сенсоры температуры
- Сенсоры влажности
- Сенсоры CO2
- Любые устройства, управляемые по протоколу Modbus
Документация скорректирована, так как HA внес большие изменения в компонент MQTT в 2023 году
Параметры брокера теперь настраиваются только через пользовательский интерфейс в разделе Настройки/Интеграции и в файле конфигурации настройки следует убрать
Теперь предполагается, что настройки MQTT вынесены в отдельный файл mqtt.yaml
который подгружается директивой
```yaml
mqtt: !include mqtt.yaml
```
В файле configuration.yaml
Это, действительно, удобнее.
Далее, даны примеры разделов файла mqtt.yaml, которые можно скорректировать и использовать для своих нужд
## Сенсоры
В примерах ниже:
Имя контроллера: light-d2
Предположим, что к этому контроллеру подключен датчик качества воздуха CCS811 и HDC1080 и в конфиге контроллера для этого заданы такие вот настройки:
```json
"98":{"T":5,"emit":"myhome/sensor/airq"},
"99":{"T":6,"emit":"myhome/sensor/humidity"}
```
Также, на pin3 подключен сенсор температуры и влажности dht-22, расположенный в ванной, с такой вот настройкой в JSON конфиге контроллера:
```json
"3":{"T":4,"emit":"dht"},
```
ну и к шине 1-wire подключен термометр в прихожей
```json
"ow":{"28EEA76713160204":{"emit":"t_aentr"}
}
```
В этом случае, конфигурация HomeAssistant будет выглядеть вот таким образом:
```yaml
sensor:
- name: "CO2"
icon: "mdi:periodic-table-co2"
expire_after: 600
state_topic: "myhome/sensor/airq/CO2"
unit_of_measurement: 'ppm'
availability_topic: "myhome/light-d2/$state"
payload_available: "ready"
payload_not_available: "disconnected"
- name: "TVOC"
expire_after: 600
state_topic: "myhome/sensor/airq/TVOC"
unit_of_measurement: 'ppm'
availability_topic: "myhome/light-d2/$state"
payload_available: "ready"
payload_not_available: "disconnected"
- name: "Влажность"
icon: "mdi:water-percent"
expire_after: 600
state_topic: "myhome/sensor/humidity/H"
unit_of_measurement: '%'
availability_topic: "myhome/light-d2/$state"
payload_available: "ready"
payload_not_available: "disconnected"
- name: "Влажность ванная DHT"
icon: "mdi:water-percent"
expire_after: 600
state_topic: "myhome/s_out/dhtH"
unit_of_measurement: '%'
- name: "Воздух ванная DHT"
icon: "mdi:thermometer"
expire_after: 600
state_topic: "myhome/s_out/dhtT"
unit_of_measurement: '°C'
- name: "Воздух прихожая DS"
icon: "mdi:thermometer"
expire_after: 600
state_topic: "myhome/s_out/t_aentr"
unit_of_measurement: '°C'
```
## Светильники
```yaml
light:
# дискретный выключатель света (вкл-выкл)
- name: "Прихожая"
state_topic: "myhome/s_out/spots_en"
command_topic: "myhome/in/spots_en"
qos: 1
# Диммируемый одноцветный светильник
- name: Кухня точки
command_topic: "myhome/in/ktc/cmd"
state_topic: "myhome/s_out/ktc/cmd"
# brightness_scale: 100 - начиная с версии 3.0.0 контроллера, настройка не нужна
brightness_command_topic: "myhome/in/ktc/set"
brightness_state_topic: "myhome/s_out/ktc/set"
# Цветной LED светильник
- name: Кухня LED
command_topic: "myhome/in/kuh/cmd"
state_topic: "myhome/s_out/kuh/cmd"
hs_command_topic: "myhome/in/kuh/set"
hs_state_topic: "myhome/s_out/kuh/set"
hs_value_template: "{%set a=value.split(',')%}
{% if a[1] -%}
{{a[0]+','+a[1]}}
{%- endif %}"
brightness_command_topic: "myhome/in/kuh/set"
brightness_state_topic: "myhome/s_out/kuh/set"
brightness_value_template: "{{ value.split(',')[2] }}"
color_temp_value_template: "{{ value.split(',')[3] }}" # Опционально
color_temp_command_topic: "myhome/in/kuh/temp" # Опционально
color_temp_state_topic: "myhome/s_out/kuh/set" # Опционально
#Новая версия интеграции. Поддерживает не только HSV но и RGBW нотацию цвета.
#Полезно, если на DMX вход контроллера подключена сенсорная панель, которая выдает значения каждого из каналов в отдельности
#- то есть RGBW. В этом случае контроллер прозрачно транслирует такой цвет в статусный топик, добавляя признак RGB в начало payload
# предполагается имя контроллера light
- name: Кухня по новому LED
command_topic: "myhome/light/kuh/cmd"
state_topic: "myhome/s_out/kuh/cmd"
hs_command_topic: "myhome/light/kuh/set"
hs_state_topic: "myhome/s_out/kuh/set"
brightness_command_topic: "myhome/light/kuh/set"
brightness_state_topic: "myhome/s_out/kuh/set"
color_temp_command_topic: "myhome/light/kuh/temp"
color_temp_state_topic: "myhome/s_out/kuh/set"
rgbw_state_topic: "myhome/s_out/kuh/set"
hs_value_template: "{%if not value is match('RGB')%}
{%set a=value.split(',')%}
{%if a[1]%}
{{a[0]+','+a[1]}}
{%endif%}
{% endif %}"
brightness_value_template: "{%if not value is match('RGB')%}
{%set a=value.split(',')%}
{% if a[2] %}
{{ a[2] }}
{% endif %}
{% endif %}"
color_temp_value_template: "{%if not value is match('RGB')%}
{%set a=value.split(',')%}
{% if a[3] %}
{{ a[3] }}
{% endif %}
{% endif %}"
rgbw_value_template: "{%if value is match('RGB')%}
{{value.split()[1]}}
{% endif %}"
```
## Выключатели
```yaml
switch:
- name: "Air heat"
icon: "mdi:radiator"
state_topic: "myhome/s_out/fm_t/cmd"
command_topic: "myhome/in/fm_t/cmd"
- name: "Air auto"
icon: "mdi:auto-fix"
state_topic: "myhome/s_out/fm_auto"
command_topic: "myhome/in/fm_auto"
- name: "Перекрыть воду"
icon: "mdi:water-off"
state_topic: "myhome/s_out/alock_leak"
command_topic: "myhome/in/alock"
qos: 1
- name: "Сушилки"
icon: "mdi:radiator"
state_topic: "myhome/s_out/h_polotenc"
command_topic: "myhome/in/h_polotenc"
qos: 1
- name: "Бойлер большой"
state_topic: "myhome/s_out/h_boil1"
command_topic: "myhome/in/h_boil1"
qos: 1
- name: "Бойлер малый"
state_topic: "myhome/s_out/h_boil2"
command_topic: "myhome/in/h_boil2"
qos: 1
```
## Климат и термостаты
```yaml
climate:
- name: Кондиционер
modes:
- "off"
- "cool"
- "fan_only"
- "heat"
- "auto"
fan_modes:
- "auto"
- "high"
- "medium"
- "low"
swing_modes:
- "on"
- "off"
swing_mode_state_topic: "myhome/s_out/ac/swing"
swing_mode_command_topic: "myhome/in/ac/swing"
swing_mode_state_template: "{{value|lower()}}"
mode_command_topic: "myhome/in/ac/cmd"
mode_state_topic: "myhome/s_out/ac/cmd"
mode_state_template: "{{value|lower()}}"
temperature_command_topic: "myhome/in/ac/set"
temperature_state_topic: "myhome/s_out/ac/set"
fan_mode_command_topic: "myhome/in/ac/fan"
fan_mode_state_topic: "myhome/s_out/ac/fan"
fan_mode_state_template: "{{value|lower()}}"
current_temperature_topic: "myhome/s_out/ac/temp"
- name: "Теплый пол душ"
modes:
- "off"
- "heat"
- "auto"
mode_command_topic: "myhome/in/h_bath1/cmd"
temperature_command_topic: "myhome/in/h_bath1/set"
mode_state_topic: "myhome/s_out/h_bath1/cmd"
mode_state_template: "{{value|lower()}}"
temperature_state_topic: "myhome/s_out/h_bath1/set"
current_temperature_topic: "myhome/s_out/t_bath1"
- name: "Климат спальня"
modes:
- "off"
- "heat"
- "auto"
- "cool"
- "fan_only"
mode_command_topic: "myhome/in/c_bedr/cmd"
temperature_command_topic: "myhome/in/c_bedr/set"
mode_state_topic: "myhome/s_out/c_bedr/cmd"
mode_state_template: "{{value|lower()}}"
temperature_state_topic: "myhome/s_out/c_bedr/set"
current_temperature_topic: "myhome/s_out/t_bedr"
```
## Увлажнитель
```yaml
humidifier:
- name: "Увлажнитель пар"
command_topic: "myhome/plug00/reghum/cmd"
state_topic: "myhome/s_out/reghum/cmd"
target_humidity_command_topic: "myhome/plug00/reghum/set"
target_humidity_state_topic: "myhome/s_out/reghum/set"
current_humidity_topic: "myhome/s_out/plughum"
max_humidity: 60
min_humidity: 20
```
## Приточка
```yaml
climate:
- name: Вентиляция
modes:
- "off"
- "fan_only"
- "heat"
- "auto"
mode_command_topic: "myhome/in/fm/cmd"
mode_state_topic: "myhome/s_out/fm/cmd"
mode_state_template: "{{value|lower()}}"
temperature_command_topic: "myhome/in/fm_t/set"
temperature_state_topic: "myhome/s_out/fm_t/set"
current_temperature_topic: "myhome/s_out/fm_stat"
current_temperature_template: "{{ value_json.t }}"
sensor:
- name: "Heater power"
state_topic: "myhome/s_out/fm_stat"
icon: "mdi:radiator"
unit_of_measurement: '%'
value_template: "{{ value_json.pwr }}"
- name: "Fan RPM"
icon: "mdi:fan"
state_topic: "myhome/s_out/fm_stat"
unit_of_measurement: 'RPM'
value_template: "{{ value_json.RPM }}"
- name: "Fan Current"
icon: "mdi:current-ac"
state_topic: "myhome/s_out/fm_stat"
unit_of_measurement: 'A'
value_template: "{{ value_json.I }}"
- name: "Fan Fault"
icon: "mdi:alert"
state_topic: "myhome/s_out/fm_stat"
value_template: "{{ value_json.flt }}"
# - platform: mqtt
# name: "Fan Temp"
# state_topic: "myhome/s_out/fm_stat"
# unit_of_measurement: '°C'
# value_template: "{{ value_json.t }}"
# - platform: mqtt
# name: "Fan Temp set"
# state_topic: "myhome/s_out/fm_stat"
# unit_of_measurement: '°C'
# value_template: "{{ value_json.set }}"
```
## Сверка с кодом (2026-10-02)
- Страница содержит только примеры конфигурации HA (yaml) и стандартные фрагменты конфига LightHub; специфических для HA ключей контроллера нет.
- Форматы топиков `myhome/in/...` и `myhome/s_out/...`, а также служебный топик `myhome/<имя_контроллера>/$state` соответствуют префиксам по умолчанию контроллера.
- Настройки датчиков в примерах — стандартные записи входов (`"98":{"T":5,...}`, `"3":{"T":4,...}`) и раздел `ow` (см. [Подключение 1-Wire датчиков](1wire_sensors.md)).
- Контент, относящийся к модулю sprinkler, на странице отсутствует (отдельный документ — `documentation/Sprinkler_HomeAssistant.md`).
+599
View File
@@ -0,0 +1,599 @@
# Настройка Modbus
> Источник: Wiki LightHub (lazyhome.ru), страницы «настройка_modbus» и «режим_шлюза_ip_modbus». Снапшот от 2026-10-02.
## Функциональность драйвера Modbus v2
LightHub можно настроить на работу в качестве шлюза с фактически любым устройством, поддерживающим Modbus RTU и работающем в режиме Slave
В отличии от v1, драйвер можно настроить на работу в качестве шлюза с фактически любым устройством, поддерживающим Modbus RTU и работающем в режиме Slave
Поддерживается как чтение так и запись в modbus устройства
## Раздел "modbus" конфигурации
В корневом разделе modbus конфигурации описывается библиотека используемых типов устройств.
Для каждого устройства в библиотеки возможно задать такие параметры как скорость обмена (раздел baud) /параметры четности (раздел serial), назначение и тип регистров (раздел par), а также, интервал и параметры опроса этих регистров (раздел poll)
### раздел par
Данный раздел содержит информацию о назначении каждого опрашиваемого или управляемого регистра (или групп регистров) используемого устройства. Раздел состоит из JSON объектов следующего формата:
```json
"t_heat":{"reg":8,"map":[0,1024,0,1024],"type":"i16"},
```
В примере выше:
- "t_heat" - имя параметра устройства.
- "reg" - регистр (или стартовый HOLDING REGISTER) параметра
- "ir" - INPUT REGISTER или "reg"- HOLDING REGISTER или "coil": COIL или "din" - DISCRETE INPUT
- "map" - правила преобразования (TBD)
- "type":"i16" - указывает, что значение - 16-ти битное число со знаком
Возможные варианты типов:
- i16 - знаковый 16-ти битный регистр (по умолчанию)
- i32 - знаковый 32-ти битный регистр (первый регистр - младшие биты, следующий - старшие)
- u16 - беззнаковый 16-ти битный регистр
- u32 - беззнаковый 32-ти битный регистр (первый регистр - младшие биты, следующий - старшие)
- i8h - старшие 8 бит регистра (при записи значения, другие 8 бит будут заполнены значением 0xFF)
- i8l - младшие 8 бит регистра (при записи значения, другие 8 бит будут заполнены значением 0xFF)
- x10 - дробное число с точностью до 0.1 полученное путем деления значения 16 битного регистра со знаком на 10 (часто используется в разных устройствах для кодирования температуры, например, значение 124 в регистре соответствует 12,4)
- 100 - дробное число с точностью до 0.01 полученное путем деления значения 16 битного регистра со знаком на 100
### раздел poll
задает интервал и параметры опроса регистров устройства
Причем, в целях оптимизации обмена, можно опрашивать устройство командой чтения группы регистров.
Пример:
```json
"poll":{"regs":[[40000,40014],[30000,30002],40099],"delay":10000}
```
Обозначает, что с интервалом 10 сек будут произведены следующие три опроса:
- Команда чтения группы из 15-ти регистров с 40000 по 40014
- Команда чтения группы из 3-x регистров с 30000 по 30002
- Команда чтения одиночного регистра 40099
Для каждого из успешно прочитанных регистров, проводится поиск соответствия в разделе par и ir
Если есть запись, соответствующая данному регистру, прочитанные значения преобразовываются (см описание map) и направляются в MQTT и/или локальным объектам контроллера
Отправка происходит, если с момента последнего опроса значение регистра изменилось
кроме regs допустимы irs и coils
Или вот пример для сенсора Sensair S8
Опрашиваем INPUT REGISTERS 0-3,21,25-30 и HOLDING REGISTERS 0,1,31
```json
"sensair":{"baud":9600,
"poll":{"irs":[[0,3],21,[25,30]],"regs":[0,1,31],"delay":1000},
"par":{
"co2":{"ir":3},
"meterStat":{"ir":0},
"alarmStat":{"ir":1},
"outStat":{"ir":0},
"pwm":{"ir":21},
"typeid":{"ir":25,"type":"u32"},
"mapver":{"ir":27},
"fwver":{"ir":28},
"sensorid":{"ir":29,"type":"u32"},
"ack":{"reg":0},
"command":{"reg":1},
"abc":{"reg":31}
}
```
А вот пример подключения Modbus адаптера кондиционера Haier
```json
"modbus":
{
"haier":{"baud":9600,
"poll":{"regs":[[0,3]],"irs":[[0,1]],"coils":[0],"delay":5000},
"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},
"$fault":{"ir":1},
"set":{"reg":0,"id":2},
"fan":{"reg":2,"id":7,"map":{"cmd":[["OFF",0],["LOW",1],["HIGH",3],["MEDIUM",2],["AUTO",4]]}},
"lock":{"reg":3,"map":{"cmd":[["OFF",1],["ON",4]]}}
}
}
},
"items": {
"ac_2":[14,[128,
"haier",
{
"pwr":{"emit":"home/s_out/ac_2/cmd","@V":null},
"$temp":{"emit":"home/s_out/ac_2/$temp","@S":null},
"$fault":{"emit":"home/s_out/ac_2/$fault"},
"set":{"emit":"home/s_out/ac_2/set"},
"acmode":{"emit":"home/s_out/ac_2/$mode","@V":null},
"fan":{"emit":"home/s_out/ac_2/fan","@V":null},
"lock":{"emit":"home/s_out/ac_2/lock","@V":null}
}
]
]
}
}
```
### Разделы baud и serial
Пример:
```json
"baud":9600,
"serial":"8E1"
```
Соответственно, скорость обмена (по умолчанию, 9600) и параметр четности порта
Параметр четности - одно из значений ниже. По умолчанию 8N1
"8E1","8N1","8E2", "8N2", "8O1", "8O2", "8M1", "8S1", "7E1", "7N1", "7E2", "7N2", "7O1", "7O2", "7M1", "7S1"
## Раздел "items" конфигурации
В данном разделе задаются конкретные modbus устройства по шаблону, определенному в разделе modbus
```json
"items": {
"dimer1":[14,[1,
"dim4",
{
"ch1":{"emit":"aaa1,"item":"localdimmer1"},
"ch2":{"emit":"abc/aaa2"},
"ch3":{"item":"localdimmer3"},
"ch4":[{"emit":"aaa4,"item":"localdimmer4"},{"emit":"aaa44,"item":"localdimmer44"}]
}
]
],
```
В данном примере, создается item (объект) dimer1 с типом 14 (modbus v2) адресом modbus=1, на основе библиотечного устройства "dim4"
Устройство опрашивается согласно настройкам в библиотеке. А вот результаты опроса используются согласно настройкам в items.
В данном примере,
- "ch1" передается в MQTT топик "myhome/s_out/aaa1" плюс локальному устройству "localdimmer1"
- "ch2" передается в MQTT топик "abc/aaa2" (если в названии топика есть / - он не дополняется слева статусным префиксом)
- "ch3" передается локальному устройству "localdimmer3"
- "ch4" передается в MQTT топик "myhome/s_out/aaa4" и "myhome/s_out/aaa44", локальному устройству "localdimmer4" и "localdimmer44" (использован массив из двух JSON объектов)
Строки ch1 - ch4 в данном примере, определенные в третем параметре массива конфигурации, далее будем называть "именованными параметрами modbus item"
Имена этих параметров используются для доступа на запись в modbus
Для данного примера, чтобы записать значение в первый канал modbus димера можно использовать mqtt топик:
```
myhome/in/dimer1/ch1/set
```
(Здесь и далее для простоты предполагаем что mqtt префикс по-умолчанию myhome и обращение через broadcast имя устройства in)
"ch1" используется как subItem устройства (ставится между именем item и суффиксом)
таким образом обеспечивается индивидуальный доступ к каждому описанному в настройках регистру modbus устройства из mqtt/httpApi
NB. Не надо именовать данные параметры именами стандартных суффиксов (set, cmd, fan и пр) (см. полный перечень стандартных суффиксов)
Также, возможно управлять не отдельными subItem - ами modbus устройства, а устройством в целом, по аналогии с тем, как это делается для всех типичных item-ов LightHub. То есть, задавать один общий параметр устройства через суффикс /set, команды через суффикс /cmd и пр (см. полный перечень стандартных суффиксов)
Для этого в разделе шаблона устройства, в описании конкретного параметра modbus можно задать связь параметра с конкретным суффиксом при помощи значения "id"=N, где N - цифровой идентификатор стандартного суффикса (см. полный перечень стандартных суффиксов)
Далее, соберем фрагменты в более полный пример:
```json
"modbus":
{
"airset":{
"baud":9600,
"serial":"8N1",
"poll":{"regs":[1,[8,24]],"delay":1000},
"par":{
"t_heat":{"reg":8,"map":[0,1024,0,1024],"type":"i16"},
"mode":{"reg":24}
}
},
"dim4":{
"poll":{"regs":[[0,4]],"delay":10000},
"par":{
"ch1":{"reg":0},
"ch2":{"reg":1},
"ch3":{"reg":2},
"ch4":{"reg":3}
}
},
"sensair":{"baud":9600,
"poll":{"irs":[[0,3],21,[25,30]],"regs":[0,1,31],"delay":1000},
"par":{
"co2":{"ir":3},
"meterStat":{"ir":0},
"alarmStat":{"ir":1},
"outStat":{"ir":0},
"pwm":{"ir":21},
"typeid":{"ir":25,"type":"u32"},
"mapver":{"ir":27},
"fwver":{"ir":28},
"sensorid":{"ir":29,"type":"u32"},
"ack":{"reg":0},
"command":{"reg":1},
"abc":{"reg":31}
}
}
},
"panel":{
"poll":{"regs":[[40000,40014],[30000,30002]],"delay":10000},
"par":{
"fan" :{"reg":40000},
"mode" :{"reg":40001},
"set" :{"reg":40002},
"pwr" :{"reg":40003},
"alm01":{"reg":40004},
"alm17":{"reg":40005},
"alm33":{"reg":40006},
"sethum" :{"reg":40007},
"setvoc" :{"reg":40008},
"temp" :{"reg":30000},
"hum" :{"reg":30001},
"voc" :{"reg":30002},
"ch_temp" :{"reg":40009},
"ext_temp" :{"reg":40010},
"out_temp" :{"reg":40011},
"water_temp" :{"reg":40012},
"ch_hum" :{"reg":40013},
"heat_pwr":{"reg":40014}
}
}
},
"items": {
"airset1":[14,[10,"airset",{"t_heat":{"emit":"aaa"}}]],
"panel1":[14,[2,"panel"]],
"dimer1":[14,[1,"dim4",
{
"ch1":{"emit":"aaa1,"item":"localdimmer1"},
"ch2":{"emit":"abc/aaa2"},
"ch3":{"item":"localdimmer3"},
"ch4":[{"emit":"aaa4,"item":"localdimmer4"},{"emit":"aaa44,"item":"localdimmer44"}]
}
]
]
},
"sensair1":[14,[254,
"sensair",
{"co2":{"emit":"co2"}}
]
]
}
}
```
## Подавление повторных значений
В процессе опроса устройств, драйвер запоминает последнее считанное из регистра modbus значение во внутреннюю переменную @S внутри именованного параметра item
Если значение не изменилось с последнего считывания - операция по отправки значения в modbus или локальному обьекту не производится
Данное поведение можно отменить. Если данную переменную определить в конфиге и ее тип будет отличен от целого значения, последнее опрошенное значение не будет сохраняться, что приведет к отправке результата каждого опроса в mqtt или локальному обьекту
Пример - панель управления климатом Zentec. Измерения влажности передаются каждый раз:
```json
"modbus":
{
"panel":{
"serial":"8E1",
"poll":{"regs":[[40000,40014],[30000,30002]],"delay":10000},
"par":{
"fan" :{"reg":40000,"map":[1,[0,7,0,100]],"id":11},
"mode" :{"reg":40001,"mapcmd":[2,[[1,"FAN_ONLY"],[2,"HEAT"],[4,"COOL"],[8,"AUTO"]]]},
"settemp" :{"reg":40002,"id":12},
"pwr" :{"reg":40003,"mapcmd":[2,[[0,2],[1,1]]]},
"alm01":{"reg":40004},
"alm17":{"reg":40005},
"alm33":{"reg":40006},
"sethum" :{"reg":40007,"id":13},
"setvoc" :{"reg":40008,"id":14},
"roomtemp" :{"reg":30000,"type":"x10"},
"hum" :{"reg":30001},
"voc" :{"reg":30002},
"ch_temp" :{"reg":40009,"type":"x10","id":15},
"ext_temp" :{"reg":40010,"type":"x10","id":16},
"out_temp" :{"reg":40011,"type":"x10","id":17},
"water_temp" :{"reg":40012,"type":"x10","id":18},
"ch_hum" :{"reg":40013},
"heat_pwr":{"reg":40014}
}
}
},
items:{
"p_zal3":[14,[2,"panel",
{
"fan" :{"emit":"edem/air/vents/zal3/fan"},
"mode":{"emit":"edem/air/vents/zal3/mode"},
"pwr" :{"emit":"edem/air/vents/zal3/pwr"},
"sethum":{"emit":"edem/air/humzal3/set"},
"hum" :{"emit":"edem/air/humzal3/val","@S":null},
"setvoc":{"emit":"edem/air/voczal3/set"},
"voc" :{"emit":"edem/air/voczal3/val"},
"settemp" :{"item":"tzal3/set"},
"roomtemp" :{"emit":"edem/fl2/term_bedr/1/val"},
"ch_temp":{},
"ch_hum":{},
"ext_temp":{},
"out_temp":{},
"water_temp":{},
"heat_pwr":{}
}
]]
}
```
Также, по-умолчанию, контроллер выполняет какие-то действия, только если регистр Модбас устройства поменялся не в результате записи в него со стороны контроллера(такая логика сделана, чтобы избежать зацикливания нотификаций)
Например, если в регистре число 3 а мы записали в него 5 - никаких действий при опросе не произойдет. А вот если значение в регистре изменилось в результате каких-то внутренних процессов устройства (например, пользователь изменил значение температуры на панеле) - это значение будет обработано.
Данную фильтрацию можно отменить, если в настройке параметра добавить переменную @V типа, отличного от целого.
Например так:
```json
"fan" :{"emit":"edem/air/vents/zal3/fan","@V":null},
```
В этом случае, после того, как мы что-то записали в регистр, при следующем же опросе устройства, это будет обнаружено (если значение изменилось) и будут предприняты настроенные действия (например, значение будет отправлено по MQTT и отобразится в мобильном приложении Home Assistant)
~~И еще один фильтр: при попытке записать в регистр значение, не отличающееся от последнего полученного при опросе, такая попытка будет проигнорирована. Такое поведение отключить нельзя.~~
## Запись в Modbus устройство
Параметры Модбас устройства можно записывать аналогично, со всеми остальными items контроллера - с использованием MQTT, прямым обращением из других items контроллера, через http API
Рассмотрим на примере вентустановки:
Скорость можно поменять, обращаясь к "суб-топику" fanspeed
//vent/fanspeed/set// (для прямого обращения по api или как к item-у)
Для обращения через MQTT топик будет выглядеть как myhome/devicename/vent/fanspeed/set
Внимание, для названий субтопиков следует избегать стандартных имен суффиксов (cmd,set,hsv,rgb,fan,mode,hue,sat,temp,val,del,raw)
Параметры fanmin и fanmax доступны только на запись (контроллер не будет отслеживать изменение их значений)
также, есть возможность "прикрепить" параметры к стандартным суффиксам item-а (set,cmd,fan и пр), указав числовой параметр id, соответствующий данному стандартному суффиксу в описании этого параметра.
Перечень суффиксов:
```
CMD 1
SET 2
HSV 5
RGB 6
FAN 7
MODE 8
HUE 9
SAT 10
TEMP 11
VAL 12
DELAYED 13
RAW 14
```
в примере ниже, это значит, что альтернативный описанному метод поменять скорость:
//vent/fan//
А при записи в vent/cmd это значение установится как в регистр 41 (параметр on) так и в регистр 43 (параметр pmode) так как у них указан одинаковый id=1, соответствующий суффиксу /cmd
```json
"modbus":
{
"airset":{
"baud":9600,
"serial":"8E1",
"poll":{"regs":[[0,60],1008],"delay":2000},
"par":{
"rtemp":{"reg":5,"type":"100", "mode":"r"},
"fanmin":{"reg":50,"type":"u8l"},
"fanmax":{"reg":51,"type":"u8l"},
"on":{"reg":41,"type":"u8l","id":1},
"fanspeed":{"reg":42,"type":"u8l","id":7},
"pmode":{"reg":43,"type":"u8l","id":1,"map":{}},
"tset":{"reg":44,"type":"u8l","id":2},
"numspeed":{"reg":60,"type":"u8l"},
"fault":{"reg":1008}
}
}
},
"items": {
"vent":[14,[247,"airset",
{
"tset":{"emit":"edem/s_out/vent/tset/set","@V":null},
"pmode":{"emit":"edem/s_out/vent/pmode/set","@V":null},
"fanspeed":{"emit":"edem/s_out/vent/fanspeed/set","@V":null},
"on":{"emit":"edem/s_out/vent/on/set","@V":null},
"rtemp":{"emit":"edem/s_out/vent/rtemp"},
"fanmin":{},
"fanmax":{}
}
]],
}
```
## Mapping значений и команд контроллера в регистры Modbus
Более подробно настройка преобразований описана в отдельном разделе [использование преобразований map](../core/analog_inputs_and_map.md)
Далее, разобраны примеры применения
Рассмотрим на примере вентустановки
Допустим, регистр 41 отвечает за включение установки. Соответственно, в него надо записать "1" для всех рабочих режимов:
- AUTO
- ON
- HEAT
- FAN_ONLY
Для команды OFF записываем 0
Это реализуется строкой
```json
"on":{"reg":41,"type":"u8l","id":1,"map":{"cmd":[["OFF",0],["ON",1],["AUTO",1],["HEAT",1],["FAN_ONLY",1]]}}
```
наличие "id"=1 позволяет не только напрямую управлять данным регистром при помощи именованного параметра "on" (топика air/on/set) но и привязать его к командному суффиксу канала
Соответственно, доступно управление по командному топику air/cmd
В нашей вентустановке за переключение режима работы (нагрев-вентиляция-авто) отвечает отдельный регистр 43
настроим отображение режима работы на требуемые значения данного регистра и, также, привяжем это отображение к командному топику ("id":1)
```json
"pmode":{"reg":43,"type":"u8l","id":1,"map":{"cmd":[["AUTO",3],["HEAT",2],["FAN_ONLY",1]]}},
```
теперь при переключении режимов в регистр 43 будет записываться 3 для Авторежима, 2 - для режима нагрева, 1 - для режима вентиляции
Еще лайфхак:
```json
"humpwr":{"reg":39998,"map":{"cmd":[null,["ON",1],["OFF",0]],"val":null}},
```
В примере выше, в значения регистра будет маппироваться только команда, поступающая на humpwr. Команда ON в 1, команда OFF в 0
первый null перед массивом соответствия команда -> значение по умолчанию, которое будет использоваться если не удастся подобрать команду. (null тут можно не указывать)
Если не подобрали - пытаемся преобразовать по значению
Если не использовать "val":null - то значения, отправляемые в humpwr/set будут передаваться в регистр без преобразований. Использование null обеспечивает игнорирование значений (не команд)
(описание не завершено)
```json
"modbus":
{
"airset":{
"baud":9600,
"serial":"8E1",
"poll":{"regs":[[0,60],1008],"delay":2000},
"par":{
"on":{"reg":41,"type":"u8l","id":1,"map":{"cmd":[["OFF",0],["ON",1],["AUTO",1],["HEAT",1],["FAN_ONLY",1]]}},
"fanspeed":{"reg":42,"type":"u8l","id":7,"map":{"cmd":"fan"}},
"offbyfan":{"reg":41,"type":"u8l","id":7,"map":{"cmd":[1,["OFF",0]]}},
"pmode":{"reg":43,"type":"u8l","id":1,"map":{"cmd":[["AUTO",3],["HEAT",2],["FAN_ONLY",1]]}},
"tset":{"reg":44,"type":"u8l","id":2},
"di":{"reg":47,"type":"u8l"},
"dp":{"reg":48,"type":"u8l"},
"dt":{"reg":49,"type":"u8l"},
"fault":{"reg":1008}
}
}
}
},
"items":
{
"vent":[14,[247,"airset",
{
"tset":{"emit":"edem/s_out/vent/set","@V":null},
"pmode":{"emit":"edem/s_out/vent/cmd","@V":null},
"fanspeed":{"emit":"edem/s_out/vent/fan","@V":null},
"on":{"emit":"edem/s_out/vent/oncmd","@V":null},
"ruheat":{"emit":"edem/s_out/vent/ruheat"},
"ruslow":{"emit":"edem/s_out/vent/rupump"},
"ramode":{"emit":"edem/s_out/vent/ramode"},
"rfanspd":{"emit":"edem/s_out/vent/rfanspd"},
"rfanlvl":{"emit":"edem/s_out/vent/rfanlvl"},
"rpumpon":{"emit":"edem/s_out/vent/rpumpon"},
"rtemp":{"emit":"edem/s_out/vent/rtemp"},
"rtempset":{"emit":"edem/s_out/vent/rtempset"},
"fault":{"emit":"edem/s_out/vent/fault"},
"tautoheat":{},
"tautocool":{},
"di":{},
"dp":{},
"dt":{},
"fanmin":{},
"fanmax":{},
"tmreheat":{},
"tairfreeze":{},
"twaterstart":{},
"twatershut":{},
"twateridle":{},
"fanauto":{"emit":"edem/s_out/vent/fanauto/set","@V":null},
"numspeed":{},
"offbyfan":{}
}
]]
}
```
## Режим шлюза IP-Modbus
На контроллере может быть активизирован режим доступа к шине MODBUS через TCP/IP
Данный режим может быть полезен для удаленного управления/перепрошивки устройств, которыми управляет контроллер в режиме Modbus-Master
Доступ обеспечивается как через протокол UDP так и через TCP с использованием стандартного порта 502
Для активации такого шлюза, надо перекомпилировать прошивку со следующими опциями (см [опции компиляции](https://www.lazyhome.ru/dokuwiki/doku.php?id=опции_компиляции))
```
-D IPMODBUS
```
Будет использован порт Modbus v1 и его настройки. Изменить настройки можно следующими директивами:
```
-D MODBUS_SERIAL_PARAM=SERIAL_8N1
-D MODBUS_SERIAL_BAUD=9600
```
В примере выше даны настройки по-умолчанию
## Сверка с кодом (2026-10-02)
Сверено с `lighthub/modules/out_modbus.cpp`, `lighthub/modules/out_modbus.h`, `lighthub/ipmodbus.cpp`, `lighthub/ipmodbus.h`, `lighthub/options.h`, `lighthub/item.h`.
- Ключи шаблона устройства, подтвержденные в коде (`out_Modbus::getConfig`, out_modbus.cpp:139-249): `baud` (по умолчанию 9600), `serial` (по умолчанию `SERIAL_8N1`), `poll` с подклавишами `regs`, `irs`, `coils`, `dins` и `delay` (по умолчанию 1000 мс — в wiki значение по умолчанию не указано), `par`.
- Ключи параметра в `par` (out_modbus.cpp:433-467, 1084-1085, 203-204): `reg`, `ir`, `coil`, `din`, `type`, `map`, `id`, `prefetch` (boolean). Ключ `prefetch` поддерживается кодом (при записи предварительно опрашивается регистр), но в wiki не описан.
- Поддерживаемые типы (таблица `regSize_P`, out_modbus.cpp:47-60): `i16`, `i32`, `u16`, `u32`, `i8h`, `i8l`, `u8h`, `u8l`, `x10`, `100` — только эти типы. Список в wiki неполный: отсутствуют `u8h` и `u8l`.
- Ключ `mapcmd` (пример панели Zentec, раздел «Подавление повторных значений») в коде не найден — поддерживается только `map`; вероятно, опечатка/устаревшее имя.
- Ключ `"mode":"r"` в примере параметра `rtemp` в out_modbus.cpp не обрабатывается — вероятно, унаследован от драйвера Modbus v1.
- В коде есть ключ `sendchanges` (out_modbus.cpp:1085), не упомянутый в wiki.
- Перечень числовых идентификаторов суффиксов в wiki (HUE 9, SAT 10, TEMP 11, VAL 12, DELAYED 13, RAW 14) **не совпадает** с текущим кодом (item.h:27-39): `CMD 1, SET 2, VAL 3, DELAYED 4, HSV 5, RGB 6, FAN 7, MODE 8, CTRL 9, HUE 10, SAT 11, TEMP 12, RAW 13`. Примеры с `id` 11-18 (Zentec, вентустановка) соответствуют старой нумерации; при использовании на актуальной прошивке значения `id` нужно пересматривать.
- Описание типа `i8h`/`i8l` («при записи другие 8 бит будут заполнены 0xFF») не подтверждается кодом: запись идет целиком в 16-битный регистр смещенным байтом (`writeSingleRegister`, out_modbus.cpp:897-905), остальные биты обнуляются.
- Механика `@S`/`@V` (подавление повторных значений и «записали сами — не обрабатываем») подтверждена: `createLastMeasured`/`getLastMeasured`, сравнение с `@V` («Ignored - equal with setted val», out_modbus.cpp:676-701).
- Шлюз IP-Modbus: компиляционная опция `IPMODBUS` (ipmodbus.h:1), порты TCP и UDP — оба 502 (ipmodbus.h:26-27), значения по умолчанию `MODBUS_SERIAL_BAUD 9600` и `MODBUS_SERIAL_PARAM SERIAL_8N1` (options.h:154-159) — совпадает с wiki.
+71
View File
@@ -0,0 +1,71 @@
# Интеграция с OpenHAB
> Источник: Wiki LightHub (lazyhome.ru), страница «openhab». Снапшот от 2026-10-02.
Initially, LightHub was developed taking in mind integration with OpenHAB. Thus that might be configured easy.
All integration done, using MQTT broker as extension of OpenHab's message bus.
First of all, you need to install MQTT binding via "Paper UI" and then configure broker connection for your OpenHab.
The following examples are for OpenHab 2.
The path of your configuration files is system-dependent.
For example, for UNIX installations from repository configuration path is /etc/openhab2/
File: services/mqtt.cfg
```
# URL to the MQTT broker, e.g. tcp://localhost:1883 or ssl://localhost:8883
mqtt.url=tcp://192.168.88.2:1883
# Optional. User id to authenticate with the broker.
mqtt.user=<user>
# Optional. Password to authenticate with the broker.
mqtt.pwd=<password>
```
then configure openhab message bus
File: services/mqtt-eventbus.cfg
```
# Name of the broker from mqtt.cfg
broker=mqtt
# Publish command
commandPublishTopic=/myhome/in/${item}
# Receive status
stateSubscribeTopic=/myhome/s_out/${item}
```
after such kind of configuring, you can use same items name between OpenHab and LightHub
Example:
File items/demo.item (sor sitemap demo)
```
Dimmer bth2 "Ванная люстра [%d %%]" <slider> (gBath,Lights) ["Lighting"]
Color kuh "RGB Вся Кухня" <slider> (gKitchen,Lights) ["Lighting"]
Switch h_entr "Corridor" <heating> (gEntr, Heating) ["Switchable"]
```
And appropriate configuration of LightHub items
```json
{
"dmx":[3,60], //Init 60 channels dmx out on pin 3 (pin def for Mega only)
"items": {
"bth1":[4,[96,0,0]],
"bth2":[4,[96,0,1]], // 4=Modbus dimmer on modbus address 96, Register 0, subchannel 1
"kuh":[1,5], // 1=RGBW DMX channel with base address 5
"h_entr":[5,39,32] //5=thermostat with relay on pin 39 and default temperature preset = 32 degrees Celsium
}
}
```
Note:
There is not necessary to set-up persistent topics in Openhab nor configure persistent storage in OpenHab.
LightHub using persistent MQTT publishing for Status topic /myhome/s_out. After "cold start" and establishing MQTT connection with broker, Lighthub subscribing on Status topic for 5 seconds interval to capture and retrieve previous status from persistent MQTT topic /myhome/s_out
## Сверка с кодом (2026-10-02)
- Страница не содержит специфических ключей конфигурации LightHub, кроме стандартных типов item; прямая сверка с кодом не требуется.
- Пример использует тип item 4 (`CH_MODBUS`, «Modbus AC Dimmer», item.h:52) — драйвер Modbus v1; определение в текущем коде присутствует. Для произвольных Modbus-устройств (драйвер v2) используется тип 14 (`CH_MBUS`, item.h:62) — см. [Настройка Modbus](modbus_setup.md).
- MQTT-префиксы `/myhome/in` и `/myhome/s_out` соответствуют значениям по умолчанию контроллера.
@@ -0,0 +1,49 @@
# Работаем дистанционно
> Источник: Wiki LightHub (lazyhome.ru), страница «работаем_дистанционно». Снапшот от 2026-10-02.
## ОТА прошивка
для Windows из папки C:\Program Files (x86)\Arduino\hardware\tools\avr\bin копируем arduinoOTA.exe
в папку с прошивкой (firmware.bin).
Создаем командный файл и указываем адрес вашего контроллера
```
arduinoOTA.exe -address 192.168.XXX.XXX -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch
```
Запускаем!
для Mac
```
arduinoOTA -address 192.168.XXX.XXX -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch
```
password - значение по-умолчанию. Его можно заменить при помощи CLI команды otapwd
## Работа с SYSLOG
Для Windows устанавливаем Visual Syslog Сервер для Windows [https://github.com/MaxBelkov/visualsyslog/blob/master/readme_rus.md](https://github.com/MaxBelkov/visualsyslog/blob/master/readme_rus.md)
В корне конфигурационного файлa Lighthub указываем:
```json
"syslog":["IP"]
```
где "IP" - адрес сервера Syslog
## Выполнение CLI команд через MQTT
Достаточно в топик myhome/имя_контроллера/$command послать нужную команду [CLI интерфейс](../core/cli_interface.md)
Также, можно воспользоваться http [API](https://www.lazyhome.ru/dokuwiki/doku.php?id=api)
## Сверка с кодом (2026-10-02)
- CLI-команда `otapwd` подтверждена: `cmdAdd("otapwd", cmdFunctionOTAPwd)` (main.cpp:2863); о подстановом пароле HTTP/OTA API см. main.cpp:562.
- Топик `$command` для отправки CLI-команд по MQTT подтвержден: `#define CMDTOPIC "$command"` (options.h:200).
- Корневой раздел `"syslog"` (массив адресов серверов) подтвержден: `udpSyslogArr = aJson.getObjectItem(root, "syslog")` (main.cpp:588).
- Отдельных cloud-брокеров (AWS IoT, MQTT over TLS и т.п.) в прошивке не выявлено — удаленный доступ обеспечивается внешним MQTT-брокером и/или VPN, как описано на странице.