Wikilicious / pygmc

Python interface/API for GQ GMC Geiger Counter.
https://pypi.org/project/pygmc/
MIT License
8 stars 2 forks source link

Add connection timeout as parameter #112

Closed Wikilicious closed 2 months ago

Wikilicious commented 4 months ago

The GMC device appears to have moments where it's busy doing something internally and takes a while to open a connection. On the GMC-600+ re-running pygmc.connect() seems to have a ~1-in-8 chance of a timeout error :(

Perhaps it's a Windows-running-VMware-running-Ubuntu issue?

It seems unplugging and re-plugging the usb completely solves the issue! Add a user message for TimeoutError during connecting with a suggestion to disconnect and reconnect the USB.

DEBUG:pygmc.connection:get_available_usb_devices(6790, 29987, .*, True
DEBUG:pygmc.connection:All devices: [('/dev/ttyS0', 'PNP0501'), ('/dev/ttyUSB3', 'USB VID:PID=1A86:7523 LOCATION=1-2.2')]
DEBUG:pygmc.connection:Matched devices: [('/dev/ttyUSB3', 'USB VID:PID=1A86:7523 LOCATION=1-2.2')]
DEBUG:pygmc.discovery:Checking port=/dev/ttyUSB3 baudrate=115200

---------------------------------------------------------------------------
TimeoutError                              Traceback (most recent call last)
Cell In[13], line 1
----> 1 gc = pygmc.connect()

File ~/code/pygmc/pygmc/__init__.py:70, in connect(port, baudrate)
     42 def connect(
     43     port=None,
     44     baudrate=None,
     45 ):
     46     """
     47     Connect to device.
     48 
   (...)
     68         Unable to connect to device.
     69     """
---> 70     discover = Discovery(port=port, baudrate=baudrate)
     71     discovered_devices = discover.get_all_devices()
     73     if len(discovered_devices) == 0:
     74         # Give user direction in case of brltty udev rule blocking GMC USB device

File ~/code/pygmc/pygmc/connection/discovery.py:34, in Discovery.__init__(self, port, baudrate)
     23 """
     24 Discover GMC devices.
     25 
   (...)
     31     Device baudrate, if known. Leave None to auto-discover correct baudrate.
     32 """
     33 self._discovered_devices = []
---> 34 self._discover_devices_flow(port=port, baudrate=baudrate)

File ~/code/pygmc/pygmc/connection/discovery.py:50, in Discovery._discover_devices_flow(self, port, baudrate)
     47     self._discover_with_known_baudrate(baudrate=baudrate)
     48 else:
     49     # lemme just do everything for you... likely most common case
---> 50     self._discover_all()

File ~/code/pygmc/pygmc/connection/discovery.py:126, in Discovery._discover_all(self)
    123 ports = self._get_gmc_usb_ports()
    124 for port in ports:
    125     # D.R.Y. (don't repeat yourself)
--> 126     self._discover_with_known_port(port=port)

File ~/code/pygmc/pygmc/connection/discovery.py:118, in Discovery._discover_with_known_port(self, port)
    116 def _discover_with_known_port(self, port) -> None:
    117     for baudrate in BAUDRATES:
--> 118         is_valid = self._validate_device(port=port, baudrate=baudrate)
    119         if is_valid:
    120             break

File ~/code/pygmc/pygmc/connection/discovery.py:90, in Discovery._validate_device(self, port, baudrate)
     88 logger.debug(f"Checking port={port} baudrate={baudrate}")
     89 try:
---> 90     conn = Connection(port=port, baudrate=baudrate, timeout=2)
     91 except SerialException as e:
     92     # Should a convenience method log as warning/error?
     93     # If only GQ Electronics would put the version/serial in USB description...
     94     logger.warning(f"Skipping error connecting: {e}", exc_info=True)

File ~/code/pygmc/pygmc/connection/connection.py:66, in Connection.__init__(self, port, baudrate, timeout, serial_connection)
     64     logger.error(f"Known compatible baudrates={BAUDRATES}")
     65     logger.error("To force baudrate, pass in your own serial_connection")
---> 66 self._con = serial.Serial(port=port, baudrate=baudrate, timeout=timeout)

File ~/notebook/.venv/lib/python3.10/site-packages/serial/serialutil.py:240, in SerialBase.__init__(self, port, baudrate, bytesize, parity, stopbits, timeout, xonxoff, rtscts, write_timeout, dsrdtr, inter_byte_timeout, exclusive, **kwargs)
    237     raise ValueError('unexpected keyword arguments: {!r}'.format(kwargs))
    239 if port is not None:
--> 240     self.open()

File ~/notebook/.venv/lib/python3.10/site-packages/serial/serialposix.py:286, in Serial.open(self)
    284 try:
    285     if not self._dsrdtr:
--> 286         self._update_dtr_state()
    287     if not self._rtscts:
    288         self._update_rts_state()

File ~/notebook/.venv/lib/python3.10/site-packages/serial/serialposix.py:634, in Serial._update_dtr_state(self)
    632 """Set terminal status line: Data Terminal Ready"""
    633 if self._dtr_state:
--> 634     fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
    635 else:
    636     fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)

TimeoutError: [Errno 110] Connection timed out
Wikilicious commented 4 months ago

related #103