def checklivesessions(authdb, user, expiry): import pilib import time activesessions = 0 sessions = pilib.readalldbrows(authdb, 'sessions') for session in sessions: sessioncreation = pilib.timestringtoseconds(session['timecreated']) currenttime = time.mktime(time.localtime()) if currenttime - sessioncreation < expiry: activesessions += 1 return activesessions
def checkifdisableready(outputname, outputs): from time import time from pilib import timestringtoseconds # Find the variables we want for output in outputs: if output['name'] == outputname: minontime = output['minontime'] ontime = timestringtoseconds(output['ontime']) if time() - ontime > minontime: return True else: return False
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()
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]
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)
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,
# 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:
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
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) 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:
wpastatusmsg = '' # Do we want to autoconfig the network? # TODO: Better split netconfig up into reporting and configuration if systemstatus['netconfigenabled']: pilib.writedatedlogmsg(pilib.systemstatuslog, 'Running interface configuration. ', 4, pilib.systemstatusloglevel) # If mode is ap or tempap if netconfigdata['mode'] in ['ap', 'tempap']: pilib.writedatedlogmsg(pilib.networklog, 'AP Mode is set. ', 1, pilib.networkloglevel) timesincelastretry = pilib.timestringtoseconds( currenttime) - pilib.timestringtoseconds( netconfigdata['laststationretry']) pilib.writedatedlogmsg( pilib.networklog, 'Time since last retry: ' + str(timesincelastretry), 1, pilib.networkloglevel) # If it's time to go back to station mode, we don't care whether we are connected as ap or not # We use dhcp status as indicator of ap status. Imperfect, but functional. if netconfigdata[ 'mode'] == 'tempap' and timesincelastretry > netconfigdata[ 'stationretrytime']: # We go back to station mode wpastatusmsg += 'Time to go back to station mode. ' pilib.setsinglevalue(pilib.systemdatadatabase, 'netconfig', 'mode', 'station')
netconfigdata = pilib.readonedbrow(pilib.systemdatadatabase, 'netconfig')[0] netstatus = pilib.readonedbrow(pilib.systemdatadatabase, 'netstatus')[0] wpastatusmsg = '' # Do we want to autoconfig the network? # TODO: Better split netconfig up into reporting and configuration if systemstatus['netconfigenabled']: pilib.writedatedlogmsg(pilib.systemstatuslog, 'Running interface configuration. ', 4, pilib.systemstatusloglevel) # If mode is ap or tempap if netconfigdata['mode'] in ['ap', 'tempap']: pilib.writedatedlogmsg(pilib.networklog, 'AP Mode is set. ', 1, pilib.networkloglevel) timesincelastretry = pilib.timestringtoseconds(currenttime) - pilib.timestringtoseconds(netconfigdata['laststationretry']) pilib.writedatedlogmsg(pilib.networklog, 'Time since last retry: ' + str(timesincelastretry), 1, pilib.networkloglevel) # If it's time to go back to station mode, we don't care whether we are connected as ap or not # We use dhcp status as indicator of ap status. Imperfect, but functional. if netconfigdata['mode'] == 'tempap' and timesincelastretry > netconfigdata['stationretrytime']: # We go back to station mode wpastatusmsg += 'Time to go back to station mode. ' pilib.setsinglevalue(pilib.systemdatadatabase, 'netconfig', 'mode', 'station') pilib.setsinglevalue(pilib.systemdatadatabase, 'netconfig', 'laststationretry', '') netconfig.runconfig() else: # If we have ap up, do nothing if wpastatusdict['dhcpstatus']: wpastatusmsg += 'AP checked and ok. ' pilib.setsinglevalue(pilib.systemdatadatabase, 'netstatus', 'mode', 'ap')
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]
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 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
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:
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.'
import time # Determine whether this process is enabled: enabled = pilib.sqlitedatumquery(pilib.controldatabase, 'select sessioncontrolenabled from \'systemstatus\'') while enabled: #print('enabled') polltime = pilib.sqlitedatumquery(pilib.sessiondatabase, 'select updatefrequency from \'settings\'') # Go through sessions and delete expired ones sessions = pilib.readalldbrows(pilib.sessiondatabase, 'sessions') sessions = pilib.readalldbrows(pilib.sessiondatabase, 'sessions') arrayquery = [] for session in sessions: sessionstart = pilib.timestringtoseconds(session['timecreated']) sessionlength = session['sessionlength'] if time.time() - sessionstart > sessionlength: arrayquery.append('delete from sessions where sessionid=\'' + session['sessionid'] + '\'') # Delete offensive sessions pilib.sqlitemultquery(pilib.sessiondatabase, arrayquery) # Reload surviving sessions and summarize sessions = pilib.readalldbrows(pilib.sessiondatabase, 'sessions') sessiondictarray = [] for session in sessions: found = 0 for dict in sessiondictarray: if dict['username'] == session['username']: found = 1
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
enabled = pilib.sqlitedatumquery( pilib.controldatabase, 'select sessioncontrolenabled from \'systemstatus\'') while enabled: #print('enabled') polltime = pilib.sqlitedatumquery( pilib.sessiondatabase, 'select updatefrequency from \'settings\'') # Go through sessions and delete expired ones sessions = pilib.readalldbrows(pilib.sessiondatabase, 'sessions') sessions = pilib.readalldbrows(pilib.sessiondatabase, 'sessions') arrayquery = [] for session in sessions: sessionstart = pilib.timestringtoseconds(session['timecreated']) sessionlength = session['sessionlength'] if time.time() - sessionstart > sessionlength: arrayquery.append('delete from sessions where sessionid=\'' + session['sessionid'] + '\'') # Delete offensive sessions pilib.sqlitemultquery(pilib.sessiondatabase, arrayquery) # Reload surviving sessions and summarize sessions = pilib.readalldbrows(pilib.sessiondatabase, 'sessions') sessiondictarray = [] for session in sessions: found = 0 for dict in sessiondictarray: if dict['username'] == session['username']: