def __init__(self): self.OPTION_USE_3_WIRE_VALVES = self.getConfigValueByName( "use3WireValves") self.OPTION_RESTART_FANTIMER_AFTER_POUR = self.getConfigValueByName( "restartFanAfterPour") setupSocket = MCAST_RETRY_ATTEMPTS if GPIO_IMPORT_SUCCESSFUL: GPIO.setwarnings(False) GPIO.setmode(GPIO.BOARD) # Broadcom pin-numbering scheme self.alaModeReconfig = False while setupSocket > 0: try: #multicast socket self.mcast = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self.mcast.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1) mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) self.mcast.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) setupSocket = 0 except socket.error as msg: setupSocket = setupSocket - 1 log(msg.strerror + " - Sleeping to try again") time.sleep(MCAST_RETRY_SLEEP_SEC) if setupSocket == MCAST_RETRY_ATTEMPTS: log(str(setupSocket)) log("FATAL: Unable to setup socket") quit() self.valvesState = [] self.fanTimer = None self.valvePowerTimer = None if int(self.OPTION_USE_3_WIRE_VALVES) == 1: self.valvePowerTimer = Timer(OPTION_VALVEPOWERON, self.valveStopPower) self.updateFlowmeterConfig() self.updateValvePins() self.commandserver = CommandTCPServer(('localhost', MCAST_PORT), CommandTCPHandler) self.commandserver.pintdispatch = self self.fanControl = FanControlThread("fanControl1", self) self.flowmonitor = FlowMonitor(self)
class PintDispatch(object): def __init__(self): self.OPTION_USE_3_WIRE_VALVES = self.getConfigValueByName( "use3WireValves") self.OPTION_RESTART_FANTIMER_AFTER_POUR = self.getConfigValueByName( "restartFanAfterPour") setupSocket = MCAST_RETRY_ATTEMPTS if GPIO_IMPORT_SUCCESSFUL: GPIO.setwarnings(False) GPIO.setmode(GPIO.BOARD) # Broadcom pin-numbering scheme self.alaModeReconfig = False while setupSocket > 0: try: #multicast socket self.mcast = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self.mcast.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1) mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) self.mcast.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) setupSocket = 0 except socket.error as msg: setupSocket = setupSocket - 1 log(msg.strerror + " - Sleeping to try again") time.sleep(MCAST_RETRY_SLEEP_SEC) if setupSocket == MCAST_RETRY_ATTEMPTS: log(str(setupSocket)) log("FATAL: Unable to setup socket") quit() self.valvesState = [] self.fanTimer = None self.valvePowerTimer = None if int(self.OPTION_USE_3_WIRE_VALVES) == 1: self.valvePowerTimer = Timer(OPTION_VALVEPOWERON, self.valveStopPower) self.updateFlowmeterConfig() self.updateValvePins() self.commandserver = CommandTCPServer(('localhost', MCAST_PORT), CommandTCPHandler) self.commandserver.pintdispatch = self self.fanControl = FanControlThread("fanControl1", self) self.flowmonitor = FlowMonitor(self) def parseConnFile(self): connFileName = ADMIN_INCLUDES_DIR + "/conn.php" connDict = dict() with open(connFileName) as connFile: for line in connFile: instructions = line.split(";") if (len(instructions) < 1): continue php = instructions[0].strip() php = php.strip("$") keyValue = php.split("=") if (len(keyValue) != 2): continue connDict[keyValue[0]] = keyValue[1].strip("\"") return connDict def connectDB(self): cp = self.parseConnFile() con = mdb.connect(cp['host'], cp['username'], cp['password'], cp['db_name']) return con def getConfig(self): con = self.connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT * from config") rows = cursor.fetchall() con.close() return rows def getConfigValueByName(self, name): con = self.connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT configValue from config WHERE configName='" + name + "'") rows = cursor.fetchall() con.close() if len(rows) == 0: return None return rows[0]['configValue'] def getTapConfig(self): con = self.connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute( "SELECT tc.tapId,tc.flowPin,tc.valvePin,tc.valveOn FROM tapconfig tc LEFT JOIN taps t ON tc.tapId = t.id WHERE t.active = 1 ORDER BY tc.tapId" ) rows = cursor.fetchall() con.close() return rows def getRFIDReaders(self): con = self.connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT * from rfidReaders ORDER BY priority") rows = cursor.fetchall() con.close() return rows def getMotionDetectors(self): con = self.connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT * from motionDetectors ORDER BY priority") rows = cursor.fetchall() con.close() return rows def getLoadCellConfig(self): con = self.connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute( "SELECT tapId,loadCellCmdPin,loadCellRspPin,loadCellUnit FROM tapconfig WHERE loadCellCmdPin IS NOT NULL ORDER BY tapId" ) rows = cursor.fetchall() con.close() return rows def getTareRequest(self, tapId): con = self.connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute( "SELECT tapId,loadCellTareReq FROM tapconfig WHERE tapId = " + str(tapId)) rows = cursor.fetchall() con.close() if len(rows) == 0: return False return rows[0]['loadCellTareReq'] == 1 def setTareRequest(self, tapId, tareRequested): tareReq = "0" if tareRequested: tareReq = "1" sql = "UPDATE tapconfig SET loadCellTareReq=" + tareReq if not tareRequested: sql = sql + ",loadCellTareDate=NOW()" sql = sql + " WHERE tapId = " + str(tapId) con = self.connectDB() cursor = con.cursor(mdb.cursors.DictCursor) result = cursor.execute(sql) con.commit() con.close() def addTempProbeAsNeeded(self, probe): sql = "SELECT * FROM tempProbes WHERE name='" + probe + "';" con = self.connectDB() cursor = con.cursor(mdb.cursors.DictCursor) result = cursor.execute(sql) if (cursor.rowcount <= 0): cursor.execute("INSERT INTO tempProbes (name, type) VALUES('" + probe + "', 0)") con.commit() con.close() def saveTemp(self, probe, temp, tempUnit): insertLogSql = "INSERT INTO tempLog (probe, temp, tempUnit, takenDate) " insertLogSql += "VALUES('" + probe + "'," + str( temp ) + "+ COALESCE((SELECT manualAdj FROM tempProbes WHERE name = '" + probe + "'), 0), '" + str( tempUnit) + "', NOW());" con = self.connectDB() cursor = con.cursor(mdb.cursors.DictCursor) result = cursor.execute(insertLogSql) con.commit() con.close() self.archiveTemp() def getTempProbeConfig(self): useTempProbes = self.getConfigValueByName("useTempProbes") if (useTempProbes is not None and int(useTempProbes) == 1): return True return False #set to -1 so on startup archive is checked lastArchiveCheck = -1 #Combine all readings older than 2 months into 1 average for the month to reduce rows in the table def archiveTemp(self): #only archive if the month has changed if self.lastArchiveCheck == datetime.datetime.now().month: return insertLogSql = """INSERT INTO tempLog (takenDate, probe, temp, humidity) (SELECT CAST(DATE_FORMAT(takenDate,'%Y-%m-01') as DATE), 'History', TRUNCATE(AVG(temp), 2), TRUNCATE(hl.humidity, 2) FROM tempLog tl LEFT JOIN (SELECT CAST(DATE_FORMAT(takenDate,'%Y-%m-01') AS DATE) as takenMonth, AVG(humidity) AS humidity FROM tempLog WHERE probe != 'History' AND humidity IS NOT NULL AND takenDate < CAST(DATE_FORMAT(NOW() ,'%Y-%m-01') as DATE) GROUP BY MONTH(takenDate)) hl ON CAST(DATE_FORMAT(tl.takenDate,'%Y-%m-01') as DATE) = hl.takenMonth WHERE probe != 'History' AND takenDate < CAST(DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 1 MONTH) ,'%Y-%m-01') as DATE) GROUP BY MONTH(takenDate));""" deleteSQL = """DELETE FROM tempLog WHERE probe != 'History' AND takenDate < CAST(DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 1 MONTH) ,'%Y-%m-01') as DATE) ;""" con = self.connectDB() cursor = con.cursor(mdb.cursors.DictCursor) result = cursor.execute(insertLogSql) result = cursor.execute(deleteSQL) con.commit() con.close() self.lastArchiveCheck = datetime.datetime.now().month def useFanControl(self): useFanControl = self.getConfigValueByName("useFanControl") if (useFanControl is None or int(useFanControl) == 0): return False return True def getFanPin(self): fanPin = self.getConfigValueByName("useFanPin") if fanPin is not None: return int(fanPin) return -1 def getFanOnTime(self): fanPin = self.getConfigValueByName("fanOnTime") if fanPin is not None: return int(fanPin) return 0 def getFanOffTime(self): fanPin = self.getConfigValueByName("fanInterval") if fanPin is not None: return int(fanPin) return 0 # check if we're exceeding the pour threshold def sendflowupdate(self, pin, count): return # check if we're exceeding the pour threshold def sendkickupdate(self, pin): msg = "RPU:KICK:" + str(pin) debug("Kicking Keg: " + msg.rstrip()) self.mcast.sendto(msg + "\n", (MCAST_GRP, MCAST_PORT)) # send a mcast flow update def sendflowcount(self, rfid, pin, count): if self.OPTION_RESTART_FANTIMER_AFTER_POUR: self.fanControl.restartNeeded(True) msg = "RPU:FLOW:" + str(pin) + "=" + str(count) + ":" + rfid debug("count update: " + msg.rstrip()) self.mcast.sendto(msg + "\n", (MCAST_GRP, MCAST_PORT)) # send a mcast valve/pin update def sendvalveupdate(self, pin, value): msg = "RPU:VALVE:" + str(pin) + "=" + str(value) debug("valve update: " + msg.rstrip()) self.mcast.sendto(msg + "\n", (MCAST_GRP, MCAST_PORT)) # send a mcast fan update def sendfanupdate(self, pin, value): msg = "RPU:FAN:" + str(pin) + "=" + str(value) debug("fan update: " + msg.rstrip()) self.mcast.sendto(msg + "\n", (MCAST_GRP, MCAST_PORT)) # send a mcast fan update def sendconfigupdate(self, ): debug("config update: " + "RPU:CONFIG") self.mcast.sendto("RPU:CONFIG\n", (MCAST_GRP, MCAST_PORT)) # start running the flow monitor in it's own thread def spawn_flowmonitor(self): while True: try: if (config['dispatch.debugMonitoring']): self.flowmonitor.fakemonitor() else: self.flowmonitor.monitor() except Exception, e: log("serial connection stopped...") debug(str(e)) finally:
class PintDispatch(object): def __init__(self): self.OPTION_USE_3_WIRE_VALVES = self.getConfigValueByName("use3WireValves") self.OPTION_RESTART_FANTIMER_AFTER_POUR = self.getConfigValueByName("restartFanAfterPour") setupSocket = MCAST_RETRY_ATTEMPTS if GPIO_IMPORT_SUCCESSFUL: GPIO.setwarnings(False) GPIO.setmode(GPIO.BOARD) # Broadcom pin-numbering scheme self.alaModeReconfig = False; while setupSocket > 0: try: #multicast socket self.mcast = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self.mcast.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1) mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) self.mcast.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) setupSocket = 0 except socket.error as msg: setupSocket = setupSocket - 1 log(msg.strerror + " - Sleeping to try again") time.sleep(MCAST_RETRY_SLEEP_SEC) if setupSocket == MCAST_RETRY_ATTEMPTS: log(str(setupSocket)) log("FATAL: Unable to setup socket") quit() self.valvesState = [] self.fanTimer = None self.valvePowerTimer = None if int(self.OPTION_USE_3_WIRE_VALVES) == 1: self.valvePowerTimer = Timer(OPTION_VALVEPOWERON, self.valveStopPower) self.updateFlowmeterConfig() self.updateValvePins() self.commandserver = CommandTCPServer(('localhost', MCAST_PORT), CommandTCPHandler) self.commandserver.pintdispatch = self self.fanControl = FanControlThread("fanControl1", self) self.flowmonitor = FlowMonitor(self, Logger()) def getConfig(self): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT * from config") rows = cursor.fetchall() con.close() return rows def getConfigValueByName(self, name): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT configValue from config WHERE configName='"+name+"'") rows = cursor.fetchall() con.close() if len(rows) == 0: return None return rows[0]['configValue'] def getTapConfig(self): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT tc.tapId,tc.flowPin,tc.valvePin,tc.valveOn FROM tapconfig tc LEFT JOIN taps t ON tc.tapId = t.id WHERE t.active = 1 ORDER BY tc.tapId") rows = cursor.fetchall() con.close() return rows def getRFIDReaders(self): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT * from rfidReaders ORDER BY priority") rows = cursor.fetchall() con.close() return rows def getMotionDetectors(self): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT * from motionDetectors ORDER BY priority") rows = cursor.fetchall() con.close() return rows def getLoadCellConfig(self): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT tapId,loadCellCmdPin,loadCellRspPin,loadCellUnit,loadCellScaleRatio,loadCellTareOffset FROM tapconfig WHERE loadCellCmdPin IS NOT NULL ORDER BY tapId") rows = cursor.fetchall() con.close() return rows def getGasTankLoadCellConfig(self): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT id,loadCellCmdPin,loadCellRspPin,loadCellUnit,loadCellScaleRatio,loadCellTareOffset FROM gasTanks WHERE loadCellCmdPin IS NOT NULL ORDER BY id") rows = cursor.fetchall() con.close() return rows def getTareRequest(self, tapId): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT tapId,loadCellTareReq FROM tapconfig WHERE tapId = " + str(tapId)) rows = cursor.fetchall() con.close() if len(rows) == 0: return False return rows[0]['loadCellTareReq'] == 1 def setLoadCellTareOffset(self, tapId, offset): sql = "UPDATE tapconfig SET loadCellTareOffset="+str(offset) sql = sql + " WHERE tapId = " + str(tapId) con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) result = cursor.execute(sql) con.commit() con.close() def getGasTankTareRequest(self, id): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT id,loadCellTareReq FROM gasTanks WHERE id = " + str(id)) rows = cursor.fetchall() con.close() if len(rows) == 0: return False return rows[0]['loadCellTareReq'] == 1 def setGasTankTareRequest(self, id, tareRequested): tareReq = "0" if tareRequested: tareReq = "1" sql = "UPDATE gasTanks SET loadCellTareReq="+tareReq if not tareRequested: sql = sql + ",loadCellTareDate=NOW()" sql = sql + " WHERE id = " + str(id) con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) result = cursor.execute(sql) con.commit() con.close() def getiSpindelConnectors(self): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT * from iSpindel_Connector") rows = cursor.fetchall() con.close() return rows def getiSpindelDevice(self, id, token, name, gravity): self.addiSpindelDeviceAsNeeded(id, token, name, gravity) con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT i.*, b.name AS beerName, COALESCE(bb.name,bb.batchNumber) as batchName from iSpindel_Device i LEFT JOIN beers b ON i.beerId = b.id LEFT JOIN beerBatches bb ON i.beerBatchId = bb.id WHERE iSpindelId = "+str(id)) rows = cursor.fetchall() con.close() if(cursor.rowcount <= 0): return None else: return rows[0] def addiSpindelDeviceAsNeeded(self, id, token, name, gravity): sql = "SELECT * FROM iSpindel_Device WHERE iSpindelId='" + str(id) + "';" con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) result = cursor.execute(sql) rows = cursor.fetchall() if(cursor.rowcount <= 0): cursor.execute("INSERT INTO iSpindel_Device (iSpindelId, token, name, gravityUnit, createdDate) VALUES("+str(id)+",'"+str(token)+"','"+str(name)+"','"+("sg" if gravity<2 else "p")+"', NOW())") else: if(rows[0]['active'] == 0 or rows[0]['token'] != str(token) or rows[0]['name'] != str(name)) : updateCursor = con.cursor(mdb.cursors.DictCursor) updateCursor.execute("UPDATE iSpindel_Device SET active=1, token='"+str(token)+"', name ='"+name+"' WHERE iSpindelId ='" + str(id) + "'") con.commit() con.close() def getiSpindelUnsentConfig(self, id): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT iSpindelId, `interval`, token, polynomial, sent from iSpindel_Device WHERE sent != TRUE AND iSpindelId = "+str(id)) rows = cursor.fetchall() con.close() if(cursor.rowcount <= 0): return None else: return rows[0] def updateiSpindeConfigMarkSent(self, id): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) cursor.execute("UPDATE iSpindel_Device SET sent = TRUE WHERE sent != TRUE AND iSpindelId = "+str(id)) con.commit() con.close() def insertiSpindelData(self, fieldlist, valuelist): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) #debug(str(fieldlist)) #debug(str(valuelist)) # gather the data now and send it to the database fieldstr = ', '.join(fieldlist) valuestr = ', '.join(['%s' for x in valuelist]) add_sql = 'INSERT INTO iSpindel_Data (' + fieldstr + ')' add_sql += ' VALUES (' + valuestr + ')' #debug(add_sql) cursor.execute(add_sql, valuelist) con.commit() cursor.close() con.close() def setTareRequest(self, tapId, tareRequested): tareReq = "0" if tareRequested: tareReq = "1" sql = "UPDATE tapconfig SET loadCellTareReq="+tareReq if not tareRequested: sql = sql + ",loadCellTareDate=NOW()" sql = sql + " WHERE tapId = " + str(tapId) con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) result = cursor.execute(sql) con.commit() con.close() def addTempProbeAsNeeded(self, probe): state_pin = 0 sql = "SELECT * FROM tempProbes WHERE name='"+probe+"';" con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) result = cursor.execute(sql) rows = cursor.fetchall() if(cursor.rowcount <= 0): cursor.execute("INSERT INTO tempProbes (name, type) VALUES('"+probe+"', 0)") else: if rows[0]['statePin'] != None: state_pin = int(rows[0]['statePin']) if(rows[0]['active'] == 0) : updateCursor = con.cursor(mdb.cursors.DictCursor) updateCursor.execute("UPDATE tempProbes SET active=1 WHERE name ='" + probe+"'") con.commit() con.close() return state_pin def saveTemp(self, probe, temp, tempUnit, takenDate): insertLogSql = "INSERT INTO tempLog (probe, temp, tempUnit, takenDate) " insertLogSql += "VALUES('"+probe+"',"+str(temp)+"+ COALESCE((SELECT manualAdj FROM tempProbes WHERE name = '"+probe+"'), 0), '"+str(tempUnit)+"', '"+takenDate+"');" con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) result = cursor.execute(insertLogSql) con.commit() con.close() self.archiveTemp() def saveTemps(self, temps): con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) for temp in temps: insertLogSql = "INSERT INTO tempLog (probe, temp, tempUnit, takenDate, statePinState) " insertLogSql += "VALUES('"+temp[0]+"',"+str(temp[1])+"+ COALESCE((SELECT manualAdj FROM tempProbes WHERE name = '"+temp[0]+"'), 0), '"+str(temp[2])+"', '"+temp[3]+"'," insertLogSql += str(temp[4]) if temp[4] != None else "null" insertLogSql += ");" result = cursor.execute(insertLogSql) con.commit() con.close() self.archiveTemp() def getTempProbeConfig(self): useTempProbes = self.getConfigValueByName("useTempProbes") if(useTempProbes is not None and int(useTempProbes) == 1): return True return False #set to -1 so on startup archive is checked lastArchiveCheck = -1 #Combine all readings older than 2 months into 1 average for the month to reduce rows in the table def archiveTemp(self): #only archive if the month has changed if self.lastArchiveCheck == datetime.datetime.now().month: return insertLogSql = """INSERT INTO tempLog (takenDate, probe, temp, humidity) (SELECT CAST(DATE_FORMAT(takenDate,'%Y-%m-01') as DATE), 'History', TRUNCATE(AVG(temp), 2), TRUNCATE(hl.humidity, 2) FROM tempLog tl LEFT JOIN (SELECT CAST(DATE_FORMAT(takenDate,'%Y-%m-01') AS DATE) as takenMonth, AVG(humidity) AS humidity FROM tempLog WHERE probe != 'History' AND humidity IS NOT NULL AND takenDate < CAST(DATE_FORMAT(NOW() ,'%Y-%m-01') as DATE) GROUP BY MONTH(takenDate)) hl ON CAST(DATE_FORMAT(tl.takenDate,'%Y-%m-01') as DATE) = hl.takenMonth WHERE probe != 'History' AND takenDate < CAST(DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 1 MONTH) ,'%Y-%m-01') as DATE) GROUP BY MONTH(takenDate));""" deleteSQL = """DELETE FROM tempLog WHERE probe != 'History' AND takenDate < CAST(DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 1 MONTH) ,'%Y-%m-01') as DATE) ;""" con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) result = cursor.execute(insertLogSql) result = cursor.execute(deleteSQL) con.commit() con.close() self.lastArchiveCheck = datetime.datetime.now().month def useFanControl(self): useFanControl = self.getConfigValueByName("useFanControl") if(useFanControl is None or int(useFanControl) == 0): return False return True def getFanPin(self): fanPin = self.getConfigValueByName("useFanPin") if fanPin is not None: return int(fanPin) return -1 def getFanOnTime(self): fanPin = self.getConfigValueByName("fanOnTime") if fanPin is not None: return int(fanPin) return 0 def getFanOffTime(self): fanPin = self.getConfigValueByName("fanInterval") if fanPin is not None: return int(fanPin) return 0 # check if we're exceeding the pour threshold def sendflowupdate(self, pin, count): return # check if we're exceeding the pour threshold def sendkickupdate(self, pin): msg = "RPU:KICK:" + str(pin) debug("Kicking Keg: " + msg.rstrip()) self.mcast.sendto(msg + "\n", (MCAST_GRP, MCAST_PORT)) # send a mcast flow update def sendflowcount(self, rfid, pin, count): if self.OPTION_RESTART_FANTIMER_AFTER_POUR: self.fanControl.restartNeeded(True) msg = "RPU:FLOW:" + str(pin) + "=" + str(count) +":" + rfid debug("count update: " + msg.rstrip()) self.mcast.sendto(msg + "\n", (MCAST_GRP, MCAST_PORT)) # send a mcast valve/pin update def sendvalveupdate(self, pin, value): msg = "RPU:VALVE:" + str(pin) + "=" + str(value) debug("valve update: " + msg.rstrip()) self.mcast.sendto(msg + "\n", (MCAST_GRP, MCAST_PORT)) # send a mcast fan update def sendfanupdate(self, pin, value): msg = "RPU:FAN:" + str(pin) + "=" + str(value) debug("fan update: " + msg.rstrip()) self.mcast.sendto(msg + "\n", (MCAST_GRP, MCAST_PORT)) # send a mcast fan update def sendconfigupdate(self,): debug("config update: " + "RPU:CONFIG") self.mcast.sendto("RPU:CONFIG\n", (MCAST_GRP, MCAST_PORT)) # start running the flow monitor in it's own thread def spawn_flowmonitor(self): while True: try: if(config['dispatch.debugMonitoring']): self.flowmonitor.fakemonitor() else: self.flowmonitor.monitor(self.useOption("useFlowMeter")) except Exception as e: log("serial connection stopped...") debug( str(e) ) finally: time.sleep(1) log("flowmonitor aborted, restarting...") def spawnWebSocketServer(self): args = ["-p", "8081", "-d", PYTHON_WSH_DIR] #only log all errors in the webservice if we are debuging, turn level to critical if(not config['dispatch.debug']): args.append("--log-level") args.append("critical") options, args = _parse_args_and_config(args=args) options.cgi_directories = [] options.is_executable_method = None os.chdir(options.document_root) _configure_logging(options) server = WebSocketServer(options) server.serve_forever() # main setup def setup(self): # need small delay to get logging going, otherwise first log entries are missing time.sleep(2) debug("starting setup...") self.flowmonitor.setup() # main start method def start(self): log("starting WS server") t = threading.Thread(target=self.spawnWebSocketServer) t.setDaemon(True) t.start() log("starting device monitors...") t = threading.Thread(target=self.spawn_flowmonitor) t.setDaemon(True) t.start() log("starting command server") t = threading.Thread(target=self.commandserver.serve_forever) t.setDaemon(True) t.start() log("starting fan control") self.fanControl.start() signal.pause() debug( "exiting...") # def triggerAlaModeReset(self): self.alaModeReconfig = True; # check if something got changed which requires reset/reconfigure of alamode def needAlaModeReconfig(self): return 1 if self.alaModeReconfig else 0 # reset the alamode by tripping it's reset line def resetAlaMode(self): self.alaModeReconfig = False; resetpin = 12 if GPIO_IMPORT_SUCCESSFUL: GPIO.setup(int(resetpin), GPIO.OUT) oldValue = GPIO.input(resetpin) if (oldValue == 1): value1 = 0 else: value1 = 1 self.updatepin(resetpin, value1) time.sleep(1) self.updatepin(resetpin, oldValue) self.OPTION_RESTART_FANTIMER_AFTER_POUR = self.getConfigValueByName("restartFanAfterPour") # update PI gpio pin mode (either input or output), this requires that this is run as root def setpinmode(self, pin, value): if not GPIO_IMPORT_SUCCESSFUL: return False if (pin < 1): debug("invalid pin " + str(pin)) return False debug( "update pin MODE %s to %s" %(pin, value)) if int(value) == 0 : GPIO.setup(int(pin), GPIO.IN) else: GPIO.setup(int(pin), GPIO.OUT) return True # update PI gpio pin (either turn on or off), this requires that this is run as root def updatepin(self, pin, value): if not GPIO_IMPORT_SUCCESSFUL: return False pin = int(pin) value = int(value) if (pin < 1): debug("invalid pin " + str(pin)) return False GPIO.setup(pin, GPIO.OUT) oldValue = GPIO.input(pin) if(oldValue != value): #debug( "update pin %s from %s to %s" %(pin, oldValue, value)) if value == 0 : GPIO.output(pin, GPIO.LOW) else: GPIO.output(pin, GPIO.HIGH) sql = "UPDATE tapconfig SET valvePinState=" + str(value) + " WHERE valvePin =" + str(-1*pin) con = connectDB() cursor = con.cursor(mdb.cursors.DictCursor) result = cursor.execute(sql) con.commit() con.close() return True return False # update PI gpio pin (either turn on or off), this requires that this is run as root def readpin(self, pin): if not GPIO_IMPORT_SUCCESSFUL: return 0 pin = int(pin) if (pin < 1): debug("invalid pin " + str(pin)) return 0 value = GPIO.input(pin) debug( "read pin %s value %s" %(pin, value)) return value; def valveStopPower(self): debug( "stopping valve power on pin %s" %(OPTION_VALVEPOWERPIN)) self.updatepin(self.getValvesPowerPin(), 0) def updateValvePins(self): taps = self.getTapConfig() ii = 0 for tap in taps: if( len(self.valvesState) < ii + 1): self.valvesState.append(-1) if(tap["valveOn"] is None): tap["valveOn"] = 0 if self.valvesState[ii] != int(tap["valveOn"]): self.sendvalveupdate(ii, tap["valveOn"]) self.valvesState[ii] = int(tap["valveOn"]) ii = ii + 1 def getValvesState(self): return self.valvesState def getConfigItem(self, itemName): config = self.getConfig() for item in config: if (item["configName"] == itemName): return item return None def updateFlowmeterConfig(self): pourShutOffCountItem = self.getConfigItem("pourShutOffCount") if(pourShutOffCountItem is None): self.pourShutOffCount = 0; else: self.pourShutOffCount = int(pourShutOffCountItem["configValue"]) def useOption(self, option): cfItem = self.getConfigItem(option) if cfItem is None: return False cfUse = cfItem["configValue"] if(int(cfUse) == 1): return True return False def getValvesPowerPin(self): if self.useOption("useTapValves"): valveItem = self.getConfigItem("valvesPowerPin") if valveItem is not None: return int(valveItem["configValue"]) return -1 def getValvesPowerTime(self): if self.useOption("useTapValves"): valveItem = self.getConfigItem("valvesOnTime") if valveItem is not None: return int(valveItem["configValue"]) return -1 def shutdown(self,): log("Shuting Down System") os.system('sudo shutdown -P now') def restart(self,): log("Rebooting System") os.system('sudo reboot') def restartService(self,): log("Restarting Service") os.system('sudo /etc/init.d/flowmon restart') def upgrade(self,varient="", branch_to_use="", tag=""): log("Upgrading RPints Service") cmds = {} if varient == "": subprocess.call(""+PINTS_DIR+"/util/installRaspberryPints --u --i "+PINTS_DIR, shell=True) elif varient == "force": subprocess.call(""+PINTS_DIR+"/util/installRaspberryPints --u --f --i "+PINTS_DIR, shell=True) # send a mcast refresh update def refreshWebpages(self): debug("config update: REFRESH") self.mcast.sendto("RPU:REFRESH\n", (MCAST_GRP, MCAST_PORT))