diff --git a/README.md b/README.md index aabbcc7..c4d2f3b 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/config-examples/README.md b/config-examples/README.md new file mode 100644 index 0000000..b2affe6 --- /dev/null +++ b/config-examples/README.md @@ -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). diff --git a/config-examples/ac_haier_control.json b/config-examples/ac_haier_control.json new file mode 100644 index 0000000..93c28cc --- /dev/null +++ b/config-examples/ac_haier_control.json @@ -0,0 +1,8 @@ +{ + "mqtt": ["ac-demo", "192.168.88.2"], + "topics": { "root": "house" }, + "items": { + "ac_living": [10, 1], + "ac_bedroom": [10, 2] + } +} diff --git a/config-examples/buttons_and_rotary.json b/config-examples/buttons_and_rotary.json new file mode 100644 index 0000000..6c2eb6e --- /dev/null +++ b/config-examples/buttons_and_rotary.json @@ -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" } + } + } +} diff --git a/config-examples/can_two_controllers.json b/config-examples/can_two_controllers.json new file mode 100644 index 0000000..15f3d3a --- /dev/null +++ b/config-examples/can_two_controllers.json @@ -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" + } + } + } +} \ No newline at end of file diff --git a/config-examples/climate_panel_z031.json b/config-examples/climate_panel_z031.json new file mode 100644 index 0000000..e6662fc --- /dev/null +++ b/config-examples/climate_panel_z031.json @@ -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 + ] + } +} \ No newline at end of file diff --git a/config-examples/counter_energy_monitoring.json b/config-examples/counter_energy_monitoring.json new file mode 100644 index 0000000..e0c7c4d --- /dev/null +++ b/config-examples/counter_energy_monitoring.json @@ -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] + } +} diff --git a/config-examples/damper_motor_feedback.json b/config-examples/damper_motor_feedback.json new file mode 100644 index 0000000..2e163bf --- /dev/null +++ b/config-examples/damper_motor_feedback.json @@ -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"]] + } +} diff --git a/config-examples/dimmer_pwm_gpio.json b/config-examples/dimmer_pwm_gpio.json new file mode 100644 index 0000000..e39682d --- /dev/null +++ b/config-examples/dimmer_pwm_gpio.json @@ -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"]] + } +} diff --git a/config-examples/energy_meter_mercury.json b/config-examples/energy_meter_mercury.json new file mode 100644 index 0000000..4f23546 --- /dev/null +++ b/config-examples/energy_meter_mercury.json @@ -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 + ] + ] + } +} \ No newline at end of file diff --git a/config-examples/c4-3e-11-03-1b-1e.config.json b/config-examples/garden_relay_thermostat_1wire.json similarity index 100% rename from config-examples/c4-3e-11-03-1b-1e.config.json rename to config-examples/garden_relay_thermostat_1wire.json diff --git a/config-examples/group_lighting_scene.json b/config-examples/group_lighting_scene.json new file mode 100644 index 0000000..f8c7470 --- /dev/null +++ b/config-examples/group_lighting_scene.json @@ -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"]] + } +} diff --git a/config-examples/heating_relayx_floor.json b/config-examples/heating_relayx_floor.json new file mode 100644 index 0000000..eeebe27 --- /dev/null +++ b/config-examples/heating_relayx_floor.json @@ -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" + } + } + } +} \ No newline at end of file diff --git a/config-examples/de-ad-be-ef-fe-ef.config.json b/config-examples/heating_thermostat_and_water_leak.json similarity index 100% rename from config-examples/de-ad-be-ef-fe-ef.config.json rename to config-examples/heating_thermostat_and_water_leak.json diff --git a/config-examples/humidifier_control.json b/config-examples/humidifier_control.json new file mode 100644 index 0000000..35c0cfe --- /dev/null +++ b/config-examples/humidifier_control.json @@ -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] + } +} diff --git a/config-examples/led_spiled_neopixel.json b/config-examples/led_spiled_neopixel.json new file mode 100644 index 0000000..2c83d8b --- /dev/null +++ b/config-examples/led_spiled_neopixel.json @@ -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" } + } + } +} diff --git a/config-examples/lh22-test.json b/config-examples/lh22-test.json deleted file mode 100644 index 48374c9..0000000 --- a/config-examples/lh22-test.json +++ /dev/null @@ -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"} - } - } - } \ No newline at end of file diff --git a/config-examples/12-12-12-12-12-12.config.json b/config-examples/lighting_dmx_full_house.json similarity index 97% rename from config-examples/12-12-12-12-12-12.config.json rename to config-examples/lighting_dmx_full_house.json index 7177987..5aff5bf 100644 --- a/config-examples/12-12-12-12-12-12.config.json +++ b/config-examples/lighting_dmx_full_house.json @@ -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], diff --git a/config-examples/de-ad-be-ef-fe-ed.config.json b/config-examples/lighting_dmx_rgb_multizone.json similarity index 100% rename from config-examples/de-ad-be-ef-fe-ed.config.json rename to config-examples/lighting_dmx_rgb_multizone.json diff --git a/config-examples/modbus_ac_dimmer_legacy.json b/config-examples/modbus_ac_dimmer_legacy.json new file mode 100644 index 0000000..cb1f48c --- /dev/null +++ b/config-examples/modbus_ac_dimmer_legacy.json @@ -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]] + } +} diff --git a/config-examples/modbus_panel_lh22_test.json b/config-examples/modbus_panel_lh22_test.json new file mode 100644 index 0000000..b37f2c1 --- /dev/null +++ b/config-examples/modbus_panel_lh22_test.json @@ -0,0 +1,1002 @@ +{ + "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" + ] + ], + "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" + ] + ], + "water": [ + 6, + 36, + 1, + 1 + ] + }, + "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" + } + } + } +} \ No newline at end of file diff --git a/config-examples/multivent_ventilation.json b/config-examples/multivent_ventilation.json new file mode 100644 index 0000000..81f4feb --- /dev/null +++ b/config-examples/multivent_ventilation.json @@ -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 + } + } + ] + ] + } +} \ No newline at end of file diff --git a/config-examples/pid_heating_batteries.json b/config-examples/pid_heating_batteries.json new file mode 100644 index 0000000..0fd946c --- /dev/null +++ b/config-examples/pid_heating_batteries.json @@ -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 + ] + } +} \ No newline at end of file diff --git a/config-examples/relay_gpio_switch.json b/config-examples/relay_gpio_switch.json new file mode 100644 index 0000000..16f20f5 --- /dev/null +++ b/config-examples/relay_gpio_switch.json @@ -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" } + } + } +} diff --git a/config-examples/rgbw_led_strip.json b/config-examples/rgbw_led_strip.json new file mode 100644 index 0000000..2c5ab74 --- /dev/null +++ b/config-examples/rgbw_led_strip.json @@ -0,0 +1,7 @@ +{ + "mqtt": ["rgb-demo", "192.168.88.2"], + "items": { + "rgbw_strip": [1, 10], + "rgbw_strip_backup": [1, 20, 255, 0] + } +} diff --git a/config-examples/sensors_modbus_co2.json b/config-examples/sensors_modbus_co2.json new file mode 100644 index 0000000..d88ad7a --- /dev/null +++ b/config-examples/sensors_modbus_co2.json @@ -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 + ] + } +} \ No newline at end of file diff --git a/config-examples/sonoff_s26_humidity_controller.json b/config-examples/sonoff_s26_humidity_controller_example.json similarity index 100% rename from config-examples/sonoff_s26_humidity_controller.json rename to config-examples/sonoff_s26_humidity_controller_example.json diff --git a/config-examples/sprinkler_irrigation.json b/config-examples/sprinkler_irrigation.json new file mode 100644 index 0000000..b4e51fe --- /dev/null +++ b/config-examples/sprinkler_irrigation.json @@ -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" } + } +} diff --git a/config-examples/thermostat_onoff_relay.json b/config-examples/thermostat_onoff_relay.json new file mode 100644 index 0000000..bdacfd5 --- /dev/null +++ b/config-examples/thermostat_onoff_relay.json @@ -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" + } + } +} diff --git a/config-examples/c4-3e-1f-03-1b-1b.config.json b/config-examples/ventilation_fan_monitoring.json similarity index 100% rename from config-examples/c4-3e-1f-03-1b-1b.config.json rename to config-examples/ventilation_fan_monitoring.json diff --git a/documentation/README.md b/documentation/README.md index 5ac6815..9faa413 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -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, суффиксы, матрица) | diff --git a/documentation/core/channel_types_reference.md b/documentation/core/channel_types_reference.md index 63ed8cc..9dc93a3 100644 --- a/documentation/core/channel_types_reference.md +++ b/documentation/core/channel_types_reference.md @@ -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) - Увлажнитель diff --git a/documentation/core/configuration_examples.md b/documentation/core/configuration_examples.md index 4c2fe93..89184e7 100644 --- a/documentation/core/configuration_examples.md +++ b/documentation/core/configuration_examples.md @@ -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) ``` --- diff --git a/documentation/core/core_concepts.md b/documentation/core/core_concepts.md new file mode 100644 index 0000000..a0e6984 --- /dev/null +++ b/documentation/core/core_concepts.md @@ -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). diff --git a/documentation/core/light_hub_полное_инженерное_описание_json_конфигурации_v2.md b/documentation/core/light_hub_полное_инженерное_описание_json_конфигурации_v2.md index fcf817e..eb03491 100644 --- a/documentation/core/light_hub_полное_инженерное_описание_json_конфигурации_v2.md +++ b/documentation/core/light_hub_полное_инженерное_описание_json_конфигурации_v2.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) — Многозональная вентиляция diff --git a/documentation/core/modules_description.md b/documentation/core/modules_description.md index 171c2cd..db249a1 100644 --- a/documentation/core/modules_description.md +++ b/documentation/core/modules_description.md @@ -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) | --- diff --git a/documentation/core/modules_real_config.md b/documentation/core/modules_real_config.md index 9a825a0..0fc0ce0 100644 --- a/documentation/core/modules_real_config.md +++ b/documentation/core/modules_real_config.md @@ -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) --- diff --git a/documentation/core/technical_channel_types_table.md b/documentation/core/technical_channel_types_table.md index 908010f..0dcc354 100644 --- a/documentation/core/technical_channel_types_table.md +++ b/documentation/core/technical_channel_types_table.md @@ -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) — Увлажнитель diff --git a/documentation/integrations/z031_panel.md b/documentation/integrations/z031_panel.md index 8064028..672e4a3 100644 --- a/documentation/integrations/z031_panel.md +++ b/documentation/integrations/z031_panel.md @@ -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: `[адрес, diff --git a/documentation/modules/multivent_module_description.md b/documentation/modules/multivent_module_description.md index 05ab908..fe8fee3 100644 --- a/documentation/modules/multivent_module_description.md +++ b/documentation/modules/multivent_module_description.md @@ -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] } } ```