mirror of
https://github.com/anklimov/lighthub
synced 2026-06-13 19:36:23 +03:00
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user