"""Tool used to reset a Arduino Leonardo board.""" from os import O_NDELAY, O_NOCTTY, O_RDWR, open as os_open, close as os_close import sys from termios import ( B1200, TCSANOW, TIOCM_DTR, TIOCM_RTS, TIOCMBIC, TIOCMBIS, tcgetattr, tcsetattr ) from fcntl import ioctl from argparse import ArgumentParser from dataclasses import dataclass from pathlib import Path from struct import pack from time import sleep @dataclass class ParsedArguments: """Parsed command-line arguments.""" serial_port: Path class TTYAttributes: """TTY attributes.""" def __init__(self, tty_fd: int): """Initializes the TTY attributes.""" self.__tty_fd = tty_fd self.__attrs = tcgetattr(tty_fd) @property def ispeed(self): """The ispeed.""" return self.__attrs[4] @ispeed.setter def ispeed(self, ispeed: int): self.__attrs[4] = ispeed @property def ospeed(self): """The ospeed.""" return self.__attrs[5] @ospeed.setter def ospeed(self, ospeed: int): self.__attrs[5] = ospeed def set(self): """Sets the TTY attributes.""" tcsetattr(self.__tty_fd, TCSANOW, self.__attrs) RESET_BAUD_RATE = B1200 DESCRIPTION = "Tool used to reset a Arduino Leonardo board." def main(): """Main.""" parser = ArgumentParser(allow_abbrev=False, description=DESCRIPTION) parser.add_argument( "serial_port", type=Path, help="The serial port for a Arduino Leonardo board" ) arguments = parser.parse_args(namespace=ParsedArguments) is_serial_port_char_device = arguments.serial_port.is_char_device() # Verify that the serial port exists if not arguments.serial_port.is_file() and not is_serial_port_char_device: print("Error: The serial port file doesn't exist") sys.exit(1) # Verify that the serial port is a character device if not is_serial_port_char_device: print("Error: The serial port file is not a character device") sys.exit(1) serial_port_fd = os_open( str(arguments.serial_port), O_RDWR | O_NOCTTY | O_NDELAY ) tty_attributes = TTYAttributes(serial_port_fd) tty_attributes.ispeed = RESET_BAUD_RATE tty_attributes.ospeed = RESET_BAUD_RATE tty_attributes.set() ioctl(serial_port_fd, TIOCMBIS, pack("I", TIOCM_RTS)) ioctl(serial_port_fd, TIOCMBIC, pack("I", TIOCM_DTR)) os_close(serial_port_fd) sleep(1.98) if __name__ == "__main__": main()