Ejemplo n.º 1
0
def readhardwarefileintoversions():

    from iiutilities import utility
    from cupid import pilib
    from iiutilities import dblib

    devicefile = '/var/wwwsafe/devicedata'
    try:
        file = open(devicefile)
        lines = file.readlines()
        devicedict = {}
        for line in lines:
            split = line.split(':')
            try:
                devicedict[split[0].strip()] = split[1].strip()
            except:
                utility.log(pilib.dirs.logs.system, 'Device data parse error',
                            1, pilib.loglevels.system)
        dblib.sqlitequery(
            pilib.dirs.dbs.system,
            dblib.makesqliteinsert('versions',
                                   ['hardware', devicedict['hardware']],
                                   ['item', 'version']))
    except:
        utility.log(pilib.dirs.logs.system,
                    'Error opening devicedata file to parse', 1,
                    pilib.loglevels.system)
Ejemplo n.º 2
0
def process_notifications_queue():
    from iiutilities import dblib
    from iiutilities.utility import log

    notifications_db = cupidDatabase(dirs.dbs.notifications)
    queuednotifications = notifications_db.read_table('queued')

    for notification in queuednotifications:
        if loglevels.notifications >= 5:
            log(dirs.logs.notifications, 'Processing notification of type' + notification['type'] + '. Message: ' + notification['message'] + '. Options: ' + notification['options'])
        else:
            log(dirs.logs.notifications, 'Processing notification of type' + notification['type'])

        result = processnotification(notification)

        if result['status'] == 0:
            log(dirs.logs.notifications, 'Notification appears to have been successful. Copying message to sent.')
            sententry = notification.copy()
            sententry['senttime'] = result['senttime']
            dblib.insertstringdicttablelist(dirs.dbs.notifications, 'sent', [sententry], droptable=False)

            log(dirs.logs.notifications, 'Removing entry from queued messages.')

            # match by time and message
            conditionnames = ['queuedtime', 'message']
            conditionvalues = [sententry['queuedtime'], sententry['message']]

            notifications_db.delete('queued', {'conditionnames':conditionnames, 'conditionvalues':conditionvalues})

            # delquery = dblib.makedeletesinglevaluequery('queuednotifications', {'conditionnames':conditionnames, 'conditionvalues':conditionvalues})
            # dblib.sqlitequery(dirs.dbs.notifications, delquery)

        else:
            log(dirs.logs.notifications, 'Notification appears to have failed. Status: ' + str(result['status']))
Ejemplo n.º 3
0
def getsystemserialport():

    port = '/dev/ttyAMA0'
    versions = pilib.dbs.system.read_table('versions')

    try:
        versions = pilib.dbs.system.read_table('versions')
        hw_version = ''
        for version in versions:
            print(version['item'])
            if version['item'] == 'versionname':
                print(version)
                hw_version = version['version']
    except:
        utility.log(
            pilib.dirs.dbs.system,
            'Error retrieving hardware version in serial monitor. Reverting to /dev/tty/AMA0'
        )
        print(
            'Error retrieving hardware version in serial monitor. Reverting to /dev/tty/AMA0'
        )
    else:
        print(hw_version, port)

        if hw_version in ['RPi 3 Model B', 'Pi 3 Model B']:
            port = '/dev/ttyS0'

    return port
Ejemplo n.º 4
0
def runpicontrol(runonce=False):
    from time import sleep
    from iiutilities import utility
    from cupid import pilib
    from iiutilities import datalib

    control_db = pilib.cupidDatabase(pilib.dirs.dbs.control)
    log_db = pilib.cupidDatabase(pilib.dirs.dbs.log)
    system_db = pilib.cupidDatabase(pilib.dirs.dbs.system)

    systemstatus = system_db.read_table_row('systemstatus')[0]

    while systemstatus['picontrolenabled']:

        utility.log(pilib.dirs.logs.system, 'Running picontrol', 3, pilib.loglevels.system)
        utility.log(pilib.dirs.logs.control, 'Running picontrol', 3, pilib.loglevels.control)

        # 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'

        system_db.set_single_value('systemstatus', 'lastpicontrolpoll', datalib.gettimestring())

        channels = control_db.read_table('channels')

        # Cycle through channels and set action based on setpoint
        # and algorithm if set to auto mode

        log_tablenames = log_db.get_table_names()

        for channel in channels:
            process_channel(channel=channel)

        # We do this system status again to refresh settings

        systemstatus = system_db.read_table_row('systemstatus')[0]

        # Note that these are also processed in cupiddaemon to catch things like whether this script is running
        # actions.processactions()

        # Wait for delay time
        #print('sleeping')
        # spilights.updatelightsfromdb(pilib.dirs.dbs.control, 'indicators')
        if runonce:
            break

        utility.log(pilib.dirs.logs.system, 'Picontrol Sleeping for ' + str(systemstatus['picontrolfreq']), 2, pilib.loglevels.system)
        utility.log(pilib.dirs.logs.control, 'Picontrol Sleeping for ' + str(systemstatus['picontrolfreq']), 2, pilib.loglevels.system)

        print('sleeping')
        sleep(systemstatus['picontrolfreq'])
        print('done sleeping')

    utility.log(pilib.dirs.logs.system, 'picontrol not enabled. exiting.', 1, pilib.loglevels.system)
Ejemplo n.º 5
0
def getifconfigstatus_DEPRECATED():
    import subprocess
    import pilib
    from iiutilities import utility

    ifconfigdata = subprocess.check_output(['/sbin/ifconfig']).decode('utf-8').split('\n')
    interfaces = []
    ifaceindex = -1
    blankinterface = {'name':'', 'hwaddress':'', 'address':'', 'ifaceindex':'', 'bcast':'', 'mask': '', 'flags':''}
    for line in ifconfigdata:
        if line:
            print('First character: "{}"'.format(line[0]))
        else:
            continue
        # if line.find('Link encap:') >= 0: This breaks in new jessie distro
        if line[0].strip():
            print('item!')
            ifaceindex += 1
            interfaces.append(blankinterface.copy())
            interfaces[ifaceindex]['ifaceindex'] = str(ifaceindex)
            interfaces[ifaceindex]['name'] = line.split(' ')[0].strip()
            if interfaces[ifaceindex]['name'] == 'lo':
                interfaces[ifaceindex]['hwaddress'] = ''
            else:
                try:
                    interfaces[ifaceindex]['hwaddress'] = line.split('HWaddr')[1].strip()
                except:
                    # print('error parsing interface - ' + )
                    utility.log(pilib.dirs.logs.network, 'Error parsing hwaddress in ifconfig for interface' + interfaces[ifaceindex]['name'], 4, pilib.loglevels.network)

        else:
            if line.find('addr') >= 0:
                items = {}
                splits = line.split(':')
                numitems = len(splits) - 1
                if numitems == 1:
                    items[splits[0].strip()]=splits[1].strip()
                elif numitems == 2:
                    items[splits[0].strip()]= splits[1].split(' ')[0].strip()
                    items[splits[1].split(' ')[-1]] = splits[2].strip()
                elif numitems == 3:
                    items[splits[0].strip()]= splits[1].split(' ')[0].strip()
                    items[splits[1].split(' ')[-1]] = splits[2].split(' ')[0].strip()
                    items[splits[2].split(' ')[-1]] = splits[3].strip()

                if 'inet addr' in items:
                    interfaces[ifaceindex]['address'] = items['inet addr']
                if 'Mask' in items:
                    interfaces[ifaceindex]['mask'] = items['Mask']
                if 'Bcast' in items:
                    interfaces[ifaceindex]['bcast'] = items['Bcast']

    return interfaces
Ejemplo n.º 6
0
def process_notifications_queue():
    from iiutilities import dblib
    from iiutilities.utility import log

    notifications_db = cupidDatabase(dirs.dbs.notifications)
    queuednotifications = notifications_db.read_table('queued')

    for notification in queuednotifications:
        if loglevels.notifications >= 5:
            log(
                dirs.logs.notifications,
                'Processing notification of type' + notification['type'] +
                '. Message: ' + notification['message'] + '. Options: ' +
                notification['options'])
        else:
            log(dirs.logs.notifications,
                'Processing notification of type' + notification['type'])

        result = processnotification(notification)

        if result['status'] == 0:
            log(
                dirs.logs.notifications,
                'Notification appears to have been successful. Copying message to sent.'
            )
            sententry = notification.copy()
            sententry['senttime'] = result['senttime']
            dblib.insertstringdicttablelist(dirs.dbs.notifications,
                                            'sent', [sententry],
                                            droptable=False)

            log(dirs.logs.notifications,
                'Removing entry from queued messages.')

            # match by time and message
            conditionnames = ['queuedtime', 'message']
            conditionvalues = [sententry['queuedtime'], sententry['message']]

            notifications_db.delete(
                'queued', {
                    'conditionnames': conditionnames,
                    'conditionvalues': conditionvalues
                })

            # delquery = dblib.makedeletesinglevaluequery('queuednotifications', {'conditionnames':conditionnames, 'conditionvalues':conditionvalues})
            # dblib.sqlitequery(dirs.dbs.notifications, delquery)

        else:
            log(
                dirs.logs.notifications,
                'Notification appears to have failed. Status: ' +
                str(result['status']))
Ejemplo n.º 7
0
    def readprop(self, propname, garbage=None):
        try:
            proppath = self.devicedir + '/' + propname
            propvalue = open(proppath).read().strip()
        except:
            if hasattr(self, 'logpath'):
                from iiutilities.utility import log
                log(self.logpath, 'Error reading property ' + propname + ' for device ' + self.address)

            propvalue = -1

        setattr(self, propname, propvalue)
        return propvalue
Ejemplo n.º 8
0
def replaceifaceparameters(iffilein, iffileout, iface, parameternames,
                           parametervalues):
    from iiutilities import utility
    from cupid import pilib

    file = open(iffilein)
    lines = file.readlines()
    writestring = ''
    ifacename = None
    for line in lines:
        if line.find('iface') >= 0 > line.find('default'):
            # we are at an iface stanza beginning
            foundname = line[6:11].strip()
            ifacename = foundname

        if ifacename == iface:
            # do our replace
            for parametername, parametervalue in zip(parameternames,
                                                     parametervalues):
                if line.find(parametername) > 0:
                    split = line.split(' ')
                    # We find where the parameter is, then assume the value is the
                    # next position. We then trim everything past the parameter
                    # This safeguards against whitespace at the end of lines creating problems.
                    index = split.index(parametername)
                    split[index + 1] = str(parametervalue) + '\n'
                    line = ' '.join(split[0:index + 2])

        writestring += line
    try:
        myfile = open(iffileout, 'w')
    except:
        utility.log(pilib.dirs.logs.network, 'Error opening interface file. ',
                    0, pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network,
                    'Interface file read successfully. ', 3,
                    pilib.loglevels.network)

    try:
        myfile.write(writestring)
    except:
        utility.log(pilib.dirs.logs.network, 'Error writing interface file. ',
                    0, pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network,
                    'Interface file written successfully. ', 3,
                    pilib.loglevels.network)
        utility.log(pilib.dirs.logs.network, 'Write string: ' + writestring, 3,
                    pilib.loglevels.network)
Ejemplo n.º 9
0
def startapservices(interface='wlan0', type='dnsmasq'):
    from time import sleep
    import subprocess
    from cupid import pilib
    from iiutilities import utility

    try:
        # We name the file by the interfae. This way when we pgrep, we know we're running AP on the right interface
        hostapdfilename = '/etc/hostapd/hostapd{}.conf'.format(interface)
        updatehostapd(path=hostapdfilename, interface=interface)
        subprocess.call(['/usr/sbin/hostapd', '-B', hostapdfilename])
    except:
        utility.log(pilib.dirs.logs.network, 'Error starting hostapd. ', 0,
                    pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network, 'Started hostapd without error. ',
                    3, pilib.loglevels.network)

    sleep(1)

    try:
        if type == 'isc':
            updatedhcpd(path='/etc/dhcp/dhcpd.conf', interface=interface)
            subprocess.call(['/usr/sbin/service', 'isc-dhcp-server', 'start'])
        elif type == 'dnsmasq':
            update_dnsmasq_conf()
            subprocess.call(['/usr/sbin/service', 'dnsmasq', 'start'])
    except:
        utility.log(pilib.dirs.logs.network, 'Error starting dhcp server. ', 0,
                    pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network,
                    'Started dhcp server without error. ', 3,
                    pilib.loglevels.network)
Ejemplo n.º 10
0
def processapoverride(pin):
    from iiutilities import utility
    from iiutilities.dblib import setsinglevalue
    import pilib
    utility.log(pilib.dirs.logs.network,
                "Reading GPIO override on pin " + str(pin) + '. ', 3,
                pilib.loglevels.network)
    utility.log(pilib.dirs.logs.system,
                "Reading GPIO override on pin " + str(pin) + '. ', 2,
                pilib.loglevels.system)

    import RPi.GPIO as GPIO
    import pilib

    try:
        GPIO.set_mode(GPIO.BCM)
        GPIO.setwarnings(False)
        GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    except:
        utility.log(pilib.dirs.logs.network, "Error reading GPIO", 3,
                    pilib.loglevels.network)
    else:
        # jumper in place = input off, --> AP mode
        if not GPIO.input(pin):
            utility.log(pilib.dirs.logs.network, "GPIO On. Setting AP Mode.",
                        3, pilib.loglevels.network)
            setsinglevalue(pilib.dirs.dbs.system, 'netconfig', 'mode', 'ap')
Ejemplo n.º 11
0
    def readprop(self, propname, garbage=None):
        try:
            proppath = self.devicedir + '/' + propname
            propvalue = open(proppath).read().strip()
        except:
            if hasattr(self, 'logpath'):
                from iiutilities.utility import log
                log(
                    self.logpath, 'Error reading property ' + propname +
                    ' for device ' + self.address)

            propvalue = -1

        setattr(self, propname, propvalue)
        return propvalue
Ejemplo n.º 12
0
def processsystemflags(systemflags=None):
    from cupid import pilib
    from iiutilities import dblib
    from iiutilities import utility

    if not systemflags:
        systemflags = pilib.dbs.system.read_table('systemflags')

    flagnames = []
    flagvalues = []
    for flag in systemflags:
        flagnames.append(flag['name'])
        flagvalues.append(flag['value'])

    stop = False
    if 'reboot' in flagnames:
        if flagvalues[flagnames.index('reboot')]:
            stop = True
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemflags', 'value',
                                 0, "name='reboot'")
            import subprocess

            utility.log(pilib.dirs.logs.system, 'Rebooting for system flag', 0,
                        pilib.loglevels.system)
            subprocess.call(['/sbin/reboot'])
    if 'netconfig' in flagnames:
        if flagvalues[flagnames.index('netconfig')]:
            stop = True
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemflags', 'value',
                                 0, "name='netconfig'")
            from netconfig import runconfig

            utility.log(pilib.dirs.logs.system,
                        'Restarting network configuration', 0,
                        pilib.loglevels.system)
            runconfig()
    if 'updateiicontrollibs' in flagnames and not stop:
        if flagvalues[flagnames.index('updateiicontrollibs')]:
            stop = True
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemflags', 'value',
                                 0, 'name=\'updateiicontrollibs\'')
            from iiutilities.gitupdatelib import updateiicontrollibs

            utility.log(pilib.dirs.logs.system, 'Updating iicontrollibs', 0,
                        pilib.loglevels.system)
            updateiicontrollibs(True)
    if 'updatecupidweblib' in flagnames and not stop:
        if flagvalues[flagnames.index('updatecupidweblib')]:
            stop = True
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemflags', 'value',
                                 0, 'name=\'updatecupidweblib\'')
            from iiutilities.gitupdatelib import updatecupidweblib

            utility.log(pilib.dirs.logs.system, 'Updating cupidweblib', 0,
                        pilib.loglevels.system)
            updatecupidweblib(True)
Ejemplo n.º 13
0
def processnotification(notification):
    from iiutilities import datalib
    from iiutilities import utility
    from iiutilities.netfun import pingstatus

    senttime = datalib.gettimestring()
    result = {'status': 1, 'senttime': senttime}
    if notification['type'] == 'email':

        # Check to make sure we're online.
        pingresult = pingstatus()
        if not pingresult['status']:

            utility.log(dirs.logs.notifications,
                        'WAN access is ok, so processing notification')
            options = datalib.parseoptions(notification['options'])
            message = notification['message']
            if 'subject' in options:
                subject = options['subject']
            else:
                subject = 'CuPID Notification Email'

            message += '\r\n\r\n'
            message += 'Message queued:\t ' + notification[
                'queuedtime'] + '\r\n'
            message += 'Message sent:\t ' + senttime + '\r\n'

            if 'email' in options:
                try:
                    email = options['email']
                    actionmail = utility.gmail(message=message,
                                               subject=subject,
                                               recipient=email)
                    actionmail.send()
                except:
                    pass
                else:
                    result['status'] = 0
        else:
            utility.log(
                dirs.logs.notifications,
                'WAN access does not appear to be ok. Status is: ' +
                str(pingresult['status']))

    return result
Ejemplo n.º 14
0
def getwpasupplicantconfig(conffile='/etc/wpa_supplicant/wpa_supplicant.conf'):
    from iiutilities import utility
    from cupid import pilib

    class data():
        pass

    file = open(conffile)
    lines = file.readlines()
    header = ''
    tail = ''
    datalines = []
    readheader = True
    readbody = False
    readtail = False
    for line in lines:
        if readheader:
            header = header + line
        if '}' in line:
            utility.log(pilib.dirs.logs.network, 'Ending supplicant parse. ',
                        5, pilib.loglevels.network)
            readbody = False
            readtail = True
        if readbody:
            datalines.append(line)
        if readtail:
            tail = tail + line
        if '{' in line:
            utility.log(pilib.dirs.logs.network,
                        'Beginning supplicant parse. ', 5,
                        pilib.loglevels.network)
            readheader = False
            readbody = True

    datadict = {}
    for line in datalines:
        split = line.split('=')
        datadict[split[0].strip()] = split[1].strip()

    returndict = data()
    returndict.header = header
    returndict.tail = tail
    returndict.data = datadict
    return returndict
Ejemplo n.º 15
0
def getifacestatus():
    from pilib import dirs, loglevels
    from iiutilities.utility import log
    import resource.pyiface.iface as pyiface

    allIfaces = pyiface.getIfaces()
    log(dirs.logs.network, 'Got ifaces data. ', 5, loglevels.network)
    ifacesdictarray=[]
    for iface in allIfaces:
        ifacedict = {}
        ifacedict['name'] = iface.name.strip()
        ifacedict['hwaddress'] = iface.hwaddr.strip()
        ifacedict['address'] = iface._Interface__sockaddrToStr(iface.addr).strip()
        ifacedict['ifaceindex'] = str(iface.index).strip()
        ifacedict['bcast'] = iface._Interface__sockaddrToStr(iface.broadaddr).strip()
        ifacedict['mask'] = iface._Interface__sockaddrToStr(iface.netmask).strip()
        ifacedict['flags'] = pyiface.flagsToStr(iface.flags).replace('\n','').replace('\t',' ').strip()
        ifacesdictarray.append(ifacedict)

    return ifacesdictarray
Ejemplo n.º 16
0
def getwpaclientstatus(interface='wlan0'):
    import subprocess
    from pilib import dirs, loglevels
    from iiutilities.utility import log

    resultdict = {}
    try:
        log(dirs.logs.network,
            'Attempting WPA client status read for interface ' + interface, 4,
            loglevels.network)
        result = subprocess.check_output(
            ['/sbin/wpa_cli', 'status', '-i', interface],
            stderr=subprocess.PIPE).decode('utf-8')
    except:
        log(dirs.logs.network,
            'Unabe to read wpa client status on interface ' + interface + ' .',
            0, loglevels.network)
        resultdict['wpa_state'] = 'None'
    else:
        log(dirs.logs.network, 'Completed WPA client status read. ', 4,
            loglevels.network)

        # prune interface ID
        resultitems = result.split('\n')
        for resultitem in resultitems:
            if resultitem.find('=') > 0:
                split = resultitem.split('=')
                resultdict[split[0]] = split[1].strip()
    if 'wpa_state' not in resultdict:
        resultdict['wpa_state'] = 'UNCAUGHT ERROR'
    return resultdict
Ejemplo n.º 17
0
def readhardwarefileintoversions():

    from iiutilities import utility
    from cupid import pilib
    from iiutilities import dblib

    devicefile = '/var/wwwsafe/devicedata'
    try:
        file = open(devicefile)
        lines = file.readlines()
        devicedict = {}
        for line in lines:
            split = line.split(':')
            try:
                devicedict[split[0].strip()] = split[1].strip()
            except:
                utility.log(pilib.dirs.logs.system, 'Device data parse error', 1, pilib.loglevels.system)
        dblib.sqlitequery(pilib.dirs.dbs.system,
                          dblib.makesqliteinsert('versions', ['hardware', devicedict['hardware']], ['item', 'version']))
    except:
        utility.log(pilib.dirs.logs.system, 'Error opening devicedata file to parse', 1,
                      pilib.loglevels.system)
Ejemplo n.º 18
0
def updatewirelessnetworks(interface='wlan0'):
    from iiutilities.netfun import getwirelessnetworks
    from iiutilities.datalib import dicttojson
    from iiutilities.utility import log
    from iiutilities.dblib import dropcreatetexttablefromdict, sqliteemptytable
    from pilib import dirs

    networks = []
    for i in range(2):
        try:
            networks = getwirelessnetworks(interface)
        except:
            log(
                'Error getting wireless interface networks. Setting empty networks for restart on catch',
                dirs.logs.network)

        if not networks:
            log(
                'No networks returned or error in retrieving, restarting interface '
                + interface, dirs.logs.network)
            reset_net_iface(interface=interface)
        else:
            break

    if networks:
        netinsert = []
        for network in networks:
            # print(network)
            netinsert.append({
                'ssid': network['ssid'],
                'strength': network['signallevel'],
                'data': dicttojson(network)
            })

        dropcreatetexttablefromdict(dirs.dbs.system, 'wirelessnetworks',
                                    netinsert)
    else:
        sqliteemptytable(dirs.dbs.system, 'wirelessnetworks')
    return networks
Ejemplo n.º 19
0
def processnotification(notification):
    from iiutilities import datalib
    from iiutilities import utility
    from iiutilities.netfun import pingstatus

    senttime = datalib.gettimestring()
    result = {'status':1, 'senttime':senttime}
    if notification['type'] == 'email':

        # Check to make sure we're online.
        pingresult = pingstatus()
        if not pingresult['status']:

            utility.log(dirs.logs.notifications, 'WAN access is ok, so processing notification')
            options = datalib.parseoptions(notification['options'])
            message = notification['message']
            if 'subject' in options:
                subject = options['subject']
            else:
                subject = 'CuPID Notification Email'

            message += '\r\n\r\n'
            message += 'Message queued:\t ' + notification['queuedtime'] + '\r\n'
            message += 'Message sent:\t ' + senttime + '\r\n'

            if 'email' in options:
                try:
                    email = options['email']
                    actionmail = utility.gmail(message=message, subject=subject, recipient=email)
                    actionmail.send()
                except:
                    pass
                else:
                    result['status'] = 0
        else:
            utility.log(dirs.logs.notifications, 'WAN access does not appear to be ok. Status is: ' + str(pingresult['status']))

    return result
Ejemplo n.º 20
0
def runsendhandler(ser):
    from iiutilities import dblib, datalib
    from iiutilities import utility

    # print('looking for message to send')

    motes_db = pilib.dbs.motes

    try:
        last_queued_message = motes_db.get_first_time_row(
            'queued', 'queuedtime')
    except:
        import traceback
        utility.log(
            pilib.dirs.logs.serial,
            'Error getting queued message : {}'.format(traceback.format_exc()),
            1, pilib.loglevels.serial)
    else:
        try:
            utility.log(
                pilib.dirs.logs.serial,
                'Sending message : {}'.format(last_queued_message['message']),
                3, pilib.loglevels.serial)
            ser.write(last_queued_message['message'].encode())
            # sendserialmessage(ser, lastqueuedmessage['message'])
        except:
            utility.log(pilib.dirs.logs.serial, 'Error sending message', 1, 1)
        else:
            utility.log(pilib.dirs.logs.serial, 'Success sending message', 1,
                        1)

            conditionnames = ['queuedtime', 'message']
            conditionvalues = [
                last_queued_message['queuedtime'],
                last_queued_message['message']
            ]
            delquery = dblib.makedeletesinglevaluequery(
                'queued', {
                    'conditionnames': conditionnames,
                    'conditionvalues': conditionvalues
                })
            dblib.sqlitequery(pilib.dirs.dbs.motes, delquery)
            dblib.sqliteinsertsingle(pilib.dirs.dbs.motes, 'sent', [
                last_queued_message['queuedtime'],
                datalib.gettimestring(), last_queued_message['message']
            ])
            dblib.size_sqlite_table(pilib.dirs.dbs.motes, 'sent', 1000)
    return
Ejemplo n.º 21
0
def processsystemflags(systemflags=None):
    from cupid import pilib
    from iiutilities import dblib
    from iiutilities import utility


    if not systemflags:
        systemflags = pilib.dbs.system.read_table('systemflags')

    flagnames = []
    flagvalues = []
    for flag in systemflags:
        flagnames.append(flag['name'])
        flagvalues.append(flag['value'])

    stop = False
    if 'reboot' in flagnames:
        if flagvalues[flagnames.index('reboot')]:
            stop = True
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemflags', 'value', 0, "name='reboot'")
            import subprocess

            utility.log(pilib.dirs.logs.system, 'Rebooting for system flag', 0, pilib.loglevels.system)
            subprocess.call(['/sbin/reboot'])
    if 'netconfig' in flagnames:
        if flagvalues[flagnames.index('netconfig')]:
            stop = True
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemflags', 'value', 0, "name='netconfig'")
            from netconfig import runconfig

            utility.log(pilib.dirs.logs.system, 'Restarting network configuration', 0, pilib.loglevels.system)
            runconfig()
    if 'updateiicontrollibs' in flagnames and not stop:
        if flagvalues[flagnames.index('updateiicontrollibs')]:
            stop = True
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemflags', 'value', 0, 'name=\'updateiicontrollibs\'')
            from iiutilities.gitupdatelib import updateiicontrollibs

            utility.log(pilib.dirs.logs.system, 'Updating iicontrollibs', 0, pilib.loglevels.system)
            updateiicontrollibs(True)
    if 'updatecupidweblib' in flagnames and not stop:
        if flagvalues[flagnames.index('updatecupidweblib')]:
            stop = True
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemflags', 'value', 0, 'name=\'updatecupidweblib\'')
            from iiutilities.gitupdatelib import updatecupidweblib

            utility.log(pilib.dirs.logs.system, 'Updating cupidweblib', 0, pilib.loglevels.system)
            updatecupidweblib(True)
Ejemplo n.º 22
0
def killapservices():
    from iiutilities import utility
    from cupid import pilib
    utility.log(pilib.dirs.logs.network, 'Killing AP Services. ', 1,
                pilib.loglevels.network)
    try:
        killhostapd()
    except:
        utility.log(pilib.dirs.logs.network, 'Error killing hostapd. ', 0,
                    pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network, 'Killed hostapd. ', 3,
                    pilib.loglevels.network)

    try:
        killdhcpserver()
    except:
        utility.log(pilib.dirs.logs.network, 'Error killing dhcp server. ', 0,
                    pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network,
                    'Successfully killed dhcp server. ', 3,
                    pilib.loglevels.network)
Ejemplo n.º 23
0
def getifacestatus():
    from pilib import dirs, loglevels
    from iiutilities.utility import log
    import resource.pyiface.iface as pyiface

    allIfaces = pyiface.getIfaces()
    log(dirs.logs.network, 'Got ifaces data. ', 5, loglevels.network)
    ifacesdictarray = []
    for iface in allIfaces:
        ifacedict = {}
        ifacedict['name'] = iface.name.strip()
        ifacedict['hwaddress'] = iface.hwaddr.strip()
        ifacedict['address'] = iface._Interface__sockaddrToStr(
            iface.addr).strip()
        ifacedict['ifaceindex'] = str(iface.index).strip()
        ifacedict['bcast'] = iface._Interface__sockaddrToStr(
            iface.broadaddr).strip()
        ifacedict['mask'] = iface._Interface__sockaddrToStr(
            iface.netmask).strip()
        ifacedict['flags'] = pyiface.flagsToStr(iface.flags).replace(
            '\n', '').replace('\t', ' ').strip()
        ifacesdictarray.append(ifacedict)

    return ifacesdictarray
Ejemplo n.º 24
0
def writesupplicantfile(filedata,
                        filepath='/etc/wpa_supplicant/wpa_supplicant.conf'):
    import subprocess
    from iiutilities import utility
    from cupid import pilib
    writestring = ''

    supplicantfilepath = '/etc/wpa_supplicant/wpa_supplicant.conf'
    # We are hard-coding this, as this will unfortunately propagate a mangled file
    subprocess.call([
        '/bin/cp', '/usr/lib/iicontrollibs/misc/wpa_supplicant.conf',
        supplicantfilepath
    ])

    # iterate over fed data
    ssid = 'not found'
    psk = 'not found'
    for key, value in filedata.data.items():
        if key == 'ssid':
            ssid = value
        elif key == 'psk':
            psk = value

    file = open(supplicantfilepath)
    lines = file.readlines()
    writestring = ''
    ifacename = None
    for line in lines:
        if line.find('psk=') >= 0:
            # insert our iface parameters
            try:
                writestring += 'psk=' + psk + '\n'
            except:
                writestring += 'psk=error'
        elif line.find('ssid=') >= 0:
            # insert our iface parameters
            try:
                writestring += 'ssid=' + ssid + '\n'
            except:
                writestring += 'psk=error'
        else:
            writestring += line

    utility.log(pilib.dirs.logs.network, 'Writing supplicant file. ', 1,
                pilib.loglevels.network)
    try:
        myfile = open(filepath, 'w')
        myfile.write(writestring)
    except:
        utility.log(pilib.dirs.logs.network, 'Error writing supplicant file. ',
                    1, pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network, 'Supplicant file written. ', 3,
                    pilib.loglevels.network)
Ejemplo n.º 25
0
def processapoverride(pin):
    from iiutilities import utility
    from iiutilities.dblib import setsinglevalue
    import pilib
    utility.log(pilib.dirs.logs.network, "Reading GPIO override on pin " + str(pin) + '. ', 3, pilib.loglevels.network)
    utility.log(pilib.dirs.logs.system, "Reading GPIO override on pin " + str(pin) + '. ', 2, pilib.loglevels.system)

    import RPi.GPIO as GPIO
    import pilib

    try:
        GPIO.set_mode(GPIO.BCM)
        GPIO.setwarnings(False)
        GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    except:
        utility.log(pilib.dirs.logs.network, "Error reading GPIO", 3, pilib.loglevels.network)
    else:
        # jumper in place = input off, --> AP mode
        if not GPIO.input(pin):
            utility.log(pilib.dirs.logs.network, "GPIO On. Setting AP Mode.", 3, pilib.loglevels.network)
            setsinglevalue(pilib.dirs.dbs.system, 'netconfig', 'mode', 'ap')
Ejemplo n.º 26
0
def runIPTables(mode, flush=True):
    import pilib
    from iiutilities import utility
    if flush:
        utility.log(pilib.dirs.logs.network, 'Flushing IPTables', 2,
                    pilib.loglevels.network)
        flushIPTables()
    if mode == 'eth0wlan0bridge':
        utility.log(pilib.dirs.logs.network,
                    'Running eth0wlan0 bridge IPTables', 2,
                    pilib.loglevels.network)
        runeth0wlan0bridgeIPTables()
    elif mode == 'wlan0wlan1bridge':
        utility.log(pilib.dirs.logs.network,
                    'Running wlan0wlan1 bridge IPTables', 2,
                    pilib.loglevels.network)
        runwlan0wlan1bridgeIPTables()
    elif mode == 'wlan1wlan0bridge':
        utility.log(pilib.dirs.logs.network,
                    'Running wlan1wlan0 bridge IPTables', 2,
                    pilib.loglevels.network)
        runwlan1wlan0bridgeIPTables()
Ejemplo n.º 27
0
def reset_net_iface(interface='wlan0'):
    from iiutilities import utility
    import subprocess
    from cupid import pilib

    utility.log(pilib.dirs.logs.network, 'Resetting ' + interface + ' . ', 3,
                pilib.loglevels.network)
    try:
        subprocess.call(['/sbin/ifdown', interface], stderr=subprocess.PIPE)
        subprocess.call(['/sbin/ifup', interface], stderr=subprocess.PIPE)
    except:
        import traceback
        utility.log(
            pilib.dirs.logs.network,
            'Error resetting ' + interface + ' : ' + traceback.format_exc(), 0,
            pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network,
                    'Completed resetting ' + interface + '. ', 3,
                    pilib.loglevels.network)
Ejemplo n.º 28
0
def setapmode(interface='wlan0', netconfig=None):
    from iiutilities import utility
    import subprocess
    from cupid import pilib

    utility.log(pilib.dirs.logs.network,
                'Setting ap mode for interface ' + interface, 1,
                pilib.loglevels.network)
    try:
        if interface == 'wlan0':
            subprocess.call([
                '/bin/cp',
                '/usr/lib/iicontrollibs/misc/interfaces/interfaces.ap',
                '/etc/network/interfaces'
            ])
        elif interface == 'wlan0wlan1':
            subprocess.call([
                '/bin/cp',
                '/usr/lib/iicontrollibs/misc/interfaces/interfaces.wlan0dhcp.wlan1cupidwifi',
                '/etc/network/interfaces'
            ])
        elif interface == 'wlan1wlan0':
            subprocess.call([
                '/bin/cp',
                '/usr/lib/iicontrollibs/misc/interfaces/interfaces.wlan1dhcp.wlan0cupidwifi',
                '/etc/network/interfaces'
            ])
    except:
        utility.log(pilib.dirs.logs.network,
                    'Error copying network configuration file. ', 0,
                    pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network,
                    'Copied network configuration file successfully. ', 3,
                    pilib.loglevels.network)

    killapservices()
    reset_net_iface()
    startapservices(interface)
Ejemplo n.º 29
0
def getwpaclientstatus(interface='wlan0'):
    import subprocess
    from pilib import dirs, loglevels
    from iiutilities.utility import log

    resultdict = {}
    try:
        log(dirs.logs.network, 'Attempting WPA client status read for interface ' + interface, 4, loglevels.network)
        result = subprocess.check_output(['/sbin/wpa_cli', 'status', '-i', interface], stderr=subprocess.PIPE).decode('utf-8')
    except:
        log(dirs.logs.network, 'Unabe to read wpa client status on interface ' + interface +  ' .', 0, loglevels.network)
        resultdict['wpa_state'] = 'None'
    else:
        log(dirs.logs.network, 'Completed WPA client status read. ', 4, loglevels.network)

        # prune interface ID
        resultitems = result.split('\n')
        for resultitem in resultitems:
            if resultitem.find('=') > 0:
                split = resultitem.split('=')
                resultdict[split[0]] = split[1].strip()
    if 'wpa_state' not in resultdict:
        resultdict['wpa_state'] = 'UNCAUGHT ERROR'
    return resultdict
Ejemplo n.º 30
0
def run_system_status(**kwargs):
    import pilib
    import time
    from iiutilities import utility
    from iiutilities import dblib
    from iiutilities import datalib
    from iiutilities import gitupdatelib
    from iiutilities import data_agent

    settings = {
        'debug':False,
        'quiet':False, 
        'force':True
    }
    settings.update(kwargs)

    if settings['debug']:
        print('DEBUG MODE')
        settings['quiet']=False
        pilib.set_debug()

    # This doesn't update git libraries. It checks current versions and updates the database

    try:
        utility.log(pilib.dirs.logs.system, 'Checking git versions', 3, pilib.loglevels.system)
        gitupdatelib.updaterepoversion(pilib.dirs.baselib, pilib.dirs.dbs.system, versiontablename='versions')
        gitupdatelib.updaterepoversion(pilib.dirs.web, pilib.dirs.dbs.system, versiontablename='versions')
    except:
        utility.log(pilib.dirs.logs.system, 'Error in git version check', 0, pilib.loglevels.system)
    else:
        utility.log(pilib.dirs.logs.system, 'Git version check complete', 3, pilib.loglevels.system)

    systemstatus = pilib.dbs.system.read_table_row('systemstatus')[0]

    # Get hardware info
    updatehardwareinfo()

    ## Read wireless config via iwconfig
    # this is breaking systemstatus for some reason
    # updateiwstatus()

    ## Read current netstatus
    lastnetstatus={}
    try:
        lastnetstatus = dblib.readonedbrow(pilib.dirs.dbs.system, 'netstatus')[0]
    except:
        utility.log(pilib.dirs.logs.network, 'Error reading network status. ', 1, pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.system, 'Completed network status. ', 3, pilib.loglevels.network)

    # # Poll netstatus and return data
    # allnetstatus = updatenetstatus(lastnetstatus, quiet=settings['quiet'])

    # Keep reading system status?
    while systemstatus['systemstatusenabled'] or settings['force']:

        # Run notifications
        pilib.process_notifications_queue()

        try:
            data_agent.run_data_agent()
        except:
            utility.log(pilib.dirs.logs.system, 'Error running data agent. ', 1, pilib.loglevels.network)
        else:
            utility.log(pilib.dirs.logs.system, 'Data agent run successfully. ', 3, pilib.loglevels.network)


        currenttime = datalib.gettimestring()
        dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemstatus', 'lastsystemstatuspoll', datalib.gettimestring())

        starttime = time.time()
        utility.log(pilib.dirs.logs.system, 'System status routine is starting. ', 3,
                      pilib.loglevels.system)

        """
        Check all network statuses. The goal here is to totally decouple status read and reconfigure
        When we need to check all status data, we'll have it either in a dict or dict array, or in a database table
        
        This sub will read config and status and give both overall and granular interface statuses.
        Then, if status is not 'ok', we will reconfigure interface.
        """

        if systemstatus['netstatusenabled']:
            utility.log(pilib.dirs.logs.system, 'Beginning network routines. ', 3, pilib.loglevels.system)

            # Update network interfaces statuses for all interfaces, in database tables as well
            # Check on wpa supplicant status as well. Function returns wpastatusdict
            try:
                utility.log(pilib.dirs.logs.system, 'Running updateifacestatus. ', 4, pilib.loglevels.system)
                utility.log(pilib.dirs.logs.network, 'Running updateifacestatus', 4, pilib.loglevels.network)
                allnetstatus = update_net_status(lastnetstatus, quiet=settings['quiet'])
            except:
                utility.log(pilib.dirs.logs.network, 'Exception in updateifacestatus. ')
            else:
                utility.log(pilib.dirs.logs.network, 'Updateifacestatus completed. ')

            utility.log(pilib.dirs.logs.system, 'Completed net status update. ', 4, pilib.loglevels.system)

        """
        End network configuration status
        """


        """
        Do we want to autoconfig the network? 
        
        If so, we analyze our netstatus data against what should be going on,
        and translate this into a network status. We have a list of ifaceconfigs and a list if ifacestatus
        """
        if systemstatus['netconfigenabled'] and systemstatus['netstatusenabled']:

            # No need to get this fresh. We have it stored.
            netconfig_data = allnetstatus['netconfig_data']

            # We are going to hack in a jumper that sets AP configuration. This isn't the worst thing ever.
            # if netconfig_data['apoverride']:
            #     result = processapoverride(21)

            ''' Now we check network status depending on the configuration we have selected '''
            utility.log(pilib.dirs.logs.system, 'Running interface configuration watchdog. ', 4,
                          pilib.loglevels.system)
            utility.log(pilib.dirs.logs.network, 'Running interface configuration. Mode: {}'.format(netconfig_data['mode']), 4,
                          pilib.loglevels.network)

            # print('ALL IFACE STATUS')
            # print(allnetstatus['ifaces_status'])

            result = watchdognetstatus(allnetstatus=allnetstatus)

        else:
            utility.log(pilib.dirs.logs.system, 'Netconfig or netstatus disabled. ', 1, pilib.loglevels.system)
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'mode', 'manual')
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'statusmsg', 'netconfig is disabled')

        """ Check Hamachi """
        if systemstatus['checkhamachistatus']:
            utility.log(pilib.dirs.logs.system, 'Hamachi watchdog is enabled', 3, pilib.loglevels.system)
            utility.log(pilib.dirs.logs.network, 'Hamachi watchdog is enabled. ', 3, pilib.loglevels.network)

            # Only watchdog haamchi if we are connected to the network.
            netstatus = dblib.readonedbrow(pilib.dirs.dbs.system, 'netstatus')[0]
            if netstatus['WANaccess']:
                utility.log(pilib.dirs.logs.system, 'We appear to be online. Checking Hamachi Status. ', 3, pilib.loglevels.system)
                utility.log(pilib.dirs.logs.network, 'We appear to be online. Checking Hamachi Status. ', 3, pilib.loglevels.network)
                
                watchdoghamachi(pingip='25.11.87.7')

                utility.log(pilib.dirs.logs.system, 'Completed checking Hamachi Status. ', 3, pilib.loglevels.network)
                utility.log(pilib.dirs.logs.system, 'Completed checking Hamachi Status. ', 3, pilib.loglevels.network)

            else:
                utility.log(pilib.dirs.logs.system, 'We appear to be offline. Not checking Hamachi Status, but setting to 0. ', 3, pilib.loglevels.system)
                utility.log(pilib.dirs.logs.network, 'We appear to be offline. Not checking Hamachi Status, but setting to 0. ', 3, pilib.loglevels.network)
                dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemstatus', 'hamachistatus', 0)
        else:
            utility.log(pilib.dirs.logs.system, 'Hamachi watchdog is disabled', 3, pilib.loglevels.system)

        utility.log(pilib.dirs.logs.system, 'Finished interface configuration. ', 4,
                      pilib.loglevels.system)
        # pilib.writedatedlogmsg(pilib.dirs.logs.network, statusmsg)

        utility.log(pilib.dirs.logs.system, 'Running updateifacestatus. ', 4, pilib.loglevels.system)

        update_net_status()

        utility.log(pilib.dirs.logs.system, 'Completed updateifacestatus. ', 4, pilib.loglevels.system)

        utility.log(pilib.dirs.logs.system, 'Network routines complete. ', 3, pilib.loglevels.system)

        utility.log(pilib.dirs.logs.system, 'Checking system flags. ', 3, pilib.loglevels.system)
        processsystemflags()
        utility.log(pilib.dirs.logs.system, 'System flags complete. ', 3, pilib.loglevels.system)

        # Get system status again
        systemstatus = pilib.dbs.system.read_table('systemstatus')[0]

        elapsedtime = int(time.time() - starttime)

        utility.log(pilib.dirs.logs.system, 'Status routines complete. Elapsed time: {}'.format(str(elapsedtime)), 3,
                      pilib.loglevels.system)

        utility.log(pilib.dirs.logs.system,
                               'System status is sleeping for {} .'.format(systemstatus['systemstatusfreq']), 3,
                      pilib.loglevels.system)

        # print('enabled: ' , systemstatus['systemstatusenabled'])
        if 'runonce' in kwargs and kwargs['runonce']:
            break

        time.sleep(systemstatus['systemstatusfreq'])

    else:
        utility.log(pilib.dirs.logs.system, 'System status is disabled. Exiting. ', 0, pilib.loglevels.system)
Ejemplo n.º 31
0
def application(environ, start_response):

    import cgi
    import json

    import os, sys, inspect

    # Set top folder to allow import of modules

    top_folder = os.path.split(os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0])))[0]
    if top_folder not in sys.path:
        sys.path.insert(0,top_folder)

    from cupid import pilib, controllib
    from iiutilities import dblib, utility, datalib

    # post_env = environ.copy()
    # post_env['QUERY_STRING'] = ''
    # post = cgi.FieldStorage(
    #     fp=environ['wsgi.input'],
    #     environ=post_env,
    #     keep_blank_values=True
    # )
    #
    # formname=post.getvalue('name')
    # output = {}
    # output['message'] = 'Output Message: '
    # for k in post.keys():
    #     d[k] = post.getvalue(k)

    try:
        request_body_size = int(environ.get('CONTENT_LENGTH', 0))
    except ValueError:
        request_body_size = 0

    request_body = environ['wsgi.input'].read(request_body_size)
    post = json.loads(request_body.decode('utf-8'))

    output = {}
    output['message'] = ''

    status = '200 OK'
    wsgiauth = True
    authverified = False

    if wsgiauth:
        # Verfiy that session login information is legit: hashed password, with salt and username, match
        # hash stored in database.
        import hashlib

        safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.users)
        if 'username' in post and post['username']:
            output['message'] += 'Session user is ' + post['username'] + '. '
        else:
            output['message'] += 'No session user found. '
            post['username'] = ''

        if post['username']:
            try:
                condition = "name='" + post['username'] + "'"
                user_data = safe_database.read_table_row('users', condition=condition)[0]
            except:
                output['message'] += 'Error in user sqlite query for session user "' + post['username'] + '". '
                output['message'] += 'Condition: ' + condition + '. Path: ' + pilib.dirs.dbs.safe
                user_data = {'accesskeywords': 'demo', 'admin': False}
            else:
                # Get session hpass to verify credentials
                hashedpassword = post['hpass']
                hname = hashlib.new('sha1')
                hname.update(post['username'])
                hashedname = hname.hexdigest()
                hentry = hashlib.new('md5')
                hentry.update(hashedname + pilib.salt + hashedpassword)
                hashedentry = hentry.hexdigest()
                if hashedentry == user_data['password']:
                    # successful auth
                    output['message'] += 'Password verified. '
                    authverified = True

                    # TODO: implement usermeta
        else:
            # Demo status
            authverified = True
            user_data = {'authlevel':0}

    else:
        output['message'] += 'WSGI authorization not enabled. '

    if authverified or not wsgiauth:
        output['authorized'] = True

    try:
        action = post['action']
    except KeyError:
        output['message'] = 'no action in request'
        action = ''
    else:
        output['message'] += '{} action keyword found'.format(action)

    if output['authorized'] and action:
        output['action_allowed'] = pilib.check_action_auths(action, user_data['authlevel'])
    else:
        output['action_allowed'] = False

    if output['authorized'] and output['action_allowed']:

        output['message'] += 'Found action. '

        if action == 'testdbvn':
            from iiutilities.dblib import dbvntovalue
            try:
                output['data'] = dbvntovalue(post['dbvn'])
            except:
                output['message'] += 'Error in dbvn evaluation. '
                output['data'] = 'error'
            else:
                output['message'] += 'Seems to have worked out. '
        elif action == 'testlogical':
            from iiutilities.datalib import evaldbvnformula
            try:
                output['data'] = evaldbvnformula(post['logical'])
            except:
                output['message'] += 'Error in logical evaluation. '
                output['data'] = 'error'
            else:
                output['message'] += 'Seems to have worked out. '

        elif action == 'testmodule':
            output['message'] += 'Testing module: '
            if 'modulename' in post:
                import cupid.cupidunittests
                output['message'] += post['modulename']
                output['data'] = cupid.cupidunittests.testmodule(post['modulename'])
            else:
                output['message'] += 'Modulename not found. '
        elif action == 'testfunction':
            output['message'] += 'Testing function: '
            if 'testname' in post:
                import cupid.cupidunittests
                output['message'] += post['testname']
                # output['data'] = cupid.tests.testfunction(d['testname'])
                output['data'] = cupid.cupidunittests.testfunction(post['testname'])
                # output['data'] = str(cupid.tests.testfunction('systemstatus'))
            else:
                output['message'] += 'Testname not found. '

        elif action == 'modifychannelalarm':
            controllib.handle_modify_channel_alarm(post, output)
            from cupid.actions import processactions

            # process only this action.
            processactions(name=post['actionname'])

        elif action == 'modifychannel':
            controllib.handle_modify_channel(post, output)

        elif action == 'getalarmscount':
            control_db = dblib.sqliteDatabase(pilib.dirs.dbs.control)
            actions = control_db.read_table('actions')
            output['data'] = {'totalalarms':len(actions),'channelalarms':0, 'activealarms':0, 'activechannelalarms':0}
            for action in actions:
                if action['conditiontype'] == 'channel':
                    output['data']['channelalarms'] += 1
                    if action['active']:
                        output['data']['activechannelalarms'] += 1

                if action['active']:
                    output['data']['activealarms'] += 1

        elif action == 'copy_log_to_archive':
            pilib.app_copy_log_to_archive(post, output)

        elif action == 'getlogscount':
            logtablenames = dblib.sqliteDatabase(pilib.dirs.dbs.log).get_table_names()
            output['data'] = {'logscount':len(logtablenames)}


        elif action == 'test_action':
            output['message'] += 'Testing action. '
            controldb = dblib.sqliteDatabase(pilib.dirs.dbs.control)
            actiondict = controldb.read_table('actions',condition='"name"=\'' + post['actionname'] + "'")[0]
            from cupid.actions import action
            test_action = action(actiondict)
            test_action.test()

        elif action == 'update_network':
            safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.safe)
            safe_database.set_single_value('wireless', 'password', post['password'], "SSID='" + post['ssid'] + "'")

        elif action == 'add_network':
            safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.safe)
            insert = {'SSID':post['ssid'], 'auto':1, 'priority':1}
            if 'password' in post:
                insert['password'] = post['password']
            safe_database.insert('wireless',insert)

        elif action == 'delete_network':
            safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.safe)
            safe_database.delete('wireless', "SSID='" + post['ssid'] + "'")

        # elif action == 'dump':
        #     # this has to go.
        #     if 'database' in d:
        #         dbpath = pilib.dbnametopath(d['database'])
        #         if dbpath:
        #             if 'tablelist' in d and 'outputfile' in d:
        #                 dbpath = pilib.dbnametopath(d['database'])
        #                 dblib.sqlitedatadump(dbpath, d['tablelist'], d['outputfile'])
        #                 output['message'] = 'data dumped'
        #             elif 'tablename' in d and 'outputfile' in d:
        #                 dblib.sqlitedatadump(dbpath, [d['tablename']], d['outputfile'])
        #                 output['message'] = 'data dumped. '
        #             else:
        #                 output['message'] += 'keys not present for dump. '
        #         else:
        #             output['message'] += 'keys not present for dump. '
        #     else:
        #         output['message'] += 'keys not present for dump. '
        elif action in ['userdelete', 'useradd', 'usermodify']:
            """
            This needs to be consolidate with the other useradd, modify algorithm written already.
            Probably do this when we update the user permissions interface.
            """
            # Ensure that we are authorized for this action
            if action == 'userdelete':
                try:
                    dblib.sqlitequery(pilib.dirs.dbs.users, "delete from users where name='" + post['usertodelete'] + "'")
                except:
                    output['message'] += 'Error in delete query. '
                else:
                    output['message'] += 'Successful delete query. '
            elif action == 'usermodify':

                if 'usertomodify' in post:
                    querylist=[]
                    if 'newpass' in post:
                        from pilib import salt
                        # Get session hpass to verify credentials
                        hashedpassword = post['newpass']
                        hname = hashlib.new('sha1')
                        hname.update(post['usertomodify'])
                        hashedname = hname.hexdigest()
                        hentry = hashlib.new('md5')
                        hentry.update(hashedname + salt + hashedpassword)
                        hashedentry = hentry.hexdigest()
                        querylist.append('update users set password='******'" + post['usertomodify'] + "'")

                    if 'newemail' in post:
                        querylist.append("update users set email='" + post['newemail'] + "' where name='" + post['usertomodify'] + "'")
                    if 'newauthlevel' in post:
                        querylist.append("update users set authlevel='" + post['newauthlevel'] + "' where name='" + post['usertomodify'] + "'")

                    try:
                        dblib.sqlitemultquery(pilib.dirs.dbs.users, querylist)
                    except:
                        output['message'] += 'Error in modify/add query: ' + ",".join(querylist)
                    else:
                        output['message'] += 'Successful modify/add query. ' + ",".join(querylist)
                else:
                    output['message'] += 'Need usertomodify in query. '
            elif action == 'useradd':
                try:
                    username = post['newusername']
                except:
                    username = '******'
                try:
                    newemail = post['newemail']
                except:
                    newemail = '*****@*****.**'
                try:
                    newauthlevel = post['newauthlevel']
                except:
                    newauthlevel = 0
                    query = "insert into users values(NULL,'" + username + "','','" + newemail + "',''," + str(newauthlevel) + ")"
                try:
                    dblib.sqlitequery(pilib.dirs.dbs.users, query)
                except:
                    output['message'] += "Error in useradd sqlite query: " + query + ' . '
                else:
                    output['message'] += "Successful query: " + query + ' . '
        elif action == 'getfiletext':
            try:
                filepath = post['filepath']
                if 'numlines' in post:
                    numlines = int(post['numlines'])
                else:
                    numlines = 9999
                output['message'] += 'Using numlines: ' + str(numlines) + ' for read action. '
                if 'startposition' in post:
                    startposition = post['startposition']
                else:
                    startposition = 'end'
                output['message'] += 'Reading from position ' + startposition + '. '
            except KeyError:
                output['message'] += 'Sufficient keys for action getfile text do not exist. '
            except:
                output['message'] += 'Uncaught error in getfiletext. '
            else:
                try:
                    file = open(filepath)
                    lines = file.readlines()
                except:
                    output['message'] += 'Error reading file in getfiletext action. '
                else:
                    output['data'] = []
                    if startposition == 'end':
                        try:
                            output['data'] = datalib.tail(file, numlines)[0]
                        except:
                            output['message'] += 'Error in tail read. '
                    else:
                        linecount = 0
                        for line in lines:
                            linecount += 1
                            if linecount > numlines:
                                break
                            else:
                                output['data'].append(line)
        elif action == 'getmbtcpdata':
            try:
                clientIP = post['clientIP']
                register = post['register']
                length = post['length']
            except KeyError:
                output['message'] += 'Sufficient keys do not exist for the command. Requires clientIP, register, and length. '
            else:
                from iiutilities.netfun import readMBcodedaddresses
                # try:
                output['response'] = readMBcodedaddresses(clientIP, int(register), int(length))
        elif action == 'queuemessage':
            output['message'] += 'Queue message. '
            if 'message' in post:
                try:
                    dblib.sqliteinsertsingle(pilib.dirs.dbs.motes, 'queuedmessages', [datalib.gettimestring(), post['message']])
                except:
                    import traceback
                    exc_type, exc_value, exc_traceback = sys.exc_info()
                    output['message'] += 'Error in queue insert query: {}. '.format(traceback.format_exc())
                else:
                    output['message'] += 'Message insert successful'
            else:
                output['message'] += 'No message present. '

        elif action == 'setsystemflag' and 'systemflag' in post:
            database = pilib.dirs.dbs.system
            dblib.setsinglevalue(database, 'systemflags', 'value', 1, "name=\'" + post['systemflag'] + "'")
        elif action == 'rundaemon':
            from cupiddaemon import rundaemon
            rundaemon()

        # TODO: Eliminate this scary thing.
        elif action == 'setvalue':
            utility.log(pilib.dirs.logs.control, "Setting value in wsgi", 1, 1)

            # we use the auxiliary 'setsinglecontrolvalue' to add additional actions to update
            if all(k in post for k in ('database', 'table', 'valuename', 'value')):
                dbpath = pilib.dbnametopath(post['database'])
                if dbpath:
                    output['message'] += 'Carrying out setvalue for value ' + post['valuename'] + ' on ' + post['table'] + ' in '  + dbpath
                    if 'condition' in post:
                        pilib.setsinglecontrolvalue(dbpath, post['table'], post['valuename'], post['value'], post['condition'])
                    elif 'index' in post:
                        condition = 'rowid= ' + post['index']
                        pilib.setsinglecontrolvalue(dbpath, post['table'], post['valuename'], post['value'], condition)
                    else:
                        pilib.setsinglecontrolvalue(dbpath, post['table'], post['valuename'], post['value'])
                else:
                    output['message'] += 'Problem translating dbpath from friendly name: ' + post['database']
            else:
                output['message'] += 'Insufficient data for setvalue '
        elif action == 'updateioinfo':
            if all(k in post for k in ['database', 'ioid', 'value']):
                query = dblib.makesqliteinsert('ioinfo', [post['ioid'], post['value']], ['id', 'name'])
                try:
                    dblib.sqlitequery(pilib.dirs.dbs.control, query)
                except:
                    output['message'] += 'Error in updateioinfo query execution: ' + query +'. into database: ' + pilib.dirs.dbs.control
                    output['message'] += 'ioid: ' + post['ioid'] + ' . '
                else:
                    output['message'] += 'Executed updateioinfo query. '
            else:
                output['message'] += 'Insufficient data for updateioinfo query ! '


        # TODO: properly incorporate and test channel class functions here, and then sub it.
        elif action == 'modify_channel':
            controllib.app_modify_channel(post, output)

        elif action == 'deletechannelbyname' and 'database' in post and 'channelname' in post:
            dbpath = pilib.dbnametopath(post['database'])
            dblib.sqlitequery(dbpath, 'delete channelname from channels where name=\"' + post['channelname'] + '\"')
        elif action == 'updatecameraimage':
            output['message'] += 'Take camera image keyword. '
            import cupid.camera
            if 'width' in post:
                width = post['width']
            else:
                width = 800
            try:
                values = cupid.camera.takesnap(width=width)
            except:
                output['message'] += 'Error taking image. '
            else:
                output['message'] += 'Appears successful. Path : ' + values['imagepath'] + '. Timestamp : ' + values['timestamp'] + '. '
                output['data'] = values
        elif action == 'getcurrentcamtimestamp':
            output['message'] += 'getcurrentcamtimestamp keyword found. '
            try:
                with open('/var/www/webcam/images/current.jpg.timestamp') as f:
                    data = f.read()
            except:
                output['message'] += 'Error reading file as requested. '
            else:
                output['data'] = data
        else:
            output['message'] += 'Action keyword present(' + action + '), but not handled. '
    else:
        output['message'] += 'Authentication unsuccessful or action not authorized.'
        status = '401 Not Authorized'

    foutput = json.dumps(output, indent=1)

    response_headers = [('Content-type', 'application/json')]
    start_response(status, response_headers)

    return [foutput]
Ejemplo n.º 32
0
def check_interface_status(iface_config, iface_status):
    import pilib
    from iiutilities import utility
    # print("CONFIG")
    # print(iface_config)
    # print("STATUS")
    # print(iface_status)
    utility.log(pilib.dirs.logs.network, 'Checking configuration of interface {} type: {}. '.format(
        iface_config['name'], iface_config['mode']), 3, pilib.loglevels.network)

    return_dict = {'status':'ok', 'status_message':''}

    # Check address exists
    if iface_config['mode'] in ['ap', 'station', 'dhcp', 'static']:
        if 'address' not in iface_status['config']:
            new_message = 'no address present. Status: {}'.format(iface_status)
            utility.log(pilib.dirs.logs.network, new_message, 1, pilib.loglevels.network)
            return_dict['status_message'] += new_message
            return_dict['status'] = 'fail'
            return return_dict

    # Check for address match
    if iface_config['mode'] in ['ap', 'static']:
        if iface_status['config']['address'] != iface_config['config']['address']:
            # print(iface_config)
            # print(iface_status)
            return_dict['status'] = 'fail'
            new_message = 'Address mismatch. Expected {}. Found {}. '.format(iface_config['config']['address'], iface_status['config']['address'])
            utility.log(pilib.dirs.logs.network, new_message, 1, pilib.loglevels.network)
            return_dict['status_message'] += new_message

    # Check AP Mode
    if iface_config['mode'] in ['ap']:
        from netconfig import get_dhcp_status, get_hostapd_status

        # Check dhcp server
        iface_status['config']['dhcpstatus'] = get_dhcp_status()
        if not iface_status['config']['dhcpstatus']['status']:
            new_message = 'AP dhcp status checked and ok. '
            utility.log(pilib.dirs.logs.network, new_message, 1, pilib.loglevels.network)
            return_dict['status_message'] += new_message
        else:
            new_message = 'AP dhcp status is not ok. '
            utility.log(pilib.dirs.logs.network, new_message, 1, pilib.loglevels.network)
            return_dict['status'] = 'fail'
            return_dict['status_message'] += new_message
            return return_dict

        # Check hostapd
        iface_status['config']['hostapdstatus'] = get_hostapd_status()
        if not iface_status['config']['hostapdstatus']['status']:
            new_message = 'AP hostapd status checked and ok. '
            utility.log(pilib.dirs.logs.network, new_message, 1, pilib.loglevels.network)
            return_dict['status_message'] += new_message
        else:
            new_message = 'AP hostapd status is not ok. '
            utility.log(pilib.dirs.logs.network, new_message, 1, pilib.loglevels.network)
            return_dict['status'] = 'fail'
            return_dict['status_message'] += new_message
            return return_dict

    # Check for wpa state
    if iface_config['mode'] in ['station']:
        # print('STATION')
        # print(iface_status)
        if 'wpastate' not in iface_status['config']:
            new_message = 'No wpa state present in iface_status. '
            utility.log(pilib.dirs.logs.network, new_message, 1, pilib.loglevels.network)
            return_dict['status'] = 'fail'
            return_dict['status_message'] += new_message
            return return_dict

        wpadata = iface_status['config']['wpastate']
        if wpadata['wpa_state'] == 'COMPLETED':
            new_message = 'wpa state appears ok for interface. '
            utility.log(pilib.dirs.logs.network, new_message, 3, pilib.loglevels.network)
            return_dict['status_message'] += new_message
        else:
            new_message = 'wpa state appears BAD for interface: {} '.format(wpadata['wpastate'])
            utility.log(pilib.dirs.logs.network, new_message, 3, pilib.loglevels.network)
            return_dict['status_message'] += new_message
            return_dict['status'] = 'fail'

    return return_dict
Ejemplo n.º 33
0
def setstationmode(netconfigdata=None):
    import subprocess
    from iiutilities import utility
    from cupid import pilib
    from iiutilities import dblib

    utility.log(pilib.dirs.logs.network, 'Setting station mode. ', 3,
                pilib.loglevels.network)

    from time import sleep
    if not netconfigdata:
        utility.log(pilib.dirs.logs.network,
                    'Retrieving unfound netconfig data. ', 3,
                    pilib.loglevels.network)
        try:
            netconfigdata = dblib.readonedbrow(pilib.dirs.dbs.system,
                                               'netconfig')[0]
        except:
            utility.log(pilib.dirs.logs.network,
                        'Error reading netconfig data. ', 0,
                        pilib.loglevels.network)
        else:
            utility.log(pilib.dirs.logs.network, 'Read netconfig data. ', 4,
                        pilib.loglevels.network)

    killapservices()
    if netconfigdata['mode'] == 'staticeth0_stationdhcp':
        utility.log(pilib.dirs.logs.network,
                    'Configuring static eth0 and dhcp wlan0. ', 3,
                    pilib.loglevels.network)

        subprocess.call([
            '/bin/cp',
            '/usr/lib/iicontrollibs/misc/interfaces/interfaces.sta.eth0staticwlan0dhcp',
            '/etc/network/interfaces'
        ])
        reset_net_iface(interface='eth0')

        # update IP from netconfig
        utility.log(pilib.dirs.logs.network,
                    'Updating netconfig with ip ' + netconfigdata['address'],
                    3, pilib.loglevels.network)
        replaceifaceparameters(
            '/etc/network/interfaces', '/etc/network/interfaces', 'wlan0',
            ['address', 'gateway'],
            [netconfigdata['address'], netconfigdata['gateway']])

    # This is the old mode for legacy purposes and backward compatibility
    elif netconfigdata['mode'] == 'station':

        if netconfigdata['addtype'] == 'static':
            utility.log(pilib.dirs.logs.network,
                        'Configuring static address. ', 3,
                        pilib.loglevels.network)

            subprocess.call([
                '/bin/cp',
                '/usr/lib/iicontrollibs/misc/interfaces/interfaces.sta.static',
                '/etc/network/interfaces'
            ])

            # update IP from netconfig
            utility.log(
                pilib.dirs.logs.network,
                'Updating netconfig with ip ' + netconfigdata['address'], 3,
                pilib.loglevels.network)
            replaceifaceparameters(
                '/etc/network/interfaces', '/etc/network/interfaces', 'wlan0',
                ['address', 'gateway'],
                [netconfigdata['address'], netconfigdata['gateway']])
        elif netconfigdata['addtype'] == 'dhcp':
            utility.log(pilib.dirs.logs.network, 'Configuring dhcp. ', 3,
                        pilib.loglevels.network)
            subprocess.call([
                '/bin/cp',
                '/usr/lib/iicontrollibs/misc/interfaces/interfaces.sta.dhcp',
                '/etc/network/interfaces'
            ])

    utility.log(pilib.dirs.logs.network, 'Resetting wlan. ', 3,
                pilib.loglevels.network)
    reset_net_iface()
    sleep(1)
    reset_net_iface()
Ejemplo n.º 34
0
def updatewpasupplicantOLD(interface='wlan0'):
    from iiutilities import utility
    from cupid import pilib
    # print('I AM UPDATING SUPPLICANT DATA')
    suppdata = None
    try:
        suppdata = getwpasupplicantconfig()
    except:
        utility.log(pilib.dirs.logs.network, 'Error getting supplicant data. ',
                    0, pilib.loglevels.network)
        return
    else:
        utility.log(pilib.dirs.logs.network,
                    'Supplicant data retrieved successfully. ', 3,
                    pilib.loglevels.network)

    try:
        updateddata = updatesupplicantdata(suppdata)
    except:
        utility.log(pilib.dirs.logs.network,
                    'Error updating supplicant data. ', 0,
                    pilib.loglevels.network)
        return
    else:
        utility.log(pilib.dirs.logs.network,
                    'Supplicant data retrieved successfully. ', 3,
                    pilib.loglevels.network)

    try:
        writesupplicantfile(updateddata)
    except:
        utility.log(pilib.dirs.logs.network, 'Error writing supplicant data. ',
                    0, pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network,
                    'Supplicant data written successfully. ', 3,
                    pilib.loglevels.network)

    return
Ejemplo n.º 35
0
def updatewpasupplicant(**kwargs):
    from cupid import pilib
    from iiutilities import dblib
    from iiutilities import utility

    settings = {
        'station_interface': 'wlan0',
        # 'network_select':['name','strongest'],
        'network_select': ['strongest'],
        'network_ssid': 'leHouse',
        'path': '/etc/wpa_supplicant/wpa_supplicant.conf',
        'debug': False
    }
    settings.update(kwargs)

    # Update networks to see what is available to attach to
    # try:
    networks = updatewirelessnetworks(settings['station_interface'])

    if settings['debug']:
        network_dict = {}
        for network in networks:
            network_dict[network['ssid']] = network

        print('all networks by strength: ')
        networks_with_strength = [{
            'ssid':
            network['ssid'],
            'signallevel':
            int(network['signallevel'].split('dB')[0].strip())
        } for network_name, network in network_dict.items()]

        from operator import itemgetter
        networks_by_strength = sorted(networks_with_strength,
                                      key=itemgetter('signallevel'),
                                      reverse=True)
        print(networks_by_strength)

    # except:
    # utility.log(pilib.dirs.logs.network, 'Error finding network interface. Is interface down?', 0, pilib.loglevels.network)

    # availablessids = []
    # for network in networks:
    #     availablessids.append(network['ssid'])

    # At first pass, this could be as simple as checking the last SSID and trying the other one

    try:
        wirelessauth_list = pilib.dbs.safe.read_table('wireless')
    except:
        utility.log(pilib.dirs.logs.network, 'Error reading wireless data. ',
                    0, pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network, 'Read wireless data. ', 4,
                    pilib.loglevels.network)

    auths = {}
    for auth_element in wirelessauth_list:
        auths[auth_element['SSID']] = auth_element

    # Get paired lists of networks and auths that match
    matchnetworks = {}
    for network in networks:
        this_ssid = network['ssid']
        if this_ssid in auths:
            matchnetworks[this_ssid] = network
            matchnetworks[this_ssid]['auths'] = auths[this_ssid]

    # So now the matchnetworks are available and we have credentials for them
    print('*** AVAILABLE NETWORKS ***')
    print(matchnetworks)

    newnetwork = {}
    if len(matchnetworks.items()) > 0:
        # matchnetwork_names = [matchnetwork['name'] for matchnetwork in matchnetworks]

        utility.log(pilib.dirs.logs.network,
                    str(len(matchnetworks)) + ' matching networks found. ', 1,
                    pilib.loglevels.network)
        """
        Choose network
        
        This is written such that if you have 'name' selected and not 'by strength' as secondary choice, no network
        will be selected. This is potentially a valid option.
        
        """
        #        TODO: Add in possibility of sorting by priority as stored in credentials.

        for network_method in settings['network_select']:
            if network_method == 'name':
                utility.log(pilib.dirs.logs.network,
                            'Using method name with name {}. ', 2,
                            pilib.loglevels.network)

                if settings['network_ssid'] in matchnetworks:
                    utility.log(pilib.dirs.logs.network,
                                'Selected network {} found. ', 2,
                                pilib.loglevels.network)
                    newnetwork = matchnetworks[settings['network_ssid']]
                    break
                else:
                    utility.log(pilib.dirs.logs.network,
                                'Selected network {} NOT found. ', 2,
                                pilib.loglevels.network)
            elif network_method == 'strongest':
                utility.log(pilib.dirs.logs.network,
                            'Using method strongest. ', 2,
                            pilib.loglevels.network)

                networks_with_strength = [{
                    'ssid':
                    network['ssid'],
                    'signallevel':
                    int(network['signallevel'].split('dB')[0].strip()),
                    'network':
                    network
                } for network_name, network in matchnetworks.items()]
                print(networks_with_strength)

                from operator import itemgetter
                networks_by_strength = sorted(networks_with_strength,
                                              key=itemgetter('signallevel'),
                                              reverse=True)
                newnetwork = networks_by_strength[0]['network']
                print(networks_by_strength)
                break

        if newnetwork:
            print('NEW NETWORK')
            print(newnetwork)
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'netconfig', 'SSID',
                                 newnetwork['ssid'])

            utility.log(pilib.dirs.logs.network,
                        'Network "' + newnetwork['ssid'] + '" selected', 1,
                        pilib.loglevels.network)

            myfile = open(settings['path'], 'w')

            filestring = 'ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\nupdate_config=1\n\n'
            filestring += 'network={\n'
            filestring += 'psk="' + newnetwork['auths']['password'] + '"\n'
            filestring += 'ssid="' + newnetwork['ssid'] + '"\n'
            filestring += 'proto=RSN\nauth_alg=OPEN\npairwise=CCMP\nkey_mgmt=WPA-PSK\n}'

            myfile.write(filestring)
            myfile.close()

        else:
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'netconfig', 'SSID',
                                 '')
            utility.log(
                pilib.dirs.logs.network,
                'No network found with method selected and auths/ssids available. ',
                1, pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network,
                    'No available ssids found with saved auths.', 1,
                    pilib.loglevels.network)
Ejemplo n.º 36
0
def updatesupplicantdata(configdata):
    from cupid import pilib
    from iiutilities import utility

    netconfig = []
    try:
        netconfig = pilib.dbs.system.read_table_row('netconfig')[0]
    except:
        utility.log(pilib.dirs.logs.network, 'Error reading netconfig data. ',
                    0, pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network, 'Read netconfig data. ', 4,
                    pilib.loglevels.network)

    wirelessauths = []
    try:
        wirelessauths = pilib.dirs.dbs.safe.read_table('wireless')
    except:
        utility.log(pilib.dirs.logs.network, 'Error reading wireless data. ',
                    0, pilib.loglevels.network)
    else:
        utility.log(pilib.dirs.logs.network, 'Read wireless data. ', 4,
                    pilib.loglevels.network)

    utility.log(pilib.dirs.logs.network, 'Netconfig data: ' + str(netconfig),
                2, pilib.loglevels.network)

    # we only update if we find the credentials
    for auth in wirelessauths:
        if auth['SSID'] == netconfig['SSID']:
            password = '******' + auth['password'] + '"'
            ssid = '"' + auth['SSID'] + '"'
            utility.log(pilib.dirs.logs.network,
                        'SSID ' + auth['SSID'] + 'found. ', 1,
                        pilib.loglevels.network)
            configdata.data['psk'] = password
            configdata.data['ssid'] = ssid
    return configdata
Ejemplo n.º 37
0
def runboot():
    import subprocess
    from time import sleep

    import pilib
    import spilights
    from iiutilities import utility, dblib, datalib

    try:
        pilib.set_all_wal(False)
    except:
        print('error setting wal mode')

    interfaces = pilib.dbs.control.read_table('interfaces')

    # Clear out status bits, if for no other reason to see the LEDs come on
    for statusvalue in ['systemstatusstatus', 'hamachistatus', 'picontrolstatus', 'updateiostatus', 'serialhandlerstatus' ]:
        dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemstatus', statusvalue, 0)

    systemstatus = dblib.readonedbrow(pilib.dirs.dbs.system, 'systemstatus')[0]


    # Queue a message indicating we are rebooting
    # TODO: Make this an actions option, or put it somewhere.
    # try:
    import socket
    hostname = socket.gethostname()

    message = 'CuPID is booting:\r\n\r\n'
    notifications_email = '*****@*****.**'
    subject = 'CuPID : ' + hostname + ' : booting'
    notification_database = pilib.cupidDatabase(pilib.dirs.dbs.notifications)
    system_database = pilib.cupidDatabase(pilib.dirs.dbs.system)

    currenttime = datalib.gettimestring()
    notification_database.insert('queued',
                                 {'type': 'email', 'message': message,
                                  'options': 'email:' + notifications_email + ',subject:' + subject,
                                  'queuedtime': currenttime})
    system_database.set_single_value('notifications', 'lastnotification', currenttime, condition="item='boot'")

    # except Exception as e:
    #     error_message = 'EXCEPTION in notification: {}'.format(e.message)
    #     print (error_message)
    #     utility.log(pilib.dirs.logs.system, error_message)
    # else:
    #     utility.log(pilib.dirs.logs.system, 'Boot notificaiton complete. ')


    # Start pigpiod

    subprocess.call(['killall','pigpiod'])
    sleep(1)
    utility.log(pilib.dirs.logs.system, 'boot: starting pigpio daemon', 3, pilib.loglevels.system)
    subprocess.call(['/usr/local/bin/pigpiod'])

    # Start webserver

    subprocess.call(['killall','nginx'])
    subprocess.call(['killall','uwsgi'])
    subprocess.call(['killall','apache2'])

    if systemstatus['webserver'] == 'apache':
        utility.log(pilib.dirs.logs.system, 'boot: starting apache', 3, pilib.loglevels.system)
        subprocess.call(['service', 'apache2', 'start'])
    elif systemstatus['webserver'] == 'nginx':
        utility.log(pilib.dirs.logs.system, 'boot: starting nginx', 3, pilib.loglevels.system)
        subprocess.call(['service', 'nginx', 'start'])

    # Run uwsgi daemon if nginx is running

    try:
        result = subprocess.check_output(['service', 'nginx', 'status']).decode('utf-8')
    except subprocess.CalledProcessError as e:
        result = ''
        # print('I AM FAILING')
        # print e.output

    if result:
        utility.log(pilib.dirs.logs.system, 'boot: starting uwsgi based on nginx call', 0)
        subprocess.call(['uwsgi', '--emperor', '/usr/lib/iicontrollibs/wsgi/', '--daemonize', '/var/log/cupid/uwsgi.log'])
    else:
        # print(' I KNOW NGINX IS NOT RUNNING')
        pass
    # Mount 1wire master

    subprocess.call(['killall','owfs'])
    subprocess.call(['killall','owserver'])
    subprocess.call(['killall','owhttpd'])

    runi2cowfs = True
    runusbowfs = False

    temp_unit = 'C'
    for interface in interfaces:
        if interface['enabled']:
            from iiutilities.datalib import parseoptions
            options_dict = parseoptions(interface['options'])
            if 'tempunit' in options_dict:
                if options_dict['tempunit'] in ['F','f','Fahrenheit','fahrenheit']:
                    temp_unit = 'F'

            if interface['interface'] == 'I2C' and interface['type'] == 'DS2483':
                runi2cowfs = True
            if interface['interface'] == 'USB' and interface['type'] == 'DS9490':
                runusbowfs = True

            if interface['interface'] == 'SPI1' and type == 'CuPIDlights':
                spilights.updatelightsfromdb(pilib.dirs.dbs.control, 'indicators', 1)
            if interface['interface'] == 'SPI0' and type == 'CuPIDlights':
                spilights.updatelightsfromdb(pilib.dirs.dbs.control, 'indicators', 0)

    if runi2cowfs or runusbowfs:
        if runi2cowfs:
            utility.log(pilib.dirs.logs.system, 'boot: Running i2c owserver', 3, pilib.loglevels.system)
            try:
                if temp_unit == 'F':
                    subprocess.call(['/opt/owfs/bin/owserver', '-F', '--i2c=/dev/i2c-1:ALL', '-p', '4304'])
                else:
                    subprocess.call(['/opt/owfs/bin/owserver', '--i2c=/dev/i2c-1:ALL', '-p', '4304'])
            except:
                utility.log(pilib.dirs.logs.system, 'boot: error running i2c owserver', 1, pilib.loglevels.system)
        if runusbowfs:
            utility.log(pilib.dirs.logs.system, 'boot: Running usb owserver', 3, pilib.loglevels.system)
            try:
                if temp_unit == 'F':
                    subprocess.call(['/opt/owfs/bin/owserver', '-F', '-u', '-p', '4304'])
                else:
                    subprocess.call(['/opt/owfs/bin/owserver', '-u', '-p', '4304'])
            except:
                utility.log(pilib.dirs.logs.system, 'error running usb owserver', 1, pilib.loglevels.system)

        utility.log(pilib.dirs.logs.system, 'boot: Running owfs/owserver mount', 3, pilib.loglevels.system)
        try:
            if temp_unit == 'F':
                subprocess.call(['/opt/owfs/bin/owfs', '-F', '-s', '4304', '/var/1wire/'])
            else:
                subprocess.call(['/opt/owfs/bin/owfs', '-s', '4304', '/var/1wire/'])
        except:
            utility.log(pilib.dirs.logs.system, 'boot: error running owfs', 1, pilib.loglevels.system)

        utility.log(pilib.dirs.logs.system, 'boot: Running owhttpd/owserver mount', 3, pilib.loglevels.system)
        try:
            if temp_unit == 'F':
                subprocess.call(['/opt/owfs/bin/owhttpd', '-F', '-s', '4304', '-p', '4305'])
            else:
                subprocess.call(['/opt/owfs/bin/owhttpd', '-s', '4304', '-p', '4305'])
        except:
            utility.log(pilib.dirs.logs.system, 'boot: error running owhttpd', 1, pilib.loglevels.system)

    else:
        utility.log(pilib.dirs.logs.system, 'boot: not running owfs', 3, pilib.loglevels.system)

    # Run netstart script if enabled
    if systemstatus['netconfigenabled']:
        from netconfig import runconfig
        utility.log(pilib.dirs.logs.system, 'boot: running boot netconfig', 2, pilib.loglevels.system)
        runconfig(onboot=True)
Ejemplo n.º 38
0
def update_net_status(lastnetstatus=None, quiet=True, ifaces_config=None, netconfig_data=None):

    """
    This function does two main things:

    1. Updates netstatus table. This table contains overall status information, i.e. whether we are attached to WAN,
    hamachi, etc.

    2. Updates netiface_status table (previously netifaces table). This does some contextual stuff like getting wpastate
    info if it makes sense based on mode. Trying to get wpastate data on interfaces that don't matter is not a big deal,
    except that it takes a little time. No need wasting time if the interface is not configured to use wpa.

    3. For interfaces that have a configuration, sets status in netifaces_status based on mode

    """

    import time
    from iiutilities import netfun
    from iiutilities import dblib
    from cupid import pilib
    from iiutilities import utility
    from iiutilities import datalib
    from iiutilities.netfun import getifconfigstatus, getwpaclientstatus

    if not netconfig_data:
        netconfig_data = dblib.readonedbrow(pilib.dirs.dbs.system, 'netconfig')[0]

    if not ifaces_config:

        # Get config data
        ifaces_config = pilib.dbs.system.read_table('netifaceconfig', keyed_dict=True)

        # Unpack config
        for interface_name, element in ifaces_config.items():
            element['config'] = json.loads(element['config'])

    """ 
    We get last netstatus so that we can save last online times, previous online status, etc. 
    """

    if not lastnetstatus:
        try:
            lastnetstatus = dblib.readonedbrow(pilib.dirs.dbs.system, 'netstatus')[0]
        except:
            utility.log(pilib.dirs.logs.system, 'Error reading netstatus. Attempting to recreate netstatus table with default values. ', 1, pilib.loglevels.network)
            try:
                dblib.emptyandsetdefaults(pilib.dirs.dbs.system, 'netstatus')
                lastnetstatus = dblib.readonedbrow(pilib.dirs.dbs.system, 'netstatus')[0]
            except:
                utility.log(pilib.dirs.logs.system, 'Error recreating netstatus. ', 1, pilib.loglevels.network)

    utility.log(pilib.dirs.logs.network, 'Reading ifaces with ifconfig status. ', 4, pilib.loglevels.network)

    # Returns a dictionary, config is unpacked
    ifaces_status = getifconfigstatus()

    """
    We supplement with wpa status on the wlan interfaces if station mode should be set
    Here, we need to decide which interfaces should have a proper wpa status
    """

    for interface_name, this_interface_config in ifaces_config.items():
        this_interface_status = ifaces_status[interface_name]

        # Insert mode into status
        this_interface_status['mode'] = this_interface_config['mode']

        # this_interface_status = json.loads(this_interface_status['config'])
        if this_interface_config['mode'] == 'station':
            this_interface_status['config']['wpastate'] = getwpaclientstatus(interface_name)
        else:
            this_interface_status['config']['wpastate'] = ''

        this_interface_status_result = check_interface_status(this_interface_config, this_interface_status)

        this_interface_status['status'] = this_interface_status_result['status']
        this_interface_status['status_message'] = this_interface_status_result['status_message']


    """ 
    Then write it to the table 
    TODO : Double-check no problems here with not recreating status from scratch (stale data, et.)
    """

    utility.log(pilib.dirs.logs.network, 'Sending ifaces query \n {}. '.format(ifaces_status), 5, pilib.loglevels.network)
        # print(ifacesdictarray)
    this_schema = dblib.sqliteTableSchema([
        {'name':'name', 'primary':True},
        {'name':'config'},
        {'name':'status'},
        {'name':'status_message'},
        {'name':'mode'}
    ])

    pilib.dbs.system.create_table('netifacestatus', schema=this_schema, queue=True)
    from copy import deepcopy
    # print('IFACES')
    # print(ifaces_status)
    for interface_name, interface in ifaces_status.items():
        insert = deepcopy(interface)

        # Pack up the interface configuration data
        try:
            insert['config'] = json.dumps(interface['config'])
        except:
            print('error with interface {}'.format(interface_name))
            print(interface)

        pilib.dbs.system.insert('netifacestatus', insert, queue=True)

    """ Now we check to see if we can connect to WAN """

    utility.log(pilib.dirs.logs.network, 'Checking pingtimes. ', 4, pilib.loglevels.network)
    okping = float(netconfig_data['pingthreshold'])

    pingresults = netfun.runping('8.8.8.8', quiet=quiet)

    # pingresults = [20, 20, 20]
    pingresult = sum(pingresults) / float(len(pingresults))

    if pingresult == 0:
        wanaccess = 0
        latency = 0
    else:
        latency = pingresult
        if pingresult < okping:
            wanaccess = 1
            pilib.dbs.system.set_single_value('netstatus', 'WANaccess', 1, queue=True)
            if lastnetstatus['WANaccess'] == 0 or not lastnetstatus['onlinetime']:
                lastnetstatus['onlinetime'] = datalib.gettimestring()

        else:
            wanaccess = 0

    if not wanaccess:
        dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'WANaccess', 0)
        if lastnetstatus['WANaccess'] == 1 or not lastnetstatus['offlinetime']:
            lastnetstatus['offlinetime'] = datalib.gettimestring()

    # we set all the values here, so when we retreive it we get changed and also whatever else happens to be there.
    lastnetstatus['latency'] = latency
    lastnetstatus['updatetime'] =  datalib.gettimestring()
    lastnetstatus['WANaccess'] = wanaccess

    # pilib.dbs.system.insert('netstatus', lastnetstatus, queue=True)

    utility.log(pilib.dirs.logs.network, 'Done checking pings. ', 4, pilib.loglevels.network)

    if netconfig_data['netstatslogenabled']:
        # print('going to log stuff')
        dblib.logtimevaluedata(pilib.dirs.dbs.log, 'system_WANping', time.time(), pingresult, 1000,
                               netconfig_data['netstatslogfreq'])

    #This is kinda ugly. Should be fixed.
    # netstatusdict = {'WANaccess':wanaccess, 'latency': latency, 'updatetime': updatetime}

    pilib.dbs.system.execute_queue(debug=True)
    return {'netstatusdict': lastnetstatus, 'ifaces_status': ifaces_status, 'ifaces_config':ifaces_config,
            'netconfig_data':netconfig_data}
Ejemplo n.º 39
0
def watchdognetstatus(allnetstatus={}):

    from iiutilities import utility
    from cupid import pilib
    from iiutilities import datalib
    from cupid import netconfig
    from iiutilities import dblib

    """
    And now comes the checking of configuration specific statuses and restarting them if enabled
    and necessary

    We are getting updated status information for each interface. 
    
    We have configuration info for interfaces. We compare the two based on mode and decide if we need to run 
    a netconfig on each interface. We do this by running through, interface by interface on netconfigstatus, and 
    comparing. We then add the name to interfaces we need to reconfig and pass to netconfig().
    
    We ignore interfaces we don't have a config for so we ignore things like hamachi interfaces, loopback, GSM, etc.

    """

    if 'ifaces_config' not in allnetstatus or 'ifaces_status' not in allnetstatus:
        allnetstatus = update_net_status()

    netconfig_data = allnetstatus['netconfig_data']
    netstatus = allnetstatus['netstatusdict']
    ifaces_config = allnetstatus['ifaces_config']
    ifaces_status = allnetstatus['ifaces_status']


    statusmsg = ''
    currenttime = datalib.gettimestring()

    reconfig_interfaces = []
    for iface_name, iface_status in ifaces_status.items():
        utility.log(pilib.dirs.logs.network, 'Checking status of interface {}. '.format(iface_name, 3, pilib.loglevels.network))
        if iface_status['status'] == 'fail':
            reconfig_interfaces.append(iface_name)
            utility.log(pilib.dirs.logs.network,
                'Interface has fail status. Setting reconfig for {}. '.format(iface_name, 1, pilib.loglevels.network))


    # 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

    run_WAN_reconfig = False
    if netconfig_data['requireWANaccess']:
        utility.log(pilib.dirs.logs.network, 'Requiring WAN access. Checking status and times. ', 3, pilib.loglevels.network)
        # print('NETSTATUS')
        # print(netstatus)
        if not netstatus['WANaccess']:
            utility.log(pilib.dirs.logs.network, 'No WANaccess. Checking offline time. ', 2, pilib.loglevels.network)
            try:
                offlinetime = netstatus['offlinetime']
            except:
                # print('netstatus ERROR')
                utility.log(pilib.dirs.logs.network, 'Error getting offlinetime. ', 2, pilib.loglevels.network)


            offlineperiod = datalib.timestringtoseconds(datalib.gettimestring()) - datalib.timestringtoseconds(offlinetime)

            utility.log(pilib.dirs.logs.network, 'We have been offline for ' + str(offlineperiod))

            # When did we last restart the network config? Is it time to again?
            timesincelastnetrestart = datalib.timestringtoseconds(
                datalib.gettimestring()) - datalib.timestringtoseconds(netstatus['lastnetreconfig'])

            utility.log(pilib.dirs.logs.network, 'It has been ' + str(timesincelastnetrestart) + ' seconds since we last restarted the network configuration. ')

            # Require that offline time is greater than WANretrytime
            if timesincelastnetrestart > int(netconfig_data['WANretrytime']) and offlineperiod >  int(netconfig_data['WANretrytime']):
                utility.log(pilib.dirs.logs.network, 'We are not online, and it has been long enough, exceeding retry time of ' + str(int(netconfig_data['WANretrytime'])))
                dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'lastnetreconfig', datalib.gettimestring())

                # We do reset the WAN offline time in the reboot sequence, hwoever.

                restarts = int(dblib.getsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'WANaccessrestarts'))
                restarts += 1
                dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'WANaccessrestarts', restarts)

                utility.log(pilib.dirs.logs.network, 'Going to run netconfig to correct WAN access.')
                run_WAN_reconfig = True

            else:
                utility.log(pilib.dirs.logs.network, 'Not yet time to run netconfig to correct WAN access. Retry time set at ' + str(netconfig_data['WANretrytime']))
        else:
            utility.log(pilib.dirs.logs.network, 'WANAccess is fine. ')

    if run_WAN_reconfig:
        # Set bad status in netstatus
        dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'netstate', 0)

        # Set ok time to '' to trigger rewrite next time status is ok
        lastoktime = dblib.getsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'netstateoktime')
        if not lastoktime:
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'netstateoktime', datalib.gettimestring())
        else:
            if netconfig_data['rebootonfail']:
                offlinetime = datalib.timestringtoseconds(datalib.gettimestring()) - datalib.timestringtoseconds(lastoktime)
                if offlinetime > int(netconfig_data['rebootonfailperiod']):

                    # Set to '' so we get another full fail period before rebooting again
                    dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'netstateoktime', '')

                    # Same thing for WAN offline time
                    dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'offlinetime', '')

                    bootcounts = int(dblib.getsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'netrebootcounter'))
                    bootcounts += 1
                    dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'netrebootcounter', str(bootcounts))

                    # Set system flag to reboot
                    utility.log(pilib.dirs.logs.system, 'REBOOTING to try to fix network', 0, pilib.loglevels.system)
                    dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemflags', 'reboot', 1)


        # Figure out which interfaces to restart to fix WAN issues

        for interface_name, interface in ifaces_config.items():
            utility.log(pilib.dirs.logs.network, 'Adding interface {} to reconfig list'.format(interface_name), 1, pilib.loglevels.network)
            if interface['mode'] in ['status', 'station', 'dhcp']:
                reconfig_interfaces.append(interface_name)

    else:
        # Clear bad status in netstatus and set netoktime
        dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'statusmsg', 'Mode appears to be set.')
        dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'netstate', 1)
        dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'netstateoktime', datalib.gettimestring())

    dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'statusmsg', statusmsg)
    if reconfig_interfaces:
        utility.log(pilib.dirs.logs.network, 'Running netreconfig on list: {}'.format(reconfig_interfaces), 1,
                    pilib.loglevels.network)

        netconfig.runconfig(ifaces_to_configure=reconfig_interfaces, config=ifaces_config, config_all=False)
Ejemplo n.º 40
0
def runboot():
    import subprocess
    from time import sleep

    import pilib
    import spilights
    from iiutilities import utility, dblib, datalib

    try:
        pilib.set_all_wal(False)
    except:
        print('error setting wal mode')

    interfaces = pilib.dbs.control.read_table('interfaces')

    # Clear out status bits, if for no other reason to see the LEDs come on
    for statusvalue in [
            'systemstatusstatus', 'hamachistatus', 'picontrolstatus',
            'updateiostatus', 'serialhandlerstatus'
    ]:
        dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemstatus',
                             statusvalue, 0)

    systemstatus = dblib.readonedbrow(pilib.dirs.dbs.system, 'systemstatus')[0]

    # Queue a message indicating we are rebooting
    # TODO: Make this an actions option, or put it somewhere.
    # try:
    import socket
    hostname = socket.gethostname()

    message = 'CuPID is booting:\r\n\r\n'
    notifications_email = '*****@*****.**'
    subject = 'CuPID : ' + hostname + ' : booting'
    notification_database = pilib.cupidDatabase(pilib.dirs.dbs.notifications)
    system_database = pilib.cupidDatabase(pilib.dirs.dbs.system)

    currenttime = datalib.gettimestring()
    notification_database.insert(
        'queued', {
            'type': 'email',
            'message': message,
            'options': 'email:' + notifications_email + ',subject:' + subject,
            'queuedtime': currenttime
        })
    system_database.set_single_value('notifications',
                                     'lastnotification',
                                     currenttime,
                                     condition="item='boot'")

    # except Exception as e:
    #     error_message = 'EXCEPTION in notification: {}'.format(e.message)
    #     print (error_message)
    #     utility.log(pilib.dirs.logs.system, error_message)
    # else:
    #     utility.log(pilib.dirs.logs.system, 'Boot notificaiton complete. ')

    # Start pigpiod

    subprocess.call(['killall', 'pigpiod'])
    sleep(1)
    utility.log(pilib.dirs.logs.system, 'boot: starting pigpio daemon', 3,
                pilib.loglevels.system)
    subprocess.call(['/usr/local/bin/pigpiod'])

    # Start webserver

    subprocess.call(['killall', 'nginx'])
    subprocess.call(['killall', 'uwsgi'])
    subprocess.call(['killall', 'apache2'])

    if systemstatus['webserver'] == 'apache':
        utility.log(pilib.dirs.logs.system, 'boot: starting apache', 3,
                    pilib.loglevels.system)
        subprocess.call(['service', 'apache2', 'start'])
    elif systemstatus['webserver'] == 'nginx':
        utility.log(pilib.dirs.logs.system, 'boot: starting nginx', 3,
                    pilib.loglevels.system)
        subprocess.call(['service', 'nginx', 'start'])

    # Run uwsgi daemon if nginx is running

    try:
        result = subprocess.check_output(['service', 'nginx',
                                          'status']).decode('utf-8')
    except subprocess.CalledProcessError as e:
        result = ''
        # print('I AM FAILING')
        # print e.output

    if result:
        utility.log(pilib.dirs.logs.system,
                    'boot: starting uwsgi based on nginx call', 0)
        subprocess.call([
            'uwsgi', '--emperor', '/usr/lib/iicontrollibs/wsgi/',
            '--daemonize', '/var/log/cupid/uwsgi.log'
        ])
    else:
        # print(' I KNOW NGINX IS NOT RUNNING')
        pass
    # Mount 1wire master

    subprocess.call(['killall', 'owfs'])
    subprocess.call(['killall', 'owserver'])
    subprocess.call(['killall', 'owhttpd'])

    runi2cowfs = True
    runusbowfs = False

    temp_unit = 'C'
    for interface in interfaces:
        if interface['enabled']:
            from iiutilities.datalib import parseoptions
            options_dict = parseoptions(interface['options'])
            if 'tempunit' in options_dict:
                if options_dict['tempunit'] in [
                        'F', 'f', 'Fahrenheit', 'fahrenheit'
                ]:
                    temp_unit = 'F'

            if interface['interface'] == 'I2C' and interface[
                    'type'] == 'DS2483':
                runi2cowfs = True
            if interface['interface'] == 'USB' and interface[
                    'type'] == 'DS9490':
                runusbowfs = True

            if interface['interface'] == 'SPI1' and type == 'CuPIDlights':
                spilights.updatelightsfromdb(pilib.dirs.dbs.control,
                                             'indicators', 1)
            if interface['interface'] == 'SPI0' and type == 'CuPIDlights':
                spilights.updatelightsfromdb(pilib.dirs.dbs.control,
                                             'indicators', 0)

    if runi2cowfs or runusbowfs:
        if runi2cowfs:
            utility.log(pilib.dirs.logs.system, 'boot: Running i2c owserver',
                        3, pilib.loglevels.system)
            try:
                if temp_unit == 'F':
                    subprocess.call([
                        '/opt/owfs/bin/owserver', '-F', '--i2c=/dev/i2c-1:ALL',
                        '-p', '4304'
                    ])
                else:
                    subprocess.call([
                        '/opt/owfs/bin/owserver', '--i2c=/dev/i2c-1:ALL', '-p',
                        '4304'
                    ])
            except:
                utility.log(pilib.dirs.logs.system,
                            'boot: error running i2c owserver', 1,
                            pilib.loglevels.system)
        if runusbowfs:
            utility.log(pilib.dirs.logs.system, 'boot: Running usb owserver',
                        3, pilib.loglevels.system)
            try:
                if temp_unit == 'F':
                    subprocess.call(
                        ['/opt/owfs/bin/owserver', '-F', '-u', '-p', '4304'])
                else:
                    subprocess.call(
                        ['/opt/owfs/bin/owserver', '-u', '-p', '4304'])
            except:
                utility.log(pilib.dirs.logs.system,
                            'error running usb owserver', 1,
                            pilib.loglevels.system)

        utility.log(pilib.dirs.logs.system,
                    'boot: Running owfs/owserver mount', 3,
                    pilib.loglevels.system)
        try:
            if temp_unit == 'F':
                subprocess.call(
                    ['/opt/owfs/bin/owfs', '-F', '-s', '4304', '/var/1wire/'])
            else:
                subprocess.call(
                    ['/opt/owfs/bin/owfs', '-s', '4304', '/var/1wire/'])
        except:
            utility.log(pilib.dirs.logs.system, 'boot: error running owfs', 1,
                        pilib.loglevels.system)

        utility.log(pilib.dirs.logs.system,
                    'boot: Running owhttpd/owserver mount', 3,
                    pilib.loglevels.system)
        try:
            if temp_unit == 'F':
                subprocess.call([
                    '/opt/owfs/bin/owhttpd', '-F', '-s', '4304', '-p', '4305'
                ])
            else:
                subprocess.call(
                    ['/opt/owfs/bin/owhttpd', '-s', '4304', '-p', '4305'])
        except:
            utility.log(pilib.dirs.logs.system, 'boot: error running owhttpd',
                        1, pilib.loglevels.system)

    else:
        utility.log(pilib.dirs.logs.system, 'boot: not running owfs', 3,
                    pilib.loglevels.system)

    # Run netstart script if enabled
    if systemstatus['netconfigenabled']:
        from netconfig import runconfig
        utility.log(pilib.dirs.logs.system, 'boot: running boot netconfig', 2,
                    pilib.loglevels.system)
        runconfig(onboot=True)
Ejemplo n.º 41
0
def watchdoghamachi(pingip='self', threshold=3000, debug=False, restart=True):
    from iiutilities.netfun import runping, restarthamachi, killhamachi, gethamachistatusdata
    from iiutilities import utility
    from iiutilities import dblib
    from cupid import pilib

    if debug:
        pilib.set_debug()

    try:
        # if this throws an error, it means that there is not a valid status
        hamachistatusdata = gethamachistatusdata()
    except:
        import traceback
        error_message = traceback.format_exc()
        print(error_message)
        utility.log(pilib.dirs.logs.network, 'Error checking Hamachi via gethamachistatusdata with message:  {}'.format(error_message), 1,
                pilib.loglevels.network)
        hamachistatusdata = {}

    # We are having some issue with return on hamachi status check. This is not always a reason to restart hamachi
    # We will carry on below and try to ping. if we can ping, we are good. if we need to self ping, this will still
    # Throw errors. BUT, main point is that if we can ping our chosen hamachi address, we are good.

    numpings = 10

    try:

        print('I am here, doing the pings')
        utility.log(pilib.dirs.logs.network,
                    'Trying to ping hamachi gateway ({} pings) ... '.format(numpings), 1,
                    pilib.loglevels.network)

        # So instead, we are going to test with a ping to another member on the network that
        # should always be online. This of course means that we have to make sure that it is, in fact, always
        # online
        if pingip in ['self', 'Self']:
            pingip = hamachistatusdata['address']

        pingtimes = runping(pingip, numpings=numpings, quiet=False)
        pingmax = max(pingtimes)
        pingmin = min(pingtimes)
        pingave = sum(pingtimes)/len(pingtimes)

        # if hamachistatusdata['status'] not in ['logged in']:
        if pingave <= 0 or pingave > threshold:
            utility.log(pilib.dirs.logs.network, 'Pingtime unacceptable: ' + str(pingave) + '. ', 1, pilib.loglevels.network)
            dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemstatus', 'hamachistatus', 0)
            utility.log(pilib.dirs.logs.network, 'Restarting Hamachi. ', 1, pilib.loglevels.network)

            killhamachi()
            restarthamachi()
            utility.log(pilib.dirs.logs.network, 'Completed restarting Hamachi. ', 1, pilib.loglevels.network)

        else:
            if pingmax > threshold or pingmin <= 0:
                utility.log(pilib.dirs.logs.system, 'Hamachi lives, with issues: ' + str(pingtimes), 3, pilib.loglevels.system)
            else:
                dblib.setsinglevalue(pilib.dirs.dbs.system, 'systemstatus', 'hamachistatus', 1)
                utility.log(pilib.dirs.logs.network, 'Hamachi appears fine. ', 3, pilib.loglevels.network)

    except:
        import traceback
        error_message = traceback.format_exc()

        utility.log(pilib.dirs.logs.network, 'Error checking Hamachi (second stage, pings) with message:  {}'.format(error_message), 1, pilib.loglevels.network)

        if restart:
            utility.log(pilib.dirs.logs.network, 'Restarting hamachi:  {}'.format(error_message), 1,
                        pilib.loglevels.network)

            killhamachi()
            restarthamachi()
Ejemplo n.º 42
0
def queue_commands(**kwargs):
    """
    This will check the commands table. If it has not been sent or cleared as acknowledged, we will queue the command
    in the queued items for serial send.

    We pass in the actiondatadict for the optional parameters below. These come from the action when it is queued, or
    from default settings in action.onact() or the defaults below.

    We optionally:
       check to ensure we don't already have queued messages of the same type. This is not typically going to be an
       issue, as messages are dispatched very quickly.

    We increment number of retries and terminate request as aborted if we exceed this.
    """

    settings = {
        'destination': None,
        'message': None,
        'retry_time': 120.0,
        'retries': 10,
        'no_duplicates': True,
    }
    settings.update(kwargs)
    commands = pilib.dbs.motes.read_table('commands')

    for command in commands:
        print('COMMAND {}'.format(command))
        if command['status'] in ['new', 'retrying',
                                 'sending']:  # Redundant status types here?
            message = '~sendmsg;{};;{}'.format(command['destination'],
                                               command['message'])

            queue_command = True
            if not command['senttimes']:
                command['senttimes'] = []

            sent_times = json.loads(command['senttimes'])
            attempts = len(sent_times)
            if attempts >= settings['retries']:
                print('FAIL')
                inc_message = 'Command retries exceeded ({}). '.format(
                    settings['retries'])
                command['status_message'] += inc_message
                utility.log(pilib.dirs.logs.serial, inc_message, 2,
                            pilib.loglevels.serial)
                command['status'] = 'failed'
                queue_command = False
            else:
                print('NOT FAIL')

            if queue_command:

                # Only check to see if existing command contain a duplicate entry if we were going to send it.
                queued_match_commands = pilib.dbs.motes.read_table(
                    'queued', condition="message='{}'".format(message))
                if queued_match_commands:
                    inc_message = 'Message is already queued. '
                    utility.log(pilib.dirs.logs.serial, inc_message, 2,
                                pilib.loglevels.serial)
                    command['status_message'] += inc_message
                    queue_command = False

            if queue_command and sent_times:

                # If no sent times, then we don't need to see how long it's been
                # Now check to see that it is time to retry
                most_recent_sent_time = sent_times[-1]

                print('most recent time: '.format(most_recent_sent_time))
                elapsed_time = datalib.mstimestringtoseconds(
                    datalib.getmstimestring()) - datalib.mstimestringtoseconds(
                        most_recent_sent_time)
                print('it has been : {}'.format(elapsed_time))

                if elapsed_time > settings['retry_time']:
                    inc_message = 'It has been {}, longer than retry time of {}. Retrying. '.format(
                        elapsed_time, settings['retry_time'])

                else:
                    inc_message = 'It has been {}, not greater than retry time of {}. '.format(
                        elapsed_time, settings['retry_time'])
                    queue_command = False

                utility.log(pilib.dirs.logs.serial, inc_message, 2,
                            pilib.loglevels.serial)

            if queue_command:
                sent_times.append(datalib.getmstimestring())
                command['senttimes'] = json.dumps(sent_times)

                pilib.dbs.motes.insert('queued', {
                    'queuedtime': datalib.getmstimestring(),
                    'message': message
                },
                                       queue=True)
                command['status'] = 'retrying'

            # Update message regardless
            print('\n **INSERTING COMMAND (queued:{}) \n {}\n\n'.format(
                queue_command, command))

            pilib.dbs.motes.insert('commands', command)

        if pilib.dbs.motes.queued_queries:
            pilib.dbs.motes.execute_queue()
Ejemplo n.º 43
0
def runowfsupdate(execute=True, **kwargs):
    import time
    from iiutilities import utility

    settings = {
        'logpath':None,
        'owfsdir':'/var/1wire',
        'loglevel':1
    }
    settings.update(kwargs)

    queries = []
    if settings['logpath']:
        utility.log(settings['logpath'], 'getting buses', 9, settings['loglevel'])

    starttime = time.time()
    # busdevices = owfsgetbusdevices(settings['owfsdir'])
    # Try using pyownet. No point in parsing directories manually, as far as I can tell.
    proxy, busdevices = getowbusdevices()

    utility.log(settings['logpath'], 'done getting devices, took ' + str(time.time() - starttime), 9, settings['loglevel'])
    utility.log(settings['logpath'], 'updating device data', 9, settings['loglevel'])

    starttime = time.time()
    updateddevices = updateowfsdevices(busdevices, proxy)

    utility.log(settings['logpath'], 'done reading devices, took ' + str(time.time() - starttime), 9, settings['loglevel'])
    utility.log(settings['logpath'], 'your devices: ', 9, settings['loglevel'])

    for device in busdevices:
        utility.log(settings['logpath'], device.id)

    utility.log(settings['logpath'], 'updating entries in owfstable', 9, settings['loglevel'])
    starttime = time.time()

    owfstableentries = updateowfstable(settings['logpath'], 'owfs', updateddevices, execute=execute)

    utility.log(settings['logpath'], 'done updating owfstable, took ' + str(time.time() - starttime), 9, settings['loglevel'])

    owfsinputentries = updateowfsinputentries(settings['logpath'], 'inputs', updateddevices, execute=execute)

    queries.extend(owfstableentries)
    queries.extend(owfsinputentries)

    return busdevices, queries
Ejemplo n.º 44
0
def setsinglecontrolvalue(database, table, valuename, value, condition=None):
    from iiutilities.datalib import gettimestring
    from iiutilities import dblib
    from iiutilities import utility

    if table == 'channels':
        utility.log(dirs.logs.control, "Table: " + table + " found in keywords", 4, loglevels.control)

        if valuename in ['setpointvalue']:
            utility.log(dirs.logs.control, "Set value: " + valuename + " found in keywords", 4, loglevels.control)

            # Get the channel data
            try:
                channeldata = dblib.readonedbrow(dirs.dbs.control, 'channels', condition=condition)[0]
            except:
                utility.log(dirs.logs.control, "error retrieving channel with condition " + condition, 1, loglevels.control)
            else:
                utility.log(dirs.logs.control, "Channel retrieval went ok with " + condition, 1, loglevels.control)

                """
                This all needs to go into the picontrol section
                Set a pending value in modify channel, then picontrol processes pending setpoint

                """
                if channeldata['type'] == 'remote' and channeldata['enabled']:
                    # Process setpointvalue send for remote here to make it as fast as possible.
                    # First we need to identify the node and channel by retrieving the interface

                    channelname = channeldata['name']
                    utility.log(dirs.logs.control, "Processing remote setpoint for channel " + channelname, 1, loglevels.io)

                    # Then go to the interfaces table to get the node and channel addresses
                    address = dblib.getsinglevalue(dirs.dbs.control, 'interfaces', 'address', condition ="name='" + channelname + "'")
                    utility.log(dirs.logs.control, "Channel has address " + address, 1, loglevels.io)

                    node = address.split(':')[0]
                    channel = address.split(':')[1]

                    # If it's local, we send the command to the controller directly
                    if int(node) == 1:
                        message = '~setsv;' + channel + ';' + str(value)

                    # If not, first insert the sendmsg command to send it to the remote node
                    else:
                        message = '~sendmsg;' + node + ';;~setsv;' + channel + ';' + str(value)

                    utility.log(dirs.logs.control, "Sending message: " + message, 1, loglevels.io)


                    # Then queue up the message for dispatch

                    dblib.sqliteinsertsingle(dirs.dbs.motes, 'queued', [gettimestring(), message])

                # get existing pending entry
                pendingvaluelist = []

                pendingentry = dblib.getsinglevalue(database, table, 'pending', condition=condition)
                if pendingentry:
                    try:
                        pendingvaluelist = pendingentry.split(',')
                    except:
                        pendingvaluelist = []

                if valuename in pendingvaluelist:
                    pass
                else:
                    pendingvaluelist.append(valuename)

                pendinglistentry = ','.join(pendingvaluelist)

                dblib.setsinglevalue(database, table, 'pending', pendinglistentry, condition)
        else:
            utility.log(dirs.logs.control, "Set value: " + valuename + " not found in keywords", 4, loglevels.control)

    # carry out original query no matter what
    response = dblib.setsinglevalue(database, table, valuename, value, condition)
    return response
Ejemplo n.º 45
0
def runconfig(**kwargs):
    from iiutilities import utility
    from cupid import pilib
    from iiutilities.datalib import gettimestring
    from iiutilities import dblib
    """
    Interfaces and modes

    Interfaces:         eth0 | wlan0 | wlan1
    Modes:        dhcp|  ok  |  --   |  --
                static|  ok  |  --   |  --

               station|  --  |  ok   |  ok
                    ap|  --  |  ok   |  ok 
    """

    settings = {
        'debug': False,
        'onboot': False,
        'config_all': False,
        'ifaces_to_configure': ['wlan0'],
        'config': {
            'eth0': {
                'enabled': True,
                'mode': 'dhcp'
            },
            'wlan0': {
                'enabled': True,
                'mode': 'station',
                'config': {
                    'network_select': ['name', 'strongest'],
                    'network': 'leHouse'
                }
            }
        },
        'use_default': False
    }
    settings.update(kwargs)
    if settings['debug']:
        pilib.set_debug()

    # Get from database
    # TODO : Used passed configuration data.

    if not settings['use_default']:
        import json
        netiface_config = pilib.dbs.system.read_table('netifaceconfig')

        if not netiface_config:
            message = 'netifaceconfig table empty or not found ! '
            utility.log(pilib.dirs.logs.network, message, 0,
                        pilib.loglevels.network)
            return {'status': 1, 'status_message': message}

        settings['config'] = {}
        for iface_config in netiface_config:
            settings['config'][iface_config['name']] = iface_config

            # unpack json dump of config details
            try:
                settings['config'][
                    iface_config['name']]['config'] = json.loads(
                        iface_config['config'])
            except:
                message = 'Config entry for interface {} is empty or cannot be unpacked as json: {}. '.format(
                    iface_config['name'], iface_config['config'])
                # print(settings['config'][iface_config['name']])
                utility.log(pilib.dirs.logs.network, message, 3,
                            pilib.loglevels.network)

    utility.log(pilib.dirs.logs.network, 'Updating ifconfig file. ', 0,
                pilib.loglevels.network)

    print('MAKING CONFIG FILE WITH CONFIG')
    print(settings['config'])
    make_ifconfig_file(config=settings['config'])

    # For now, we are going to assume that we are only using one wireless interface at most as a network station
    station_interface = None
    for interface_name, interface in settings['config'].items():
        if interface['mode'] == 'station':
            station_interface = interface['name']

    utility.log(pilib.dirs.logs.network,
                'Running network reconfig (setting lastnetreconfig). ', 0,
                pilib.loglevels.network)
    dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'lastnetreconfig',
                         gettimestring())

    try:
        netconfigdata = dblib.readonedbrow(pilib.dirs.dbs.system,
                                           'netconfig')[0]
        if settings['debug']:
            print("NETCONFIG:\n{}".format(netconfigdata))
    except:
        utility.log(pilib.dirs.logs.network, 'Error reading netconfig data. ',
                    0, pilib.loglevels.network)
        return {
            'status': 1,
            'status_message': 'Error reading netconfig data. '
        }
    else:
        utility.log(pilib.dirs.logs.network,
                    'Successfully read netconfig data', 3,
                    pilib.loglevels.network)

    dblib.setsinglevalue(pilib.dirs.dbs.system, 'netstatus', 'mode',
                         netconfigdata['mode'])

    utility.log(pilib.dirs.logs.network, 'Netconfig is enabled', 3,
                pilib.loglevels.network)

    # This will grab the specified SSID and the credentials and update
    # the wpa_supplicant file. At the moment, it also looks to see if the network is available.

    if station_interface:
        utility.log(pilib.dirs.logs.network, 'Updating wpa_supplicant', 3,
                    pilib.loglevels.network)
        updatewpasupplicant(station_interface=station_interface)

    if settings['config_all']:
        utility.log(pilib.dirs.logs.network, 'Configuring all interfaces. ', 3,
                    pilib.loglevels.network)
        settings['ifaces_to_configure'] = [
            interface_name for interface_name in settings['config']
        ]

    for interface_name in settings['ifaces_to_configure']:
        utility.log(pilib.dirs.logs.network,
                    'Configuring interface: {}'.format(interface_name), 3,
                    pilib.loglevels.network)

        if interface_name not in settings['config']:
            message = 'Configuration not present for interface {}. '.format(
                interface_name)
            utility.log(pilib.dirs.logs.network, message, 1,
                        pilib.loglevels.network)
            continue

        this_config = settings['config'][interface_name]
        if settings['debug']:
            print('CONFIG: \n{}'.format(this_config))

        if this_config['mode'] == 'ap':
            killapservices()
            reset_net_iface(interface=interface_name)
            startapservices(interface_name)
        else:
            reset_net_iface(interface=interface_name)

    # Bridges require ipv4 being enabled in /etc/sysctl.conf
    # Here we are going to auto-bridge, but I think we should probably manually specify that the bridge should exist

    mode = None
    if all(interface in settings['config'] for interface in ['eth0', 'wlan0']):
        if settings['config']['wlan0']['mode'] == 'ap':
            mode = 'eth0wlan0bridge'
    if all(interface in settings['config']
           for interface in ['wlan0', 'wlan1']):
        if settings['config']['wlan0']['mode'] == 'dhcp' and settings[
                'config']['wlan1']['mode'] == 'ap':
            mode = 'wlan0wlan1bridge'
    if all(interface in settings['config']
           for interface in ['wlan0', 'wlan1']):
        if settings['config']['wlan1']['mode'] == 'dhcp' and settings[
                'config']['wlan0']['mode'] == 'ap':
            mode = 'wlan1wlan0bridge'

    if mode:
        utility.log(pilib.dirs.logs.network,
                    'Setting bridge for mode {}'.format(mode), 1,
                    pilib.loglevels.network)
        runIPTables(mode)
Ejemplo n.º 46
0
def application(environ, start_response):

    import cgi
    import json

    import os, sys, inspect

    # Set top folder to allow import of modules

    top_folder = os.path.split(
        os.path.realpath(
            os.path.abspath(
                os.path.split(inspect.getfile(inspect.currentframe()))[0])))[0]
    if top_folder not in sys.path:
        sys.path.insert(0, top_folder)

    from cupid import pilib, controllib
    from iiutilities import dblib, utility, datalib

    # post_env = environ.copy()
    # post_env['QUERY_STRING'] = ''
    # post = cgi.FieldStorage(
    #     fp=environ['wsgi.input'],
    #     environ=post_env,
    #     keep_blank_values=True
    # )
    #
    # formname=post.getvalue('name')
    # output = {}
    # output['message'] = 'Output Message: '
    # for k in post.keys():
    #     d[k] = post.getvalue(k)

    try:
        request_body_size = int(environ.get('CONTENT_LENGTH', 0))
    except ValueError:
        request_body_size = 0

    request_body = environ['wsgi.input'].read(request_body_size)
    post = json.loads(request_body.decode('utf-8'))

    output = {}
    output['message'] = ''

    status = '200 OK'
    wsgiauth = True
    authverified = False

    if wsgiauth:
        # Verfiy that session login information is legit: hashed password, with salt and username, match
        # hash stored in database.
        import hashlib

        safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.users)
        if 'username' in post and post['username']:
            output['message'] += 'Session user is ' + post['username'] + '. '
        else:
            output['message'] += 'No session user found. '
            post['username'] = ''

        if post['username']:
            try:
                condition = "name='" + post['username'] + "'"
                user_data = safe_database.read_table_row(
                    'users', condition=condition)[0]
            except:
                output[
                    'message'] += 'Error in user sqlite query for session user "' + post[
                        'username'] + '". '
                output[
                    'message'] += 'Condition: ' + condition + '. Path: ' + pilib.dirs.dbs.safe
                user_data = {'accesskeywords': 'demo', 'admin': False}
            else:
                # Get session hpass to verify credentials
                hashedpassword = post['hpass']
                hname = hashlib.new('sha1')
                hname.update(post['username'])
                hashedname = hname.hexdigest()
                hentry = hashlib.new('md5')
                hentry.update(hashedname + pilib.salt + hashedpassword)
                hashedentry = hentry.hexdigest()
                if hashedentry == user_data['password']:
                    # successful auth
                    output['message'] += 'Password verified. '
                    authverified = True

                    # TODO: implement usermeta
        else:
            # Demo status
            authverified = True
            user_data = {'authlevel': 0}

    else:
        output['message'] += 'WSGI authorization not enabled. '

    if authverified or not wsgiauth:
        output['authorized'] = True

    try:
        action = post['action']
    except KeyError:
        output['message'] = 'no action in request'
        action = ''
    else:
        output['message'] += '{} action keyword found'.format(action)

    if output['authorized'] and action:
        output['action_allowed'] = pilib.check_action_auths(
            action, user_data['authlevel'])
    else:
        output['action_allowed'] = False

    if output['authorized'] and output['action_allowed']:

        output['message'] += 'Found action. '

        if action == 'testdbvn':
            from iiutilities.dblib import dbvntovalue
            try:
                output['data'] = dbvntovalue(post['dbvn'])
            except:
                output['message'] += 'Error in dbvn evaluation. '
                output['data'] = 'error'
            else:
                output['message'] += 'Seems to have worked out. '
        elif action == 'testlogical':
            from iiutilities.datalib import evaldbvnformula
            try:
                output['data'] = evaldbvnformula(post['logical'])
            except:
                output['message'] += 'Error in logical evaluation. '
                output['data'] = 'error'
            else:
                output['message'] += 'Seems to have worked out. '

        elif action == 'testmodule':
            output['message'] += 'Testing module: '
            if 'modulename' in post:
                import cupid.cupidunittests
                output['message'] += post['modulename']
                output['data'] = cupid.cupidunittests.testmodule(
                    post['modulename'])
            else:
                output['message'] += 'Modulename not found. '
        elif action == 'testfunction':
            output['message'] += 'Testing function: '
            if 'testname' in post:
                import cupid.cupidunittests
                output['message'] += post['testname']
                # output['data'] = cupid.tests.testfunction(d['testname'])
                output['data'] = cupid.cupidunittests.testfunction(
                    post['testname'])
                # output['data'] = str(cupid.tests.testfunction('systemstatus'))
            else:
                output['message'] += 'Testname not found. '

        elif action == 'modifychannelalarm':
            controllib.handle_modify_channel_alarm(post, output)
            from cupid.actions import processactions

            # process only this action.
            processactions(name=post['actionname'])

        elif action == 'modifychannel':
            controllib.handle_modify_channel(post, output)

        elif action == 'getalarmscount':
            control_db = dblib.sqliteDatabase(pilib.dirs.dbs.control)
            actions = control_db.read_table('actions')
            output['data'] = {
                'totalalarms': len(actions),
                'channelalarms': 0,
                'activealarms': 0,
                'activechannelalarms': 0
            }
            for action in actions:
                if action['conditiontype'] == 'channel':
                    output['data']['channelalarms'] += 1
                    if action['active']:
                        output['data']['activechannelalarms'] += 1

                if action['active']:
                    output['data']['activealarms'] += 1

        elif action == 'copy_log_to_archive':
            pilib.app_copy_log_to_archive(post, output)

        elif action == 'getlogscount':
            logtablenames = dblib.sqliteDatabase(
                pilib.dirs.dbs.log).get_table_names()
            output['data'] = {'logscount': len(logtablenames)}

        elif action == 'test_action':
            output['message'] += 'Testing action. '
            controldb = dblib.sqliteDatabase(pilib.dirs.dbs.control)
            actiondict = controldb.read_table('actions',
                                              condition='"name"=\'' +
                                              post['actionname'] + "'")[0]
            from cupid.actions import action
            test_action = action(actiondict)
            test_action.test()

        elif action == 'update_network':
            safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.safe)
            safe_database.set_single_value('wireless', 'password',
                                           post['password'],
                                           "SSID='" + post['ssid'] + "'")

        elif action == 'add_network':
            safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.safe)
            insert = {'SSID': post['ssid'], 'auto': 1, 'priority': 1}
            if 'password' in post:
                insert['password'] = post['password']
            safe_database.insert('wireless', insert)

        elif action == 'delete_network':
            safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.safe)
            safe_database.delete('wireless', "SSID='" + post['ssid'] + "'")

        # elif action == 'dump':
        #     # this has to go.
        #     if 'database' in d:
        #         dbpath = pilib.dbnametopath(d['database'])
        #         if dbpath:
        #             if 'tablelist' in d and 'outputfile' in d:
        #                 dbpath = pilib.dbnametopath(d['database'])
        #                 dblib.sqlitedatadump(dbpath, d['tablelist'], d['outputfile'])
        #                 output['message'] = 'data dumped'
        #             elif 'tablename' in d and 'outputfile' in d:
        #                 dblib.sqlitedatadump(dbpath, [d['tablename']], d['outputfile'])
        #                 output['message'] = 'data dumped. '
        #             else:
        #                 output['message'] += 'keys not present for dump. '
        #         else:
        #             output['message'] += 'keys not present for dump. '
        #     else:
        #         output['message'] += 'keys not present for dump. '
        elif action in ['userdelete', 'useradd', 'usermodify']:
            """
            This needs to be consolidate with the other useradd, modify algorithm written already.
            Probably do this when we update the user permissions interface.
            """
            # Ensure that we are authorized for this action
            if action == 'userdelete':
                try:
                    dblib.sqlitequery(
                        pilib.dirs.dbs.users,
                        "delete from users where name='" +
                        post['usertodelete'] + "'")
                except:
                    output['message'] += 'Error in delete query. '
                else:
                    output['message'] += 'Successful delete query. '
            elif action == 'usermodify':

                if 'usertomodify' in post:
                    querylist = []
                    if 'newpass' in post:
                        from pilib import salt
                        # Get session hpass to verify credentials
                        hashedpassword = post['newpass']
                        hname = hashlib.new('sha1')
                        hname.update(post['usertomodify'])
                        hashedname = hname.hexdigest()
                        hentry = hashlib.new('md5')
                        hentry.update(hashedname + salt + hashedpassword)
                        hashedentry = hentry.hexdigest()
                        querylist.append('update users set password='******'" +
                                         post['usertomodify'] + "'")

                    if 'newemail' in post:
                        querylist.append("update users set email='" +
                                         post['newemail'] + "' where name='" +
                                         post['usertomodify'] + "'")
                    if 'newauthlevel' in post:
                        querylist.append("update users set authlevel='" +
                                         post['newauthlevel'] +
                                         "' where name='" +
                                         post['usertomodify'] + "'")

                    try:
                        dblib.sqlitemultquery(pilib.dirs.dbs.users, querylist)
                    except:
                        output[
                            'message'] += 'Error in modify/add query: ' + ",".join(
                                querylist)
                    else:
                        output[
                            'message'] += 'Successful modify/add query. ' + ",".join(
                                querylist)
                else:
                    output['message'] += 'Need usertomodify in query. '
            elif action == 'useradd':
                try:
                    username = post['newusername']
                except:
                    username = '******'
                try:
                    newemail = post['newemail']
                except:
                    newemail = '*****@*****.**'
                try:
                    newauthlevel = post['newauthlevel']
                except:
                    newauthlevel = 0
                    query = "insert into users values(NULL,'" + username + "','','" + newemail + "',''," + str(
                        newauthlevel) + ")"
                try:
                    dblib.sqlitequery(pilib.dirs.dbs.users, query)
                except:
                    output[
                        'message'] += "Error in useradd sqlite query: " + query + ' . '
                else:
                    output['message'] += "Successful query: " + query + ' . '
        elif action == 'getfiletext':
            try:
                filepath = post['filepath']
                if 'numlines' in post:
                    numlines = int(post['numlines'])
                else:
                    numlines = 9999
                output['message'] += 'Using numlines: ' + str(
                    numlines) + ' for read action. '
                if 'startposition' in post:
                    startposition = post['startposition']
                else:
                    startposition = 'end'
                output[
                    'message'] += 'Reading from position ' + startposition + '. '
            except KeyError:
                output[
                    'message'] += 'Sufficient keys for action getfile text do not exist. '
            except:
                output['message'] += 'Uncaught error in getfiletext. '
            else:
                try:
                    file = open(filepath)
                    lines = file.readlines()
                except:
                    output[
                        'message'] += 'Error reading file in getfiletext action. '
                else:
                    output['data'] = []
                    if startposition == 'end':
                        try:
                            output['data'] = datalib.tail(file, numlines)[0]
                        except:
                            output['message'] += 'Error in tail read. '
                    else:
                        linecount = 0
                        for line in lines:
                            linecount += 1
                            if linecount > numlines:
                                break
                            else:
                                output['data'].append(line)
        elif action == 'getmbtcpdata':
            try:
                clientIP = post['clientIP']
                register = post['register']
                length = post['length']
            except KeyError:
                output[
                    'message'] += 'Sufficient keys do not exist for the command. Requires clientIP, register, and length. '
            else:
                from iiutilities.netfun import readMBcodedaddresses
                # try:
                output['response'] = readMBcodedaddresses(
                    clientIP, int(register), int(length))
        elif action == 'queuemessage':
            output['message'] += 'Queue message. '
            if 'message' in post:
                try:
                    dblib.sqliteinsertsingle(
                        pilib.dirs.dbs.motes, 'queuedmessages',
                        [datalib.gettimestring(), post['message']])
                except:
                    import traceback
                    exc_type, exc_value, exc_traceback = sys.exc_info()
                    output[
                        'message'] += 'Error in queue insert query: {}. '.format(
                            traceback.format_exc())
                else:
                    output['message'] += 'Message insert successful'
            else:
                output['message'] += 'No message present. '

        elif action == 'setsystemflag' and 'systemflag' in post:
            database = pilib.dirs.dbs.system
            dblib.setsinglevalue(database, 'systemflags', 'value', 1,
                                 "name=\'" + post['systemflag'] + "'")
        elif action == 'rundaemon':
            from cupiddaemon import rundaemon
            rundaemon()

        # TODO: Eliminate this scary thing.
        elif action == 'setvalue':
            utility.log(pilib.dirs.logs.control, "Setting value in wsgi", 1, 1)

            # we use the auxiliary 'setsinglecontrolvalue' to add additional actions to update
            if all(k in post
                   for k in ('database', 'table', 'valuename', 'value')):
                dbpath = pilib.dbnametopath(post['database'])
                if dbpath:
                    output[
                        'message'] += 'Carrying out setvalue for value ' + post[
                            'valuename'] + ' on ' + post[
                                'table'] + ' in ' + dbpath
                    if 'condition' in post:
                        pilib.setsinglecontrolvalue(dbpath, post['table'],
                                                    post['valuename'],
                                                    post['value'],
                                                    post['condition'])
                    elif 'index' in post:
                        condition = 'rowid= ' + post['index']
                        pilib.setsinglecontrolvalue(dbpath, post['table'],
                                                    post['valuename'],
                                                    post['value'], condition)
                    else:
                        pilib.setsinglecontrolvalue(dbpath, post['table'],
                                                    post['valuename'],
                                                    post['value'])
                else:
                    output[
                        'message'] += 'Problem translating dbpath from friendly name: ' + post[
                            'database']
            else:
                output['message'] += 'Insufficient data for setvalue '
        elif action == 'updateioinfo':
            if all(k in post for k in ['database', 'ioid', 'value']):
                query = dblib.makesqliteinsert('ioinfo',
                                               [post['ioid'], post['value']],
                                               ['id', 'name'])
                try:
                    dblib.sqlitequery(pilib.dirs.dbs.control, query)
                except:
                    output[
                        'message'] += 'Error in updateioinfo query execution: ' + query + '. into database: ' + pilib.dirs.dbs.control
                    output['message'] += 'ioid: ' + post['ioid'] + ' . '
                else:
                    output['message'] += 'Executed updateioinfo query. '
            else:
                output[
                    'message'] += 'Insufficient data for updateioinfo query ! '

        # TODO: properly incorporate and test channel class functions here, and then sub it.
        elif action == 'modify_channel':
            controllib.app_modify_channel(post, output)

        elif action == 'deletechannelbyname' and 'database' in post and 'channelname' in post:
            dbpath = pilib.dbnametopath(post['database'])
            dblib.sqlitequery(
                dbpath, 'delete channelname from channels where name=\"' +
                post['channelname'] + '\"')
        elif action == 'updatecameraimage':
            output['message'] += 'Take camera image keyword. '
            import cupid.camera
            if 'width' in post:
                width = post['width']
            else:
                width = 800
            try:
                values = cupid.camera.takesnap(width=width)
            except:
                output['message'] += 'Error taking image. '
            else:
                output['message'] += 'Appears successful. Path : ' + values[
                    'imagepath'] + '. Timestamp : ' + values['timestamp'] + '. '
                output['data'] = values
        elif action == 'getcurrentcamtimestamp':
            output['message'] += 'getcurrentcamtimestamp keyword found. '
            try:
                with open('/var/www/webcam/images/current.jpg.timestamp') as f:
                    data = f.read()
            except:
                output['message'] += 'Error reading file as requested. '
            else:
                output['data'] = data
        else:
            output[
                'message'] += 'Action keyword present(' + action + '), but not handled. '
    else:
        output[
            'message'] += 'Authentication unsuccessful or action not authorized.'
        status = '401 Not Authorized'

    foutput = json.dumps(output, indent=1)

    response_headers = [('Content-type', 'application/json')]
    start_response(status, response_headers)

    return [foutput]
Ejemplo n.º 47
0
def updateowfsdevices(busdevices, myProxy=None, debug=False):
    from cupid import pilib
    from iiutilities import dblib
    from iiutilities import datalib
    from iiutilities import utility

    # get defaults
    defaults = pilib.dirs.dbs.control.read_table('defaults')
    default_dict={}
    for default_item in defaults:
        default_dict[default_item['valuename']] = default_item['value']

    # get current entries
    previnputs = pilib.dirs.dbs.control.read_table('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):
        # print(device.__dict__)
        if device.sensorid in previnputids:
            try:
                newpollfreq = float(previnputs[previnputids.index(device.sensorid)]['pollfreq'])
            except ValueError:
                device.pollfreq = float(default_dict['inputpollfreq'])
            else:
                if newpollfreq >= 0:
                    device.pollfreq = float(previnputs[previnputids.index(device.sensorid)]['pollfreq'])
                else:
                    device.pollfreq = float(default_dict['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']
            device.log_options = previnputs[previnputids.index(device.sensorid)]['log_options']
        else:
            device.pollfreq = float(default_dict['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

        Not really sure why this is conditional?
        """

        if device.type in ['DS18B20', 'DS1825']:

            # Get name if one exists
            name = dblib.sqlitedatumquery(pilib.dirs.dbs.control, '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 = dblib.sqlitedatumquery(pilib.dirs.dbs.control, 'select id from ioinfo where name=\'' + name + '\'')
                    # print('foundid' + foundid)
                    if foundid:
                        pass
                    else:
                        dblib.sqlitequery(pilib.dirs.dbs.control, dblib.makesqliteinsert('ioinfo', valuelist=[device.sensorid, name],
                                                                                        valuenames=['id', 'name']))
                        break
            device.name = name

            device.time_since_last = datalib.timestringtoseconds(datalib.gettimestring()) - datalib.timestringtoseconds(device.polltime, defaulttozero=True)

            # Is it time to read temperature?
            if device.time_since_last > device.pollfreq:
                utility.log(pilib.dirs.logs.io, 'reading temperature [' + device.name + '][' + device.id + ']' , 9, pilib.loglevels.io)
                device.readprop('temperature', myProxy)
                device.polltime = datalib.gettimestring()
                device.value = device.temperature.decode('utf-8')
            else:
                utility.log(pilib.dirs.logs.io, 'not time to poll', 9, pilib.loglevels.io, )
                # print('not time to poll')

            device.unit = 'F'

        # We update the device and send them back for other purposes.
        busdevices[index] = device

    return busdevices
Ejemplo n.º 48
0
def setrawspilights(enabledlists, CS=1, **kwargs):

    from pilib import dirs, loglevels
    from iiutilities.utility import log
    if 'method' in kwargs:
        method = kwargs['method']
    else:
        method = 'spidev'

    # Notes:
    # Low is on. Cathodes are open drain.
    # This unforunately means we need to initialize
    # to off on start-up. not a huge deal

    spiassignments = []
    for enabledlist in enabledlists:
        bytesum = 0
        for index, bit in enumerate(enabledlist):
            bytesum += bit * (2**index)

        spiassign = 255 - bytesum
        spiassignments.append(spiassign)

    resp = []
    if method == 'spidev':
        try:
            import spidev
        except ImportError:
            log(dirs.logs.system,
                'You have not installed the spidev python package. Exiting.',
                0, loglevels.system)
            exit
        else:
            spi = spidev.SpiDev()
        try:
            spi.open(0, CS)  # Port 0, CS1
            spi.max_speed_hz = 50000
        except:
            log(dirs.logs.system, 'Error raised on spi open. exiting.', 0,
                loglevels.system)
            exit
        else:

            # Transfer bytes
            # print('spi assignments')
            # print(spiassignments)
            resp = spi.xfer2(spiassignments)
            # resp = spi.xfer2(spiassignments)

    elif method == 'pigpio':
        import pigpio
        import array
        if 'piobject' in kwargs:
            pi = kwargs['piobject']
        else:
            pi = pigpio.pi()

        handle = pi.spi_open(0, 50000, 0)

        resp = pi.spi_write(handle, array.array(spiassignments).tostring())
        # print(resp)

    if method == 'pigpio' and 'piobject' not in kwargs:
        pi.stop()

    return resp
Ejemplo n.º 49
0
def monitor(**kwargs):

    settings = {
        'port': None,
        'baudrate': 115200,
        'timeout': 1,
        'checkstatus': True,
        'printmessages': False,
        'debug': True
    }
    settings.update(kwargs)

    if not settings['port']:
        settings['port'] = getsystemserialport()

    import serial
    from iiutilities import datalib, dblib
    from time import mktime, localtime
    from time import sleep

    motes_db = pilib.dbs.motes
    system_db = pilib.dbs.system

    if settings['debug']:
        pilib.set_debug()
    if settings['printmessages']:
        print('Message printing is enabled.')

    data = []

    stringmessage = ''
    seriallog = True
    if seriallog:
        print('serial logging is enabled.')
        logfile = open(pilib.dirs.logs.serial, 'a', 1)
        logfile.write('\n' + datalib.gettimestring() +
                      ": Initializing serial log\n")

    if settings['checkstatus']:
        systemstatus = system_db.read_table_row('systemstatus')[0]
        runhandler = systemstatus['serialhandlerenabled']
        checktime = mktime(localtime())
        checkfrequency = 15  # seconds
        if runhandler:
            utility.log(
                pilib.dirs.logs.io,
                "Starting monitoring of serial port based on check status", 1,
                pilib.loglevels.io)
        else:
            utility.log(
                pilib.dirs.logs.io,
                "Not starting monitoring of serial port. How did I get here?",
                1, pilib.loglevels.serial)
    else:
        runhandler = True

    if runhandler:
        ser = serial.Serial(port=settings['port'],
                            baudrate=settings['baudrate'],
                            timeout=settings['timeout'])
        utility.log(
            pilib.dirs.logs.io,
            "Monitoring serial port {}, settings {}/{}".format(
                ser.name, settings['baudrate'],
                settings['timeout']), 1, pilib.loglevels.serial)
    else:
        utility.log(pilib.dirs.logs.io, 'not monitoring serial port ', 1,
                    pilib.loglevels.serial)
    while runhandler:
        # This reading has to happen faster than the messages come, or they will all be stuck together
        try:
            ch = ser.read(1).decode('utf-8')
            # if ch == '\x0D':
            #     print('carriage return')
            # elif ch == '\x00':
            #     print('null character')

            if len(ch) == 0 or ch == '\x0D':
                utility.log(pilib.dirs.logs.io, 'Time to process message ', 5,
                            pilib.loglevels.serial)

                # rec'd nothing print all
                if len(
                        data
                ) > 1:  # This will avoid processing endline characters and other trash.
                    s = ''
                    for x in data:
                        s += '%s' % x  # ord(x)

                    # clear data

                    data = []
                    # Here for diagnostics
                    # print '%s [len = %d]' % (s, len(data))

                    # now process data
                    # print(s)
                    # print(s.split('\n'))
                    try:
                        utility.log(
                            pilib.dirs.logs.serial,
                            'processing datadict from serial message of length {}'
                            .format(len(data)), 3, pilib.loglevels.serial)
                        datadicts, messages = processserialdata(s)
                    except:
                        import traceback
                        message = "An exception of occurred (line 99): {}".format(
                            traceback.format_exc())
                        utility.log(pilib.dirs.logs.serial, message, 1,
                                    pilib.loglevels.serial)

                    else:
                        for datadict, message in zip(datadicts, messages):
                            if datadict:
                                if (settings['printmessages']):
                                    print("datadict: ")
                                    print(datadict)
                                # print("message: ")
                                # print(message)

                                # publish = False
                                # for k in datadict:
                                #     # print(k + datadict[k])
                                #     if k not in ['nodeid','RX_RSSI']:
                                #         pass
                                # if 'cmd' in datadict:
                                publish = True
                                if publish:
                                    if (settings['printmessages']):
                                        print('publishing message: ')
                                        print(message)
                                    lograwmessages(message)

                                motes_db.size_table('read', **{'size': 1000})
                                try:
                                    processremotedata(datadict, message)
                                except:
                                    import traceback
                                    message = "An exception of occurred (line 184): {}".format(
                                        traceback.format_exc())
                                    utility.log(pilib.dirs.logs.serial,
                                                message, 1,
                                                pilib.loglevels.serial)

                            else:
                                if message and settings['printmessage']:
                                    print('message: \n{}'.format(message))
                                    print(message)

                            # Log message
                            if seriallog:
                                try:
                                    logfile.write(datalib.gettimestring() +
                                                  ' : ' + message + '\n')
                                except:
                                    import traceback
                                    message = "An exception of occurred (line 198): {}".format(
                                        traceback.format_exc())
                                    utility.log(pilib.dirs.logs.serial,
                                                message, 1,
                                                pilib.loglevels.serial)

                else:
                    # no data, let's see if we should send message
                    utility.log(pilib.dirs.logs.serial, 'No data, try sending',
                                1, pilib.loglevels.serial)

                # print('CLEARING DATA !!!')
                data = []
                # try:
                #     utility.log(pilib.dirs.logs.serial, "Attempting send routine", 4, pilib.loglevels.serial)
                # except Exception as e:
                #     template = "An exception of type {0} occured while doing some serial logging. Arguments:\n{1!r}"
                #     message = template.format(type(ex).__name__, ex.args)
                #     print message

                # See if there are messages to send.
                # print('LET US TRY SEND HANDLER')
                try:
                    queue_commands()
                except:
                    import traceback
                    print('ERROR IN QUEUE COMMANDS \n {}'.format(
                        traceback.format_exc()))

                try:
                    runsendhandler(ser)
                except:
                    import traceback
                    template = "An exception of in runsendhandler (line 142): {} .".format(
                        traceback.format_exc())
                    utility.log(pilib.dirs.logs.serial,
                                "Error in send routine: {}".format(template),
                                1, 1)
                # print('SEND HANDLER DONE')

                #
                #     template = "An exception of type {0} occured. Arguments:\n{1!r}"
                #     message = template.format(type(ex).__name__, ex.args)
                #     pilib.log(pilib.dirs.logs.serial, message, 1, 1)

            else:
                # print('DATA NOT ZERO')
                # print(ch)
                data.append(ch)
                stringmessage += str(ch)

            if settings['checkstatus']:
                print('checking status')
                thetime = mktime(localtime())
                if thetime - checktime > checkfrequency:
                    print('checking control status')
                    systemstatus = dblib.readonedbrow(pilib.dirs.dbs.control,
                                                      'systemstatus')[0]
                    runserialhandler = systemstatus['serialhandlerenabled']
                    if runserialhandler:
                        checktime = thetime
                        utility.log(
                            pilib.dirs.logs.io,
                            'Continuing serialhandler based on status check',
                            3, pilib.loglevels.io)
                    else:
                        runhandler = False
                        utility.log(
                            pilib.dirs.logs.io,
                            'Aborting serialhandler based on status check', 3,
                            pilib.loglevels.io)
        except KeyboardInterrupt:
            print('\n Exiting on keyboard interrupt\n')
            logfile.close()
            return
        except:
            # print('no characters available!')
            sleep(0.5)
        #     return
        #runsendhandler(ser)

    logfile.close()
    ser.close()
    return
Ejemplo n.º 50
0
 def log(self, message, reqloglevel=1, currloglevel=1):
     from iiutilities.utility import log
     if self.log_path:
         log(self.log_path, message, reqloglevel, currloglevel)
Ejemplo n.º 51
0
def setrawspilights(enabledlists, CS=1, **kwargs):

    from pilib import dirs, loglevels
    from iiutilities.utility import log
    if 'method' in kwargs:
        method = kwargs['method']
    else:
        method = 'spidev'

    # Notes:
    # Low is on. Cathodes are open drain.
    # This unforunately means we need to initialize
    # to off on start-up. not a huge deal

    spiassignments = []
    for enabledlist in enabledlists:
        bytesum = 0
        for index, bit in enumerate(enabledlist):
            bytesum += bit * (2 ** index)

        spiassign = 255 - bytesum
        spiassignments.append(spiassign)

    resp = []
    if method == 'spidev':
        try:
            import spidev
        except ImportError:
            log(dirs.logs.system, 'You have not installed the spidev python package. Exiting.', 0, loglevels.system)
            exit
        else:
            spi = spidev.SpiDev()
        try:
            spi.open(0, CS)  # Port 0, CS1
            spi.max_speed_hz = 50000
        except:
            log(dirs.logs.system, 'Error raised on spi open. exiting.', 0, loglevels.system)
            exit
        else:

            # Transfer bytes
            # print('spi assignments')
            # print(spiassignments)
            resp = spi.xfer2(spiassignments)
            # resp = spi.xfer2(spiassignments)

    elif method == 'pigpio':
        import pigpio
        import array
        if 'piobject' in kwargs:
            pi = kwargs['piobject']
        else:
            pi = pigpio.pi()

        handle = pi.spi_open(0, 50000, 0)

        resp = pi.spi_write(handle, array.array(spiassignments).tostring())
        # print(resp)

    if method == 'pigpio' and 'piobject' not in kwargs:
        pi.stop()

    return resp
Ejemplo n.º 52
0
def runperiodicio(**kwargs):

    settings = {'force_run': False, 'run_once': False, 'debug': False, 'quiet':True, 'logerrors':True}
    settings.update(kwargs)

    systemdb = pilib.cupidDatabase(pilib.dirs.dbs.system, **settings)
    logdb = pilib.cupidDatabase(pilib.dirs.dbs.log, **settings)
    controldb = pilib.cupidDatabase(pilib.dirs.dbs.control, **settings)


    if settings['force_run']:
        updateioenabled = True
    else:
        updateioenabled = systemdb.get_single_value('systemstatus', 'updateioenabled')


    if settings['debug']:
        pilib.set_debug()
        settings['quiet'] = False

    if updateioenabled:
        import pigpio
        pi = pigpio.pi()
        io_objects = {}
        first_run = True

    # print("quiet : {}, {}, {} ".format(systemdb.settings['quiet'], logdb.settings['quiet'], controldb.settings['quiet']))

    while updateioenabled:

        utility.log(pilib.dirs.logs.io, 'Running periodicupdateio', 3, pilib.loglevels.io)
        utility.log(pilib.dirs.logs.system, 'Running periodicupdateio', 3, pilib.loglevels.system)

        # Set last run time
        systemdb.set_single_value('systemstatus', 'lastupdateiopoll', datalib.gettimestring())
        systemdb.set_single_value('systemstatus', 'updateiostatus', '1')

        # Read and record everything as specified in dirs.dbs.control
        # Update database of inputs with read data

        # DEBUG
        runupdate = True
        if runupdate:
            try:
                reply = updateio.updateiodata(piobject=pi, io_objects=io_objects, first_run=first_run, settings=settings)
            except:
                import traceback
                formatted_lines = traceback.format_exc().splitlines()

                error_mail = utility.gmail()
                import socket
                hostname = socket.gethostname()
                error_mail.subject = 'Error running ioupdate on host ' + hostname + '. '
                error_mail.message = error_mail.subject + ' Traceback: ' + '\n'.join(formatted_lines)
                error_mail.send()

        else:
            utility.log(pilib.dirs.logs.io, 'DEBUG: Update IO disabled', 1, pilib.loglevels.io)
            utility.log(pilib.dirs.log.system, 'DEBUG: Update IO disabled', 1, pilib.loglevels.system)

        systemsdict = systemdb.read_table_row('systemstatus')[0]

        readtime = systemsdict['updateiofreq']

        """
        Defaults.
        TODO: We need to get these from a db entry that the user can set on the main control panel. These will live in
        the 'defaults' table. Imagine that.

        Then, we can set the logpoints for each input and channel. We'll store them in the ioinfo table
        """

        plotpoints = 20
        logpoints = 1000

        try:
            logsettings = logdb.read_table('logsettings')
            for setting in logsettings:
                if setting['item'] == 'defaultlogpoints':
                    logpoints = int(setting['value'])
                    # print('logpoints found and set to ' + str(logpoints))
        except:
            pass
            # print('not found or other error. oops. ')

        """
        Update process_values in channels
        """

        channels = controldb.read_table('channels')
        for channel in channels:
            # Get pv_input for each channel
            channelname = channel['name']
            pv_input = channel['pv_input']

            # Get the input for the name from inputs info
            # Then get the value and readtime from the input if it
            # can be found

            if pv_input and pv_input not in ['none', 'None']:

                values = controldb.get_values('inputs', ['value', 'polltime'], condition="name='" + pv_input + "'")
                if values:
                    process_value = values['value']
                    process_value_time = values['polltime']

                    # Only update channel value if value was found
                    # print('process_value: ', process_value)
                    if process_value or process_value == 0:
                        # print('control value for channel ' + channelname + ' = ' + str(process_value))
                        controldb.set_single_value('channels', 'process_value', str(process_value), "pv_input='" + pv_input + "'", queue=True)
                        # pilib.sqlitequery(pilib.dirs.dbs.control, 'update channels set process_value=' + str(
                        #     process_value) + ' where pv_input = ' + "'" + pv_input + "'")
                        controldb.set_single_value('channels', 'process_value_time', str(process_value_time), "pv_input='" + pv_input + "'", queue=True)
                        # pilib.sqlitequery(pilib.dirs.dbs.control,
                        #                   'update channels set process_valuetime=\'' + controltime + '\' where pv_input = ' + "'" + pv_input + "'")
                else:
                    print('input not found. ')

            else:  # input is empty
                controldb.set_single_value('channels', 'statusmessage', 'No pv_input found', "name='" + channelname + "'", queue=True)

                # disable channel
                #pilib.sqlitequery(dirs.dbs.control,"update channels set enabled=0 where pv_input = \'" + pv_input + "'")

            if channel['sv_input'] and channel['sv_input'] not in ['none', 'None']:

                value = controldb.set_single_value('inputs', 'value', "name='" + channel['sv_input'] + "'", queue=True)

                # Only update channel value if value was found
                if value or value==0:
                    # print('control value for channel ' + channelname + ' = ' + str(process_value))
                    controldb.set_single_value('channels', 'setpoint_value', str(value), "sv_input='" + channel['sv_input'] + "'", queue=True)

            if channel['enabled_input'] and channel['enabled_input'] not in ['none', 'None']:

                value = controldb.set_single_value('inputs', 'value', "name='" + channel['enabled_input'] + "'", queue=True)


                # Only update channel value if value was found
                if value or value==0:
                    # print('control value for channel ' + channelname + ' = ' + str(process_value))
                    controldb.set_single_value('channels', 'enabled', str(value), "enabled_input='" + channel['enabled_input'] + "'", queue=True)

        if controldb.queued_queries:
            controldb.execute_queue()

        """
        Log value into tabled log

        Get data for all sensors online
        """

        inputsdata = controldb.read_table('inputs')
        for inputrow in inputsdata:
            logtablename = 'input_' + inputrow['id'] + '_log'
            utility.log(pilib.dirs.logs.io, 'Logging: ' + logtablename, 5, pilib.loglevels.io)
            # print( 'Logging: ' + logtablename, 5, pilib.loglevels.io)

            if datalib.isvalidtimestring(inputrow['polltime']):
                # Create table if it doesn't exist

                # query = 'create table if not exists \'' + logtablename + '\' ( value real, time text primary key)'
                # print('we are logging')

                log_db = pilib.cupidDatabase(pilib.dirs.dbs.log, **settings)

                # Includes 'if not exists' , so will not overwrite
                log_db.create_table(logtablename, pilib.schema.standard_datalog, dropexisting=False, queue=True)
                # dblib.sqlitequery(pilib.dirs.dbs.log, query)

                # Enter row
                insert = {'time':inputrow['polltime'], 'value':inputrow['value']}
                log_db.insert(logtablename, insert, queue=True)

                # query = dblib.makesqliteinsert(logtablename, [inputrow['value'], inputrow['polltime']],['value', 'time'])
                # dblib.sqlitequery(pilib.dirs.dbs.log, query)

                # print(log_db.queued_queries)
                log_db.execute_queue()

                # Clean log
                log_db.clean_log(logtablename)

                # Size log based on specified size
                log_options = datalib.parseoptions(inputrow['log_options'])
                log_db.size_table(logtablename, **log_options)
            else:
                pass
                # print('invalid poll time')

        """
        log metadata
        """

        pilib.get_and_set_logdb_metadata(pilib.dirs.dbs.log)

        if not settings['run_once']:
            utility.log(pilib.dirs.logs.io, 'Sleeping for ' + str(readtime), 1, pilib.loglevels.io)
            sleep(readtime)
        else:
            break

        if not settings['force_run']:
            # Read from systemstatus to make sure we should be running
            updateioenabled = systemdb.get_single_value('systemstatus', 'updateioenabled')

        # Signal to io reads that we just started.
        first_run = False

    systemdb.set_single_value('systemstatus', 'updateiostatus', '0')