mirror of
https://github.com/meshtastic/python.git
synced 2026-04-21 15:34:04 -04:00
add device and port detection on linux
This commit is contained in:
137
meshtastic/supported_device.py
Executable file
137
meshtastic/supported_device.py
Executable 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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user