initial python serial repl

This commit is contained in:
2025-02-10 17:29:02 -05:00
parent d27bfc9734
commit afb2ea67fe
4 changed files with 114 additions and 0 deletions

82
serial_repl.py Normal file
View File

@@ -0,0 +1,82 @@
import serial
import threading
from time import sleep
class SelfHealingSerial():
"""A wrapper class for pyserial's Serial class
This reimplements the basic Serial functions but wraps them in _reestablish_and_retry.
This attempts a reconnect if the arduino is unplugged or otherwise unavailable.
Also this has defaults that work with the Adafruit M0 LoRa feather.
"""
def __init__(self, path: str = '/dev/ttyACM0', baudrate: int = 115200, timeout: int = 2):
self._path = path
self._baudrate = baudrate
self._timeout = timeout
self._connection = None
self._waiting_response = False
def _establish_connection(self):
"""Connects to the feather
"""
self._connection = serial.Serial(self._path, self._baudrate, timeout=self._timeout)
def _reestablish_and_retry(func):
"""If disconnect, keep trying every second
We know if there's a disconnect when the attempted function fails.
"""
def wrapper(self: "SelfHealingSerial", *args, **kwargs):
while True:
try:
if not self._connection:
self._establish_connection()
return func(self, *args, **kwargs)
except (IOError, serial.serialutil.SerialException):
print("Connection failed.")
sleep(1)
print("Reestablishing connection.")
self._connection = False
return wrapper
@_reestablish_and_retry
def read_all(self):
"""Read all data from the serial port
"""
return self._connection.read_all()
@_reestablish_and_retry
def write(self, bytestring: bytes):
"""Write to the serial port
"""
self._waiting_response = True
return self._connection.write(bytestring)
def print_serial(serial_obj: SelfHealingSerial):
"""Check for new serial output and print it to the terminal
"""
while True:
line = serial_obj.read_all()
if line:
serial_obj._waiting_response = False
print("\n" + line.decode() + "\n>>>", end="")
def write_serial(serial_obj: SelfHealingSerial):
"""If we're not waiting for a response, write data to the serial port, then wait for a response.
"""
while True:
if not serial_obj._waiting_response:
send_string = input("")
if send_string and send_string != '\n' and send_string != '\r\n':
serial_obj.write(send_string.encode('utf-8'))
else:
sleep(1)
if __name__ == "__main__":
connection: SelfHealingSerial = SelfHealingSerial('/dev/ttyACM0', 115200, timeout=1)
listen_thread = threading.Thread(target=print_serial, args=(connection,))
listen_thread.start()
print(">>> ", end="")
write_serial(connection)