handle errors and retry logic better
This commit is contained in:
parent
9d9a625b08
commit
ee8ec92c67
|
@ -1,9 +1,11 @@
|
|||
import argparse
|
||||
import asyncio
|
||||
import contextlib
|
||||
import errno
|
||||
import re
|
||||
import sys
|
||||
import termios
|
||||
import traceback
|
||||
import tty
|
||||
from types import TracebackType
|
||||
from typing import Any, List, Optional, Tuple, Type
|
||||
|
@ -76,9 +78,33 @@ async def megacom(tty: str, baud: int, mode: str) -> None:
|
|||
bytesize = MODE_LOOKUP["bytesize"][m.group(1)]
|
||||
parity = MODE_LOOKUP["parity"][m.group(2)]
|
||||
stopbits = MODE_LOOKUP["stopbits"][m.group(3)]
|
||||
(serialin, serialout) = await serial_asyncio.open_serial_connection(
|
||||
loop=asyncio.get_event_loop(), url=tty, baudrate=baud, bytesize=bytesize, parity=parity,
|
||||
stopbits=stopbits)
|
||||
|
||||
printed_fnf = False
|
||||
|
||||
while True:
|
||||
try:
|
||||
(serialin, serialout) = await serial_asyncio.open_serial_connection(
|
||||
loop=asyncio.get_event_loop(), url=tty, baudrate=baud, bytesize=bytesize,
|
||||
parity=parity, stopbits=stopbits)
|
||||
break
|
||||
except serial.SerialException as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
# the device could not be plugged in yet.. just wait
|
||||
if not printed_fnf:
|
||||
printed_fnf = True
|
||||
stdout.write(f"waiting for {tty} to become available...\r\n".encode())
|
||||
await stdout.drain()
|
||||
else:
|
||||
# permanent failure
|
||||
stdout.write(f"failed to open port because: {e}\r\n".encode())
|
||||
await stdout.drain()
|
||||
return
|
||||
except Exception as e:
|
||||
# permanant failure
|
||||
stdout.write(f"failed to open port because: {e}\r\n".encode())
|
||||
await stdout.drain()
|
||||
return
|
||||
await asyncio.sleep(2)
|
||||
|
||||
stdout.write(f"megacom connected to {tty}:{baud}:{mode}\r\n".encode())
|
||||
await stdout.drain()
|
||||
|
@ -113,21 +139,51 @@ async def megacom(tty: str, baud: int, mode: str) -> None:
|
|||
|
||||
stdin_to_serial = asyncio.create_task(connect_pipe(stdin, serialout, True))
|
||||
serial_to_stdout = asyncio.create_task(connect_pipe(serialin, stdout))
|
||||
await exit_flag.wait()
|
||||
time_to_exit = asyncio.create_task(exit_flag.wait())
|
||||
|
||||
do_retry = False
|
||||
|
||||
def handle_done(task):
|
||||
nonlocal do_retry
|
||||
if task.done():
|
||||
exc = task.exception()
|
||||
if exc is not None:
|
||||
stdout.write(f"\r\n\r\nmegacom encountered error: {exc}\r\n".encode())
|
||||
if isinstance(exc, serial.SerialException):
|
||||
do_retry = True
|
||||
else:
|
||||
task.result()
|
||||
return task.done()
|
||||
|
||||
await asyncio.wait([time_to_exit, stdin_to_serial, serial_to_stdout], return_when=asyncio.FIRST_COMPLETED)
|
||||
if handle_done(time_to_exit):
|
||||
pass
|
||||
elif handle_done(stdin_to_serial):
|
||||
pass
|
||||
elif handle_done(serial_to_stdout):
|
||||
pass
|
||||
|
||||
stdin_to_serial.cancel()
|
||||
serial_to_stdout.cancel()
|
||||
with contextlib.suppress(asyncio.CancelledError):
|
||||
await stdin_to_serial
|
||||
with contextlib.suppress(serial.SerialException):
|
||||
await stdin_to_serial
|
||||
with contextlib.suppress(asyncio.CancelledError):
|
||||
await serial_to_stdout
|
||||
with contextlib.suppress(serial.SerialException):
|
||||
await serial_to_stdout
|
||||
|
||||
stdout.write(b"\r\n\r\nmegacom is exiting\r\n")
|
||||
if not do_retry:
|
||||
stdout.write(b"\r\n\r\nmegacom is exiting\r\n")
|
||||
|
||||
await serialout.drain()
|
||||
serialout.close()
|
||||
with contextlib.suppress(serial.SerialException):
|
||||
await serialout.drain()
|
||||
with contextlib.suppress(serial.SerialException):
|
||||
serialout.close()
|
||||
await stdout.drain()
|
||||
|
||||
if do_retry:
|
||||
return await megacom(tty, baud, mode)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(prog="megacom",
|
||||
|
|
Loading…
Reference in New Issue