From 00b08bc50912709f274bf2cea068b63ffa721019 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Wed, 25 Apr 2018 17:27:40 +0200 Subject: [PATCH] Add more timer user input checks --- sonoff/settings.h | 2 +- sonoff/webserver.ino | 4 +++ sonoff/xdrv_09_timers.ino | 70 ++++++++++++++++++++++++--------------- 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index dec5ef2fe..313ca3c6f 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -98,7 +98,7 @@ typedef union { uint32_t days : 7; // bits 16 - 22 = week day mask uint32_t device : 4; // bits 23 - 26 = 16 devices uint32_t power : 2; // bits 27 - 28 = 4 power states - Off, On, Toggle, Blink or Rule - uint32_t mode : 2; // bits 29 - 30 = timer modes - Scheduler, Sunrise, Sunset + uint32_t mode : 2; // bits 29 - 30 = timer modes - 0 = Scheduler, 1 = Sunrise, 2 = Sunset uint32_t arm : 1; // bit 31 }; } Timer; diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index e7d9262be..f82fa2e6d 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -628,7 +628,11 @@ void HandleConfiguration() page += FPSTR(HTTP_HEAD_STYLE); page += FPSTR(HTTP_BTN_MENU_MODULE); #if defined(USE_TIMERS) && defined(USE_TIMERS_WEB) +#ifdef USE_RULES + page += FPSTR(HTTP_BTN_MENU_TIMER); +#else if (devices_present) { page += FPSTR(HTTP_BTN_MENU_TIMER); } +#endif // USE_RULES #endif // USE_TIMERS and USE_TIMERS_WEB page += FPSTR(HTTP_BTN_MENU_WIFI); if (Settings.flag.mqtt_enabled) { page += FPSTR(HTTP_BTN_MENU_MQTT); } diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 26b23b258..981609b41 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -22,7 +22,7 @@ * Timers * * Arm a timer using one or all of the following JSON values: - * {"Arm":1,"Mode":0,"Time":"09:23","Days":"--TW--S","Repeat":1,"Output":1,"Action":1} + * {"Arm":1,"Mode":0,"Time":"09:23","Window":0,"Days":"--TW--S","Repeat":1,"Output":1,"Action":1} * * Arm 0 = Off, 1 = On * Mode 0 = Schedule, 1 = Sunrise, 2 = Sunset @@ -268,7 +268,7 @@ void TimerEverySecond() uint8_t days = 1 << (RtcTime.day_of_week -1); for (byte i = 0; i < MAX_TIMERS; i++) { - if (Settings.timer[i].device >= devices_present) Settings.timer[i].data = 0; // Reset timer due to change in devices present +// if (Settings.timer[i].device >= devices_present) Settings.timer[i].data = 0; // Reset timer due to change in devices present Timer xtimer = Settings.timer[i]; uint16_t set_time = xtimer.time; #ifdef USE_SUNRISE @@ -290,7 +290,7 @@ void TimerEverySecond() RulesProcess(); } else #endif // USE_RULES - ExecuteCommandPower(xtimer.device +1, xtimer.power); + if (devices_present) { ExecuteCommandPower(xtimer.device +1, xtimer.power); } } } } @@ -302,6 +302,7 @@ void TimerEverySecond() void PrepShowTimer(uint8_t index) { char days[8] = { 0 }; + char soutput[80]; Timer xtimer = Settings.timer[index -1]; @@ -309,16 +310,21 @@ void PrepShowTimer(uint8_t index) uint8_t mask = 1 << i; snprintf(days, sizeof(days), "%s%d", days, ((xtimer.days & mask) > 0)); } + + soutput[0] = '\0'; + if (devices_present) { + snprintf_P(soutput, sizeof(soutput), PSTR(",\"" D_JSON_TIMER_OUTPUT "\":%d"), xtimer.device +1); + } #ifdef USE_SUNRISE int16_t hour = xtimer.time / 60; if ((1 == xtimer.mode) || (2 == xtimer.mode)) { // Sunrise or Sunset if (hour > 11) { hour = (hour -12) * -1; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_MODE "\":%d,\"" D_JSON_TIMER_TIME "\":\"%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d,\"" D_JSON_TIMER_OUTPUT "\":%d,\"" D_JSON_TIMER_ACTION "\":%d}"), - mqtt_data, index, xtimer.arm, xtimer.mode, hour, xtimer.time % 60, xtimer.window, days, xtimer.repeat, xtimer.device +1, xtimer.power); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_MODE "\":%d,\"" D_JSON_TIMER_TIME "\":\"%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), + mqtt_data, index, xtimer.arm, xtimer.mode, hour, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_TIME "\":\"%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d,\"" D_JSON_TIMER_OUTPUT "\":%d,\"" D_JSON_TIMER_ACTION "\":%d}"), - mqtt_data, index, xtimer.arm, xtimer.time / 60, xtimer.time % 60, xtimer.window, days, xtimer.repeat, xtimer.device +1, xtimer.power); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_TIME "\":\"%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), + mqtt_data, index, xtimer.arm, xtimer.time / 60, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); #endif // USE_SUNRISE } @@ -345,7 +351,9 @@ boolean TimerCommand() Settings.timer[index -1].data = Settings.timer[XdrvMailbox.payload -1].data; // Copy timer } } else { +#ifndef USE_RULES if (devices_present) { +#endif StaticJsonBuffer<200> jsonBuffer; JsonObject& root = jsonBuffer.parseObject(dataBufUc); if (!root.success()) { @@ -408,18 +416,21 @@ boolean TimerCommand() } if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_OUTPUT))].success()) { uint8_t device = ((uint8_t)root[parm_uc] -1) & 0x0F; - Settings.timer[index].device = (device < devices_present) ? device : devices_present -1; + Settings.timer[index].device = (device < devices_present) ? device : 0; } if (root[UpperCase_P(parm_uc, PSTR(D_JSON_TIMER_ACTION))].success()) { - Settings.timer[index].power = (uint8_t)root[parm_uc] & 0x03; + uint8_t action = ((uint8_t)root[parm_uc] -1) & 0x03; + Settings.timer[index].power = (devices_present) ? action : 3; // If no devices than only allow rules } index++; } +#ifndef USE_RULES } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_TIMER_NO_DEVICE "\"}"), index); // No outputs defined so nothing to control error = 1; } +#endif } } if (!error) { @@ -527,8 +538,12 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = "m=qs('input[name=\"rd\"]:checked').value;" // Check mode "s|=(qs('input[name=\"rd\"]:checked').value<<29);" // Get mode #endif - "s|=(eb('p1').value<<27);" // Get power - "s|=(qs('#d1').selectedIndex<<23);" // Get device + "if(}1>0){" + "i=qs('#d1').selectedIndex;if(i>=0){s|=(i<<23);}" // Get output + "s|=(qs('#p1').selectedIndex<<27);" // Get action + "}else{" + "s|=3<<27;" // Get action (rule) + "}" "l=((qs('#ho').selectedIndex*60)+qs('#mi').selectedIndex)&0x7FF;" "if(m==0){s|=l;}" // Get time #ifdef USE_SUNRISE @@ -559,8 +574,10 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = #endif "q=(s>>11)&0xF;if(q<10){q='0'+q;}qs('#mw').value=q;" // Set window minutes "for(i=0;i<7;i++){p=(s>>(16+i))&1;eb('w'+i).checked=p;}" // Set weekdays - "p=(s>>23)&0xF;qs('#d1').value=p+1;" // Set device - "p=(s>>27)&3;eb('p1').value=p;" // Set power + "if(}1>0){" + "p=(s>>23)&0xF;qs('#d1').value=p+1;" // Set output + "p=(s>>27)&3;qs('#p1').selectedIndex=p;" // Set action + "}" "p=(s>>15)&1;eb('r0').checked=p;" // Set repeat "p=(s>>31)&1;eb('a0').checked=p;" // Set arm "}" @@ -569,13 +586,24 @@ const char HTTP_TIMER_SCRIPT[] PROGMEM = "pt=eb('t0').value.split(',').map(Number);" // Get parameters from hidden area to array "s='';for(i=0;i<" STR(MAX_TIMERS) ";i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" "eb('bt').innerHTML=s;" // Create tabs + "if(}1>0){" // Create Output and Action drop down boxes + "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" + "o=qs('#p1');ce('" D_OFF "',o);ce('" D_ON "',o);ce('" D_TOGGLE "',o);" // Create offset direction select options +#ifdef USE_RULES + "ce('" D_RULE "',o);" +#else + "ce('" D_BLINK "',o);" +#endif + "}else{" + "eb('oa').innerHTML=\"" D_TIMER_ACTION " " D_RULE "\";" // No outputs but rule is allowed + "}" #ifdef USE_SUNRISE "o=qs('#dr');ce('+',o);ce('-',o);" // Create offset direction select options #endif "o=qs('#ho');for(i=0;i<=23;i++){ce((i<10)?('0'+i):i,o);}" // Create hours select options "o=qs('#mi');for(i=0;i<=59;i++){ce((i<10)?('0'+i):i,o);}" // Create minutes select options "o=qs('#mw');for(i=0;i<=15;i++){ce((i<10)?('0'+i):i,o);}" // Create window minutes select options - "o=qs('#d1');for(i=0;i<}1;i++){ce(i+1,o);}" // Create devices + "o=qs('#d1');for(i=0;i<}1;i++){ce(i+1,o);}" // Create outputs "var a='" D_DAY3LIST "';" "s='';for(i=0;i<7;i++){s+=\"\"+a.substring(i*3,(i*3)+3)+\"\"}" "eb('ds').innerHTML=s;" // Create weekdays @@ -592,19 +620,7 @@ const char HTTP_FORM_TIMER[] PROGMEM = "



" - "
" - "" D_TIMER_OUTPUT "  " - "" D_TIMER_ACTION " " - "

" + "

" "
" "" D_TIMER_ARM " " "" D_TIMER_REPEAT ""