def ProcessExitKey(zone): # global GD.exitPending # Keep the current mode so we can check if it changes and we need to re-display the keyboard. lastCurrentMode = GD.currentMode # If the data has not changed or the user has pressed EXIT at the 'Save or Exit?' prompt we will exit back to a select mode. if zones.zoneTimes.CheckIfDataChanged() == False or GD.exitPending == True: # Clear info messages. display.DisplayBottomRightInfoPrompt() display.DisplayBottomLeftInfoPrompt(GD.BLANK_PROMPT) display.DisplayZoneMode() # No exit pending now. GD.exitPending = False # Move back to a select mode. Use correct select for rad, ufh or sys. if zone < 14: ProcessRadKey(zone) elif zone < 30: ProcessUfhKey(zone) else: keysSystem.ProcessImmersionTimesKey(zone) # We have changed the data so we will set exit pending flag and prompt for save or exit. else: GD.exitPending = True display.DisplayBottomLeftInfoPrompt() return 1
def ProcessDigitKey(key): # Only process key if we are in a time on or off edit mode. if GD.currentMode in (GD.MODE_PROG_ON_AT, GD.MODE_PROG_OFF_AT): # Convert keycode to character '0' to '9' key = chr(key - 2) if GD.currentMode == GD.MODE_PROG_ON_AT: # Update and display the on time. Call to modify will return -ve when all digits done and +ve if OK. status = zones.zoneTimes.ModifyTime(GD.ON_TIME_INDEX, key) display.DisplayProgOnTime() else: # Update and display the off time. Call to modify will return -ve when all digits done and +ve if OK. status = zones.zoneTimes.ModifyTime(GD.OFF_TIME_INDEX, key) display.DisplayProgOffTimeAndDays() # Update save and valid prompts now we have changed the data display.DisplayBottomLeftInfoPrompt() display.DisplayBottomRightInfoPrompt() # Check to see if we have edited all the digits. if status < 0: # Return to time programming mode. GD.currentMode = GD.MODE_PROG_TIME display.DisplayKeyboardImage(useMode=GD.currentMode) return 1
def SwitchToRunMode(): # Clear all the prompts. display.DisplayZoneMode() display.TopRightInfoPrompt(GD.BLANK_PROMPT) display.DisplayProgOnTime(GD.BLANK_PROMPT) display.DisplayProgOffTimeAndDays(GD.BLANK_PROMPT) display.DisplayEntries(GD.BLANK_PROMPT) display.DisplayBottomLeftInfoPrompt(GD.BLANK_PROMPT) display.DisplayBottomRightInfoPrompt(GD.BLANK_PROMPT) # Set system bits as required. system.SetModeOutputControlBitsFromConfigBits() # Switch to run mode. GD.currentMode = GD.MODE_RUN # Put display into waiting for a press mode. display.WriteToDisplay(GD.BACKLIGHT_OFF) display.DisplayForm(GD.BLANK_SCREEN_FORM) display.DisplayPressToStart() display.WriteToDisplay(GD.BACKLIGHT_LOW) # For android screen display.DisplayMiddleLeftInfoPrompt(GD.PRESS_ANY_KEY_PROMPT) # Clear any boost presses so they are not there when we restart later. GD.boostPresses = 0 # Start a zones check to update any changes to zones. GD.checkZone = 0
def ProcessAutoManualKey(zone): # Switch between Auto and Manual mode with each press. zones.zoneTimes.SwitchModes() display.DisplayBottomLeftInfoPrompt() display.DisplayZoneMode(zone) return 1
def ProcessEnableDisableKey(zone): # Only allow disable if we are in days entry mode. if GD.currentMode == GD.MODE_PROG_DAYS_ON: # Do disable/enable (toggle action). zones.zoneTimes.ModifyDay(GD.DAYS_INDEX, GD.DAYS_DISABLED) # Update save prompt as we have changed the data. display.DisplayBottomLeftInfoPrompt() display.DisplayBottomRightInfoPrompt() # Display the Current programming data entry. Force a display update. display.DisplayProgEntry(0, forceUpdate=True) return 1
def ProcessClearKey(zone): # global GD.clearPending if GD.currentMode == GD.MODE_PROG_ON_AT: # Clear the on time. zones.zoneTimes.ClearTime(GD.ON_TIME_INDEX) # Display the new time. display.DisplayProgOnTime() elif GD.currentMode == GD.MODE_PROG_OFF_AT: # Clear the off time. zones.zoneTimes.ClearTime(GD.OFF_TIME_INDEX) # Display the new time. display.DisplayProgOffTimeAndDays() elif GD.currentMode == GD.MODE_PROG_DAYS_ON and zones.zoneTimes.CheckIfDisabled( GD.DAYS_INDEX) == False: # Clear the days if we are not disabled. zones.zoneTimes.ClearDays(GD.DAYS_INDEX) # Display the new day info. Days info is displayed with the off time. display.DisplayProgOffTimeAndDays() elif GD.currentMode in (GD.MODE_PROG_TIME, GD.MODE_PROG_DAY): if GD.clearPending == True: GD.clearPending = False # Clear the on time zones.zoneTimes.ClearTime(GD.ON_TIME_INDEX) # Clear the off time zones.zoneTimes.ClearTime(GD.OFF_TIME_INDEX) # Clear the days zones.zoneTimes.ClearDays(GD.DAYS_INDEX) # Display the on time, off time and days. display.DisplayProgOnTime() display.DisplayProgOffTimeAndDays() else: GD.clearPending = True # Update info prompts now we have chaged the data display.DisplayBottomLeftInfoPrompt() display.DisplayBottomRightInfoPrompt() return 1
def ProcessWakeupKey(zone): # Start up the display by setting the correct form. Clear any info messages. display.DisplayForm(GD.MAIN_SCREEN_FORM) display.DisplayBottomLeftInfoPrompt(GD.BLANK_PROMPT) display.DisplayBottomRightInfoPrompt() # Check if the system is on or off. If we are on we display the rad select screen. If we are off we display the system screen. if system.systemControl[GD.SYSTEM_OFF_MODE].CheckIfBitHigh() == True: ProcessSystemKey(-1) else: ProcessRadKey(-1) display.WriteToDisplay(GD.BACKLIGHT_HALF) return 1
def ProcessUfhSelectExitKey(keyValue): # Return to ufh waiting select mode and keyboard. GD.currentMode = GD.MODE_UFH_WAITING_ZONE_SELECT display.DisplayKeyboardImage(useMode=GD.currentMode) # Clear any previously active select key and display any active bands. keyData.UpdateSelectKeyGroupText(textIdle=GD.KEY_GROUP_UFH) display.UpdateSelectKeyImages(GD.KEY_GROUP_UFH) # Update prompts. display.DisplayMiddleLeftInfoPrompt(GD.UFH_SELECT_PROMPT) display.DisplayBottomLeftInfoPrompt(GD.INFO_1_BLANKED) display.DisplayZoneMode() return 1
def ProcessDayOfWeekKey(key): # Only process key if we are in correct mode and not disabled. if GD.currentMode == GD.MODE_PROG_DAYS_ON and zones.zoneTimes.CheckIfDisabled( GD.DAYS_INDEX) == False: # Convert keycode to values 0 to 9 so we can use as index to string of days. key = key - 60 # Update the day. zones.zoneTimes.ModifyDay(GD.DAYS_INDEX, key) # Display the new day info. display.DisplayProgOffTimeAndDays() # Update the save and valid prompts now we have changed the data. display.DisplayBottomLeftInfoPrompt() display.DisplayBottomRightInfoPrompt() return 1
def ProcessProgramKey(zone): # Switch to the program keyboard (time entry). display.DisplayKeyboardImage(GD.TIME_SELECT_KEYBOARD_IMAGE) # Say we are in programming mode. We start in time entry mode. GD.currentMode = GD.MODE_PROG_TIME # Clear the zone select data ready for displaying programming data fields. display.DisplayMiddleLeftInfoPrompt(GD.BLANK_PROMPT) # Read the programmed times and display the 1st programming data entry. Force a display update. zones.ReadZoneTimes(zone) display.DisplayProgEntry(1, forceUpdate=True) display.DisplayBottomLeftInfoPrompt() display.DisplayBottomRightInfoPrompt() return 1
def ProcessNewKey(zone): #Limit number of entries to a reasonable number. if zones.zoneTimes.GetNumberOfProgramEntries() < 8: # Create new entry and get the number. newEntryNumber = zones.zoneTimes.AddNewEntry() # Return to initial state if we are in ON AT, OFF AT or day select mode. if GD.currentMode in (GD.MODE_PROG_ON_AT, GD.MODE_PROG_OFF_AT, GD.MODE_PROG_DAYS_ON): GD.currentMode = GD.MODE_PROG_DAY if GD.currentMode == GD.MODE_PROG_DAYS_ON else GD.MODE_PROG_TIME # Update info prompts now we have changed the data. display.DisplayBottomLeftInfoPrompt() display.DisplayBottomRightInfoPrompt() # Display the new programming data entry. display.DisplayProgEntry(newEntryNumber, forceUpdate=True) return 1
def ProcessSaveKey(zone): # Only save if a change has been made. if zones.zoneTimes.CheckIfDataChanged() == True: zones.zoneTimes.UpdateProgramEntries() # Return to initial state if we are in ON AT, OFF AT or day select mode. if GD.currentMode in (GD.MODE_PROG_ON_AT, GD.MODE_PROG_OFF_AT, GD.MODE_PROG_DAYS_ON): GD.currentMode = GD.MODE_PROG_DAY if GD.currentMode == GD.MODE_PROG_DAYS_ON else GD.MODE_PROG_TIME # Clear the flag now we have saved data and update prompts. GD.exitPending = False display.DisplayBottomLeftInfoPrompt() display.DisplayBottomRightInfoPrompt() # We need to re-display as the current entry may be blank and will be removed on save. Go back to 1st entry. display.DisplayProgEntry(1, forceUpdate=True) return 1
def ProcessDaysKey(zone): #We only process key if we are NOT already in day edit mode if GD.currentMode != GD.MODE_PROG_DAYS_ON: # Say we are now in day edit mode. GD.currentMode = GD.MODE_PROG_DAYS_ON # Switch to the day entry program keyboard. display.DisplayKeyboardImage(GD.DAY_SELECT_KEYBOARD_IMAGE) # Check if any edit has been aborted and if it has restore the original data. No need to update # display as we do this below. CheckForEditAbort(updateDisplay=False) # Update info prompts. display.DisplayBottomLeftInfoPrompt() display.DisplayBottomRightInfoPrompt() # Display the Current programming data entry. Force a display update. display.DisplayProgEntry(0, forceUpdate=True) return 1
def ProcessKeys(keyValue, zone): # Dictionary holds keycodes with functions to call. keyList = { GD.KEYVALUE_DAY: ProcessDaysKey, GD.KEYVALUE_BOOST: ProcessBoostKey, GD.KEYVALUE_CAN_RES: ProcessCanResKey, GD.KEYVALUE_PROGRAM: ProcessProgramKey, GD.KEYVALUE_RAD: ProcessRadKey, GD.KEYVALUE_UFH: ProcessUfhKey, GD.KEYVALUE_NEXT_PROGRAM_ENTRY: ProcessNextProgramEntrytKey, GD.KEYVALUE_NEXT_STATUS_ENTRY: keysSystem.ProcessNextStatusEntrytKey, GD.KEYVALUE_PREV_PROGRAM_ENTRY: ProcessPreviousProgramEntrytKey, GD.KEYVALUE_PREV_STATUS_ENTRY: keysSystem.ProcessPreviousStatusEntrytKey, GD.KEYVALUE_ON_AT: ProcessOnAtKey, GD.KEYVALUE_OFF_AT: ProcessOffAtKey, GD.KEYVALUE_CLEAR: ProcessClearKey, GD.KEYVALUE_SAVE: ProcessSaveKey, GD.KEYVALUE_NEW: ProcessNewKey, GD.KEYVALUE_ENABLE_DISABLE: ProcessEnableDisableKey, GD.KEYVALUE_AUTO_MANUAL: ProcessAutoManualKey, GD.KEYVALUE_WAKEUP: ProcessWakeupKey, GD.KEYVALUE_SYSTEM: ProcessSystemKey, GD.KEYVALUE_FINISHED: ProcessFinishedKey, GD.KEYVALUE_SYSTEM_OFF: keysSystem.ProcessSystemModeKeys, GD.KEYVALUE_AUTO_MODE: keysSystem.ProcessSystemModeKeys, GD.KEYVALUE_MANUAL_MODE: keysSystem.ProcessSystemModeKeys, GD.KEYVALUE_HOLIDAY_MODE: keysSystem.ProcessSystemModeKeys, GD.KEYVALUE_SYSTEM_OPTIONS: keysSystem.ProcessSystemOptionsKey, GD.KEYVALUE_MANUAL_OPTIONS: keysSystem.ProcessManualOptionsKey, GD.KEYVALUE_AUTO_OPTIONS: keysSystem.ProcessAutoOptionsKey, GD.KEYVALUE_HOLIDAY_OPTIONS: keysSystem.ProcessHolidayOptionsKey, GD.KEYVALUE_IMMERSION_TIMES: keysSystem.ProcessImmersionTimesKey, GD.KEYVALUE_T1_TO_HEAT: keysSystem.ProcessT1ToHeatingKey, GD.KEYVALUE_T2_TO_HEAT: keysSystem.ProcessT2ToHeatingKey, GD.KEYVALUE_OIL_TO_HEAT: keysSystem.ProcessOilToHeatingKey, GD.KEYVALUE_OIL_TO_T1: keysSystem.ProcessOilToT1Key, GD.KEYVALUE_OIL_TO_T2: keysSystem.ProcessOilToT2Key, GD.KEYVALUE_OIL_OFF: keysSystem.ProcessOilOffKey, GD.KEYVALUE_MANUAL_OVERRIDE: keysSystem.ProcessManualOverrideKey, GD.KEYVALUE_DISPLAY_STATUS: keysSystem.ProcessDisplayStatusKey, GD.KEYVALUE_IMMERSION_CONTROL: keysSystem.ProcessManualOverrideKeySubMenu, GD.KEYVALUE_WOODBURNER_CONTROL: keysSystem.ProcessManualOverrideKeySubMenu, GD.KEYVALUE_TANK_1_CONTROL: keysSystem.ProcessManualOverrideKeySubMenu, GD.KEYVALUE_TANK_2_CONTROL: keysSystem.ProcessManualOverrideKeySubMenu, GD.KEYVALUE_HEATING_CONTROL: keysSystem.ProcessManualOverrideKeySubMenu, GD.KEYVALUE_BOILER_CONTROL: keysSystem.ProcessManualOverrideKeySubMenu, GD.KEYVALUE_EXIT: ProcessExitKey, GD.KEYVALUE_RAD_SELECT_EXIT: ProcessRadSelectExitKey, GD.KEYVALUE_UFH_SELECT_EXIT: ProcessUfhSelectExitKey, GD.KEYVALUE_EDIT_EXIT: ProcessEditExitKey, GD.KEYVALUE_RETURN_TO_SYSTEM_EXIT: ProcessSystemKey, GD.KEYVALUE_MANUAL_CONTROL_MAIN_MENU_EXIT: keysSystem.ProcessManualOptionsKey, GD.KEYVALUE_MANUAL_CONTROL_OPTION_EXIT: keysSystem.ProcessManualOverrideKey, GD.KEYVALUE_RETURN_TO_SYSTEM_OPTIONS_EXIT: keysSystem.ProcessSystemOptionsKey } # If we have a pending exit we need to check if the key is SAVE, EXIT or something else. if GD.exitPending == True and keyValue not in (GD.KEYVALUE_SAVE, GD.KEYVALUE_EXIT): # Not SAVE or EXIT so clear pending status. GD.exitPending = False display.DisplayBottomLeftInfoPrompt() # If we have a pending clear we need to check if the key is CLEAR or something else. if GD.clearPending == True and keyValue != GD.KEYVALUE_CLEAR: # Not CLEAR so clear pending status. GD.clearPending = False display.DisplayBottomLeftInfoPrompt() # If the key is a general control type key then call the function for the supplied key. if keyValue in keyList: # If we are processing a system key we pass the key value to the function. # If it is a zone control or edit key we pass the current zone. passData = keyValue if keyValue >= GD.SYSTEM_KEY_START else zone status = keyList[keyValue](passData) # Is it a manual override key? These all call the same function. elif keyValue in (GD.KEY_GROUP_ALL_MANUAL_OVERRIDE): # At present imm 3 and imm 4 are in parallel so we need to activate both. # if keyValue in (GD.KEYVALUE_IMM_3_ON, GD.KEYVALUE_IMM_4_ON) : # status = keysSystem.ProcessManualOverrideOnOffKey (GD.KEYVALUE_IMM_3_ON) # status = keysSystem.ProcessManualOverrideOnOffKey (GD.KEYVALUE_IMM_4_ON) # elif keyValue in (GD.KEYVALUE_IMM_3_OFF, GD.KEYVALUE_IMM_4_OFF) : # status = keysSystem.ProcessManualOverrideOnOffKey (GD.KEYVALUE_IMM_3_OFF) # status = keysSystem.ProcessManualOverrideOnOffKey (GD.KEYVALUE_IMM_4_OFF) # else : # Process key status = keysSystem.ProcessManualOverrideOnOffKey(keyValue) # Is it a rad select key?, these all call the same function. elif keyValue in GD.KEY_GROUP_RADS: status = ProcessRadSelectKey(keyValue) # Is it a ufh select key?, these all call the same function. elif keyValue in GD.KEY_GROUP_UFH: status = ProcessUfhSelectKey(keyValue) # Is it an immersion select key?, these all call the same function. elif keyValue in GD.KEY_GROUP_IMMERSIONS: status = keysSystem.ProcessImmersionSelectKey(keyValue) # Is it a numeric key?, these all call the same function. elif keyValue in GD.KEY_GROUP_NUMERIC: status = ProcessDigitKey(keyValue) # Is it a day key?, these all call the same function. elif keyValue in GD.KEY_GROUP_DAYS: status = ProcessDayOfWeekKey(keyValue) # Is it a status key?, these all call the same function. elif keyValue in GD.KEY_GROUP_STATUS: status = keysSystem.ProcessStatusKey(keyValue) return
def main(): #Initialise the I2C port used for the relays and get I2C port object. I2CPort = smbus.SMBus(1) #Initialise 1 wire. ow.init('localhost:4304') # Create data structures to hold zone data. zones.InitialiseZones() # Initialise all the system control bits. system.InitialiseSystemControlBits() # Initialise the RS232 serial port and the display module and get serial port object. display.RS232Port = display.InitialiseDisplayKeyboardModule() # We run a process to read the 1 wire bus for the temperature sensors. Communication with the process is via 2 queues. # The command queue takes a 2 element tuple of the sensor id to start reading and the rad interval. # The result queue will contain a 2 element tuple of a sensor id and the temperature just read. # So here we initialise 2 queues and start the process. commandQueue = multiprocessing.Queue() resultQueue = multiprocessing.Queue() p = multiprocessing.Process(target=sensor.ReadTemperatures, args=( commandQueue, resultQueue, )) p.start() # Start reading the woodburner temperature sensors. We always have the woodburner code operational, even when the # system is in OFF mode. This is for safety lest the woodburner is lit with the system turned off. commandQueue.put((GD.SYSTEM_WOODBURNER_FLOW_TEMP, 1)) commandQueue.put((GD.SYSTEM_WOODBURNER_RETURN_TEMP, 1)) # DEBUG OUTPUT for entry in system.systemControl: print system.systemControl[entry].GetDisplayText( ), system.systemControl[entry].GetAddress() # This is the zone that is currently selected for viewing or editing. Initialise to the 1st zone (rad 1). selectedZone = GD.RAD_BED1 # We keep the last zone selected so that we can determine if a new zone has been selected. lastSelectedZone = GD.NO_ZONE # We need to read a zone to create a time object to use later. zones.ReadZoneTimes(selectedZone) # We time how long since the user last pressed a key so that we can blank the screen on no key activity and # also start zone checking and relay operation, which is suspended while key activity is in operation. lastKeypressTime = time.time() lastKeyImage = '' # This is a flag for our 1 second threading timer. When the timer expires we set this flag to give us a 1 second tick. oneSecondTimerTick = threading.Event() # Set it so that we do the 1st 1 second operations. oneSecondTimerTick.set() # Use same startup screen as wakeup so simply call wakeup key code. keys.ProcessWakeupKey(-1) # Set volume on the display to max. display.AdjustVolume(GD.SOUND_VOLUME_MAX) # This is our main loop while (1): # Let the CPU have a break from us. time.sleep(0.01) # Check if we have received any temperature readings and if we have get and save them. We do this in the # main loop so we can empty the queue faster than the readTemperatures process can fill it. if not resultQueue.empty(): systemId, sensorTemperature = resultQueue.get() system.systemControl[systemId].UpdateTemperature(sensorTemperature) print system.systemControl[systemId].GetDisplayText( ), sensorTemperature # Process possible key message from display module. keyCode = display.CheckForSerialInput(GD.CHECK_FOR_BUTTON) # Have we got a key? KeyCode is the physical button value on the display module if keyCode: # Sound key press. display.GenerateSound(GD.SOUND_CLICK) # Delay and then check for a key again. This will remove any key bounce that occurs in the delay time. # The delay also allows the sound to output without interference caused by sending data to the display # whilist it is generating the sound. We just ignore any keycode returned. time.sleep(0.4) display.CheckForSerialInput(GD.CHECK_FOR_BUTTON) # If we detect a longer keybounce (2 keypresses within a set time) ignore the key by making it zero. if time.time() < (lastKeypressTime + 0.85): print 'BOUNCE', time.time() - lastKeypressTime # Re-display the last key image again as we will have lost it on the bounce. display.WriteToDisplay(lastKeyImage) # Clear the key keyCode = 0 keyValue = 0 else: # Get the actual value for the key. Each physical key can have several different keyValues. It depends on the # mode we are in as we display different keyboards for each mode. keyValue = keyData.GetKeyValue(keyCode) print 'INITIAL KEYVALUE', keyValue # Found a key so reload our bounce timer. lastKeypressTime = time.time() # Have we got a key value? We may not have if it was a key bounce or a blank key. if keyValue: # We have a key so reload activity timer. GD.timeToRunMode = GD.KEYPRESS_WAIT_TIME # If it is a zone select key save it for later use. if keyValue in GD.KEY_GROUP_ALL_ZONES: # Adjust key value as zones start at 0 and key is 1 for zone 0. selectedZone = keyValue - 1 # If we have moved zones reset the boost key counter so we start at 1st boost for new zone. if lastSelectedZone != selectedZone: GD.boostPresses = 0 lastSelectedZone = selectedZone print 'SELECTED ZONE', selectedZone # If it is status select key save it for later use. elif keyValue in GD.KEY_GROUP_STATUS: selectedZone = keyValue # Go and process key. keys.ProcessKeys(keyValue, selectedZone) # We may now be in a different mode so we need to update the keyvalue for the new mode. keyValue = keyData.GetKeyValue(keyCode) # Update key image. Keep image so we can redisplay key after a key bounce. # If the key is displayed elsewhere lastKeyImage will be set null and the image will not be changed. lastKeyImage = keyData.GetKeyImageSequence(keyValue) display.WriteToDisplay(lastKeyImage) print 'KEYVALUE NOW', keyValue # If we are in a zone select mode read the programmed times and update display so user can see the zone status. if GD.currentMode in (GD.MODE_RAD_ZONE_SELECT, GD.MODE_UFH_ZONE_SELECT, GD.MODE_IMMERSION_SELECT): zones.ReadZoneTimes(selectedZone) zoneStatus = zones.UpdateZoneStatus(selectedZone) display.DisplayZoneStatus(selectedZone, zoneStatus) display.DisplayZoneMode(selectedZone) display.DisplayBottomLeftInfoPrompt() # Update boost key image and if it is the key currently pressed save the image. tempKeyImage = display.DisplayBoostKeyImage(selectedZone) if keyValue == GD.KEYVALUE_BOOST: lastKeyImage = tempKeyImage # Update cancel / resume key image and if it is the key currently pressed save the image. tempKeyImage = display.DisplayCancelResumeKeyImage( selectedZone) if keyValue == GD.KEYVALUE_CAN_RES: lastKeyImage = tempKeyImage # If we are in a programming mode update the auto / manual / enable / disable key image and if it is # the key currently pressed save the image. if GD.currentMode in (GD.MODE_PROG_TIME, GD.MODE_PROG_ON_AT, GD.MODE_PROG_OFF_AT, GD.MODE_PROG_DAY, GD.MODE_PROG_DAYS_ON): tempKeyImage = display.DisplayAutoEnableKeyImage( selectedZone) if keyValue in (GD.KEYVALUE_AUTO_MANUAL, GD.KEYVALUE_ENABLE_DISABLE): lastKeyImage = tempKeyImage # If there has been no activity we will revert to run mode and display the 'press to start' screen. if GD.timeToRunMode == 0: # Make flag -ve so we don't come here again. GD.timeToRunMode -= 1 # Set up run mode. SwitchToRunMode() # Has our 1 second timer ticked? If it has, do all the operations we do at 1 second intervals. # Restart the 1 second timer. It will set the oneSecondTimerTick event flag on timeout. This provides us with a 1 second tick. if oneSecondTimerTick.isSet(): oneSecondTimerTick.clear() threading.Timer(1, OneSecondTimeout, args=(oneSecondTimerTick, )).start() # Do our 1 second operations. ProcessOneSecondOperations(I2CPort, resultQueue) # Are we in run mode and a zone check is required. checkZone will have been set to 0 if a check is required if GD.currentMode == GD.MODE_RUN and GD.checkZone >= 0: # Update a zone's status. zones.UpdateZoneStatus(GD.checkZone) # Do any heating zone relay operation required. Heating zones are from 0 to 29. The relays for heating zones # are latching and in a matrix and are therefore accessed differently to system relays. if GD.checkZone < 30: relay.ActivateHeatingZoneRelay(I2CPort, GD.checkZone) # Immersion zones are from 30 to 33. Zones 30-33 are the 4 immersions. We will set the output control bits here and # the system relay code will control the actual outputs (relays). else: system.SetImmersionOutputControlBitsFromImmersionStatus( GD.checkZone) # If a zone pump is required set bits so system relay code sets it on. system.SetZonePumpOutputControlBitsFromZonePumpStatus(GD.checkZone) # Update the band status for a heating or immersion zone. keyData.SetZoneSelectBandStatus(GD.checkZone) # Move to next zone to check. When we pass the last zone stop further checking. GD.checkZone += 1 if GD.checkZone >= 34: GD.checkZone = -1 # Not in run mode. Are we in a select mode where a zone's state is displayed by a band? elif GD.currentMode in (GD.MODE_RAD_WAITING_ZONE_SELECT, GD.MODE_RAD_ZONE_SELECT, GD.MODE_IMMERSION_WAITING_SELECT, GD.MODE_IMMERSION_SELECT, GD.MODE_UFH_WAITING_ZONE_SELECT, GD.MODE_UFH_ZONE_SELECT): # If this is the 1st time here since run mode (checkZone = -1) or we have reached the end we need to set checkZone # to zero, otherwise move to next zone. if GD.checkZone < 0 or GD.checkZone >= 33: GD.checkZone = 0 else: GD.checkZone += 1 # Update the band status for a heating or immersion zone. keyData.SetZoneSelectBandStatus(GD.checkZone)