예제 #1
0
def invoke_callback(channel):

    """Invoke Callback"""

    try:

        HUB_LOGGER.info("Impulse Callback from pin %s", channel)

        # Only one impulse per pin allowed,
        #     so we can lookup the impulse from pin number

        # Establish database Connection
        conn = hub_connect.get_connection()
        # Create cursor - needed for any database operation
        cur = hub_connect.get_cursor(conn)

        select_sql = 'SELECT * from "Impulse" WHERE "BCMPinNumber" = %s'
        cur.execute(select_sql, (channel, ))

        # Read result
        impulse = cur.fetchone()

        if cur.rowcount == 1:

            HUB_LOGGER.info("Impulse Button Detected for pin %s", channel)

            create_event(conn, cur, impulse)

    except Exception:
        HUB_LOGGER.error("Unable to invoke impulse callback")
        etype = sys.exc_info()[0]
        value = sys.exc_info()[1]
        trace = sys.exc_info()[2]
        line = trace.tb_lineno
        HUB_LOGGER.error("%s %s %s", etype, value, line)
예제 #2
0
def toggle_actuator(state, agent, method_params, email_recipient,
                    text_recipient):
    """this action is simply to set the actuator state

       to the negation of the incoming state"""

    try:

        actuator_id = int(method_params[0])

        # need to ignore incoming state and re-read the actuator state!

        # Establish database Connection

        conn = hub_connect.get_connection()

        # Create cursor - needed for any database operation

        cur = hub_connect.get_cursor(conn)

        select_sql = 'SELECT * from "Actuator" WHERE "ActuatorID" = %s'

        # Read result

        cur.execute(select_sql, (actuator_id, ))

        actuator = cur.fetchone()

        if actuator is not None:

            cur_val = actuator.get('CurrentValue')

            HUB_LOGGER.info(
                "In toggle_actuator reading %s current value as %s",
                actuator_id, cur_val)

            state = (float(cur_val) > 0.0)

            HUB_LOGGER.info("In toggle_actuator reading state as %s", state)

            new_state = not state  # toggle

            HUB_LOGGER.info("In toggle_actuator using new state %s", new_state)

            do_action(new_state, actuator_id, agent, 'toggle_actuator',
                      email_recipient, text_recipient)

        else:

            new_state = False

        return new_state

    except Exception:

        HUB_LOGGER.error("Unable to Toggle Actuator %s %s %s",
                         sys.exc_info()[0],
                         sys.exc_info()[1],
                         sys.exc_info()[2].tb_lineno)
예제 #3
0
def truncate_samples():
    """Truncate Samples"""

    try:

        # Establish database Connection

        conn = hub_connect.get_connection()

        # Create cursor - needed for any database operation

        cur = hub_connect.get_cursor(conn)

        delete_sql1 = ('DELETE FROM "Sample" '
                       'WHERE "Timestamp" < (NOW() - INTERVAL \'1 WEEK\')')

        HUB_LOGGER.info("Truncating Sample Table...")

        cur.execute(delete_sql1)

        conn.commit()

        delete_sql2 = ('DELETE FROM "EventQueue" '
                       'WHERE "Timestamp" < (NOW() - INTERVAL \'1 WEEK\')')

        HUB_LOGGER.info("Truncating EventQueue Table...")

        cur.execute(delete_sql2)

        conn.commit()

        # Close communication with the database

        cur.close()

        conn.close()

    except Exception:

        HUB_LOGGER.error("Unable to truncate samples")

        etype = sys.exc_info()[0]

        value = sys.exc_info()[1]

        trace = sys.exc_info()[2]

        line = trace.tb_lineno

        HUB_LOGGER.error("%s %s %s", etype, value, line)
예제 #4
0
def arp_detected(mac):

    """ARP packet detected"""

    HUB_LOGGER.debug("ARP Request Detected : %s", mac)

    # Query Impulse for this mac address
    # Establish database Connection
    conn = hub_connect.get_connection()
    # Create cursor - needed for any database operation
    cur = hub_connect.get_cursor(conn)
    select_sql = 'SELECT * from "Impulse" WHERE "MacAddress" = %s'
    cur.execute(select_sql, (mac, ))

    # Read result
    impulse = cur.fetchone()

    if cur.rowcount == 1:

        HUB_LOGGER.info("Dash ARP Request Detected for %s", mac)

        create_event(conn, cur, impulse)
예제 #5
0
def process_actuators():
    """Process Actuators"""

    try:

        # Establish database Connection

        conn = hub_connect.get_connection()

        # Create cursor - needed for any database operation

        cur = hub_connect.get_cursor(conn)

        select_sql = 'SELECT * from "vwActuators" ORDER BY "ActuatorID"'

        cur.execute(select_sql)

        # Read results into python list

        actuators = cur.fetchall()

        # uncomment to debug

        # print_actuators(actuators)

        HUB_LOGGER.debug("Processing actuators...")

        for actuator in actuators:

            actuator_id = int(actuator.get('ActuatorID'))

            HUB_LOGGER.debug("Processing actuator %d", actuator_id)

            cur_val = float(actuator.get('CurrentValue'))

            # Use computed method for actuators for this version

            # Actuator Function may include additional parameters,

            # so pass them as list

            # e.g. remote.130.5

            # {function.subnet_host.id} => function([subnet_host, id])

            actuator_function = actuator.get('ActuatorFunction')

            if actuator_function is not None:

                method_params = actuator_function.split('.')

                HUB_LOGGER.debug("method_params: %s", method_params)

                method_to_call = method_params.pop(0)

                HUB_LOGGER.debug("method_to_call: %s", method_to_call)

                method_exists = hasattr(actuator_helpers, method_to_call)

                HUB_LOGGER.debug("%s method exists: %s", method_to_call,
                                 method_exists)

                if method_exists:

                    # method_to_call = 'SimpleOnOff'

                    method = getattr(actuator_helpers, method_to_call)

                    result = method(cur_val, method_params)

                    HUB_LOGGER.debug("%f => %s", cur_val, result)

                else:

                    HUB_LOGGER.error("Missing Function: %s", method_to_call)

            else:

                HUB_LOGGER.error(
                    "Missing Function Specification for Actuator: %s",
                    actuator_id)

        # Close communication with the database

        cur.close()

        conn.close()

    except Exception:

        HUB_LOGGER.error("Unable to process actuators %s %s %s",
                         sys.exc_info()[0],
                         sys.exc_info()[1],
                         sys.exc_info()[2].tb_lineno)
예제 #6
0
def do_action(state, actuator_id, agent, action, email_recipient,
              text_recipient):
    """Do the Action"""

    HUB_LOGGER.info("In do_action incoming action alerts %s %s %s %s %s",
                    state, actuator_id, action, email_recipient,
                    text_recipient)

    try:

        # Establish database Connection

        conn = hub_connect.get_connection()

        # Create cursor - needed for any database operation

        cur = hub_connect.get_cursor(conn)

        # Update the Actuator only if Current Value has changed!

        upd_sql = ('UPDATE "Actuator" SET "CurrentValue" = %s,'
                   ' "LastUpdated" = CURRENT_TIMESTAMP,'
                   ' "UpdatedBy" = %s WHERE'
                   ' "ActuatorID" = %s AND "IsInAuto" = \'Y\''
                   ' AND "CurrentValue" <> %s;')

        cur.execute(upd_sql, (state * 1, agent, actuator_id, state * 1))

        rows_affected = cur.rowcount

        HUB_LOGGER.debug("Update Actuator qry: [ %s ] Rows Affected: %s",
                         cur.query, rows_affected)

        conn.commit()

        if rows_affected > 0:

            # Look-up the Actuator's Name for the alerts

            read_sql = ('SELECT "ActuatorName" FROM "Actuator" '
                        'WHERE "ActuatorID" = %s')

            # Read result

            cur.execute(read_sql, (actuator_id, ))

            actuator = cur.fetchone()

            act_name = 'UnNamed Actuator'

            if actuator is not None:

                act_name = actuator.get('ActuatorName')

            # Send Alerts?

            if ((email_recipient is not None and email_recipient != '')
                    or (text_recipient is not None and text_recipient != '')):

                send_alert(state, agent, action, email_recipient,
                           text_recipient, act_name)

        # Close communication with the database

        cur.close()

        conn.close()

    except Exception:

        HUB_LOGGER.error("Unable to Do Action %s %s %s",
                         sys.exc_info()[0],
                         sys.exc_info()[1],
                         sys.exc_info()[2].tb_lineno)

    return True
예제 #7
0
def process_samples():

    """Process Samples"""

    try:
        # Establish database Connection
        conn = hub_connect.get_connection()
        # Create cursor - needed for any database operation
        cur = hub_connect.get_cursor(conn)
        select_sql = 'SELECT * from "vwSampleDefs" ORDER BY "SampleDefID"'
        cur.execute(select_sql)
        # Read results into python list
        sample_defs = cur.fetchall()
        print_sample_defs(sample_defs)
        HUB_LOGGER.info("Processing Sample Definitions")
        for sample_def in sample_defs:
            sensor_id = int(sample_def.get('SensorEntryID'))
            cur_val = float(sample_def.get('CurrentValue'))
            method_to_call = sample_def.get('SampleTypeName').lower()
            HUB_LOGGER.debug("method_to_call: %s", method_to_call)
            max_val = sample_def.get('MaxValue')
            min_val = sample_def.get('MinValue')
            HUB_LOGGER.debug(
                "max: %s[%s] min: %s[%s]",
                max_val,
                type(max_val),
                min_val,
                type(min_val)
                )
            method = getattr(sampler_helpers, method_to_call)
            result = method(sensor_id, cur_val)
            HUB_LOGGER.debug(
                "%s => %s[%s]",
                cur_val,
                result,
                type(result)
                )

            # Insert Database with sample value?
            if ((result is not None) and
                (max_val is None or result <= max_val) and
                    (min_val is None or result >= min_val)):
                cur.execute(
                    'INSERT INTO "Sample" ("SensorEntryID","Value")'
                    ' VALUES (%s, %s);',
                    (sensor_id, result))
            else:
                HUB_LOGGER.warning(
                    "Excluding invalid sample from database %s",
                    result)
        conn.commit()

        # Close communication with the database
        cur.close()
        conn.close()

    except Exception:
        HUB_LOGGER.error("Unable to process samples")
        HUB_LOGGER.error("%s %s %s",
                         sys.exc_info()[0],
                         sys.exc_info()[1],
                         sys.exc_info()[2].tb_lineno)
예제 #8
0
def process_rules_from_event_queue(source_type='*', source_id=-1):
    """Process Rules from Event Queue"""

    HUB_LOGGER.debug("Processing Rules From Event Queue for %s %s...",
                     source_type, source_id)

    try:

        # Establish database Connection

        conn = hub_connect.get_connection()

        # Create cursor - needed for any database operation

        cur = hub_connect.get_cursor(conn)

        event_queue_sql = "SELECT * from \"vwEventRuleActions\""

        if source_type != '*' and source_id != -1:

            # Request for specific rules to be processed

            event_queue_sql += (' WHERE "SourceType" = \'' + source_type +
                                '\' AND "SourceID" = ' + str(source_id))

            HUB_LOGGER.info("Processing Rules From Event Queue sql: %s",
                            event_queue_sql)

        cur.execute(event_queue_sql)

        # Read results into python list

        event_rule_actions = cur.fetchall()

        era_count = cur.rowcount

        if era_count > 0:

            HUB_LOGGER.info("Processing %s event rule actions...", era_count)

            for event_rule_action in event_rule_actions:

                process_event_rule_action(conn, cur, event_rule_action)

        # Close communication with the database

        cur.close()

        conn.close()

    except Exception:

        HUB_LOGGER.error("Unable to process rules")

        etype = sys.exc_info()[0]

        value = sys.exc_info()[1]

        trace = sys.exc_info()[2]

        line = trace.tb_lineno

        HUB_LOGGER.error("%s %s %s", etype, value, line)
예제 #9
0
def process_timers():
    """Processes Timers"""

    try:

        # Establish database Connection

        conn = hub_connect.get_connection()

        # Create cursor - needed for any database operation

        cur = hub_connect.get_cursor(conn)

        # Process Actuator Timers

        select_sql = ('SELECT "ActuatorEntryID", "OnForMins", "OffForMins" '
                      'FROM "Actuator"')

        cur.execute(select_sql)

        # Read results into python list

        actuators = cur.fetchall()

        HUB_LOGGER.info("Processing Actuator Timers")

        for act in actuators:

            act_id = int(act.get('ActuatorEntryID'))

            cur_on_val = int(act.get('OnForMins'))

            if cur_on_val >= 0:

                HUB_LOGGER.debug("Incrementing Actuator On Timer %s", act_id)

                cur_on_val = cur_on_val + 1

                # Update Database with current value

                cur.execute(
                    'UPDATE "Actuator" SET "OnForMins" = %s '
                    'WHERE "ActuatorEntryID" = %s;', (cur_on_val, act_id))

                conn.commit()

            else:

                HUB_LOGGER.debug("Ignoring Actuator On Timer %s - Disabled",
                                 act_id)

            cur_off_val = int(act.get('OffForMins'))

            if cur_off_val >= 0:

                HUB_LOGGER.debug("Incrementing Actuator Off Timer %s", act_id)

                cur_off_val = cur_off_val + 1

                # Update Database with current value

                cur.execute(
                    'UPDATE "Actuator" SET "OffForMins" = %s '
                    'WHERE "ActuatorEntryID" = %s;', (cur_off_val, act_id))

                conn.commit()

            else:

                HUB_LOGGER.debug("Ignoring Actuator Off Timer %s - Disabled",
                                 act_id)

        # Close communication with the database

        cur.close()

        conn.close()

    except Exception:

        HUB_LOGGER.error("Unable to process timers")

        etype = sys.exc_info()[0]

        value = sys.exc_info()[1]

        trace = sys.exc_info()[2]

        line = trace.tb_lineno

        HUB_LOGGER.error("%s %s %s", etype, value, line)
예제 #10
0
def check_complex_conditions():
    """Check Complex Conditions"""

    try:

        # Establish database Connection

        conn = hub_connect.get_connection()

        # Create cursor - needed for any database operation

        cur = hub_connect.get_cursor(conn)

        select_sql = ('SELECT * from "vwComplexConditions" '
                      'ORDER BY "ConditionID"')

        cur.execute(select_sql)

        # Read results into python list

        conditions = cur.fetchall()

        print_complex_conditions(conditions)

        select_sql = ('SELECT "SensorID", "CurrentValue" FROM "Sensor" '
                      'ORDER BY "SensorID" DESC')

        cur.execute(select_sql)

        # Read results into python list

        cur_vals = cur.fetchall()

        select_sql = ('SELECT "ActuatorID", "OnForMins", "OffForMins" '
                      'FROM "Actuator"')

        cur.execute(select_sql)

        # Read results into python list

        cur_timers = cur.fetchall()

        HUB_LOGGER.info("Processing Complex Conditions...")

        for condition in conditions:

            HUB_LOGGER.info("-------------------------------")

            check_condition(conn, cur, cur_vals, cur_timers, condition)

        # Close communication with the database

        cur.close()

        conn.close()

    except Exception:

        HUB_LOGGER.error("Unable to process complex conditions")

        etype = sys.exc_info()[0]

        value = sys.exc_info()[1]

        trace = sys.exc_info()[2]

        line = trace.tb_lineno

        HUB_LOGGER.error("%s %s %s", etype, value, line)
예제 #11
0
def initialise(impulse_pins):

    """Initialise"""

    try:

        HUB_LOGGER.info("Initialising impulses wired to physical buttons...")

        # Establish database Connection
        conn = hub_connect.get_connection()
        # Create cursor - needed for any database operation
        cur = hub_connect.get_cursor(conn)

        select_sql = (
            'SELECT * from "Impulse" WHERE "BCMPinNumber" IS NOT NULL'
            ' ORDER BY "ImpulseID"')
        cur.execute(select_sql)

        # Read results into python list
        impulses = cur.fetchall()
        print_impulses(impulses)

        GPIO.setmode(GPIO.BCM)

        cur_impulse_pins = []

        for impulse in impulses:

            impulse_id = int(impulse.get('ImpulseID'))
            pin = int(impulse.get('BCMPinNumber'))
            cur_impulse_pins.append(pin)

            if pin not in impulse_pins:

                # Impulse Switch wired from Pin to Ground
                # Add Pull-Up
                GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

                # Clear any existing
                GPIO.remove_event_detect(pin)
                GPIO.add_event_detect(pin,
                                      GPIO.RISING,
                                      callback=invoke_callback,
                                      bouncetime=2000)

                # Mark Impulse as Initialised
                impulse_pins.append(pin)

                HUB_LOGGER.info("Initialised impulse %s on pin %s",
                                impulse_id, pin)

        ex_impulse_pins = set(impulse_pins) - set(cur_impulse_pins)

        for pin in ex_impulse_pins:
            # Clear any existing
            GPIO.remove_event_detect(pin)
            HUB_LOGGER.info("Decommissioned impulse on pin %s", pin)
            impulse_pins.remove(pin)

    except Exception:
        HUB_LOGGER.error("Unable to initialise impulses")
        etype = sys.exc_info()[0]
        value = sys.exc_info()[1]
        trace = sys.exc_info()[2]
        line = trace.tb_lineno
        HUB_LOGGER.error("%s %s %s", etype, value, line)
예제 #12
0
def process_stats():
    """Process Statistics"""

    try:

        # Establish database Connection

        conn = hub_connect.get_connection()

        # Create cursor - needed for any database operation

        cur = hub_connect.get_cursor(conn)

        select_sql = (
            'SELECT * from "Sensor" s'
            ' INNER JOIN "Measurand" m ON s."MeasurandID" = m."MeasurandID"'
            ' ORDER BY "SensorID"')

        cur.execute(select_sql)

        # Read results into python list

        sensors = cur.fetchall()

        HUB_LOGGER.info("Processing Stats")

        for sensor in sensors:

            sensor_entry_id = int(sensor.get('SensorEntryID'))

            cur_val = float(sensor.get('CurrentValue'))

            meas_max_val = sensor.get('MaxValue')

            meas_min_val = sensor.get('MinValue')

            if meas_max_val is None or meas_max_val >= cur_val:

                HUB_LOGGER.info("Processing Max Stats for sensor %s",
                                sensor_entry_id)

                process_max_min(conn, cur, sensor_entry_id, cur_val, 'Maximum')

            if meas_min_val is None or meas_min_val <= cur_val:

                HUB_LOGGER.info("Processing Min Stats for sensor %s",
                                sensor_entry_id)

                process_max_min(conn, cur, sensor_entry_id, cur_val, 'Minimum')

        # Close communication with the database

        cur.close()

        conn.close()

    except Exception:

        HUB_LOGGER.error("Unable to process statistics")

        etype = sys.exc_info()[0]

        value = sys.exc_info()[1]

        trace = sys.exc_info()[2]

        line = trace.tb_lineno

        trace = traceback.format_exc()

        HUB_LOGGER.error("%s %s %s %s", etype, value, line, trace)
예제 #13
0
def daily_summary():
    """Daily Summary"""

    try:

        # Establish database Connection

        conn = hub_connect.get_connection()

        # Create cursor - needed for any database operation

        cur = hub_connect.get_cursor(conn)

        select_sql = 'SELECT * from "vwTodaysMaximums" ORDER BY "SensorID"'

        cur.execute(select_sql)

        msg_body = ''

        msg_tmplt = '* {0} {1} {2} at {3}\r\n'

        if cur.rowcount > 0:

            # Read results into python list

            maximums = cur.fetchall()

            HUB_LOGGER.info("Processing Daily Maxs")

            msg_body += ('The following highest values'
                         ' have been recorded today:\r\n\r\n')

            for maximum in maximums:

                sensor_title = maximum.get('SensorTitle')

                val = float(maximum.get('Value'))

                units = maximum.get('TextUnits')

                date = datetime.datetime.strftime(maximum.get('Timestamp'),
                                                  '%H:%M %d/%m/%Y')

                msg_body += msg_tmplt.format(sensor_title, val, units, date)

            msg_body += '\r\n'

        select_sql = "SELECT * from \"vwTodaysMinimums\" ORDER BY \"SensorID\""

        cur.execute(select_sql)

        if cur.rowcount > 0:

            # Read results into python list

            minimums = cur.fetchall()

            HUB_LOGGER.info("Processing Daily Mins")

            msg_body += ('The following lowest values'
                         ' have been recorded today:\r\n\r\n')

            for minimum in minimums:

                sensor_title = minimum.get('SensorTitle')

                val = float(minimum.get('Value'))

                units = minimum.get('TextUnits')

                date = datetime.datetime.strftime(minimum.get('Timestamp'),
                                                  '%H:%M %d/%m/%Y')

                msg_body += msg_tmplt.format(sensor_title, val, units, date)

        if msg_body != '':

            HUB_LOGGER.info("Processing Daily Summary: %s", msg_body)

            # Send Email

            subject = ('Daily Highs and Lows from the Hub ' +
                       datetime.datetime.strftime(datetime.datetime.now(),
                                                  '%Y-%m-%d'))

            email_recip = helpers.get_user_setting('AdminRecipient')

            helpers.send_email(msg_body, subject, email_recip)

    except Exception:

        HUB_LOGGER.error("Unable to process daily summary statistics")

        HUB_LOGGER.error("%s %s %s",
                         sys.exc_info()[0],
                         sys.exc_info()[1],
                         sys.exc_info()[2].tb_lineno)
예제 #14
0
def invoke_callback(channel):
    """Invoke Callback"""

    try:

        HUB_LOGGER.info("Impulse Callback from pin %s", channel)

        # Only one impulse per pin allowed,

        #     so we can lookup the impulse from pin number

        # Establish database Connection

        conn = hub_connect.get_connection()

        # Create cursor - needed for any database operation

        cur = hub_connect.get_cursor(conn)

        select_sql = 'SELECT * from "Impulse" WHERE "BCMPinNumber" = %s'

        cur.execute(select_sql, (channel, ))

        # Read results into python list

        impulses = cur.fetchall()

        impulse_id = int(impulses[0].get('ImpulseID'))

        HUB_LOGGER.info("Inserting Impulse Event in Database... %s",
                        impulse_id)

        ins_sql = ('INSERT INTO "EventQueue" '
                   '("SourceID", "SourceType", "SourceAgent", "Value")'
                   'SELECT %s, \'Impulse\', \'Occupant\', 1'
                   'WHERE ('
                   '    SELECT COUNT(*)'
                   '    FROM "EventQueue"'
                   '    WHERE "SourceID" = %s AND'
                   '          "SourceType" = \'Impulse\''
                   '    AND "Timestamp" > '
                   '    current_timestamp - interval \'%s seconds\''
                   ') = 0;')

        cur.execute(ins_sql, (impulse_id, impulse_id, LOCKOUT_SECONDS))

        conn.commit()

        HUB_LOGGER.info("Impulse Update Query... %s", cur.query)

        HUB_LOGGER.info("Updating Impulse Last Updated in Database... %s",
                        impulse_id)

        cur.execute(
            'UPDATE "Impulse" SET "LastUpdated" = CURRENT_TIMESTAMP'
            ' WHERE "ImpulseID" = %s;', (impulse_id, ))

        conn.commit()

    except Exception:

        HUB_LOGGER.error("Unable to invoke impulse callback")

        etype = sys.exc_info()[0]

        value = sys.exc_info()[1]

        trace = sys.exc_info()[2]

        line = trace.tb_lineno

        HUB_LOGGER.error("%s %s %s", etype, value, line)