Source code for pymodaq_plugins_utils.hardware.serial_ports

"""pyserial hardware discovery cache.

Wraps :mod:`serial.tools.list_ports` to enumerate available serial ports
exactly once per process. ``pyserial`` is an optional dependency: if it is
not installed, all functions return empty lists and a warning is logged.

Typical usage in a plugin::

    from pymodaq_utils.hardware.serial_ports import list_resources

    ports = list_resources()  # e.g. ['/dev/ttyUSB0', 'COM3']

After hot-plugging a device, refresh the cache with::

    from pymodaq_utils.hardware.serial_ports import invalidate_cache
    invalidate_cache()
"""
import pymodaq_utils.logger as logger_module
from .base import HardwareCache

logger = logger_module.set_logger(logger_module.get_module_name(__file__))


class SerialPortsCache(HardwareCache):
    _cache = None

    @classmethod
    def _fetch(cls) -> list:
        try:
            from serial.tools.list_ports import comports
            return list(comports())
        except ImportError:
            logger.warning('pyserial is not installed — serial port discovery unavailable. '
                           'Install it with: pip install pyserial')
            return []
        except Exception as e:
            logger.warning(f'Serial port discovery failed: {e}')
            return []

    @classmethod
    def list_resources(cls) -> list[str]:
        """Serial port device strings (e.g. '/dev/ttyUSB0', 'COM3')."""
        return [p.device for p in cls._get_cache()]

    @classmethod
    def list_port_descriptions(cls) -> list[str]:
        """Human-readable descriptions for each serial port."""
        return [p.description for p in cls._get_cache()]


[docs] def list_resources() -> list[str]: """Serial port device strings (e.g. '/dev/ttyUSB0', 'COM3').""" return SerialPortsCache.list_resources()
[docs] def list_port_descriptions() -> list[str]: """Human-readable descriptions for each serial port.""" return SerialPortsCache.list_port_descriptions()
[docs] def invalidate_cache() -> None: """Clear the serial port cache so the next call re-discovers.""" SerialPortsCache.invalidate_cache()