Module meshtastic.serial_interface
Serial interface class
Expand source code
""" Serial interface class
"""
import logging
import platform
import os
import stat
import serial
from .stream_interface import StreamInterface
from .util import findPorts, our_exit
class SerialInterface(StreamInterface):
"""Interface class for meshtastic devices over a serial link"""
def __init__(self, devPath=None, debugOut=None, noProto=False, connectNow=True):
"""Constructor, opens a connection to a specified serial port, or if unspecified try to
find one Meshtastic device by probing
Keyword Arguments:
devPath {string} -- A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
debugOut {stream} -- If a stream is provided, any debug serial output from the device will be emitted to that stream. (default: {None})
"""
if devPath is None:
ports = findPorts()
logging.debug(f"ports:{ports}")
if len(ports) == 0:
our_exit("Warning: No Meshtastic devices detected.")
elif len(ports) > 1:
message = "Warning: Multiple serial ports were detected so one serial port must be specified with the '--port'.\n"
message += f" Ports detected:{ports}"
our_exit(message)
else:
devPath = ports[0]
logging.debug(f"Connecting to {devPath}")
# Note: we provide None for port here, because we will be opening it later
self.stream = serial.Serial(
None, 921600, exclusive=True, timeout=0.5, write_timeout=0)
# rts=False Needed to prevent TBEAMs resetting on OSX, because rts is connected to reset
self.stream.port = devPath
# HACK: If the platform driving the serial port is unable to leave the RTS pin in high-impedance
# mode, set RTS to false so that the device platform won't be reset spuriously.
# Linux does this properly, so don't apply this hack on Linux (because it makes the reset button not work).
if self._hostPlatformAlwaysDrivesUartRts():
self.stream.rts = False
self.stream.open()
StreamInterface.__init__(
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
"""true if platform driving the serial port is Windows Subsystem for Linux 1."""
def _isWsl1(self):
# WSL1 identifies itself as Linux, but has a special char device at /dev/lxss for use with session control,
# e.g. /init. We should treat WSL1 as Windows for the RTS-driving hack because the underlying platfrom
# serial driver for the CP21xx still exhibits the buggy behavior.
# WSL2 is not covered here, as it does not (as of 2021-May-25) support the appropriate functionality to
# share or pass-through serial ports.
try:
# Claims to be Linux, but has /dev/lxss; must be WSL 1
return platform.system() == 'Linux' and stat.S_ISCHR(os.stat('/dev/lxss').st_mode)
except:
# Couldn't stat /dev/lxss special device; not WSL1
return False
def _hostPlatformAlwaysDrivesUartRts(self):
# OS-X/Windows seems to have a bug in its CP21xx serial drivers. It ignores that we asked for no RTSCTS
# control and will always drive RTS either high or low (rather than letting the CP102 leave
# it as an open-collector floating pin).
# TODO: When WSL2 supports USB passthrough, this will get messier. If/when WSL2 gets virtual serial
# ports that "share" the Windows serial port (and thus the Windows drivers), this code will need to be
# updated to reflect that as well -- or if T-Beams get made with an alternate USB to UART bridge that has
# a less buggy driver.
return platform.system() != 'Linux' or self._isWsl1()
Classes
class SerialInterface (devPath=None, debugOut=None, noProto=False, connectNow=True)-
Interface class for meshtastic devices over a serial link
Constructor, opens a connection to a specified serial port, or if unspecified try to find one Meshtastic device by probing
Keyword Arguments: devPath {string} – A filepath to a device, i.e. /dev/ttyUSB0 (default: {None}) debugOut {stream} – If a stream is provided, any debug serial output from the device will be emitted to that stream. (default: {None})
Expand source code
class SerialInterface(StreamInterface): """Interface class for meshtastic devices over a serial link""" def __init__(self, devPath=None, debugOut=None, noProto=False, connectNow=True): """Constructor, opens a connection to a specified serial port, or if unspecified try to find one Meshtastic device by probing Keyword Arguments: devPath {string} -- A filepath to a device, i.e. /dev/ttyUSB0 (default: {None}) debugOut {stream} -- If a stream is provided, any debug serial output from the device will be emitted to that stream. (default: {None}) """ if devPath is None: ports = findPorts() logging.debug(f"ports:{ports}") if len(ports) == 0: our_exit("Warning: No Meshtastic devices detected.") elif len(ports) > 1: message = "Warning: Multiple serial ports were detected so one serial port must be specified with the '--port'.\n" message += f" Ports detected:{ports}" our_exit(message) else: devPath = ports[0] logging.debug(f"Connecting to {devPath}") # Note: we provide None for port here, because we will be opening it later self.stream = serial.Serial( None, 921600, exclusive=True, timeout=0.5, write_timeout=0) # rts=False Needed to prevent TBEAMs resetting on OSX, because rts is connected to reset self.stream.port = devPath # HACK: If the platform driving the serial port is unable to leave the RTS pin in high-impedance # mode, set RTS to false so that the device platform won't be reset spuriously. # Linux does this properly, so don't apply this hack on Linux (because it makes the reset button not work). if self._hostPlatformAlwaysDrivesUartRts(): self.stream.rts = False self.stream.open() StreamInterface.__init__( self, debugOut=debugOut, noProto=noProto, connectNow=connectNow) """true if platform driving the serial port is Windows Subsystem for Linux 1.""" def _isWsl1(self): # WSL1 identifies itself as Linux, but has a special char device at /dev/lxss for use with session control, # e.g. /init. We should treat WSL1 as Windows for the RTS-driving hack because the underlying platfrom # serial driver for the CP21xx still exhibits the buggy behavior. # WSL2 is not covered here, as it does not (as of 2021-May-25) support the appropriate functionality to # share or pass-through serial ports. try: # Claims to be Linux, but has /dev/lxss; must be WSL 1 return platform.system() == 'Linux' and stat.S_ISCHR(os.stat('/dev/lxss').st_mode) except: # Couldn't stat /dev/lxss special device; not WSL1 return False def _hostPlatformAlwaysDrivesUartRts(self): # OS-X/Windows seems to have a bug in its CP21xx serial drivers. It ignores that we asked for no RTSCTS # control and will always drive RTS either high or low (rather than letting the CP102 leave # it as an open-collector floating pin). # TODO: When WSL2 supports USB passthrough, this will get messier. If/when WSL2 gets virtual serial # ports that "share" the Windows serial port (and thus the Windows drivers), this code will need to be # updated to reflect that as well -- or if T-Beams get made with an alternate USB to UART bridge that has # a less buggy driver. return platform.system() != 'Linux' or self._isWsl1()Ancestors
Inherited members