openrvdas.logger.writers.serial_writer
1#!/usr/bin/env python3 2 3import logging 4 5from typing import Union 6 7# Don't freak out if pyserial isn't installed - unless they actually 8# try to instantiate a SerialWriter 9try: 10 import serial 11 SERIAL_MODULE_FOUND = True 12except ModuleNotFoundError: 13 SERIAL_MODULE_FOUND = False 14 15from logger.writers.writer import Writer # noqa: E402 16 17 18################################################################################ 19class SerialWriter(Writer): 20 """ 21 Writes records to a serial port. 22 """ 23 def __init__(self, port, baudrate=9600, bytesize=8, parity='N', 24 stopbits=1, timeout=None, xonxoff=False, rtscts=False, 25 write_timeout=None, dsrdtr=False, inter_byte_timeout=None, 26 exclusive=None, eol='\n', **kwargs): 27 """ 28 By default, the SerialWriter write records to the specified serial port encoded by UTF-8 29 and will ignore non unicode characters it encounters. These defaults may be changed by 30 specifying. 31 32 eol - if specified, append to end of records to signify end of line, 33 otherwise use \n 34 35 encoding - 'utf-8' by default. If empty or None, will throw type error. 36 Other possible encodings are listed in online documentation here: 37 https://docs.python.org/3/library/codecs.html#standard-encodings 38 39 encoding_errors - 'ignore' by default. Other error strategies are 'strict', 40 'replace', and 'backslashreplace', described here: 41 https://docs.python.org/3/howto/unicode.html#encodings 42 quiet - allows for the logger to silence warnings if not all the bits were succesfully 43 written to the serial port. 44 """ 45 super().__init__(**kwargs) # processes 'quiet', encodings and type hints 46 47 48 if not SERIAL_MODULE_FOUND: 49 raise RuntimeError('Serial port functionality not available. Please ' 50 'install Python module pyserial.') 51 try: 52 self.serial = serial.Serial(port=port, baudrate=baudrate, 53 bytesize=bytesize, parity=parity, 54 stopbits=stopbits, timeout=timeout, 55 xonxoff=xonxoff, rtscts=rtscts, 56 write_timeout=write_timeout, dsrdtr=dsrdtr, 57 inter_byte_timeout=inter_byte_timeout, 58 exclusive=exclusive) 59 except serial.SerialException as e: 60 raise serial.SerialException(f'Failed to open serial port {port}: {e}') 61 62 # 'eol' comes in as a (probably escaped) string. We need to 63 # unescape it, which means converting to bytes and back. 64 if eol: 65 if self.encoding: 66 # NOTE: Technically, it's safe to call _unescape_str() with no 67 # encoding, it just returns the str/bytes/thing 68 # unmodified. But why tempt fate, right? 69 eol = self._unescape_str(eol) 70 else: 71 # if encoding has been set to '' or None, we're dealing with raw/binary 72 # output. encode eol so we can append it safely in write() 73 eol = eol.encode() 74 self.eol = eol 75 76 ############################ 77 def write(self, record: Union[str, bytes]): 78 79 # See if it's something we can process, and if not, try digesting 80 if not self.can_process_record(record): # inherited from BaseModule() 81 self.digest_record(record) # inherited from BaseModule() 82 return 83 84 try: 85 if self.eol: 86 record += self.eol 87 written = self.serial.write(self._encode_str(record)) 88 if not written and not self.quiet: 89 logging.error("Not all bits written") 90 except KeyboardInterrupt as e: 91 raise e 92 except TypeError as e: 93 raise e 94 except serial.serialutil.SerialException as e: 95 logging.error(str(e))
20class SerialWriter(Writer): 21 """ 22 Writes records to a serial port. 23 """ 24 def __init__(self, port, baudrate=9600, bytesize=8, parity='N', 25 stopbits=1, timeout=None, xonxoff=False, rtscts=False, 26 write_timeout=None, dsrdtr=False, inter_byte_timeout=None, 27 exclusive=None, eol='\n', **kwargs): 28 """ 29 By default, the SerialWriter write records to the specified serial port encoded by UTF-8 30 and will ignore non unicode characters it encounters. These defaults may be changed by 31 specifying. 32 33 eol - if specified, append to end of records to signify end of line, 34 otherwise use \n 35 36 encoding - 'utf-8' by default. If empty or None, will throw type error. 37 Other possible encodings are listed in online documentation here: 38 https://docs.python.org/3/library/codecs.html#standard-encodings 39 40 encoding_errors - 'ignore' by default. Other error strategies are 'strict', 41 'replace', and 'backslashreplace', described here: 42 https://docs.python.org/3/howto/unicode.html#encodings 43 quiet - allows for the logger to silence warnings if not all the bits were succesfully 44 written to the serial port. 45 """ 46 super().__init__(**kwargs) # processes 'quiet', encodings and type hints 47 48 49 if not SERIAL_MODULE_FOUND: 50 raise RuntimeError('Serial port functionality not available. Please ' 51 'install Python module pyserial.') 52 try: 53 self.serial = serial.Serial(port=port, baudrate=baudrate, 54 bytesize=bytesize, parity=parity, 55 stopbits=stopbits, timeout=timeout, 56 xonxoff=xonxoff, rtscts=rtscts, 57 write_timeout=write_timeout, dsrdtr=dsrdtr, 58 inter_byte_timeout=inter_byte_timeout, 59 exclusive=exclusive) 60 except serial.SerialException as e: 61 raise serial.SerialException(f'Failed to open serial port {port}: {e}') 62 63 # 'eol' comes in as a (probably escaped) string. We need to 64 # unescape it, which means converting to bytes and back. 65 if eol: 66 if self.encoding: 67 # NOTE: Technically, it's safe to call _unescape_str() with no 68 # encoding, it just returns the str/bytes/thing 69 # unmodified. But why tempt fate, right? 70 eol = self._unescape_str(eol) 71 else: 72 # if encoding has been set to '' or None, we're dealing with raw/binary 73 # output. encode eol so we can append it safely in write() 74 eol = eol.encode() 75 self.eol = eol 76 77 ############################ 78 def write(self, record: Union[str, bytes]): 79 80 # See if it's something we can process, and if not, try digesting 81 if not self.can_process_record(record): # inherited from BaseModule() 82 self.digest_record(record) # inherited from BaseModule() 83 return 84 85 try: 86 if self.eol: 87 record += self.eol 88 written = self.serial.write(self._encode_str(record)) 89 if not written and not self.quiet: 90 logging.error("Not all bits written") 91 except KeyboardInterrupt as e: 92 raise e 93 except TypeError as e: 94 raise e 95 except serial.serialutil.SerialException as e: 96 logging.error(str(e))
Writes records to a serial port.
24 def __init__(self, port, baudrate=9600, bytesize=8, parity='N', 25 stopbits=1, timeout=None, xonxoff=False, rtscts=False, 26 write_timeout=None, dsrdtr=False, inter_byte_timeout=None, 27 exclusive=None, eol='\n', **kwargs): 28 """ 29 By default, the SerialWriter write records to the specified serial port encoded by UTF-8 30 and will ignore non unicode characters it encounters. These defaults may be changed by 31 specifying. 32 33 eol - if specified, append to end of records to signify end of line, 34 otherwise use \n 35 36 encoding - 'utf-8' by default. If empty or None, will throw type error. 37 Other possible encodings are listed in online documentation here: 38 https://docs.python.org/3/library/codecs.html#standard-encodings 39 40 encoding_errors - 'ignore' by default. Other error strategies are 'strict', 41 'replace', and 'backslashreplace', described here: 42 https://docs.python.org/3/howto/unicode.html#encodings 43 quiet - allows for the logger to silence warnings if not all the bits were succesfully 44 written to the serial port. 45 """ 46 super().__init__(**kwargs) # processes 'quiet', encodings and type hints 47 48 49 if not SERIAL_MODULE_FOUND: 50 raise RuntimeError('Serial port functionality not available. Please ' 51 'install Python module pyserial.') 52 try: 53 self.serial = serial.Serial(port=port, baudrate=baudrate, 54 bytesize=bytesize, parity=parity, 55 stopbits=stopbits, timeout=timeout, 56 xonxoff=xonxoff, rtscts=rtscts, 57 write_timeout=write_timeout, dsrdtr=dsrdtr, 58 inter_byte_timeout=inter_byte_timeout, 59 exclusive=exclusive) 60 except serial.SerialException as e: 61 raise serial.SerialException(f'Failed to open serial port {port}: {e}') 62 63 # 'eol' comes in as a (probably escaped) string. We need to 64 # unescape it, which means converting to bytes and back. 65 if eol: 66 if self.encoding: 67 # NOTE: Technically, it's safe to call _unescape_str() with no 68 # encoding, it just returns the str/bytes/thing 69 # unmodified. But why tempt fate, right? 70 eol = self._unescape_str(eol) 71 else: 72 # if encoding has been set to '' or None, we're dealing with raw/binary 73 # output. encode eol so we can append it safely in write() 74 eol = eol.encode() 75 self.eol = eol
By default, the SerialWriter write records to the specified serial port encoded by UTF-8 and will ignore non unicode characters it encounters. These defaults may be changed by specifying.
eol - if specified, append to end of records to signify end of line, otherwise use
encoding - 'utf-8' by default. If empty or None, will throw type error. Other possible encodings are listed in online documentation here: https://docs.python.org/3/library/codecs.html#standard-encodings
encoding_errors - 'ignore' by default. Other error strategies are 'strict', 'replace', and 'backslashreplace', described here: https://docs.python.org/3/howto/unicode.html#encodings quiet - allows for the logger to silence warnings if not all the bits were succesfully written to the serial port.
78 def write(self, record: Union[str, bytes]): 79 80 # See if it's something we can process, and if not, try digesting 81 if not self.can_process_record(record): # inherited from BaseModule() 82 self.digest_record(record) # inherited from BaseModule() 83 return 84 85 try: 86 if self.eol: 87 record += self.eol 88 written = self.serial.write(self._encode_str(record)) 89 if not written and not self.quiet: 90 logging.error("Not all bits written") 91 except KeyboardInterrupt as e: 92 raise e 93 except TypeError as e: 94 raise e 95 except serial.serialutil.SerialException as e: 96 logging.error(str(e))
Core method - write a record that we've been passed.