示例#1
0
    def message_loop(self):

        loop_start_at = datetime.now()
        loop_last_print_at = datetime.now()

        while True:
            # Two parts to loop body: 1) look for and handle any
            # incoming messages, and 2) send out any outgoing
            # messages.

            # Hacky flag variables to avoid spinning fast if there is
            # nothing coming in and nothing going out (the common
            # case...)
            no_inputs = True
            no_outputs = True

            #
            # Handle any synthetic messages and loop them back to us.
            #
            if not self.fake_rx_queue.empty():
                no_inputs = False
                msg = self.fake_rx_queue.get()
                self.logger.debug("Received synthetic message")
                # Don't need to confirm checksum as we computed it
                # ourselves!
                self.handle_message(msg)

            #
            # Handle incoming messages.
            #
            if self.serial_interface.wait_for_message_start() == MSG_START:
                no_inputs = False

                msg_ok = True
                try:
                    msg = self.serial_interface.read_next_message()
                except CommException, ex:
                    self.send_nak()
                    self.logger.error(repr(ex))
                    continue

                msg_time = datetime.now()

                if len(msg) < 3:
                    # Message too short, need at least length byte,
                    # command byte, and checksum byte.
                    self.send_nak()
                    self.logger.error("Message too short: %r" %
                                      encode_message_to_ascii(msg))

                if validate_message_checksum(msg):
                    self.send_ack()
                    self.handle_message(msg)
                else:
                    # Bad checksum
                    self.send_nak()
                    self.logger.error("Bad checksum for message %r" %
                                      encode_message_to_ascii(msg))

            # TODO: check here if there is pending input and handle it
            # by looping again, before worrying about sending out any
            # commands.

            #
            # If there is a pending message awaiting ack, see if it needs
            # to be resent.  If there is no pending message (or the
            # pending message timed-out), send what's on the transmit
            # queue.
            #
            if self.tx_pending is not None and self.tx_timeout_exceded():
                no_outputs = False
                self.maybe_resend_message("timeout")
            if self.tx_pending is None and not self.tx_queue.empty():
                no_outputs = False
                msg = self.tx_queue.get()
                if msg == STOP:
                    # Close the serial port once all the pending
                    # messages have been sent.  Because we close it,
                    # we can't rerun message_loop(); we have to create
                    # a new AlarmPanelInterface instance.
                    self.serial_interface.close()
                    return
                self.send_message(msg)

            # If there was nothing to do on this pass through the
            # loop, take a nap...
            if no_inputs and no_outputs:
                time.sleep(self.timeout_secs)

            secs_since_print = total_secs(datetime.now() - loop_last_print_at)
            if secs_since_print > 20:
                self.logger.debug_verbose("Looping %d" % \
                                              total_secs(datetime.now() - loop_start_at))
                loop_last_print_at = datetime.now()
示例#2
0
 def tx_timeout_exceded(self):
     assert self.tx_pending is not None
     elapsed = datetime.now() - self.tx_time
     return total_secs(elapsed) > ACK_TIMEOUT_INBOUND