logMessage("Warning: minimum BrewPi version compatible with this script is " + compatibleHwVersion + " but version number received is " + hwVersion.toString()) if int(hwVersion.log) != int(expandLogMessage.getVersion()): logMessage("Warning: version number of local copy of logMessages.h " + "does not match log version number received from controller." + "controller version = " + str(hwVersion.log) + ", local copy version = " + str(expandLogMessage.getVersion())) bg_ser = None if ser is not None: ser.flush() # set up background serial processing, which will continuously read data from serial and put whole lines in a queue bg_ser = BackGroundSerial(ser) bg_ser.start() # request settings from controller, processed later when reply is received bg_ser.write('s') # request control settings cs bg_ser.write('c') # request control constants cc # answer from controller is received asynchronously later. # create a listening socket to communicate with PHP is_windows = sys.platform.startswith('win') useInetSocket = bool(config.get('useInetSocket', is_windows)) if useInetSocket: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) socketPort = config.get('socketPort', 6332) s.bind((config.get('socketHost', 'localhost'), int(socketPort))) logMessage('Bound to TCP socket on port %d ' % int(socketPort))
def updateFromGitHub(userInput, beta, useDfu, restoreSettings=True, restoreDevices=True): import BrewPiUtil as util from gitHubReleases import gitHubReleases import brewpiVersion import programController as programmer configFile = util.scriptPath() + '/settings/config.cfg' config = util.readCfgWithDefaults(configFile) printStdErr( "Stopping any running instances of BrewPi to check/update controller..." ) quitBrewPi(config['wwwPath']) hwVersion = None shield = None board = None family = None ### Get version number printStdErr("\nChecking current firmware version...") bg_ser = BackGroundSerial(config.get('port', 'auto')) hwVersion = brewpiVersion.getVersionFromSerial(bg_ser) if hwVersion is not None: family = hwVersion.family shield = hwVersion.shield board = hwVersion.board else: printStdErr( "Unable to receive version from controller.\n" "Is your controller unresponsive and do you wish to try restoring your firmware? [y/N]: " ) choice = raw_input() if not any(choice == x for x in ["yes", "Yes", "YES", "yes", "y", "Y"]): printStdErr( "Please make sure your controller is connected properly and try again." ) return 0 port = autoSerial.detect_port() if not port: printStdErr( "Could not find compatible device in available serial ports.") return 0 name = autoSerial.recognized_device_name(port) if "Particle" in name: family = "Particle" if "P1" in name: board = 'p1' elif "Photon" in name: board = 'photon' elif "Core" in name: board = 'core' elif "Arduino" in name: family = "Arduino" if "Leonardo" in name: board = 'leonardo' elif "Uno" in name: board = 'uno' if board is None: printStdErr( "Unable to connect to controller, perhaps it is disconnected or otherwise unavailable." ) return -1 else: printStdErr("Will try to restore the firmware on your %s" % name) if family == "Arduino": printStdErr( "Assuming a Rev C shield. If this is not the case, please program your Arduino manually" ) shield = 'RevC' else: printStdErr( "Please put your controller in DFU mode now by holding the setup button during reset, until the LED blinks yellow." ) printStdErr("Press Enter when ready.") choice = raw_input() useDfu = True # use dfu mode when board is not responding to serial bg_ser.stop() del bg_ser if hwVersion: printStdErr("Current firmware version on controller: " + hwVersion.toString()) else: restoreDevices = False restoreSettings = False printStdErr("\nChecking GitHub for available release...") releases = gitHubReleases("https://api.github.com/repos/BrewPi/firmware") availableTags = releases.getTags(beta) stableTags = releases.getTags(False) compatibleTags = [] for tag in availableTags: url = None if family == "Arduino": url = releases.getBinUrl(tag, [board, shield, ".hex"]) elif family == "Spark" or family == "Particle": url = releases.getBinUrl(tag, [board, 'brewpi', '.bin']) if url is not None: compatibleTags.append(tag) if len(compatibleTags) == 0: printStdErr("No compatible releases found for %s %s" % (family, board)) return -1 # default tag is latest stable tag, or latest unstable tag if no stable tag is found default_choice = next( (i for i, t in enumerate(compatibleTags) if t in stableTags), 0) tag = compatibleTags[default_choice] if userInput: print("\nAvailable releases:\n") for i, menu_tag in enumerate(compatibleTags): print("[%d] %s" % (i, menu_tag)) print("[" + str(len(compatibleTags)) + "] Cancel firmware update") num_choices = len(compatibleTags) while 1: try: choice = raw_input( "Enter the number [0-%d] of the version you want to program [default = %d (%s)]: " % (num_choices, default_choice, tag)) if choice == "": break else: selection = int(choice) except ValueError: print("Use the number! [0-%d]" % num_choices) continue if selection == num_choices: return False # choice = skip updating try: tag = compatibleTags[selection] except IndexError: print("Not a valid choice. Try again") continue break else: printStdErr("Latest version on GitHub: " + tag) if hwVersion is not None and not hwVersion.isNewer(tag): if hwVersion.isEqual(tag): printStdErr("You are already running version %s." % tag) else: printStdErr("Your current version is newer than %s." % tag) if userInput: printStdErr( "If you are encountering problems, you can reprogram anyway." " Would you like to do this?" "\nType yes to reprogram or just press enter to keep your current firmware: " ) choice = raw_input() if not any(choice == x for x in ["yes", "Yes", "YES", "yes", "y", "Y"]): return 0 else: printStdErr("No update needed. Exiting.") exit(0) if hwVersion is not None and userInput: printStdErr( "Would you like me to try to restore you settings after programming? [Y/n]: " ) choice = raw_input() if not any(choice == x for x in ["", "yes", "Yes", "YES", "yes", "y", "Y"]): restoreSettings = False printStdErr( "Would you like me to try to restore your configured devices after programming? [Y/n]: " ) choice = raw_input() if not any(choice == x for x in ["", "yes", "Yes", "YES", "yes", "y", "Y"]): restoreDevices = False printStdErr("Downloading firmware...") localFileName = None system1 = None system2 = None if family == "Arduino": localFileName = releases.getBin(tag, [board, shield, ".hex"]) elif family == "Spark" or family == "Particle": localFileName = releases.getBin(tag, [board, 'brewpi', '.bin']) else: printStdErr("Error: Device family {0} not recognized".format(family)) return -1 if board == "photon" or board == "p1" and useDfu: if hwVersion: oldVersion = hwVersion.version.vstring else: oldVersion = "0.0.0" latestSystemTag = releases.getLatestTagForSystem(board, prerelease=beta, since=oldVersion) if latestSystemTag is not None: printStdErr( "Updated system firmware for the {0} found in release {1}". format(board, latestSystemTag)) system1 = releases.getBin(latestSystemTag, [board, 'system-part1', '.bin']) system2 = releases.getBin(latestSystemTag, [board, 'system-part2', '.bin']) if system1: printStdErr("Downloaded new system firmware to:\n") printStdErr("{0}\nand\n".format(system1)) if system2: printStdErr("{0}\n".format(system2)) else: printStdErr( "Error: system firmware part2 not found in release") return -1 else: printStdErr("Photon system firmware is up to date.\n") if localFileName: printStdErr("Latest firmware downloaded to:\n" + localFileName) else: printStdErr("Downloading firmware failed") return -1 printStdErr("\nUpdating firmware...\n") result = programmer.programController(config, board, localFileName, system1, system2, useDfu, { 'settings': restoreSettings, 'devices': restoreDevices }) util.removeDontRunFile(config['wwwPath'] + "/do_not_run_brewpi") return result
if hwVersion.family == 'Arduino': exit( "\n ERROR: the newest version of BrewPi is not compatible with Arduino. \n" + "You can use our legacy branch with your Arduino, in which we only include the backwards compatible changes. \n" + "To change to the legacy branch, run: sudo ~/brewpi-tools/updater.py --ask , and choose the legacy branch." ) bg_ser = None if ser is not None: ser.flush() # set up background serial processing, which will continuously read data from serial and put whole lines in a queue bg_ser = BackGroundSerial(ser) bg_ser.start() # request settings from controller, processed later when reply is received bg_ser.write('s') # request control settings cs bg_ser.write('c') # request control constants cc bg_ser.write('v') # request control variables cv # answer from controller is received asynchronously later. # create a listening socket to communicate with PHP is_windows = sys.platform.startswith('win') useInetSocket = bool(config.get('useInetSocket', is_windows)) if useInetSocket: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) socketPort = config.get('socketPort', 6332) s.bind((config.get('socketHost', 'localhost'), int(socketPort)))
config = util.configSet(configFile, 'dataLogging', 'active') return { 'status': 0, 'statusMessage': "Successfully continued logging." } else: return {'status': 1, 'statusMessage': "Logging was not paused."} logMessage("Notification: Script started for beer '" + urllib.unquote(config['beerName']) + "'") logMessage("Connecting to controller...") # set up background serial processing, which will continuously read data from serial and put whole lines in a queue bg_ser = BackGroundSerial(config.get('port', 'auto')) hwVersion = brewpiVersion.getVersionFromSerial(bg_ser) if hwVersion is None: logMessage( "Warning: Cannot receive version number from controller. " + "Check your port setting in the Maintenance Panel or in settings/config.cfg." ) else: logMessage("Found " + hwVersion.toExtendedString()) if LooseVersion(hwVersion.toString()) < LooseVersion(compatibleHwVersion): logMessage( "Warning: minimum BrewPi version compatible with this script is " + compatibleHwVersion + " but version number received is " + hwVersion.toString()) if int(hwVersion.log) != int(expandLogMessage.getVersion()):
def resumeLogging(): global config logMessage("Continued logging data, as requested in web interface.") if config['dataLogging'] == 'paused': config = util.configSet(configFile, 'dataLogging', 'active') return {'status': 0, 'statusMessage': "Successfully continued logging."} else: return {'status': 1, 'statusMessage': "Logging was not paused."} logMessage("Notification: Script started for beer '" + urllib.unquote(config['beerName']) + "'") logMessage("Connecting to controller...") # set up background serial processing, which will continuously read data from serial and put whole lines in a queue bg_ser = BackGroundSerial(config.get('port', 'auto')) hwVersion = brewpiVersion.getVersionFromSerial(bg_ser) if hwVersion is None: logMessage("Warning: Cannot receive version number from controller. " + "Check your port setting in the Maintenance Panel or in settings/config.cfg.") else: logMessage("Found " + hwVersion.toExtendedString()) if LooseVersion( hwVersion.toString() ) < LooseVersion(compatibleHwVersion): logMessage("Warning: minimum BrewPi version compatible with this script is " + compatibleHwVersion + " but version number received is " + hwVersion.toString()) if int(hwVersion.log) != int(expandLogMessage.getVersion()): logMessage("Warning: version number of local copy of logMessages.h " + "does not match log version number received from controller." + "controller version = " + str(hwVersion.log) +
def updateFromGitHub(userInput, beta, useDfu, restoreSettings = True, restoreDevices = True): import BrewPiUtil as util from gitHubReleases import gitHubReleases import brewpiVersion import programController as programmer configFile = util.scriptPath() + '/settings/config.cfg' config = util.readCfgWithDefaults(configFile) printStdErr("Stopping any running instances of BrewPi to check/update controller...") quitBrewPi(config['wwwPath']) hwVersion = None shield = None board = None family = None ### Get version number printStdErr("\nChecking current firmware version...") bg_ser = BackGroundSerial(config.get('port', 'auto')) hwVersion = brewpiVersion.getVersionFromSerial(bg_ser) if hwVersion is not None: family = hwVersion.family shield = hwVersion.shield board = hwVersion.board else: printStdErr("Unable to receive version from controller.\n" "Is your controller unresponsive and do you wish to try restoring your firmware? [y/N]: ") choice = raw_input() if not any(choice == x for x in ["yes", "Yes", "YES", "yes", "y", "Y"]): printStdErr("Please make sure your controller is connected properly and try again.") return 0 port, name = autoSerial.detect_port() if not port: printStdErr("Could not find compatible device in available serial ports.") return 0 if "Particle" in name: family = "Particle" if "P1" in name: board = 'p1' elif "Photon" in name: board = 'photon' elif "Core" in name: board = 'core' elif "Arduino" in name: family = "Arduino" if "Leonardo" in name: board = 'leonardo' elif "Uno" in name: board = 'uno' if board is None: printStdErr("Unable to connect to controller, perhaps it is disconnected or otherwise unavailable.") return -1 else: printStdErr("Will try to restore the firmware on your %s" % name) if family == "Arduino": printStdErr("Assuming a Rev C shield. If this is not the case, please program your Arduino manually") shield = 'RevC' else: printStdErr("Please put your controller in DFU mode now by holding the setup button during reset, until the LED blinks yellow.") printStdErr("Press Enter when ready.") choice = raw_input() useDfu = True # use dfu mode when board is not responding to serial bg_ser.stop() del bg_ser if hwVersion: printStdErr("Current firmware version on controller: " + hwVersion.toString()) else: restoreDevices = False restoreSettings = False printStdErr("\nChecking GitHub for available release...") releases = gitHubReleases("https://api.github.com/repos/BrewPi/firmware") availableTags = releases.getTags(beta) stableTags = releases.getTags(False) compatibleTags = [] for tag in availableTags: url = None if family == "Arduino": url = releases.getBinUrl(tag, [board, shield, ".hex"]) elif family == "Spark" or family == "Particle": url = releases.getBinUrl(tag, [board, 'brewpi', '.bin']) if url is not None: compatibleTags.append(tag) if len(compatibleTags) == 0: printStdErr("No compatible releases found for %s %s" % (family, board)) return -1 # default tag is latest stable tag, or latest unstable tag if no stable tag is found default_choice = next((i for i, t in enumerate(compatibleTags) if t in stableTags), 0) tag = compatibleTags[default_choice] if userInput: print("\nAvailable releases:\n") for i, menu_tag in enumerate(compatibleTags): print("[%d] %s" % (i, menu_tag)) print ("[" + str(len(compatibleTags)) + "] Cancel firmware update") num_choices = len(compatibleTags) while 1: try: choice = raw_input("Enter the number [0-%d] of the version you want to program [default = %d (%s)]: " % (num_choices, default_choice, tag)) if choice == "": break else: selection = int(choice) except ValueError: print("Use the number! [0-%d]" % num_choices) continue if selection == num_choices: return False # choice = skip updating try: tag = compatibleTags[selection] except IndexError: print("Not a valid choice. Try again") continue break else: printStdErr("Latest version on GitHub: " + tag) if hwVersion is not None and not hwVersion.isNewer(tag): if hwVersion.isEqual(tag): printStdErr("You are already running version %s." % tag) else: printStdErr("Your current version is newer than %s." % tag) if userInput: printStdErr("If you are encountering problems, you can reprogram anyway." " Would you like to do this?" "\nType yes to reprogram or just press enter to keep your current firmware: ") choice = raw_input() if not any(choice == x for x in ["yes", "Yes", "YES", "yes", "y", "Y"]): return 0 else: printStdErr("No update needed. Exiting.") exit(0) if hwVersion is not None and userInput: printStdErr("Would you like me to try to restore you settings after programming? [Y/n]: ") choice = raw_input() if not any(choice == x for x in ["", "yes", "Yes", "YES", "yes", "y", "Y"]): restoreSettings = False printStdErr("Would you like me to try to restore your configured devices after programming? [Y/n]: ") choice = raw_input() if not any(choice == x for x in ["", "yes", "Yes", "YES", "yes", "y", "Y"]): restoreDevices = False printStdErr("Downloading firmware...") localFileName = None system1 = None system2 = None if family == "Arduino": localFileName = releases.getBin(tag, [board, shield, ".hex"]) elif family == "Spark" or family == "Particle": localFileName = releases.getBin(tag, [board, 'brewpi', '.bin']) else: printStdErr("Error: Device family {0} not recognized".format(family)) return -1 if board == "photon" or board == "p1" and useDfu: if hwVersion: oldVersion = hwVersion.version.vstring else: oldVersion = "0.0.0" latestSystemTag = releases.getLatestTagForSystem(board, prerelease=beta, since=oldVersion) if latestSystemTag is not None: printStdErr("Updated system firmware for the {0} found in release {1}".format(board, latestSystemTag)) system1 = releases.getBin(latestSystemTag, [board, 'system-part1', '.bin']) system2 = releases.getBin(latestSystemTag, [board, 'system-part2', '.bin']) if system1: printStdErr("Downloaded new system firmware to:\n") printStdErr("{0}\nand\n".format(system1)) if system2: printStdErr("{0}\n".format(system2)) else: printStdErr("Error: system firmware part2 not found in release") return -1 else: printStdErr("Photon system firmware is up to date.\n") if localFileName: printStdErr("Latest firmware downloaded to:\n" + localFileName) else: printStdErr("Downloading firmware failed") return -1 printStdErr("\nUpdating firmware...\n") result = programmer.programController(config, board, localFileName, system1, system2, useDfu, {'settings': restoreSettings, 'devices': restoreDevices}) util.removeDontRunFile(config['wwwPath'] + "/do_not_run_brewpi") return result
def open_bg_serial(self): self.close_serial() if self.bg_ser is None: self.bg_ser = BackGroundSerial(self.config.get('port', 'auto'))
class SerialProgrammer: @staticmethod def create(config, boardType): if boardType=='core': msg_map["a"] = "Spark Core" programmer = SparkProgrammer(config, boardType) elif boardType == 'photon': msg_map["a"] = "Photon" programmer = SparkProgrammer(config, boardType) elif boardType == 'p1': msg_map["a"] = "P1" programmer = SparkProgrammer(config, boardType) else: programmer = None return programmer def __init__(self, config): self.config = config self.restoreSettings = False self.restoreDevices = False self.ser = None self.bg_ser = None self.versionNew = None self.versionOld = None self.oldSettings = {} def program(self, hexFile, system1File, system2File, useDfu, restoreWhat): printStdErr("**** %(a)s Program script started ****" % msg_map) self.parse_restore_settings(restoreWhat) self.open_bg_serial() if self.restoreSettings or self.restoreDevices: printStdErr("Checking old version before programming.") # request all settings from board before programming if self.fetch_current_version(): self.retrieve_settings_from_serial() self.save_settings_to_file() self.close_bg_serial() if useDfu: printStdErr("\nTrying to automatically reboot into DFU mode and update your firmware.") printStdErr("\nIf the Photon does not reboot into DFU mode automatically, please put it in DFU mode manually.") self.close_all_serial() myDir = os.path.dirname(os.path.abspath(__file__)) flashDfuPath = os.path.join(myDir, 'utils', 'flashDfu.py') command = sys.executable + ' ' + flashDfuPath + " --autodfu --noreset --file={0}".format(os.path.abspath(hexFile)) if system1File is not None and system2File is not None: systemParameters = " --system1={0} --system2={1}".format(system1File, system2File) command = command + systemParameters if platform.system() == "Linux": command = 'sudo ' + command printStdErr("Running command: " + command) process = subprocess.Popen(command, shell=True) process.wait() printStdErr("\nUpdating firmware over DFU finished\n") else: if not self.open_serial(self.config, 57600, 0.2): printStdErr("Could not open serial port to flash the firmware.") return False if system1File: printStdErr("Flashing system part 1.") if not self.flash_file(system1File): return False waitForReset(15) if not self.open_serial_with_retry(self.config, 57600, 0.2): printStdErr("Error opening serial port after flashing system part 1. Program script will exit.") printStdErr("If your device stopped working, use flashDfu.py to restore it.") return False if system2File: printStdErr("Flashing system part 2.") if not self.flash_file(system2File): return False waitForReset(15) if not self.open_serial_with_retry(self.config, 57600, 0.2): printStdErr("Error opening serial port after flashing system part 2. Program script will exit.") printStdErr("If your device stopped working, use flashDfu.py to restore it.") return False if(hexFile): if not self.flash_file(hexFile): return False waitForReset(15) self.close_serial() printStdErr("Now checking new version.") self.open_bg_serial() # request all settings from board before programming self.fetch_new_version() self.reset_settings() if self.restoreSettings or self.restoreDevices: printStdErr("Now checking which settings and devices can be restored...") if self.versionNew is None: printStdErr(("Warning: Cannot receive version number from controller after programming. " "\nSomething must have gone wrong. Restoring settings/devices settings failed.\n")) return 0 if not self.versionOld and (self.restoreSettings or self.restoreDevices): printStdErr("Could not receive valid version number from old board, " + "No settings/devices are restored.") return 0 if self.restoreSettings: printStdErr("Trying to restore compatible settings from " + self.versionOld.toString() + " to " + self.versionNew.toString()) if(self.versionNew.isNewer("0.2")): printStdErr("Sorry, settings can only be restored when updating to BrewPi 0.2.0 or higher") self.restoreSettings = False if self.restoreSettings: self.restore_settings() if self.restoreDevices: self.restore_devices() printStdErr("**** Program script done! ****") self.close_bg_serial() return 1 def parse_restore_settings(self, restoreWhat): restoreSettings = False restoreDevices = False if 'settings' in restoreWhat: if restoreWhat['settings']: restoreSettings = True if 'devices' in restoreWhat: if restoreWhat['devices']: restoreDevices = True # Even when restoreSettings and restoreDevices are set to True here, # they might be set to false due to version incompatibility later printStdErr("Settings will " + ("" if restoreSettings else "not ") + "be restored" + (" if possible" if restoreSettings else "")) printStdErr("Devices will " + ("" if restoreDevices else "not ") + "be restored" + (" if possible" if restoreSettings else "")) self.restoreSettings = restoreSettings self.restoreDevices = restoreDevices def open_serial(self, config, baud, timeout): self.close_bg_serial() if self.ser is None: self.ser = util.setupSerial(config, baud, timeout) if self.ser is None: return False return True def open_bg_serial(self): self.close_serial() if self.bg_ser is None: self.bg_ser = BackGroundSerial(self.config.get('port', 'auto')) def close_serial(self): if self.ser: self.ser.close() self.ser = None def close_bg_serial(self): if self.bg_ser: self.bg_ser.stop() self.bg_ser = None def close_all_serial(self): self.close_bg_serial() def open_serial_with_retry(self, config, baud, timeout): # reopen serial port retries = 30 self.ser = None while retries: time.sleep(1) if self.open_serial(config, baud, timeout): return True retries -= 1 return False def fetch_version(self, msg): self.open_bg_serial() version = brewpiVersion.getVersionFromSerial(self.bg_ser) if version is None: printStdErr("Warning: Cannot receive version number from controller. It will be reset to defaults.") return version def fetch_current_version(self): self.versionOld = self.fetch_version("Checking current version: ") return self.versionOld def fetch_new_version(self): self.versionNew = self.fetch_version("Checking new version: ") return self.versionNew def retrieve_settings_from_serial(self): self.open_bg_serial() self.oldSettings.clear() printStdErr("Requesting old settings from %(a)s..." % msg_map) expected_responses = 2 if not self.versionOld.isNewer("0.2.0"): # versions older than 2.0.0 did not have a device manager expected_responses += 1 self.bg_ser.writeln("d{}") # installed devices time.sleep(1) self.bg_ser.writeln("c") # control constants self.bg_ser.writeln("s") # control settings start = time.time() timeout = False while expected_responses > 0 and not timeout: line = self.bg_ser.read_line() if line: if line[0] == 'C': expected_responses -= 1 self.oldSettings['controlConstants'] = json_decode_response(line) elif line[0] == 'S': expected_responses -= 1 self.oldSettings['controlSettings'] = json_decode_response(line) elif line[0] == 'd': expected_responses -= 1 self.oldSettings['installedDevices'] = json_decode_response(line) time.sleep(0.2) if time.time() - start > 10: timeout = True if(timeout): printStdErr("Timeout when requesting old settings from %(a)s..." % msg_map) printStdErr("Not all settings will be restored") def save_settings_to_file(self): oldSettingsFileName = 'settings-' + time.strftime("%b-%d-%Y-%H-%M-%S") + '.json' settingsBackupDir = util.scriptPath() + '/settings/controller-backup/' if not os.path.exists(settingsBackupDir): os.makedirs(settingsBackupDir, 0777) oldSettingsFilePath = os.path.join(settingsBackupDir, oldSettingsFileName) oldSettingsFile = open(oldSettingsFilePath, 'wb') oldSettingsFile.write(json.dumps(self.oldSettings)) oldSettingsFile.truncate() oldSettingsFile.close() os.chmod(oldSettingsFilePath, 0777) # make sure file can be accessed by all in case the script ran as root printStdErr("Saved old settings to file " + oldSettingsFileName) def delay(self, countDown): while countDown > 0: time.sleep(1) countDown -= 1 printStdErr("Back up in " + str(countDown) + "...") def flash_file(self, hexFile): raise Exception("not implemented") def reset_settings(self, setTestMode = False): printStdErr("Resetting EEPROM to default settings") self.open_bg_serial() self.bg_ser.writeln('E') if setTestMode: self.bg_ser.writeln('j{mode:t}') start = time.time() # read log messages from controller while time.time() - start < 10: # read all lines on serial interface message = self.bg_ser.read_message() if message: # message available? printStdErr(message) if "RESET" in message: break def restore_settings(self): oldSettingsDict = self.get_combined_settings_dict(self.oldSettings) ms = MigrateSettings() restored, omitted = ms.getKeyValuePairs(oldSettingsDict, self.versionOld.toString(), self.versionNew.toString()) printStdErr("Migrating these settings: " + json.dumps(restored.items())) printStdErr("Omitting these settings: " + json.dumps(omitted.items())) self.send_restored_settings(restored) def get_combined_settings_dict(self, oldSettings): combined = oldSettings.get('controlConstants').copy() # copy keys/values from controlConstants combined.update(oldSettings.get('controlSettings')) # add keys/values from controlSettings return combined def send_restored_settings(self, restoredSettings): for key in restoredSettings: self.open_bg_serial() setting = restoredSettings[key] command = "j{" + json.dumps(key) + ":" + json.dumps(setting) + "}\n" self.bg_ser.write(command) time.sleep(0.1) message = self.bg_ser.read_message() if message: printStdErr(message) time.sleep(1) while True: # read remaining log messages message = self.bg_ser.read_message() if message: printStdErr(message) else: break def restore_devices(self): self.open_bg_serial() oldDevices = self.oldSettings.get('installedDevices') if oldDevices: printStdErr("Now trying to restore previously installed devices: " + str(oldDevices)) else: printStdErr("No devices to restore!") return detectedDevices = None for device in oldDevices: printStdErr("Restoring device: " + json.dumps(device)) if "a" in device.keys(): # check for sensors configured as first on bus if int(device['a'], 16) == 0: printStdErr("OneWire sensor was configured to autodetect the first sensor on the bus, " + "but this is no longer supported. " + "We'll attempt to automatically find the address and add the sensor based on its address") if detectedDevices is None: self.bg_ser.write("h{}\n") # installed devices time.sleep(1) # get list of detected devices for line in self.bg_ser: if line[0] == 'h': detectedDevices = json_decode_response(line) for detectedDevice in detectedDevices: if device['p'] == detectedDevice['p']: device['a'] = detectedDevice['a'] # get address from sensor that was first on bus self.bg_ser.write("U" + json.dumps(device) + "\n") requestTime = time.time() # read log messages from controller while 1: # read all lines on serial interface line = self.bg_ser.read_line() if line: # line available? if line[0] == 'U': printStdErr(("%(a)s reports: device updated to: " % msg_map) + line[2:]) break message = self.bg_ser.read_message() if message: printStdErr(message) if time.time() - requestTime > 5: # wait max 5 seconds for an answer break printStdErr("Restoring installed devices done!")