예제 #1
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)
예제 #2
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))
예제 #3
0
def getNewTemp(scriptPath):
    with open(util.addSlash(scriptPath) + 'settings/tempProfile.csv',
              'rU') as csvfile:
        dialect = csv.Sniffer().sniff(csvfile.readline())
        csvfile.seek(0)
        temperatureReader = csv.reader(csvfile, dialect)
        next(temperatureReader
             )  # Discard the first row, which is the table header
        prevTemp = None
        nextTemp = None
        interpolatedTemp = -99
        prevDate = None
        nextDate = None

        now = time.mktime(
            time.localtime())  # Get current time in seconds since epoch

        for row in temperatureReader:
            dateString = row[0]
            try:
                date = time.mktime(
                    time.strptime(dateString, "%Y-%m-%dT%H:%M:%S"))
            except ValueError:
                continue  # Skip dates that cannot be parsed

            try:
                temperature = float(row[1])
            except ValueError:
                if row[1].strip() == '':
                    # Cell is left empty, this is allowed to disable temperature control in part of the profile
                    temperature = None
                else:
                    # Invalid number string, skip this row
                    continue

            prevTemp = nextTemp
            nextTemp = temperature
            prevDate = nextDate
            nextDate = date
            timeDiff = now - nextDate
            if timeDiff < 0:
                if prevDate is None:
                    interpolatedTemp = nextTemp  # First set point is in the future
                    break
                else:
                    if prevTemp is None or nextTemp is None:
                        # When the previous or next temperature is an empty cell, disable temperature control.
                        # This is useful to stop temperature control after a while or to not start right away.
                        interpolatedTemp = None
                    else:
                        interpolatedTemp = ((now - prevDate) /
                                            (nextDate - prevDate) *
                                            (nextTemp - prevTemp) + prevTemp)
                        interpolatedTemp = round(interpolatedTemp, 2)
                    break

        if interpolatedTemp == -99:  # All set points in the past
            interpolatedTemp = nextTemp

        return interpolatedTemp
예제 #4
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)
예제 #5
0
def startBeer(beerName):
    global config
    global localJsonFileName
    global localCsvFileName
    global wwwJsonFileName
    global wwwCsvFileName
    global lastDay
    global day

    # create directory for the data if it does not exist
    dataPath = util.addSlash(config["scriptPath"]) + "data/" + beerName + "/"
    wwwDataPath = util.addSlash(config["wwwPath"]) + "data/" + beerName + "/"

    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)  # sudgive group all permissions

        # Keep track of day and make new data tabe for each day
        # This limits data table size, which can grow very big otherwise
    day = time.strftime("%Y-%m-%d")
    lastDay = day
    # define a JSON file to store the data table
    jsonFileName = config["beerName"] + "-" + 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 + config["beerName"] + ".csv"
    wwwCsvFileName = wwwDataPath + config["beerName"] + ".csv"
    changeWwwSetting("beerName", beerName)
예제 #6
0
def getNewTemp(scriptPath):
    temperatureReader = csv.reader(	open(util.addSlash(scriptPath) + 'settings/tempProfile.csv', 'rb'),
                                    delimiter=',', quoting=csv.QUOTE_ALL)
    temperatureReader.next()  # discard the first row, which is the table header
    prevTemp = None
    nextTemp = None
    interpolatedTemp = -99
    prevDate = None
    nextDate = None


    now = time.mktime(time.localtime())  # get current time in seconds since epoch

    for row in temperatureReader:
        dateString = row[0]
        try:
            date = time.mktime(time.strptime(dateString, "%Y-%m-%dT%H:%M:%S"))
        except ValueError:
            continue  # skip dates that cannot be parsed

        try:
            temperature = float(row[1])
        except ValueError:
            if row[1].strip() == '':
                # cell is left empty, this is allowed to disable temperature control in part of the profile
                temperature = None
            else:
                # invalid number string, skip this row
                continue

        prevTemp = nextTemp
        nextTemp = temperature
        prevDate = nextDate
        nextDate = date
        timeDiff = now - nextDate
        if timeDiff < 0:
            if prevDate is None:
                interpolatedTemp = nextTemp  # first set point is in the future
                break
            else:
                if prevTemp is None or nextTemp is None:
                    # When the previous or next temperature is an empty cell, disable temperature control.
                    # This is useful to stop temperature control after a while or to not start right away.
                    interpolatedTemp = None
                else:
                    interpolatedTemp = ((now - prevDate) / (nextDate - prevDate) * (nextTemp - prevTemp) + prevTemp)
                    interpolatedTemp = round(interpolatedTemp, 2)
                break

    if interpolatedTemp == -99:  # all set points in the past
        interpolatedTemp = nextTemp

    return interpolatedTemp
예제 #7
0
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")
            wwwSettings = {}  # start with a fresh file when the json is corrupt.
    else:
        wwwSettingsFile = open(wwwSettingsFileName, 'w+b')  # create new file
        wwwSettings = {}

    wwwSettings[settingName] = str(value)
    wwwSettingsFile.seek(0)
    wwwSettingsFile.write(json.dumps(wwwSettings))
    wwwSettingsFile.truncate()
    wwwSettingsFile.close()
예제 #8
0
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")
            wwwSettings = {}  # start with a fresh file when the json is corrupt.
    else:
        wwwSettingsFile = open(wwwSettingsFileName, 'w+b')  # create new file
        wwwSettings = {}

    wwwSettings[settingName] = str(value)
    wwwSettingsFile.seek(0)
    wwwSettingsFile.write(json.dumps(wwwSettings))
    wwwSettingsFile.truncate()
    wwwSettingsFile.close()
예제 #9
0
	def __init__(self, cfg):
		""" Creates a BrewPi socket object and reads the settings from a BrewPi ConfigObj.
		Does not create a socket, just prepares the settings.

		Args:
		cfg: a ConfigObj object form a BrewPi config file
		"""

		self.type = 'f'  # default to file socket
		self.file = None
		self.host = 'localhost'
		self.port = None
		self.sock = 0

		isWindows = sys.platform.startswith('win')
		useInternetSocket = bool(cfg.get('useInternetSocket', isWindows))
		if useInternetSocket:
			self.port = cfg.get('socketPort', 6332)
			self.type = 'i'
		else:
			self.file = util.addSlash(cfg['scriptPath']) + 'BEERSOCKET'
예제 #10
0
# You should have received a copy of the GNU General Public License
# along with BrewPi.  If not, see <http://www.gnu.org/licenses/>.

import serial
import msvcrt
import sys
import os
import simplejson as json
import expandLogMessage
import BrewPiUtil as util

# Read in command line arguments
if len(sys.argv) < 2:
    print >> sys.stderr, 'Using default config path ./settings/config.cfg, to override use : %s <config file full path>' % sys.argv[0]
    configFile = util.addSlash(sys.path[0]) + 'settings/config.cfg'
else:
    configFile = sys.argv[1]

if not os.path.exists(configFile):
    sys.exit('ERROR: Config file "%s" was not found!' % configFile)

config = util.readCfgWithDefaults(configFile)

print "***** BrewPi Windows Test Terminal ****"
print "This simple Python script lets you send commands to the Arduino."
print "It also echoes everything the Arduino returns."
print "On known debug ID's in JSON format, it expands the messages to the full message"
print "press 's' to send a string to the Arduino, press 'q' to quit"

ser = 0
예제 #11
0
        if len(allProcesses.update()) > 1:  # if I am not the only one running
            allProcesses.quitAll()
            time.sleep(2)
            if len(allProcesses.update()) > 1:
                printStdErr("Asking the other processes to quit nicely did not work. Killing them with force!")
    # redirect output of stderr and stdout to files in log directory
    if o in ('-l', '--log'):
        logToFiles = True
    # only start brewpi when the dontrunfile is not found
    if o in ('-d', '--dontrunfile'):
        checkDontRunFile = True
    if o in ('--checkstartuponly'):
        checkStartupOnly = True

if not configFile:
    configFile = util.addSlash(sys.path[0]) + 'settings/config.cfg'

config = util.readCfgWithDefaults(configFile)

dontRunFilePath = os.path.join(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(0)

# 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):
예제 #12
0
import msvcrt
import sys
import os
# import simplejson as json
import json

# append parent directory to be able to import files
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/..")
import expandLogMessage
import BrewPiUtil as util

# Read in command line arguments
if len(sys.argv) < 2:
    print >> sys.stderr, 'Using default config path ./settings/config.cfg, to override use : %s <config file full path>' % sys.argv[
        0]
    configFile = util.addSlash(sys.path[0]) + '../settings/config.cfg'
else:
    configFile = sys.argv[1]

if not os.path.exists(configFile):
    sys.exit('ERROR: Config file "%s" was not found!' % configFile)

config = util.readCfgWithDefaults(configFile)

print "***** BrewPi Windows Test Terminal ****"
print "This simple Python script lets you send commands to the Arduino."
print "It also echoes everything the Arduino returns."
print "On known debug ID's in JSON format, it expands the messages to the full message"
print "press 's' to send a string to the Arduino, press 'q' to quit"

# open serial port
예제 #13
0
                # complete line received, [0] is complete line [1] is separator [2] is the rest
                self.buffer = lines[2]
                return self.__asciiToUnicode(lines[0])

    # remove extended ascii characters from string, because they can raise UnicodeDecodeError later
    def __asciiToUnicode(self, s):
        s = s.replace(chr(0xB0), '&deg')
        return unicode(s, 'ascii', 'ignore')

if __name__ == '__main__':
    # some test code that requests data from serial and processes the response json
    import simplejson
    import time
    import BrewPiUtil as util

    config_file = util.addSlash(sys.path[0]) + 'settings/config.cfg'
    config = util.readCfgWithDefaults(config_file)
    ser = util.setupSerial(config, time_out=0)
    if not ser:
        printStdErr("Could not open Serial Port")
        exit()

    bg_ser = BackGroundSerial(ser)
    bg_ser.start()

    success = 0
    fail = 0
    for i in range(1, 5):
        # request control variables 4 times. This would overrun buffer if it was not read in a background thread
        # the json decode will then fail, because the message is clipped
        bg_ser.write('v')
예제 #14
0
            time.sleep(2)
            if len(allProcesses.update()) > 1:
                printStdErr(
                    "Asking the other processes to quit nicely did not work. Killing them with force!"
                )
    # redirect output of stderr and stdout to files in log directory
    if o in ('-l', '--log'):
        logToFiles = True
    # only start brewpi when the dontrunfile is not found
    if o in ('-d', '--dontrunfile'):
        checkDontRunFile = True
    if o in ('--checkstartuponly'):
        checkStartupOnly = True

if not configFile:
    configFile = util.addSlash(sys.path[0]) + 'settings/config.cfg'

config = util.readCfgWithDefaults(configFile)

dontRunFilePath = os.path.join(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(0)

# 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):
예제 #15
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!"
    # redirect output of stderr and stdout to files in log directory
    if o in ('-l', '--log'):
        logToFiles = True
    # only start brewpi when the dontrunfile is not found
    if o in ('-d', '--dontrunfile'):
        checkDontRunFile = True
    if o in ('--checkstartuponly'):
        checkStartupOnly = True

if not configFile:
    configFile = util.addSlash(sys.path[0]) + '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(0)

# 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):
예제 #16
0
    # request settings from Arduino, processed later when reply is received
    ser.write("s")  # request control settings cs
    ser.write("c")  # request control constants cc
    # answer from Arduino is received asynchronously later.

# create a listening socket to communicate with PHP
is_windows = sys.platform.startswith("win")
useInetSocket = bool(config.get("useInetSocket", is_windows))
if useInetSocket:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    port = config.get("socketPort", 6332)
    s.bind((config.get("socketHost", "localhost"), int(port)))
    logMessage("Bound to TCP socket on port %d " % port)
else:
    socketFile = util.addSlash(config["scriptPath"]) + "BEERSOCKET"
    if os.path.exists(socketFile):
        # if socket already exists, remove it
        os.remove(socketFile)
    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(socketFile)  # Bind BEERSOCKET
    # set all permissions for socket
    os.chmod(socketFile, 0777)

serialCheckInterval = 0.5
s.setblocking(1)  # set socket functions to be blocking
s.listen(10)  # Create a backlog queue for up to 10 connections
# blocking socket functions wait 'serialCheckInterval' seconds
s.settimeout(serialCheckInterval)