Add configuration examples for various devices and functionalities

- Introduced multivent ventilation configuration for managing multiple zones.
- Added PID heating batteries configuration for temperature control.
- Created relay GPIO switch configuration for controlling relays.
- Implemented RGBW LED strip configuration for lighting control.
- Added Modbus CO2 sensor configuration for environmental monitoring.
- Introduced Sonoff S26 humidity controller example for humidity management.
- Created sprinkler irrigation configuration for garden management.
- Added thermostat on/off relay configuration for heating and cooling control.
- Implemented ventilation fan monitoring configuration for performance tracking.
- Added core concepts documentation for LightHub, detailing items, commands, and execution objects.
This commit is contained in:
2026-10-15 19:11:34 +03:00
parent 8bc4525d66
commit f496e30600
40 changed files with 2770 additions and 292 deletions
+2 -2
View File
@@ -8,7 +8,7 @@ Useful links:
* [WIKI/RU](https://www.lazyhome.ru/dokuwiki/doku.php?id=start)
* [Doxygen autodocumentation for developers](https://lighthub.github.io/doxygen/)
* [Doxygen autodocumentation for developers](https://anklimov.github.io/doxygen/)
* [In-repo documentation (RU)](documentation/README.md)
@@ -52,7 +52,7 @@ Scalability of Lighthub is virtually unlimited: Setup so many controllers you ne
# Documentation
* [In-repo documentation index](documentation/README.md) (RU): JSON configuration, channel types, MQTT API, CLI, integrations (CAN, Modbus, 1-Wire, HA/OpenHAB), hardware
* [Russian-language Wiki](https://www.lazyhome.ru/dokuwiki/doku.php)
* [Developer documentation site](https://lighthub.github.io/) (Doxygen + developer notes)
* [Developer documentation site](https://anklimov.github.io/) (Doxygen + developer notes)
* [Browser Plugin for searching and configure controllers](https://github.com/anklimov/zeroconf-lighthub)
* [Release notes](https://github.com/anklimov/lighthub/releases)
+88
View File
@@ -0,0 +1,88 @@
# Примеры конфигураций LightHub
Готовые JSON-конфигурации для типовых кейсов из документации. Имя файла
отражает кейс. Каждый пример — законченный конфиг: адаптируйте пины,
адреса и топики под своё оборудование и схему подключения.
Все примеры проверены на синтаксическую корректность JSON и ссылочную
целостность (члены групп и `item`-ссылки существуют).
## Свет и реле
| Файл | Кейс | Документация |
|------|------|--------------|
| [relay\_gpio\_switch.json](relay_gpio_switch.json) | Реле на GPIO: насос, бойлер, вентилятор; управление кнопкой | [Типы каналов](../documentation/core/channel_types_reference.md) |
| [dimmer\_pwm\_gpio.json](dimmer_pwm_gpio.json) | PWM-диммер света и скорости вентилятора, группа каналов | [CH\_PWM](../documentation/core/technical_channel_types_table.md) |
| [rgbw\_led\_strip.json](rgbw_led_strip.json) | RGBW-лента (DMX RGBW, 4 канала) | [CH\_RGBW](../documentation/core/technical_channel_types_table.md) |
| [led\_spiled\_neopixel.json](led_spiled_neopixel.json) | Адресуемая NeoPixel-лента, управление диапазоном пикселей (10-20) | [CH\_SPILED](../documentation/core/technical_channel_types_table.md) |
| [group\_lighting\_scene.json](group_lighting_scene.json) | Группировка светильников, пересекающиеся группы (сцены) | [CH\_GROUP](../documentation/core/technical_channel_types_table.md) |
| [lighting\_dmx\_full\_house.json](lighting_dmx_full_house.json) | Большой дом: DMX-освещение, группы, реле, PWM, термостат, входы | [Примеры конфигураций](../documentation/core/configuration_examples.md) |
| [lighting\_dmx\_rgb\_multizone.json](lighting_dmx_rgb_multizone.json) | Многозональный DMX: RGB, диммеры, legacy Modbus-диммеры, Vacom | [Примеры конфигураций](../documentation/core/configuration_examples.md) |
## Климат и отопление
| Файл | Кейс | Документация |
|------|------|--------------|
| [thermostat\_onoff\_relay.json](thermostat_onoff_relay.json) | Простой ON/OFF термостат на реле (бак, пол) | [CH\_THERMO](../documentation/core/technical_channel_types_table.md) |
| [pid\_heating\_batteries.json](pid_heating_batteries.json) | PID-регулирование батарей отопления через slow-PWM реле (RELAYX), датчики 1-Wire | [CH\_PID](../documentation/core/technical_channel_types_table.md), [1-Wire](../documentation/integrations/1wire_sensors.md) |
| [heating\_relayx\_floor.json](heating_relayx_floor.json) | Тёплый пол: PID + медленный PWM (RELAYX), защита по времени | [CH\_RELAYX](../documentation/core/technical_channel_types_table.md) |
| [heating\_thermostat\_and\_water\_leak.json](heating_thermostat_and_water_leak.json) | Отопление всего дома, термостаты по комнатам, вход протечки | [Примеры конфигураций](../documentation/core/configuration_examples.md) |
| [garden\_relay\_thermostat\_1wire.json](garden_relay_thermostat_1wire.json) | Сад/теплица: реле, термостат, 1-Wire датчики, дискретные входы | [1-Wire](../documentation/integrations/1wire_sensors.md) |
## Вентиляция и кондиционирование
| Файл | Кейс | Документация |
|------|------|--------------|
| [multivent\_ventilation.json](multivent_ventilation.json) | Многозональная вентиляция: центральная установка (MBUS), зоны с PID и PWM-задвижками | [Модуль Multivent](../documentation/modules/multivent_module_description.md) |
| [damper\_motor\_feedback.json](damper_motor_feedback.json) | Моторные задвижки с обратной связью (аналоговый датчик положения) | [CH\_MOTOR](../documentation/core/technical_channel_types_table.md) |
| [ventilation\_fan\_monitoring.json](ventilation_fan_monitoring.json) | Мониторинг вентилятора: реле скоростей, датчик температуры | [Примеры конфигураций](../documentation/core/configuration_examples.md) |
| [ac\_haier\_control.json](ac_haier_control.json) | Кондиционер Haier по UART (родной протокол) | [CH\_AC](../documentation/core/technical_channel_types_table.md) |
| [climate\_panel\_z031.json](climate_panel_z031.json) | Климатическая панель Z031-2C0 (Modbus RTU 8E1): уставки, аварии, увлажнение, тёплый пол, кондиционер | [Панель Z031](../documentation/integrations/z031_panel.md) |
## Датчики и счётчики
| Файл | Кейс | Документация |
|------|------|--------------|
| [sensors\_modbus\_co2.json](sensors_modbus_co2.json) | CO2-датчик Sensair S8 и термометр по Modbus; PID по CO2 выдаёт запрос воздуха | [Настройка Modbus](../documentation/integrations/modbus_setup.md) |
| [counter\_energy\_monitoring.json](counter_energy_monitoring.json) | Виртуальный счётчик-сумматор (тарифные импульсы) | [CH\_COUNTER](../documentation/core/technical_channel_types_table.md) |
| [energy\_meter\_mercury.json](energy_meter_mercury.json) | Трёхфазный счётчик электроэнергии «Меркурий» по RS485 | [CH\_MERCURY](../documentation/core/technical_channel_types_table.md) |
| [modbus\_panel\_lh22\_test.json](modbus_panel_lh22_test.json) | Стенд LH22: Z031-панель, S8 CO2, термометр, DHT, датчики влажности, PWM, DMX | [Настройка Modbus](../documentation/integrations/modbus_setup.md) |
## Полив и вода
| Файл | Кейс | Документация |
|------|------|--------------|
| [sprinkler\_irrigation.json](sprinkler_irrigation.json) | Автополив: бак с поплавками, насосы, дренаж, клапаны зон, водосчётчик | [Модуль Sprinkler](../documentation/modules/Sprinkler_module.md) |
## Увлажнение
| Файл | Кейс | Документация |
|------|------|--------------|
| [humidifier\_control.json](humidifier_control.json) | Паровой увлажнитель: насос, промывочный клапан, датчик давления, зоны | [CH\_HUMIDIFIER](../documentation/core/technical_channel_types_table.md) |
| [sonoff\_s26\_humidity\_controller\_example.json](sonoff_s26_humidity_controller_example.json) | Sonoff S26 (ESP8266): PID влажности, реле, DHT22 | [Примеры конфигураций](../documentation/core/configuration_examples.md) |
## Кнопки, энкодер, CAN
| Файл | Кейс | Документация |
|------|------|--------------|
| [buttons\_and\_rotary.json](buttons_and_rotary.json) | Кнопки: одиночные/двойные/тройные/длительные нажатия, repeat; rotary-энкодер (яркость, цвет) | [Нажатия кнопок](../documentation/core/button_presses.md), [Энкодер](../documentation/core/rotary_encoder.md) |
| [can\_two\_controllers.json](can_two_controllers.json) | Два контроллера по CAN: панель Z031 на одном, вентиляция/увлажнение на другом; маршрутизация `can:[addr, item, suffix]` | [CAN и lightspot](../documentation/integrations/can_lightspot.md) |
## Legacy
| Файл | Кейс | Примечание |
|------|------|------------|
| [modbus\_ac\_dimmer\_legacy.json](modbus_ac_dimmer_legacy.json) | AC-диммер по Modbus (старый драйвер CH\_MODBUS) | Для новых проектов используйте CH\_MBUS (14) |
## Как адаптировать пример
1. **MQTT**: укажите имя контроллера и адрес брокера; при необходимости —
`topics.root` (корень топиков) и `syslog`.
2. **Пины**: сверьте номера GPIO с распиновкой вашей платы
([pins\_io](../documentation/hardware/pins_io.md)); отрицательный пин
инвертирует выход.
3. **Аппаратные адреса**: Modbus-адреса устройств, адрес CAN-контроллера.
4. **Item-имена**: переименуйте под вашу схему; имена топиков MQTT
строятся из `root` + имя контроллера/`s_out` + имя item.
5. Конфигурация загружается контроллером как описано в
[работе с файлом конфигурации](../documentation/core/config_file_workflow.md).
+8
View File
@@ -0,0 +1,8 @@
{
"mqtt": ["ac-demo", "192.168.88.2"],
"topics": { "root": "house" },
"items": {
"ac_living": [10, 1],
"ac_bedroom": [10, 2]
}
}
+29
View File
@@ -0,0 +1,29 @@
{
"mqtt": ["buttons-demo", "192.168.88.2"],
"topics": { "root": "house" },
"items": {
"lamp_living": [0, 5],
"led_living": [1, 10],
"lights_all": [7, ["lamp_living", "led_living"]]
},
"in": {
"0": {
"T": 0,
"click": { "item": "lamp_living/cmd", "icmd": "TOGGLE" },
"dclick": { "item": "led_living/cmd", "icmd": "TOGGLE" },
"tclick": { "item": "lights_all/cmd", "icmd": "TOGGLE" },
"lcmd": { "item": "lights_all/cmd", "icmd": "HALT" },
"rpcmd": { "item": "lamp_living/set", "icmd": "%+4" }
},
"2": {
"T": 0,
"scmd": { "item": "lights_all/cmd", "icmd": "OFF" },
"rcmd": { "item": "lights_all/cmd", "icmd": "REST" }
},
"4": {
"T": 32, "#": [14, 6, 7],
"+-": { "item": "led_living/set", "icmd": "%+1", "irev": "%-1" },
"click": { "item": "led_living/cmd", "icmd": "TOGGLE" }
}
}
}
+183
View File
@@ -0,0 +1,183 @@
{
"mqtt": [
"house-climate",
"192.168.88.2"
],
"topics": {
"root": "house",
"snsr": "house/snsr/"
},
"can": {
"addr": 13
},
"ow": {
"28FFC68116208A08": [
{
"emit": "t_bath",
"item": "tbath"
},
{
"item": "p_bedr/floor_temp"
}
],
"28FFE45716208A7B": [
{
"emit": "t_bedr",
"item": "tbedr"
},
{
"item": "p_bedr/ch_temp"
}
]
},
"items": {
"p_bedr": [
14,
[
33,
"panel",
{
"settemp": {
"item": "tbedr/set",
"can": [
15,
6,
"set"
],
"@S": 0
},
"sethum": {
"can": [
15,
433,
"set"
],
"@S": 0
},
"hum": {
"emit": "${snsr}humbedr/val",
"@S": null,
"can": [
15,
433,
"val"
]
},
"setfloor": {
"item": "tbath/set",
"@S": 0
},
"acon": {
"can": [
15,
6,
"cmd"
],
"@S": 0
},
"fanspeed": {
"can": [
15,
3,
"fan",
9
],
"@S": 0
},
"humpwr": {
"can": [
15,
433,
"cmd"
],
"@S": 0
},
"roomtemp": {
"emit": "house/t_bedr_panel",
"@S": 0
},
"floor_temp": {},
"actemp": {},
"alm01": {},
"alm17": {}
}
]
],
"tbedr": [
13,
[
[
450,
100,
9720,
50,
200,
255
],
{
"item": "rbedr/set"
},
{
"item": "p_bedr/settemp"
}
],
23,
526
],
"rbedr": [
16,
[
-28,
1800
],
255,
513
],
"tbath": [
13,
[
[
320,
100,
6912,
50,
200,
100
],
{
"item": "rbath/set"
},
{
"item": "p_bedr/setfloor"
}
],
26,
526
],
"rbath": [
16,
[
-29,
1800
],
100,
513
]
},
"in": {
"0": {
"click": {
"item": "tbedr",
"icmd": "TOGGLE"
},
"dclick": {
"can": [
15,
433,
"cmd"
],
"icmd": "TOGGLE"
}
}
}
}
+429
View File
@@ -0,0 +1,429 @@
{
"mqtt": [
"climate-demo",
"192.168.88.2"
],
"topics": {
"root": "house",
"snsr": "house/snsr/"
},
"modbus": {
"panel": {
"serial": "8E1",
"poll": {
"regs": [
[
39993,
40008
],
[
30000,
30001
]
],
"delay": 5000
},
"par": {
"fanspeed": {
"reg": 40000,
"prefetch": true,
"map": {
"val": [
1,
255,
1,
5
],
"cmd": [
[
"OFF",
0
]
]
},
"id": 7
},
"settemp": {
"reg": 40002,
"prefetch": true,
"id": 12
},
"alm01": {
"reg": 40004,
"id": 13
},
"alm17": {
"reg": 40005,
"id": 14
},
"sethum": {
"reg": 40007,
"prefetch": true,
"id": 16
},
"setvoc": {
"reg": 40008,
"prefetch": true,
"map": {
"val": [
400,
2000,
0,
100
]
},
"id": 17
},
"roomtemp": {
"reg": 30000,
"type": "x10"
},
"hum": {
"reg": 30001
},
"ch_temp": {
"reg": 40009,
"type": "x10",
"id": 3
},
"ext_temp": {
"reg": 40010,
"type": "x10",
"id": 18
},
"floor_temp": {
"reg": 40012,
"type": "x10",
"id": 20
},
"extvoc": {
"reg": 40015,
"map": {
"val": [
400,
2000,
0,
100
]
},
"id": 27
},
"actemp": {
"reg": 40016,
"type": "x10",
"id": 25
},
"fanlvl": {
"reg": 40017,
"id": 21
},
"floormode": {
"reg": 39995,
"prefetch": true,
"id": 22
},
"setfloor": {
"reg": 39996,
"prefetch": true,
"id": 23
},
"humpwr": {
"reg": 39998,
"prefetch": true,
"map": {
"cmd": [
null,
[
"ON",
1
],
[
"OFF",
0
]
],
"val": null
},
"id": 24
},
"fanauto": {
"reg": 39999,
"prefetch": true,
"map": {
"cmd": [
[
"ENABLE",
1
],
[
"DISABLE",
0
],
[
"AUTO",
1
]
],
"val": null
},
"id": 7
},
"acsettemp": {
"reg": 39994,
"prefetch": true,
"id": 26
},
"acon": {
"reg": 40003,
"prefetch": true,
"map": {
"cmd": [
1,
[
"OFF",
0
]
],
"val": null,
"def": 40001
},
"id": 8
},
"acmode": {
"reg": 40001,
"prefetch": true,
"map": {
"cmd": [
[
"FAN_ONLY",
1
],
[
"HEAT",
4
],
[
"COOL",
2
],
[
"AUTO",
8
]
]
},
"id": 8
},
"acfanauto": {
"reg": 39993,
"prefetch": true,
"map": {
"cmd": [
0,
[
"AUTO",
1
]
],
"val": null,
"def": 39997
},
"id": 2
},
"acfan": {
"reg": 39997,
"prefetch": true,
"map": {
"cmd": [
[
"OFF",
0
],
[
"LOW",
1
],
[
"HIGH",
3
],
[
"MEDIUM",
2
]
]
},
"id": 2
}
}
}
},
"items": {
"panels": [
[
7,
210
],
[
"p_living"
],
null
],
"p_living": [
14,
[
31,
"panel",
{
"fanspeed": {
"emit": "house/climate/living/fan",
"@S": 0
},
"settemp": [
{
"item": "t_living/set",
"@S": 0
},
{
"item": "ac_living/set"
}
],
"sethum": {
"item": "hum_living/set",
"@S": 0
},
"hum": {
"emit": "${snsr}humliving/val",
"@S": null
},
"roomtemp": {
"emit": "house/t_living_panel",
"@S": 0
},
"setfloor": {
"item": "floor_living/set",
"@S": 0
},
"acon": {
"item": "ac_living/cmd",
"@S": 0
},
"acfanauto": {
"item": "ac_living/fan",
"@S": 0
},
"acsettemp": {
"item": "ac_living/set",
"@S": 0
},
"acmode": {
"@S": 0
},
"acfan": {
"@S": 0
},
"humpwr": {
"item": "hum_living/cmd",
"@S": 0
},
"fanauto": {
"emit": "house/climate/living/fanauto",
"@S": 0
},
"floor_temp": {},
"actemp": {},
"ext_temp": {},
"alm01": {},
"alm17": {},
"fanlvl": {}
}
]
],
"t_living": [
13,
[
[
500,
100,
10800,
50,
200,
200,
30
],
{
"item": "r_living/set"
},
{
"item": "p_living/settemp"
}
],
21,
526
],
"r_living": [
16,
[
-33,
1800
],
200,
513
],
"floor_living": [
13,
[
[
400,
0,
6480,
50,
200,
255
],
{
"item": "r_floor/set"
},
{
"item": "p_living/setfloor"
}
],
31,
526
],
"r_floor": [
16,
[
-32,
1800
],
255,
513
],
"ac_living": [
10,
0
],
"hum_living": [
13,
[
[
10,
0,
0,
50,
250,
40
],
{
"emit": "house/humidifier/living/set"
},
{
"emit": "house/climate/living/humset"
}
],
30,
2
]
}
}
@@ -0,0 +1,8 @@
{
"mqtt": ["counter-demo", "192.168.88.2"],
"items": {
"energy_ticks": [20, [0.02, 3600]],
"load_relay": [6, 30],
"load_pwm": [3, 11]
}
}
@@ -0,0 +1,9 @@
{
"mqtt": ["damper-demo", "192.168.88.2"],
"topics": { "root": "house" },
"items": {
"damper_living": [12, [4, 33, 58, 629, 289, 5000]],
"damper_bedroom": [12, [5, 32, 59, 631, 296, 5000]],
"dampers": [7, ["damper_living", "damper_bedroom"]]
}
}
+8
View File
@@ -0,0 +1,8 @@
{
"mqtt": ["pwm-demo", "192.168.88.2"],
"items": {
"light_dim": [3, 9],
"vent_speed": [3, 10],
"led_group": [7, ["light_dim", "vent_speed"]]
}
}
+32
View File
@@ -0,0 +1,32 @@
{
"mqtt": [
"power-demo",
"192.168.88.2"
],
"topics": {
"root": "house"
},
"syslog": [
"192.168.88.2"
],
"items": {
"merc": [
22,
[
67,
9600,
"8N1",
2,
[
1,
2,
3,
4,
5,
6
],
3600000
]
]
}
}
+11
View File
@@ -0,0 +1,11 @@
{
"mqtt": ["scene-demo", "192.168.88.2"],
"items": {
"lamp_hall_1": [6, 22],
"lamp_hall_2": [6, 23],
"lamp_hall_3": [6, 24],
"hall_lights": [7, ["lamp_hall_1", "lamp_hall_2", "lamp_hall_3"]],
"entry_light": [6, 27],
"corridor_group": [7, ["lamp_hall_1", "entry_light"]]
}
}
+92
View File
@@ -0,0 +1,92 @@
{
"mqtt": [
"floor-demo",
"192.168.88.2"
],
"topics": {
"root": "house"
},
"ow": {
"28FFC68116208A08": [
{
"emit": "house/t_bath",
"item": "tbath"
}
],
"28AA5C343E1401DC": [
{
"emit": "house/t_kitchen",
"item": "tkitchen"
}
]
},
"items": {
"tbath": [
13,
[
[
320,
100,
6912,
50,
200,
100
],
{
"item": "rbath/set"
}
],
26,
526
],
"rbath": [
16,
[
-29,
1800
],
100,
513
],
"tkitchen": [
13,
[
[
400,
0,
17280,
50,
200,
100
],
{
"item": "rkitchen/set"
}
],
21,
526
],
"rkitchen": [
16,
[
-30,
1800
],
100,
513
]
},
"in": {
"2": {
"T": 0,
"click": {
"item": "tbath/cmd",
"icmd": "TOGGLE"
},
"lcmd": {
"item": "tbath/cmd",
"icmd": "OFF"
}
}
}
}
+18
View File
@@ -0,0 +1,18 @@
{
"mqtt": ["humidifier-demo", "192.168.88.2"],
"items": {
"humidifier": [
21,
[
[22, 23, 54, 200, 600, 11, 20, 50],
{
"living_room": { "N": 1, "pin": 27, "set": 40 },
"bedroom": { "N": 1, "pin": 25, "set": 40 }
},
{ "emit": "house/humidifier/motor" },
{ "emit": "house/humidifier/fault" }
]
],
"humidifier_led": [6, 29, 1, 1]
}
}
+16
View File
@@ -0,0 +1,16 @@
{
"mqtt": ["spiled-demo", "192.168.88.2"],
"topics": { "root": "house" },
"items": {
"led_ambilight": [11, [7, 60]],
"led_cabinet": [11, [8, 30]]
},
"in": {
"0": {
"T": 0,
"click": { "item": "led_ambilight/cmd", "icmd": "TOGGLE" },
"rpcmd": { "item": "led_ambilight/set", "icmd": "%+4" },
"dclick": { "item": "led_ambilight/10-20/cmd", "icmd": "TOGGLE" }
}
}
}
-221
View File
@@ -1,221 +0,0 @@
{
"dmx":[3,60],
"mqtt":["lh22-test","192.168.11.4"],
"dmxin":["led5","led6","led7","led8"],
"topics":{"root":"test2"},
"syslog":["192.168.88.2"],
"ow":{
"282F7E81E3713C59":{"emit":"t_1"}
},
"modbus":
{
"s8":{
"poll":{"irs":[[0,3]],"regs":[[0,1],31],"delay":11000},
"par":{
"co2":{"ir":3},
"meterStat":{"ir":0},
"alarmStat":{"ir":1},
"hr1":{"reg":0},
"hr2":{"reg":1},
"hr32":{"reg":31}
}
},
"term":{
"poll":{"regs":[0],"delay":12000},
"par":{
"t":{"reg":0,"type":"x10"}
}
},
"thmeter":{
"serial":"8N1",
"baud":4800,
"poll":{"regs":[[0,1],[2000,2001],[80,81]],"delay":3000},
"par":{
"hum" :{"reg":0,"type":"x10"},
"temp" :{"reg":1,"type":"x10"},
"slaveid" :{"reg":2000},
"baud" :{"reg":2001},
"tcalib":{"reg":80,"type":"x10"},
"hcalib":{"reg":81,"type":"x10"}
}
},
"panel":{
"serial":"8E1",
"poll":{"regs":[[39993,40008],[30000,30001]],"delay":5000},
"par":{
"fanspeed" :{"reg":40000,"prefetch":true,"map":{"val":[1,255,1,5],"cmd":[["OFF",0]]},"id":7},
"settemp" :{"reg":40002,"prefetch":true,"id":12},
"alm01":{"reg":40004,"id":13},
"alm17":{"reg":40005,"id":14},
"alm33":{"reg":40006,"id":15},
"sethum" :{"reg":40007,"prefetch":true,"id":16},
"setvoc" :{"reg":40008,"prefetch":true,"map":{"val":[400,2000,0,100]},"id":17},
"roomtemp" :{"reg":30000,"type":"x10"},
"hum" :{"reg":30001},
"voc" :{"reg":30002},
"ch_temp" :{"reg":40009,"type":"x10","id":3},
"ext_temp" :{"reg":40010,"type":"x10","id":18},
"out_temp" :{"reg":40011,"type":"x10","id":19},
"floor_temp" :{"reg":40012,"type":"x10","id":20},
"ch_hum" :{"reg":40013,"id":28},
"heat_pwr":{"reg":40014,"id":29},
"extvoc":{"reg":40015,"map":{"val":[400,2000,0,100]},"id":27},
"actemp":{"reg":40016,"type":"x10","id":25},
"fanlvl":{"reg":40017,"id":21},
"floormode":{"reg":39995,"prefetch":true,"id":22},
"setfloor":{"reg":39996,"prefetch":true,"id":23},
"humpwr":{"reg":39998,"prefetch":true,"map":{"cmd":[null,["ON",1],["OFF",0]],"val":null},"id":24},
"fanauto":{"reg":39999,"prefetch":true,"map":{"cmd":[["ENABLE",1],["DISABLE",0],["AUTO",1]],"val":null},"id":7},
"acsettemp":{"reg":39994,"prefetch":true,"id":26},
"acon":{"reg":40003,"prefetch":true,"map":{"cmd":[1,["OFF",0]],"val":null,"def":40001},"id":8},
"acmode" :{"reg":40001,"prefetch":true,"map":{"cmd":[["FAN_ONLY",1],["HEAT",4],["COOL",2],["AUTO",8]]},"id":8},
"acfanauto":{"reg":39993,"prefetch":true,"map":{"cmd":[0,["AUTO",1]],"val":null,"def":39997},"id":2},
"acfan":{"reg":39997,"prefetch":true,"map":{"cmd":[["OFF",0],["LOW",1],["HIGH",3],["MEDIUM",2]]},"id":2},
"y":{"reg":65512},
"mo":{"reg":65513},
"d":{"reg":65514},
"dw":{"reg":65515},
"h":{"reg":65516},
"m":{"reg":65517},
"s":{"reg":65518},
"blmind":{"reg":50051},
"blmaxd":{"reg":50052},
"blminn":{"reg":50053},
"blmaxn":{"reg":50054}
}
}
},
"items": {
"th":[14,[1,"thmeter",
{
"temp":{"emit":"temp","@S":null},
"hum" :{"emit":"zal2hum","@S":null},
"slaveid" :{"emit":"slaveid"},
"baud" :{"emit":"baud"},
"tcalib":{"emit":"tcalib"},
"hcalib":{"emit":"hcalib"}
}
]],
"pout0":[6,22],
"pout1":[6,23],
"pout2":[6,24],
"pout3":[6,25],
"pout4":[3,9],
"pout5":[3,8],
"pout6":[3,11],
"pout7":[3,12],
"pwm0" :[3,4],
"pwm1" :[3,5],
"pwm2" :[3,6],
"pwm3" :[3,7],
"unprot0":[6,33],
"unprot1":[6,32],
"unprot2":[6,31],
"unprot3":[6,30],
"unprot4":[6,29],
"unprot5":[6,28],
"unprot6":[6,27],
"unprot7":[6,26],
"led": [1,1],
"led2":[1,5],
"led3":[1,9],
"led4":[1,13],
"led5":[1,17],
"led6":[1,21],
"led7":[1,25],
"led8":[1,29],
"dimmer" :[0,33],
"dimmer2":[0,34],
"dimmer3":[0,35],
"dimmer4":[0,36],
"dimmer5":[0,37],
"dimmer6":[0,38],
"dimmers":[7,["dimmer","dimmer2","dimmer3","dimmer4","dimmer5","dimmer6"]],
"leds":[7,["led","led2","led3","led4","led5","led6"]],
"mbuses":[7,["mbusdim1","mbusdim2","mbusdim3","mbusdim4"]],
"all":[7,["dimmers","uouts","relays","leds"]],
"relays":[7,["pout0","pout1","pout2","pout3","pout4","pout5","pout6","pout7"]],
"uouts":[7,["unprot0","unprot1","unprot2","unprot3","unprot4","unprot5","unprot6","unprot7"]]
},
"in":{
"42":{"emit":"in0"},
"44":{"emit":"in1"},
"46":{"emit":"in2"},
"49":{"emit":"in3"},
"43":{"emit":"in4"},
"45":{"emit":"in5"},
"47":{"emit":"in6"},
"48":{"emit":"in7"},
"34":{"emit":"in8"},
"36":{"emit":"in9"},
"38":{"emit":"in10"},
"40":{"emit":"in11"},
"35":{"emit":"in12"},
"37":{"emit":"in13"},
"39":{"emit":"in14"},
"41":{"emit":"in15"},
"54":{"T":64,"emit":"a00","item":"water","map":[200,700],"scmd":"ON","rcmd":"OFF"},
"55":{"T":64,"emit":"a01","item":"water","map":[200,700],"scmd":"ON","rcmd":"OFF"},
"56":{"T":64,"emit":"a02","map":[0,1024,0,1024,10]},
"57":{"T":64,"emit":"a03","map":[0,1024,0,1024,10]},
"58":{"T":64,"emit":"a04","map":[0,1024,0,1024,10]},
"59":{"T":64,"emit":"a05","map":[0,1024,0,1024,10]},
"60":{"T":64,"emit":"a06"},
"61":{"T":64,"emit":"a07","map":[0,1024,0,1024,5]},
"62":{"T":64,"emit":"a08","map":[0,1024,0,1024,5]},
"63":{"T":64,"emit":"a09","map":[0,1024,0,1024,5]},
"64":{"T":64,"emit":"a10","map":[0,1024,0,1024,5]},
"65":{"T":64,"emit":"a11","map":[0,1024,0,1024,5]},
"66":{"T":2,"emit":"d12"},
"67":{
"T":2,
"scmd":{"emit":"d13","ecmd":"scmd"},
"rcmd":{"emit":"d13","ecmd":"rcmd"},
"lcmd":{"emit":"d13","ecmd":"lcmd"},
"click":{"emit":"d13","ecmd":"click"},
"dclick":{"emit":"d13","ecmd":"dclick"},
"tclick":{"emit":"d13","ecmd":"tclick"},
"scmd2":{"emit":"d13","ecmd":"scmd2"},
"scmd3":{"emit":"d13","ecmd":"scmd3"},
"lcmd2":{"emit":"d13","ecmd":"lcmd2"},
"lcmd3":{"emit":"d13","ecmd":"lcmd3"},
"rpcmd":{"emit":"d13","ecmd":"rpcmd"},
"rpcmd2":{"emit":"d13","ecmd":"rpcmd2"},
"rpcmd3":{"emit":"d13","ecmd":"rpcmd3"}
},
"68":{"T":2,
"scmd":{"emit":"d14","ecmd":"scmd"},
"rcmd":{"emit":"d14","ecmd":"rcmd"},
"lcmd":{"emit":"d14","ecmd":"lcmd"},
"click":{"emit":"d14","ecmd":"click"},
"dclick":{"emit":"d14","ecmd":"dclick"},
"tclick":{"emit":"d14","ecmd":"tclick"},
"scmd2":{"emit":"d14","ecmd":"scmd2"},
"scmd3":{"emit":"d14","ecmd":"scmd3"},
"lcmd2":{"emit":"d14","ecmd":"lcmd2"},
"lcmd3":{"emit":"d14","ecmd":"lcmd3"},
"rpcmd":{"emit":"d14","ecmd":"rpcmd"},
"rpcmd2":{"emit":"d14","ecmd":"rpcmd2"},
"rpcmd3":{"emit":"d14","ecmd":"rpcmd3"}
},
"69":{"T":2,
"scmd":{"emit":"d15","ecmd":"scmd"},
"rcmd":{"emit":"d15","ecmd":"rcmd"},
"lcmd":{"emit":"d15","ecmd":"lcmd"},
"click":{"emit":"d15","ecmd":"click"},
"dclick":{"emit":"d15","ecmd":"dclick"},
"tclick":{"emit":"d15","ecmd":"tclick"},
"scmd2":{"emit":"d15","ecmd":"scmd2"},
"scmd3":{"emit":"d15","ecmd":"scmd3"},
"lcmd2":{"emit":"d15","ecmd":"lcmd2"},
"lcmd3":{"emit":"d15","ecmd":"lcmd3"},
"rpcmd":{"emit":"d15","ecmd":"rpcmd"},
"rpcmd2":{"emit":"d15","ecmd":"rpcmd2"},
"rpcmd3":{"emit":"d15","ecmd":"rpcmd3"}
}
}
}
@@ -11,7 +11,7 @@
"lampcab31",
"lampcab32",
"lampsauna3",
"lampbath33",
"lampbath3",
"lampktc3",
"lampwc3",
"lamp4",
@@ -27,14 +27,9 @@
"bra32"]],
"gr_hall3":[7,["lamphall3","lampstw3"]],
"gr_gost3":[7,["lampgst3","lampktc3"]],
"relays":[7,["pout0","thermostat","pout2","pout3","pout4","pout5","pout6"]],
"relays":[7,["pout0","thermostat","pout2","pout4","pout5","pout6"]],
"uouts":[7,["unprot0","unprot1","unprot2","unprot3","unprot4","unprot5","unprot6","unprot7"]],
"mb1":[44,[1,0,3,100]],
"mb2":[44,[1,1,3,100]],
"mb3":[44,[1,2,3,100]],
"mb4":[44,[1,3,3,100]],
"mba":[44,[96,0,0]],
"lampbedr3":[0,1],
"lampcab31":[0,2],
@@ -0,0 +1,7 @@
{
"mqtt": ["modbus-demo", "192.168.88.2"],
"items": {
"ac_dimmer": [4, [96, 0, 0, 255]],
"ac_dimmer_2": [4, [97, 0, 0, 255]]
}
}
File diff suppressed because it is too large Load Diff
+100
View File
@@ -0,0 +1,100 @@
{
"mqtt": [
"lh1",
"192.168.1.10"
],
"topics": {
"root": "house"
},
"items": {
"ac_multizone": [
[
18,
5
],
{
"bedroom": {
"V": 40,
"pid": [
1.0,
0.05,
0.02,
5.0
],
"set": 21.0,
"cmd": 15,
"fan": -1,
"out": -1,
"item": "damper_bedroom/set",
"cas": {
"fan": {
"emit": "house/climate/bedroom/fan"
}
}
},
"living_room": {
"V": 80,
"pid": [
1.0,
0.05,
0.02,
5.0
],
"set": 22.0,
"cmd": 15,
"fan": -1,
"out": -1,
"item": "damper_living/set",
"cas": {
"fan": {
"emit": "house/climate/living/fan"
}
}
},
"": {
"item": "vent",
"turnbyfan": 15,
"val": -1,
"mode": 2
}
}
],
"damper_bedroom": [
3,
5
],
"damper_living": [
3,
6
],
"vent": [
14,
[
4,
"airset",
{
"tset": {
"emit": "house/vent/set",
"@V": null
},
"pmode": {
"emit": "house/vent/cmd",
"@V": null
},
"fanspeed": {
"emit": "house/vent/fan",
"@V": null
},
"on": {
"emit": "house/vent/oncmd",
"@V": null
},
"$temp": {
"item": "ac_multizone/val",
"@S": null
}
}
]
]
}
}
@@ -0,0 +1,81 @@
{
"mqtt": [
"heating-demo",
"192.168.88.2"
],
"topics": {
"root": "house"
},
"ow": {
"28FF163116208AC7": [
{
"emit": "house/t_living",
"item": "tliving"
}
],
"28FF403E16208A54": [
{
"emit": "house/t_cabinet",
"item": "tcabinet"
}
]
},
"items": {
"tliving": [
13,
[
[
500,
100,
10800,
50,
200,
200,
30
],
{
"item": "rliving/set"
}
],
22,
526
],
"rliving": [
16,
[
-27,
1800
],
200,
513
],
"tcabinet": [
13,
[
[
500,
100,
10800,
50,
200,
200,
30
],
{
"item": "rcabinet/set"
}
],
21,
526
],
"rcabinet": [
16,
[
-33,
1800
],
200,
513
]
}
}
+14
View File
@@ -0,0 +1,14 @@
{
"mqtt": ["relay-demo", "192.168.88.2"],
"items": {
"pump_relay": [6, 23],
"boiler_relay": [6, 24, 0, 0],
"fan_relay": [6, 25, 1, 1]
},
"in": {
"0": {
"click": { "item": "pump_relay", "icmd": "TOGGLE" },
"dclick": { "item": "fan_relay", "icmd": "TOGGLE" }
}
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"mqtt": ["rgb-demo", "192.168.88.2"],
"items": {
"rgbw_strip": [1, 10],
"rgbw_strip_backup": [1, 20, 255, 0]
}
}
+122
View File
@@ -0,0 +1,122 @@
{
"mqtt": [
"sensors-demo",
"192.168.88.2"
],
"topics": {
"root": "house",
"s8": "house/snsr/s8",
"snsr": "house/snsr/"
},
"modbus": {
"s8": {
"poll": {
"irs": [
[
0,
3
]
],
"regs": [
[
0,
1
],
31
],
"delay": 11000
},
"par": {
"co2": {
"ir": 3
},
"$meterStat": {
"ir": 0
},
"$alarmStat": {
"ir": 1
},
"hr1": {
"reg": 0
},
"hr2": {
"reg": 1
},
"hr32": {
"reg": 31
}
}
},
"term": {
"poll": {
"regs": [
0
],
"delay": 12000
},
"par": {
"t": {
"reg": 0,
"type": "x10"
}
}
}
},
"items": {
"s8living": [
14,
[
51,
"s8",
{
"co2": {
"emit": "${s8}living/val",
"item": "co2living_pid/val",
"@S": null
},
"$meterStat": {
"emit": "${s8}living/meterStat",
"@S": null
},
"$alarmStat": {
"emit": "${s8}living/alarmStat",
"@S": null
},
"hr1": {},
"hr2": {}
}
]
],
"t_duct": [
14,
[
52,
"term",
{
"t": {
"emit": "house/snsr/t_duct/val",
"@S": null
}
}
]
],
"co2living_pid": [
13,
[
[
-0.5,
1,
0,
300,
250,
0
],
{
"emit": "house/climate/living/air_request"
}
],
600,
20
]
}
}
+31
View File
@@ -0,0 +1,31 @@
{
"mqtt": ["sprinkler-demo", "192.168.88.2"],
"topics": { "root": "garden" },
"items": {
"sprinkler": [
23,
{
"": {
"vIn": 35,
"wMax": 44,
"wMin": 46,
"rDren": 34,
"fbDren": 63,
"rPump": 33,
"fbPump": 62,
"wCtr": 49
},
"north": { "pin": 36, "set": 60, "cmd": 1 },
"south": { "pin": 37, "set": 100, "cmd": 1 },
"trees": { "pin": 38, "set": 60, "cmd": 2 },
"outlets": { "set": 0, "cmd": 2 }
}
]
},
"in": {
"44": { "emit": "garden/s_out/sprinkler/$wMax" },
"46": { "emit": "garden/s_out/sprinkler/$wMin" },
"62": { "emit": "garden/s_out/sprinkler/$fbPump" },
"63": { "emit": "garden/s_out/sprinkler/$fbDren" }
}
}
@@ -0,0 +1,15 @@
{
"mqtt": ["thermo-demo", "192.168.88.2"],
"items": {
"heater_tank": [5, 24, 33],
"heater_floor": [5, 25, 28],
"cooling_fan": [6, 26]
},
"in": {
"5": {
"T": 4,
"emit": "/myhome/s_out/t_room",
"item": "heater_tank"
}
}
}
+1
View File
@@ -8,6 +8,7 @@
| Файл | Я | Описание |
|--|--|--|
| [core\_concepts.md](core/core_concepts.md) | RU | **Основные принципы**: базовые сущности — item (канал), itemCmd (унифицированная команда), execObj (объект действия) |
| [light\_hub\_полное\_инженерное\_описание\_json\_конфигурации\_v2.md](core/light_hub_полное_инженерное_описание_json_конфигурации_v2.md) | RU | Полное описание JSON-конфигурации: секции, 24 типа каналов (0-23), примеры |
| [channel\_types\_reference.md](core/channel_types_reference.md) | RU | Справочник типов каналов: коды, форматы настройки, команды, доступность по целям |
| [technical\_channel\_types\_table.md](core/technical_channel_types_table.md) | RU | Техническая таблица типов каналов (формат item.h, суффиксы, матрица) |
@@ -209,8 +209,8 @@
### CH\_COUNTER (20) - Счётчик по импульсам/времени
```json
"energy_meter": [20, [0.02, 1.2]] // коэфф 0.02, период автосуммирования 1.2 с
"gas_counter": [20, 0] // без калибровки
"energy_meter": [20, [0.02, 1.2]] // инкремент 0.02, период автосуммирования 1.2 с (увеличивается когда канал активен )
"gas_counter": [20, 0] // счетчик просто сохраняет значение, изменение которых происзодит только по внешним командам
```
### CH\_HUMIDIFIER (21) - Увлажнитель
+73 -16
View File
@@ -27,7 +27,7 @@
- [CH\_RGBWW (17)](#ch_rgbww-17---dmx-rgbww)
- [CH\_MULTIVENT (18)](#ch_multivent-18---многозональная-вентиляция)
- [CH\_ELEVATOR (19)](#ch_elevator-19---управление-лифтом)
- [CH\_COUNTER (20)](#ch_counter-20---счётчик-импульсов)
- [CH\_COUNTER (20)](#ch_counter-20---счётчик)
- [CH\_HUMIDIFIER (21)](#ch_humidifier-21---управление-увлажнителем)
- [CH\_MERCURY (22)](#ch_mercury-22---счётчик-энергии-mercury)
- [CH\_SPRINKLER (23)](#ch_sprinkler-23---система-полива)
@@ -678,34 +678,91 @@ myhome/dev/multivent_main/bedroom/mode ← HEAT, COOL, FAN
---
## CH\_COUNTER (20) - Счётчик импульсов
## CH\_COUNTER (20) - Счётчик
**Назначение**: Счётчик импульсов (электроэнергия, газ, вода)
**Назначение**: накопление показаний — вода, газ, электроэнергия,
моторчасы оборудования. GPIO не используется: значение хранится в самих
данных канала (I\_VAL) и переживает перезагрузку. Работает в двух
режимах.
### Синтаксис
### Режим 1: внешние импульсы (вода, газ)
```json
"counter_name": [20, [коэффициент, период_автосуммирования_сек]]
"counter_name": [20, коэффициент]
```
### Примеры
Канал просто **держит накопленное значение**, а вход контроллера
(геркон водосчётчика, контакт газосчётчика) инкрементирует его
относительной командой `%X`, где `X` — вес одного импульса в единицах
измерения.
```json
{
"items": {
"energy_meter": [20, [0.02, 1.2]], // коэфф 0.02, автосуммирование раз в 1.2 сек
"gas_meter": [20, 0.001], // коэфф 0.001
"water_meter": [20, 0.01, 0, 0] // с начальным значением 0
"waterctr": [20, 0], // 0 — автосуммирования нет
"gasctr": [20, 0],
"fillctr": [20, 0.01, 0] // с начальным значением 0
},
"in": {
"41": { "item": "waterctr/set", "scmd": "%0.01", "rcmd": "" },
"39": { "item": "gasctr/set", "scmd": "%0.1", "rcmd": "" }
}
}
```
### MQTT команды
Каждое срабатывание геркона (передний фронт) отправляет в `/set`
команду `%0.01` — значение растёт на 0.01 м³. Показание читается из
статусного топика `/set`.
```
myhome/dev/energy_meter/val ← текущее значение (кВт·ч)
myhome/dev/gas_meter/val ← текущее значение (м³)
myhome/dev/waterctr/set ← 123.45 (текущее показание, м³)
```
### Режим 2: автоинкремент старт-стоп (моторчасы)
Если задан массив `[импульс, период_сек]`, канал превращается в
**счётчик времени работы**: по команде `ON` (также HEAT/COOL/AUTO/FAN/
DRY/HEATCOOL) стартует таймер, и каждые `период` секунд к значению
добавляется `импульс`. Команда `OFF` останавливает счёт. Установка
ненулевого значения в `/set` также запускает счёт, нулевое —
останавливает.
```json
{
"items": {
"pumpctr": [20, [0.02, 1.2]] // каждые 1.2 сек добавляет 0.02
}
}
```
Запуск/остановка обычно привязываются к управляемому оборудованию
через execObj. Например, счётчик наработки насоса увлажнителя (тип 21
вызывает свой `motorExecObj` с командой `ON` при включении насоса и
`OFF` при выключении):
```json
{
"items": {
"hum": [21, [
[22, 23, 54, 200, 600, 11, 20, 50],
{ "bedroom": { "N": 1, "pin": 25 } },
{ "item": "pumpctr" }
]],
"pumpctr": [20, [0.02, 1.2]]
}
}
```
С 0.02 за 1.2 секунды канал набирает 1 «минуту» за минуту реального
времени работы насоса — показание в `/set` и есть наработка в минутах.
```
myhome/dev/pumpctr/set ← 1523.6 (наработка, мин)
```
### Синтаксис
```json
"counter_name": [20] // режим 1, без аргументов
"counter_name": [20, вес_импульса] // режим 1 (вес для справки)
"counter_name": [20, [импульс, период_сек]] // режим 2: автоинкремент
"counter_name": [20, ..., начальное_значение] // + стартовое показание (I_VAL)
```
---
+276
View File
@@ -0,0 +1,276 @@
# Основные принципы LightHub
> Этот раздел объясняет базовые сущности, на которых построен контроллер:
> **item** (канал), **itemCmd** (унифицированная команда) и **execObj**
> (унифицированный объект действия). Понимание этих трёх вещей делает
> предсказуемым всё остальное: конфигурацию, MQTT-топики, поведение
> модулей и расширение системы новыми типами устройств.
>
> Раздел адресован инженерам-интеграторам и разработчикам модулей.
---
## 1. Item — виртуальный канал
**Item — это канал**: единая абстракция для всего, чем LightHub управляет
или что измеряет. Лампа за DMX, реле на GPIO, термостат, датчик 1-Wire,
Modbus-устройство, кондиционер Haier, группа светильников, система полива —
всё это items.
### 1.1 Как item описан в конфигурации
Каждый item — запись в глобальном объекте `items` JSON-конфигурации.
Имя записи — имя канала (оно же база MQTT-топика), значение — массив:
```json
"items": {
"lamp_living": [0, 5],
"pump": [6, 23],
"heating": [13, [[500, 100, 10800], {"item": "rheat/set"}], 21]
}
```
Позиции массива фиксированы (см. `item.h`, `I_TYPE…I_TIMESTAMP`):
| Индекс | Поле | Содержимое |
|---|---|---|
| 0 | `I_TYPE` | Тип канала `CH_*` (0–23) — выбирает драйвер |
| 1 | `I_ARG` | Аргумент драйвера: пин, адрес или массив параметров |
| 2 | `I_VAL` | Последнее значение (уставка) — сохраняется, переживает перезагрузку |
| 3 | `I_CMD` | Последняя команда + служебные флаги |
| 4 | `I_EXT` | Расширение драйвера |
| 5 | `I_TIMESTAMP` | Отложенная команда (время срабатывания) |
В конфигурации обычно задают только `[тип, аргумент]`; остальные поля
контроллер создаёт и ведёт сам.
Опционально, можно задать третий параметр масива - значение, которое будет изначально записано в уставку канала при включении (при восстановлении состояния из топика MQTT оно будет перезаписано, если в топике сохранено предыдущее значение)
Также, можно определить четвертый параметр массива - команду, с которой будет инициализирован канал (по умолчанию OFF, но можно задать иное значение (в виде цифры). Также, будет перезаписано при восстановлении, если в топике сохранено предыдущее значение)
Специальная возможность: к значению этого параметра можно добавить специальное побитовое значение, которое инициализирует канал сразу с одним или несколькими специальными флагами, например, в заблокированном состоянии (см команда FREEZE), в котором команды и/или значения будут игнорироваться вплоть до команды UNFREEZE, или "Запрещенном" (команда DISABLE) состоянии, выход из которых возможен по команде ENABLE
Полный перечень флагов:
```
#define FLAG_DISABLED 0x100UL // 256 в десятичном виде
#define FLAG_LOCKED_CMD 0x200UL // 512 в десятичном виде
#define FLAG_LOCKED_SET 0x400UL // 1024 в десятичном виде
#define FLAG_FREEZED 0x600UL // 1536 - игнорируем и команду и значение
```
### 1.2 Тип канала выбирает драйвер, общее — наследуется
Тип канала (`CH_RELAY`, `CH_PID`, `CH_MBUS`, …) определяет **драйвер** —
модуль, который знает, как говорить с конкретной природой устройства.
Но все драйверы наследуются от общего базового класса (`abstractOut`),
поэтому у всех каналов есть одинаковый набор базовых свойств, работающих
**одинаково для каналов разной природы**:
- **Команды** `ON / OFF / TOGGLE / HALT / REST / XON / XOFF / FREEZE /
UNFREEZE / ENABLE / DISABLE` — включая сквозные флаги: `HALT` гасит
канал с возможностью обратного включения по `REST`; `XON/XOFF` —
моментные включения; `FREEZE` блокирует изменения.
- **Значения** `/set` — числовая уставка (яркость, температура, положение
задвижки, скважность), `/val` — измеренное вовне значение полезное каналу.
- **Отложенные команды** — `ON 5000` выполнится через 5 секунд (если направлено в суффикс /del) либо немедленно выполненная команда ON с отложенной через 5 сек противоположной командой (тут- OFF) если отправлено в суффикс /cmd
- **Статусы** — контроллер публикует состояние канала в MQTT и рассылает
по CAN по единой схеме.
- **Группы** — item типа `CH_GROUP` просто перечисляет имена других
items; команда группе рекурсивно выполняется на всех членах. Группы
могут вкладываться друг в друга и пересекаться.
- **Персистентность** — значение и команда канала хранятся в MQTT брокере
и восстанавливаются после перезагрузки.
Именно поэтому, научившись управлять диммером, вы уже умеете управлять
реле, термостатом и Modbus-устройством: интерфейс один, разница — только
в аргументах драйвера.
### 1.3 Item с суффиксом: `item/subitem/suffix`
Канал адресуется строкой `имя_канала/суффикс`, где суффикс указывает,
какое свойство канала затрагивается (`cmd`, `set`, `val`, `fan`, `mode`,
`hue`, …). Ряд драйверов (MULTIVENT, HUMIDIFIER, SPRINKLER, MBUS) делит
один item на **подканалы** по имени: `vents/zal3/set`, `hum/bedr1/cmd`.
Имена подканалов — это ключи объекта-аргумента канала.
Полный список суффиксов — в [справочнике суффиксов](suffixes_reference.md).
---
## 2. itemCmd — унифицированная команда
**Всё, что приходит в канал, кодируется одной структурой — `itemCmd`.**
Неважно, откуда пришло сообщение (MQTT, CAN, кнопка на входе, HTTP API,
другой item) и куда оно идёт: сначала оно разбирается в `itemCmd`, и уже
в этом виде передаётся каналу. Это «единая валюта» управляющего ядра.
### 2.1 Что внутри
`itemCmd` упаковывает в два 32-битных слова три вещи:
- **Код команды** (`CMD_*`): `ON`, `OFF`, `TOGGLE`, `HALT`, `REST`,
`XON`, `XOFF`, `HEAT`, `COOL`, `AUTO`, `FAN_ONLY`, `DRY`,
`HEAT_COOL`, `HIGH/MEDIUM/LOW`, `ENABLE/DISABLE`, `FREEZE/UNFREEZE`,
`RGB`, `HSV`, `RESET` — текстовые имена, массив кодов 1–0x19.
- **Тип значения + само значение** (`ST_*`): целое 0–255 (проценты),
float (температура и пр), «десятые» целочисленное представление вещественного числа без потери точности (12.3 кодируется как 123), цвета HSV/RGB/RGBW и пр.
- **Суффикс** (`S_*`): какому свойству канала адресовано — `cmd`, `set`,
`val`, `fan`, `mode`, `hue`, `sat`, `temp`, `raw` и т.д.
Команда и значение могут присутствовать одновременно: `HEAT` в `/cmd`
кондиционера — это команда; `22.5` в `/set` — значение с суффиксом `set`.
Одна и та же структура используется и в обратную сторону — статусы
каналов сериализуются из `itemCmd` в текст MQTT.
Такая плотная побитная упаковка позволяет уместить унифицированную команду/уставку/измерянное значение или статус канала всего в 64 бита - размер CAN сообщения, что делает возможным надежную коммуникацию между каналами в физически разных контроллерах по шине CAN,
### 2.2 Как это выглядит снаружи
По MQTT сообщение — это просто payload в топике канала с суффиксом:
```
house/lh1/pump/cmd ← ON (команда)
house/lh1/pump/set ← 128 (значение)
house/lh1/ac/cmd ← HEAT (команда)
house/lh1/ac/set ← 22.5 (значение, float)
house/lh1/rgb/HSV ← 240,100,200 (цвет)
house/lh1/lamp/cmd ← ON 5000 (отложенная команда, 5 сек)
```
Внутри конфигурации (EXEC-объекты, входы) команды задаются строками
`"icmd": "TOGGLE"`, `"icmd": "%+4"` (инкремент текущего значения на 4) —
они разбираются тем же парсером в `itemCmd`.
### 2.3 Преобразования
Универсальность `itemCmd` позволяет ядру преобразовывать формулы между
форматами без знания о природе устройства:
- **`map`** — линейное масштабирование значения и/или подстановка
текстовых команд в числа регистра (для Modbus): `"map": {"val": [400,
2000, 0, 100], "cmd": [["HEAT", 4], ["COOL", 2]]}`.
- **Проценты** — 0–100 в топике без суффикса и 0–255 внутри.
---
## 3. execObj — унифицированный объект действия
**execObj (EXEC-объект)** — это маленький JSON-объект, описывающий
«что сделать». Он используется во многих модулях — везде, где нужно
описать реакцию: маршрутизация параметров Modbus-шаблона, каскады
MULTIVENT (`cas`), выходы PID-регулятора, обработчики кнопок и входов,
`onFault` спринклера, `onextcmd` центральной установки.
Исполнением занимается единая функция `executeCommand` (utils.cpp):
один и тот же формат работает и в конфиге, и во время исполнения.
### 3.1 Ключи execObj
```json
{
"item": "имя_item[/subitem][/suffix]",
"emit": "MQTT-топик",
"can": [адрес_контроллера, номер_item, "суффикс", subitem],
"icmd": "команда/значение для item",
"ecmd": "payload для emit",
"map": { ...преобразование значения... }
}
```
| Ключ | Назначение |
|---|---|
| `item` | Вызвать локальный канал: строка `имя/суффикс` (например `pump/cmd`, `ac/set`). Если `icmd` не задан — передаётся само значение, с которым исполнен execObj |
| `emit` | Опубликовать в MQTT. Топик поддерживает подстановки `${ключ}` из секции `topics` и `${sfx}` — текущий суффикс |
| `can` | Отправить команду на другой контроллер LightHub по CAN-шине: `[id_контроллера, id_item, суффикс]`, четвёртый элемент — номер подканала. На приёме адресуется в item целевого контроллера |
| `icmd` | Текст команды для `item` (`ON`, `TOGGLE`, `%+4`, число) |
| `ecmd` | Текст payload для `emit`; без него публикуется значение |
| `map` | Преобразование значения перед доставкой (см. [преобразования map](analog_inputs_and_map.md)) |
Входы (секция `in`) дополнительно понимают пары `icmd`/`irev`, `ecmd`/
`erev` — чередующиеся команды для повторных срабатываний (например,
одна кнопка увеличивает яркость, повторное нажатие уменьшает).
### 3.2 Примеры
Значение регистратора Modbus → в PID и в MQTT:
```json
"co2": {
"emit": "house/snsr/co2living/val",
"item": "co2living_pid/val",
"@S": null
}
```
Команда кнопки → включить локальный насос и отправить по CAN на
контроллер 15, item 431:
```json
"click": { "item": "pump/cmd", "icmd": "TOGGLE" },
"dclick": { "can": [15, 431, "cmd"], "icmd": "TOGGLE" }
```
Выход PID → уставка реле и каскад уставки на панель:
```json
"tliving": [13,
[500, 100, 10800, 50, 200, 200, 30],
[
{ "item": "rliving/set" },
{ "item": "p_living/settemp" }
], 22]
```
execObj может быть **массивом** объектов — выполнятся все по очереди
(как в примере выше: два адресата одного значения). Строка вместо
объекта — тоже execObj (легаси-форма): она трактуется как `emit`.
### 3.3 Служебные пометки `@S` / `@V`
В объектах маршрутизации параметров Modbus (и аналогичных) используются
служебные ключи-пометки:
- `"@S": 0` — не публиковать статус повторно, если значение не изменилось;
- `"@S": null` — публикация при каждом опросе (для датчиков);
- `"@V"` — запоминание последнего отправленного значения (защита от
«эха»: значение, записанное нами самими, не обрабатывается как
изменение от устройства).
---
## 4. Как всё сходится
```
MQTT / CAN / кнопка / HTTP
│ (текст: "ON", "22.5", "HEAT")
▼
┌─────────┐
│ itemCmd │ унифицированная команда/значение
└────┬────┘
│ адресация: item/subitem/suffix
▼
┌───────────────────┐
│ Item (канал) │ общие свойства: команды, значения,
│ + драйвер CH_* │ статусы, группы, персистентность
└─────────┬─────────┘
│ (реакция модуля)
▼
┌─────────┐
│ execObj │ куда доставить результат: item / emit / can
└─────────┘
```
- **Вход** любой природы превращается в `itemCmd`.
- **`itemCmd` адресуется в item** (канал) по имени и суффиксу.
- **Драйвер канала** выполняет команду и/или вычисляет результат.
- **Результат уходит наружу** через `execObj`: в другой item, в MQTT
или на другой контроллер по CAN.
Смежные разделы: [справочник суффиксов](suffixes_reference.md),
[типы каналов](channel_types_reference.md),
[техническая таблица типов](technical_channel_types_table.md),
[работа с MQTT](mqtt_api_reference.md),
[примеры конфигураций](../../config-examples/README.md).
@@ -484,11 +484,11 @@ myhome/s_out/lamp1/hue # текущий оттенок RGB лампы
"ac_haier": [10, 0] // portNum 0-3
```
#### CH\_COUNTER (20) — Счётчик энергии
#### CH\_COUNTER (20) — Счётчик
```json
"energy": [20, [0.02, 60]], // импульс, период автосуммирования (сек)
"gas": [20, 0] // без калибровки
"energy": [20, [0.02, 60]], // инкремент, период автосуммирования (сек) (автоматически увеличивается в активном состоянии)
"gas": [20, 0] // вариант с изменением только по внешним событиям
```
#### CH\_MULTIVENT (18) — Многозональная вентиляция
+27 -12
View File
@@ -471,36 +471,51 @@ RELAYX: [16, [pin, period_сек], val, cmd]
---
## out\_Counter — Автосуммирующий счётчик
## out\_Counter — Счётчик
### Описание
Периодический автосуммированный счётчик: каждые `period` секунд к значению прибавляется `impulse` (контроль расхода воды, газа или подсчёт событий). Не является счётчиком GPIO-импульсов.
Универсальный накопитель показаний: вода, газ, электроэнергия, моторчасы.
GPIO не использует — значение хранится в данных канала (I\_VAL) и
переживает перезагрузку. Два режима работы:
**Основные функции:**
- Периодическое прибавление импульса
- Накопление значений
**Режим 1 — внешние импульсы**: канал держит показание (например,
водосчётчика с герконом), вход контроллера инкрементирует его
относительной командой `%X` в `/set`, где X — вес импульса:
```json
"waterctr": [20, 0],
...
"in": { "41": { "item": "waterctr/set", "scmd": "%0.01", "rcmd": "" } }
```
**Режим 2 — автоинкремент старт-стоп**: с аргументом
`[импульс, период_сек]` канал считает время работы: команда `ON`
запускает, `OFF` останавливает, каждые `период` секунд добавляется
`импульс`. Типично для счётчика моторчасов (старт/стоп приходит через
execObj — например, `motorExecObj` увлажнителя).
### Тип в JSON
```
[20, [impulse, periodSec], val]
[20] // режим 1
[20, вес_импульса] // режим 1
[20, [impulse, periodSec]] // режим 2
[20, ..., начальное_значение] // + стартовое показание
```
### Формат конфигурации
```json
"water_meter": [
20,
[0.02, 60]
]
"gasctr": [20, 0],
"pumpctr": [20, [0.02, 1.2]] // моторчасы: 1 «минута» за минуту
```
### Параметры
| Параметр | Тип | Описание |
|----------|-----|---------|
| `impulse` | float | Значение, прибавляемое за период (arg[0]) |
| `periodSec` | int | Период суммирования (секунды, arg[1]) |
| `impulse` | float | Значение, прибавляемое за период (arg[0], режим 2) |
| `periodSec` | float | Период суммирования, сек (arg[1], режим 2) |
---
+60 -19
View File
@@ -29,36 +29,69 @@
---
## 1. out\_counter — Счётчик импульсов
## 1. out\_counter — Счётчик
### Конфигурация (Type 20)
```json
"pumpctr": [20, [0.02, 1.2]],
"gasctr": [20, 0]
"pumpctr": [20, [0.02, 1.2]], // режим 2: автоинкремент (моторчасы)
"gasctr": [20, 0] // режим 1: внешние импульсы (газ)
```
### Параметры массива
### Два режима работы
**Режим 1 — внешние импульсы** (`[20]`, `[20, вес]` или `[20, 0]`):
канал держит показание, вход контроллера добавляет к нему вес импульса
командой `%X` в `/set`:
```json
"waterctr": [20, 0],
...
"in": {
"41": { "item": "waterctr/set", "scmd": "%0.01", "rcmd": "" }
}
```
**Режим 2 — автоинкремент старт-стоп** (`[20, [импульс, период_сек]]`):
команды `ON`/`OFF` стартуют/останавливают таймер, каждые `период`
секунд добавляется `импульс`. Типичное применение — наработка
оборудования; старт/стоп привязывается через execObj (например,
`motorExecObj` увлажнителя вызывает `{"item": "pumpctr"}` с `ON`/`OFF`
при включении/выключении насоса).
### Параметры массива (режим 2)
| Индекс | Тип | Описание | Пример |
|--------|-----|---------|--------|
| [0] | float | Импульс (накопление за период) | 0.02 л/импульс |
| [0] | float | Импульс — приращение за период | 0.02 (1 «минута» моторчасов) |
| [1] | float | Период накопления (сек) | 1.2 сек |
### Логика работы
### Логика работы (по коду, out\_counter.cpp)
1. Модуль ждёт команду (S\_SET или любой CMD)
2. При получении команды с процентом > 0 запускается таймер
3. По истечении периода [1] добавляется значение [0] * TENS\_BASE
4. Считанное значение публикуется в MQTT
1. `ON`-подобная команда (`ON`, `HEAT`, `COOL`, `AUTO`, `FAN`, `DRY`,
`HEATCOOL`) или ненулевое `/set` запускают таймер (`I_EXT` = метка
времени); `OFF` или `/set 0` останавливают
2. По истечении периода к значению канала (I\_VAL, хранится в «десятых»)
добавляется `импульс × 100`
3. Обновлённое значение публикуется в MQTT (`/set`)
### Пример использования
### Пример (реальная конфигурация, контроллер air)
```json
{
"items": {
"water_meter": [20, [0.01, 5.0]],
"gas_meter": [20, [0.1, 10.0]]
"hum": [21, [
[22, 29, 61, 200, 600, 11, 20, 50],
{ "bedr3": { "N": 1, "pin": 30 } },
{ "item": "pumpctr" }
]],
"pumpctr": [20, [0.02, 1.2]],
"waterctr": [20, 0],
"gasctr": [20, 0]
},
"in": {
"41": { "item": "waterctr/set", "scmd": "%0.01", "rcmd": "" },
"39": { "item": "gasctr/set", "scmd": "%0.1", "rcmd": "" }
}
}
```
@@ -238,15 +271,23 @@ if (!period) period = 5000UL; // по умолчанию 5 сек
### Загружаемые параметры (Poll)
```cpp
uint32_t impulse = item->getFloatArg(0) * TENS_BASE; // [0]
uint32_t impulse = item->getFloatArg(0) * TENS_BASE; // [0] массива аргументов
uint32_t period = item->getFloatArg(1) * 1000.0; // [1] в мс
```
**Логика**:
1. Модуль ждёт активации (getExt() = 0)
2. При получении команды ON/HEAT/COOL/etc запускает таймер
3. По истечении period добавляет impulse к накопленному значению
4. Публикует обновлённое значение
Оба параметра читаются только в режиме автоинкремента
(`[20, [импульс, период]]`); при скалярном аргументе автоинкремент
отключён (period = 0) и канал работает как накопитель внешних
импульсов (`%X` в `/set`).
**Логика** (out\_counter.cpp):
1. Пока таймер не запущен (`getExt() = 0`), Poll ничего не делает
2. Команда `ON` (или HEAT/COOL/AUTO/FAN/DRY/HEATCOOL), а также
ненулевое `/set`, записывают в `I_EXT` метку времени старта; `OFF`
или `/set 0` обнуляют её
3. По истечении period к значению (I\_VAL, в «десятых») добавляется
impulse, метка времени сдвигается на период
4. Публикуется обновлённое значение (FLAG\_PARAMETERS)
---
@@ -274,15 +274,19 @@
| **Конфигурация** | `[19, {"serial":"8N1","baud":19200,"log":...}]` |
| **Статус** | Реализован; компилируется с ELEVATOR\_ENABLE (включён только в custom-build mega2560-optiboot) |
### CH\_COUNTER (20) — Счётчик импульсов
### CH\_COUNTER (20) — Счётчик
Универсальный накопитель показаний. GPIO не использует: значение живёт в
самих данных канала (переживает перезагрузку). Два режима работы.
| Параметр | Значение |
|----------|----------|
| **Назначение** | Счётчик импульсов (кВт·ч, м³, л) |
| **Конфигурация** | int или array `[коэффициент_импульса, период_сек]` |
| **Coefficient** | Кол-во единиц на один импульс |
| **Период** | Период автосуммирования (сек) |
| **Вход** | Внешние импульсы (GPIO-входа в конфиге нет) |
| **Режим 1 — внешние импульсы** | Конфигурация: `[20, коэффициент_импульса]` или `[20, 0]`. Канал просто держит значение (показания водосчётчика, газа); вход (геркон/контакт) инкрементирует его командой `%X` в `/set`, где X — вес одного импульса |
| **Режим 2 — автоинкремент (старт-стоп)** | Конфигурация: `[20, [импульс, период_сек]]`. По команде `ON` (или HEAT/COOL/AUTO/FAN/DRY/HEATCOOL) стартует таймер; каждые `период` секунд к значению добавляется `импульс`. Команда `OFF` останавливает счёт. Типичный кейс — счётчик моторчасов (наработка оборудования) |
| **Хранение** | Значение — в `/set` канала (I\_VAL); публикация после каждого изменения |
| **Команды** | `/set %0.01` — инкремент на 0.01; `/cmd ON/OFF` — старт/стоп автоинкремента; также `/set <значение>` — прямая установка |
Примеры см. [configuration\_examples.md](configuration_examples.md#ch_counter-20---счётчик).
### CH\_HUMIDIFIER (21) — Увлажнитель
+2 -2
View File
@@ -291,7 +291,7 @@ E33–E48 (бит 0 = E01 и т.д.). Запись значения 1–15 бл
Каждая панель — item типа `MBUS` (14) с адресом абонента и именем шаблона:
```json
"p_zal3": [14, [31, "panel", { ...маршрутизация параметров... }], null, 8192, 0]
"p_zal3": [14, [31, "panel", { ...маршрутизация параметров... }]]
```
Первый элемент — Modbus-адрес панели (31/32/33), второй — имя шаблона,
@@ -319,7 +319,7 @@ E33–E48 (бит 0 = E01 и т.д.). Запись значения 1–15 бл
"alm01": {}, "alm17": {}, "alm33": {},
"acmode": { "@S": 0 }, "acfan": { "@S": 0 },
"m": {}, "s": {}, "blmind": {}, "blmaxd": {}
}], null, 8192, 0]
}], null]
```
Элемент `"can"` — маршрутизация на другой контроллер по CAN: `[адрес,
@@ -370,7 +370,7 @@ PWM-каналами. Запросы воздуха в зоны приходят
"fanspeed": {"emit": "house/vent/fan", "@V": null},
"on": {"emit": "house/vent/oncmd", "@V": null},
"$temp": {"item": "ac_multizone/val", "@S": null}
}], null, 8192, 0]
}], null]
}
}
```