def save_settings_to_file(self): # This is format" "2019-01-08-16-50-15" oldSettingsFileName = 'settings-{0}.json'.format(time.strftime("%Y-%m-%dT%H-%M-%S")) settingsBackupDir = '{0}settings/controller-backup/'.format(util.addSlash(util.scriptPath())) if not os.path.exists(settingsBackupDir): os.makedirs(settingsBackupDir) # Set owner and permissions for directory fileMode = stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH # 775 owner = 'brewpi' group = 'brewpi' uid = pwd.getpwnam(owner).pw_uid gid = grp.getgrnam(group).gr_gid os.chown(settingsBackupDir, uid, gid) # chown dir os.chmod(settingsBackupDir, fileMode) # chmod dir oldSettingsFilePath = os.path.join( settingsBackupDir, oldSettingsFileName) oldSettingsFile = open(oldSettingsFilePath, 'w') oldSettingsFile.write(json.dumps(self.oldSettings)) oldSettingsFile.truncate() oldSettingsFile.close() # Set owner and permissions for file fileMode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP # 660 owner = 'brewpi' group = 'brewpi' uid = pwd.getpwnam(owner).pw_uid gid = grp.getgrnam(group).gr_gid os.chown(oldSettingsFilePath, uid, gid) # chown file os.chmod(oldSettingsFilePath, fileMode) # chmod file printStdErr("\nSaved old settings to file {0}.".format(oldSettingsFileName))
def parseProcess(self, process): """ Converts a psutil process into a BrewPiProcess object by parsing the config file it has been called with. Params: a psutil.Process object Returns: BrewPiProcess object """ bp = BrewPiProcess() db_config = None cfg = None try: bp.pid = process._pid try: # If this is a database configured installation, try loading via the process ID db_config = models.BrewPiDevice.objects.get(process_id=bp.pid) except: cfg = [s for s in process.cmdline() if '.cfg' in s] # get config file argument except psutil.NoSuchProcess: # process no longer exists return None if db_config is not None: # If this is a database-configured installation, use the database configuration bp.cfg = util.read_config_from_database_without_defaults(db_config) else: if cfg: cfg = cfg[0] # add full path to config file else: # use default config file location cfg = util.scriptPath() + "/settings/config.cfg" bp.cfg = util.read_config_file_with_defaults(cfg) bp.port = bp.cfg['port'] bp.sock = BrewPiSocket.BrewPiSocket(bp.cfg) return bp
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 setFiles(): global config global localJsonFileName global localCsvFileName global wwwJsonFileName global wwwCsvFileName global lastDay global day # create directory for the data if it does not exist beerFileName = config['beerName'] dataPath = util.addSlash( util.addSlash(util.scriptPath()) + 'data/' + beerFileName) wwwDataPath = util.addSlash( util.addSlash(config['wwwPath']) + 'data/' + beerFileName) if not os.path.exists(dataPath): os.makedirs(dataPath) os.chmod(dataPath, 0775) # give group all permissions if not os.path.exists(wwwDataPath): os.makedirs(wwwDataPath) os.chmod(wwwDataPath, 0775) # give group all permissions # Keep track of day and make new data file for each day day = time.strftime("%Y-%m-%d") lastDay = day # define a JSON file to store the data jsonFileName = beerFileName + '-' + day #if a file for today already existed, add suffix if os.path.isfile(dataPath + jsonFileName + '.json'): i = 1 while os.path.isfile(dataPath + jsonFileName + '-' + str(i) + '.json'): i += 1 jsonFileName = jsonFileName + '-' + str(i) localJsonFileName = dataPath + jsonFileName + '.json' brewpiJson.newEmptyFile(localJsonFileName) # Define a location on the web server to copy the file to after it is written wwwJsonFileName = wwwDataPath + jsonFileName + '.json' # Define a CSV file to store the data as CSV (might be useful one day) localCsvFileName = (dataPath + beerFileName + '.csv') wwwCsvFileName = (wwwDataPath + beerFileName + '.csv') # create new empty json file brewpiJson.newEmptyFile(localJsonFileName)
def setFiles(): global config global localJsonFileName global localCsvFileName global wwwJsonFileName global wwwCsvFileName global lastDay global day # create directory for the data if it does not exist beerFileName = config['beerName'] dataPath = util.addSlash(util.addSlash(util.scriptPath()) + 'data/' + beerFileName) wwwDataPath = util.addSlash(util.addSlash(config['wwwPath']) + 'data/' + beerFileName) if not os.path.exists(dataPath): os.makedirs(dataPath) os.chmod(dataPath, 0775) # give group all permissions if not os.path.exists(wwwDataPath): os.makedirs(wwwDataPath) os.chmod(wwwDataPath, 0775) # give group all permissions # Keep track of day and make new data file for each day day = time.strftime("%Y-%m-%d") lastDay = day # define a JSON file to store the data jsonFileName = beerFileName + '-' + day #if a file for today already existed, add suffix if os.path.isfile(dataPath + jsonFileName + '.json'): i = 1 while os.path.isfile(dataPath + jsonFileName + '-' + str(i) + '.json'): i += 1 jsonFileName = jsonFileName + '-' + str(i) localJsonFileName = dataPath + jsonFileName + '.json' brewpiJson.newEmptyFile(localJsonFileName) # Define a location on the web server to copy the file to after it is written wwwJsonFileName = wwwDataPath + jsonFileName + '.json' # Define a CSV file to store the data as CSV (might be useful one day) localCsvFileName = (dataPath + beerFileName + '.csv') wwwCsvFileName = (wwwDataPath + beerFileName + '.csv') # create new empty json file brewpiJson.newEmptyFile(localJsonFileName)
def parseProcess(self, process): """ Converts a psutil process into a BrewPiProcess object by parsing the config file it has been called with. Params: a psutil.Process object Returns: BrewPiProcess object """ bp = BrewPiProcess() bp.pid = process._pid cfg = [s for s in process.cmdline() if '.cfg' in s] # get config file argument if cfg: cfg = cfg[0] # add full path to config file else: # use default config file location cfg = util.scriptPath() + "/settings/config.cfg" bp.cfg = util.readCfgWithDefaults(cfg) bp.port = bp.cfg['port'] bp.sock = BrewPiSocket.BrewPiSocket(bp.cfg) return bp
def parseProcess(self, process): """ Converts a psutil process into a BrewPiProcess object by parsing the config file it has been called with. Params: a psutil.Process object Returns: BrewPiProcess object """ bp = BrewPiProcess() try: bp.pid = process._pid cfg = [s for s in process.cmdline() if '.cfg' in s] # get config file argument except psutil.NoSuchProcess: # process no longer exists return None if cfg: cfg = cfg[0] # add full path to config file else: # use default config file location cfg = util.scriptPath() + "/settings/config.cfg" bp.cfg = util.readCfgWithDefaults(cfg) bp.port = bp.cfg['port'] bp.sock = BrewPiSocket.BrewPiSocket(bp.cfg) return bp
def save_settings(self): ser, oldSettings = self.ser, self.oldSettings oldSettings.clear() printStdErr("Requesting old settings from %(a)s..." % msg_map) expected_responses = 2 if self.avrVersionOld.minor > 1: # older versions did not have a device manager expected_responses += 1 ser.write("d{}") # installed devices time.sleep(1) ser.write("c") # control constants ser.write("s") # control settings time.sleep(2) while expected_responses: line = ser.readline() if line: if line[0] == 'C': expected_responses -= 1 oldSettings['controlConstants'] = json_decode_response(line) elif line[0] == 'S': expected_responses -= 1 oldSettings['controlSettings'] = json_decode_response(line) elif line[0] == 'd': expected_responses -= 1 oldSettings['installedDevices'] = json_decode_response(line) oldSettingsFileName = 'oldAvrSettings-' + time.strftime("%b-%d-%Y-%H-%M-%S") + '.json' scriptDir = util.scriptPath() # <-- absolute dir the script is in if not os.path.exists(scriptDir + '/settings/avr-backup/'): os.makedirs(scriptDir + '/settings/avr-backup/') oldSettingsFile = open(scriptDir + '/settings/avr-backup/' + oldSettingsFileName, 'wb') oldSettingsFile.write(json.dumps(oldSettings)) oldSettingsFile.truncate() oldSettingsFile.close() printStdErr("Saved old settings to file " + oldSettingsFileName)
def updateFromGitHub(userInput = False, 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 boardName = None family = None ser = None ### Get version number printStdErr("\nChecking current firmware version...") try: ser = util.setupSerial(config) hwVersion = brewpiVersion.getVersionFromSerial(ser) family = hwVersion.family shield = hwVersion.shield board = hwVersion.board boardName = hwVersion.boardName() except: printStdErr("Unable to connect to controller, perhaps it is disconnected or otherwise unavailable.") return -1 if ser: ser.close() # close serial port ser = None if not hwVersion: printStdErr("Unable to retrieve firmware version from controller") printStdErr("If your controller has not been programmed with an earlier version of BrewPi," " follow these instructions:") printStdErr("\n If you have an Arduino:") printStdErr("Please go to https://github.com/BrewPi/firmware/releases to download" "the firmware and upload via the BrewPi web interface") printStdErr("\n If you have a Spark Core:") printStdErr("Put it in DFU mode and run: sudo /home/brewpi/utils/flashDfu.py") else: printStdErr("Current firmware version on controller: " + hwVersion.toString()) printStdErr("\nChecking GitHub for latest release...") releases = gitHubReleases("https://api.github.com/repos/BrewPi/firmware") latest = releases.getLatestTag() printStdErr("Latest version on GitHub: " + latest) if hwVersion.isNewer(latest): printStdErr("\nVersion on GitHub is newer than your current version, downloading new version...") else: printStdErr("\nYour current firmware version is up-to-date. There is no need to update.") 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 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 else: return 0 printStdErr("Downloading latest firmware...") localFileName = None if family == "Arduino": localFileName = releases.getBin(latest, [boardName, shield, ".hex"]) elif family == "Spark": localFileName = releases.getBin(latest, [boardName, ".bin"]) if localFileName: printStdErr("Latest firmware downloaded to " + localFileName) else: printStdErr("Downloading firmware failed") return -1 result = programmer.programController(config, board, localFileName, {'settings': restoreSettings, 'devices': restoreDevices}) util.removeDontRunFile(config['wwwPath'] + "/do_not_run_brewpi") return result
"Another instance of BrewPi is already running, which will conflict with this instance. " + "This instance will exit") exit(0) if checkStartupOnly: exit(1) localJsonFileName = "" localCsvFileName = "" wwwJsonFileName = "" wwwCsvFileName = "" lastDay = "" day = "" if logToFiles: logPath = util.addSlash(util.scriptPath()) + 'logs/' logMessage( "Redirecting output to log files in %s, output will not be shown in console" % logPath) sys.stderr = open(logPath + 'stderr.txt', 'a', 0) # append to stderr file, unbuffered sys.stdout = open(logPath + 'stdout.txt', 'w', 0) # overwrite stdout file on script start, unbuffered # userSettings.json is a copy of some of the settings that are needed by the web server. # This allows the web server to load properly, even when the script is not running. def changeWwwSetting(settingName, value): wwwSettingsFileName = util.addSlash( config['wwwPath']) + 'userSettings.json' if os.path.exists(wwwSettingsFileName):
print "Updating system firmware for the {0}, part 2: {1}".format(device_type, system2) p = subprocess.Popen(dfuPath + " -d {0} -a 0 -s 0x8060000 -D {1}".format(pid_vid[device_type], system2), shell=True) p.wait() time.sleep(1) print "Now writing BrewPi firmware {0} to {1}".format(binFile, device_type) p = subprocess.Popen(dfuPath + " -d {0} -a 0 -s 0x80A0000:leave -D {1}".format(pid_vid[device_type], binFile), shell=True) p.wait() time.sleep(1) print "Programming done" if not noReset: print "Now resetting EEPROM to defaults" # reset EEPROM to defaults configFile = util.scriptPath() + '/settings/config.cfg' config = util.readCfgWithDefaults(configFile) config_copy = config if 'socket:' in config['port']: print "Socket configured as serial port, using auto detect to find USB serial" config_copy['port'] = 'auto' raw_input("Press Enter to continue...") programmer = SerialProgrammer.create(config_copy, device_type) # open serial port print "Opening serial port to reset factory defaults" if not programmer.open_serial_with_retry(config_copy, 57600, 1): print "Could not open serial port after programming" else: programmer.fetch_version("Success! ")
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 ser = None ### Get version number printStdErr("\nChecking current firmware version...") try: ser = util.setupSerial(config) hwVersion = brewpiVersion.getVersionFromSerial(ser) family = hwVersion.family shield = hwVersion.shield board = hwVersion.board printStdErr("Found " + hwVersion.toExtendedString() + " on port " + ser.name + "\n") except: if hwVersion is None: 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 "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 if ser: ser.close() # close serial port ser = None 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), compatibleTags[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": if hwVersion: oldVersion = hwVersion.version.vstring else: oldVersion = "0.0.0" latestSystemTag = releases.getLatestTagForSystem(prerelease=beta, since=oldVersion) if latestSystemTag is not None: printStdErr("Updated system firmware for the photon found in release {0}".format(latestSystemTag)) system1 = releases.getBin(latestSystemTag, ["photon", "system-part1", ".bin"]) system2 = releases.getBin(latestSystemTag, ["photon", "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
print "Updating system firmware for the {0}, part 2: {1}".format(device_type, system2) p = subprocess.Popen(dfuPath + " -d {0} -a 0 -s 0x8060000 -D {1}".format(pid_vid[device_type], system2), shell=True) p.wait() time.sleep(1) print "Now writing BrewPi firmware {0} to {1}".format(binFile, device_type) p = subprocess.Popen(dfuPath + " -d {0} -a 0 -s 0x80A0000:leave -D {1}".format(pid_vid[device_type], binFile), shell=True) p.wait() time.sleep(1) print "Programming done" if not noReset: print "Now resetting EEPROM to defaults" # reset EEPROM to defaults configFile = util.scriptPath() + '/settings/config.cfg' config = util.readCfgWithDefaults(configFile) config_copy = config if 'socket:' in config['port']: print "Socket configured as serial port, using auto detect to find USB serial" config_copy['port'] = 'auto' programmer = SerialProgrammer.create(config_copy, device_type) # open serial port print "Opening serial port to reset factory defaults" if not programmer.open_serial_with_retry(config_copy, 57600, 1): print "Could not open serial port after programming" else: programmer.fetch_version("Success! ") time.sleep(5) programmer.reset_settings(testMode)
def updateFromGitHub(userInput=False, 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 boardName = None family = None ser = None ### Get version number printStdErr("\nChecking current firmware version...") try: ser = util.setupSerial(config) hwVersion = brewpiVersion.getVersionFromSerial(ser) family = hwVersion.family shield = hwVersion.shield board = hwVersion.board boardName = hwVersion.boardName() printStdErr("Found " + hwVersion.toExtendedString() + \ " on port " + ser.name + "\n") except: printStdErr( "Unable to connect to controller, perhaps it is disconnected or otherwise unavailable." ) return -1 if ser: ser.close() # close serial port ser = None if not hwVersion: printStdErr("Unable to retrieve firmware version from controller") printStdErr( "If your controller has not been programmed with an earlier version of BrewPi," " follow these instructions:") printStdErr("\n If you have an Arduino:") printStdErr( "Please go to https://github.com/BrewPi/firmware/releases to download" "the firmware and upload via the BrewPi web interface") printStdErr("\n If you have a Spark Core:") printStdErr( "Put it in DFU mode and run: sudo /home/brewpi/utils/flashDfu.py") else: printStdErr("Current firmware version on controller: " + hwVersion.toString()) printStdErr("\nChecking GitHub for latest release...") releases = gitHubReleases("https://api.github.com/repos/BrewPi/firmware") tag = releases.getLatestTag() printStdErr("Latest version on GitHub: " + tag) if hwVersion.isNewer(tag): printStdErr( "\nVersion on GitHub is newer than your current version, downloading new version..." ) else: printStdErr( "\nYour current firmware version is up-to-date. There is no need to update." ) 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 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 else: return 0 printStdErr("Downloading latest firmware...") localFileName = None system1 = None system2 = None if family == "Arduino": localFileName = releases.getBin(tag, [boardName, shield, ".hex"]) elif family == "Spark" or family == "Particle": localFileName = releases.getBin(tag, [boardName, 'brewpi', '.bin']) else: printStdErr("Error: Device family {0} not recognized".format(family)) return -1 if boardName == "Photon": latestSystemTag = releases.getLatestTagForSystem() if hwVersion.isNewer(latestSystemTag): printStdErr( "Updated system firmware for the photon found in release {0}". format(latestSystemTag)) system1 = releases.getBin(latestSystemTag, ['photon', 'system-part1', '.bin']) system2 = releases.getBin(latestSystemTag, ['photon', 'system-part2', '.bin']) if system1: printStdErr("Downloaded new system firmware to:\n") printStdErr("{0} and\n".format(system1)) if not system2: printStdErr("{0}\n".format(system2)) printStdErr( "Error: system firmware part2 not found in release") return -1 if localFileName: printStdErr("Latest firmware downloaded to " + localFileName) else: printStdErr("Downloading firmware failed") return -1 printStdErr("\nUpdating firmware over Serial...\n") result = programmer.programController(config, board, localFileName, system1, system2, { 'settings': restoreSettings, 'devices': restoreDevices }) util.removeDontRunFile(config['wwwPath'] + "/do_not_run_brewpi") return result
logMessage("Another instance of BrewPi is already running, which will conflict with this instance. " + "This instance will exit") exit(0) if checkStartupOnly: exit(1) localJsonFileName = "" localCsvFileName = "" wwwJsonFileName = "" wwwCsvFileName = "" lastDay = "" day = "" if logToFiles: logPath = util.addSlash(util.scriptPath()) + 'logs/' logMessage("Redirecting output to log files in %s, output will not be shown in console" % logPath) sys.stderr = open(logPath + 'stderr.txt', 'a', 0) # append to stderr file, unbuffered sys.stdout = open(logPath + 'stdout.txt', 'w', 0) # overwrite stdout file on script start, unbuffered # userSettings.json is a copy of some of the settings that are needed by the web server. # This allows the web server to load properly, even when the script is not running. def changeWwwSetting(settingName, value): wwwSettingsFileName = util.addSlash(config['wwwPath']) + 'userSettings.json' if os.path.exists(wwwSettingsFileName): wwwSettingsFile = open(wwwSettingsFileName, 'r+b') try: wwwSettings = json.load(wwwSettingsFile) # read existing settings except json.JSONDecodeError: logMessage("Error in decoding userSettings.json, creating new empty json file")
logMessage("stopScript message received on socket. " + "Stopping script and writing dontrunfile to prevent automatic restart") run = 0 dontrunfile = open(dontRunFilePath, "w") dontrunfile.write("1") dontrunfile.close() continue elif messageType == "quit": # quit instruction received. Probably sent by another brewpi script instance logMessage("quit message received on socket. Stopping script.") run = 0 # Leave dontrunfile alone. # This instruction is meant to restart the script or replace it with another instance. continue elif messageType == "eraseLogs": # erase the log files for stderr and stdout open(util.scriptPath() + '/logs/stderr.txt', 'wb').close() open(util.scriptPath() + '/logs/stdout.txt', 'wb').close() logMessage("Fresh start! Log files erased.") continue elif messageType == "interval": # new interval received newInterval = int(value) if 5 < newInterval < 5000: try: config = util.configSet(configFile, 'interval', float(newInterval)) except ValueError: logMessage("Cannot convert interval '" + value + "' to float") continue logMessage("Notification: Interval changed to " + str(newInterval) + " seconds") elif messageType == "startNewBrew": # new beer name newName = value
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
oldSettings["controlConstants"] = json.loads(line[2:]) elif line[0] == "S": oldSettings["controlSettings"] = json.loads(line[2:]) elif line[0] == "d": oldSettings["installedDevices"] = json.loads(line[2:]) except json.decoder.JSONDecodeError, e: printStdErr("JSON decode error: " + str(e)) printStdErr("Line received was: " + line) ser.close() del ser # Arduino won't reset when serial port is not completely removed oldSettingsFileName = "oldAvrSettings-" + time.strftime("%b-%d-%Y-%H-%M-%S") + ".json" printStdErr("Saving old settings to file " + oldSettingsFileName) scriptDir = util.scriptPath() # <-- absolute dir the script is in if not os.path.exists(scriptDir + "/settings/avr-backup/"): os.makedirs(scriptDir + "/settings/avr-backup/") oldSettingsFile = open(scriptDir + "/settings/avr-backup/" + oldSettingsFileName, "wb") oldSettingsFile.write(json.dumps(oldSettings)) oldSettingsFile.truncate() oldSettingsFile.close() printStdErr("Loading programming settings from board.txt") # parse the Arduino board file to get the right program settings for line in boardsFile: if line.startswith(boardType): # strip board name, period and \n
def programArduino(config, boardType, hexFile, restoreWhat): printStdErr("**** Arduino Program script started ****") arduinohome = config.get('arduinoHome', '/usr/share/arduino/') # location of Arduino sdk avrdudehome = config.get('avrdudeHome', arduinohome + 'hardware/tools/') # location of avr tools avrsizehome = config.get('avrsizeHome', '') # default to empty string because avrsize is on path avrconf = config.get('avrConf', avrdudehome + 'avrdude.conf') # location of global avr conf boardsFile = loadBoardsFile(arduinohome) boardSettings = fetchBoardSettings(boardsFile, boardType) 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 "")) ser, port = openSerial(config['port'], config['altport'], 57600, 0.2) if ser is None: printStdErr("Could not open serial port. Programming aborted.") return 0 time.sleep(5) # give the arduino some time to reboot in case of an Arduino UNO printStdErr("Checking old version before programming.") avrVersionOld = brewpiVersion.getVersionFromSerial(ser) if avrVersionOld is None: printStdErr(("Warning: Cannot receive version number from Arduino. " + "Your Arduino is either not programmed yet or running a very old version of BrewPi. " "Arduino will be reset to defaults.")) else: printStdErr("Found " + avrVersionOld.toExtendedString() + \ " on port " + port + "\n") oldSettings = {} # request all settings from board before programming if avrVersionOld is not None: printStdErr("Requesting old settings from Arduino...") if avrVersionOld.minor > 1: # older versions did not have a device manager ser.write("d{}") # installed devices time.sleep(1) ser.write("c") # control constants ser.write("s") # control settings time.sleep(2) for line in ser: try: if line[0] == 'C': oldSettings['controlConstants'] = json.loads(line[2:]) elif line[0] == 'S': oldSettings['controlSettings'] = json.loads(line[2:]) elif line[0] == 'd': oldSettings['installedDevices'] = json.loads(line[2:]) except json.decoder.JSONDecodeError, e: printStdErr("JSON decode error: " + str(e)) printStdErr("Line received was: " + line) oldSettingsFileName = 'oldAvrSettings-' + time.strftime("%b-%d-%Y-%H-%M-%S") + '.json' printStdErr("Saving old settings to file " + oldSettingsFileName) scriptDir = util.scriptPath() # <-- absolute dir the script is in if not os.path.exists(scriptDir + '/settings/avr-backup/'): os.makedirs(scriptDir + '/settings/avr-backup/') oldSettingsFile = open(scriptDir + '/settings/avr-backup/' + oldSettingsFileName, 'wb') oldSettingsFile.write(json.dumps(oldSettings)) oldSettingsFile.truncate() oldSettingsFile.close()
if len(allProcesses.update()) > 1: # if I am not the only one running allProcesses.quitAll() time.sleep(2) if len(allProcesses.update()) > 1: print "Asking the other processes to quit nicely did not work. Killing them with force!" # only start brewpi when the donotrunfile is not found if o in ("-d", "--dontrunfile"): checkDontRunFile = True if not configFile: if not checkDontRunFile: # Do not print when this option is active. CRON uses it and it will flood the logs print >> sys.stderr, ( "Using default config path <script dir>/settings/config.cfg, " + "to override use: %s --config <config file full path>" % sys.argv[0] ) configFile = util.scriptPath() + "/settings/config.cfg" config = util.readCfgWithDefaults(configFile) dontRunFilePath = config["wwwPath"] + "do_not_run_brewpi" # check dont run file when it exists and exit it it does if checkDontRunFile: if os.path.exists(dontRunFilePath): # do not print anything, this will flood the logs exit() # check for other running instances of BrewPi that will cause conflicts with this instance allProcesses = BrewPiProcess.BrewPiProcesses() allProcesses.update() myProcess = allProcesses.me() if allProcesses.findConflicts(myProcess):