diff --git a/documentation/Sprinkler_module.md b/documentation/Sprinkler_module.md index 7e398c4..8f04f51 100644 --- a/documentation/Sprinkler_module.md +++ b/documentation/Sprinkler_module.md @@ -91,11 +91,24 @@ DREN\_OPERATE|таймаут 2000 сек |FAULT_DREN|выключить rDren - Для сброса счетчиков можно использовать как непосредственную установку значения параметра "val" для каждой зоны так и команду RESET, отправленную в нужную зону или в объект sprinkler через суффикс /cmd. -В последнем случае, контроллер итерационно сбросит счетчики в значение 0 для каждой зоны полива. -А также, отключит систему полива, чтобы программа не стартовала в момент сброса счетчиков (например, в полночь) - **Пример:** ```root/name/sprinkler/cmd -> RESET``` +В последнем случае, контроллер итерационно сбросит счетчики в значение 0 для каждой зоны полива. +Это инициирует старт программы полива, если система находится в состоянии ON + +Команда RESET не отработает если обьект полива находится в состоянии DISABLE или FREEZE + +Также, в этих режимах, в принципе, не отработает запуск полива какой-либо зоны (команды set/RESET), если для нее задано время/обьем полива. + +Если обьем полива не задан (set==0) - это например водяная розетка для мытья машины, то такая зона запустится даже в режиме DISABLE + +Если в процессе полива придет команда DISABLE (начался дождь) - полив прекратится, программа полива возобновится после ENABLE + + + + + + ## Управление @@ -110,7 +123,9 @@ DREN\_OPERATE|таймаут 2000 сек |FAULT_DREN|выключить rDren - ### Включение/выключение цикла полива: **Включить** ```root/name/sprinkler/cmd -> ON``` -Система начнет или продолжит цикл полива, переходя от зоны к зоне по мере завершения работы с каждой предыдущей зоной. После завершения работы со всеми зонами, sprinkler перейдет в состояние OFF +Система начнет или продолжит цикл полива, переходя от зоны к зоне по мере завершения работы с каждой предыдущей зоной. После завершения работы со всеми зонами, sprinkler НЕ перейдет в состояние OFF автоматически, но полив прекратится для тех зон, где показатель val достиг параметра set + +Если не будет ни одной активной зоны - насос обесточится. Перед включением полива, система убедится что бак наполнен или до-наполнит его до максимума из водопровода. @@ -162,6 +177,19 @@ root/name/sprinkler/val -> -1 //система перейдет в режим FR ``` +Так как команда FREEZE блокирует запуск каких либо насосов и открытие клапанов, это делает невозможным слив системы в процессе подготовки к зиме + +Когда требуется слить систему, необходимо отключить дренажный насос, перекрыть водопроводный кран + +Данный режим реализован при помощи команды DRY + +Дополнительно к перекрытию поступления воды в бак (заблокирован автомат пополнения бака из дренажного насоса и водопровода) данная команда включает помпу. + +Далее, требуется слить бак включением выбранных зон полива или через водяные розетки. +Только после осушения бака (насос выключится) - систему необходимо перевести в режим FREEZE +Перевод в этот редим сбрасывает режим DRY (а также, состояния ошибки автомата наполнения бака) + + ### Передача статусных значений @@ -225,16 +253,16 @@ sensor: state_topic: "edem/s_out/sprinkler/trees/val" - name: "Поливаем юг" - state_topic: "edem/s_out/sprinkler/south/$state" + state_topic: "root/s_out/sprinkler/south/$state" - name: "Поливаем север" - state_topic: "edem/s_out/sprinkler/nord/$state" + state_topic: "root/s_out/sprinkler/nord/$state" - name: "Поливаем капельно" - state_topic: "edem/s_out/sprinkler/trees/$state" + state_topic: "root/s_out/sprinkler/trees/$state" - name: "Полив розетка статус" - state_topic: "edem/s_out/sprinkler/outlets/$state" + state_topic: "root/s_out/sprinkler/outlets/$state" - name: "Полив блокировки" state_topic: "root/s_out/sprinkler/ctrl" diff --git a/lighthub/modules/out_sprinkler.cpp b/lighthub/modules/out_sprinkler.cpp index 1b25ad5..ffbf730 100644 --- a/lighthub/modules/out_sprinkler.cpp +++ b/lighthub/modules/out_sprinkler.cpp @@ -284,6 +284,10 @@ switch (state) { strcpy(val,"FULL"); break; + case SP_DRYING: + strcpy(val,"DRYING"); + break; + case SP_FAULT_VIN: strcpy(val,"FAULT_VIN"); fault = 1; @@ -347,6 +351,11 @@ int out_sprinkler::moveToState(sprinklerState nextState) dren(false); vin(false); break; + case SP_DRYING: + dren(false); + vin(false); + pump(true); + break; } //publishBooleanState("/$rDren", nextState == SP_DREN_ON || nextState == SP_DREN_OPERATE); @@ -624,66 +633,71 @@ int out_sprinkler::Poll(short cause) pump(false); return 0; } - + bool isActiveZone = false; if (item->getCmd() == CMD_ON && tankReady) { currentZone = findNextZone(); if (currentZone) - { - long setVal = getIntFromJson(currentZone, "set", 0); - long valVal = getIntFromJson(currentZone, "val", 0); + { + long setVal = getIntFromJson(currentZone, "set", 0); + long valVal = getIntFromJson(currentZone, "val", 0); + // if not active - activate + if (!getIntFromJson(currentZone, "@active", 0)) + { + turnOffAllZones(); + if (!item->getFlag(FLAG_DISABLED) || !setVal) + { + setZoneActive(currentZone, true); + short zonePin = getIntFromJson(currentZone, "pin", PINS_COUNT); + if (isValidControlPin(zonePin)) setOutput(zonePin, true); + setValToJson(gatesObj, "@flowTimer", (long)now); + isActiveZone = true; + } + } + else isActiveZone = true; - if (!getIntFromJson(currentZone, "@active", 0)) - { - turnOffAllZones(); - setZoneActive(currentZone, true); - short zonePin = getIntFromJson(currentZone, "pin", PINS_COUNT); - if (isValidControlPin(zonePin)) setOutput(zonePin, true); - setValToJson(gatesObj, "@flowTimer", (long)now); - } + if (isActiveZone) + { + if (abs(wCtrPin) < PINS_COUNT) + { + bool curr = readInPin(wCtrPin); + if (curr && !lastWctrlState) + { + updateZoneValue(currentZone, 1); + } + if (curr) lastVals |= LASTWCTRLSTATE; else lastVals &= ~LASTWCTRLSTATE; + setValToJson(gatesObj, "@lastVals", (long)lastVals); + } + else + { + uint32_t flowTimer = (uint32_t)getIntFromJson(gatesObj, "@flowTimer", now); + if (isTimeOver(flowTimer, now, 1000UL)) + { + updateZoneValue(currentZone, 1); + setValToJson(gatesObj, "@flowTimer", (long)now); + } + } + } - if (abs(wCtrPin) < PINS_COUNT) - { - bool curr = readInPin(wCtrPin); - if (curr && !lastWctrlState) - { - updateZoneValue(currentZone, 1); - } - if (curr) lastVals |= LASTWCTRLSTATE; else lastVals &= ~LASTWCTRLSTATE; - setValToJson(gatesObj, "@lastVals", (long)lastVals); - } - else - { - uint32_t flowTimer = (uint32_t)getIntFromJson(gatesObj, "@flowTimer", now); - if (isTimeOver(flowTimer, now, 1000UL)) - { - updateZoneValue(currentZone, 1); - setValToJson(gatesObj, "@flowTimer", (long)now); - } - } + if (setVal > 0 && (valVal >= setVal || item->getFlag(FLAG_DISABLED))) + { + short zonePin = getIntFromJson(currentZone, "pin", PINS_COUNT); + if (isValidControlPin(zonePin)) setOutput(zonePin, false); + setZoneActive(currentZone, false); + currentZone = findNextZone(); + } - - if (setVal > 0 && valVal >= setVal) - { - short zonePin = getIntFromJson(currentZone, "pin", PINS_COUNT); - if (isValidControlPin(zonePin)) setOutput(zonePin, false); - - setZoneActive(currentZone, false); - //////setValToJson(currentZone, "cmd", (long)CMD_OFF); - //item->SendStatusImmediate(itemCmd().Cmd(CMD_OFF).setSuffix(S_CMD), FLAG_COMMAND, currentZone->name); - currentZone = findNextZone(); - } - - if (currentZone) - { - needPump = true; - } + if (currentZone) + { + needPump = true; + } } } if (!needPump) { pump(false); + /* if (item->getCmd() == CMD_ON) { aJsonObject * resultZone = findNextZone(); @@ -693,6 +707,7 @@ int out_sprinkler::Poll(short cause) item->SendStatus(FLAG_COMMAND); } } + */ } else { @@ -764,6 +779,7 @@ int out_sprinkler::Ctrl(itemCmd cmd, char* subItem, bool toExecute, bool authori return 1; case CMD_RESET: + if (item->getFlag(FLAG_FREEZED || FLAG_DISABLED)) return -1; setValToJson(zone, "val", (long)0); if (sendStatus) { @@ -788,11 +804,18 @@ int out_sprinkler::Ctrl(itemCmd cmd, char* subItem, bool toExecute, bool authori case CMD_OFF: turnOffAllZones(); pump(false); - //dren(false); return 1; + case CMD_DRY: + setValToJson(gatesObj, "@state", (long)SP_DRYING); + moveToState(SP_DRYING); + notifyState(SP_DRYING); + return 1; + case CMD_RESET: { + if (item->getFlag(FLAG_FREEZED || FLAG_DISABLED)) return -1; + aJsonObject * zone = gatesObj->child; while (zone) { @@ -806,9 +829,10 @@ int out_sprinkler::Ctrl(itemCmd cmd, char* subItem, bool toExecute, bool authori } zone = zone->next; } - turnOffAllZones(); - pump(false); - item->Off(); + + // turnOffAllZones(); + // pump(false); + // item->Off(); } return 1; diff --git a/lighthub/modules/out_sprinkler.h b/lighthub/modules/out_sprinkler.h index dbd2acf..de4bfe6 100644 --- a/lighthub/modules/out_sprinkler.h +++ b/lighthub/modules/out_sprinkler.h @@ -28,6 +28,7 @@ enum sprinklerState { SP_DREN_EMPTY = 4, SP_VIN = 5, SP_FULL = 6, + SP_DRYING = 7, SP_FAULT_VIN = -1, SP_FAULT_DREN = -2 };