add alarm if pumps did not change state to wet after X consecutive tries

This commit is contained in:
Your Name 2021-08-23 00:58:37 +02:00
parent 61098724b6
commit e927fc8c70
4 changed files with 72 additions and 18 deletions

View File

@ -69,7 +69,7 @@ HomieNode stayAlive("stay", "alive", "alive"); /**< Necessary for Mqtt Active C
HomieSetting<long> deepSleepTime("sleep", "time in seconds to sleep"); HomieSetting<long> deepSleepTime("sleep", "time in seconds to sleep");
HomieSetting<long> deepSleepNightTime("nightsleep", "time in seconds to sleep (0 uses same setting: deepsleep at night, too)"); HomieSetting<long> deepSleepNightTime("nightsleep", "time in seconds to sleep (0 uses same setting: deepsleep at night, too)");
HomieSetting<long> wateringDeepSleep("pumpsleep", "time seconds to sleep, while a pump is running"); HomieSetting<long> wateringDeepSleep("pumpsleep", "time seconds to sleep, while a pump is running");
HomieSetting<long> pumpIneffectiveWarning("pumpConsecutiveWarn", "if the pump was triggered this amount directly after each cooldown, without resolving dryness, warn");
HomieSetting<long> waterLevelMax("tankmax", "distance (mm) at maximum water level"); HomieSetting<long> waterLevelMax("tankmax", "distance (mm) at maximum water level");
HomieSetting<long> waterLevelMin("tankmin", "distance (mm) at minimum water level (pumps still covered)"); HomieSetting<long> waterLevelMin("tankmin", "distance (mm) at minimum water level (pumps still covered)");
HomieSetting<long> waterLevelWarn("tankwarn", "warn (mm) if below this water level %"); HomieSetting<long> waterLevelWarn("tankwarn", "warn (mm) if below this water level %");

View File

@ -20,6 +20,9 @@
#define LOG_PUMP_AND_DOWNLOADMODE "Download mode, ignoring pump request" #define LOG_PUMP_AND_DOWNLOADMODE "Download mode, ignoring pump request"
#define LOG_PUMP_AND_DOWNLOADMODE_CODE 2 #define LOG_PUMP_AND_DOWNLOADMODE_CODE 2
//msg is dynamic defined
#define LOG_PUMP_INEFFECTIVE -4
#define LOG_DEBUG_CODE 1001 #define LOG_DEBUG_CODE 1001
#define LOG_NOPUMP_LOWLIGHT 100 #define LOG_NOPUMP_LOWLIGHT 100
#define LOG_NOPUMPS 101 #define LOG_NOPUMPS 101

View File

@ -121,7 +121,6 @@ void Plant::postMQTTconnection(void)
this->mPlant->setProperty("moist").send(String(round(pct*10)/10)); this->mPlant->setProperty("moist").send(String(round(pct*10)/10));
this->mPlant->setProperty("moistraw").send(String(raw)); this->mPlant->setProperty("moistraw").send(String(raw));
this->mPlant->setProperty("moisttrigger").send(String(getSetting2Moisture())); this->mPlant->setProperty("moisttrigger").send(String(getSetting2Moisture()));
} }
void Plant::deactivatePump(void) void Plant::deactivatePump(void)

View File

@ -34,7 +34,6 @@
#include <Wire.h> #include <Wire.h>
#include <VL53L0X.h> #include <VL53L0X.h>
/****************************************************************************** /******************************************************************************
* DEFINES * DEFINES
******************************************************************************/ ******************************************************************************/
@ -70,6 +69,7 @@ RTC_DATA_ATTR int lastPumpRunning = -1; /**< store last successfully waterd plan
RTC_DATA_ATTR long lastWaterValue = 0; /**< to calculate the used water per plant */ RTC_DATA_ATTR long lastWaterValue = 0; /**< to calculate the used water per plant */
RTC_DATA_ATTR long rtcLastWateringPlant[MAX_PLANTS] = {0}; RTC_DATA_ATTR long rtcLastWateringPlant[MAX_PLANTS] = {0};
RTC_DATA_ATTR long consecutiveWateringPlant[MAX_PLANTS] = {0};
/****************************************************************************** /******************************************************************************
* LOCAL VARIABLES * LOCAL VARIABLES
@ -416,6 +416,11 @@ int determineNextPump()
int pumpToUse = -1; int pumpToUse = -1;
for (int i = 0; i < MAX_PLANTS; i++) for (int i = 0; i < MAX_PLANTS; i++)
{ {
bool wateralarm = consecutiveWateringPlant[i] >= pumpIneffectiveWarning.get();
if (wateralarm)
{
log(LOG_LEVEL_ERROR, String(String(i) + " Plant still dry after " + String(consecutiveWateringPlant[i]) + " watering attempts"), LOG_PUMP_INEFFECTIVE);
}
Plant plant = mPlants[i]; Plant plant = mPlants[i];
if (!plant.isPumpTriggerActive()) if (!plant.isPumpTriggerActive())
{ {
@ -424,14 +429,29 @@ int determineNextPump()
continue; continue;
} }
if ((rtcLastWateringPlant[i] + plant.getCooldownInSeconds()) > getCurrentTime()) if ((rtcLastWateringPlant[i] + plant.getCooldownInSeconds()) > getCurrentTime())
{
if (wateralarm)
{
plant.publishState("cooldown+alarm");
}
else
{ {
plant.publishState("cooldown"); plant.publishState("cooldown");
}
log(LOG_LEVEL_DEBUG, String(String(i) + " Skipping due to cooldown " + String(rtcLastWateringPlant[i] + plant.getCooldownInSeconds())), LOG_DEBUG_CODE); log(LOG_LEVEL_DEBUG, String(String(i) + " Skipping due to cooldown " + String(rtcLastWateringPlant[i] + plant.getCooldownInSeconds())), LOG_DEBUG_CODE);
continue; continue;
} }
if (!isLowLight && plant.isAllowedOnlyAtLowLight()) if (!isLowLight && plant.isAllowedOnlyAtLowLight())
{
if (wateralarm)
{
plant.publishState("sunny+alarm");
}
else
{ {
plant.publishState("sunny"); plant.publishState("sunny");
}
log(LOG_LEVEL_DEBUG, String(String(i) + " No pump required: due to light"), LOG_DEBUG_CODE); log(LOG_LEVEL_DEBUG, String(String(i) + " No pump required: due to light"), LOG_DEBUG_CODE);
continue; continue;
} }
@ -451,14 +471,30 @@ int determineNextPump()
(getCurrentHour() >= plant.getHoursStart() && getCurrentHour() <= plant.getHoursEnd())) || (getCurrentHour() >= plant.getHoursStart() && getCurrentHour() <= plant.getHoursEnd())) ||
/* no time from NTP received */ /* no time from NTP received */
(getCurrentTime() < 10000)) (getCurrentTime() < 10000))
{
if (wateralarm)
{
plant.publishState("active+alarm");
}
else
{ {
plant.publishState("active"); plant.publishState("active");
}
consecutiveWateringPlant[i]++;
log(LOG_LEVEL_DEBUG, String(String(i) + " Requested pumping"), LOG_DEBUG_CODE); log(LOG_LEVEL_DEBUG, String(String(i) + " Requested pumping"), LOG_DEBUG_CODE);
pumpToUse = i; pumpToUse = i;
} }
else else
{
if (wateralarm)
{
plant.publishState("after-work+alarm");
}
else
{ {
plant.publishState("after-work"); plant.publishState("after-work");
}
log(LOG_LEVEL_DEBUG, String(String(i) + " ignored due to time boundary: " + String(plant.getHoursStart()) + " to " + String(plant.getHoursEnd()) + " ( current " + String(getCurrentHour()) + " )"), LOG_DEBUG_CODE); log(LOG_LEVEL_DEBUG, String(String(i) + " ignored due to time boundary: " + String(plant.getHoursStart()) + " to " + String(plant.getHoursEnd()) + " ( current " + String(getCurrentHour()) + " )"), LOG_DEBUG_CODE);
} }
continue; continue;
@ -466,6 +502,8 @@ int determineNextPump()
else else
{ {
plant.publishState("wet"); plant.publishState("wet");
//plant was detected as wet, remove consecutive count
consecutiveWateringPlant[i] = 0;
} }
} }
return pumpToUse; return pumpToUse;
@ -513,31 +551,38 @@ void homieLoop()
} }
} }
bool switch1(const HomieRange& range, const String& value) { bool switch1(const HomieRange &range, const String &value)
{
return mPlants[0].switchHandler(range, value); return mPlants[0].switchHandler(range, value);
} }
bool switch2(const HomieRange& range, const String& value) { bool switch2(const HomieRange &range, const String &value)
{
return mPlants[1].switchHandler(range, value); return mPlants[1].switchHandler(range, value);
} }
bool switch3(const HomieRange& range, const String& value) { bool switch3(const HomieRange &range, const String &value)
{
return mPlants[2].switchHandler(range, value); return mPlants[2].switchHandler(range, value);
} }
bool switch4(const HomieRange& range, const String& value) { bool switch4(const HomieRange &range, const String &value)
{
return mPlants[3].switchHandler(range, value); return mPlants[3].switchHandler(range, value);
} }
bool switch5(const HomieRange& range, const String& value) { bool switch5(const HomieRange &range, const String &value)
{
return mPlants[4].switchHandler(range, value); return mPlants[4].switchHandler(range, value);
} }
bool switch6(const HomieRange& range, const String& value) { bool switch6(const HomieRange &range, const String &value)
{
return mPlants[5].switchHandler(range, value); return mPlants[5].switchHandler(range, value);
} }
bool switch7(const HomieRange& range, const String& value) { bool switch7(const HomieRange &range, const String &value)
{
return mPlants[6].switchHandler(range, value); return mPlants[6].switchHandler(range, value);
} }
@ -626,7 +671,8 @@ void setup()
// Set default values // Set default values
//in seconds //in seconds
deepSleepTime.setDefaultValue(600).setValidator([](long candidate) { return (candidate > 0) && (candidate < (60 * 60 * 2) /** 2h max sleep */); }); deepSleepTime.setDefaultValue(600).setValidator([](long candidate)
{ return (candidate > 0) && (candidate < (60 * 60 * 2) /** 2h max sleep */); });
deepSleepNightTime.setDefaultValue(600); deepSleepNightTime.setDefaultValue(600);
wateringDeepSleep.setDefaultValue(5); wateringDeepSleep.setDefaultValue(5);
ntpServer.setDefaultValue("pool.ntp.org"); ntpServer.setDefaultValue("pool.ntp.org");
@ -637,6 +683,9 @@ void setup()
waterLevelVol.setDefaultValue(5000); /* 5l in ml */ waterLevelVol.setDefaultValue(5000); /* 5l in ml */
lipoSensorAddr.setDefaultValue(""); lipoSensorAddr.setDefaultValue("");
waterSensorAddr.setDefaultValue(""); waterSensorAddr.setDefaultValue("");
pumpIneffectiveWarning.setDefaultValue(600).setValidator([](long candidate)
{ return (candidate > 0) && (candidate < (20)); });
pumpIneffectiveWarning.setDefaultValue(5);
Homie.setLoopFunction(homieLoop); Homie.setLoopFunction(homieLoop);
Homie.onEvent(onHomieEvent); Homie.onEvent(onHomieEvent);
@ -802,6 +851,7 @@ void plantcontrol()
for (int i = 0; i < MAX_PLANTS; i++) for (int i = 0; i < MAX_PLANTS; i++)
{ {
mPlants[i].postMQTTconnection(); mPlants[i].postMQTTconnection();
mPlants[i].setProperty("consecutivePumps").send(String(consecutiveWateringPlant[i]));
} }
} }
@ -817,10 +867,12 @@ void plantcontrol()
if (mAliveWasRead) if (mAliveWasRead)
{ {
float remaining = waterLevelMax.get() - waterRawSensor.getAverage(); float remaining = waterLevelMax.get() - waterRawSensor.getAverage();
if (! isnan(remaining)) { if (!isnan(remaining))
{
sensorWater.setProperty("remaining").send(String(remaining)); sensorWater.setProperty("remaining").send(String(remaining));
} }
if (! isnan(waterRawSensor.getAverage())) { if (!isnan(waterRawSensor.getAverage()))
{
sensorWater.setProperty("distance").send(String(waterRawSensor.getAverage())); sensorWater.setProperty("distance").send(String(waterRawSensor.getAverage()));
} }
sensorLipo.setProperty("percent").send(String(100 * batteryVoltage / VOLT_MAX_BATT)); sensorLipo.setProperty("percent").send(String(100 * batteryVoltage / VOLT_MAX_BATT));