/* SCHEDULER MODULE Copyright (C) 2017 by faina09 Adapted by Xose PĂ©rez */ #if SCHEDULER_SUPPORT #include // ----------------------------------------------------------------------------- #if WEB_SUPPORT void _schWebSocketOnSend(JsonObject &root){ root["schVisible"] = 1; root["maxSchedules"] = SCHEDULER_MAX_SCHEDULES; JsonArray &sch = root.createNestedArray("schedule"); for (byte i = 0; i < SCHEDULER_MAX_SCHEDULES; i++) { if (!hasSetting("schSwitch", i)) break; JsonObject &scheduler = sch.createNestedObject(); scheduler["schEnabled"] = getSetting("schEnabled", i, 1).toInt() == 1; scheduler["schSwitch"] = getSetting("schSwitch", i, 0).toInt(); scheduler["schAction"] = getSetting("schAction", i, 0).toInt(); scheduler["schType"] = getSetting("schType", i, 0); scheduler["schHour"] = getSetting("schHour", i, 0).toInt(); scheduler["schMinute"] = getSetting("schMinute", i, 0).toInt(); scheduler["schWDs"] = getSetting("schWDs", i, ""); } } #endif // WEB_SUPPORT // ----------------------------------------------------------------------------- void _schConfigure() { bool delete_flag = false; for (unsigned char i = 0; i < SCHEDULER_MAX_SCHEDULES; i++) { int sch_switch = getSetting("schSwitch", i, 0xFF).toInt(); if (sch_switch == 0xFF) delete_flag = true; if (delete_flag) { delSetting("schEnabled", i); delSetting("schSwitch", i); delSetting("schAction", i); delSetting("schHour", i); delSetting("schMinute", i); delSetting("schWDs", i); delSetting("schType", i); } else { #if DEBUG_SUPPORT int sch_enabled = getSetting("schEnabled", i, 1).toInt() == 1; int sch_action = getSetting("schAction", i, 0).toInt(); int sch_hour = getSetting("schHour", i, 0).toInt(); int sch_minute = getSetting("schMinute", i, 0).toInt(); String sch_weekdays = getSetting("schWDs", i, ""); DEBUG_MSG_P( PSTR("[SCH] Schedule #%d: %s switch #%d at %02d:%02d on %s%s\n"), i, sch_action == 0 ? "turn OFF" : sch_action == 1 ? "turn ON" : "toggle", sch_switch, sch_hour, sch_minute, (char *) sch_weekdays.c_str(), sch_enabled ? "" : " (disabled)" ); #endif // DEBUG_SUPPORT } } } bool _schIsThisWeekday(String weekdays){ // Convert from Sunday to Monday as day 1 int w = weekday(now()) - 1; if (w == 0) w = 7; char pch; char * p = (char *) weekdays.c_str(); unsigned char position = 0; while (pch = p[position++]) { if ((pch - '0') == w) return true; } return false; } int _schMinutesLeft(unsigned char schedule_hour, unsigned char schedule_minute){ time_t t = now(); unsigned char now_hour = hour(t); unsigned char now_minute = minute(t); return (schedule_hour - now_hour) * 60 + schedule_minute - now_minute; } void _schCheck() { // Check schedules for (unsigned char i = 0; i < SCHEDULER_MAX_SCHEDULES; i++) { int sch_switch = getSetting("schSwitch", i, 0xFF).toInt(); if (sch_switch == 0xFF) break; // Skip disabled schedules if (getSetting("schEnabled", i, 1).toInt() == 0) continue; String sch_weekdays = getSetting("schWDs", i, ""); if (_schIsThisWeekday(sch_weekdays)) { int sch_hour = getSetting("schHour", i, 0).toInt(); int sch_minute = getSetting("schMinute", i, 0).toInt(); int minutes_to_trigger = _schMinutesLeft(sch_hour, sch_minute); if (minutes_to_trigger == 0) { if (getSetting("schType", i, "") == "light") { int sch_brightness = getSetting("schAction", i, -1).toInt(); DEBUG_MSG_P(PSTR("[SCH] Switching light %d to %d\n"), sch_switch, sch_brightness); #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE lightChannel(sch_switch, sch_brightness); lightUpdate(true, true); #endif } else { int sch_action = getSetting("schAction", i, 0).toInt(); DEBUG_MSG_P(PSTR("[SCH] Switching switch %d to %d\n"), sch_switch, sch_action); if (sch_action == 2) { relayToggle(sch_switch); } else { relayStatus(sch_switch, sch_action); } } DEBUG_MSG_P(PSTR("[SCH] Schedule #%d TRIGGERED!!\n"), i); // Show minutes to trigger every 15 minutes // or every minute if less than 15 minutes to scheduled time. // This only works for schedules on this same day. // For instance, if your scheduler is set for 00:01 you will only // get one notification before the trigger (at 00:00) } else if (minutes_to_trigger > 0) { #if DEBUG_SUPPORT if ((minutes_to_trigger % 15 == 0) || (minutes_to_trigger < 15)) { DEBUG_MSG_P( PSTR("[SCH] %d minutes to trigger schedule #%d\n"), minutes_to_trigger, sch_switch ); } #endif } } } } void _schLoop() { // Check time has been sync'ed if (!ntpSynced()) return; // Check schedules every minute at hh:mm:00 static unsigned long last_minute = 60; unsigned char current_minute = minute(); if (current_minute != last_minute) { last_minute = current_minute; _schCheck(); } } // ----------------------------------------------------------------------------- void schSetup() { _schConfigure(); // Update websocket clients #if WEB_SUPPORT wsOnSendRegister(_schWebSocketOnSend); wsOnAfterParseRegister(_schConfigure); #endif // Register loop espurnaRegisterLoop(_schLoop); } #endif // SCHEDULER_SUPPORT