static bool ManualZone(const KVPairs & key_value_pairs) { freeMemory(); // Turn off the current schedules. SetRunSchedules(false); bool bOn = false; int iZoneNum = -1; // Iterate through the kv pairs and update the appropriate structure values. for (int i = 0; i < key_value_pairs.num_pairs; i++) { const char * key = key_value_pairs.keys[i]; const char * value = key_value_pairs.values[i]; if ((strcmp(key, "zone") == 0) && (value[0] == 'z') && (value[1] > 'a') && (value[1] <= ('a' + NUM_ZONES))) { iZoneNum = value[1] - 'a'; } else if (strcmp(key, "state") == 0) { if (strcmp(value, "on") == 0) bOn = true; else bOn = false; } } if ((iZoneNum >= 0) && bOn) { TurnOnZone(iZoneNum); runState.SetManual(true, iZoneNum); } else { TurnOffZones(); runState.SetManual(false); } return true; }
// this version uses QuickSchedule mechanism, allows setting run time as well as multi-valve runs void manual_station_on(byte sid, int ontimer) { if( sid >= NUM_ZONES ) return; // basic protection, ensure that required zone number is within acceptable range // So, we first end any schedule that's currently running by turning things off then on again. ReloadEvents(); if( ActiveZoneNum() != -1 ){ // something is currently running, turn it off TurnOffZones(); runState.SetManual(false); } for( byte n=0; n<NUM_ZONES; n++ ){ quickSchedule.zone_duration[n] = 0; // clear up QuickSchedule to zero out run time for all zones } // set run time for required zone. // quickSchedule.zone_duration[sid] = ontimer; LoadSchedTimeEvents(0, true); }
// Home screen mode handler. // It is responsible for updating the UI and handling input keys. All operations are asynchronous - must return right away. // Typically it is called from loop(), but could be called from other places as well, usually to force UI refresh. // Parameter indicates whether UI refresh is required (e.g. if the screen was previously modified by some other code). // TRUE means that refresh is required, FALSE means nobody touched LCD since the last call to this handler and UI updates could be more targeted. // byte OSLocalUI::modeHandler_Home(byte forceRefresh) { static unsigned long old_millis = 0; // assert if( osUI_Mode != OSUI_MODE_HOME ) return false; // Basic protection to ensure current UI mode is actually HOME mode. if( forceRefresh == 2 ){ // entering this Mode display_board = 0; // set initial view to board 0; } char btn = get_button_async(0); // handle input if( btn == BUTTON_MODE ){ set_mode( OSUI_MODE_MANUAL ); // change mode to "view settings" which is the next mode return true; } else if( btn == BUTTON_CONFIRM ){ if( GetRunSchedules() ) SetRunSchedules(false); // schedules are currently enabled, disable it else { if( ActiveZoneNum() != -1 ){ // schedules are disabled, but something is currently running (manual mode), turn it off TurnOffZones(); runState.SetManual(false); } else { SetRunSchedules(true); // schedules are currently disabled and no manual channels running, enable schedules } } // Apply changes to stop/start schedules as required. ReloadEvents(); forceRefresh = 1; // force UI refresh to provide immediate visual feedback } // Show time and station status // if 1 second has passed unsigned long new_millis = millis(); // Note: we are using built-in Arduino millis() function instead of now() or time-zone adjusted LocalNow(), because it is a lot faster // and for detecting second change it does not make any difference. if( ((new_millis - old_millis) >= 1000) || (forceRefresh != 0) ){ // update UI once a second, OR if explicit refresh is required old_millis = new_millis; lcd_print_time(0); // print time // process LCD display if(SHOW_MEMORY) lcd_print_memory(1); else lcd_print_station(1, ui_anim_chars[now()%3]); } return true; }