handle errors and retry logic better

This commit is contained in:
xenia 2021-05-12 16:32:02 -04:00
parent 9d9a625b08
commit ee8ec92c67
1 changed files with 65 additions and 9 deletions

View File

@ -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",