Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
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()
Exemple #5
0
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]
Exemple #6
0
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)
Exemple #7
0
                        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:
Exemple #11
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')
Exemple #12
0
        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')
Exemple #13
0
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()
Exemple #15
0
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
Exemple #16
0
                        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:
Exemple #17
0
    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
Exemple #19
0
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
Exemple #20
0
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']: