Merge branch 'master' of github.com:0110/PlantCtrl

This commit is contained in:
Empire 2023-02-10 22:12:57 +01:00
commit 68386ce02f
6 changed files with 89 additions and 65 deletions

View File

@ -94,7 +94,7 @@
#define MOIST_SENSOR_MIN_FRQ 500 // 0.5kHz (500Hz margin) #define MOIST_SENSOR_MIN_FRQ 500 // 0.5kHz (500Hz margin)
#define ANALOG_SENSOR_MAX_MV 1300 //successive approximation of good range #define ANALOG_SENSOR_MAX_MV 1300 //successive approximation of good range
#define ANALOG_SENSOR_MIN_MV 300 //successive approximation of good range #define ANALOG_SENSOR_MIN_MV 100 //successive approximation of good range
#define SOLAR_VOLT_FACTOR 11 #define SOLAR_VOLT_FACTOR 11
#define BATTSENSOR_INDEX_SOLAR 0 #define BATTSENSOR_INDEX_SOLAR 0

View File

@ -45,6 +45,8 @@ static const char *SENSOR_STRING[] = {
#define MISSING_SENSOR -2 #define MISSING_SENSOR -2
//plant uses only cooldown and duration, moisture is measured but ignored, allowedHours is ignored (eg. make a 30min on 30min off cycle) //plant uses only cooldown and duration, moisture is measured but ignored, allowedHours is ignored (eg. make a 30min on 30min off cycle)
#define HYDROPONIC_MODE -3 #define HYDROPONIC_MODE -3
//plant uses cooldown and duration and workhours, moisture is measured but ignored
#define TIMER_ONLY -4
typedef struct PlantSettings_t typedef struct PlantSettings_t
{ {

View File

@ -29,6 +29,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
#define LOG_VERY_COLD_WATER "Water potentially frozen, ignoring pump request"
#define LOG_VERY_COLD_WATER -7
//msg is dynamic defined //msg is dynamic defined
#define LOG_PUMP_INEFFECTIVE -4 #define LOG_PUMP_INEFFECTIVE -4
#define LOG_PUMP_STARTED_CODE 10 #define LOG_PUMP_STARTED_CODE 10

View File

@ -73,6 +73,12 @@ public:
return SENSOR_STRING[mode]; return SENSOR_STRING[mode];
} }
bool isTimerOnly()
{
long current = this->mSetting->pSensorDry->get();
return equalish(current, TIMER_ONLY);
}
bool isHydroponic() bool isHydroponic()
{ {
long current = this->mSetting->pSensorDry->get(); long current = this->mSetting->pSensorDry->get();
@ -92,7 +98,7 @@ public:
*/ */
bool isPumpRequired() bool isPumpRequired()
{ {
if (isHydroponic()) if (isHydroponic() || isTimerOnly())
{ {
// hydroponic only uses timer based controll // hydroponic only uses timer based controll
return true; return true;

View File

@ -30,7 +30,7 @@ void Plant::init(void)
/* Initialize Home Settings validator */ /* Initialize Home Settings validator */
this->mSetting->pSensorDry->setDefaultValue(DEACTIVATED_PLANT); this->mSetting->pSensorDry->setDefaultValue(DEACTIVATED_PLANT);
this->mSetting->pSensorDry->setValidator([](long candidate) this->mSetting->pSensorDry->setValidator([](long candidate)
{ return (((candidate >= 0.0) && (candidate <= 100.0)) || equalish(candidate, DEACTIVATED_PLANT) || equalish(candidate, HYDROPONIC_MODE)); }); { return (((candidate >= 0.0) && (candidate <= 100.0)) || equalish(candidate, DEACTIVATED_PLANT) || equalish(candidate, HYDROPONIC_MODE) || equalish(candidate, TIMER_ONLY)); });
this->mSetting->pPumpAllowedHourRangeStart->setDefaultValue(8); // start at 8:00 this->mSetting->pPumpAllowedHourRangeStart->setDefaultValue(8); // start at 8:00
this->mSetting->pPumpAllowedHourRangeStart->setValidator([](long candidate) this->mSetting->pPumpAllowedHourRangeStart->setValidator([](long candidate)
@ -38,7 +38,7 @@ void Plant::init(void)
this->mSetting->pPumpAllowedHourRangeEnd->setDefaultValue(20); // stop pumps at 20:00 this->mSetting->pPumpAllowedHourRangeEnd->setDefaultValue(20); // stop pumps at 20:00
this->mSetting->pPumpAllowedHourRangeEnd->setValidator([](long candidate) this->mSetting->pPumpAllowedHourRangeEnd->setValidator([](long candidate)
{ return ((candidate >= 0) && (candidate <= 23)); }); { return ((candidate >= 0) && (candidate <= 23)); });
this->mSetting->pPumpOnlyWhenLowLight->setDefaultValue(true); this->mSetting->pPumpOnlyWhenLowLight->setDefaultValue(false);
this->mSetting->pPumpCooldownInSeconds->setDefaultValue(60 * 60); // 1 hour this->mSetting->pPumpCooldownInSeconds->setDefaultValue(60 * 60); // 1 hour
this->mSetting->pPumpCooldownInSeconds->setValidator([](long candidate) this->mSetting->pPumpCooldownInSeconds->setValidator([](long candidate)
{ return (candidate >= 0); }); { return (candidate >= 0); });
@ -263,9 +263,9 @@ void Plant::advertise(void)
{ {
// Advertise topics // Advertise topics
mPump = this->mPlant->advertise("switch").setName("Pump").setDatatype("Boolean"); mPump = this->mPlant->advertise("switch").setName("Pump").setDatatype("Boolean");
this->mPlant->advertise("lastPump").setName("lastPump").setDatatype("Integer").setUnit("unixtime"); this->mPlant->advertise("lastPump").setName("lastPump").setDatatype("Integer").setUnit("unixtime").setRetained(true);
this->mPlant->advertise("moist").setName("Percent").setDatatype("Float").setUnit("%"); this->mPlant->advertise("moist").setName("Percent").setDatatype("Float").setUnit("%").setRetained(true);
this->mPlant->advertise("moistraw").setName("adc").setDatatype("Float").setUnit("3.3/4096V"); this->mPlant->advertise("moistraw").setName("adc").setDatatype("Float").setUnit("3.3/4096V").setRetained(true);
this->mPlant->advertise("state").setName("state").setDatatype("String"); this->mPlant->advertise("state").setName("state").setDatatype("String").setRetained(true);
} }

View File

@ -12,7 +12,7 @@
/****************************************************************************** /******************************************************************************
* INCLUDES * INCLUDES
******************************************************************************/ ******************************************************************************/
#include "LogDefines.h" #include "LogDefines.h"
#include "FileUtils.h" #include "FileUtils.h"
#include "TimeUtils.h" #include "TimeUtils.h"
@ -37,29 +37,29 @@
#include "MQTTUtils.h" #include "MQTTUtils.h"
#include "esp_ota_ops.h" #include "esp_ota_ops.h"
#if defined(TIMED_LIGHT_PIN) #if defined(TIMED_LIGHT_PIN)
#include "ulp-pwm.h" #include "ulp-pwm.h"
#endif #endif
/****************************************************************************** /******************************************************************************
* DEFINES * DEFINES
******************************************************************************/ ******************************************************************************/
#define AMOUNT_SENOR_QUERYS 8 #define AMOUNT_SENOR_QUERYS 8
#define MAX_TANK_DEPTH 2000 #define MAX_TANK_DEPTH 2000
#define REBOOT_LOOP_DETECTION_ERROR 5 #define REBOOT_LOOP_DETECTION_ERROR 5
/****************************************************************************** /******************************************************************************
* FUNCTION PROTOTYPES * FUNCTION PROTOTYPES
******************************************************************************/ ******************************************************************************/
int determineNextPump(bool lowLight); int determineNextPump(bool lowLight);
void plantcontrol(); void plantcontrol();
void readPowerSwitchedSensors(); void readPowerSwitchedSensors();
bool determineTimedLightState(bool lowLight); bool determineTimedLightState(bool lowLight);
bool otaRunning = false;
/****************************************************************************** /******************************************************************************
* NON VOLATILE VARIABLES in DEEP SLEEP * NON VOLATILE VARIABLES in DEEP SLEEP
******************************************************************************/ ******************************************************************************/
#if defined(TIMED_LIGHT_PIN) #if defined(TIMED_LIGHT_PIN)
RTC_DATA_ATTR bool timedLightLowVoltageTriggered = false; /**remember if it was shut down due to voltage level */ RTC_DATA_ATTR bool timedLightLowVoltageTriggered = false; /**remember if it was shut down due to voltage level */
#endif // TIMED_LIGHT_PIN #endif // TIMED_LIGHT_PIN
@ -69,7 +69,7 @@ RTC_DATA_ATTR long consecutiveWateringPlant[MAX_PLANTS] = {0};
/****************************************************************************** /******************************************************************************
* LOCAL VARIABLES * LOCAL VARIABLES
******************************************************************************/ ******************************************************************************/
bool volatile mDownloadMode = false; /**< Controller must not sleep */ bool volatile mDownloadMode = false; /**< Controller must not sleep */
bool volatile mSensorsRead = false; /**< Sensors are read without Wifi or MQTT */ bool volatile mSensorsRead = false; /**< Sensors are read without Wifi or MQTT */
int volatile pumpToRun = -1; /** pump to run at the end of the cycle */ int volatile pumpToRun = -1; /** pump to run at the end of the cycle */
@ -90,6 +90,8 @@ long lastSendPumpUpdate = 0;
long pumpTargetMl = -1; long pumpTargetMl = -1;
#endif #endif
float waterTemp = 30;
/*************************** Hardware abstraction *****************************/ /*************************** Hardware abstraction *****************************/
OneWire oneWire(SENSOR_ONEWIRE); OneWire oneWire(SENSOR_ONEWIRE);
@ -130,7 +132,7 @@ Plant mPlants[MAX_PLANTS] = {
/****************************************************************************** /******************************************************************************
* LOCAL FUNCTIONS * LOCAL FUNCTIONS
******************************************************************************/ ******************************************************************************/
void finsihedCycleSucessfully() void finsihedCycleSucessfully()
{ {
@ -152,7 +154,7 @@ void espDeepSleep(bool afterPump = false)
if (mDownloadMode) if (mDownloadMode)
{ {
log(LOG_LEVEL_DEBUG, "abort deepsleep, DownloadMode active", LOG_DEBUG_CODE); log(LOG_LEVEL_DEBUG, "abort deepsleep, DownloadMode active", LOG_DEBUG_CODE);
//if we manage to get to the download mode, the device can be restored // if we manage to get to the download mode, the device can be restored
finsihedCycleSucessfully(); finsihedCycleSucessfully();
return; return;
} }
@ -212,7 +214,7 @@ void espDeepSleep(bool afterPump = false)
} }
} }
//requires homie being started // requires homie being started
void readOneWireSensors() void readOneWireSensors()
{ {
for (uint8_t i = 0; i < sensors.getDeviceCount(); i++) for (uint8_t i = 0; i < sensors.getDeviceCount(); i++)
@ -240,7 +242,7 @@ void readOneWireSensors()
if (!valid) if (!valid)
{ {
//wrong family or crc errors on each retry // wrong family or crc errors on each retry
continue; continue;
} }
@ -267,6 +269,7 @@ void readOneWireSensors()
{ {
mqttWrite(&sensorTemp, TEMPERATUR_SENSOR_WATER, String(temp)); mqttWrite(&sensorTemp, TEMPERATUR_SENSOR_WATER, String(temp));
Serial << "Water Temperatur " << temp << " °C " << endl; Serial << "Water Temperatur " << temp << " °C " << endl;
waterTemp = temp;
} }
/* Always send the sensor address with the temperatur value */ /* Always send the sensor address with the temperatur value */
mqttWrite(&sensorTemp, String(buf), String(temp)); mqttWrite(&sensorTemp, String(buf), String(temp));
@ -401,10 +404,7 @@ void onHomieEvent(const HomieEvent &event)
{ {
mPlants[i].deactivatePump(); mPlants[i].deactivatePump();
} }
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); otaRunning = true;
digitalWrite(OUTPUT_ENABLE_PUMP, HIGH);
delay(100);
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1);
mDownloadMode = true; mDownloadMode = true;
break; break;
case HomieEventType::OTA_SUCCESSFUL: case HomieEventType::OTA_SUCCESSFUL:
@ -461,7 +461,7 @@ int determineNextPump(bool isLowLight)
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;
} }
if (!plant.isHydroponic()) if (! (plant.isHydroponic() || plant.isTimerOnly()))
{ {
if (equalish(plant.getCurrentMoistureRaw(), MISSING_SENSOR)) if (equalish(plant.getCurrentMoistureRaw(), MISSING_SENSOR))
{ {
@ -493,10 +493,9 @@ int determineNextPump(bool isLowLight)
}else { }else {
plant.publishState("active"); plant.publishState("active");
} }
} }
if (!plant.isHydroponic()) if (! (plant.isHydroponic() || plant.isTimerOnly()))
{ {
consecutiveWateringPlant[i]++; consecutiveWateringPlant[i]++;
} }
@ -522,7 +521,7 @@ int determineNextPump(bool isLowLight)
else else
{ {
plant.publishState("wet"); plant.publishState("wet");
//plant was detected as wet, remove consecutive count // plant was detected as wet, remove consecutive count
consecutiveWateringPlant[i] = 0; consecutiveWateringPlant[i] = 0;
} }
} }
@ -608,12 +607,12 @@ bool switch7(const HomieRange &range, const String &value)
void initPumpLogic() void initPumpLogic()
{ {
//set targets // set targets
#ifdef FLOWMETER_PIN #ifdef FLOWMETER_PIN
pumpTargetMl = mPlants[pumpToRun].getPumpMl(); pumpTargetMl = mPlants[pumpToRun].getPumpMl();
//0-6 are used for moisture measurment // 0-6 are used for moisture measurment
pcnt_unit_t unit = (pcnt_unit_t)(PCNT_UNIT_7); pcnt_unit_t unit = (pcnt_unit_t)(PCNT_UNIT_7);
pcnt_config_t pcnt_config = {}; // Instancia PCNT config pcnt_config_t pcnt_config = {}; // Instancia PCNT config
pcnt_config.pulse_gpio_num = FLOWMETER_PIN; // Configura GPIO para entrada dos pulsos pcnt_config.pulse_gpio_num = FLOWMETER_PIN; // Configura GPIO para entrada dos pulsos
@ -639,7 +638,7 @@ void initPumpLogic()
#endif #endif
//enable power // enable power
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
digitalWrite(OUTPUT_ENABLE_PUMP, HIGH); digitalWrite(OUTPUT_ENABLE_PUMP, HIGH);
delay(100); delay(100);
@ -666,7 +665,7 @@ void pumpActiveLoop()
mqttUpdateTick = true; mqttUpdateTick = true;
} }
long duration = millis() - pumpStartTime; long duration = millis() - pumpStartTime;
#ifdef FLOWMETER_PIN #ifdef FLOWMETER_PIN
int16_t pulses; int16_t pulses;
pcnt_unit_t unit = (pcnt_unit_t)(PCNT_UNIT_7); pcnt_unit_t unit = (pcnt_unit_t)(PCNT_UNIT_7);
@ -676,11 +675,10 @@ long duration = millis() - pumpStartTime;
log(LOG_LEVEL_ERROR, LOG_HARDWARECOUNTER_ERROR_MESSAGE, LOG_HARDWARECOUNTER_ERROR_CODE); log(LOG_LEVEL_ERROR, LOG_HARDWARECOUNTER_ERROR_MESSAGE, LOG_HARDWARECOUNTER_ERROR_CODE);
targetReached = true; targetReached = true;
log(LOG_LEVEL_INFO, "Reached pump target ml " + String(pumpToRun), LOG_PUMP_STARTED_CODE); log(LOG_LEVEL_INFO, "Reached pump target ml " + String(pumpToRun), LOG_PUMP_STARTED_CODE);
} }
else else
{ {
float mLPumped = pulses/FLOWMETER_PULSES_PER_ML; //mLperMs*duration; float mLPumped = pulses / FLOWMETER_PULSES_PER_ML; // mLperMs*duration;
if (mLPumped >= pumpTargetMl) if (mLPumped >= pumpTargetMl)
{ {
targetReached = true; targetReached = true;
@ -697,7 +695,6 @@ long duration = millis() - pumpStartTime;
} }
#endif #endif
if (millis() > pumpTarget) if (millis() > pumpTarget)
{ {
mPlants[pumpToRun].setProperty("watertime").send(String(duration)); mPlants[pumpToRun].setProperty("watertime").send(String(duration));
@ -711,12 +708,12 @@ long duration = millis() - pumpStartTime;
if (targetReached) if (targetReached)
{ {
//disable all // disable all
digitalWrite(OUTPUT_ENABLE_PUMP, LOW); digitalWrite(OUTPUT_ENABLE_PUMP, LOW);
mPlants[pumpToRun].deactivatePump(); mPlants[pumpToRun].deactivatePump();
//disable loop, to prevent multi processing // disable loop, to prevent multi processing
pumpStarted = false; pumpStarted = false;
//if runtime is larger than cooldown, else it would run continously // if runtime is larger than cooldown, else it would run continously
rtcLastWateringPlant[pumpToRun] = getCurrentTime(); rtcLastWateringPlant[pumpToRun] = getCurrentTime();
espDeepSleep(true); espDeepSleep(true);
} }
@ -733,7 +730,7 @@ void safeSetup()
WiFi.mode(WIFI_OFF); WiFi.mode(WIFI_OFF);
Serial.flush(); Serial.flush();
//restore state before releasing pin, to prevent flickering // restore state before releasing pin, to prevent flickering
#if defined(TIMED_LIGHT_PIN) #if defined(TIMED_LIGHT_PIN)
ulp_pwm_init(); ulp_pwm_init();
#endif // TIMED_LIGHT_PIN #endif // TIMED_LIGHT_PIN
@ -753,15 +750,17 @@ void safeSetup()
pinMode(OUTPUT_ENABLE_SENSOR, OUTPUT); pinMode(OUTPUT_ENABLE_SENSOR, OUTPUT);
static_assert(HomieInternals::MAX_CONFIG_SETTING_SIZE >= MAX_CONFIG_SETTING_ITEMS, "Limits.hpp not adjusted MAX_CONFIG_SETTING_ITEMS");
if (HomieInternals::MAX_CONFIG_SETTING_SIZE < MAX_CONFIG_SETTING_ITEMS) if (HomieInternals::MAX_CONFIG_SETTING_SIZE < MAX_CONFIG_SETTING_ITEMS)
{ {
//increase the config settings // increase the config settings
Serial << "Limits.hpp is not adjusted, please search for this string and increase" << endl; Serial << "Limits.hpp is not adjusted, please search for this string and increase" << endl;
return; return;
} }
static_assert(HomieInternals::MAX_JSON_CONFIG_FILE_SIZE >= MAX_JSON_CONFIG_FILE_SIZE_CUSTOM, "Limits.hpp not adjusted MAX_JSON_CONFIG_FILE_SIZE");
if (HomieInternals::MAX_JSON_CONFIG_FILE_SIZE < MAX_JSON_CONFIG_FILE_SIZE_CUSTOM) if (HomieInternals::MAX_JSON_CONFIG_FILE_SIZE < MAX_JSON_CONFIG_FILE_SIZE_CUSTOM)
{ {
//increase the config settings // increase the config settings
Serial << "Limits.hpp is not adjusted, please search for this string and increase" << endl; Serial << "Limits.hpp is not adjusted, please search for this string and increase" << endl;
return; return;
} }
@ -772,7 +771,7 @@ void safeSetup()
Homie_setBrand("PlantControl"); Homie_setBrand("PlantControl");
// Set default values // Set default values
//in seconds // in seconds
deepSleepTime.setDefaultValue(600).setValidator([](long candidate) deepSleepTime.setDefaultValue(600).setValidator([](long candidate)
{ return (candidate > 0) && (candidate < (60 * 60 * 2) /** 2h max sleep */); }); { return (candidate > 0) && (candidate < (60 * 60 * 2) /** 2h max sleep */); });
deepSleepNightTime.setDefaultValue(600); deepSleepNightTime.setDefaultValue(600);
@ -809,14 +808,12 @@ void safeSetup()
} }
readPowerSwitchedSensors(); readPowerSwitchedSensors();
Homie.setup(); Homie.setup();
Wire = TwoWire(0); Wire = TwoWire(0);
Wire.setPins(SENSOR_TANK_SDA, SENSOR_TANK_SCL); Wire.setPins(SENSOR_TANK_SDA, SENSOR_TANK_SCL);
Wire.begin(); Wire.begin();
/************************* Start One-Wire bus ***************/ /************************* Start One-Wire bus ***************/
int tempInitStartTime = millis(); int tempInitStartTime = millis();
uint8_t sensorCount = 0U; uint8_t sensorCount = 0U;
@ -835,7 +832,7 @@ void safeSetup()
/* Measure temperature TODO idea: move this into setup */ /* Measure temperature TODO idea: move this into setup */
if (sensorCount > 0) if (sensorCount > 0)
{ {
//sensors.setResolution(DS18B20_RESOLUTION); // sensors.setResolution(DS18B20_RESOLUTION);
sensors.requestTemperatures(); sensors.requestTemperatures();
} }
@ -905,7 +902,7 @@ void safeSetup()
} }
readOneWireSensors(); readOneWireSensors();
//prevent BOD to be paranoid // prevent BOD to be paranoid
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
digitalWrite(OUTPUT_ENABLE_PUMP, HIGH); digitalWrite(OUTPUT_ENABLE_PUMP, HIGH);
delay(100); delay(100);
@ -981,7 +978,14 @@ void loop()
digitalWrite(OUTPUT_ENABLE_SENSOR, !digitalRead(OUTPUT_ENABLE_SENSOR)); digitalWrite(OUTPUT_ENABLE_SENSOR, !digitalRead(OUTPUT_ENABLE_SENSOR));
if (mConfigured) if (mConfigured)
{ {
nextBlink = millis() + 500; if (otaRunning)
{
nextBlink = millis() + 100;
}
else
{
nextBlink = millis() + 501;
}
} }
else else
{ {
@ -1078,12 +1082,14 @@ void plantcontrol()
#endif // TIMED_LIGHT_PIN #endif // TIMED_LIGHT_PIN
bool hasWater = true; //FIXME remaining > waterLevelMin.get(); bool isLiquid = waterTemp > 5;
//FIXME no water warning message bool hasWater = true; // FIXME remaining > waterLevelMin.get();
// FIXME no water warning message
pumpToRun = determineNextPump(isLowLight); pumpToRun = determineNextPump(isLowLight);
//early aborts // early aborts
if (pumpToRun != -1) if (pumpToRun != -1)
{ {
if(isLiquid){
if (hasWater) if (hasWater)
{ {
if (mDownloadMode) if (mDownloadMode)
@ -1098,6 +1104,11 @@ void plantcontrol()
pumpToRun = -1; pumpToRun = -1;
} }
} }
else{
log(LOG_LEVEL_ERROR, LOG_PUMP_BUTNOTANK_MESSAGE, LOG_PUMP_BUTNOTANK_CODE);
pumpToRun = -1;
}
}
// go directly to sleep, skipping the pump loop // go directly to sleep, skipping the pump loop
if (pumpToRun == -1) if (pumpToRun == -1)
@ -1115,7 +1126,7 @@ bool determineTimedLightState(bool lowLight)
long hoursStart = timedLightStart.get(); long hoursStart = timedLightStart.get();
long hoursEnd = timedLightEnd.get(); long hoursEnd = timedLightEnd.get();
//ntp missing // ntp missing
if (getCurrentTime() < 10000) if (getCurrentTime() < 10000)
{ {
timedLightNode.setProperty("state").send(String("Off, missing ntp")); timedLightNode.setProperty("state").send(String("Off, missing ntp"));
@ -1129,9 +1140,11 @@ bool determineTimedLightState(bool lowLight)
} }
int curHour = getCurrentHour(); int curHour = getCurrentHour();
bool condition1 = ((hoursStart > hoursEnd) && bool condition1 = ((hoursStart > hoursEnd) &&
(curHour >= hoursStart || curHour <= hoursEnd)); (curHour >= hoursStart || curHour <= hoursEnd));
bool condition2 = /* Handle e.g. start = 8, end = 21 */ bool condition2 = /* Handle e.g. start = 8, end = 21 */
((hoursStart < hoursEnd) && ((hoursStart < hoursEnd) &&
(curHour >= hoursStart && curHour <= hoursEnd)); (curHour >= hoursStart && curHour <= hoursEnd));
timedLightNode.setProperty("debug").send(String(curHour) + " " + String(hoursStart) + " " + String(hoursEnd) + " " + String(condition1) + " " + String(condition2)); timedLightNode.setProperty("debug").send(String(curHour) + " " + String(hoursStart) + " " + String(hoursEnd) + " " + String(condition1) + " " + String(condition2));