mirror of
https://github.com/anklimov/lighthub
synced 2026-05-05 21:45:48 +00:00
Multi AC/vent - released. Sprinkler - alpha for testing
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -43,3 +43,4 @@
|
||||
-D ROTARYENCODER
|
||||
-D CANDRV
|
||||
-D THERMO_OVERHEAT_CELSIUS=44.
|
||||
-D SPRINKLER_ENABLE
|
||||
@@ -28,7 +28,7 @@ int abstractCh::publishTopic(const char* topic, float value, const char* subtopi
|
||||
return publishTopic(topic, valstr,subtopic);
|
||||
};
|
||||
|
||||
int abstractCh::publishTopic(const char* topic, const char * value, const char* subtopic)
|
||||
int abstractCh::publishTopic(const char* topic, const char * value, const char* subtopic, const char* suffix)
|
||||
{
|
||||
#if not defined (NOIP)
|
||||
char addrstr[MQTT_TOPIC_LENGTH];
|
||||
@@ -38,6 +38,10 @@ int abstractCh::publishTopic(const char* topic, const char * value, const char*
|
||||
strncpy(addrstr,topic,sizeof(addrstr));
|
||||
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,topic);
|
||||
strncat(addrstr,subtopic,sizeof(addrstr)-1);
|
||||
if (suffix)
|
||||
{
|
||||
strncat(addrstr,suffix,sizeof(addrstr)-1);
|
||||
}
|
||||
if (mqttClient.connected() && lanStatus == OPERATION && !ethernetIdleCount)
|
||||
{
|
||||
mqttClient.publish(addrstr, value, true);
|
||||
|
||||
@@ -21,6 +21,6 @@ public:
|
||||
protected:
|
||||
int publishTopic(const char* topic, long value, const char* subtopic = NULL);
|
||||
int publishTopic(const char* topic, float value, const char* subtopic = NULL );
|
||||
int publishTopic(const char* topic, const char * value, const char* subtopic = NULL);
|
||||
int publishTopic(const char* topic, const char * value, const char* subtopic = NULL, const char* suffix = NULL);
|
||||
|
||||
};
|
||||
|
||||
@@ -2066,6 +2066,9 @@ int Item::SendStatus(long sendFlags, char * subItem) {
|
||||
case S_FAN:
|
||||
strncat_P(addrstr, suffix_P[S_FAN], sizeof(addrstr)-1);
|
||||
break;
|
||||
case S_VAL:
|
||||
strncat_P(addrstr, suffix_P[S_VAL], sizeof(addrstr)-1);
|
||||
break;
|
||||
default:
|
||||
strncat_P(addrstr, suffix_P[S_SET], sizeof(addrstr)-1);
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ int out_Multivent::isActive()
|
||||
if (i->name && *i->name)
|
||||
{
|
||||
int preHaltcmd = getIntFromJson(i,"@preHaltcmd",CMD_OFF);
|
||||
if (preHaltcmd) //setPassiveMode(i, false);
|
||||
if (preHaltcmd && (preHaltcmd != CMD_OFF)) //setPassiveMode(i, false);
|
||||
fanCtrl(itemCmd().Cmd(preHaltcmd).setSuffix(S_CMD),i->name,true);
|
||||
setValToJson(i,"@preHaltcmd",0); //reset preHaltcmd in any case
|
||||
}
|
||||
@@ -711,7 +711,7 @@ while (i)
|
||||
case S_CMD:
|
||||
if (cmd.isCommand())
|
||||
{
|
||||
|
||||
bool checkMinFanLevel = false;
|
||||
if (cmd.getCmd() == CMD_ON)
|
||||
{
|
||||
if (getFlag(i,FLAG_FREEZED)) {debugSerial<<F("VENT: zone frozen")<<endl; return -2;}
|
||||
@@ -729,6 +729,7 @@ while (i)
|
||||
switch (cmd.getCmd())
|
||||
{
|
||||
case CMD_ON:
|
||||
checkMinFanLevel = true;
|
||||
break;
|
||||
case CMD_OFF:
|
||||
if (getFlag(i,FLAG_FREEZED)) {debugSerial<<F("VENT: zone frozen")<<endl; return -2;}
|
||||
@@ -773,6 +774,7 @@ while (i)
|
||||
sendFlags |= FLAG_COMMAND;
|
||||
cmdObj->valueint = cmd.getCmd();
|
||||
setPassiveMode(i,false);
|
||||
checkMinFanLevel = true;
|
||||
break;
|
||||
|
||||
case CMD_HEAT:
|
||||
@@ -783,6 +785,7 @@ while (i)
|
||||
sendFlags |= FLAG_COMMAND;
|
||||
cmdObj->valueint = cmd.getCmd();
|
||||
setPassiveMode(i,false);
|
||||
checkMinFanLevel = true;
|
||||
break;
|
||||
|
||||
case CMD_FAN:
|
||||
@@ -795,10 +798,11 @@ while (i)
|
||||
sendFlags |= FLAG_COMMAND;
|
||||
cmdObj->valueint = cmd.getCmd();
|
||||
setPassiveMode(i,false);
|
||||
checkMinFanLevel = true;
|
||||
break;
|
||||
//todo - halt-rest-xon-xoff
|
||||
}
|
||||
if (isNotRetainingStatus() && (cmdObj->valueint == CMD_ON) && (fanObj->valueint<20))
|
||||
if (isNotRetainingStatus() && checkMinFanLevel && (fanObj->valueint<20))
|
||||
{
|
||||
fanObj->valueint=30;
|
||||
cmd.Percents255(30);
|
||||
@@ -961,7 +965,7 @@ bool out_Multivent::pidEnabled(aJsonObject* pidObj)
|
||||
if (!(acCmd == CMD_OFF && lastFan == 0))
|
||||
{
|
||||
debugSerial<<"VENT: AC MODE changed manually from "<<lastCmd<<" to "<<acCmd<<endl;
|
||||
//TODO!
|
||||
|
||||
switch (acCmd)
|
||||
{
|
||||
case CMD_OFF:
|
||||
@@ -971,6 +975,12 @@ bool out_Multivent::pidEnabled(aJsonObject* pidObj)
|
||||
restoreAllzones();
|
||||
break;
|
||||
}
|
||||
|
||||
aJsonObject * execObj = aJson.getObjectItem(acObj, "onextcmd");
|
||||
if (execObj)
|
||||
{
|
||||
executeCommand(execObj,-1,itemCmd().Cmd(acCmd).setSuffix(S_CMD).setArgType(0).doReverseMapping(aJson.getObjectItem(execObj, "map")));
|
||||
}
|
||||
}
|
||||
setValToJson(acObj,"@lastCmd",acCmd);
|
||||
setValToJson(acObj,"@lastFan",-1);
|
||||
@@ -1004,6 +1014,11 @@ bool out_Multivent::pidEnabled(aJsonObject* pidObj)
|
||||
|
||||
if (lastSet && (acSet != lastSet)) {
|
||||
debugSerial<<"VENT: AC SET changed manually from "<<lastSet<<" to "<<acSet<<endl;
|
||||
aJsonObject * execObj = aJson.getObjectItem(acObj, "onextcmd");
|
||||
if (execObj)
|
||||
{
|
||||
executeCommand(execObj,-1,itemCmd().Int(acSet).setSuffix(S_SET).doReverseMapping(aJson.getObjectItem(execObj, "map")));
|
||||
}
|
||||
setValToJson(acObj,"@lastSet",acSet);
|
||||
return;}
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
bool out_sprinkler::getConfig()
|
||||
{
|
||||
gatesObj = NULL;
|
||||
vinPin = drenPin = pumpPin = -1;
|
||||
wMaxPin = wMinPin = fbDrenPin = fbPumpPin = wCtrPin = -1;
|
||||
vinPin = drenPin = pumpPin = PINS_COUNT;
|
||||
wMaxPin = wMinPin = fbDrenPin = fbPumpPin = wCtrPin = PINS_COUNT;
|
||||
|
||||
if (!item || !item->itemArg) return false;
|
||||
|
||||
@@ -33,21 +33,21 @@ bool out_sprinkler::getConfig()
|
||||
aJsonObject * rootCfg = aJson.getObjectItem(gatesObj, "");
|
||||
if (!rootCfg) rootCfg = gatesObj;
|
||||
|
||||
vinPin = getIntFromJson(rootCfg, "vIn", -1);
|
||||
drenPin = getIntFromJson(rootCfg, "rDren", -1);
|
||||
pumpPin = getIntFromJson(rootCfg, "rPump", -1);
|
||||
wMaxPin = getIntFromJson(rootCfg, "wMax", -1);
|
||||
wMinPin = getIntFromJson(rootCfg, "wMin", -1);
|
||||
fbDrenPin = getIntFromJson(rootCfg, "fbDren", -1);
|
||||
fbPumpPin = getIntFromJson(rootCfg, "fbPump", -1);
|
||||
wCtrPin = getIntFromJson(rootCfg, "wCtr", -1);
|
||||
vinPin = getIntFromJson(rootCfg, "vIn", PINS_COUNT);
|
||||
drenPin = getIntFromJson(rootCfg, "rDren", PINS_COUNT);
|
||||
pumpPin = getIntFromJson(rootCfg, "rPump", PINS_COUNT);
|
||||
wMaxPin = getIntFromJson(rootCfg, "wMax", PINS_COUNT);
|
||||
wMinPin = getIntFromJson(rootCfg, "wMin", PINS_COUNT);
|
||||
fbDrenPin = getIntFromJson(rootCfg, "fbDren", PINS_COUNT);
|
||||
fbPumpPin = getIntFromJson(rootCfg, "fbPump", PINS_COUNT);
|
||||
wCtrPin = getIntFromJson(rootCfg, "wCtr", PINS_COUNT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isValidControlPin(short pin)
|
||||
{
|
||||
return (pin >= 0 && pin < PINS_COUNT && !isProtectedPin(pin));
|
||||
return (abs(pin) < PINS_COUNT && !isProtectedPin(abs(pin)));
|
||||
}
|
||||
|
||||
void out_sprinkler::publishBooleanStateIfChanged(const char * subItem, bool state, uint32_t flag, uint32_t & lastState)
|
||||
@@ -59,8 +59,7 @@ void out_sprinkler::publishBooleanStateIfChanged(const char * subItem, bool stat
|
||||
|
||||
void out_sprinkler::setOutput(short pin, bool value)
|
||||
{
|
||||
if (!isValidControlPin(pin)) return;
|
||||
digitalWrite(pin, value ? HIGH : LOW);
|
||||
writeOutPin(pin, value ? HIGH : LOW);
|
||||
}
|
||||
|
||||
int out_sprinkler::Setup()
|
||||
@@ -73,17 +72,19 @@ int out_sprinkler::Setup()
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isValidControlPin(vinPin)) { pinMode(vinPin, OUTPUT); digitalWrite(vinPin, LOW); }
|
||||
if (isValidControlPin(drenPin)) { pinMode(drenPin, OUTPUT); digitalWrite(drenPin, LOW); }
|
||||
if (isValidControlPin(pumpPin)) { pinMode(pumpPin, OUTPUT); digitalWrite(pumpPin, LOW); }
|
||||
if (isValidControlPin(vinPin)) { pinMode(vinPin, OUTPUT); writeOutPin(vinPin, LOW); }
|
||||
if (isValidControlPin(drenPin)) { pinMode(drenPin, OUTPUT); writeOutPin(drenPin, LOW); }
|
||||
if (isValidControlPin(pumpPin)) { pinMode(pumpPin, OUTPUT); writeOutPin(pumpPin, LOW); }
|
||||
|
||||
debugSerial << F("SPRINKLER: ")<<"vIN=" << vinPin << " dren=" << drenPin << " pump=" << pumpPin << endl;
|
||||
|
||||
aJsonObject * zone = gatesObj->child;
|
||||
while (zone)
|
||||
{
|
||||
if (zone->name && *zone->name && zone->type == aJson_Object)
|
||||
{
|
||||
short pin = getIntFromJson(zone, "pin", -1);
|
||||
if (isValidControlPin(pin)) { pinMode(pin, OUTPUT); digitalWrite(pin, LOW); }
|
||||
short pin = getIntFromJson(zone, "pin", PINS_COUNT);
|
||||
if (isValidControlPin(pin)) { pinMode(pin, OUTPUT); writeOutPin(pin, LOW); }
|
||||
getCreateObject(zone, "cmd", (long)CMD_OFF);
|
||||
getCreateObject(zone, "val", (long)0);
|
||||
getCreateObject(zone, "set", (long)0);
|
||||
@@ -96,28 +97,29 @@ int out_sprinkler::Setup()
|
||||
getCreateObject(gatesObj, "@timer", (long)0);
|
||||
getCreateObject(gatesObj, "@flowTimer", (long)0);
|
||||
|
||||
debugSerial << F("SPRINKLER: ") << " wMax=" << wMaxPin << " wMin=" << wMinPin << " fbDren=" << fbDrenPin << " fbPump=" << fbPumpPin << " wCtr=" << wCtrPin << endl;
|
||||
uint16_t lastVals = 0;
|
||||
if (wCtrPin >= 0 && wCtrPin < PINS_COUNT)
|
||||
if (wCtrPin != PINS_COUNT)
|
||||
{
|
||||
pinMode(wCtrPin, INPUT);
|
||||
lastVals |= (getPinVal(wCtrPin) ? LASTWCTRLSTATE : 0);
|
||||
lastVals |= (getPinVal(wCtrPin) ? LASTWCTRLSTATE_ALL : 0);
|
||||
setupInPin(wCtrPin);
|
||||
lastVals |= (readInPin(wCtrPin) ? LASTWCTRLSTATE : 0);
|
||||
lastVals |= (readInPin(wCtrPin) ? LASTWCTRLSTATE_ALL : 0);
|
||||
}
|
||||
if (wMaxPin >= 0 && wMaxPin < PINS_COUNT) {
|
||||
pinMode(wMaxPin, INPUT);
|
||||
lastVals |= (publishBooleanState("$wMax", getPinVal(wMaxPin)) ? LASTWMAXSTATE : 0);
|
||||
if (wMaxPin != PINS_COUNT) {
|
||||
setupInPin(wMaxPin);
|
||||
lastVals |= (publishBooleanState("/$wMax", readInPin(wMaxPin)) ? LASTWMAXSTATE : 0);
|
||||
}
|
||||
if (wMinPin >= 0 && wMinPin < PINS_COUNT) {
|
||||
pinMode(wMinPin, INPUT);
|
||||
lastVals |= (publishBooleanState("$wMin", getPinVal(wMinPin)) ? LASTWMINSTATE : 0);
|
||||
if (wMinPin != PINS_COUNT) {
|
||||
setupInPin(wMinPin);
|
||||
lastVals |= (publishBooleanState("/$wMin", readInPin(wMinPin)) ? LASTWMINSTATE : 0);
|
||||
}
|
||||
if (fbDrenPin >= 0 && fbDrenPin < PINS_COUNT) {
|
||||
pinMode(fbDrenPin, INPUT);
|
||||
lastVals |= (publishBooleanState("$fbDren", getPinVal(fbDrenPin)) ? LASTFBDRENSTATE : 0);
|
||||
if (fbDrenPin != PINS_COUNT) {
|
||||
setupInPin(fbDrenPin);
|
||||
lastVals |= (publishBooleanState("/$fbDren", readInPin(fbDrenPin)) ? LASTFBDRENSTATE : 0);
|
||||
}
|
||||
if (fbPumpPin >= 0 && fbPumpPin < PINS_COUNT) {
|
||||
pinMode(fbPumpPin, INPUT);
|
||||
lastVals |= (publishBooleanState("$fbPump", getPinVal(fbPumpPin)) ? LASTFBPUMPSTATE : 0);
|
||||
if (fbPumpPin != PINS_COUNT) {
|
||||
setupInPin(fbPumpPin);
|
||||
lastVals |= (publishBooleanState("/$fbPump", readInPin(fbPumpPin)) ? LASTFBPUMPSTATE : 0);
|
||||
}
|
||||
|
||||
setValToJson(gatesObj, "@lastVals", (long)lastVals);
|
||||
@@ -133,39 +135,18 @@ int out_sprinkler::Stop()
|
||||
debugSerial << F("SPRINKLER: stop") << endl;
|
||||
turnOffAllZones();
|
||||
pump(false);
|
||||
dren(false);
|
||||
setOutput(vinPin, false);
|
||||
setOutput(drenPin, false);
|
||||
setOutput(pumpPin, false);
|
||||
setStatus(CST_UNKNOWN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
int out_sprinkler::Status()
|
||||
{
|
||||
if (!item || !gatesObj) return 0;
|
||||
|
||||
bool wMax = (wMaxPin >= 0) ? getPinVal(wMaxPin) : false;
|
||||
bool wMin = (wMinPin >= 0) ? getPinVal(wMinPin) : false;
|
||||
bool fbDren = (fbDrenPin >= 0) ? getPinVal(fbDrenPin) : false;
|
||||
bool fbPump = (fbPumpPin >= 0) ? getPinVal(fbPumpPin) : false;
|
||||
|
||||
publishBooleanStateIfChanged("$wMax", wMax, lastWMaxState);
|
||||
publishBooleanStateIfChanged("$wMin", wMin, lastWMinState);
|
||||
publishBooleanStateIfChanged("$fbDren", fbDren, lastFbDrenState);
|
||||
publishBooleanStateIfChanged("$fbPump", fbPump, lastFbPumpState);
|
||||
|
||||
int state = getIntFromJson(gatesObj, "@state", SP_UNKNOWN);
|
||||
publishNumericState("$state", state);
|
||||
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
bool out_sprinkler::isFreeze()
|
||||
{
|
||||
if (!item) return false;
|
||||
return ((item->getFlag(FLAG_FREEZED) & FLAG_FREEZED) == FLAG_FREEZED);
|
||||
return (item->getFlag(FLAG_FREEZED));
|
||||
}
|
||||
|
||||
bool out_sprinkler::isNeedPump(bool steelNeed)
|
||||
@@ -195,8 +176,27 @@ bool out_sprinkler::isNeedPump(bool steelNeed)
|
||||
void out_sprinkler::pump(bool state)
|
||||
{
|
||||
if (!isValidControlPin(pumpPin)) return;
|
||||
uint32_t lastVals = getIntFromJson (gatesObj, "@lastVals", 0);
|
||||
setOutput(pumpPin, state);
|
||||
publishBooleanState("$rPump", state);
|
||||
if (state != (bool)(lastVals & LASTPUMPSTATE))
|
||||
{
|
||||
if(state) lastVals |= LASTPUMPSTATE; else lastVals &= ~LASTPUMPSTATE;
|
||||
setValToJson(gatesObj, "@lastVals", (long)lastVals);
|
||||
publishBooleanState("/$rPump", state);
|
||||
}
|
||||
}
|
||||
|
||||
void out_sprinkler::dren(bool state)
|
||||
{
|
||||
if (!isValidControlPin(drenPin)) return;
|
||||
uint32_t lastVals = getIntFromJson (gatesObj, "@lastVals", 0);
|
||||
setOutput(drenPin, state);
|
||||
if (state != (bool)(lastVals & LASTDRENSTATE))
|
||||
{
|
||||
if(state) lastVals |= LASTDRENSTATE; else lastVals &= ~LASTDRENSTATE;
|
||||
setValToJson(gatesObj, "@lastVals", (long)lastVals);
|
||||
publishBooleanState("/$rDren", state);
|
||||
}
|
||||
}
|
||||
|
||||
void out_sprinkler::turnOffAllZones()
|
||||
@@ -207,7 +207,7 @@ void out_sprinkler::turnOffAllZones()
|
||||
{
|
||||
if (zone->name && *zone->name && zone->type == aJson_Object)
|
||||
{
|
||||
short pin = getIntFromJson(zone, "pin", -1);
|
||||
short pin = getIntFromJson(zone, "pin", PINS_COUNT);
|
||||
setOutput(pin, false);
|
||||
if (getIntFromJson(zone, "@active", 0))
|
||||
{
|
||||
@@ -225,12 +225,78 @@ void out_sprinkler::turnOffValves()
|
||||
setOutput(drenPin, false);
|
||||
}
|
||||
|
||||
void out_sprinkler::notifyState(short state)
|
||||
//void out_sprinkler::notifyState(short state)
|
||||
//{
|
||||
// if (!gatesObj) return;
|
||||
// setValToJson(gatesObj, "@state", (long)state);
|
||||
// publishNumericState("$state", state);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
void out_sprinkler::notifyState(short state)
|
||||
{
|
||||
char val[16];
|
||||
long fault = 0;
|
||||
|
||||
if (!gatesObj) return;
|
||||
setValToJson(gatesObj, "@state", (long)state);
|
||||
publishNumericState("$state", state);
|
||||
|
||||
aJsonObject *faultObj = aJson.getArrayItem(item->itemArg, 3);
|
||||
switch (state) {
|
||||
|
||||
case SP_OFF:
|
||||
strcpy(val,"OFF");
|
||||
break;
|
||||
|
||||
case SP_DREN_ON:
|
||||
strcpy(val,"DREN_ON");
|
||||
break;
|
||||
|
||||
case SP_DREN_OPERATE:
|
||||
strcpy(val,"DREN_OPERATE");
|
||||
break;
|
||||
|
||||
case SP_DREN_EMPTY:
|
||||
strcpy(val,"DREN_EMPTY");
|
||||
break;
|
||||
|
||||
case SP_VIN:
|
||||
strcpy(val,"VIN");
|
||||
break;
|
||||
case SP_FULL:
|
||||
|
||||
strcpy(val,"FULL");
|
||||
break;
|
||||
|
||||
case SP_FAULT_VIN:
|
||||
strcpy(val,"FAULT_VIN");
|
||||
fault = 1;
|
||||
break;
|
||||
|
||||
case SP_FAULT_DREN:
|
||||
strcpy(val,"FAULT_DREN");
|
||||
fault = 2;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
strcpy(val,"UNKNOWN");
|
||||
break;
|
||||
|
||||
}
|
||||
//if (fault) strcpy(val,"FAULT");
|
||||
|
||||
if (faultObj)
|
||||
{
|
||||
executeCommand(faultObj,-1,itemCmd().Int((int32_t) fault));
|
||||
}
|
||||
else publishTopic(item->itemArr->name,fault,"/$fault");
|
||||
|
||||
publishTopic(item->itemArr->name,val,"/$state");
|
||||
}
|
||||
|
||||
|
||||
|
||||
int out_sprinkler::shutdown(sprinklerState nextState)
|
||||
{
|
||||
@@ -268,8 +334,8 @@ int out_sprinkler::shutdown(sprinklerState nextState)
|
||||
break;
|
||||
}
|
||||
|
||||
publishBooleanState("$rDren", nextState == SP_DREN_ON || nextState == SP_DREN_OPERATE);
|
||||
publishBooleanState("$vIN", nextState == SP_VIN);
|
||||
publishBooleanState("/$rDren", nextState == SP_DREN_ON || nextState == SP_DREN_OPERATE);
|
||||
publishBooleanState("/$vIN", nextState == SP_VIN);
|
||||
notifyState(nextState);
|
||||
return 1;
|
||||
}
|
||||
@@ -311,14 +377,17 @@ inline aJsonObject * out_sprinkler::findNextZone()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
void out_sprinkler::setZoneActive(aJsonObject * zone, bool active)
|
||||
{
|
||||
if (!zone) return;
|
||||
setValToJson(zone, "@active", (long)(active ? 1 : 0));
|
||||
|
||||
char subItem[48];
|
||||
snprintf(subItem, sizeof(subItem), "%s/$state", zone->name);
|
||||
item->SendStatusImmediate(itemCmd().Cmd(active ? CMD_ON : CMD_OFF).setSuffix(S_CMD), FLAG_COMMAND, subItem);
|
||||
snprintf(subItem, sizeof(subItem), "/%s/$state", zone->name);
|
||||
publishTopic(item->itemArr->name, active ? "ON": "OFF", subItem);
|
||||
}
|
||||
|
||||
void out_sprinkler::updateZoneValue(aJsonObject * zone, long value)
|
||||
@@ -336,7 +405,7 @@ void out_sprinkler::updateCounterValue()
|
||||
if (!gatesObj) return;
|
||||
long current = getIntFromJson(gatesObj, "@wCtr", 0);
|
||||
current += value;
|
||||
setValToJson(gatesObj, "wCtr", current);
|
||||
setValToJson(gatesObj, "@wCtr", current);
|
||||
item->SendStatusImmediate(itemCmd().Int(current).setSuffix(S_SET), FLAG_PARAMETERS);
|
||||
}
|
||||
|
||||
@@ -344,15 +413,11 @@ void out_sprinkler::updateCounterValue()
|
||||
bool out_sprinkler::publishBooleanState(const char * subItem, bool state)
|
||||
{
|
||||
if (!item) return state;
|
||||
item->SendStatusImmediate(itemCmd().Cmd(state ? CMD_ON : CMD_OFF).setSuffix(S_CMD), FLAG_COMMAND, (char *)subItem);
|
||||
|
||||
publishTopic(item->itemArr->name,state ? "ON": "OFF", subItem);
|
||||
return state;
|
||||
}
|
||||
|
||||
void out_sprinkler::publishNumericState(const char * subItem, long value)
|
||||
{
|
||||
if (!item) return;
|
||||
item->SendStatusImmediate(itemCmd().Int(value).setSuffix(S_SET), FLAG_PARAMETERS, (char *)subItem);
|
||||
}
|
||||
|
||||
int out_sprinkler::Poll(short cause)
|
||||
{
|
||||
@@ -360,17 +425,17 @@ int out_sprinkler::Poll(short cause)
|
||||
|
||||
|
||||
bool freeze = isFreeze();
|
||||
bool wMax = (wMaxPin >= 0) ? getPinVal(wMaxPin) : false;
|
||||
bool wMin = (wMinPin >= 0) ? getPinVal(wMinPin) : false;
|
||||
bool fbDren = (fbDrenPin >= 0) ? getPinVal(fbDrenPin) : false;
|
||||
bool fbPump = (fbPumpPin >= 0) ? getPinVal(fbPumpPin) : false;
|
||||
bool wMax = (wMaxPin != PINS_COUNT) ? readInPin(wMaxPin) : false;
|
||||
bool wMin = (wMinPin != PINS_COUNT) ? readInPin(wMinPin) : false;
|
||||
bool fbDren = (fbDrenPin != PINS_COUNT) ? readInPin(fbDrenPin) : false;
|
||||
bool fbPump = (fbPumpPin != PINS_COUNT) ? readInPin(fbPumpPin) : false;
|
||||
|
||||
uint32_t lastVals = getIntFromJson(gatesObj, "@lastVals", 0);
|
||||
|
||||
publishBooleanStateIfChanged("$wMax", wMax, LASTWMAXSTATE, lastVals);
|
||||
publishBooleanStateIfChanged("$wMin", wMin, LASTWMINSTATE, lastVals);
|
||||
publishBooleanStateIfChanged("$fbDren", fbDren, LASTFBDRENSTATE, lastVals);
|
||||
publishBooleanStateIfChanged("$fbPump", fbPump, LASTFBPUMPSTATE, lastVals);
|
||||
publishBooleanStateIfChanged("/$wMax", wMax, LASTWMAXSTATE, lastVals);
|
||||
publishBooleanStateIfChanged("/$wMin", wMin, LASTWMINSTATE, lastVals);
|
||||
publishBooleanStateIfChanged("/$fbDren", fbDren, LASTFBDRENSTATE, lastVals);
|
||||
publishBooleanStateIfChanged("/$fbPump", fbPump, LASTFBPUMPSTATE, lastVals);
|
||||
|
||||
uint32_t now = millisNZ();
|
||||
int state = getIntFromJson(gatesObj, "@state", SP_UNKNOWN);
|
||||
@@ -378,9 +443,9 @@ int out_sprinkler::Poll(short cause)
|
||||
bool lastWctrlState = lastVals & LASTWCTRLSTATE;
|
||||
bool lastWctrlStateAll = lastVals & LASTWCTRLSTATE_ALL;
|
||||
|
||||
if (wCtrPin >= 0)
|
||||
if (wCtrPin != PINS_COUNT)
|
||||
{
|
||||
bool curr = getPinVal(wCtrPin);
|
||||
bool curr = readInPin(wCtrPin);
|
||||
if (curr && !lastWctrlStateAll)
|
||||
{
|
||||
updateCounterValue();
|
||||
@@ -520,7 +585,7 @@ int out_sprinkler::Poll(short cause)
|
||||
break;
|
||||
}
|
||||
|
||||
bool tankReady = (state == SP_FULL || wMax);
|
||||
bool tankReady = (state == SP_FULL || wMax || wMin || fbPump);
|
||||
bool needPump = false;
|
||||
aJsonObject * currentZone = NULL;
|
||||
|
||||
@@ -543,14 +608,14 @@ int out_sprinkler::Poll(short cause)
|
||||
{
|
||||
turnOffAllZones();
|
||||
setZoneActive(currentZone, true);
|
||||
short zonePin = getIntFromJson(currentZone, "pin", -1);
|
||||
short zonePin = getIntFromJson(currentZone, "pin", PINS_COUNT);
|
||||
setOutput(zonePin, true);
|
||||
setValToJson(gatesObj, "@flowTimer", (long)now);
|
||||
}
|
||||
|
||||
if (wCtrPin >= 0)
|
||||
if (wCtrPin != PINS_COUNT)
|
||||
{
|
||||
bool curr = getPinVal(wCtrPin);
|
||||
bool curr = readInPin(wCtrPin);
|
||||
if (curr && !lastWctrlState)
|
||||
{
|
||||
updateZoneValue(currentZone, 1);
|
||||
@@ -571,10 +636,10 @@ int out_sprinkler::Poll(short cause)
|
||||
|
||||
if (setVal > 0 && valVal >= setVal)
|
||||
{
|
||||
setOutput(getIntFromJson(currentZone, "pin", -1), false);
|
||||
setOutput(getIntFromJson(currentZone, "pin", PINS_COUNT), false);
|
||||
setZoneActive(currentZone, false);
|
||||
//////setValToJson(currentZone, "cmd", (long)CMD_OFF);
|
||||
item->SendStatusImmediate(itemCmd().Cmd(CMD_OFF).setSuffix(S_CMD), FLAG_COMMAND, currentZone->name);
|
||||
//item->SendStatusImmediate(itemCmd().Cmd(CMD_OFF).setSuffix(S_CMD), FLAG_COMMAND, currentZone->name);
|
||||
currentZone = findNextZone();
|
||||
}
|
||||
|
||||
@@ -610,29 +675,37 @@ int out_sprinkler::Ctrl(itemCmd cmd, char* subItem, bool toExecute, bool authori
|
||||
{
|
||||
if (!item || !gatesObj) return 0;
|
||||
int suffixCode = cmd.isCommand() ? S_CMD : cmd.getSuffix();
|
||||
debugSerial << "SPRINKLER: CTRL " << subItem << " "<< "Execute:"<< toExecute << " "; cmd.debugOut();
|
||||
bool sendStatus = isNotRetainingStatus();
|
||||
|
||||
if (subItem && *subItem)
|
||||
{
|
||||
aJsonObject * zone = getZone(subItem);
|
||||
if (!zone) return 0;
|
||||
|
||||
///// FOR ZONES
|
||||
switch (suffixCode)
|
||||
{
|
||||
case S_SET:
|
||||
if (toExecute)
|
||||
// if (toExecute)
|
||||
{
|
||||
long value = cmd.getInt();
|
||||
setValToJson(zone, "set", value);
|
||||
item->SendStatusImmediate(itemCmd().Int(value).setSuffix(S_SET), FLAG_PARAMETERS, subItem);
|
||||
if (sendStatus)
|
||||
{
|
||||
item->SendStatusImmediate(itemCmd().Int(value).setSuffix(S_SET), FLAG_PARAMETERS, subItem);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
case S_VAL:
|
||||
if (toExecute)
|
||||
// if (toExecute)
|
||||
{
|
||||
long value = cmd.getInt();
|
||||
setValToJson(zone, "val", value);
|
||||
item->SendStatusImmediate(itemCmd().Int(value).setSuffix(S_VAL), FLAG_PARAMETERS, subItem);
|
||||
if (sendStatus)
|
||||
{
|
||||
item->SendStatusImmediate(itemCmd().Int(value).setSuffix(S_VAL), FLAG_PARAMETERS, subItem);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
@@ -641,27 +714,28 @@ int out_sprinkler::Ctrl(itemCmd cmd, char* subItem, bool toExecute, bool authori
|
||||
switch (cmd.getCmd())
|
||||
{
|
||||
case CMD_ON:
|
||||
if (toExecute)
|
||||
setValToJson(zone, "cmd", (long)CMD_ON);
|
||||
if (sendStatus)
|
||||
{
|
||||
setValToJson(zone, "cmd", (long)CMD_ON);
|
||||
item->SendStatusImmediate(itemCmd().Cmd(CMD_ON).setSuffix(S_CMD), FLAG_COMMAND, subItem);
|
||||
}
|
||||
return 1;
|
||||
|
||||
case CMD_OFF:
|
||||
if (toExecute)
|
||||
setValToJson(zone, "cmd", (long)CMD_OFF);
|
||||
setZoneActive(zone, false);
|
||||
setOutput(getIntFromJson(zone, "pin", PINS_COUNT), false);
|
||||
|
||||
if (sendStatus)
|
||||
{
|
||||
setValToJson(zone, "cmd", (long)CMD_OFF);
|
||||
setZoneActive(zone, false);
|
||||
setOutput(getIntFromJson(zone, "pin", -1), false);
|
||||
item->SendStatusImmediate(itemCmd().Cmd(CMD_OFF).setSuffix(S_CMD), FLAG_COMMAND, subItem);
|
||||
}
|
||||
return 1;
|
||||
|
||||
case CMD_RESET:
|
||||
if (toExecute)
|
||||
setValToJson(zone, "val", (long)0);
|
||||
if (sendStatus)
|
||||
{
|
||||
setValToJson(zone, "val", (long)0);
|
||||
item->SendStatusImmediate(itemCmd().Int(0).setSuffix(S_VAL), FLAG_PARAMETERS, subItem);
|
||||
}
|
||||
return 1;
|
||||
@@ -671,7 +745,7 @@ int out_sprinkler::Ctrl(itemCmd cmd, char* subItem, bool toExecute, bool authori
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// FOR SPRINKLER CONTROLLER
|
||||
switch (suffixCode)
|
||||
{
|
||||
case S_CMD:
|
||||
@@ -683,6 +757,7 @@ int out_sprinkler::Ctrl(itemCmd cmd, char* subItem, bool toExecute, bool authori
|
||||
case CMD_OFF:
|
||||
turnOffAllZones();
|
||||
pump(false);
|
||||
//dren(false);
|
||||
return 1;
|
||||
|
||||
case CMD_RESET:
|
||||
@@ -693,7 +768,10 @@ int out_sprinkler::Ctrl(itemCmd cmd, char* subItem, bool toExecute, bool authori
|
||||
if (zone->name && *zone->name && zone->type == aJson_Object)
|
||||
{
|
||||
setValToJson(zone, "val", (long)0);
|
||||
item->SendStatusImmediate(itemCmd().Int(0).setSuffix(S_VAL), FLAG_PARAMETERS, zone->name);
|
||||
if (sendStatus)
|
||||
{
|
||||
item->SendStatusImmediate(itemCmd().Int(0).setSuffix(S_VAL), FLAG_PARAMETERS, zone->name);
|
||||
}
|
||||
}
|
||||
zone = zone->next;
|
||||
}
|
||||
@@ -706,39 +784,44 @@ int out_sprinkler::Ctrl(itemCmd cmd, char* subItem, bool toExecute, bool authori
|
||||
break;
|
||||
|
||||
case S_SET:
|
||||
if (toExecute)
|
||||
{
|
||||
{
|
||||
debugSerial << F("SPRINKLER: set wCtr to ") << cmd.getInt() << endl;
|
||||
long value = cmd.getInt();
|
||||
setValToJson(gatesObj, "@wCtr", value);
|
||||
|
||||
if (sendStatus)
|
||||
{
|
||||
item->SendStatusImmediate(itemCmd().Int(0).setSuffix(S_SET), FLAG_PARAMETERS);
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
case S_VAL:
|
||||
if (toExecute)
|
||||
{
|
||||
{
|
||||
debugSerial << F("SPRINKLER: ext temperature: ") << cmd.getInt() << endl;
|
||||
long value = cmd.getInt();
|
||||
if (value < 0)
|
||||
{
|
||||
item->setFlag(FLAG_FREEZED);
|
||||
item->SendStatus(FLAG_FLAGS);
|
||||
}
|
||||
else if (isFreeze())
|
||||
{
|
||||
item->clearFlag(FLAG_FREEZED);
|
||||
item->SendStatus(FLAG_FLAGS);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
// else if (isFreeze())
|
||||
// {
|
||||
// item->clearFlag(FLAG_FREEZED);
|
||||
// item->SendStatus(FLAG_FLAGS);
|
||||
// }
|
||||
|
||||
default:
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// default:
|
||||
// break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int out_sprinkler::getChanType()
|
||||
{
|
||||
return CH_RELAY;
|
||||
return CH_COUNTER;
|
||||
}
|
||||
|
||||
#endif // SPRINKLER_ENABLE
|
||||
@@ -15,6 +15,8 @@
|
||||
#define LASTWMINSTATE 8
|
||||
#define LASTFBDRENSTATE 16
|
||||
#define LASTFBPUMPSTATE 32
|
||||
#define LASTPUMPSTATE 64
|
||||
#define LASTDRENSTATE 128
|
||||
|
||||
enum sprinklerState {
|
||||
SP_UNKNOWN = 0,
|
||||
@@ -48,6 +50,7 @@ protected:
|
||||
|
||||
|
||||
void pump(bool state);
|
||||
void dren(bool state);
|
||||
void setOutput(short pin, bool value);
|
||||
bool isNeedPump(bool steelNeed=false);
|
||||
void turnOffValves();
|
||||
|
||||
@@ -1136,5 +1136,54 @@ return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setupInPin(short pin)
|
||||
{
|
||||
if (abs(pin)>=PINS_COUNT)
|
||||
{
|
||||
debugSerial<<F("Attempt to setup non existing pin: ")<<pin<<endl;
|
||||
return;
|
||||
}
|
||||
//debugSerial<<F("Setup pin: ")<<pin<<endl;
|
||||
if (pin<0)
|
||||
pinMode(-pin, INPUT_PULLUP);
|
||||
else
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
|
||||
bool readInPin(short pin)
|
||||
{
|
||||
if (abs(pin)>=PINS_COUNT)
|
||||
{
|
||||
debugSerial<<F("Attempt to read non existing pin: ")<<pin<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pin<0)
|
||||
return (digitalRead(-pin)==LOW);
|
||||
else
|
||||
return (digitalRead(pin)==HIGH);
|
||||
}
|
||||
|
||||
void writeOutPin(short pin, bool val)
|
||||
{
|
||||
if(isProtectedPin(abs(pin)))
|
||||
{
|
||||
debugSerial<<F("Attempt to write protected pin: ")<<pin<<endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (abs(pin)>=PINS_COUNT)
|
||||
{
|
||||
debugSerial<<F("Attempt to write non existing pin: ")<<pin<<endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pin<0)
|
||||
digitalWrite(-pin, val?LOW:HIGH);
|
||||
else
|
||||
digitalWrite(pin, val?HIGH:LOW);
|
||||
}
|
||||
|
||||
#pragma message(VAR_NAME_VALUE(debugSerial))
|
||||
#pragma message(VAR_NAME_VALUE(SERIAL_BAUD))
|
||||
|
||||
@@ -91,7 +91,9 @@ bool checkToken(char * token, char * data);
|
||||
long getIntFromJson(aJsonObject * a, const char * name, int i,long def);
|
||||
float getFloatFromJson(aJsonObject * a, const char * name, int i, float def);
|
||||
|
||||
|
||||
void setupInPin(short pin);
|
||||
bool readInPin(short pin);
|
||||
void writeOutPin(short pin, bool val);
|
||||
|
||||
// Get object from array, create if absent and return pointer to object
|
||||
template<typename Type>
|
||||
|
||||
Reference in New Issue
Block a user