# LightHub: Модуль многоканальной системы полива (out\_sprinkler) Данный модуль реализует многозональную систему полива ## Система состоит из следующих компонент: * Накопительный водяной бак. Снабжен двумя поплавками. Максимум воды и минимум воды. Заведены на входы wMax и wMin * Насос полива высокого давления. Запитан из бака. Включается реле, подключенным к выходу rPump. Датчик тока для контроля того, что насос включен, заведен на вход fbPump * Набор клапанов зон полива. Подключены через оптореле к выходам, заданным в параметре pin соответствующей зоны полива. * Клапан налива из водопровода. Подключен через оптореле к выходу vIn * Насос дренажного колодца. Приоритетный источник для наполнения бака полива. Когда система полива находится в ждущем или активном режиме, бак пытается максимально наполнится из дренажного колодца. Насос дренажа имеет поплавковый выключатель, отключающий насос при осушении дренажного колодца. Насос включается реле, которое подключено к выходу rDren. Для контроля того, что насос включен и момента осушения колодца, используется датчик тока, который подключен в входу fbDren * Опциональный водосчетчик. Контакты подключены к входу wCtr ## Система налива воды реализована при помощи конечного автомата со следующими состояниями: * SP\_UNKNOWN * SP\_OFF * SP\_DREN\_ON - дренажный насос включен * SP\_DREN\_OPERATE - дренажный насос работает * SP\_DREN\_EMPTY - дренажный насос выключился встроенным поплавком - колодец пуст * SP\_VIN - включено наполнение из водопровода * SP\_FULL - бак наполнен * SP\_DRYING - режим осушения системы: налив перекрыт, работает насос полива для слива бака (SP\_DRYING=7, out\_sprinkler.h:34) Строковые значения, публикуемые в топик `$state` (out\_sprinkler.cpp:263-308): `OFF`, `DREN_ON`, `DREN_OPERATE`, `DREN_EMPTY`, `VIN`, `FULL`, `DRYING`, `FAULT_VIN`, `FAULT_DREN`, `UNKNOWN`. граф переходов конечного автомата системы налива воды Состояние SP\_* | Условие перехода | перейти в состояние | выполнить при переходе | |------|--------|-------|---------| INIT | true | OFF | выключить клапана и насосы | OFF | vMax && !FREEZE | FULL | выключить vIN, rDren| OFF | ! vMax && !FREEZE | DREN\_ON|включить rDren| DREN\_ON|fbDren (насос дренажа реально работает)|DREN\_OPERATE| DREN\_ON|таймаут 10 сек|DREN\_EMPTY| насос так и не заработал - видимо в колодце пусто DREN\_EMPTY|включен цикл полива и бак не полон|VIN|включить клапан vIN для набора бака из водопровода| DREN\_OPERATE| ! fbDren (насос дренажа более не работает)|DREN\_EMPTY|| VIN|fbDren|DREN\_OPERATE|вылючить клапан vIN для набора бака из водопровода - заработал дренажный насос| VIN, DREN\_OPERATE|vMax|FULL | выключить vIN, rDren - бак полон| VIN|таймаут 1200 сек | FAULT\_VIN| выключить vIN - бак так и не наполнился| DREN\_OPERATE|fbPump (качает основной насос)|DREN\_OPERATE|сброс таймера (@timer = now) — не считать ошибку, пока качает основной насос (L562)| DREN\_OPERATE|таймаут 4000 сек |FAULT\_DREN|выключить rDren - не смотря на продолжительную работу насоса бак не наполнен| FULL|! wMax|DREN\_ON|дренаж перезапускается при опустошении бака (L609-617)| FAULT\_VIN, FAULT\_DREN|wMax|FULL|сброс ошибки при наполнении бака (L619-635)| ## Конфигурирование: ``` "items": { "sprinkler":[23, { "":{ "vIn":3, "wMax":44, "wMin":46, "rDren":23, "fbDren":63, "rPump":24, "fbPump":62, "wCtr":49 }, "nord":{"pin":6,"set":60,"cmd":1}, "south":{"pin":7,"set":100,"cmd":1}, "trees":{"pin":10,"set":60,"cmd":2}, "outlets:{} }] } ``` В корневом (`""`) объекте, помимо выходов/входов, можно задать EXEC-объект `onFault` — при срабатывании ошибки автомата налива вместо публикации в `$fault` исполняется он с кодом ошибки аргументом (L260-262, L311-314). ## Алгоритм работы в настройки зон полива задаем интенсивность для каждой зоны. Это можно сделать как в конфиге так динамически, (стандартными механизмами управления по MQTT, HTTP, CAN) Рассмотрим на примере MQTT: **топик** ```root/name/sprinkler/garden/set -> 60``` Задаем обьем полива 60 отсчетов счетчика воды (если счетчик не сконфигурирован - 60 секунд) Контроллер должен передать это значение в выходной топик ```root/name/s_out/sprinkrer/garden/set``` и оно будет восстановлено при перезагрузке контроллера отработанный обьем воды или время будет сохраняться в параметре "val" каждой зоны (параметр будет автоматически увеличиваться при работе зоны, передаваться в соответствующий зоне топик для мониторинга и восстановления в случае перезагрузки контроллера) **Пример топика:** ```root/s_out/sprinkler/garden/val``` Когда данный параметр достигнет значения (или времени), заданного в параметре "set" контроллер завершит полив данной зоны и перейдет к следующей. Важно: если set=0 (по умолчанию) то время работы зоны не лимитируется. Если такая зона включена - система полива не будет отключаться после окончания полива прочих зон и насос не будет обесточиваться. Это удобно, если в системе полива есть водяная розетка для подключения поливочного шланга, которая всегда должна находиться под давлением. Такую зону конфигурируйте последней в списке. Для сброса счетчиков можно использовать как непосредственную установку значения параметра "val" для каждой зоны так и команду RESET, отправленную в нужную зону или в объект sprinkler через суффикс /cmd. **Пример:** ```root/name/sprinkler/cmd -> RESET``` В последнем случае, контроллер итерационно сбросит счетчики в значение 0 для каждой зоны полива. Это инициирует старт программы полива, если система находится в состоянии ON Команда RESET не отработает если обьект полива находится в состоянии DISABLE или FREEZE Также, в этих режимах, в принципе, не отработает запуск полива какой-либо зоны (команды set/RESET), если для нее задано время/обьем полива. Если обьем полива не задан (set==0) - это например водяная розетка для мытья машины, то такая зона запустится даже в режиме DISABLE Если в процессе полива придет команда DISABLE (начался дождь) - полив прекратится, программа полива возобновится после ENABLE ## Управление ### Включение/выключение полива конкретной зоны: **Включить** ```root/name/sprinkler/garden/cmd -> ON``` **Выключить** ```root/name/sprinkler/garden/cmd -> OFF``` ### Включение/выключение цикла полива: **Включить** ```root/name/sprinkler/cmd -> ON``` Система начнет или продолжит цикл полива, переходя от зоны к зоне по мере завершения работы с каждой предыдущей зоной. После завершения работы со всеми зонами, sprinkler НЕ перейдет в состояние OFF автоматически, но полив прекратится для тех зон, где показатель val достиг параметра set Если не будет ни одной активной зоны - насос обесточится. Перед включением полива, система убедится что бак готов: полив стартует при `state==FULL || wMax || wMin || fbPump` (L638) — то есть и при минимальном уровне / работающей помпе, иначе система до-наполнит бак до максимума из водопровода. **Выключить** ```root/name/sprinkler/cmd -> OFF``` Система немедленно остановит текущий цикл полива (закроет клапаны зон, выключит насос полива) Аналогично, будут работать команды XON и XOFF, с одним исключением, что команда XON может быть запрещена и игнорироваться если активирован режим DISABLE. Это базовая функция контроллера и не относится к функционалу данного модуля. Но может быть использована, например, для запрета полива на определенное время после выпадения осадков **Пример** ``` root/name/sprinkler/ctrl -> DISABLE root/name/sprinkler/cmd -> XON //Будет проигнорировано root/name/sprinkler/ctrl -> ENABLE root/name/sprinkler/cmd -> XON //А вот теперь сработает ``` Даже в выключенном состоянии (OFF) , система полива работает в дежурном режиме, поддерживая максимальный уровень воды в баке за счет немедленной перекачки из дренажного колодца При попытке включения системы после завершения дневного задания по поливу всех зон (параметр val для всех зон достиг параметра set) авто-перехода в OFF не происходит: item остаётся в состоянии ON и просто простаивает, не запуская активного полива (автоматическое выключение закомментировано, L712-722) — что согласуется с описанием выше: команда ON не переводит систему в OFF автоматически. ### Полная блокировка системы полива (в зимнее время) Ддя перевода канала полива в полностью заблокированное состояние и обратно импользуется системная команда FREEZE/UNFREEZE соответственно В режиме FREEZE полностью заблокирована обработка всех команд, кроме UNFREEZE, заблокирован автомат пополнения бака из дренажного насоса и выключены насосы и все клапана. Если одновременно выставлены флаги FREEZE и DISABLE, то в /ctrl публикуется FREEZE — приоритет над DISABLE (item.cpp:2174-2176). Рекомендуется задать флаг FREEZE в конфигурации канала (см документ ...) , чтобы избежать разблокировки при утере значений топика /clrl и перезагрузки системы Также, на вход /val обЪекта sprinkler можно подать значение уличной температуры. И если значения будут ниже нуля, система автоматически перейдет в режим FREEZE **Пример** ``` root/name/sprinkler/ctrl -> FREEZE root/name/sprinkrer/cmd -> ON //Будет проигнорировано root/name/sprinkler/ctrl -> UNFREEZE root/name/sprinkrer/cmd -> ON //А вот теперь сработает root/name/sprinkler/val -> -1 //система перейдет в режим FREEZE ``` Так как команда FREEZE блокирует запуск каких либо насосов и открытие клапанов, это делает невозможным слив системы в процессе подготовки к зиме Когда требуется слить систему, необходимо отключить дренажный насос, перекрыть водопроводный кран Данный режим реализован при помощи команды DRY Дополнительно к перекрытию поступления воды в бак (заблокирован автомат пополнения бака из дренажного насоса и водопровода) данная команда включает помпу. - DRY переопределяет ON: если система находится в режиме `@state==SP_DRYING` и приходит команда ON, она исполняется как CMD\_DRY, а не ON (out\_sprinkler.cpp:837-841). - Режим DRY персистентен: `@state=SP_DRYING` хранится в конфиге и переживает перезагрузку контроллера; реле восстанавливаются из `@lastVals`, после рестарта в топик публикуется `DRYING`. Далее, требуется слить бак включением выбранных зон полива или через водяные розетки. Только после осушения бака (насос выключится) - систему необходимо перевести в режим FREEZE Перевод в этот редим сбрасывает режим DRY (а также, состояния ошибки автомата наполнения бака) ### Передача статусных значений При старте (первый Poll) контроллер принудительно публикует все ключевые статусы: `$wMax`/`$wMin`/`$fbDren`/`$fbPump`/`$rPump`/`$rDren`/`$rVIN` + `$state`/`$fault` (L474-487). Повторно `$state`/`$fault` публикуются при командах ON/OFF (L842, L848). **Ошибки (onFault / $fault):** при каждом переходе состояния публикуется код ошибки в топик `$fault`: 0 — без ошибки, 1 — FAULT\_VIN, 2 — FAULT\_DREN (L311-315). Вместо публикации в `$fault` можно задать EXEC-объект `onFault` в корневом (`""`) объекте — в этом случае при срабатывании ошибки исполняется он с кодом ошибки аргументом (L260-262, L311-314). **Примеры выдачи в топики:** ``` root/s_out/sprinkler/$fbPump - ON/OFF признак того, что включен основной насос (от датчика тока) root/s_out/sprinkler/$fbDren - ON/OFF признак того, что включен дренажный насос (от датчика тока) root/s_out/sprinkler/$state - состояние конечного автомата Системы налива воды root/s_out/sprinkler/$fault - код ошибки: 0 / 1=FAULT_VIN / 2=FAULT_DREN root/s_out/sprinkler/$wMax - ON/OFF достигнут максимум воды в баке (от поплавкового датчика) root/s_out/sprinkler/$wMin - ON/OFF достигнут минимум воды в баке (от поплавкового датчика) root/s_out/sprinkler/$rDren - ON/OFF включено реле дренажного насоса root/s_out/sprinkler/$rPump - ON/OFF включено реле основного насоса root/s_out/sprinkler/set - значение счетчика воды (восстанавливается при перезагрузке из данного топика) root/s_out/sprinkler/$rVIN - ON/OFF - признак открытия клапана налива бака из водопровода root/s_out/sprinkler/garden/set - требуемый обьем (или время) полива зоны root/s_out/sprinkler/garden/cmd - ON или OFF - признак включения полива зоны root/s_out/sprinkler/garden/$state - ON или OFF - признак того что зона поливается в настоящее время root/s_out/sprinkler/garden/val - текущее время или обьем полива данной зоны ``` ### Пример конфигурации Home Assistant ``` sensor: - name: "Полив бак Макс" state_topic: "root/s_out/sprinkler/$wMax" - name: "Полив бак Мin" state_topic: "root/s_out/sprinkler/$wMin" - name: "Полив водопровод" state_topic: "root/s_out/sprinkler/$rVIN" - name: "Полив дренаж вкл" state_topic: "root/s_out/sprinkler/$rDren" - name: "Полив дренаж качает" state_topic: "root/s_out/sprinkler/$fbDren" - name: "Полив насос вкл" state_topic: "root/s_out/sprinkler/$rPump" - name: "Полив насос качает" state_topic: "root/s_out/sprinkler/$fbPump" - name: "Полив состояние" state_topic: "root/s_out/sprinkler/$state" - name: "Полив ошибка" state_topic: "root/s_out/sprinkler/$fault" - name: "Полив юг выполнено" state_topic: "root/s_out/sprinkler/south/val" - name: "Полив север выполнено" state_topic: "root/s_out/sprinkler/nord/val" - name: "Полив капельный выполнено" state_topic: "house/s_out/sprinkler/trees/val" - name: "Поливаем юг" state_topic: "root/s_out/sprinkler/south/$state" - name: "Поливаем север" state_topic: "root/s_out/sprinkler/nord/$state" - name: "Поливаем капельно" state_topic: "root/s_out/sprinkler/trees/$state" - name: "Полив розетка статус" state_topic: "root/s_out/sprinkler/outlets/$state" - name: "Полив блокировки" state_topic: "root/s_out/sprinkler/ctrl" switch: - name: "Полив" state_topic: "root/s_out/sprinkler/cmd" command_topic: "root/air/sprinkler/cmd" availability_topic: "root/air/$state" payload_available: "ready" payload_not_available: "disconnected" - name: "Полив север" state_topic: "root/s_out/sprinkler/nord/cmd" command_topic: "root/air/sprinkler/nord/cmd" availability_topic: "root/air/$state" payload_available: "ready" payload_not_available: "disconnected" - name: "Полив юг" state_topic: "root/s_out/sprinkler/south/cmd" command_topic: "root/air/sprinkler/south/cmd" availability_topic: "root/air/$state" payload_available: "ready" payload_not_available: "disconnected" - name: "Полив капельный" state_topic: "root/s_out/sprinkler/trees/cmd" command_topic: "root/air/sprinkler/trees/cmd" availability_topic: "root/air/$state" payload_available: "ready" payload_not_available: "disconnected" - name: "Полив розетки" state_topic: "root/s_out/sprinkler/outlets/cmd" command_topic: "root/air/sprinkler/outlets/cmd" availability_topic: "root/air/$state" payload_available: "ready" payload_not_available: "disconnected" button: - name: "Полив сброс" command_topic: "root/air/sprinkler/cmd" payload_press: "RESET" - name: "Полив блокировка" command_topic: "root/air/sprinkler/cmd" payload_press: "FREEZE" - name: "Полив разблокировка" command_topic: "root/air/sprinkler/cmd" payload_press: "UNFREEZE" - name: "Полив разрешить" command_topic: "root/air/sprinkler/cmd" payload_press: "ENABLE" - name: "Полив запретить" command_topic: "root/air/sprinkler/cmd" payload_press: "DISABLE" - name: "Полив осушение бака" command_topic: "root/air/sprinkler/cmd" payload_press: "DRY" #Такую проверку можно добавить везде, при ее наличии обьекты станут недоступными если контроллер оффлайн availability_topic: "root/air/$state" payload_available: "ready" payload_not_available: "disconnected" number: - name: "Полив юг" state_topic: "root/s_out/sprinkler/south/set" command_topic: "root/air/sprinkler/south/set" min: 0 max: 6000 - name: "Полив север" state_topic: "root/s_out/sprinkler/nord/set" command_topic: "root/air/sprinkler/nord/set" min: 0 max: 6000 - name: "Полив капельный" state_topic: "root/s_out/sprinkler/trees/set" command_topic: "root/air/sprinkler/trees/set" min: 0 max: 6000 ```