Example #1
0
class SerialKISSDevice(BaseKISSDevice):
    def __init__(self, device, baudrate, *args, **kwargs):
        super(SerialKISSDevice, self).__init__(*args, **kwargs)
        self._serial = None
        self._device = device
        self._baudrate = baudrate

    def _open(self):
        self._serial = Serial(port=self._device, baudrate=self._baudrate,
                bytesize=EIGHTBITS, parity=PARITY_NONE, stopbits=STOPBITS_ONE,
                timeout=None, xonxoff=False, rtscts=False, write_timeout=None,
                dsrdtr=False, inter_byte_timeout=None)
        self._loop.add_reader(self._serial.fileno(), self._on_recv_ready)
        self._loop.call_soon(self._init_kiss)

    def _close(self):
        # Remove handlers
        self._loop.remove_reader(self._serial.fileno())

        # Wait for all data to be sent.
        self._serial.flush()

        # Close the port
        self._serial.close()
        self._serial = None
        self._state = KISSDeviceState.CLOSED

    def _on_recv_ready(self):
        try:
            self._receive(self._serial.read(self._serial.in_waiting))
        except:
            self._log.exception('Failed to read from serial device')

    def _send_raw_data(self, data):
        self._serial.write(data)
Example #2
0
class XBeeDaemon(dbus.service.Object):
    """
    Main class which connects dbus API and serial communication
    name: Unique DBUS object name for this instance
    All other arguments are passed off to the underlying pySerial implementation
    """
    def __init__(self, name, port, escaping=True, baudrate=9600):
        if escaping:
            self.serial = EscapingSerial(port=port, baudrate=baudrate, timeout=0)
        else:
            self.serial = Serial(port=port, baudrate=baudrate, timeout=0)  
        self.object_path = XBEED_DAEMON_OBJECT % name
        self.partial = PartialFrame()
        dbus.service.Object.__init__(self, BUS_NAME, self.object_path)
        gobject.io_add_watch(self.serial.fileno(), gobject.IO_IN, self.serial_read)
        
    def serial_read(self, fd, condition, *args):
        """ Called when there is data available from the serial port """
        buffer = self.serial.read(256)
        print 'xbeed: read %d bytes' % len(buffer)
        try:
            if(self.partial.add(buffer)):
                packet = XBeeModuleFrame.parse(*self.partial.get_data())
                self.handle_packet(packet)
        except ChecksumFail, e:
            print 'xbeed: ', e  
        except UnknownFrameType, e:
            print 'xbeed: ', e  
Example #3
0
def get_serial_port():
    """ Return serial.Serial instance, ready to use for RS485."""
    port = Serial(port='/dev/ttyS1', baudrate=9600, parity=PARITY_NONE,
                  stopbits=1, bytesize=8, timeout=1)

    fh = port.fileno()

    # A struct with configuration for serial port.
    serial_rs485 = struct.pack('hhhhhhhh', 1, 0, 0, 0, 0, 0, 0, 0)
    fcntl.ioctl(fh, 0x542F, serial_rs485)

    return port
Example #4
0
class DummyPty(object):
    def __init__(self, sequence):
        # type: (List[bytes]) -> None
        self._replies = []  # type: List[bytes]
        self._sequence = sequence
        self._read = threading.Event()
        master, slave = pty.openpty()
        self.fd = os.fdopen(master, 'wb', 0)
        self._serial = Serial(os.ttyname(slave))
        self._serial.timeout = None

    def master_reply(self, data):
        # type: (bytes) -> None
        self._replies.append(data)

    def master_wait(self, timeout=2):
        # type: (Optional[float]) -> None
        self._read.clear()
        self._read.wait(timeout)

    def read(self, size=None):
        # type: (Optional[int]) -> bytes
        data = self._serial.read(size)
        if data:
            self._read.set()
        return data

    def write(self, data):
        # type: (bytes) -> int
        if data != self._sequence[0]:
            assert printable(self._sequence[0]) == printable(data)
        self._sequence.pop(0)
        if self._replies:
            self.fd.write(self._replies[0])
            self._replies.pop(0)
        return len(data)

    def fileno(self):
        # type: () -> int
        return self._serial.fileno()

    @property
    def in_waiting(self):
        # type: () -> int
        return self._serial.in_waiting

    def inWaiting(self):  # pylint: disable=C0103
        # type: () -> int
        return self._serial.inWaiting()
Example #5
0
def watch(port):
    try:
        serial = Serial(port, 115200, timeout=None)
        fileno = serial.fileno()
        if fileno is not None:
            flags_rs485 = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND
            serial_rs485 = struct.pack('hhhhhhhh', flags_rs485, 0, 0, 0, 0, 0,
                                       0, 0)
            fcntl.ioctl(fileno, TIOCSRS485, serial_rs485)
        buffer = ''
        while True:
            buffer += serial.read(1)
            _print(buffer)
            if buffer == 'ping\r':
                _print(buffer)
                serial.write('pong\r\n')
                buffer = ''
    except KeyboardInterrupt:
        print('Exit')
			#data is good, lets output
			#creat a timestamp for the current message and prepend to the message
			stamp = datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
			message = stamp + ' $'  + serialData.decode('UTF-8').rstrip('\r\n') + '#'
			#debug: print(message)
			print(message)
			#save message to the buffer
			data_log_buffer.append(message)
			#send the message to the producer
			p.send("weather-test",message.encode('UTF-8'))
		#attempt to rotate the log if needed
		rotate_log()
#create an async loop object that drives the entire app
loop = asyncio.get_event_loop()
#add the serial function to the event handler
loop.add_reader(s.fileno(), SerialReader)
#call the function to write the process id to file
writePidFile()
#begin the main loop
try:
	loop.run_forever()
#on ctrl+c key press grab the exception
except KeyboardInterrupt:
	#close the serial line
	s.close()
	#save the current buffer to local file
	buffer_to_file(data_log_buffer, current_log, True)
	#delete the pid file
	deletePidFile()
	#end the main loop
	loop.close()
Example #7
0
class SerialConsole(ConsoleBase):
    def __init__(self,
                 port,
                 baud,
                 encoding=None,
                 linesep=None,
                 raw_logfile=None,
                 system: SystemContext = None):
        self.port = port
        self.baud = baud
        self._timeout = 0.001
        self._ser = None
        super().__init__(encoding=encoding,
                         linesep=linesep,
                         raw_logfile=raw_logfile,
                         system=system)

    def __repr__(self):
        return "SerialConsole[{}]".format(self.port)

    @property
    def is_open(self):
        return super().is_open and self._ser and self._ser.isOpen()

    def open(self):
        self.log(f'Trying to open serial port {self.port}',
                 level=LogLevel.DEBUG)
        self._ser = Serial(port=self.port,
                           baudrate=self.baud,
                           timeout=self._timeout)

        self.engine.open(console_fd=self._ser.fileno())

        if not self.is_open:
            raise RuntimeError(f'Failed to open serial port {self.port}')

        self.log(f'Init serial {self.port} success', level=LogLevel.DEBUG)
        return

    def close(self):
        if not self.is_open:
            return

        self._ser.flush()

        # Closes the serial too
        super().close()

        self._ser = None
        self.log("Closed serial", level=LogLevel.DEBUG)

    def interact(self, exit_char=None):
        '''
        Take interactive control of a SerialConsole.
        The intention is that this be used from the command line.
        To exit the terminal press the exit character.
        You can set the exit character with @exit_char, default is "¬".
        '''
        if not self.is_open:
            self.open()

        exit_char = exit_char or '¬'

        self.log('Starting interactive console')
        print(f'Press {exit_char} to exit')

        com = self._logging_Nanocom(self.engine.raw_logfile,
                                    self._ser,
                                    exit_character=exit_char)

        com.start()
        try:
            com.join()
        except KeyboardInterrupt:
            pass
        finally:
            self.log('Exiting interactive console...')
            com.close()

    class _logging_Nanocom(Nanocom):
        '''
        This class just slightly modifies Nanocom to get it to log
        received data to a file.
        This is done so that the text from the interactive session
        is written to the raw logfile, along with everything else.
        The reader() method is copy-pasted from Nanocom and modified.
        '''
        def __init__(self, logfile, *args, **kwargs):
            self.logfile = logfile
            Nanocom.__init__(self, *args, **kwargs)

        def reader(self):
            try:
                while self.alive:
                    data = self.serial.read(self.serial.in_waiting or 1)
                    if data:
                        self.console.write_bytes(data)
                        with open(self.logfile, 'ab') as f:
                            f.write(data)
            except Exception:
                self.alive = False
                self.console.cancel()
                raise
Example #8
0
class XBeeInterface(object):
    """
    Interfaces between an XBee connected through a serial port and messages
    passed through stdin/stdout. Uses a simple JSON protocol to encode message
    parameters.
    """
    def __init__(self, port, baud, escaped):

        self.serial_port = Serial(port, baud)
        self.xbee = ZigBee(self.serial_port, escaped=escaped)

        # Reopen stdin/stdout in line-buffered mode
        self.stdin = os.fdopen(sys.stdin.fileno(), 'r', 1)
        self.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)

        # Associate each file descriptor with handler methods
        self.handlers = {
            self.serial_port.fileno(): (self.read_frame, self.on_frame),
            self.stdin.fileno(): (self.read_message, self.on_message)
        }

        # Turn on non-blocking IO
        for fd in self.handlers.keys():
            fcntl.fcntl(fd, fcntl.F_SETFL, os.O_NONBLOCK)

    def run(self):
        # Send an AT command to trigger a response from the module
        self.xbee.at(command='NI')
        response = self.xbee.wait_read_frame()
        log.info('Network identifier is "%s"', response['parameter'])

        while True:
            # do non-blocking reading from stdin and serial port
            r, w, x = select.select(self.handlers.keys(), [], [])

            for fd in r:
                read_handler, data_handler = self.handlers[fd]
                data = read_handler()

                # read handlers return None if message is gimped
                if data is not None:
                    data_handler(data)


    def read_frame(self):
        """ Read an entire frame from the serial connection and return it """
        try:
            return self.xbee.wait_read_frame()
        except ValueError as e:
            log.warning('error in packet data: %s', e)
            return None
        except SerialException as e:
            log.error('error reading serial frame: %s', e)
            raise IOError("Error reading from serial port")

    def read_message(self):
        """ Read a line from stdin and parse it as JSON """
        try:
            line = self.stdin.readline()
            return json.loads(line)
        except ValueError as e:
            log.error('error decoding message: %s', e)
            return None

    def json_message(self, data):
        """ Write a JSON string to stdout, using latin1 encoding to keep binary
        data intact """
        json_str = json.dumps(data, encoding='latin1')
        self.stdout.write(json_str + '\n')

    def on_message(self, message):
        log.info('Message received from stdin: %s', message)

        try:
            # delegate to another method specified by action
            action = '_'.join(('do', message['action']))
            if not hasattr(self, action):
                return log.error('Unknown action "%s"', message['action'])
            getattr(self, action)(message)
        except KeyError as e:
            return log.error('Message is missing "%s"', e.message)


    def do_send(self, message):
        """ Sends a transmit request to the module """
        # encode as latin1 to get back byte string
        address, data, frame_id = (
                message['address'].encode('latin1'),
                message['data'].encode('latin1'), 
                message.get('frame_id', u'\x01').encode('latin1'))

        try:
            self.xbee.tx(data=data, frame_id=frame_id,
                    dest_addr_long=address, dest_addr='\xFF\xFE')
        except Exception as e:
            return log.error('Failed to send transmit request: %s', e)


    def do_discover(self, message):
        frame_id = message.get('frame_id', u'\x01').encode('latin1')
        self.xbee.at(command='ND', frame_id=frame_id)
            

    def on_frame(self, frame):
        log.debug('Frame received from device: %s', frame)
        try:
            event = '_'.join(('on_frame', frame['id']))
            getattr(self, event)(frame)
        except (AttributeError, KeyError):
            log.warning('unhandled frame: %s', frame)

    def on_frame_rx(self, frame):
        log.info('Received message from %s/%s', hexify(frame['source_addr_long']),
                hexify(frame['source_addr']))
        self.json_message(frame)

    def on_frame_tx_status(self, frame):
        log.info('Transmit status for frame %s: %s', frame['frame_id'],
                'success' if frame['deliver_status'] == '\x00' else 'failure')
        self.json_message(frame)

    def on_frame_at_response(self, frame):
        log.info('AT response for frame %s: "%s"', 
                frame['frame_id'], frame['parameter'])
        self.json_message(frame)
#p = KafkaProducer(bootstrap_servers=[systemconfig.kafka_connection])

s = Serial(current_port,'9600',bytesize=8,parity='N',xonxoff=0,rtscts=0,timeout=1)
#to add a serial write function, you can use a buffer or rewrite the callback
#buffer = ""

def SerialReader():
#	global p
	if s.readable():
		serialData = s.readline()
		#s.write(buffer)
		ts = time.time()
		if len(serialData) > 2:
			#data is good, lets output
			stamp = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
			message = stamp + ' $'  + serialData.decode('UTF-8').rstrip('\r\n') + '#'
			print(message)
#			p.send("weather-test",message.encode('UTF-8'))


loop = asyncio.get_event_loop()
loop.add_reader(s.fileno(), SerialReader)

try:
	loop.run_forever()
except KeyboardInterrupt:
	s.close()
	loop.close()
finally:
	loop.close()