diff --git a/release/aqualinkd-amd64 b/release/aqualinkd-amd64 deleted file mode 100755 index 1d74ff0..0000000 Binary files a/release/aqualinkd-amd64 and /dev/null differ diff --git a/release/aqualinkd-arm64 b/release/aqualinkd-arm64 index 9c2c011..e9bc84e 100755 Binary files a/release/aqualinkd-arm64 and b/release/aqualinkd-arm64 differ diff --git a/release/aqualinkd-armhf b/release/aqualinkd-armhf index 784afa8..9c87253 100755 Binary files a/release/aqualinkd-armhf and b/release/aqualinkd-armhf differ diff --git a/release/aqualinkd.conf b/release/aqualinkd.conf index 8e0fa60..2d46275 100755 --- a/release/aqualinkd.conf +++ b/release/aqualinkd.conf @@ -163,7 +163,9 @@ enable_scheduler = yes # Check if button_01 (usually Pump) is scheduled to run after an event that may have turned it off, and set it to run. # Only for RS panels, Will not work for PDA panles. -# Example below is if pump is off due to power reset, freezeprotect/swg boots turned off between 6am and 11pm turn the pump on. +# Example below is if pump is off due to power reset, freezeprotect or swg boots is turned off between 6am and 11pm then turn the pump on. +# You can leave scheduler_check_pumpon_hour & scheduler_check_pumpoff_hour commented out and AqualinkD will try to find the hours from the actual schedule +# that's been set in scheduler. This only works if you have the same schedule for every day of the week. #scheduler_check_pumpon_hour = 6 #scheduler_check_pumpoff_hour = 23 #scheduler_check_poweron = yes diff --git a/release/serial_logger-amd64 b/release/serial_logger-amd64 deleted file mode 100755 index 01a22e3..0000000 Binary files a/release/serial_logger-amd64 and /dev/null differ diff --git a/release/serial_logger-arm64 b/release/serial_logger-arm64 index 6c72b92..33210a8 100755 Binary files a/release/serial_logger-arm64 and b/release/serial_logger-arm64 differ diff --git a/release/serial_logger-armhf b/release/serial_logger-armhf index 11809e4..7bf732c 100755 Binary files a/release/serial_logger-armhf and b/release/serial_logger-armhf differ diff --git a/source/allbutton.c b/source/allbutton.c index f3c7531..f836e50 100644 --- a/source/allbutton.c +++ b/source/allbutton.c @@ -227,7 +227,7 @@ void _processMessage(char *message, struct aqualinkdata *aq_data, bool reset) if ((msg_loop & MSG_FREEZE) != MSG_FREEZE) { if (aq_data->frz_protect_state != default_frz_protect_state) { LOG(ALLB_LOG,LOG_INFO, "Freeze protect turned off\n"); - event_happened_set_device_state(FREEZE_PROTECT_OFF, aq_data); + event_happened_set_device_state(AQS_FRZ_PROTECT_OFF, aq_data); // Add code to check Pump if to turn it on (was scheduled) ie time now is inbetween ON / OFF schedule } aq_data->frz_protect_state = default_frz_protect_state; @@ -286,7 +286,7 @@ void _processMessage(char *message, struct aqualinkdata *aq_data, bool reset) if ((msg_loop & MSG_BOOST) != MSG_BOOST) { if (aq_data->boost == true) { LOG(ALLB_LOG,LOG_INFO, "Boost turned off\n"); - event_happened_set_device_state(BOOST_OFF, aq_data); + event_happened_set_device_state(AQS_BOOST_OFF, aq_data); // Add code to check Pump if to turn it on (was scheduled) ie time now is inbetween ON / OFF schedule } aq_data->boost = false; @@ -515,7 +515,7 @@ void _processMessage(char *message, struct aqualinkdata *aq_data, bool reset) { //LOG(ALLBUTTON,LOG_NOTICE, "Standard protocol initialization complete\n"); queueGetProgramData(ALLBUTTON, aq_data); - event_happened_set_device_state(POWER_ON, aq_data); + event_happened_set_device_state(AQS_POWER_ON, aq_data); //queueGetExtendedProgramData(ALLBUTTON, aq_data, _aqconfig_.use_panel_aux_labels); _initWithRS = true; } diff --git a/source/aq_scheduler.c b/source/aq_scheduler.c index 908eacd..d822d3d 100644 --- a/source/aq_scheduler.c +++ b/source/aq_scheduler.c @@ -201,7 +201,8 @@ int build_schedules_js(char* buffer, int size) if ( !_aqconfig_.enable_scheduler) { LOG(SCHD_LOG,LOG_WARNING, "Schedules are disabled\n"); - length += sprintf(buffer, "{\"message\":\"Error Schedules disabled\"}"); + if (size > 0) + length += sprintf(buffer, "{\"message\":\"Error Schedules disabled\"}"); return length; } @@ -220,22 +221,26 @@ int build_schedules_js(char* buffer, int size) regmatch_t groupArray[maxGroups]; //static char buf[100]; - length += sprintf(buffer+length,"{\"type\": \"schedules\","); + if (size > 0) + length += sprintf(buffer+length,"{\"type\": \"schedules\","); if (0 != (rc = regcomp(®exCompiled, regexString, REG_EXTENDED))) { LOG(SCHD_LOG,LOG_ERR, "regcomp() failed, returning nonzero (%d)\n", rc); - length += sprintf(buffer+length,"\"message\": \"Error reading schedules\"}"); + if (size > 0) + length += sprintf(buffer+length,"\"message\": \"Error reading schedules\"}"); return length; } fp = fopen(CRON_FILE, "r"); if (fp == NULL) { LOG(SCHD_LOG,LOG_WARNING, "Open file failed '%s'\n", CRON_FILE); - length += sprintf(buffer+length,"\"message\": \"Error reading schedules\"}"); + if (size > 0) + length += sprintf(buffer+length,"\"message\": \"Error reading schedules\"}"); return length; } - length += sprintf(buffer+length,"\"schedules\": [ "); + if (size > 0) + length += sprintf(buffer+length,"\"schedules\": [ "); while ((read_size = getline(&line, &len, fp)) != -1) { //printf("Read from cron:-\n %s", line); @@ -264,7 +269,8 @@ int build_schedules_js(char* buffer, int size) sprintf(cline.url, "%.*s", (groupArray[9].rm_eo - groupArray[9].rm_so), (line + groupArray[9].rm_so)); sprintf(cline.value, "%.*s", (groupArray[10].rm_eo - groupArray[10].rm_so), (line + groupArray[10].rm_so)); LOG(SCHD_LOG,LOG_INFO, "Read from cron. Enabled:%d Min:%s Hour:%s DayM:%s Month:%s DayW:%s URL:%s Value:%s\n",cline.enabled,cline.minute,cline.hour,cline.daym,cline.month,cline.dayw,cline.url,cline.value); - length += sprintf(buffer+length, "{\"enabled\":\"%d\", \"min\":\"%s\",\"hour\":\"%s\",\"daym\":\"%s\",\"month\":\"%s\",\"dayw\":\"%s\",\"url\":\"%s\",\"value\":\"%s\"},", + if (size > 0) { + length += sprintf(buffer+length, "{\"enabled\":\"%d\", \"min\":\"%s\",\"hour\":\"%s\",\"daym\":\"%s\",\"month\":\"%s\",\"dayw\":\"%s\",\"url\":\"%s\",\"value\":\"%s\"},", cline.enabled, cline.minute, cline.hour, @@ -273,15 +279,35 @@ int build_schedules_js(char* buffer, int size) cline.dayw, cline.url, cline.value); + } //LOG(SCHD_LOG,LOG_DEBUG, "Read from cron Day %d | Time %d:%d | Zone %d | Runtime %d\n",day,hour,minute,zone,runtime); + + // Test / get for pump start and end time + if (isAQS_USE_PUMP_TIME_FROM_CRON_ENABLED) { + // Could also check that dayw is * + if ( cline.enabled && strstr(cline.url, AQS_PUMP_URL )) + { + int value = strtoul(cline.value, NULL, 10); + int hour = strtoul(cline.hour, NULL, 10); + if (value == 0) { + if (hour > _aqconfig_.sched_chk_pumpoff_hour) // NSF this picks up the greatest offhour, (do we want the smallest???) + _aqconfig_.sched_chk_pumpoff_hour = hour; + } else if (value == 1){ + if (hour < _aqconfig_.sched_chk_pumpon_hour || _aqconfig_.sched_chk_pumpon_hour == 0) + _aqconfig_.sched_chk_pumpon_hour = hour; + } + } + } } } else { LOG(SCHD_LOG,LOG_DEBUG, "regexp no match (%d) %s\n", rc, line); } } - buffer[--length] = '\0'; - length += sprintf(buffer+length,"]}\n"); + if (size > 0) { + buffer[--length] = '\0'; + length += sprintf(buffer+length,"]}\n"); + } fclose(fp); regfree(®exCompiled); @@ -289,11 +315,27 @@ int build_schedules_js(char* buffer, int size) return length; } +void get_cron_pump_times() +{ + build_schedules_js(NULL, 0); + return; +} + + bool event_happened_set_device_state(reset_event_type type, struct aqualinkdata *aq_data) { + if (! isAQS_START_PUMP_EVENT_ENABLED) { + LOG(SCHD_LOG,LOG_DEBUG, "Event scheduler is not enabled\n"); + return false; + } // Check time is between hours. bool scheduledOn = false; + if (isAQS_USE_PUMP_TIME_FROM_CRON_ENABLED) { + get_cron_pump_times(); + LOG(SCHD_LOG,LOG_DEBUG, "Pump on times from scheduler are between hours %.2d & %.2d\n",_aqconfig_.sched_chk_pumpon_hour, _aqconfig_.sched_chk_pumpoff_hour); + } + time_t now = time(NULL); struct tm *tm_struct = localtime(&now); @@ -304,28 +346,31 @@ bool event_happened_set_device_state(reset_event_type type, struct aqualinkdata // Check event type. switch(type){ - case POWER_ON: - if (scheduledOn && _aqconfig_.sched_chk_poweron && aq_data->aqbuttons[0].led->state == OFF) { + case AQS_POWER_ON: + if (scheduledOn && isAQS_POWER_ON_ENABED && aq_data->aqbuttons[0].led->state == OFF) { LOG(SCHD_LOG,LOG_INFO, "Powered on, schedule is set for pump running and pump is off, turning pump on\n"); panel_device_request(aq_data, ON_OFF, 0, true, NET_TIMER); } else { - LOG(SCHD_LOG,LOG_DEBUG, "Powered on, schedule is not set and/or pump is already on, leaving\n"); + //LOG(SCHD_LOG,LOG_DEBUG, "Powered on, schedule is not set and/or pump is already on, leaving\n"); + LOG(SCHD_LOG,LOG_DEBUG, "Powered on, schedule Pump on is %sset, time is %sbetween scheduled hours, Pump is %s, (not changing)\n",(isAQS_POWER_ON_ENABED?"":"not "),(scheduledOn?"":" not"), (aq_data->aqbuttons[0].led->state ==OFF?"Off":"On")); } break; - case FREEZE_PROTECT_OFF: - if (scheduledOn && _aqconfig_.sched_chk_freezeprotectoff && aq_data->aqbuttons[0].led->state == OFF) { + case AQS_FRZ_PROTECT_OFF: + if (scheduledOn && isAQS_FRZ_PROTECT_OFF_ENABED && aq_data->aqbuttons[0].led->state == OFF) { LOG(SCHD_LOG,LOG_INFO, "Freeze Protect off, schedule is set for pump running and pump is off, turning pump on\n"); panel_device_request(aq_data, ON_OFF, 0, true, NET_TIMER); } else { - LOG(SCHD_LOG,LOG_DEBUG, "Freeze Protect off, schedule is not set and/or pump is already on, leaving\n"); + //LOG(SCHD_LOG,LOG_DEBUG, "Freeze Protect off, schedule is not set and/or pump is already on, leaving\n"); + LOG(SCHD_LOG,LOG_DEBUG, "Freeze Protect off, schedule Pump on is %sset, time is %sbetween scheduled hours, Pump is %s, (not changing)\n",(isAQS_FRZ_PROTECT_OFF_ENABED?"":"not "),(scheduledOn?"":" not"), (aq_data->aqbuttons[0].led->state ==OFF?"Off":"On")); } break; - case BOOST_OFF: - if (scheduledOn && _aqconfig_.sched_chk_boostoff && aq_data->aqbuttons[0].led->state == OFF) { + case AQS_BOOST_OFF: + if (scheduledOn && isAQS_BOOST_OFF_ENABED && aq_data->aqbuttons[0].led->state == OFF) { LOG(SCHD_LOG,LOG_INFO, "Boost off, schedule is set for pump running and pump is off, turning pump on\n"); panel_device_request(aq_data, ON_OFF, 0, true, NET_TIMER); } else { - LOG(SCHD_LOG,LOG_DEBUG, "Boost off, schedule is not set and/or pump is already on, leaving\n"); + //LOG(SCHD_LOG,LOG_DEBUG, "Boost off, schedule is not set and/or pump is already on, leaving\n"); + LOG(SCHD_LOG,LOG_DEBUG, "Boost off, schedule Pump on is %sset, time is %sbetween scheduled hours, Pump is %s, (not changing)\n",(isAQS_BOOST_OFF_ENABED?"":"not "),(scheduledOn?"":" not"), (aq_data->aqbuttons[0].led->state ==OFF?"Off":"On")); } break; } diff --git a/source/aq_scheduler.h b/source/aq_scheduler.h index 88804d2..299e7d3 100644 --- a/source/aq_scheduler.h +++ b/source/aq_scheduler.h @@ -5,6 +5,7 @@ #ifndef AQ_SCHEDULER_H_ #define AQ_SCHEDULER_H_ +#include "config.h" #define CRON_FILE "/etc/cron.d/aqualinkd" #define CURL "curl" @@ -26,12 +27,31 @@ typedef struct aqs_cron int build_schedules_js(char* buffer, int size); int save_schedules_js(const char* inBuf, int inSize, char* outBuf, int outSize); + +#define AQS_PUMP_URL BTN_PUMP "/set" + +#define AQS_DONT_USE_CRON_PUMP_TIME (1 << 0) +typedef enum reset_event_type{ + AQS_POWER_ON = (1 << 1), + AQS_FRZ_PROTECT_OFF = (1 << 2), + AQS_BOOST_OFF = (1 << 3) +} reset_event_type; + +#define isAQS_START_PUMP_EVENT_ENABLED ( ((_aqconfig_.schedule_event_mask & AQS_POWER_ON) == AQS_POWER_ON) || \ + ((_aqconfig_.schedule_event_mask & AQS_FRZ_PROTECT_OFF) == AQS_FRZ_PROTECT_OFF) || \ + ((_aqconfig_.schedule_event_mask & AQS_BOOST_OFF) == AQS_BOOST_OFF) ) + +#define isAQS_USE_PUMP_TIME_FROM_CRON_ENABLED !((_aqconfig_.schedule_event_mask & AQS_DONT_USE_CRON_PUMP_TIME) == AQS_DONT_USE_CRON_PUMP_TIME) +#define isAQS_POWER_ON_ENABED ((_aqconfig_.schedule_event_mask & AQS_POWER_ON) == AQS_POWER_ON) +#define isAQS_FRZ_PROTECT_OFF_ENABED ((_aqconfig_.schedule_event_mask & AQS_FRZ_PROTECT_OFF) == AQS_FRZ_PROTECT_OFF) +#define isAQS_BOOST_OFF_ENABED ((_aqconfig_.schedule_event_mask & AQS_BOOST_OFF) == AQS_BOOST_OFF) +/* typedef enum reset_event_type{ POWER_ON, FREEZE_PROTECT_OFF, BOOST_OFF } reset_event_type; - +*/ bool event_happened_set_device_state(reset_event_type type, struct aqualinkdata *aq_data); //void read_schedules(); //void write_schedules(); diff --git a/source/config.c b/source/config.c index 1665659..25fea68 100644 --- a/source/config.c +++ b/source/config.c @@ -42,6 +42,7 @@ #include "aqualink.h" #include "iaqualink.h" #include "color_lights.h" +#include "aq_scheduler.h" #define MAXCFGLINE 256 @@ -156,9 +157,10 @@ void init_parameters (struct aqconfig * parms) parms->enable_scheduler = true; - parms->sched_chk_poweron = false; - parms->sched_chk_freezeprotectoff = false; - parms->sched_chk_boostoff = false; + parms->schedule_event_mask = 0; + //parms->sched_chk_poweron = false; + //parms->sched_chk_freezeprotectoff = false; + //parms->sched_chk_boostoff = false; parms->sched_chk_pumpon_hour = 0; parms->sched_chk_pumpoff_hour = 0; @@ -690,19 +692,27 @@ bool setConfigValue(struct aqualinkdata *aqdata, char *param, char *value) { _aqconfig_.enable_scheduler = text2bool(value); rtn=true; } else if (strncasecmp (param, "scheduler_check_poweron", 23) == 0) { - _aqconfig_.sched_chk_poweron = text2bool(value); + if (text2bool(value)) { + _aqconfig_.schedule_event_mask |= AQS_POWER_ON; + } rtn=true; } else if (strncasecmp (param, "scheduler_check_freezeprotectoff", 32) == 0) { - _aqconfig_.sched_chk_freezeprotectoff = text2bool(value); + if (text2bool(value)) { + _aqconfig_.schedule_event_mask |= AQS_FRZ_PROTECT_OFF; + } rtn=true; } else if (strncasecmp (param, "scheduler_check_boostoff", 24) == 0) { - _aqconfig_.sched_chk_boostoff = text2bool(value); + if (text2bool(value)) { + _aqconfig_.schedule_event_mask |= AQS_BOOST_OFF; + } rtn=true; } else if (strncasecmp (param, "scheduler_check_pumpon_hour", 27) == 0) { _aqconfig_.sched_chk_pumpon_hour = strtoul(value, NULL, 10); + _aqconfig_.schedule_event_mask |= AQS_DONT_USE_CRON_PUMP_TIME; rtn=true; } else if (strncasecmp (param, "scheduler_check_pumpoff_hour", 28) == 0) { _aqconfig_.sched_chk_pumpoff_hour = strtoul(value, NULL, 10); + _aqconfig_.schedule_event_mask |= AQS_DONT_USE_CRON_PUMP_TIME; rtn=true; } else if (strncasecmp (param, "ftdi_low_latency", 16) == 0) { _aqconfig_.ftdi_low_latency = text2bool(value); diff --git a/source/config.h b/source/config.h index 0c51acb..052821a 100644 --- a/source/config.h +++ b/source/config.h @@ -105,9 +105,10 @@ struct aqconfig bool mqtt_timed_update; bool sync_panel_time; bool enable_scheduler; - bool sched_chk_poweron; - bool sched_chk_freezeprotectoff; - bool sched_chk_boostoff; + int16_t schedule_event_mask; + //bool sched_chk_poweron; + //bool sched_chk_freezeprotectoff; + //bool sched_chk_boostoff; int sched_chk_pumpon_hour; int sched_chk_pumpoff_hour; bool ftdi_low_latency;