示例#1
0
class BaseLogger(object):
    """ BaseLogger class receives sensor messages and writes them to
    the database.
    """
    def __init__(self, bif=None, dbfile=DBFILE):
        """ create a new BaseLogger and connect it to the sensor
        source (bif) and the database (dbfile).
        """
        self.engine = create_engine(dbfile, echo=False)
        init_model(self.engine)
        self.metadata = Base.metadata

        if bif is None:
            self.bif = BaseIF("sf@localhost:9002")
        else:
            self.bif = bif

    def create_tables(self):
        """ create any missing tables using sqlalchemy
        """
        self.metadata.create_all(self.engine)
        # TODO: follow the instructions at url:
        # https://alembic.readthedocs.org/en/latest/tutorial.html#building-an-up-to-date-database-from-scratch
        # to write an alembic version string

        session = Session()
        if session.query(SensorType).get(0) is None:
            raise Exception("SensorType must be populated by alembic " +
                            "before starting BaseLogger")
        session.close()    
                             

    def send_ack(self,
                 seq=None,
                 dest=None):
        """ send acknowledgement message
        """
        ack_msg = AckMsg()
        ack_msg.set_seq(seq)
        ack_msg.set_node_id(dest)
        
        self.bif.sendMsg(ack_msg, dest)
        LOGGER.debug("Sending Ack %s to %s" %
                     (seq, dest))


    def store_state(self, msg):
        """ receive and process a message object from the base station
        """
    
        # get the last source 

        if msg.get_special() != Packets.SPECIAL:
            raise Exception("Corrupted packet - special is %02x not %02x" %
                            (msg.get_special(), Packets.SPECIAL))

        try:
            session = Session()
            current_time = datetime.utcnow()
            node_id = msg.getAddr()
            parent_id = msg.get_ctp_parent_id()
            seq = msg.get_seq()

            node = session.query(Node).get(node_id)
            loc_id = None
            if node is None:
                add_node(session, node_id)
            else:
                loc_id = node.locationId


            pack_state = PackState.from_message(msg)
            
            if duplicate_packet(session=session,
                                receipt_time=current_time,
                                node_id=node_id,
                                localtime=msg.get_timestamp()):
                LOGGER.info("duplicate packet %d->%d, %d %s" %
                            (node_id, parent_id, msg.get_timestamp(), str(msg)))

                #send acknowledgement to base station to fwd to node
                self.send_ack(seq=seq,
                              dest=node_id)
                return

            # write a node state row
            node_state = NodeState(time=current_time,
                                   nodeId=node_id,
                                   parent=parent_id,
                localtime=msg.get_timestamp(),
                seq_num=seq)
            session.add(node_state)

            for i, value in pack_state.d.iteritems():
                if (msg.get_amType() == Packets.AM_BNMSG and
                    i not in [Packets.SC_VOLTAGE]):
                    type_id = i + BN_OFFSET   # TODO: ideally should be a flag in datbase or something
                else:
                    type_id = i

                session.add(Reading(time=current_time,
                                    nodeId=node_id,
                                    typeId=type_id,
                                    locationId=loc_id,
                    value=value))

            session.commit()

            #send acknowledgement to base station to fwd to node
            self.send_ack(seq=seq,
                          dest=node_id)
                     
            LOGGER.debug("reading: %s, %s" % (node_state, pack_state))
        except Exception as exc:
            session.rollback()
            LOGGER.exception("during storing: " + str(exc))
        finally:
            session.close()

    def run(self):
        """ run - main loop

        At the moment this is just receiving from the sensor message
        queue and processing the message.

        """

        try:
            while True:
                # wait up to 30 seconds for a message
                try:
                    msg = self.bif.queue.get(True, 30)
                    self.store_state(msg)
                except Empty:
                    pass
                except Exception as exc:
                    LOGGER.exception("during receiving or storing msg: " +
                                     str(exc))

        except KeyboardInterrupt:
            self.bif.finishAll()
示例#2
0
class BaseLogger(object):
    """ BaseLogger class receives sensor messages and writes them to
    the database.
    """
    def __init__(self, bif=None, dbfile=DBFILE):
        """ create a new BaseLogger and connect it to the sensor
        source (bif) and the database (dbfile).
        """
        self.engine = create_engine(dbfile, echo=False)
        init_model(self.engine)
        self.metadata = Base.metadata

        if bif is None:
            self.bif = BaseIF("sf@localhost:9002")
        else:
            self.bif = bif

    def create_tables(self):
        """ create any missing tables using sqlalchemy
        """
        self.metadata.create_all(self.engine)
        # TODO: follow the instructions at url:
        # https://alembic.readthedocs.org/en/latest/tutorial.html#building-an-up-to-date-database-from-scratch
        # to write an alembic version string

        session = Session()
        if session.query(SensorType).get(0) is None:
            raise Exception("SensorType must be populated by alembic " +
                            "before starting BaseLogger")
        session.close()

    def send_ack(self, seq=None, dest=None):
        """ send acknowledgement message
        """
        ack_msg = AckMsg()
        ack_msg.set_seq(seq)
        ack_msg.set_node_id(dest)

        self.bif.sendMsg(ack_msg, dest)
        LOGGER.debug("Sending Ack %s to %s" % (seq, dest))

    def store_state(self, msg):
        """ receive and process a message object from the base station
        """

        # get the last source

        if msg.get_special() != Packets.SPECIAL:
            raise Exception("Corrupted packet - special is %02x not %02x" %
                            (msg.get_special(), Packets.SPECIAL))

        try:
            session = Session()
            current_time = datetime.utcnow()
            node_id = msg.getAddr()
            parent_id = msg.get_ctp_parent_id()
            seq = msg.get_seq()

            node = session.query(Node).get(node_id)
            loc_id = None
            if node is None:
                add_node(session, node_id)
            else:
                loc_id = node.locationId

            pack_state = PackState.from_message(msg)

            if duplicate_packet(session=session,
                                receipt_time=current_time,
                                node_id=node_id,
                                localtime=msg.get_timestamp()):
                LOGGER.info(
                    "duplicate packet %d->%d, %d %s" %
                    (node_id, parent_id, msg.get_timestamp(), str(msg)))

                #send acknowledgement to base station to fwd to node
                self.send_ack(seq=seq, dest=node_id)
                return

            # write a node state row
            node_state = NodeState(time=current_time,
                                   nodeId=node_id,
                                   parent=parent_id,
                                   localtime=msg.get_timestamp(),
                                   seq_num=seq)
            session.add(node_state)

            for i, value in pack_state.d.iteritems():
                if (msg.get_amType() == Packets.AM_BNMSG
                        and i not in [Packets.SC_VOLTAGE]):
                    type_id = i + BN_OFFSET  # TODO: ideally should be a flag in datbase or something
                else:
                    type_id = i

                session.add(
                    Reading(time=current_time,
                            nodeId=node_id,
                            typeId=type_id,
                            locationId=loc_id,
                            value=value))

            session.commit()

            #send acknowledgement to base station to fwd to node
            self.send_ack(seq=seq, dest=node_id)

            LOGGER.debug("reading: %s, %s" % (node_state, pack_state))
        except Exception as exc:
            session.rollback()
            LOGGER.exception("during storing: " + str(exc))
        finally:
            session.close()

    def run(self):
        """ run - main loop

        At the moment this is just receiving from the sensor message
        queue and processing the message.

        """

        try:
            while True:
                # wait up to 30 seconds for a message
                try:
                    msg = self.bif.queue.get(True, 30)
                    self.store_state(msg)
                except Empty:
                    pass
                except Exception as exc:
                    LOGGER.exception("during receiving or storing msg: " +
                                     str(exc))

        except KeyboardInterrupt:
            self.bif.finishAll()