add device and port detection on linux

This commit is contained in:
Mike Kinney
2022-01-30 00:57:56 +00:00
parent 069056edad
commit 28a2aa47e8
20 changed files with 1350 additions and 0 deletions

137
meshtastic/supported_device.py Executable file
View File

@@ -0,0 +1,137 @@
""" Supported Meshtastic Devices - This is a class and collection of Meshtastic devices.
It is used for auto detection as to which device might be connected.
"""
import platform
import subprocess
# Goal is to detect which device and port to use from the supported devices
# without installing any libraries that are not currently in the python meshtastic library
class SupportedDevice():
"""Devices supported on Meshtastic"""
def __init__(self, name, version=None, for_firmware=None, device_class="esp32",
baseport_on_linux=None, baseport_on_mac=None, baseport_on_windows="COM",
usb_vendor_id_in_hex=None, usb_product_id_in_hex=None):
""" constructor """
self.name = name
self.version = version
self.for_firmware = for_firmware
self.device_class = device_class # could be "nrf52"
# when you run "lsusb -d xxxx:" in linux
self.usb_vendor_id_in_hex = usb_vendor_id_in_hex # store in lower case
self.usb_product_id_in_hex = usb_product_id_in_hex # store in lower case
self.baseport_on_linux = baseport_on_linux # ex: ttyUSB or ttyACM
self.baseport_on_mac = baseport_on_mac
self.baseport_on_windows = baseport_on_windows
# supported devices
tbeam_v0_7 = SupportedDevice(name="T-Beam", version="0.7", for_firmware="tbeam0.7",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
tbeam_v1_1 = SupportedDevice(name="T-Beam", version="1.1", for_firmware="tbeam",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
tbeam_M8N = SupportedDevice(name="T-Beam", version="M8N", for_firmware="tbeam",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
tbeam_M8N_SX1262 = SupportedDevice(name="T-Beam", version="M8N_SX1262", for_firmware="tbeam",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
tlora_v1_1 = SupportedDevice(name="T-Lora", version="1.1", for_firmware="tlora-v1",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
tlora_v1_3 = SupportedDevice(name="T-Lora", version="1.3", for_firmware="tlora-v1-3",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
tlora_v2_0 = SupportedDevice(name="T-Lora", version="2.0", for_firmware="tlora-v2-1",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
tlora_v2_1 = SupportedDevice(name="T-Lora", version="2.1", for_firmware="tlora-v2-1",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
tlora_v2_1_1_6 = SupportedDevice(name="T-Lora", version="2.1-1.6", for_firmware="tlora-v2-1-1.6",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="1a86", usb_product_id_in_hex="55d4")
heltec_v1 = SupportedDevice(name="Heltec", version="1", for_firmware="heltec-v1",
baseport_on_linux="ttyUSB", baseport_on_mac="ttyUSB",
usb_vendor_id_in_hex="10c4", usb_product_id_in_hex="ea60")
heltec_v2_0 = SupportedDevice(name="Heltec", version="2.0", for_firmware="heltec-v2.0",
baseport_on_linux="ttyUSB", baseport_on_mac="ttyUSB",
usb_vendor_id_in_hex="10c4", usb_product_id_in_hex="ea60")
heltec_v2_1 = SupportedDevice(name="Heltec", version="2.1", for_firmware="heltec-v2.1",
baseport_on_linux="ttyUSB", baseport_on_mac="ttyUSB",
usb_vendor_id_in_hex="10c4", usb_product_id_in_hex="ea60")
# TODO: get info on diy
meshtastic_diy_v1 = SupportedDevice(name="Meshtastic DIY", version="1", for_firmware="meshtastic-diy-v1")
# TODO: get info on TEcho
techo_1 = SupportedDevice(name="T-Echo", version="1", for_firmware="t-echo-1", device_class="nrf52")
rak4631_5005 = SupportedDevice(name="RAK 4631 5005", version="", for_firmware="rak4631_5005",
device_class="nrf52",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="239a", usb_product_id_in_hex="0029")
rak4631_19003 = SupportedDevice(name="RAK 4631 19003", version="", for_firmware="rak4631_19003",
device_class="nrf52",
baseport_on_linux="ttyACM", baseport_on_mac="cu.usbmodem",
usb_vendor_id_in_hex="239a", usb_product_id_in_hex="8029")
supported_devices = [tbeam_v0_7, tbeam_v1_1, tbeam_M8N, tbeam_M8N_SX1262,
tlora_v1_1, tlora_v1_3, tlora_v2_0, tlora_v2_1, tlora_v2_1_1_6,
heltec_v1, heltec_v2_0, heltec_v2_1,
meshtastic_diy_v1, techo_1, rak4631_5005, rak4631_19003]
def get_unique_vendor_ids():
"""Return a set of unique vendor ids"""
vids = set()
for d in supported_devices:
if d.usb_vendor_id_in_hex:
vids.add(d.usb_vendor_id_in_hex)
return vids
def get_devices_with_vendor_id(vid):
"""Return a set of unique devices with the vendor id"""
sd = set()
for d in supported_devices:
if d.usb_vendor_id_in_hex == vid:
sd.add(d)
return sd
def active_ports_on_supported_devices(sds):
"""Return a set of active ports based on the supplied supported devices"""
ports = set()
baseports = set()
system = platform.system()
# figure out what possible base ports there are
for d in sds:
if system == "Linux":
baseports.add(d.baseport_on_linux)
elif system == "Darwin":
baseports.add(d.baseport_on_mac)
elif system == "Windows":
baseports.add(d.baseport_on_windows)
for bp in baseports:
if system == "Linux":
# see if we have any devices (ignoring any stderr output)
command = f'ls -al /dev/{bp}* 2> /dev/null'
#print(f'command:{command}')
_, ls_output = subprocess.getstatusoutput(command)
#print(f'ls_output:{ls_output}')
# if we got output, there are ports
if len(ls_output) > 0:
#print('got output')
# for each line of output
lines = ls_output.split('\n')
#print(f'lines:{lines}')
for line in lines:
parts = line.split(' ')
#print(f'parts:{parts}')
port = parts[-1]
#print(f'port:{port}')
ports.add(port)
return ports

View File

@@ -10,9 +10,11 @@ import time
import platform
import logging
import threading
import subprocess
import serial
import serial.tools.list_ports
import pkg_resources
from meshtastic.supported_device import get_unique_vendor_ids, get_devices_with_vendor_id
"""Some devices such as a seger jlink we never want to accidentally open"""
blacklistVids = dict.fromkeys([0x1366])
@@ -257,3 +259,65 @@ def snake_to_camel(a_string):
def camel_to_snake(a_string):
"""convert camelCase to snake_case"""
return ''.join(['_'+i.lower() if i.isupper() else i for i in a_string]).lstrip('_')
def detect_supported_devices():
"""detect supported devices"""
system = platform.system()
#print(f'system:{system}')
possible_devices = set()
if system == "Linux":
# if linux, run lsusb and list ports
# linux: use lsusb
# Bus 001 Device 091: ID 10c4:ea60 Silicon Labs CP210x UART Bridge
_, lsusb_output = subprocess.getstatusoutput('lsusb')
vids = get_unique_vendor_ids()
for vid in vids:
#print(f'looking for {vid}...')
search = f' {vid}:'
#print(f'search:"{search}"')
if re.search(search, lsusb_output, re.MULTILINE):
#print(f'Found vendor id that matches')
devices = get_devices_with_vendor_id(vid)
# check device id
for device in devices:
#print(f'device:{device} device.usb_product_id_in_hex:{device.usb_product_id_in_hex}')
if device.usb_product_id_in_hex:
search = f' {vid}:{device.usb_product_id_in_hex} '
#print(f'search:"{search}"')
if re.search(search, lsusb_output, re.MULTILINE):
# concatenate the devices with vendor id to possibles
possible_devices.add(device)
else:
# if there is a supported device witout a product id, then it
# might be a match... so, concatenate
possible_devices.add(device)
elif system == "Windows":
# if windows, run Get-PnpDevice
pass
elif system == "Darwin":
# if mac, run ioreg
# could also run: system_profiler SPUSBDataType
# if mac air (eg: arm m1) do not know how to get info TODO: research
pass
# ls -al /dev/{tty,cu}.*
# crw-rw-rw- 1 root wheel 0x9000003 Jan 13 02:46 /dev/cu.Bluetooth-Incoming-Port
# crw-rw-rw- 1 root wheel 0x9000005 Jan 29 12:00 /dev/cu.usbserial-0001
# crw-rw-rw- 1 root wheel 0x9000001 Jan 13 02:45 /dev/cu.wlan-debug
# crw-rw-rw- 1 root wheel 0x9000002 Jan 13 02:46 /dev/tty.Bluetooth-Incoming-Port
# crw-rw-rw- 1 root wheel 0x9000004 Jan 29 12:00 /dev/tty.usbserial-0001
# crw-rw-rw- 1 root wheel 0x9000000 Jan 13 02:45 /dev/tty.wlan-debug
# and exclude any "Bluetooth" or "wlan" files
# TODO: which should we prefer: cu or tty devices?
# mac: ioreg -p IOUSB
# +-o Root <class IORegistryEntry, id 0x100000100, retain 27>
# +-o AppleT8103USBXHCI@00000000 <class AppleT8103USBXHCI, id 0x10000031c, registered, matched, active, busy 0 (9$
# +-o AppleT8103USBXHCI@01000000 <class AppleT8103USBXHCI, id 0x100000320, registered, matched, active, busy 0 (8$
# +-o CP2102 USB to UART Bridge Controller@01100000 <class IOUSBHostDevice, id 0x10000d096, registered, matched$
return possible_devices