Example #1
0
class Serial(threading.Thread):
    def __init__(self, name=None, baudrate=None, timeout=0.1):
        assert name != None, logger.error("Serial port not defined.")
        assert baudrate != None, logger.error("Serial baudrate not defined.")

        logger.info('init: Creating the Serial object.')

        # Call constructor
        threading.Thread.__init__(self)

        # Terminate thread event
        self.stop_event = threading.Event()

        # Serial port
        self.serial_port = None
        self.name = name
        self.baudrate = baudrate
        self.timeout = timeout

        # HDLC driver
        self.hdlc = Hdlc()

        # Receive variables
        self.receive_buffer = []
        self.receive_message = []
        self.receive_condition = threading.Condition()
        self.is_receiving = False
        self.rx_byte = ''
        self.last_rx_byte = ''

        # Transmit variables
        self.transmit_buffer = []
        self.transmit_message = []
        self.transmit_condition = threading.Condition()

        # Quality control variables
        self.tx_total_frames = 0
        self.tx_good_frames = 0
        self.tx_bad_frames = 0
        self.rx_total_frames = 0
        self.rx_good_frames = 0
        self.rx_bad_frames = 0

        try:
            logger.info(
                "init: Opening the serial port on {} at {} bps.".format(
                    self.name, self.baudrate))
            # Open the serial port
            self.serial_port = serial.Serial(port=self.name,
                                             baudrate=self.baudrate,
                                             timeout=self.timeout)
        except:
            logger.error(
                "init: Error while opening the serial port on {}.".format(
                    self.name))
            raise Exception
        else:
            logger.info("init: Serial object created.")

    # Runs the thread
    def run(self):
        logger.info("run: Starting the Serial.")

        if (self.serial_port == None):
            raise

        # Flush the serial input/ouput
        self.serial_port.flushInput()
        self.serial_port.flushOutput()

        # Execute while thread is alive
        while (not self.stop_event.isSet()):
            rx_bytes = []
            rx_length = 0

            try:
                # Read the number of bytes available
                rx_length = self.serial_port.in_waiting

                # If bytes are available read them
                if (rx_length > 0):
                    logger.debug(
                        "run: Read {} bytes from serial port on {}.".format(
                            rx_length, self.serial_port))

                    # Try to receive a byte from the serial port (blocking)
                    rx_bytes = self.serial_port.read(size=rx_length)

            except:
                logger.error(
                    "run: Error while receiving from the serial port on {}.".
                    format(self.serial_port))
                # Terminate the thread
                self.stop()
                # Break the loop
                break

            # Iterate over received bytes
            for rx_byte in rx_bytes:
                # Recover byte
                self.rx_byte = rx_byte

                # Start of frame
                if ((not self.is_receiving)
                        and (self.last_rx_byte == self.hdlc.HDLC_FLAG)
                        and (self.rx_byte != self.hdlc.HDLC_FLAG)):
                    logger.debug("run: Start of HDLC frame.")

                    self.is_receiving = True
                    self.receive_buffer = []
                    self.receive_buffer.append(self.hdlc.HDLC_FLAG)
                    self.receive_buffer.append(self.rx_byte)

                # Middle of HDLC frame
                elif ((self.is_receiving)
                      and (self.rx_byte != self.hdlc.HDLC_FLAG)):
                    logger.debug("run: Middle of HDLC frame.")

                    self.receive_buffer.append(self.rx_byte)

                # End of HDLC frame
                elif ((self.is_receiving)
                      and (self.rx_byte == self.hdlc.HDLC_FLAG)):
                    logger.debug("run: End of HDLC frame.")

                    # Receive the last byte
                    self.receive_buffer.append(self.rx_byte)

                    # Reset the variables
                    self.is_receiving = False
                    self.last_rx_byte = ''
                    self.rx_byte = ''

                    # Compute statistics
                    self.rx_total_frames += 1

                    try:
                        logger.debug(
                            "run: Received an HDLC frame from the Serial port, now de-HDLCifying it."
                        )

                        # Receive me
                        self.receive_message = self.hdlc.dehdlcify(
                            self.receive_buffer)

                        # Compute statistics
                        self.rx_good_frames += 1
                    except:
                        logger.error(
                            "run: Error while de-HDLCifying the frame received from the Serial port."
                        )

                        # Clean buffers
                        self.receive_buffer = []
                        self.receive_message = []

                        # Compute statistics
                        self.rx_bad_frames += 1

                    else:
                        # Acquire the receive condition
                        self.receive_condition.acquire()

                        # Notify the receive condition
                        self.receive_condition.notify()

                        # Release the transmit condition
                        self.receive_condition.release()

                        # Reset the receive buffer
                        self.receive_buffer = []

                # Always save the last received byte
                self.last_rx_byte = self.rx_byte

            # If no bytes were received, sleep
            if (rx_length == 0):
                # Sleep for a while
                time.sleep(self.timeout)

        # Close the serial port
        self.serial_port.close()

    # Stops the thread
    def stop(self):
        logger.info("stop: Stopping the {} serial port.".format(self.name))

        # Terminates the thread
        self.stop_event.set()

    # Receive a message
    def receive(self, timeout=0.1):
        status = True
        message = []
        length = -1

        # Acquire the lock
        self.receive_condition.acquire()

        # Try to receive a message with timeout
        self.receive_condition.wait(timeout)

        # If we really got a message, copy it!
        if (self.receive_message):
            message = self.receive_message
            length = len(message)

            logger.info(
                "receive: Received a message with {} bytes.".format(length))

        # Reset the receive message
        self.receive_message = []

        # Release the receive condition
        self.receive_condition.release()

        # Get the status of the thread
        status = self.stop_event.isSet()

        # Return the received message and length
        return (message, length)

    # Transmit a message
    def transmit(self, message):
        logger.info(
            "transmit: Got a message to transmit with {} bytes.".format(
                len(message)))

        # Compute statistics
        self.tx_total_frames += 1

        try:
            logger.debug("transmit: HDLCifying the transmit buffer.")

            # HDLCify the message
            self.transmit_buffer = self.hdlc.hdlcify(message)
        except:
            logger.error("transmit: Error HDLCifying the transmit buffer.")
            # Compute statistics
            self.tx_bad_frames += 1
            raise

        try:
            logger.debug("run: Transmitting the message with {} bytes.".format(
                len(self.transmit_buffer)))

            # Send the message through the serial port (blocking)
            self.serial_port.write(self.transmit_buffer)
        except:
            logger.error("transmit: Error transmitting the transmit buffer.")
            # Compute statistics
            self.tx_bad_frames += 1
            raise

        # Compute statistics
        self.tx_good_frames += 1

    def clear_statistics(self):
        self.tx_total_frames = 0
        self.tx_good_frames = 0
        self.tx_bad_frames = 0
        self.rx_total_frames = 0
        self.rx_good_frames = 0
        self.rx_bad_frames = 0

    def get_statistics(self):
        return "TX Total={}, TX Good={}, TX Bad={}, RX Total={}, RX Good={}, RX Bad={}".format(
            self.tx_total_frames, self.tx_good_frames, self.tx_bad_frames,
            self.rx_total_frames, self.rx_good_frames, self.rx_bad_frames)
Example #2
0
class Serial(threading.Thread):
    
    def __init__(self, serial_name = None, baud_rate = None, bsl_mode = None):
        assert serial_name != None, logger.error("Serial port not defined.")
        assert baud_rate   != None, logger.error("Serial baudrate not defined.")
        assert bsl_mode    != None, logger.error("Bootloader mode not defined.")
        
        logger.info('init: Creating the Serial object.')
        
        # Call constructor
        threading.Thread.__init__(self)
        
        # Set thread as daemon
        self.setDaemon(False)
        
        # Terminate thread event
        self.stop_event = threading.Event()
        
        # Serial port
        self.serial_port = None
        self.serial_name = serial_name
        self.baud_rate   = baud_rate
        self.time_out    = 1.0
        self.bsl_mode    = bsl_mode
                
        # HDLC driver
        self.hdlc = Hdlc()
        
        # Receive variables
        self.receive_buffer    = ''
        self.receive_message   = ''
        self.receive_condition = threading.Condition()
        self.is_receiving      = False
        self.last_rx_byte      = 0
        
        # Transmit variables 
        self.transmit_buffer    = ''
        self.transmit_message   = ''
        self.transmit_condition = threading.Condition()
        
        try:
            logger.info('init: Opening the serial port on %s at %s bps.', self.serial_name, self.baud_rate)
            # Open the serial port
            self.serial_port = serial.Serial(port = self.serial_name, 
                                             baudrate = self.baud_rate,
                                             timeout = self.time_out)
        except:
            logger.error('init: Error while opening the serial port on %s.', self.serial_name)
            raise Exception
        else:
            logger.info('init: Serial object created.')
            if (self.bsl_mode == "true"):
                self.bsl_start()
    
    # Runs the MoteProbe thread
    def run(self):
        logger.info("run: Starting the Serial object.")
        
        if (self.serial_port == None):
            return
        
        # Flush the serial input/ouput               
        self.serial_port.flushInput()
        self.serial_port.flushOutput() 
        
        # Execute while thread is alive
        while (not self.stop_event.isSet()): 
            try:
                # Try to receive a byte from the serial port (blocking)
                self.rx_byte = self.serial_port.read(size = 1)
            except:
                logger.error('run: Error while receiving from the serial port on %s.', self.serial_port)
                # Terminate the thread
                self.stop()
                # Break the loop
                break
            
            # Start of frame
            if ((not self.is_receiving) and 
                (self.last_rx_byte == self.hdlc.HDLC_FLAG) and
                (self.rx_byte != self.hdlc.HDLC_FLAG)):
                
                self.is_receiving = True
                self.receive_buffer = self.hdlc.HDLC_FLAG
                self.receive_buffer += self.rx_byte
                
            # Middle of HDLC frame
            elif ((self.is_receiving) and
                  (self.rx_byte != self.hdlc.HDLC_FLAG)):
                self.receive_buffer += self.rx_byte
                
            # End of HDLC frame 
            elif ((self.is_receiving) and
                  (self.rx_byte == self.hdlc.HDLC_FLAG)):
                
                # Receive the last byte
                self.receive_buffer += self.rx_byte
                
                # Reset the variables
                self.is_receiving = False
                self.last_rx_byte = ''
                self.rx_byte = ''
                
                try:
                    logger.debug('run: Received an HDLC frame from the Serial port, now de-HDLCifying it.')
                    self.receive_message = self.hdlc.dehdlcify(self.receive_buffer)
                except:
                    logger.error('run: Error while de-HDLCifying the frame received from the Serial port.')
                    self.receive_buffer  = ''
                    self.receive_message = ''
                else:
                     # Acquire the transmit condition
                    self.receive_condition.acquire()                   
                    
                     # Notify the transmit condition
                    self.receive_condition.notify()
                    
                     # Release the transmit condition
                    self.receive_condition.release()
                    
                    # Reset the receive buffer
                    self.receive_buffer = ''
            
            else:
                # Acquire the transmit condition
                self.transmit_condition.acquire()
                
                # Check if there is something to transmit
                if (not self.is_receiving and self.transmit_message):
                    logger.debug('run: HDLCifying the transmit buffer.')
                    
                    # HDLCify the message
                    self.transmit_buffer = self.hdlc.hdlcify(self.transmit_message)
                    
                    logger.debug('run: Now transmitting the message.')
                    
                    # Send the message through the serial port (blocking)
                    self.serial_port.write(self.transmit_buffer)
                    
                    # Empty the transmit message and buffer
                    self.transmit_message = ''
                
                # Release the transmit condition
                self.transmit_condition.release()
                
            # Always save the last received byte
            self.last_rx_byte = self.rx_byte
    
    # Stops the thread
    def stop(self):
        logger.info('stop: Stopping the Serial port.')

        # Terminates the thread
        self.stop_event.set()
        
        if (self.serial_port != None and self.bsl_mode == "true"):
            self.bsl_stop()
    
    # Receive a message
    def receive(self):
        status  = True
        message = None
        length  = 0
        
        # Acquire the receive condition
        self.receive_condition.acquire()
        
        # Try to receive a message with timeout
        self.receive_condition.wait(0.5)

        # If we really got a message, copy it!
        if (not self.is_receiving and self.receive_message):
            message = self.receive_message
            length  = len(self.receive_message)
        
            logger.info('receive: Received a message with %d bytes.', length)
        
        # Reset the receive message
        self.receive_message = ''
        
        # Release the receive condition
        self.receive_condition.release()
        
        # Get the status of the thread
        status = self.stop_event.isSet()
        
        # Return the received message and length
        return (status, message, length)
    
    # Transmit a message
    def transmit(self, message):
        logger.info('transmit: Got a message to transmit with %d bytes.', len(message))
        
        # Acquire the transmit condition
        self.transmit_condition.acquire()
        
        # Copy the message
        self.transmit_message = message

        # Release the transmit condition
        self.transmit_condition.release()
        
    def bsl_start(self):
        self.serial_port.setDTR(High)
        time.sleep(0.1)
        self.serial_port.setRTS(Low)
        time.sleep(0.1)
        self.serial_port.setDTR(Low)
    
    def bsl_stop(self):
        self.serial_port.setDTR(High)
        time.sleep(0.1)
        self.serial_port.setRTS(Low)
        time.sleep(0.1)
        self.serial_port.setDTR(Low)
class Serial(threading.Thread):
    def __init__(self, serial_name=None, baud_rate=None, bsl_mode=None):
        assert serial_name != None, logger.error("Serial port not defined.")
        assert baud_rate != None, logger.error("Serial baudrate not defined.")
        assert bsl_mode != None, logger.error("Bootloader mode not defined.")

        logger.info('init: Creating the Serial object.')

        # Call constructor
        threading.Thread.__init__(self)

        # Set thread as daemon
        self.setDaemon(False)

        # Terminate thread event
        self.stop_event = threading.Event()

        # Serial port
        self.serial_port = None
        self.serial_name = serial_name
        self.baud_rate = baud_rate
        self.time_out = 1.0
        self.bsl_mode = bsl_mode

        # HDLC driver
        self.hdlc = Hdlc()

        # Receive variables
        self.receive_buffer = ''
        self.receive_message = ''
        self.receive_condition = threading.Condition()
        self.is_receiving = False
        self.last_rx_byte = 0

        # Transmit variables
        self.transmit_buffer = ''
        self.transmit_message = ''
        self.transmit_condition = threading.Condition()

        try:
            logger.info('init: Opening the serial port on %s at %s bps.',
                        self.serial_name, self.baud_rate)
            # Open the serial port
            self.serial_port = serial.Serial(port=self.serial_name,
                                             baudrate=self.baud_rate,
                                             timeout=self.time_out)
        except:
            logger.error('init: Error while opening the serial port on %s.',
                         self.serial_name)
            raise Exception
        else:
            logger.info('init: Serial object created.')
            if (self.bsl_mode == "true"):
                self.bsl_start()

    # Runs the MoteProbe thread
    def run(self):
        logger.info("run: Starting the Serial object.")

        if (self.serial_port == None):
            return

        # Flush the serial input/ouput
        self.serial_port.flushInput()
        self.serial_port.flushOutput()

        # Execute while thread is alive
        while (not self.stop_event.isSet()):
            try:
                # Try to receive a byte from the serial port (blocking)
                self.rx_byte = self.serial_port.read(size=1)
            except:
                logger.error(
                    'run: Error while receiving from the serial port on %s.',
                    self.serial_port)
                # Terminate the thread
                self.stop()
                # Break the loop
                break

            # Start of frame
            if ((not self.is_receiving)
                    and (self.last_rx_byte == self.hdlc.HDLC_FLAG)
                    and (self.rx_byte != self.hdlc.HDLC_FLAG)):

                self.is_receiving = True
                self.receive_buffer = self.hdlc.HDLC_FLAG
                self.receive_buffer += self.rx_byte

            # Middle of HDLC frame
            elif ((self.is_receiving)
                  and (self.rx_byte != self.hdlc.HDLC_FLAG)):
                self.receive_buffer += self.rx_byte

            # End of HDLC frame
            elif ((self.is_receiving)
                  and (self.rx_byte == self.hdlc.HDLC_FLAG)):

                # Receive the last byte
                self.receive_buffer += self.rx_byte

                # Reset the variables
                self.is_receiving = False
                self.last_rx_byte = ''
                self.rx_byte = ''

                try:
                    logger.debug(
                        'run: Received an HDLC frame from the Serial port, now de-HDLCifying it.'
                    )
                    self.receive_message = self.hdlc.dehdlcify(
                        self.receive_buffer)
                except:
                    logger.error(
                        'run: Error while de-HDLCifying the frame received from the Serial port.'
                    )
                    self.receive_buffer = ''
                    self.receive_message = ''
                else:
                    # Acquire the transmit condition
                    self.receive_condition.acquire()

                    # Notify the transmit condition
                    self.receive_condition.notify()

                    # Release the transmit condition
                    self.receive_condition.release()

                    # Reset the receive buffer
                    self.receive_buffer = ''

            else:
                # Acquire the transmit condition
                self.transmit_condition.acquire()

                # Check if there is something to transmit
                if (not self.is_receiving and self.transmit_message):
                    logger.debug('run: HDLCifying the transmit buffer.')

                    # HDLCify the message
                    self.transmit_buffer = self.hdlc.hdlcify(
                        self.transmit_message)

                    logger.debug('run: Now transmitting the message.')

                    # Send the message through the serial port (blocking)
                    self.serial_port.write(self.transmit_buffer)

                    # Empty the transmit message and buffer
                    self.transmit_message = ''

                # Release the transmit condition
                self.transmit_condition.release()

            # Always save the last received byte
            self.last_rx_byte = self.rx_byte

    # Stops the thread
    def stop(self):
        logger.info('stop: Stopping the Serial port.')

        # Terminates the thread
        self.stop_event.set()

        if (self.serial_port != None and self.bsl_mode == "true"):
            self.bsl_stop()

    # Receive a message
    def receive(self):
        status = True
        message = None
        length = 0

        # Acquire the receive condition
        self.receive_condition.acquire()

        # Try to receive a message with timeout
        self.receive_condition.wait(0.5)

        # If we really got a message, copy it!
        if (not self.is_receiving and self.receive_message):
            message = self.receive_message
            length = len(self.receive_message)

            logger.info('receive: Received a message with %d bytes.', length)

        # Reset the receive message
        self.receive_message = ''

        # Release the receive condition
        self.receive_condition.release()

        # Get the status of the thread
        status = self.stop_event.isSet()

        # Return the received message and length
        return (status, message, length)

    # Transmit a message
    def transmit(self, message):
        logger.info('transmit: Got a message to transmit with %d bytes.',
                    len(message))

        # Acquire the transmit condition
        self.transmit_condition.acquire()

        # Copy the message
        self.transmit_message = message

        # Release the transmit condition
        self.transmit_condition.release()

    def bsl_start(self):
        self.serial_port.setDTR(High)
        time.sleep(0.1)
        self.serial_port.setRTS(Low)
        time.sleep(0.1)
        self.serial_port.setDTR(Low)

    def bsl_stop(self):
        self.serial_port.setDTR(High)
        time.sleep(0.1)
        self.serial_port.setRTS(Low)
        time.sleep(0.1)
        self.serial_port.setDTR(Low)