def recordowfsdata(controldatabase, ROMsandvalues=None): # Write to database # At the moment all are enabled by default. # Eventually we'll read this before we delete all entries if ROMsandvalues: for tuple in ROMsandvalues: ROM = tuple[0] temp = tuple[1] queryresult = pilib.sqlitequery( controldatabase, 'select name from inputsinfo where inputID = ' + "'" + ROM + "'") if not queryresult: name = '' else: name = queryresult[0][0] valuelist = [ 'OWROM' + tuple[0], tuple[1], 'F', pilib.gettimestring(), 1, name ] query = pilib.makesqliteinsert(controldatabase, 'inputsdata', valuelist) # print(query) querylist.append(query) else: return ("no ROMs passed")
def updateiwstatus(): from pilib import insertstringdicttablelist, systemdatadatabase, gettimestring import netfun iwdict = netfun.getiwstatus() iwdict['updatetime'] = gettimestring() # put into database insertstringdicttablelist(systemdatadatabase, 'iwstatus', [iwdict])
def updatehamachistatus(): from pilib import insertstringdicttablelist, systemdatadatabase, gettimestring import netfun try: hamdicts = netfun.gethamachidata() except: pass else: for index, dict in enumerate(hamdicts): hamdicts[index]['updatetime'] = gettimestring() # put into database insertstringdicttablelist(systemdatadatabase, 'hamachistatus', hamdicts)
def recordspidata(database, valuedict, execute=False): # This is incomplete and hardcoded partially querylist = [] for key, value in valuedict.iteritems(): querylist.append( pilib.makesqliteinsert('inputs', valuelist=[ key, 'SPI1', 'TC', '1', 'SPITC1', value, 'F', pilib.gettimestring(), 1, '', '' ])) querylist.append(pilib.makesqliteinsert('ioinfo', valuelist=[key, key])) if execute: pilib.sqlitemultquery(database, querylist) return querylist
def recordowfsdata(controldatabase,ROMsandvalues=None): # Write to database # At the moment all are enabled by default. # Eventually we'll read this before we delete all entries if ROMsandvalues: for tuple in ROMsandvalues: ROM=tuple[0] temp=tuple[1] queryresult=pilib.sqlitequery(controldatabase,'select name from inputsinfo where inputID = ' + "'" + ROM + "'") if not queryresult: name='' else: name = queryresult[0][0] valuelist = ['OWROM' + tuple[0],tuple[1],'F',pilib.gettimestring(),1,name] query = pilib.makesqliteinsert(controldatabase,'inputsdata',valuelist) # print(query) querylist.append(query) else: return("no ROMs passed")
def runalgorithm(controldatabase, recipedatabase, channelname): from pilib import sqlitequery, datarowtodict, gettimestring, timestringtoseconds import time message = '' # get our details of our channel channeldata = sqlitequery(controldatabase, 'select * from channels where name=' + "'" + channelname + "'")[0] channeldict = datarowtodict(controldatabase, 'channels', channeldata) # check to see if we are running a recipe controlrecipename = channeldict['controlrecipe'] if controlrecipename and controlrecipename != 'none': # Get recipe details # If recipes get too big, we'll just get # a couple stages. For now, we make a # dictionary array #print('we are in recipe ' + controlrecipename) #print(recipedatabase) recipedata = sqlitequery(recipedatabase, 'select * from \'' + controlrecipename + '\'') recipedictarray = [] for stage in recipedata: recipedict = datarowtodict(recipedatabase, controlrecipename, stage) recipedictarray.append(recipedict) # get current stage currentstagenumber = int(channeldict['recipestage']) #print('current stage is ' + str(currentstagenumber) ) # Get data for current stage stagefound = False for stage in recipedictarray: if int(stage['stagenumber']) == currentstagenumber: currentstage = stage stagefound = True break if stagefound: #print("stage found") pass else: print('error. stage not found.') # Check to see if we need to move to next stage currenttime = time.time() #print('Time') #print(currenttime) #print(gettimestring(currenttime)) if currentstagenumber == 0 or currenttime - timestringtoseconds(channeldict['recipestagestarttime']) > int( currentstage['stagelength']): print('stage time expired for stage ' + str(currentstagenumber) + '. Checking on stage advance. ') # Advance stage if there is another stage. Otherwise # update channel to be off a recipe. We assume explicitly # that the stages are sequential integers. nextstagenumber = currentstagenumber + 1 # look for next stage stagefound = False for stage in recipedictarray: if int(stage['stagenumber']) == nextstagenumber: nextstage = stage stagefound = True break if stagefound: print(' Next stage was found. Setting next stage. ') if currentstagenumber == 0: print("Stagenumber is 0. Setting recipe start time. ") # Set recipe start time sqlitequery(controldatabase, 'update channels set recipestarttime=\'' + gettimestring( currenttime) + '\' where name=\'' + channelname + '\'') # Set stage to new stage number sqlitequery(controldatabase, 'update channels set recipestage=\'' + str( nextstagenumber) + '\' where name=\'' + channelname + '\'') # Set setpointvalue sqlitequery(controldatabase, 'update channels set setpointvalue=\'' + str( nextstage['setpointvalue']) + '\' where name=\'' + channelname + '\'') # Set stage start time to now sqlitequery(controldatabase, 'update channels set recipestagestarttime=\'' + gettimestring( currenttime) + '\' where name=\'' + channelname + '\'') # Set new controlalgorithm sqlitequery(controldatabase, 'update channels set controlalgorithm=\'' + nextstage[ 'controlalgorithm'] + '\' where name=\'' + channelname + '\'') else: # Take channel off recipe sqlitequery(controldatabase, 'update channels set controlrecipe=\'none\' where name=\'' + channelname + '\'') sqlitequery(controldatabase, 'update channels set recipestate=\'0\' where name=\'' + channelname + '\'') sqlitequery(controldatabase, 'update channels set recipestage=\'0\' where name=\'' + channelname + '\'') # if lengthmode is setpoint # get current stage # check stage start against stage length # and current time # move to next stage if time and revise setpoint # adjust setpoint based on stage # set action based on setpoint else: # make sure we're not on recipe and on stage 0 sqlitequery(controldatabase, 'update channels set controlrecipe=\'none\' where name=\'' + channelname + '\'') sqlitequery(controldatabase, 'update channels set recipestate=\'0\' where name=\'' + channelname + '\'') sqlitequery(controldatabase, 'update channels set recipestage=\'0\' where name=\'' + channelname + '\'') algorithm = channeldict['controlalgorithm'] setpointvalue = float(channeldict['setpointvalue']) controlvalue = float(channeldict['controlvalue']) algorithmrows = sqlitequery(controldatabase, 'select * from controlalgorithms where name=' + "'" + algorithm + "'") algorithmrow = algorithmrows[0] algorithm = datarowtodict(controldatabase, 'controlalgorithms', algorithmrow) type = algorithm['type'] if type == 'on/off with deadband': #print(type) deadbandhigh = algorithm['deadbandhigh'] deadbandlow = algorithm['deadbandlow'] if setpointvalue > (controlvalue + deadbandhigh): action = 100 elif setpointvalue < (controlvalue - deadbandlow): action = -100 else: action = 0 #print('setpoint' + str(setpoint)) #print('controlvalue' + str(controlvalue)) #print(action) #print(message) return [action, message]
systemstatus = pilib.readalldbrows(pilib.controldatabase, 'systemstatus')[0] # Keep reading system status? while systemstatus['systemstatusenabled']: starttime = time.time() pilib.writedatedlogmsg(pilib.systemstatuslog, 'System status routine is starting. ', 3, pilib.systemstatusloglevel) pilib.writedatedlogmsg(pilib.systemstatuslog, 'Beginning network routines. ', 3, pilib.systemstatusloglevel) currenttime = pilib.gettimestring() pilib.setsinglevalue(pilib.controldatabase, 'systemstatus', 'lastsystemstatuspoll', pilib.gettimestring()) pilib.writedatedlogmsg(pilib.systemstatuslog, 'Running updateifacestatus. ', 4, pilib.systemstatusloglevel) # Update network interfaces statuses for all interfaces, in database tables as well # Check on wpa supplicant status as well. Function returns wpastatusdict try: pilib.writedatedlogmsg(pilib.networklog, 'Running updateifacestatus', 4, pilib.networkloglevel) wpastatusdict = updateifacestatus() except:
def updateiodata(database): # This recreates all input and output tables based on the interfaces table. # Thus way we don't keep around stale data values. We could at some point incorporate # a retention feature that keeps them around in case they disappear temporarily. # It also reads the elements if they are enabled and it's time to read them import pilib import RPi.GPIO as GPIO allowedGPIOaddresses = [18, 23, 24, 25, 4, 17, 21, 22] dontrun = False GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) tables = pilib.gettablenames(pilib.controldatabase) if 'interfaces' in tables: interfaces = pilib.readalldbrows(pilib.controldatabase, 'interfaces') else: print('interfaces table not found. Exiting') return if 'inputs' in tables: previnputs = pilib.readalldbrows(pilib.controldatabase, 'inputs') # Make list of IDs for easy indexing previnputids = [] for input in previnputs: previnputids.append(input['id']) else: previnputs = [] previnputids = [] if 'outputs' in tables: prevoutputs = pilib.readalldbrows(pilib.controldatabase, 'outputs') # Make list of IDs for easy indexing prevoutputids = [] prevoutputvalues = [] for output in prevoutputs: prevoutputids.append(output['id']) prevoutputvalues.append(output['value']) else: prevoutputs = {} prevoutputids = [] if 'defaults' in tables: defaults = pilib.readalldbrows(pilib.controldatabase, 'defaults')[0] defaultinputpollfreq = defaults['inputpollfreq'] defaultoutputpollfreq = defaults['outputpollfreq'] else: defaults = [] defaultinputpollfreq = 60 defaultoutputpollfreq = 60 # We drop all inputs and outputs and recreate # Add all into one query so there is no time when the IO don't exist. querylist = [] querylist.append('delete from inputs') querylist.append('delete from outputs') pilib.sqlitemultquery(pilib.controldatabase, querylist) querylist = [] for interface in interfaces: if interface['interface'] == 'I2C': if interface['enabled']: # print('processing enabled I2C') if interface['type'] == 'DS2483': from owfslib import runowfsupdate runowfsupdate() elif interface['interface'] == 'GPIO': options = pilib.parseoptions(interface['options']) # TODO : respond to more option, like pullup and pulldown address = int(interface['address']) if address in allowedGPIOaddresses: # Check if interface is enabled if interface['enabled']: # Get name from ioinfo table to give it a colloquial name gpioname = pilib.sqlitedatumquery(database, 'select name from ioinfo where id=\'' + interface['id'] + '\'') polltime = pilib.gettimestring() # Append to inputs and update name, even if it's an output (can read status as input) if options['mode'] == 'output': GPIO.setup(address, GPIO.OUT) # Set the value of the gpio. # Get previous value if exists if interface['id'] in prevoutputids: value = prevoutputvalues[prevoutputids.index(interface['id'])] else: value = 0 if value == 1: GPIO.output(address, True) else: GPIO.output(address, False) # Get output settings and keep them if the GPIO previously existed if interface['id'] in prevoutputids: pollfreq = prevoutputs[prevoutputids.index(interface['id'])]['pollfreq'] else: pollfreq = defaultoutputpollfreq # Add entry to outputs tables querylist.append('insert into outputs values (\'' + interface['id'] + '\',\'' + interface['interface'] + '\',\'' + interface['type'] + '\',\'' + str(address) + '\',\'' + gpioname + '\',\'' + str(value) + '\',\'\',\'' + str(polltime) + '\',\'' + str(pollfreq) + '\')') else: GPIO.setup(address, GPIO.IN) value = GPIO.input(address) polltime = pilib.gettimestring() # Get input settings and keep them if the GPIO previously existed if interface['id'] in prevoutputids: pollfreq = previnputs[prevoutputids.index(interface['id'])]['pollfreq'] polltime = previnputs[prevoutputids.index(interface['id'])]['polltime'] else: pollfreq = defaultinputpollfreq # Add entry to inputs tables # Get output settings and keep them if the GPIO previously existed if interface['id'] in prevoutputids: pollfreq = prevoutputs[prevoutputids.index(interface['id'])]['pollfreq'] else: pollfreq = defaultoutputpollfreq querylist.append( 'insert into inputs values (\'' + interface['id'] + '\',\'' + interface['interface'] + '\',\'' + interface['type'] + '\',\'' + str(address) + '\',\'' + gpioname + '\',\'' + str(value) + '\',\'\',\'' + str(polltime) + '\',\'' + str(pollfreq) + '\')') else: GPIO.setup(address, GPIO.IN) else: print('GPIO address ' + address + 'not allowed. BAD THINGS CAN HAPPEN.') elif interface['interface'] == 'SPI': # print('processing SPI') if interface['type'] == 'SPITC': import readspi spidata = readspi.readspitc() readspi.recordspidata(database, spidata) elif interface['type'] == 'CuPIDLights': import spilights spilights.updatelightsfromdb(pilib.controldatabase, 'indicators') # Set tables # print(querylist) pilib.sqlitemultquery(pilib.controldatabase, querylist)
F = False GPIO.setmode(GPIO.BCM) # Run the script periodically based on systemstatus systemstatus = pilib.readalldbrows(pilib.controldatabase, 'systemstatus')[0] while systemstatus['picontrolenabled']: # Set poll date. While intuitively we might want to set this # after the poll is complete, if we error below, we will know # from this stamp when it barfed. This is arguably more valuable # then 'last time we didn't barf' pilib.sqlitequery(pilib.controldatabase, 'update systemstatus set lastpicontrolpoll=\'' + pilib.gettimestring() + '\'') channels = pilib.readalldbrows(pilib.controldatabase, 'channels') outputs = pilib.readalldbrows(pilib.controldatabase, 'outputs') controlalgorithms = pilib.readalldbrows(pilib.controldatabase, 'controlalgorithms') # Cycle through channels and set action based on setpoint # and algorithm if set to auto mode for channel in channels: statusmessage = '' channelindex = str(int(channel['channelindex'])) channelname = channel['name'] logtablename = channel['name'] + '_log' time = pilib.gettimestring()
def recordspidata(database, valuedict): # This is incomplete and hardcoded partially querylist = [] for key, value in valuedict.iteritems(): querylist.append(pilib.makesqliteinsert('inputsdata', valuelist=[key, 'SPI1', 'TC', '1', value, 'F', pilib.gettimestring(), 1, key])) querylist.append(pilib.makesqliteinsert('ioinfo', valuelist=[key, key])) pilib.sqlitemultquery(database, querylist)
def updateiodata(database, **kwargs): # This recreates all input and output tables based on the interfaces table. # Thus way we don't keep around stale data values. We could at some point incorporate # a retention feature that keeps them around in case they disappear temporarily. # It also reads the elements if they are enabled and it's time to read them import pilib import traceback if 'piobject' in kwargs: pi = kwargs['piobject'] else: import pigpio pi = pigpio.pi() allowedGPIOaddresses = [18, 23, 24, 25, 4, 17, 27, 22, 5, 6, 13, 19, 26, 16, 20, 21] logconfig = pilib.getlogconfig() tables = pilib.gettablenames(pilib.controldatabase) if 'interfaces' in tables: interfaces = pilib.readalldbrows(pilib.controldatabase, 'interfaces') else: pilib.log(pilib.iolog, 'interfaces table not found. Exiting', 1, logconfig['iologlevel']) return if 'inputs' in tables: previnputs = pilib.readalldbrows(pilib.controldatabase, 'inputs') # Make list of IDs for easy indexing previnputids = [] for input in previnputs: previnputids.append(input['id']) else: previnputs = [] previnputids = [] if 'outputs' in tables: prevoutputs = pilib.readalldbrows(pilib.controldatabase, 'outputs') # Make list of IDs for easy indexing prevoutputids = [] prevoutputvalues = [] for output in prevoutputs: prevoutputids.append(output['id']) prevoutputvalues.append(output['value']) else: prevoutputs = {} prevoutputids = [] if 'defaults' in tables: defaults = pilib.readalldbrows(pilib.controldatabase, 'defaults')[0] defaultinputpollfreq = defaults['inputpollfreq'] defaultoutputpollfreq = defaults['outputpollfreq'] else: defaults = [] defaultinputpollfreq = 60 defaultoutputpollfreq = 60 if 'indicators' in tables: indicatornames = [] previndicators = pilib.readalldbrows(pilib.controldatabase, 'indicators') for indicator in previndicators: indicatornames.append(indicator['name']) else: previndicators = [] indicatornames = [] # We drop all inputs and outputs and recreate # Add all into one query so there is no time when the IO don't exist. querylist = [] querylist.append('delete from inputs') querylist.append('delete from outputs') # This is temporary. Clearing the table here and adding entries below can result in a gap in time # where there are no database indicator entries. This is not too much of a problem with indicators, as we # update the hardware explicitly after we add the entries. If the interface queries the table during # this period, however, we could end up with an apparently empty table. # TODO: FIX update on indicators in updateio # We drop this table, so that if SP1 has been disabled, the entries do not appear as valid indicators pilib.sqlitequery(pilib.controldatabase, 'delete from indicators') owfsupdate = False for interface in interfaces: if interface['interface'] == 'I2C': pilib.log(pilib.iolog, 'Processing I2C interface ' + interface['name'], 3, logconfig['iologlevel']) if interface['enabled']: pilib.log(pilib.iolog, 'I2C Interface ' + interface['name'] + ' enabled', 3, logconfig['iologlevel']) if interface['type'] == 'DS2483': pilib.log(pilib.iolog, 'Interface type is DS2483', 3, logconfig['iologlevel']) owfsupdate = True else: pilib.log(pilib.iolog, 'I2C Interface ' + interface['name'] + ' disabled', 3, logconfig['iologlevel']) elif interface['interface'] == 'USB': pilib.log(pilib.iolog, 'Processing USB interface ' + interface['name'], 3, logconfig['iologlevel']) if interface['enabled']: pilib.log(pilib.iolog, 'USB Interface ' + interface['name'] + ' enabled', 3, logconfig['iologlevel']) if interface['type'] == 'DS9490': pilib.log(pilib.iolog, 'Interface type is DS9490', 3, logconfig['iologlevel']) owfsupdate = True else: pilib.log(pilib.iolog, 'USB Interface ' + interface['name'] + ' disabled', 3, logconfig['iologlevel']) elif interface['interface'] == 'MOTE': #determine and then update id based on fields entryid = interface['interface'] + '_' + interface['type'] + '_' + interface['address'] condition = '"interface"=\'' + interface['interface'] + '\' and "type"=\'' + interface['type'] + '\' and "address"=\'' + interface['address'] + '\'' print(condition) pilib.setsinglevalue(pilib.controldatabase, 'interfaces', 'id', entryid, condition) pilib.log(pilib.iolog, 'Processing Mote interface' + interface['name'] + ', id:' + entryid, 3, logconfig['iologlevel']) if interface['enabled']: pilib.log(pilib.iolog, 'Mote Interface ' + interface['name'] + ', id:' + entryid + ' enabled', 3, logconfig['iologlevel']) # Grab mote entries from remotes table # nodeid and keyvalue are keyed into address in remotes table # keyvalues are : # channel: channel number # iovalue: ionumber # owdev: ROM # This would look like, for example # 1:1 for a nodeid:channel scenario for a controller split = interface['address'].split(':') nodeid = split[0] keyvalue = split[1] # so we used to enable an interface and then take all entries from a node # Now, we have to explicitly add an interface for each device, unless the keychar * is used as the # keyvalue. This will allow us to insert all automatically, for example for owdevs or iovals from a # node. # This pulls out all mote entries that have nodeid and keyvalue that match the interface address # We should just find one, ideally if keyvalue == '*': pass else: condition = "\"nodeid\"='" + nodeid + "' and \"keyvalue\"='" + keyvalue + "'" nodeentries = pilib.dynamicsqliteread(pilib.controldatabase, 'remotes', condition=condition) print("WE FOUND MOTE") print(condition) print(len(nodeentries)) if interface['type'] == 'channel': print('channel') if len(nodeentries) == 1: print('one entry found') nodeentry = nodeentries[0] nodedata = pilib.parseoptions(nodeentry['data']) # Find existing channel so we can get existing data, settings, etc., and retain channel ordering newchanneldata = {'name':interface['name'], 'controlvalue':nodedata['pv'], 'setpointvalue':nodedata['sv'],'controlvaluetime':pilib.gettimestring(), 'data':nodeentry['data'], 'type':'remote'} newchannel = {} existingchannels = pilib.readalldbrows(pilib.controldatabase, 'channels') for channel in existingchannels: if channel['name'] == interface['name']: print('updating') print(channel) newchannel.update(channel) print(newchannel) newchannel.update(newchanneldata) print(newchannel) keys = [] values = [] for key, value in newchannel.iteritems(): keys.append(key) values.append(value) query = pilib.makesqliteinsert('channels',values, keys) # print(query) pilib.sqlitequery(pilib.controldatabase,query) else: print('multiple entries found for channel. not appropriate') else: pass # Create queries for table insertion # TODO: process mote pollfreq, ontime, offtime moteentries = [] for nodeentry in nodeentries: # THis breaks out all of the strictly json-encoded data. datadict = pilib.parseoptions(nodeentry['data']) try: entrytype = nodeentry['msgtype'] # now treat each mote type entry specially # if entrytype == 'channel': entryid = 'MOTE' + str(nodeentry['nodeid']) + '_' + nodeentry['keyvaluename'] + '_' + nodeentry['keyvalue'] entrymetareturn = pilib.dynamicsqliteread(pilib.controldatabase, 'ioinfo', condition="\"id\"='" + entryid + "'") try: entrymeta = entrymetareturn[0] except: entrymeta = [] # print(entrymeta) entryoptions={} if entrymeta: entryname = entrymeta['name'] if entrymeta['options']: entryoptions = pilib.parseoptions(entrymeta['options']) else: entryname = '[MOTE' + str(nodeentry['nodeid']) + '] ' + nodeentry['keyvaluename'] + ':' + nodeentry['keyvalue'] except KeyError: print('OOPS KEY ERROR') else: if entrytype == 'iovalue': if 'scale' in entryoptions: entryvalue = str(float(entryoptions['scale']) * float(datadict['ioval'])) elif 'formula' in entryoptions: x = float(datadict['ioval']) try: entryvalue = eval(entryoptions['formula']) except: entryvalue = float(datadict['ioval']) else: entryvalue = float(datadict['ioval']) elif entrytype == 'owdev': if 'owtmpasc' in datadict: if 'scale' in entryoptions: entryvalue = str(float(entryoptions['scale']) * float(datadict['owtmpasc'])) elif 'formula' in entryoptions: x = float(datadict['owtmpasc']) try: entryvalue = eval(entryoptions['formula']) except: entryvalue = float(datadict['owtmpasc']) else: entryvalue = datadict['owtmpasc'] else: entryvalue = -1 else: entryvalue = -1 moteentries.append('insert into inputs values (\'' + entryid + '\',\'' + interface['interface'] + '\',\'' + interface['type'] + '\',\'' + str(address) + '\',\'' + entryname + '\',\'' + str(entryvalue) + "','','" + nodeentry['time'] + '\',\'' + str(15) + "','" + '' + "','" + '' + "')") # print('querylist') # print(moteentries) querylist.extend(moteentries) else: pilib.log(pilib.iolog, 'Mote Interface ' + interface['name'] + ' disnabled', 3, logconfig['iologlevel']) elif interface['interface'] == 'LAN': pilib.log(pilib.iolog, 'Processing LAN interface' + interface['name'], 3, logconfig['iologlevel']) if interface['enabled']: pilib.log(pilib.iolog, 'LAN Interface ' + interface['name'] + ' enabled', 3, logconfig['iologlevel']) if interface['type'] == 'MBTCP': pilib.log(pilib.iolog, 'Interface ' + interface['name'] + ' type is MBTCP', 3, logconfig['iologlevel']) try: mbentries = processMBinterface(interface, prevoutputs, prevoutputids, previnputs, previnputids, defaults, logconfig) except: pilib.log(pilib.iolog, 'Error processing MBTCP interface ' + interface['name'], 0, logconfig['iologlevel']) errorstring = traceback.format_exc() pilib.log(pilib.iolog, 'Error of kind: ' + errorstring, 0, logconfig['iologlevel']) else: pilib.log(pilib.iolog, 'Done processing MBTCP interface ' + interface['name'], 3, logconfig['iologlevel']) querylist.extend(mbentries) else: pilib.log(pilib.iolog, 'LAN Interface ' + interface['name'] + ' disabled', 3, logconfig['iologlevel']) elif interface['interface'] == 'GPIO': try: address = int(interface['address']) except KeyError: pilib.log(pilib.iolog, 'GPIO address key not found for ' + interface['name'], 1, logconfig['iologlevel']) continue if interface['enabled']: pilib.log(pilib.iolog, 'Processing GPIO interface ' + str(interface['address']), 3, logconfig['iologlevel']) if address in allowedGPIOaddresses: pilib.log(pilib.iolog, 'GPIO address' + str(address) + ' allowed. Processing.', 4, logconfig['iologlevel']) GPIOentries = processGPIOinterface(interface, prevoutputs, prevoutputvalues, prevoutputids, previnputs, previnputids, defaults, logconfig, piobject=pi) if GPIOentries: querylist.extend(GPIOentries) else: pilib.log(pilib.iolog, 'GPIO address' + str(address) + ' not allowed. Bad things can happen. ', 4, logconfig['iologlevel']) else: pilib.log(pilib.iolog, 'GPIO address' + str(address) + ' disabled. Doing nothing.', 4, logconfig['iologlevel']) elif interface['interface'] == 'SPI0': pilib.log(pilib.iolog, 'Processing SPI0', 1, logconfig['iologlevel']) if interface['enabled']: pilib.log(pilib.iolog, 'SPI0 enabled', 1, logconfig['iologlevel']) if interface['type'] == 'SPITC': pilib.log(pilib.iolog, 'Processing SPITC on SPI0', 3, logconfig['iologlevel']) import readspi tcdict = readspi.getpigpioMAX31855temp(0,0) # Convert to F for now spitcentries = readspi.recordspidata(database, {'SPITC1' :tcdict['tctemp']*1.8+32}) querylist.extend(spitcentries) if interface['type'] == 'CuPIDlights': import spilights spilightsentries, setlist = spilights.getCuPIDlightsentries('indicators', 0, previndicators) querylist.extend(spilightsentries) spilights.updatelightsfromdb(pilib.controldatabase, 'indicators', 0) spilights.setspilights(setlist, 0) else: pilib.log(pilib.iolog, 'SPI0 not enabled', 1, logconfig['iologlevel']) elif interface['interface'] == 'SPI1': pilib.log(pilib.iolog, 'Processing SPI1', 1, logconfig['iologlevel']) if interface['enabled']: pilib.log(pilib.iolog, 'SPI1 enabled', 1, logconfig['iologlevel']) if interface['type'] == 'CuPIDlights': pilib.log(pilib.iolog, 'Processing CuPID Lights on SPI1', 1, logconfig['iologlevel']) import spilights spilightsentries, setlist = spilights.getCuPIDlightsentries('indicators', 1, previndicators) querylist.extend(spilightsentries) spilights.setspilights(setlist, 1) else: pilib.log(pilib.iolog, 'SPI1 disaabled', 1, logconfig['iologlevel']) # Set tables querylist.append(pilib.makesinglevaluequery('systemstatus', 'lastiopoll', pilib.gettimestring())) if owfsupdate: from owfslib import runowfsupdate pilib.log(pilib.iolog, 'Running owfsupdate', 1, logconfig['iologlevel']) devices, owfsentries = runowfsupdate(execute=False) querylist.extend(owfsentries) else: pilib.log(pilib.iolog, 'owfsupdate disabled', 3, logconfig['iologlevel']) pilib.log(pilib.iolog, 'Executing query: ' + str(querylist), 5, logconfig['iologlevel']) try: # print(querylist) pilib.sqlitemultquery(pilib.controldatabase, querylist) except: errorstring = traceback.format_exc() pilib.log(pilib.iolog, 'Error executing query, message: ' + errorstring, 0, logconfig['iologlevel']) pilib.log(pilib.errorlog, 'Error executing updateio query, message: ' + errorstring) pilib.log(pilib.errorlog, 'Query: ' + str(querylist))
# Write to database # At the moment all are enabled by default. # Eventually we'll read this before we delete all entries for tuple in ROMsandtemps: ROM=tuple[0] temp=tuple[1] queryresult=pilib.sqlitequery(database,'select name from sensorinfo where sensorID = ' + "'" + ROM + "'") if not queryresult: name='' else: name = queryresult[0][0] valuelist = [tuple[0],tuple[1],'F',pilib.gettimestring(),1,name] query = pilib.makesqliteinsert('sensordata',valuelist) # print(query) querylist.append(query) # execute combined query #print(querylist) ######################################## # Do thermocouple stuff import subprocess tctemp=subprocess.check_output(['python3','/usr/lib/modwsgi/max31855-1.0/getmaxtemp.py']) print('temperature is ') print(tctemp)
def updatenetstatus(lastnetstatus=None): import pilib import time import subprocess from netfun import getifacestatus, getwpaclientstatus, getifconfigstatus netconfigdata = pilib.readonedbrow(pilib.systemdatadatabase, 'netconfig')[0] """ We get last netstatus so that we can save last online times, previous online status, etc. """ if not lastnetstatus: try: lastnetstatus = pilib.readonedbrow(pilib.systemdatadatabase, 'netstatus')[0] except: pilib.log(pilib.syslog, 'Error reading netstatus. Attempting to recreate netstatus table with default values. ', 1, pilib.networkloglevel) try: pilib.emptyandsetdefaults(pilib.systemdatadatabase, 'netstatus') lastnetstatus = pilib.readonedbrow(pilib.systemdatadatabase, 'netstatus')[0] except: pilib.log(pilib.syslog, 'Error recreating netstatus. ', 1, pilib.networkloglevel) """ Pyiface is one way to read some iface data, but it doesn't always appear to show all interfaces(?!) So we wrote our own instead. A work in progress but quite functional at the moment. """ pilib.log(pilib.networklog, 'Reading ifaces with ifconfig status. ', 4, pilib.networkloglevel) ifacesdictarray = getifconfigstatus() # ifacesdictarray = getifacestatus() """ We supplement with wpa status on the wlan interfaces """ updateddictarray = [] for interface in ifacesdictarray: if interface['name'].find('wlan') >= 0: interface['wpastate'] = pilib.dicttojson(getwpaclientstatus(interface['name'])) else: interface['wpastate'] = '' updateddictarray.append(interface) ifacesdictarray = updateddictarray """ Then write it to the table """ if ifacesdictarray: pilib.log(pilib.networklog, 'Sending ifaces query. ', 5, pilib.networkloglevel) # print(ifacesdictarray) pilib.insertstringdicttablelist(pilib.systemdatadatabase, 'netifaces', ifacesdictarray) else: pilib.log(pilib.networklog, 'Empty ifaces query. ', 2, pilib.networkloglevel) pilib.log(pilib.networklog, 'Completed pyiface ifaces. ', 4, pilib.networkloglevel) """ Now we check to see if we can connect to WAN """ pilib.log(pilib.networklog, 'Checking pingtimes. ', 4, pilib.networkloglevel) okping = float(netconfigdata['pingthreshold']) from netfun import runping netstatusdict = {} querylist=[] pingresults = runping('8.8.8.8') # pingresults = [20, 20, 20] pingresult = sum(pingresults) / float(len(pingresults)) if pingresult == 0: wanaccess = 0 latency = 0 else: if pingresult < okping: wanaccess = 1 pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'WANaccess', 1) if lastnetstatus['WANaccess'] == 0 or not lastnetstatus['onlinetime']: pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'onlinetime', pilib.gettimestring()) else: wanaccess = 0 pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'WANaccess', 0) if lastnetstatus['WANaccess'] == 1 or not lastnetstatus['offlinetime']: pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'offlinetime', pilib.gettimestring()) latency = pingresult # we set all the values here, so when we retreive it we get changed and also whatever else happens to be there. pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'latency', latency) updatetime = pilib.gettimestring() pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'updatetime', updatetime) pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'WANaccess', wanaccess) pilib.log(pilib.networklog, 'Done checking pings. ', 4, pilib.networkloglevel) if netconfigdata['netstatslogenabled']: # print('going to log stuff') pilib.logtimevaluedata(pilib.logdatabase, 'system_WANping', time.time(), pingresult, 1000, netconfigdata['netstatslogfreq']) #This is kinda ugly. Should be fixed. # netstatusdict = {'WANaccess':wanaccess, 'latency': latency, 'updatetime': updatetime} netstatusdict = pilib.readonedbrow(pilib.systemdatadatabase, 'netstatus')[0] return {'netstatusdict': netstatusdict, 'ifacesdictarray': ifacesdictarray, 'netconfigdata':netconfigdata}
def processGPIOinterface(interface, prevoutputs, prevoutputvalues, prevoutputids, previnputs, previnputids, defaults, logconfig): import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) import pilib options = pilib.parseoptions(interface['options']) address = int(interface['address']) # TODO : respond to more options, like pullup and pulldown pilib.writedatedlogmsg(pilib.iolog, 'GPIO address' + str(address) + ' enabled', 4, logconfig['iologlevel']) # Get name from ioinfo table to give it a colloquial name gpioname = pilib.sqlitedatumquery(pilib.controldatabase, 'select name from ioinfo where id=\'' + interface['id'] + '\'') polltime = pilib.gettimestring() querylist = [] # Append to inputs and update name, even if it's an output (can read status as input) if options['mode'] == 'output': pilib.writedatedlogmsg(pilib.iolog, 'Setting output mode for GPIO address' + str(address), 3, logconfig['iologlevel']) try: GPIO.setup(address, GPIO.OUT) except TypeError: pilib.writedatedlogmsg(pilib.iolog, 'You are trying to set a GPIO with the wrong variable type : ' + str(type(address)), 0, logconfig['iologlevel']) pilib.writedatedlogmsg(pilib.iolog, 'Exiting interface routine for ' + interface['id'], 0, logconfig['iologlevel']) return # Set the value of the gpio. # Get previous value if exists if interface['id'] in prevoutputids: value = prevoutputvalues[prevoutputids.index(interface['id'])] else: value = 0 if value == 1: GPIO.output(address, True) pilib.writedatedlogmsg(pilib.iolog, 'Setting output ON for GPIO address' + str(address), 3, logconfig['iologlevel']) else: GPIO.output(address, False) pilib.writedatedlogmsg(pilib.iolog, 'Setting output OFF for GPIO address' + str(address), 3, logconfig['iologlevel']) # Get output settings and keep them if the GPIO previously existed if interface['id'] in prevoutputids: pollfreq = prevoutputs[prevoutputids.index(interface['id'])]['pollfreq'] ontime = prevoutputs[prevoutputids.index(interface['id'])]['ontime'] offtime = prevoutputs[prevoutputids.index(interface['id'])]['offtime'] else: try: pollfreq = defaults['defaultoutputpollfreq'] except: pollfreq = 60 ontime = '' offtime = '' # Add entry to outputs tables querylist.append('insert into outputs values (\'' + interface['id'] + '\',\'' + interface['interface'] + '\',\'' + interface['type'] + '\',\'' + str( address) + '\',\'' + gpioname + '\',\'' + str(value) + "','','" + str(polltime) + '\',\'' + str(pollfreq) + "','" + ontime + "','" + offtime + "')") else: GPIO.setup(address, GPIO.IN) value = GPIO.input(address) pilib.writedatedlogmsg(pilib.iolog, 'Setting input mode for GPIO address' + str(address), 3, logconfig['iologlevel']) # Get input settings and keep them if the GPIO previously existed if interface['id'] in previnputids: pollfreq = previnputs[previnputids.index(interface['id'])]['pollfreq'] ontime = previnputs[previnputids.index(interface['id'])]['ontime'] offtime = previnputs[previnputids.index(interface['id'])]['offtime'] pilib.writedatedlogmsg(pilib.iolog, 'Restoring values from previous inputids: pollfreq = ' + str( pollfreq) + ' ontime = ' + str(ontime) + ' offtime = ' + str( offtime), 3, logconfig['iologlevel']) else: try: pollfreq = defaults['defaultinputpollfreq'] except: pollfreq = 60 ontime = '' offtime = '' pilib.writedatedlogmsg(pilib.iolog, 'Setting values to defaults, defaultinputpollfreq = ' + str( pollfreq), 3, logconfig['iologlevel']) querylist.append( 'insert into inputs values (\'' + interface['id'] + '\',\'' + interface['interface'] + '\',\'' + interface['type'] + '\',\'' + str(address) + '\',\'' + gpioname + '\',\'' + str( value) + "','','" + str(polltime) + '\',\'' + str(pollfreq) + "','" + ontime + "','" + offtime + "')") return querylist
def processactions(): # Read database to get our actions actiondicts = pilib.readalldbrows(pilib.controldatabase, 'actions') for actiondict in actiondicts: alert = False # Instantiate the action class thisaction = pilib.action(actiondict) thisaction.statusmsg = '' # print(actiondict) # process condition if thisaction.conditiontype == 'dbvalue': if thisaction.enabled: thisaction.statusmsg += 'Action enabled.' dbdir = getattr(pilib, 'databasedir') # print(dbdir) dbpath = dbdir + thisaction.database + '.db' # variablename is columnname for dbvalue conditiontype thisaction.variablevalue = pilib.getsinglevalue(dbpath, thisaction.tablename, thisaction.variablename, 'rowid=' + str(thisaction.valuerowid)) # get variable type to handle variablestypedict = pilib.getpragmanametypedict(dbpath, thisaction.tablename) vartype = variablestypedict[thisaction.variablename] thisaction.statusmsg += ' Variablevalue: ' + str(thisaction.variablevalue) + '. Criterion: ' + str(thisaction.criterion) + ' . ' # process criterion according to type curstatus = False if vartype == 'boolean': thisaction.statusmsg += ' Processing boolean. ' # TODO: String conversion is a hack here and needs series work. if str(thisaction.variablevalue) == str(thisaction.criterion): curstatus = True elif vartype == 'integer' or vartype == 'real': thisaction.statusmsg += ' Processing integer/real. ' # print(thisaction.operator) thisaction.variablevalue = float(thisaction.variablevalue) thisaction.criterion = float(thisaction.criterion) if thisaction.operator == 'greater': if thisaction.variablevalue > thisaction.criterion: curstatus = True elif thisaction.operator == 'greaterorequal': if thisaction.variablevalue >= thisaction.criterion: curstatus = True elif thisaction.operator == 'less': if thisaction.variablevalue < thisaction.criterion: curstatus = True elif thisaction.operator == 'lessorequal': if thisaction.variablevalue <= thisaction.criterion: curstatus = True elif thisaction.operator == 'equal': if thisaction.variablevalue == thisaction.criterion: curstatus = True else: thisaction.statusmsg += 'Operator error. ' if thisaction.variablevalue == thisaction.criterion: curstatus = True elif vartype == 'text': thisaction.statusmsg += ' Processing text. ' if thisaction.variablevalue == thisaction.criterion: curstatus = True else: thisaction.statusmsg += ' Mode Error for vartype ' + vartype + '. ' if curstatus: thisaction.statusmsg += 'Status is true. ' else: thisaction.statusmsg += 'Status is not true. ' currenttime = pilib.gettimestring() # if status is true and current status is false, set ontime if curstatus and not thisaction.status: # print(str(curstatus) + ' ' + str(thisaction.status)) thisaction.statusmsg += 'Setting status ontime. ' thisaction.ontime = pilib.gettimestring() thisaction.status = 1 elif not curstatus and thisaction.status: thisaction.statusmsg += 'Setting status offtime. ' thisaction.offtime = pilib.gettimestring() thisaction.status = 0 # Set current status if curstatus: thisaction.status = 1 # print('settings status') else: thisaction.status = 0 # print('resetting status') # if status is true and alarm isn't yet active, see if ondelay exceeded if curstatus and not thisaction.active: # print(pilib.timestringtoseconds(currenttime)) statusontime = pilib.timestringtoseconds(currenttime) - pilib.timestringtoseconds(thisaction.ontime) # print(statusontime) if statusontime > thisaction.ondelay: thisaction.statusmsg += 'Setting action active' thisaction.active = 1 else: thisaction.statusmsg += 'On delay not reached' # if status is not true and alarm is active, see if offdelay exceeded if not curstatus and thisaction.active: statusofftime = pilib.timestringtoseconds(currenttime) - pilib.timestringtoseconds(thisaction.offtime) if statusofftime > thisaction.offdelay: thisaction.statusmsg += 'Setting action inactive' thisaction.active = 0 # Send an alert / reset indicator if activereset is on if thisaction.activereset: thisaction.offact() else: thisaction.statusmsg += 'Off delay not reached' # test to see if it is time to alert, based on delay ond alert time if thisaction.active: # check to see if it is time to alert # For things like outputs, actionfrequency should be zero to always enforce that action is on. # print(pilib.timestringtoseconds(currenttime)) # print(pilib.timestringtoseconds(thisaction.lastactiontime)) # print(float(thisaction.actionfrequency)) # print(pilib.timestringtoseconds(currenttime)-pilib.timestringtoseconds(thisaction.lastactiontime)) if pilib.timestringtoseconds(currenttime) - pilib.timestringtoseconds(thisaction.lastactiontime) > float(thisaction.actionfrequency): alert = True thisaction.statusmsg += "Time to act. " else: alert = False thisaction.statusmsg += "Not yet time to act." if alert: # We're ready to alert or alert again. thisaction.lastactiontime = currenttime if curstatus: thisaction.onact() else: thisaction.offact() else: thisaction.statusmsg += 'Action disabled.' thisaction.status = 0 else: thisaction.statusmsg += 'Mode unrecognized.' # print(thisaction.statusmsg) thisaction.publish()
def processMBinterface(interface, prevoutputs, prevoutputids, previnputs, previnputids, defaults, logconfig): from netfun import readMBcodedaddresses, MBFCfromaddress import pilib # get all modbus reads that have the same address from the modbus table try: modbustable = pilib.readalldbrows(pilib.controldatabase, 'modbustcp') except: pilib.writedatedlogmsg(pilib.iolog, 'Error reading modbus table', 0, logconfig['iologlevel']) else: pilib.writedatedlogmsg(pilib.iolog, 'Read modbus table', 4, logconfig['iologlevel']) querylist = [] for entry in modbustable: # Get name from ioinfo table to give it a colloquial name # First we have to give it a unique ID. This is a bit difficult with modbus if entry['mode'] == 'read': shortmode = 'R' elif entry['mode'] == 'write': shortmode = 'W' elif entry['mode'] == 'readwrite': shortmode = 'RW' else: pilib.writedatedlogmsg(pilib.iolog, 'modbus mode error', 1, logconfig['iologlevel']) try: mbid = entry['interfaceid'] + '_' + str(entry['register']) + '_' + str(entry['length']) + '_' + shortmode except KeyError: pilib.writedatedlogmsg(pilib.iolog, 'Cannot form mbid due to key error', 0, logconfig['iologlevel']) return pilib.writedatedlogmsg(pilib.iolog, 'Modbus ID: ' + mbid, 4, logconfig['iologlevel']) mbname = pilib.sqlitedatumquery(pilib.controldatabase, "select name from ioinfo where id='" + mbid + "'") polltime = pilib.gettimestring() if entry['interfaceid'] == interface['id']: # For now, we're going to read them one by one. We'll assemble these into block reads # in the next iteration if entry['mode'] == 'read': # Get previous metadata and data # Get input settings and keep them if the input previously existed if mbid in previnputids: pollfreq = previnputs[previnputids.index(mbid)]['pollfreq'] ontime = previnputs[previnputids.index(mbid)]['ontime'] offtime = previnputs[previnputids.index(mbid)]['offtime'] prevvalue = previnputs[previnputids.index(mbid)]['offtime'] prevpolltime = previnputs[previnputids.index(mbid)]['offtime'] pilib.writedatedlogmsg(pilib.iolog, 'Restoring values from previous inputids: pollfreq = ' + str( pollfreq) + ' ontime = ' + str(ontime) + ' offtime = ' + str( offtime), 3, logconfig['iologlevel']) else: # set values to defaults if it did not previously exist try: pollfreq = defaults['defaultinputpollfreq'] except: pollfreq = 60 ontime = '' offtime = '' prevvalue = '' prevpolltime = '' pilib.writedatedlogmsg(pilib.iolog, 'Setting values to defaults, defaultinputpollfreq = ' + str(pollfreq), 3, logconfig['iologlevel']) # Read data try: readresult = readMBcodedaddresses(interface['address'], entry['register'], entry['length']) except: pilib.writedatedlogmsg(pilib.iolog, 'Uncaught reror reading modbus value', 0, logconfig['iologlevel']) else: if readresult['statuscode'] == 0: values = readresult['values'] try: FC = MBFCfromaddress(int(entry['register'])) except ValueError: pilib.writedatedlogmsg(pilib.iolog, 'Malformed address for FC determination : ' + str(entry['address']), 0, logconfig['iologlevel']) else: pilib.writedatedlogmsg(pilib.iolog, 'Function code : ' + str(FC), 4, logconfig['iologlevel']) returnvalue = 0 if len(values) > 0: pilib.writedatedlogmsg(pilib.iolog, 'Multiple values returned', 4, logconfig['iologlevel']) if not entry['bigendian']: try: values.reverse() except AttributeError: pilib.writedatedlogmsg(pilib.iolog, 'Error on reverse of MB values: ' + str(values), 0, logconfig['iologlevel']) if entry['format'] == 'float32': import struct byte2 = values[0] % 256 byte1 = (values[0] - byte2)/256 byte4 = values[1] % 256 byte3 = (values[1] - byte4)/256 byte1hex = chr(byte1) byte2hex = chr(byte2) byte3hex = chr(byte3) byte4hex = chr(byte4) hexstring = byte1hex + byte2hex + byte3hex + byte4hex returnvalue = struct.unpack('>f',hexstring)[0] else: for index, val in enumerate(values): if FC in [0, 1]: returnvalue += val * 2 ** index elif FC in [3, 4]: returnvalue += val * 256 ** index else: pilib.writedatedlogmsg(pilib.iolog, 'Invalid function code', 0, logconfig['iologlevel']) else: returnvalue = values[0] if entry['options'] != '': options = pilib.parseoptions(entry['options']) if 'scale' in options: # try: returnvalue = returnvalue * float(options['scale']) # except: # pilib.writedatedlogmsg(pilib.iolog, 'Error on scale operation', 0, logconfig['iologlevel']) if 'precision' in options: # try: returnvalue = round(returnvalue, int(options['precision'])) # except: # pilib.writedatedlogmsg(pilib.iolog, 'Error on precision operation', 0, logconfig['iologlevel']) pilib.writedatedlogmsg(pilib.iolog, 'Values read: ' + str(values), 4, logconfig['iologlevel']) pilib.writedatedlogmsg(pilib.iolog, 'Value returned: ' + str(returnvalue), 4, logconfig['iologlevel']) # Contruct entry for newly acquired data querylist.append('insert into inputs values (\'' + mbid + '\',\'' + interface['id'] + '\',\'' + interface['type'] + '\',\'' + str(entry['register']) + '\',\'' + mbname + '\',\'' + str( returnvalue) + "','','" + str(polltime) + '\',\'' + str(pollfreq) + "','" + ontime + "','" + offtime + "')") else: pilib.writedatedlogmsg(pilib.iolog, 'Statuscode ' + str(readresult['statuscode']) + ' on MB read : ' + readresult['message'] , 0, logconfig['iologlevel']) # restore previous value and construct entry if it existed (or not) querylist.append('insert into inputs values (\'' + mbid + '\',\'' + interface['interface'] + '\',\'' + interface['type'] + '\',\'' + str(entry['register']) + '\',\'' + mbname + '\',\'' + str(prevvalue) + "','','" + str(prevpolltime) + '\',\'' + str(pollfreq) + "','" + ontime + "','" + offtime + "')") pilib.writedatedlogmsg(pilib.iolog, 'Querylist: ' + str(querylist) , 4, logconfig['iologlevel']) return querylist
def updateiodata(database): # This recreates all input and output tables based on the interfaces table. # Thus way we don't keep around stale data values. We could at some point incorporate # a retention feature that keeps them around in case they disappear temporarily. # It also reads the elements if they are enabled and it's time to read them import pilib import traceback import RPi.GPIO as GPIO allowedGPIOaddresses = [18, 23, 24, 25, 4, 17, 21, 22] logconfig = pilib.getlogconfig() GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) tables = pilib.gettablenames(pilib.controldatabase) if 'interfaces' in tables: interfaces = pilib.readalldbrows(pilib.controldatabase, 'interfaces') else: pilib.writedatedlogmsg(pilib.iolog, 'interfaces table not found. Exiting', 1, logconfig['iologlevel']) return if 'inputs' in tables: previnputs = pilib.readalldbrows(pilib.controldatabase, 'inputs') # Make list of IDs for easy indexing previnputids = [] for input in previnputs: previnputids.append(input['id']) else: previnputs = [] previnputids = [] if 'outputs' in tables: prevoutputs = pilib.readalldbrows(pilib.controldatabase, 'outputs') # Make list of IDs for easy indexing prevoutputids = [] prevoutputvalues = [] for output in prevoutputs: prevoutputids.append(output['id']) prevoutputvalues.append(output['value']) else: prevoutputs = {} prevoutputids = [] if 'defaults' in tables: defaults = pilib.readalldbrows(pilib.controldatabase, 'defaults')[0] defaultinputpollfreq = defaults['inputpollfreq'] defaultoutputpollfreq = defaults['outputpollfreq'] else: defaults = [] defaultinputpollfreq = 60 defaultoutputpollfreq = 60 if 'indicators' in tables: indicatornames = [] previndicators = pilib.readalldbrows(pilib.controldatabase, 'indicators') for indicator in previndicators: indicatornames.append(indicator['name']) else: previndicators = [] indicatornames = [] # We drop all inputs and outputs and recreate # Add all into one query so there is no time when the IO don't exist. querylist = [] querylist.append('delete from inputs') querylist.append('delete from outputs') # This is temporary. Clearing the table here and adding entries below can result in a gap in time # where there are no database indicator entries. This is not too much of a problem with indicators, as we # update the hardware explicitly after we add the entries. If the interface queries the table during # this period, however, we could end up with an apparently empty table. # TODO: FIX update on indicators in updateio pilib.sqlitequery(pilib.controldatabase, 'delete from indicators') owfsupdate = False for interface in interfaces: if interface['interface'] == 'I2C': pilib.writedatedlogmsg(pilib.iolog, 'Processing I2C interface' + interface['name'], 3, logconfig['iologlevel']) if interface['enabled']: pilib.writedatedlogmsg(pilib.iolog, 'I2C Interface ' + interface['name'] + ' enabled', 3, logconfig['iologlevel']) if interface['type'] == 'DS2483': pilib.writedatedlogmsg(pilib.iolog, 'Interface type is DS2483', 3, logconfig['iologlevel']) owfsupdate = True elif interface['interface'] == 'USB': pilib.writedatedlogmsg(pilib.iolog, 'Processing USB interface' + interface['name'], 3, logconfig['iologlevel']) if interface['enabled']: pilib.writedatedlogmsg(pilib.iolog, 'USB Interface ' + interface['name'] + ' enabled', 3, logconfig['iologlevel']) if interface['type'] == 'DS9490': pilib.writedatedlogmsg(pilib.iolog, 'Interface type is DS9490', 3, logconfig['iologlevel']) owfsupdate = True elif interface['interface'] == 'MOTE': pilib.writedatedlogmsg(pilib.iolog, 'Processing Mote interface' + interface['name'], 3, logconfig['iologlevel']) if interface['enabled']: pilib.writedatedlogmsg(pilib.iolog, 'Mote Interface ' + interface['name'] + ' enabled', 3, logconfig['iologlevel']) # Grab mote entries from remotes table nodeaddress = int(interface['address']) nodeentries = pilib.dynamicsqliteread(pilib.controldatabase, 'remotes', condition="\"nodeid\"='" + str(nodeaddress) + "'") # Create queries for table insertion # TODO: process mote pollfreq, ontime, offtime moteentries = [] for nodeentry in nodeentries: datadict = pilib.parseoptions(nodeentry['data']) try: entrytype = nodeentry['msgtype'] entryid = 'MOTE' + str(nodeentry['nodeid']) + '_' + nodeentry['keyvaluename'] + '_' + nodeentry['keyvalue'] entrymetareturn = pilib.dynamicsqliteread(pilib.controldatabase, 'ioinfo', condition="\"id\"='" + entryid + "'") try: entrymeta = entrymetareturn[0] except: entrymeta = [] # print(entrymeta) entryoptions={} if entrymeta: entryname = entrymeta['name'] if entrymeta['options']: entryoptions = pilib.parseoptions(entrymeta['options']) else: entryname = '[MOTE' + str(nodeentry['nodeid']) + '] ' + nodeentry['keyvaluename'] + ':' + nodeentry['keyvalue'] except KeyError: print('OOPS KEY ERROR') else: if entrytype == 'iovalue': if 'scale' in entryoptions: entryvalue = str(float(entryoptions['scale']) * float(datadict['iovalue'])) else: entryvalue = datadict['iovalue'] elif entrytype == 'owdev': if 'owtmpasc' in datadict: if 'scale' in entryoptions: entryvalue = str(float(entryoptions['scale']) * float(datadict['owtmpasc'])) else: entryvalue = datadict['owtmpasc'] else: entryvalue = -1 else: entryvalue = -1 moteentries.append('insert into inputs values (\'' + entryid + '\',\'' + interface['interface'] + '\',\'' + interface['type'] + '\',\'' + str(address) + '\',\'' + entryname + '\',\'' + str(entryvalue) + "','','" + nodeentry['time'] + '\',\'' + str(15) + "','" + '' + "','" + '' + "')") # print('querylist') # print(moteentries) querylist.extend(moteentries) elif interface['interface'] == 'LAN': pilib.writedatedlogmsg(pilib.iolog, 'Processing LAN interface' + interface['name'], 3, logconfig['iologlevel']) if interface['enabled']: pilib.writedatedlogmsg(pilib.iolog, 'LAN Interface ' + interface['name'] + ' enabled', 3, logconfig['iologlevel']) if interface['type'] == 'MBTCP': pilib.writedatedlogmsg(pilib.iolog, 'Interface ' + interface['name'] + ' type is MBTCP', 3, logconfig['iologlevel']) try: mbentries = processMBinterface(interface, prevoutputs, prevoutputids, previnputs, previnputids, defaults, logconfig) except: pilib.writedatedlogmsg(pilib.iolog, 'Error processing MBTCP interface ' + interface['name'], 0, logconfig['iologlevel']) errorstring = traceback.format_exc() pilib.writedatedlogmsg(pilib.iolog, 'Error of kind: ' + errorstring, 0, logconfig['iologlevel']) else: pilib.writedatedlogmsg(pilib.iolog, 'Done processing MBTCP interface ' + interface['name'], 3, logconfig['iologlevel']) querylist.extend(mbentries) elif interface['interface'] == 'GPIO': try: address = int(interface['address']) except KeyError: pilib.writedatedlogmsg(pilib.iolog, 'GPIO address key not found for ' + interface['name'], 1, logconfig['iologlevel']) continue pilib.writedatedlogmsg(pilib.iolog, 'Processing GPIO interface ' + str(interface['address']), 3, logconfig['iologlevel']) if address in allowedGPIOaddresses: pilib.writedatedlogmsg(pilib.iolog, 'GPIO address' + str(address) + ' allowed', 4, logconfig['iologlevel']) # Check if interface is enabled if interface['enabled']: GPIOentries = processGPIOinterface(interface, prevoutputs, prevoutputvalues, prevoutputids, previnputs, previnputids, defaults, logconfig) querylist.extend(GPIOentries) else: pilib.writedatedlogmsg(pilib.iolog, 'GPIO address' + str(address) + ' disabled', 4, logconfig['iologlevel']) GPIO.setup(address, GPIO.IN) else: pilib.writedatedlogmsg(pilib.iolog, 'GPIO address' + str(address) + ' not allowed. Bad things can happen. ', 4, logconfig['iologlevel']) elif interface['interface'] == 'SPI0': pilib.writedatedlogmsg(pilib.iolog, 'Processing SPI0', 1, logconfig['iologlevel']) if interface['type'] == 'SPITC': import readspi spidata = readspi.readspitc(0) spitcentries = readspi.recordspidata(database, spidata) querylist.extend(spitcentries) if interface['type'] == 'CuPIDlights': import spilights spilightsentries, setlist = spilights.getCuPIDlightsentries('indicators', 0, previndicators) querylist.extend(spilightsentries) spilights.updatelightsfromdb(pilib.controldatabase, 'indicators', 0) spilights.setspilights(setlist, 0) elif interface['interface'] == 'SPI1': pilib.writedatedlogmsg(pilib.iolog, 'Processing SPI1', 1, logconfig['iologlevel']) if interface['type'] == 'CuPIDlights': import spilights spilightsentries, setlist = spilights.getCuPIDlightsentries('indicators', 1, previndicators) querylist.extend(spilightsentries) spilights.setspilights(setlist, 1) # Set tables querylist.append(pilib.makesinglevaluequery('systemstatus', 'lastiopoll', pilib.gettimestring())) if owfsupdate: from owfslib import runowfsupdate devices, owfsentries = runowfsupdate(execute=False) querylist.extend(owfsentries) pilib.writedatedlogmsg(pilib.iolog, 'Executing query: ' + str(querylist), 5, logconfig['iologlevel']) try: pilib.sqlitemultquery(pilib.controldatabase, querylist) except: errorstring = traceback.format_exc() pilib.writedatedlogmsg(pilib.iolog, 'Error executing query, message: ' + errorstring, 0, logconfig['iologlevel']) pilib.writedatedlogmsg(pilib.errorlog, 'Error executing updateio query, message: ' + errorstring) pilib.writedatedlogmsg(pilib.errorlog, 'Query: ' + str(querylist))
def updateowfsdevices(busdevices, myProxy=None): import pilib # get defaults defaults = pilib.readalldbrows(pilib.controldatabase, 'defaults')[0] # get current entries previnputs = pilib.readalldbrows(pilib.controldatabase, 'inputs') # Make list of IDs for easy indexing previnputids = [] for input in previnputs: previnputids.append(input['id']) # Iterate over devices. Determine if values exist for polltime, frequency. # If so, update the device. If not, use defaults. # Then determine whether we should update value or not (Read temperature) for index, device in enumerate(busdevices): if device.sensorid in previnputids: try: newpollfreq = int(previnputs[previnputids.index(device.sensorid)]['pollfreq']) except ValueError: device.pollfreq = defaults['inputpollfreq'] else: if newpollfreq >= 0: device.pollfreq = previnputs[previnputids.index(device.sensorid)]['pollfreq'] else: device.pollfreq = defaults['inputpollfreq'] device.ontime = previnputs[previnputids.index(device.sensorid)]['ontime'] device.offtime = previnputs[previnputids.index(device.sensorid)]['offtime'] device.polltime = previnputs[previnputids.index(device.sensorid)]['polltime'] device.value = previnputs[previnputids.index(device.sensorid)]['value'] else: device.pollfreq = defaults['inputpollfreq'] device.ontime = '' device.offtime = '' device.polltime = '' device.value = '' # We're going to set a name because calling things by their ids is getting # a bit ridiculous, but we can't have empty name fields if we rely on them # being there. They need to be unique, so we'll name them by type and increment them if device.type == 'DS18B20': # Get name if one exists name = pilib.sqlitedatumquery(pilib.controldatabase, 'select name from ioinfo where id=\'' + device.sensorid + '\'') # If doesn't exist, check to see if proposed name exists. If it doesn't, add it. # If it does, keep trying. if name == '': for rangeindex in range(100): # check to see if name exists name = device.type + '-' + str(int(index + 1)) # print(name) foundid = pilib.sqlitedatumquery(pilib.controldatabase, 'select id from ioinfo where name=\'' + name + '\'') # print('foundid' + foundid) if foundid: pass else: pilib.sqlitequery(pilib.controldatabase, pilib.makesqliteinsert('ioinfo', valuelist=[device.sensorid, name], valuenames=['id', 'name'])) break device.name = name # Is it time to read temperature? if pilib.timestringtoseconds(pilib.gettimestring()) - pilib.timestringtoseconds(device.polltime) > device.pollfreq: device.readprop('temperature', myProxy) device.polltime = pilib.gettimestring() device.value = device.temperature else: pass # print('not time to poll') device.unit = 'F' # We update the device and send them back for other purposes. busdevices[index] = device return busdevices
def watchdognetstatus(allnetstatus=None): import pilib import netconfig import subprocess from cupiddaemon import pgrepstatus """ And now comes the checking of configuration specific statuses and restarting them if enabled and necessary NOW Set number configuration types: eth0 is always dhcp if interface is not specified, it is assumed that the specified configuration applies to wlan0 ap : access point on wlan0. Currently, address is hard-coded as 192.168.0.1 as set in hostapd (to have dhcp all on same subnet) station : station mode on wlan0 IP address mode set in 'addtype' field. If DHCP, set as DHCP. If static, set as address field eth0wlan0bridge : wlan0 set as AP mode with bridge to eth0 wlan0wlan1bridge : wlan0 set as station mode, wlan1 as ap mode with bridge wlan1wlan0bridge wlan1 set as station mode, wlan0 as ap mode with bridge IN THE FUTURE netconfigdata will have a row for each interface that needs to be configured. Each interface can be either static, dhcp, or ap. Each interface can also bridge, but this will be limited at first, due to the number of combinations. If bridge is selected, the mode will be checked, and the appropriate IPTables will be set based on which one is AP """ if not allnetstatus: allnetstatus = updatenetstatus() netconfigdata = allnetstatus['netconfigdata'] netstatus = allnetstatus['netstatusdict'] # Refactor ifaces array. We could probably do this earlier and pass it around like this ifacedict = {} for iface in allnetstatus['ifacesdictarray']: # print(iface['name']) # print(iface) ifacedict[iface['name']] = iface # print(ifacedict) statusmsg = '' currenttime = pilib.gettimestring() runconfig = False if netconfigdata['mode'] in ['ap', 'tempap']: pilib.log(pilib.networklog, 'AP Mode is set. ', 1, pilib.networkloglevel) """ THIS NEEDS TO BE REWRITTEN ( or absorbed into eth0wlan0bridge ) """ if netconfigdata['mode'] == 'tempap': timesincelastretry = pilib.timestringtoseconds(currenttime) - pilib.timestringtoseconds(netconfigdata['laststationretry']) pilib.log(pilib.networklog, 'TempAP mode: Time since last retry: ' + str(timesincelastretry) + '. Station retry time: ' + str(netconfigdata['stationretrytime']), 1, pilib.networkloglevel) if timesincelastretry > netconfigdata['stationretrytime']: # We go back to station mode statusmsg += 'Time to go back to station mode. ' pilib.log(pilib.networklog, 'Time to go back to station mode. ', 1, pilib.networkloglevel) pilib.setsinglevalue(pilib.systemdatadatabase, 'netconfig', 'mode', 'station') pilib.setsinglevalue(pilib.systemdatadatabase, 'netconfig', 'laststationretry', '') netconfig.runconfig() else: # If we have ap up, do nothing if netstatus['dhcpstatus']: statusmsg += 'AP checked and ok. ' pilib.log(pilib.networklog, 'AP checked and ok. ', 1, pilib.networkloglevel) pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'mode', 'ap') pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'SSID', 'cupidwifi') pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'offlinetime', '') # If we don't have dhcp up, restart ap mode # this will currently cause reboot if we don't set onboot=True # We set status message in case we change our minds and reboot here. else: statusmsg += 'Restarting AP. ' pilib.log(pilib.networklog, 'Restarting AP mode. ', 1, pilib.networkloglevel) pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'statusmsg', statusmsg) netconfig.runconfig() # Station Mode. Again, like above, this should be modular. elif netconfigdata['mode'] == 'station': pilib.log(pilib.networklog, 'Station mode is set. ', 3, pilib.networkloglevel) # Check station address (not yet implemented) and wpa status (implemented) stationinterface = 'wlan0' try: stationifacedata = ifacedict[stationinterface] except KeyError: pilib.log(pilib.networklog, 'No stationiface data(' + stationinterface + ') present for mode ' + netconfigdata['mode'], 1, pilib.networkloglevel) statusmsg += 'No stationiface data(' + stationinterface + ') present for mode ' + netconfigdata['mode'] runconfig = True else: wpadata = pilib.parseoptions(stationifacedata['wpastate']) if wpadata['wpa_state'] == 'COMPLETED' and stationifacedata['address']: pilib.log(pilib.networklog, 'station interface ' + stationinterface + ' wpastatus appears ok with address ' + str(stationifacedata['address']), 3, pilib.networkloglevel) else: pilib.log(pilib.networklog, 'station interface for ' + stationinterface + ' does not appear ok judged by wpa_state: wpastate = ' + wpadata['wpa_state'] + ' address= ' + stationifacedata['address'], 1, pilib.networkloglevel) statusmsg += 'station interface does not appear ok judged by wpa_state. ' runconfig = True # Should do special handling in here to verify address for static mode. # # If we have wpa up, do nothing # if int(netstatus['connected']): # statusmsg += 'Station wpamode appears ok. ' # pilib.log(pilib.networklog, 'wpamode appears ok. ', 1, pilib.networkloglevel) # # # If wpa is not connected # else: # statusmsg += 'Station wpamode appears disconnected. ' # pilib.log(pilib.networklog, 'wpamode appears disconnected. ', 1, pilib.networkloglevel) # # if netstatus['offlinetime'] == '': # pilib.log(pilib.networklog, 'Setting offline time for empty value. ', 4, # pilib.networkloglevel) # pilib.setsinglevalue('netstatus', 'offlinetime', pilib.gettimestring()) # offlinetime = 0 # else: # pilib.log(pilib.networklog, 'Calculating offline time. ', 4, pilib.networkloglevel) # offlinetime = pilib.timestringtoseconds(currenttime) - pilib.timestringtoseconds( # netstatus['offlinetime']) # # pilib.log(pilib.networklog, 'wpa has been offline for ' + str(offlinetime) + '. ', 3, # pilib.networkloglevel) # statusmsg += 'We have been offline for ' + str(offlinetime) + '. ' # # # If aprevert is aprevert or temprevert and we've been offline long enough, flip over to ap # # then set offline time to now (otherwise this keeps happening) # if netconfigdata['aprevert'] in ['temprevert', 'aprevert'] and offlinetime > netconfigdata[ # 'apreverttime']: # # # set laststationretry to currenttime. This marks when we flipped over to ap # statusmsg += 'Setting last station retry time. ' # pilib.log(pilib.networklog, 'Reverting to AP mode', 3, pilib.networkloglevel) # pilib.log(pilib.networklog, # 'Setting last station retry time to ' + str(currenttime), 0, # pilib.networkloglevel) # pilib.setsinglevalue(pilib.systemdatadatabase, 'netconfig', 'laststationretry', currenttime) # pilib.setsinglevalue('netstatus', 'offlinetime', currenttime) # # if netconfigdata['aprevert'] == 'aprevert': # # set mode to ap # statusmsg += 'Setting mode to ap. ' # pilib.log(pilib.networklog, 'Setting mode to ap ' + str(currenttime), 3, # pilib.networkloglevel) # pilib.setsinglevalue(pilib.systemdatadatabase, 'netconfig', 'mode', 'ap') # elif netconfigdata['aprevert'] == 'temprevert': # # set mode to tempap # statusmsg += 'Setting mode to tempap. ' # pilib.log(pilib.networklog, 'Setting mode to tempap ' + str(currenttime), 3, # pilib.networkloglevel) # pilib.setsinglevalue(pilib.systemdatadatabase, 'netconfig', 'mode', 'tempap') # # # Unfortunately, to revert to ap mode successfully, we currently have to reboot # # this is built into the netconfig script - any time you set ap mode except at boot, it reboots # pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'statusmsg', statusmsg) # pilib.log(pilib.syslog, 'Running netconfig . ', 4, # pilib.sysloglevel) # netconfig.runconfig() # elif offlinetime > 15: # pilib.log(pilib.syslog, 'Restarting netconfig on bad wpastatus', 1, # pilib.sysloglevel) # runconfig = True # # # Here, we need to check the ifaces address. Netstatus address is ambiguous # if netstatus['ip_address'] != netconfigdata['address']: # pilib.log(pilib.networklog, 'IP address mismatch ( Configured for ' + netconfigdata['address'] + '. Reporting' + netstatus['ip_address'] + ' ). Running config.', 1, pilib.networkloglevel) # runconfig = True # else: # pilib.log(pilib.networklog, 'IP address match for ' + netconfigdata['address'] + '. ', 3, pilib.networkloglevel) elif netconfigdata['mode'] == 'eth0wlan0bridge': # We don't actually check eth0. This is because we shouldn't have to. Also, if we don't check on eth0, we can # use the same mode for wlan0 AP and eth0wlan0 bridge. Hot plug, works fine. # Check wlan0 dhcp and hostapd status try: wlan0ifacedata =ifacedict['wlan0'] except KeyError: pilib.log(pilib.networklog, 'No wlan0 data present in configuration of eth0wlan0bridge. ', 1, pilib.networkloglevel) statusmsg += 'wlan0 data is not present. ' runconfig = True else: pilib.log(pilib.networklog, 'Checking dhcp server status on wlan0. ', 4, pilib.networkloglevel) try: result = subprocess.check_output(['/usr/sbin/service', 'isc-dhcp-server', 'status'], stderr=subprocess.PIPE) except Exception, e: # If not running, the subprocess call will throw an error pilib.log(pilib.networklog, 'Error in reading dhcp server status. Assumed down. ', 1, pilib.networkloglevel) statusmsg += 'dhcp server appears down. ' runconfig = True else: pilib.log(pilib.networklog, 'DHCP server appears to be up. ', 1, pilib.networkloglevel) """ Check ifconfig ipaddress for wlan0 This should be programmable. """ if wlan0ifacedata['address'] == '192.168.0.1': pilib.log(pilib.networklog, 'wlan0 address is appears to be set properly: ' + str(wlan0ifacedata['address']), 3, pilib.networkloglevel) else: pilib.log(pilib.networklog, 'wlan0 address is not set properly: ' + str(wlan0ifacedata['address']), 1, pilib.networkloglevel) statusmsg += 'wlan0 address does not appear ok. ' runconfig = True if pgrepstatus('hostapd.*wlan0')['count'] == 1: pilib.log(pilib.networklog, 'hostapd on wlan0 appears to be ok. ', 3, pilib.networkloglevel) else: pilib.log(pilib.networklog, 'hostapd on wlan0 does NOT appear to be ok. ', 1, pilib.networkloglevel) statusmsg += 'wlan0 hostpad does not appear ok. ' runconfig=True
pilib.writedatedlogmsg(pilib.systemstatuslog, 'Error in git version check', 0, pilib.systemstatusloglevel) else: pilib.writedatedlogmsg(pilib.systemstatuslog, 'Git version check complete', 3, pilib.systemstatusloglevel) systemstatus = pilib.readalldbrows(pilib.controldatabase, 'systemstatus')[0] # Keep reading system status? while systemstatus['systemstatusenabled']: starttime = time.time() pilib.writedatedlogmsg(pilib.systemstatuslog, 'System status routine is starting. ', 3, pilib.systemstatusloglevel) pilib.writedatedlogmsg(pilib.systemstatuslog, 'Beginning network routines. ', 3, pilib.systemstatusloglevel) currenttime = pilib.gettimestring() pilib.setsinglevalue(pilib.controldatabase, 'systemstatus', 'lastsystemstatuspoll', pilib.gettimestring()) pilib.writedatedlogmsg(pilib.systemstatuslog, 'Running updateifacestatus. ', 4, pilib.systemstatusloglevel) # Update network interfaces statuses for all interfaces, in database tables as well # Check on wpa supplicant status as well. Function returns wpastatusdict try: pilib.writedatedlogmsg(pilib.networklog, 'Running updateifacestatus', 4, pilib.networkloglevel) wpastatusdict = updateifacestatus() except: pilib.writedatedlogmsg(pilib.networklog, 'Exception in updateifacestatus. ') else: pilib.writedatedlogmsg(pilib.networklog, 'Updateifacestatus completed. ') pilib.writedatedlogmsg(pilib.systemstatuslog, 'Completed updateifacestatus. ', 4, pilib.systemstatusloglevel)
def process(self): # print(actiondict) # process condition if self.enabled: self.statusmsg = pilib.gettimestring() + ' : Enabled and processing. ' if self.conditiontype == 'temporal': # Test event time against current time # Has time passed, and then is time within action window (don't want to act on all past actions if we miss them) timediff = float(pilib.timestringtoseconds(pilib.gettimestring()) - pilib.timestringtoseconds(self.actiontime)) if timediff >= 0: if timediff < int(self.actiontimewindow): # We act self.statusmsg += 'Time to act. ' # Then create the repeat event if we are supposed to. if hasattr(self, 'repeat'): newtimestring = str(pilib.getnexttime(self.actiontime, self.repeat, int(self.repeatvalue))) self.actiontime = newtimestring else: self.statusmsg += 'Past time but outside of window ' + str(self.actiontimewindow) + '. ' else: self.statusmsg += 'Not time yet for action scheduled for ' + str(self.actiontime) + '. ' elif self.conditiontype == 'logical': # dbpath = pilib.dbnametopath(self.database) # # variablename is columnname for dbvalue conditiontype # if hasattr('valuerowid'): # self.variablevalue = pilib.getsinglevalue(self.database, self.tablename, self.variablename, 'rowid=' + str(self.valuerowid)) # else: # self.variablevalue = pilib.getsinglevalue(self.database, self.tablename, self.variablename) currstatus = evalactionformula(self.actiondatadict['condition']) # get variable type to handle # variablestypedict = pilib.getpragmanametypedict(dbpath, self.tablename) # vartype = variablestypedict[self.variablename] # self.statusmsg += ' Variablevalue: ' + str(self.variablevalue) + '. Criterion: ' + str(self.criterion) + ' . ' # process criterion according to type # curstatus = False # if vartype == 'boolean': # self.statusmsg += ' Processing boolean. ' # # TODO: String conversion is a hack here and needs series work. # if str(self.variablevalue) == str(self.criterion): # curstatus = True # elif vartype == 'integer' or vartype == 'real': # self.statusmsg += ' Processing integer/real. ' # # print(self.operator) # self.variablevalue = float(self.variablevalue) # self.criterion = float(self.criterion) # if self.operator == 'greater': # if self.variablevalue > self.criterion: # curstatus = True # elif self.operator == 'greaterorequal': # if self.variablevalue >= self.criterion: # curstatus = True # elif self.operator == 'less': # if self.variablevalue < self.criterion: # curstatus = True # elif self.operator == 'lessorequal': # if self.variablevalue <= self.criterion: # curstatus = True # elif self.operator == 'equal': # if self.variablevalue == self.criterion: # curstatus = True # else: # self.statusmsg += 'Operator error. ' # if self.variablevalue == self.criterion: # curstatus = True # elif vartype == 'text': # self.statusmsg += ' Processing text. ' # if self.variablevalue == self.criterion: # curstatus = True # else: # self.statusmsg += ' Mode Error for vartype ' + vartype + '. ' if self.status: self.statusmsg += 'Last status is true. Currstatus is ' + str(currstatus) + '. ' else: self.statusmsg += 'Last status is not true. Currstatus is ' + str(currstatus) + '. ' currenttime = pilib.gettimestring() # if status is true and current status is false, set ontime if currstatus and not self.status: # print(str(curstatus) + ' ' + str(self.status)) self.statusmsg += 'Setting status ontime. ' self.ontime = pilib.gettimestring() self.status = 1 elif not currstatus and self.status: self.statusmsg += 'Setting status offtime. ' self.offtime = pilib.gettimestring() self.status = 0 # Set current status if currstatus: self.status = 1 # print('settings status') else: self.status = 0 # print('resetting status') # if status is true and alarm isn't yet active, see if ondelay exceeded if currstatus and not self.active: # print(pilib.timestringtoseconds(currenttime)) statusontime = pilib.timestringtoseconds(currenttime) - pilib.timestringtoseconds(self.ontime) # print(statusontime) if statusontime >= self.ondelay: self.statusmsg += 'Setting action active. ' self.active = 1 else: self.statusmsg += 'On delay not reached. ' # if status is not true and alarm is active, see if offdelay exceeded if not currstatus and self.active: statusofftime = pilib.timestringtoseconds(currenttime) - pilib.timestringtoseconds(self.offtime) if statusofftime >= self.offdelay: self.statusmsg += 'Setting action inactive. ' self.active = 0 else: self.statusmsg += 'Off delay not reached. ' # test to see if it is time to alert, based on delay ond alert time # print(self.statusmsg) act = False if self.active: # check to see if it is time to alert # For things like outputs, actionfrequency should be zero to always enforce that action is on. # print(pilib.timestringtoseconds(currenttime)) # print(pilib.timestringtoseconds(self.lastactiontime)) # print(float(self.actionfrequency)) # print(pilib.timestringtoseconds(currenttime)-pilib.timestringtoseconds(self.lastactiontime)) if pilib.timestringtoseconds(currenttime) - pilib.timestringtoseconds(self.lastactiontime) >= float(self.actionfrequency): act = True self.statusmsg += "Time to act. " else: act = False self.statusmsg += "Not yet time to act." else: # Send an alert / reset indicator if activereset is on if self.activereset: if pilib.timestringtoseconds(currenttime) - pilib.timestringtoseconds(self.lastactiontime) >= float(self.actionfrequency): act = True self.statusmsg += "Time to act. " else: act = False self.statusmsg += "Not yet time to act." if act: # We're ready to alert or alert again. self.lastactiontime = currenttime if currstatus: self.onact() else: self.offact() else: self.statusmsg += 'Action disabled.' self.status = 0 else: self.statusmsg += 'Mode unrecognized.'
def processGPIOinterface(interface, prevoutputs, prevoutputvalues, prevoutputids, previnputs, previnputids, defaults, logconfig, **kwargs): import pilib if 'method' in kwargs: method = kwargs['method'] else: method = 'pigpio' if method == 'rpigpio': import RPi.GPIO as GPIO elif method == 'pigpio': import pigpio try: if method == 'rpigpio': GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) elif method == 'pigpio': if 'piobject' in kwargs: pilib.log(pilib.iolog, 'Pigpio object already exists. ', 4, logconfig['iologlevel']) pi = kwargs['piobject'] else: pilib.log(pilib.iolog, 'Instantiating pigpio. ', 4, logconfig['iologlevel']) pi = pigpio.pi() except: pilib.log(pilib.iolog, 'Error setting up GPIO. ', 1, logconfig['iologlevel']) else: pilib.log(pilib.iolog, 'Done setting up GPIO. ', 4, logconfig['iologlevel']) options = pilib.parseoptions(interface['options']) address = int(interface['address']) pilib.log(pilib.iolog, 'GPIO address' + str(address) + ' enabled', 4, logconfig['iologlevel']) # Get name from ioinfo table to give it a colloquial name gpioname = pilib.sqlitedatumquery(pilib.controldatabase, 'select name from ioinfo where id=\'' + interface['id'] + '\'') polltime = pilib.gettimestring() querylist = [] # Append to inputs and update name, even if it's an output (can read status as input) if options['mode'] == 'output': pilib.log(pilib.iolog, 'Setting output mode for GPIO address' + str(address), 3, logconfig['iologlevel']) try: if method == 'rpigpio': GPIO.setup(address, GPIO.OUT) elif method == 'pigpio': pi.set_mode(address, pigpio.OUTPUT) except TypeError: pilib.log(pilib.iolog, 'You are trying to set a GPIO with the wrong variable type : ' + str(type(address)), 0, logconfig['iologlevel']) pilib.log(pilib.iolog, 'Exiting interface routine for ' + interface['id'], 0, logconfig['iologlevel']) return except: pilib.log(pilib.iolog, 'Error setting GPIO : ' + str(address), 1, logconfig['iologlevel']) pilib.log(pilib.iolog, 'Exiting interface routine for ' + interface['id'], 0, logconfig['iologlevel']) return # Set the value of the gpio. # Get previous value if exists if interface['id'] in prevoutputids: value = prevoutputvalues[prevoutputids.index(interface['id'])] else: value = 0 if value == 1: if method == 'rpigpio': GPIO.output(address, True) elif method == 'pigpio': pi.write(address, 1) pilib.log(pilib.iolog, 'Setting output ON for GPIO address' + str(address), 3, logconfig['iologlevel']) else: if method == 'rpigpio': GPIO.output(address, False) elif method == 'pigpio': pi.write(address,0) pilib.log(pilib.iolog, 'Setting output OFF for GPIO address' + str(address), 3, logconfig['iologlevel']) # Get output settings and keep them if the GPIO previously existed if interface['id'] in prevoutputids: pollfreq = prevoutputs[prevoutputids.index(interface['id'])]['pollfreq'] ontime = prevoutputs[prevoutputids.index(interface['id'])]['ontime'] offtime = prevoutputs[prevoutputids.index(interface['id'])]['offtime'] else: try: pollfreq = defaults['defaultoutputpollfreq'] except: pollfreq = 60 ontime = '' offtime = '' # Add entry to outputs tables querylist.append('insert into outputs values (\'' + interface['id'] + '\',\'' + interface['interface'] + '\',\'' + interface['type'] + '\',\'' + str( address) + '\',\'' + gpioname + '\',\'' + str(value) + "','','" + str(polltime) + '\',\'' + str(pollfreq) + "','" + ontime + "','" + offtime + "')") elif options['mode'] == 'input': if method == 'rpigpio': GPIO.setup(address, GPIO.IN) elif method == 'pigpio': if 'pullupdown' in options: if options['pullupdown'] == 'pullup': pi.set_pull_up_down(address, pigpio.PUD_UP) elif options['pullupdown'] == 'pulldown': pi.set_pull_up_down(address, pigpio.PUD_DOWN) else: pi.set_pull_up_down(address, pigpio.PUD_OFF) else: pi.set_pull_up_down(17, pigpio.PUD_OFF) pi.set_mode(address, pigpio.INPUT) if method == 'rpigpio': value = GPIO.input(address) elif method == 'pigpio': value = pi.read(address) if 'function' in options: if options['function'] == 'shutdown': # TODO : The reboot function is still held in a shell script, because it works. if 'functionstate' in options: if value == 1 and options['functionstate'] in ['true', 'On', 'True', '1']: from systemstatus import processsystemflags processsystemflags() pilib.log(pilib.iolog, 'Setting input mode for GPIO address' + str(address), 3, logconfig['iologlevel']) # Get input settings and keep them if the GPIO previously existed if interface['id'] in previnputids: pollfreq = previnputs[previnputids.index(interface['id'])]['pollfreq'] ontime = previnputs[previnputids.index(interface['id'])]['ontime'] offtime = previnputs[previnputids.index(interface['id'])]['offtime'] pilib.log(pilib.iolog, 'Restoring values from previous inputids: pollfreq = ' + str( pollfreq) + ' ontime = ' + str(ontime) + ' offtime = ' + str( offtime), 3, logconfig['iologlevel']) else: try: pollfreq = defaults['defaultinputpollfreq'] except: pollfreq = 60 ontime = '' offtime = '' pilib.log(pilib.iolog, 'Setting values to defaults, defaultinputpollfreq = ' + str( pollfreq), 3, logconfig['iologlevel']) querylist.append( 'insert into inputs values (\'' + interface['id'] + '\',\'' + interface['interface'] + '\',\'' + interface['type'] + '\',\'' + str(address) + '\',\'' + gpioname + '\',\'' + str( value) + "','','" + str(polltime) + '\',\'' + str(pollfreq) + "','" + ontime + "','" + offtime + "')") if method == 'pigpio' and 'piobject' not in kwargs: pi.stop() return querylist
def runsystemstatus(runonce=False): import pilib import time import netconfig from misc.gitupdatelib import updategitversions # This doesn't update git libraries. It checks current versions and updates the database try: pilib.log(pilib.syslog, 'Checking git versions', 3, pilib.sysloglevel) updategitversions() except: pilib.log(pilib.syslog, 'Error in git version check', 0, pilib.sysloglevel) else: pilib.log(pilib.syslog, 'Git version check complete', 3, pilib.sysloglevel) systemstatus = pilib.readalldbrows(pilib.controldatabase, 'systemstatus')[0] ## Read wireless config via iwconfig # this is breaking systemstatus for some reason # updateiwstatus() ## Read current netstatus lastnetstatus={} try: lastnetstatus = pilib.readonedbrow(pilib.systemdatadatabase, 'netstatus')[0] except: pilib.log(pilib.networklog, 'Error reading network status. ', 1, pilib.networkloglevel) else: pilib.log(pilib.syslog, 'Completed network status. ', 3, pilib.networkloglevel) # Poll netstatus and return data allnetstatus = updatenetstatus(lastnetstatus) # wpastatusdict = allnetstatus['wpastatusdict'] # Keep reading system status? while systemstatus['systemstatusenabled']: currenttime = pilib.gettimestring() pilib.setsinglevalue(pilib.controldatabase, 'systemstatus', 'lastsystemstatuspoll', pilib.gettimestring()) starttime = time.time() pilib.log(pilib.syslog, 'System status routine is starting. ', 3, pilib.sysloglevel) """ Check all network statuses. The goal here is to totally decouple status read and reconfigure When we need to check all status data, we'll have it either in a dict or dict array, or in a database table """ if systemstatus['netstatusenabled']: pilib.log(pilib.syslog, 'Beginning network routines. ', 3, pilib.sysloglevel) # Update network interfaces statuses for all interfaces, in database tables as well # Check on wpa supplicant status as well. Function returns wpastatusdict try: pilib.log(pilib.syslog, 'Running updateifacestatus. ', 4, pilib.sysloglevel) pilib.log(pilib.networklog, 'Running updateifacestatus', 4, pilib.networkloglevel) allnetstatus = updatenetstatus(lastnetstatus) except: pilib.log(pilib.networklog, 'Exception in updateifacestatus. ') else: pilib.log(pilib.networklog, 'Updateifacestatus completed. ') pilib.log(pilib.syslog, 'Completed net status update. ', 4, pilib.sysloglevel) else: allnetstatus={'netstatusdict': {}, 'ifacesdictarray': {}} """ End network configuration status """ """ Do we want to autoconfig the network? If so, we analyze our netstatus data against what should be going on, and translate this into a network status """ if systemstatus['netconfigenabled'] and systemstatus['netstatusenabled']: # No need to get this fresh. We have it stored. netconfigdata = allnetstatus['netconfigdata'] # We are going to hack in a jumper that sets AP configuration. This isn't the worst thing ever. if netconfigdata['apoverride']: result = processapoverride(21) ''' Now we check network status depending on the configuration we have selected ''' ''' Now we check network status depending on the configuration we have selected ''' pilib.log(pilib.syslog, 'Running interface configuration watchdog. ', 4, pilib.sysloglevel) pilib.log(pilib.networklog, 'Running interface configuration. Mode: ' + netconfigdata['mode'], 4, pilib.networkloglevel) result = watchdognetstatus() else: pilib.log(pilib.syslog, 'Netconfig disabled. ', 1, pilib.sysloglevel) pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'mode', 'manual') pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'statusmsg', 'netconfig is disabled') if systemstatus['checkhamachistatus']: pilib.log(pilib.syslog, 'Hamachi watchdog is enabled', 3, pilib.sysloglevel) pilib.log(pilib.networklog, 'Hamachi watchdog is enabled. ', 3, pilib.networkloglevel) # Only watchdog haamchi if we are connected to the network. netstatus = pilib.readonedbrow(pilib.systemdatadatabase, 'netstatus')[0] if netstatus['WANaccess']: pilib.log(pilib.syslog, 'We appear to be online. Checking Hamachi Status. ', 3, pilib.sysloglevel) pilib.log(pilib.networklog, 'We appear to be online. Checking Hamachi Status. ', 3, pilib.networkloglevel) watchdoghamachi(pingip='25.37.18.7') else: pilib.log(pilib.syslog, 'We appear to be offline. Not checking Hamachi Status. ', 3, pilib.sysloglevel) pilib.log(pilib.networklog, 'We appear to be offline. Not checking Hamachi Status. ', 3, pilib.networkloglevel) else: pilib.log(pilib.syslog, 'Hamachi watchdog is disnabled', 3, pilib.sysloglevel) pilib.log(pilib.syslog, 'Finished interface configuration. ', 4, pilib.sysloglevel) # pilib.writedatedlogmsg(pilib.networklog, statusmsg) pilib.log(pilib.syslog, 'Running updateifacestatus. ', 4, pilib.sysloglevel) updatenetstatus() pilib.log(pilib.syslog, 'Completed updateifacestatus. ', 4, pilib.sysloglevel) pilib.log(pilib.syslog, 'Network routines complete. ', 3, pilib.sysloglevel) pilib.log(pilib.syslog, 'Checking system flags. ', 3, pilib.sysloglevel) processsystemflags() pilib.log(pilib.syslog, 'System flags complete. ', 3, pilib.sysloglevel) # Get system status again systemstatus = pilib.readalldbrows(pilib.controldatabase, 'systemstatus')[0] elapsedtime = int(time.time() - starttime) pilib.log(pilib.syslog, 'Status routines complete. Elapsed time: ' + str(elapsedtime), 3, pilib.sysloglevel) pilib.log(pilib.syslog, 'System status is sleeping for ' + str(systemstatus['systemstatusfreq']) + '. ', 3, pilib.sysloglevel) if runonce: break time.sleep(systemstatus['systemstatusfreq']) else: pilib.log(pilib.syslog, 'System status is disabled. Exiting. ', 0, pilib.sysloglevel)
def recordspidata(database, valuedict, execute=False): # This is incomplete and hardcoded partially querylist = [] for key, value in valuedict.iteritems(): querylist.append(pilib.makesqliteinsert('inputs', valuelist=[key, 'SPI1', 'TC', '1', 'SPITC1', value, 'F', pilib.gettimestring(), 1, '',''])) querylist.append(pilib.makesqliteinsert('ioinfo', valuelist=[key, key, ''])) if execute: pilib.sqlitemultquery(database, querylist) return querylist
updateioenabled = pilib.getsinglevalue(pilib.controldatabase, 'systemstatus', 'updateioenabled') while updateioenabled: #print("runtime") #print("reading input") # Read again, once inside each loop so we terminate if the # variable name is changed inputsreadenabled = pilib.sqlitedatumquery( pilib.controldatabase, 'select inputsreadenabled from systemstatus') # Set last run time pilib.sqlitequery( pilib.controldatabase, 'update systemstatus set lastinputspoll=\'' + pilib.gettimestring() + '\'') pilib.sqlitequery(pilib.controldatabase, 'update systemstatus set updateiostatus=\'1\'') # Read and record everything as specified in controldatabase # Update database of inputs with read data reply = updateio.updateiodata(pilib.controldatabase) result = pilib.readonedbrow(pilib.controldatabase, 'systemstatus', 0) systemsdict = result[0] #print("here is the systems dict") #print(systemsdict) readtime = systemsdict['updateiofreq'] plotpoints = 20
def runpicontrol(runonce=False): systemstatus = pilib.readalldbrows(pilib.controldatabase, 'systemstatus')[0] while systemstatus['picontrolenabled']: pilib.log(pilib.syslog, 'Running picontrol', 3, pilib.sysloglevel) pilib.log(pilib.controllog, 'Running picontrol', 3, pilib.controlloglevel) # Set poll date. While intuitively we might want to set this # after the poll is complete, if we error below, we will know # from this stamp when it barfed. This is arguably more valuable # then 'last time we didn't barf' pilib.sqlitequery(pilib.controldatabase, "update systemstatus set lastpicontrolpoll='" + pilib.gettimestring() + "'") channels = pilib.readalldbrows(pilib.controldatabase, 'channels') outputs = pilib.readalldbrows(pilib.controldatabase, 'outputs') controlalgorithms = pilib.readalldbrows(pilib.controldatabase, 'controlalgorithms') algorithmnames=[] for algorithm in controlalgorithms: algorithmnames.append(algorithm['name']) # Cycle through channels and set action based on setpoint # and algorithm if set to auto mode for channel in channels: statusmsg = '' querylist = [] channelindex = str(int(channel['channelindex'])) channelname = channel['name'] logtablename = 'channel' + '_' + channel['name'] + '_log' time = pilib.gettimestring() disableoutputs = True # Make sure channel is enabled if channel['enabled']: # Create log if it doesn't exist query = 'create table if not exists \'' + logtablename + '\' (time text, controlinput text, controlvalue real, setpointvalue real, action real, algorithm text, enabled real, statusmsg text)' pilib.sqlitequery(pilib.logdatabase, query) statusmsg = '' if 'setpointvalue' in channel: setpointvalue = float(channel['setpointvalue']) else: statusmsg += 'No setpoint. ' # Need to test for age of data. If stale or disconnected, invalidate if 'controlvalue' in channel: try: controlvalue = float(channel['controlvalue']) except (ValueError, TypeError) as e: statusmsg += 'Invalid control value. ' controllib.setcontrolvalue(pilib.controldatabase, channelname, 0) else: statusmsg += 'No controlvalue. ' # Test to see if key exists and is true if 'enabled' in channel: if channel['enabled']: pass else: statusmsg += 'Channel disabled. ' else: statusmsg += 'Error. Enabled key does not exist' mode = channel['mode'] channelalgorithmname = channel['controlalgorithm'] controlinput = channel['controlinput'] logpoints = channel['logpoints'] # Move forward if everything is defined for control if channel['enabled'] and 'controlvalue' in locals() and 'setpointvalue' in locals(): statusmsg += 'Channel Enabled. ' if mode == 'auto': statusmsg += 'Mode:Auto. ' #print('running auto sequence') # run algorithm on channel response = controllib.runalgorithm(pilib.controldatabase, pilib.recipedatabase, channelname) action = response[0] message = response[1] statusmsg += ' ' + response[1] + ' ' statusmsg += 'Action: ' + str(action) + '. ' # Set action in channel controllib.setaction(pilib.controldatabase, channelname, action) elif mode == 'manual': #print('manual mode') statusmsg += 'Mode:Manual. ' # action = controllib.getaction(pilib.controldatabase, channelname) else: #print('error, mode= ' + mode) statusmsg += 'Mode:Error. ' if systemstatus['enableoutputs']: statusmsg += 'System outputs enabled. ' if channel['outputsenabled']: statusmsg += 'Channel outputs enabled. ' disableoutputs = False # find out whether action is positive or negative or # not at all. # and act. for now, this is binary, but in the future # this will be a duty cycle daemon outputsetnames = [] outputresetnames = [] if action > 0: print("set positive output on") outputsetnames.append(channel['positiveoutput']) outputresetnames.append(channel['negativeoutput']) elif action < 0: print("set negative output on") outputsetnames.append(channel['negativeoutput']) outputresetnames.append(channel['positiveoutput']) elif action == 0: statusmsg += 'No action. ' outputresetnames.append(channel['positiveoutput']) outputresetnames.append(channel['negativeoutput']) else: statusmsg += 'Algorithm error. Doing nothing.' outputsetname = None # Check to see if outputs are ready to enable/disable # If not, pull them from list of set/reset outputstoset=[] for outputname in outputsetnames: if channelalgorithmname in algorithmnames: offtime = pilib.sqlitedatumquery(pilib.controldatabase, "select offtime from outputs where name='" + outputname + "'" ) if pilib.timestringtoseconds(pilib.gettimestring()) - pilib.timestringtoseconds(offtime) > controlalgorithms[algorithmnames.index(channelalgorithmname)]['minofftime']: outputstoset.append(outputname) else: statusmsg += 'Output ' + outputname + ' not ready to enable. ' else: statusmsg += 'Algorithm Error: Not found. ' outputstoreset=[] for outputname in outputresetnames: if channelalgorithmname in algorithmnames: ontime = pilib.sqlitedatumquery(pilib.controldatabase, "select ontime from outputs where name='" + outputname +"'") if pilib.timestringtoseconds(pilib.gettimestring()) - pilib.timestringtoseconds(ontime) > controlalgorithms[algorithmnames.index(channelalgorithmname)]['minontime']: outputstoreset.append(outputname) else: statusmsg += 'Output ' + outputname + ' not ready to disable. ' else: statusmsg += 'Algorithm Error: Not found. ' """ TODO: Change reference to controlinputs to name rather than id. Need to double-check enforcement of no duplicates.""" # Find output in list of outputs if we have one to set time = pilib.gettimestring() if len(outputstoset) > 0 or len(outputstoreset) > 0: for output in outputs: if output['name'] in outputstoset: # check current status currvalue = output['value'] if currvalue == 0: # No need to set if otherwise. Will be different for analog out # set ontime querylist.append('update outputs set ontime=\'' + time + '\' ' + 'where id=\'' + output['id'] + '\'') # set value querylist.append("update outputs set value = 1 where id='" + output['id'] + '\'') statusmsg += 'Output ' + output['name'] + ' enabled. ' else: statusmsg += 'Output ' + output['name'] + ' already enabled. ' if output['name'] in outputstoreset: # check current status currvalue = output['value'] if currvalue == 1: # No need to set if otherwise. Will be different for analog out # set ontime querylist.append('update outputs set offtime=\'' + time + '\' ' + 'where id=\'' + output['id'] + '\'') # set value querylist.append('update outputs set value = 0 where id=\'' + output['id'] + '\'') statusmsg += 'Output ' + output['name'] + ' disabled. ' else: statusmsg += 'Output ' + output['name'] + ' already disabled. ' else: statusmsg += 'Channel outputs disabled. ' action = 0 else: statusmsg += 'System outputs disabled. ' action = 0 # Insert entry into control log pilib.makesqliteinsert(pilib.logdatabase, logtablename, [time, controlinput, controlvalue, setpointvalue, action, channelalgorithmname, channel['enabled'], statusmsg]) pilib.sqliteinsertsingle(pilib.logdatabase, logtablename, [time, controlinput, controlvalue, setpointvalue, action, channelalgorithmname, channel['enabled'], statusmsg]) # Size log pilib.sizesqlitetable(pilib.logdatabase, logtablename, logpoints) # print(statusmsg) else: # print('channel not enabled') statusmsg += 'Channel not enabled. ' # If active reset and we didn't set channel modes, disable outputs # Active reset is not yet explicitly declared, but implied if disableoutputs: statusmsg += 'Disabling Outputs. ' for output in outputs: if output['name'] in [channel['positiveoutput'], channel['negativeoutput']]: # set value querylist.append("update outputs set value = 0 where id='" + output['id'] + '\'') statusmsg += 'Output ' + output['name'] + ' disabled. ' # Set status message for channel # print(statusmsg) querylist.append('update channels set statusmessage=\'' + statusmsg + '\'' + 'where channelindex=' + channelindex) # Set update time for channel querylist.append('update channels set controlupdatetime=\'' + time + '\'' + 'where channelindex=' + channelindex) # Execute query pilib.sqlitemultquery(pilib.controldatabase, querylist) # We do this system status again to refresh settings systemstatus = pilib.readalldbrows(pilib.controldatabase, 'systemstatus')[0] from actions import processactions processactions() # Wait for delay time #print('sleeping') # spilights.updatelightsfromdb(pilib.controldatabase, 'indicators') if runonce: break pilib.log(pilib.syslog, 'Picontrol Sleeping for ' + str(systemstatus['picontrolfreq']), 2, pilib.sysloglevel) pilib.log(pilib.controllog, 'Picontrol Sleeping for ' + str(systemstatus['picontrolfreq']), 2, pilib.sysloglevel) sleep(systemstatus['picontrolfreq']) pilib.log(pilib.syslog, 'picontrol not enabled. exiting.', 1, pilib.sysloglevel)
def processMBinterface(interface, prevoutputs, prevoutputids, previnputs, previnputids, defaults, logconfig): from netfun import readMBcodedaddresses, MBFCfromaddress import pilib # get all modbus reads that have the same address from the modbus table try: modbustable = pilib.readalldbrows(pilib.controldatabase, 'modbustcp') except: pilib.log(pilib.iolog, 'Error reading modbus table', 0, logconfig['iologlevel']) else: pilib.log(pilib.iolog, 'Read modbus table', 4, logconfig['iologlevel']) querylist = [] for entry in modbustable: # Get name from ioinfo table to give it a colloquial name # First we have to give it a unique ID. This is a bit difficult with modbus if entry['mode'] == 'read': shortmode = 'R' elif entry['mode'] == 'write': shortmode = 'W' elif entry['mode'] == 'readwrite': shortmode = 'RW' else: pilib.log(pilib.iolog, 'modbus mode error', 1, logconfig['iologlevel']) try: mbid = entry['interfaceid'] + '_' + str(entry['register']) + '_' + str(entry['length']) + '_' + shortmode except KeyError: pilib.log(pilib.iolog, 'Cannot form mbid due to key error', 0, logconfig['iologlevel']) return pilib.log(pilib.iolog, 'Modbus ID: ' + mbid, 4, logconfig['iologlevel']) mbname = pilib.sqlitedatumquery(pilib.controldatabase, "select name from ioinfo where id='" + mbid + "'") polltime = pilib.gettimestring() if entry['interfaceid'] == interface['id']: # For now, we're going to read them one by one. We'll assemble these into block reads # in the next iteration if entry['mode'] == 'read': # Get previous metadata and data # Get input settings and keep them if the input previously existed if mbid in previnputids: pollfreq = previnputs[previnputids.index(mbid)]['pollfreq'] ontime = previnputs[previnputids.index(mbid)]['ontime'] offtime = previnputs[previnputids.index(mbid)]['offtime'] prevvalue = previnputs[previnputids.index(mbid)]['offtime'] prevpolltime = previnputs[previnputids.index(mbid)]['offtime'] pilib.log(pilib.iolog, 'Restoring values from previous inputids: pollfreq = ' + str( pollfreq) + ' ontime = ' + str(ontime) + ' offtime = ' + str( offtime), 3, logconfig['iologlevel']) else: # set values to defaults if it did not previously exist try: pollfreq = defaults['defaultinputpollfreq'] except: pollfreq = 60 ontime = '' offtime = '' prevvalue = '' prevpolltime = '' pilib.log(pilib.iolog, 'Setting values to defaults, defaultinputpollfreq = ' + str(pollfreq), 3, logconfig['iologlevel']) # Read data try: readresult = readMBcodedaddresses(interface['address'], entry['register'], entry['length']) except: pilib.log(pilib.iolog, 'Uncaught reror reading modbus value', 0, logconfig['iologlevel']) else: if readresult['statuscode'] == 0: values = readresult['values'] try: FC = MBFCfromaddress(int(entry['register'])) except ValueError: pilib.log(pilib.iolog, 'Malformed address for FC determination : ' + str(entry['address']), 0, logconfig['iologlevel']) else: pilib.log(pilib.iolog, 'Function code : ' + str(FC), 4, logconfig['iologlevel']) returnvalue = 0 if len(values) > 0: pilib.log(pilib.iolog, 'Multiple values returned', 4, logconfig['iologlevel']) if not entry['bigendian']: try: values.reverse() except AttributeError: pilib.log(pilib.iolog, 'Error on reverse of MB values: ' + str(values), 0, logconfig['iologlevel']) if entry['format'] == 'float32': import struct byte2 = values[0] % 256 byte1 = (values[0] - byte2)/256 byte4 = values[1] % 256 byte3 = (values[1] - byte4)/256 byte1hex = chr(byte1) byte2hex = chr(byte2) byte3hex = chr(byte3) byte4hex = chr(byte4) hexstring = byte1hex + byte2hex + byte3hex + byte4hex returnvalue = struct.unpack('>f',hexstring)[0] else: for index, val in enumerate(values): if FC in [0, 1]: returnvalue += val * 2 ** index elif FC in [3, 4]: returnvalue += val * 256 ** index else: pilib.log(pilib.iolog, 'Invalid function code', 0, logconfig['iologlevel']) else: returnvalue = values[0] if entry['options'] != '': options = pilib.parseoptions(entry['options']) if 'scale' in options: # try: returnvalue = returnvalue * float(options['scale']) # except: # pilib.writedatedlogmsg(pilib.iolog, 'Error on scale operation', 0, logconfig['iologlevel']) if 'precision' in options: # try: returnvalue = round(returnvalue, int(options['precision'])) # except: # pilib.writedatedlogmsg(pilib.iolog, 'Error on precision operation', 0, logconfig['iologlevel']) pilib.log(pilib.iolog, 'Values read: ' + str(values), 4, logconfig['iologlevel']) pilib.log(pilib.iolog, 'Value returned: ' + str(returnvalue), 4, logconfig['iologlevel']) # Contruct entry for newly acquired data querylist.append('insert into inputs values (\'' + mbid + '\',\'' + interface['id'] + '\',\'' + interface['type'] + '\',\'' + str(entry['register']) + '\',\'' + mbname + '\',\'' + str( returnvalue) + "','','" + str(polltime) + '\',\'' + str(pollfreq) + "','" + ontime + "','" + offtime + "')") else: pilib.log(pilib.iolog, 'Statuscode ' + str(readresult['statuscode']) + ' on MB read : ' + readresult['message'] , 0, logconfig['iologlevel']) # restore previous value and construct entry if it existed (or not) querylist.append('insert into inputs values (\'' + mbid + '\',\'' + interface['interface'] + '\',\'' + interface['type'] + '\',\'' + str(entry['register']) + '\',\'' + mbname + '\',\'' + str(prevvalue) + "','','" + str(prevpolltime) + '\',\'' + str(pollfreq) + "','" + ontime + "','" + offtime + "')") pilib.log(pilib.iolog, 'Querylist: ' + str(querylist) , 4, logconfig['iologlevel']) return querylist
# Set physical outputs (this is done by updateio) systemstatus = pilib.readalldbrows(pilib.controldatabase, 'systemstatus')[0] while systemstatus['picontrolenabled']: pilib.writedatedlogmsg(pilib.systemstatuslog, 'Running picontrol', 3, pilib.systemstatusloglevel) pilib.writedatedlogmsg(pilib.controllog, 'Running picontrol', 3, pilib.controlloglevel) # Set poll date. While intuitively we might want to set this # after the poll is complete, if we error below, we will know # from this stamp when it barfed. This is arguably more valuable # then 'last time we didn't barf' pilib.sqlitequery(pilib.controldatabase, "update systemstatus set lastpicontrolpoll='" + pilib.gettimestring() + "'") channels = pilib.readalldbrows(pilib.controldatabase, 'channels') outputs = pilib.readalldbrows(pilib.controldatabase, 'outputs') controlalgorithms = pilib.readalldbrows(pilib.controldatabase, 'controlalgorithms') algorithmnames=[] for algorithm in controlalgorithms: algorithmnames.append(algorithm['name']) # Cycle through channels and set action based on setpoint # and algorithm if set to auto mode for channel in channels: statusmsg = '' querylist = [] channelindex = str(int(channel['channelindex']))
import pilib import updateio from time import sleep readtime = 10 # default, seconds # Read from systemstatus to make sure we should be running updateioenabled = pilib.getsinglevalue(pilib.controldatabase, 'systemstatus', 'updateioenabled') while updateioenabled: pilib.log(pilib.iolog, 'Running periodicupdateio', 3, pilib.iologlevel) pilib.log(pilib.syslog, 'Running periodicupdateio', 3, pilib.sysloglevel) # Set last run time pilib.setsinglevalue(pilib.controldatabase, 'systemstatus', 'lastinputpoll', pilib.gettimestring()) pilib.setsinglevalue(pilib.controldatabase, 'systemstatus', 'updateiostatus', '1') # Read and record everything as specified in controldatabase # Update database of inputs with read data # DEBUG runupdate = True if runupdate: reply = updateio.updateiodata(pilib.controldatabase) else: pilib.log(pilib.iolog,'DEBUG: Update IO disabled', 1, pilib.iologlevel) pilib.log(pilib.syslog,'DEBUG: Update IO disabled', 1, pilib.sysloglevel) result = pilib.readonedbrow(pilib.controldatabase, 'systemstatus', 0)
# Write to database # At the moment all are enabled by default. # Eventually we'll read this before we delete all entries for tuple in ROMsandtemps: ROM = tuple[0] temp = tuple[1] queryresult = pilib.sqlitequery( database, 'select name from sensorinfo where sensorID = ' + "'" + ROM + "'") if not queryresult: name = '' else: name = queryresult[0][0] valuelist = [tuple[0], tuple[1], 'F', pilib.gettimestring(), 1, name] query = pilib.makesqliteinsert('sensordata', valuelist) # print(query) querylist.append(query) # execute combined query #print(querylist) ######################################## # Do thermocouple stuff import subprocess tctemp = subprocess.check_output( ['python3', '/usr/lib/modwsgi/max31855-1.0/getmaxtemp.py']) print('temperature is ')
readtime = 10 # default, seconds # Read from systemstatus to make sure we should be running inputsreadenabled = pilib.sqlitedatumquery(pilib.controldatabase, 'select inputsreadenabled from systemstatus') while inputsreadenabled: #print("runtime") #print("reading input") # Read again, once inside each loop so we terminate if the # variable name is changed inputsreadenabled = pilib.sqlitedatumquery(pilib.controldatabase, 'select inputsreadenabled from systemstatus') # Set last run time pilib.sqlitequery(pilib.controldatabase, 'update systemstatus set lastinputspoll=\'' + pilib.gettimestring() + '\'') pilib.sqlitequery(pilib.controldatabase, 'update systemstatus set inputsreadstatus=\'1\'') # Read and record everything as specified in controldatabase # Update database of inputs with read data reply = updateio.updateiodata(pilib.controldatabase) result = pilib.readonedbrow(pilib.controldatabase, 'systemstatus', 0) systemsdict = result[0] #print("here is the systems dict") #print(systemsdict) readtime = systemsdict['inputsreadfreq'] plotpoints = 20 logpoints = 100
def runalgorithm(controldatabase, recipedatabase, channelname): from pilib import sqlitequery, datarowtodict, gettimestring, timestringtoseconds import time message = '' # get our details of our channel channeldata = sqlitequery( controldatabase, 'select * from channels where name=' + "'" + channelname + "'")[0] channeldict = datarowtodict(controldatabase, 'channels', channeldata) # check to see if we are running a recipe controlrecipename = channeldict['controlrecipe'] if controlrecipename and controlrecipename != 'none': # Get recipe details # If recipes get too big, we'll just get # a couple stages. For now, we make a # dictionary array #print('we are in recipe ' + controlrecipename) #print(recipedatabase) recipedata = sqlitequery(recipedatabase, 'select * from \'' + controlrecipename + '\'') recipedictarray = [] for stage in recipedata: recipedict = datarowtodict(recipedatabase, controlrecipename, stage) recipedictarray.append(recipedict) # get current stage currentstagenumber = int(channeldict['recipestage']) #print('current stage is ' + str(currentstagenumber) ) # Get data for current stage stagefound = False for stage in recipedictarray: if int(stage['stagenumber']) == currentstagenumber: currentstage = stage stagefound = True break if stagefound: #print("stage found") pass else: print('error. stage not found.') # Check to see if we need to move to next stage currenttime = time.time() #print('Time') #print(currenttime) #print(gettimestring(currenttime)) if currentstagenumber == 0 or currenttime - timestringtoseconds( channeldict['recipestagestarttime']) > int( currentstage['stagelength']): print('stage time expired for stage ' + str(currentstagenumber) + '. Checking on stage advance. ') # Advance stage if there is another stage. Otherwise # update channel to be off a recipe. We assume explicitly # that the stages are sequential integers. nextstagenumber = currentstagenumber + 1 # look for next stage stagefound = False for stage in recipedictarray: if int(stage['stagenumber']) == nextstagenumber: nextstage = stage stagefound = True break if stagefound: print(' Next stage was found. Setting next stage. ') if currentstagenumber == 0: print("Stagenumber is 0. Setting recipe start time. ") # Set recipe start time sqlitequery( controldatabase, 'update channels set recipestarttime=\'' + gettimestring(currenttime) + '\' where name=\'' + channelname + '\'') # Set stage to new stage number sqlitequery( controldatabase, 'update channels set recipestage=\'' + str(nextstagenumber) + '\' where name=\'' + channelname + '\'') # Set setpointvalue sqlitequery( controldatabase, 'update channels set setpointvalue=\'' + str(nextstage['setpointvalue']) + '\' where name=\'' + channelname + '\'') # Set stage start time to now sqlitequery( controldatabase, 'update channels set recipestagestarttime=\'' + gettimestring(currenttime) + '\' where name=\'' + channelname + '\'') # Set new controlalgorithm sqlitequery( controldatabase, 'update channels set controlalgorithm=\'' + nextstage['controlalgorithm'] + '\' where name=\'' + channelname + '\'') else: # Take channel off recipe sqlitequery( controldatabase, 'update channels set controlrecipe=\'none\' where name=\'' + channelname + '\'') sqlitequery( controldatabase, 'update channels set recipestate=\'0\' where name=\'' + channelname + '\'') sqlitequery( controldatabase, 'update channels set recipestage=\'0\' where name=\'' + channelname + '\'') # if lengthmode is setpoint # get current stage # check stage start against stage length # and current time # move to next stage if time and revise setpoint # adjust setpoint based on stage # set action based on setpoint else: # make sure we're not on recipe and on stage 0 sqlitequery( controldatabase, 'update channels set controlrecipe=\'none\' where name=\'' + channelname + '\'') sqlitequery( controldatabase, 'update channels set recipestate=\'0\' where name=\'' + channelname + '\'') sqlitequery( controldatabase, 'update channels set recipestage=\'0\' where name=\'' + channelname + '\'') algorithm = channeldict['controlalgorithm'] setpointvalue = float(channeldict['setpointvalue']) controlvalue = float(channeldict['controlvalue']) algorithmrows = sqlitequery( controldatabase, 'select * from controlalgorithms where name=' + "'" + algorithm + "'") algorithmrow = algorithmrows[0] algorithm = datarowtodict(controldatabase, 'controlalgorithms', algorithmrow) type = algorithm['type'] if type == 'on/off with deadband': #print(type) deadbandhigh = algorithm['deadbandhigh'] deadbandlow = algorithm['deadbandlow'] if setpointvalue > (controlvalue + deadbandhigh): action = 100 elif setpointvalue < (controlvalue - deadbandlow): action = -100 else: action = 0 #print('setpoint' + str(setpoint)) #print('controlvalue' + str(controlvalue)) #print(action) #print(message) return [action, message]
while systemstatus['picontrolenabled']: pilib.writedatedlogmsg(pilib.systemstatuslog, 'Running picontrol', 3, pilib.systemstatusloglevel) pilib.writedatedlogmsg(pilib.controllog, 'Running picontrol', 3, pilib.controlloglevel) # Set poll date. While intuitively we might want to set this # after the poll is complete, if we error below, we will know # from this stamp when it barfed. This is arguably more valuable # then 'last time we didn't barf' pilib.sqlitequery( pilib.controldatabase, "update systemstatus set lastpicontrolpoll='" + pilib.gettimestring() + "'") channels = pilib.readalldbrows(pilib.controldatabase, 'channels') outputs = pilib.readalldbrows(pilib.controldatabase, 'outputs') controlalgorithms = pilib.readalldbrows(pilib.controldatabase, 'controlalgorithms') algorithmnames = [] for algorithm in controlalgorithms: algorithmnames.append(algorithm['name']) # Cycle through channels and set action based on setpoint # and algorithm if set to auto mode for channel in channels: statusmsg = '' querylist = []
def updateowfsdevices(busdevices, myProxy=None): import pilib # get defaults defaults = pilib.readalldbrows(pilib.controldatabase, 'defaults')[0] # get current entries previnputs = pilib.readalldbrows(pilib.controldatabase, 'inputs') # Make list of IDs for easy indexing previnputids = [] for input in previnputs: previnputids.append(input['id']) # Iterate over devices. Determine if values exist for polltime, frequency. # If so, update the device. If not, use defaults. # Then determine whether we should update value or not (Read temperature) for index, device in enumerate(busdevices): if device.sensorid in previnputids: try: newpollfreq = int(previnputs[previnputids.index( device.sensorid)]['pollfreq']) except ValueError: device.pollfreq = defaults['inputpollfreq'] else: if newpollfreq >= 0: device.pollfreq = previnputs[previnputids.index( device.sensorid)]['pollfreq'] else: device.pollfreq = defaults['inputpollfreq'] device.ontime = previnputs[previnputids.index( device.sensorid)]['ontime'] device.offtime = previnputs[previnputids.index( device.sensorid)]['offtime'] device.polltime = previnputs[previnputids.index( device.sensorid)]['polltime'] device.value = previnputs[previnputids.index( device.sensorid)]['value'] else: device.pollfreq = defaults['inputpollfreq'] device.ontime = '' device.offtime = '' device.polltime = '' device.value = '' # We're going to set a name because calling things by their ids is getting # a bit ridiculous, but we can't have empty name fields if we rely on them # being there. They need to be unique, so we'll name them by type and increment them if device.type == 'DS18B20': # Get name if one exists name = pilib.sqlitedatumquery( pilib.controldatabase, 'select name from ioinfo where id=\'' + device.sensorid + '\'') # If doesn't exist, check to see if proposed name exists. If it doesn't, add it. # If it does, keep trying. if name == '': for rangeindex in range(100): # check to see if name exists name = device.type + '-' + str(int(index + 1)) # print(name) foundid = pilib.sqlitedatumquery( pilib.controldatabase, 'select id from ioinfo where name=\'' + name + '\'') # print('foundid' + foundid) if foundid: pass else: pilib.sqlitequery( pilib.controldatabase, pilib.makesqliteinsert( 'ioinfo', valuelist=[device.sensorid, name], valuenames=['id', 'name'])) break device.name = name # Is it time to read temperature? if pilib.timestringtoseconds( pilib.gettimestring()) - pilib.timestringtoseconds( device.polltime) > device.pollfreq: device.readprop('temperature', myProxy) device.polltime = pilib.gettimestring() device.value = device.temperature else: pass # print('not time to poll') device.unit = 'F' # We update the device and send them back for other purposes. busdevices[index] = device return busdevices
def processactions(): # Read database to get our actions actiondicts = pilib.readalldbrows(pilib.controldatabase, 'actions') for actiondict in actiondicts: alert = False thisaction = pilib.action(actiondict) thisaction.statusmsg = '' # print(actiondict) # process condition if thisaction.conditiontype == 'dbvalue': if thisaction.enabled: thisaction.statusmsg += 'Action enabled.' dbdir = getattr(pilib, 'databasedir') # print(dbdir) dbpath = dbdir + thisaction.database + '.db' # variablename is columnname for dbvalue conditiontype thisaction.variablevalue = pilib.getsinglevalue( dbpath, thisaction.tablename, thisaction.variablename, 'rowid=' + str(thisaction.channelindex)) # get variable type to handle variablestypedict = pilib.getpragmanametypedict( pilib.controldatabase, thisaction.tablename) vartype = variablestypedict[thisaction.variablename] thisaction.statusmsg += ' Variablevalue: ' + str( thisaction.variablevalue) + '. Criterion: ' + str( thisaction.criterion) + ' . ' # process criterion according to type curstatus = False if vartype == 'boolean': thisaction.statusmsg += ' Processing boolean. ' if thisaction.variablevalue == thisaction.criterion: curstatus = True elif vartype == 'integer' or vartype == 'real': thisaction.statusmsg += ' Processing integer/real. ' # print(thisaction.operator) thisaction.variablevalue = float(thisaction.variablevalue) thisaction.criterion = float(thisaction.criterion) if thisaction.operator == '>': if thisaction.variablevalue > thisaction.criterion: curstatus = True elif thisaction.operator == '>=': if thisaction.variablevalue >= thisaction.criterion: curstatus = True elif thisaction.operator == '<': if thisaction.variablevalue < thisaction.criterion: curstatus = True elif thisaction.operator == '<=': if thisaction.variablevalue <= thisaction.criterion: curstatus = True elif thisaction.operator == '=': if thisaction.variablevalue == thisaction.criterion: curstatus = True else: thisaction.statusmsg += 'Operator error. ' if thisaction.variablevalue == thisaction.criterion: curstatus = True elif vartype == 'text': thisaction.statusmsg += ' Processing text. ' if thisaction.variablevalue == thisaction.criterion: curstatus = True else: thisaction.statusmsg += ' Mode Error for vartype ' + vartype + '. ' if curstatus: thisaction.statusmsg += 'Status is true. ' else: thisaction.statusmsg += 'Status is not true. ' currenttime = pilib.gettimestring() # if status is true and current status is false, set ontime if curstatus and not thisaction.status: # print(str(curstatus) + ' ' + str(thisaction.status)) thisaction.statusmsg += 'Setting status ontime. ' thisaction.ontime = pilib.gettimestring() thisaction.status = 1 elif not curstatus and thisaction.status: thisaction.statusmsg += 'Setting status offtime. ' thisaction.offtime = pilib.gettimestring() thisaction.status = 0 # Set current status if curstatus: thisaction.status = 1 # print('settings status') else: thisaction.status = 0 # print('resetting status') # if status is true and alarm isn't yet active, see if ondelay exceeded if curstatus and not thisaction.active: # print(pilib.timestringtoseconds(currenttime)) statusontime = pilib.timestringtoseconds( currenttime) - pilib.timestringtoseconds( thisaction.ontime) # print(statusontime) if statusontime > thisaction.ondelay: thisaction.statusmsg += 'Setting action active' thisaction.active = 1 else: thisaction.statusmsg += 'On delay not reached' # if status is not true and alarm is active, see if offdelay exceeded if not curstatus and thisaction.active: statusofftime = pilib.timestringtoseconds( currenttime) - pilib.timestringtoseconds( thisaction.offtime) if statusofftime > thisaction.offdelay: thisaction.statusmsg += 'Setting action inactive' thisaction.active = 0 # Send an alert / reset indicator if activereset is on if thisaction.activereset: thisaction.offact() else: thisaction.statusmsg += 'Off delay not reached' # test to see if it is time to alert, based on delay ond alert time if thisaction.active: # check to see if it is time to alert # print(pilib.timestringtoseconds(currenttime)) # print(pilib.timestringtoseconds(thisaction.lastactiontime)) # print(float(thisaction.actionfrequency)) # print(pilib.timestringtoseconds(currenttime)-pilib.timestringtoseconds(thisaction.lastactiontime)) if pilib.timestringtoseconds( currenttime) - pilib.timestringtoseconds( thisaction.lastactiontime) > float( thisaction.actionfrequency): alert = True thisaction.statusmsg += "Time to act. " else: alert = False thisaction.statusmsg += "Not yet time to act." if alert: # We're ready to alert or alert again. thisaction.lastactiontime = currenttime if curstatus: thisaction.onact() else: thisaction.offact() else: thisaction.statusmsg += 'Action disabled.' thisaction.status = 0 else: thisaction.statusmsg += 'Mode unrecognized.' print(thisaction.statusmsg) thisaction.publish()
# Now do some sleuthing if we are being stringent about WAN access. Have to be careful about this if we are on a # private network if netconfigdata['requireWANaccess']: pilib.log(pilib.networklog, 'Requiring WAN access. Checking status and times. ', 3, pilib.networkloglevel) print('NETSTATUS') print(netstatus) if not netstatus['WANaccess']: pilib.log(pilib.networklog, 'No WANaccess. Checking offline time. ', 2, pilib.networkloglevel) try: offlinetime = netstatus['offlinetime'] except: print('netstatus ERROR') pilib.log(pilib.networklog, 'Error gettng offlinetime. ', 2, pilib.networkloglevel) offlineperiod = pilib.timestringtoseconds(pilib.gettimestring()) - pilib.timestringtoseconds(offlinetime) pilib.log(pilib.networklog, 'We have been offline for ' + str(offlineperiod)) if offlineperiod > int(netconfigdata['WANretrytime']): pilib.log(pilib.networklog, 'Offline period of ' + str(offlineperiod) + ' has exceeded retry time of ' + str(int(netconfigdata['WANretrytime']))) # Note that although we obey this period once, after we start this process we don't reset the offlinetime, # so it will just continue to run. This is good in a way, as it will continually set the netstateok to bad, # which will eventually cause us to reboot # We do reset the WAN offline time in the reboot sequence, hwoever. restarts = int(pilib.getsinglevalue(pilib.systemdatadatabase, 'netstatus','WANaccessrestarts')) restarts += 1 pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'WANaccessrestarts', restarts) pilib.log(pilib.networklog, 'Going to run netconfig to correct WAN access.') else:
thisaction.statusmsg += 'Operator error. ' if thisaction.variablevalue == thisaction.criterion: curstatus = True elif vartype == 'text': thisaction.statusmsg += ' Processing text. ' if thisaction.variablevalue == thisaction.criterion: curstatus = True else: thisaction.statusmsg += ' Mode Error for vartype ' + vartype + '. ' if curstatus: thisaction.statusmsg += 'Status is true. ' else: thisaction.statusmsg += 'Status is not true. ' currenttime = pilib.gettimestring() # if status is true and current status is false, set ontime if curstatus and not thisaction.status: thisaction.statusmsg += 'Setting status ontime. ' thisaction.ontime = pilib.gettimestring() thisaction.status = 1 elif not curstatus and thisaction.status: thisaction.statusmsg += 'Setting status offtime. ' thisaction.ontime = pilib.gettimestring() thisaction.status = 0 # if status is true and alarm isn't yet active, see if ondelay exceeded if curstatus and not thisaction.active: print(pilib.timestringtoseconds(currenttime)) statusontime = pilib.timestringtoseconds(currenttime) - pilib.timestringtoseconds(thisaction.ontime)
def updateowfsentries(database, tablename, busdevices, myProxy=None): import pilib querylist = [] querylist.append('delete from ' + tablename + ' where interface = \'i2c1wire\'') # We're going to set a name because calling things by their ids is getting # a bit ridiculous, but we can't have empty name fields if we rely on them # being there. They need to be unique, so we'll name them by type and increment them for device in busdevices: # print(device.id) if device.type == 'DS18B20': sensorid = 'i2c1wire' + '_' + device.address # Get name if one exists name = pilib.sqlitedatumquery(database, 'select name from ioinfo where id=\'' + sensorid + '\'') # If doesn't exist, check to see if proposed name exists. If it doesn't, add it. # If it does, keep trying. if name == '': for index in range(100): # check to see if name exists name = device.type + '-' + str(int(index + 1)) print(name) foundid = pilib.sqlitedatumquery(database, 'select id from ioinfo where name=\'' + name + '\'') print('foundid' + foundid) if foundid: pass else: pilib.sqlitequery(database, pilib.makesqliteinsert('ioinfo', valuelist=[sensorid, name], valuenames=['id', 'name'])) break # Is it time to read temperature? # At the moment, we assume yes. device.readprop('temperature', myProxy) # print('temperature:') # print(device.temperature) querylist.append(pilib.makesqliteinsert(tablename, [sensorid, 'i2c1wire', device.type, device.address, name, float(device.temperature), 'F', pilib.gettimestring(), ''])) # print(querylist) pilib.sqlitemultquery(database, querylist)