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.

212 lines
6.5 KiB

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