Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
6.6 KiB

6 years ago
  1. /*
  2. SCHEDULER MODULE
  3. Copyright (C) 2017 by faina09
  4. Adapted by Xose Pérez <xose dot perez at gmail dot com>
  5. */
  6. #if SCHEDULER_SUPPORT
  7. #include <TimeLib.h>
  8. // -----------------------------------------------------------------------------
  9. #if WEB_SUPPORT
  10. bool _schWebSocketOnReceive(const char * key, JsonVariant& value) {
  11. return (strncmp(key, "sch", 3) == 0);
  12. }
  13. void _schWebSocketOnSend(JsonObject &root){
  14. if (relayCount() > 0) {
  15. root["schVisible"] = 1;
  16. root["maxSchedules"] = SCHEDULER_MAX_SCHEDULES;
  17. JsonArray &sch = root.createNestedArray("schedule");
  18. for (byte i = 0; i < SCHEDULER_MAX_SCHEDULES; i++) {
  19. if (!hasSetting("schSwitch", i)) break;
  20. JsonObject &scheduler = sch.createNestedObject();
  21. scheduler["schEnabled"] = getSetting("schEnabled", i, 1).toInt() == 1;
  22. scheduler["schSwitch"] = getSetting("schSwitch", i, 0).toInt();
  23. scheduler["schAction"] = getSetting("schAction", i, 0).toInt();
  24. scheduler["schType"] = getSetting("schType", i, 0).toInt();
  25. scheduler["schHour"] = getSetting("schHour", i, 0).toInt();
  26. scheduler["schMinute"] = getSetting("schMinute", i, 0).toInt();
  27. scheduler["schWDs"] = getSetting("schWDs", i, "");
  28. }
  29. }
  30. }
  31. #endif // WEB_SUPPORT
  32. // -----------------------------------------------------------------------------
  33. void _schConfigure() {
  34. bool delete_flag = false;
  35. for (unsigned char i = 0; i < SCHEDULER_MAX_SCHEDULES; i++) {
  36. int sch_switch = getSetting("schSwitch", i, 0xFF).toInt();
  37. if (sch_switch == 0xFF) delete_flag = true;
  38. if (delete_flag) {
  39. delSetting("schEnabled", i);
  40. delSetting("schSwitch", i);
  41. delSetting("schAction", i);
  42. delSetting("schHour", i);
  43. delSetting("schMinute", i);
  44. delSetting("schWDs", i);
  45. delSetting("schType", i);
  46. } else {
  47. #if DEBUG_SUPPORT
  48. int sch_enabled = getSetting("schEnabled", i, 1).toInt() == 1;
  49. int sch_action = getSetting("schAction", i, 0).toInt();
  50. int sch_hour = getSetting("schHour", i, 0).toInt();
  51. int sch_minute = getSetting("schMinute", i, 0).toInt();
  52. String sch_weekdays = getSetting("schWDs", i, "");
  53. unsigned char sch_type = getSetting("schType", i, SCHEDULER_TYPE_SWITCH).toInt();
  54. DEBUG_MSG_P(
  55. PSTR("[SCH] Schedule #%d: %s #%d to %d at %02d:%02d on %s%s\n"),
  56. i, SCHEDULER_TYPE_SWITCH == sch_type ? "switch" : "channel", sch_switch,
  57. sch_action, sch_hour, sch_minute, (char *) sch_weekdays.c_str(),
  58. sch_enabled ? "" : " (disabled)"
  59. );
  60. #endif // DEBUG_SUPPORT
  61. }
  62. }
  63. }
  64. bool _schIsThisWeekday(String weekdays){
  65. // Convert from Sunday to Monday as day 1
  66. int w = weekday(now()) - 1;
  67. if (w == 0) w = 7;
  68. char pch;
  69. char * p = (char *) weekdays.c_str();
  70. unsigned char position = 0;
  71. while (pch = p[position++]) {
  72. if ((pch - '0') == w) return true;
  73. }
  74. return false;
  75. }
  76. int _schMinutesLeft(unsigned char schedule_hour, unsigned char schedule_minute){
  77. time_t t = now();
  78. unsigned char now_hour = hour(t);
  79. unsigned char now_minute = minute(t);
  80. return (schedule_hour - now_hour) * 60 + schedule_minute - now_minute;
  81. }
  82. void _schCheck() {
  83. // Check schedules
  84. for (unsigned char i = 0; i < SCHEDULER_MAX_SCHEDULES; i++) {
  85. int sch_switch = getSetting("schSwitch", i, 0xFF).toInt();
  86. if (sch_switch == 0xFF) break;
  87. // Skip disabled schedules
  88. if (getSetting("schEnabled", i, 1).toInt() == 0) continue;
  89. String sch_weekdays = getSetting("schWDs", i, "");
  90. if (_schIsThisWeekday(sch_weekdays)) {
  91. int sch_hour = getSetting("schHour", i, 0).toInt();
  92. int sch_minute = getSetting("schMinute", i, 0).toInt();
  93. int minutes_to_trigger = _schMinutesLeft(sch_hour, sch_minute);
  94. if (minutes_to_trigger == 0) {
  95. unsigned char sch_type = getSetting("schType", i, SCHEDULER_TYPE_SWITCH).toInt();
  96. if (SCHEDULER_TYPE_SWITCH == sch_type) {
  97. int sch_action = getSetting("schAction", i, 0).toInt();
  98. DEBUG_MSG_P(PSTR("[SCH] Switching switch %d to %d\n"), sch_switch, sch_action);
  99. if (sch_action == 2) {
  100. relayToggle(sch_switch);
  101. } else {
  102. relayStatus(sch_switch, sch_action);
  103. }
  104. }
  105. #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
  106. if (SCHEDULER_TYPE_DIM == sch_type) {
  107. int sch_brightness = getSetting("schAction", i, -1).toInt();
  108. DEBUG_MSG_P(PSTR("[SCH] Set channel %d value to %d\n"), sch_switch, sch_brightness);
  109. lightChannel(sch_switch, sch_brightness);
  110. lightUpdate(true, true);
  111. }
  112. #endif
  113. DEBUG_MSG_P(PSTR("[SCH] Schedule #%d TRIGGERED!!\n"), i);
  114. // Show minutes to trigger every 15 minutes
  115. // or every minute if less than 15 minutes to scheduled time.
  116. // This only works for schedules on this same day.
  117. // For instance, if your scheduler is set for 00:01 you will only
  118. // get one notification before the trigger (at 00:00)
  119. } else if (minutes_to_trigger > 0) {
  120. #if DEBUG_SUPPORT
  121. if ((minutes_to_trigger % 15 == 0) || (minutes_to_trigger < 15)) {
  122. DEBUG_MSG_P(
  123. PSTR("[SCH] %d minutes to trigger schedule #%d\n"),
  124. minutes_to_trigger, i
  125. );
  126. }
  127. #endif
  128. }
  129. }
  130. }
  131. }
  132. void _schLoop() {
  133. // Check time has been sync'ed
  134. if (!ntpSynced()) return;
  135. // Check schedules every minute at hh:mm:00
  136. static unsigned long last_minute = 60;
  137. unsigned char current_minute = minute();
  138. if (current_minute != last_minute) {
  139. last_minute = current_minute;
  140. _schCheck();
  141. }
  142. }
  143. // -----------------------------------------------------------------------------
  144. void schSetup() {
  145. _schConfigure();
  146. // Update websocket clients
  147. #if WEB_SUPPORT
  148. wsOnSendRegister(_schWebSocketOnSend);
  149. wsOnReceiveRegister(_schWebSocketOnReceive);
  150. wsOnAfterParseRegister(_schConfigure);
  151. #endif
  152. // Register loop
  153. espurnaRegisterLoop(_schLoop);
  154. }
  155. #endif // SCHEDULER_SUPPORT