예제 #1
0
    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))
예제 #2
0
    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
예제 #3
0
    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 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)
예제 #5
0
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)
예제 #6
0
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)
예제 #7
0
    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
예제 #8
0
 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
예제 #9
0
    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)
예제 #10
0
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
예제 #11
0
            "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):
예제 #12
0
                    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! ")
예제 #13
0
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
예제 #14
0
                    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)
예제 #15
0
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
예제 #16
0
        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")
예제 #17
0
     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
예제 #18
0
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
예제 #19
0
                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
예제 #20
0
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()
예제 #21
0
        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):