You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've got an ESP32-S3 + TinyUSB project that creates two CDC serial devices. On macOS and Linux these always enumerate in a consistent order, and thus I'm able to sort them trivially (e.g. on macOS /dev/cu.usbmodemmyproj1, /dev/cu.usbmodemmyproj3).
However, Windows does not do this and will sometimes reorder the COM numbers, such that the lower COM number may be the second port instantiated from TinyUSB. This is a problem as there seems to be no way with pyserial's list_ports method to determine the correct ordering of the ports. I've tried to sort by usb_info which includes the location, but location is only present on one of the two devices and it's not necessarily the first TinyUSB device. These are the two ports:
I have a workaround using pywin32 that queries for serial devices, and then sorts by the MI_# string that's present in the PNPDeviceID (which consistently orders the ports correctly). This guarantees I can always pick the correct port even if the COM ordering is reversed.
deffind_windows_com_ports(vid, pid, serial_number=None):
importwin32com.client# Caution: GPT says `Win32_SerialPort` isn't reliable with USB devices.# But using `Win32_PnPEntity` requires parsing the COM port out of the# `Name`` which seems like it might break on Chinese language systems.# Seems to work for me.wmi=win32com.client.GetObject("winmgmts:")
query=f"SELECT * FROM Win32_SerialPort"serial_ports= []
fordeviceinwmi.ExecQuery(query):
logger.info(f"Found COM port: {device.DeviceID}{device.PNPDeviceID}")
ifdevice.PNPDeviceIDandf"VID_{vid}&PID_{pid}"indevice.PNPDeviceID:
com_port=device.DeviceID# Extract MI_ number from DeviceID# Not exactly sure what this is but it seems to consistently enumerate in a# consistent order for the two USB devices, regardless of the COM port ordermi_match=re.search(r"MI_([0-9A-F]+)", device.PNPDeviceID)
mi=mi_match.group(1) ifmi_matchelse"Unknown"# If we had a way to get the "Bus reported device description" here that'd work too# and be more consistent with other platforms. But we don't, and I guess it's hard?# See also: https://github.com/pyserial/pyserial/pull/338ifserial_numberisnotNone:
ports=list_ports.grep(com_port)
port=next(ports)
ifport.serial_number!=serial_number:
logger.info(f"Skipping {com_port} ({serial_number} != {port.serial_number})")
continueserial_ports.append((com_port, mi))
# Sort by the second field (MI number)serial_ports.sort(key=lambdax: x[1])
return [port[0] forportinserial_ports]
I don't love this workaround since it requires an additional dependency on Windows (pywin32) and is a special code path to maintain and test only for Windows.
I'm opening this issue to discuss other ways of capturing the device order in a way that can be exposed in serial.tools.list_ports. Exposing the MI_ number that pywin32 has could solve the problem. Or if we could get LOCATION included on both ports that would probably also solve the issue. Or possibly there's a more elegant solution I'm not informed enough to reason about!
I've got an ESP32-S3 + TinyUSB project that creates two CDC serial devices. On macOS and Linux these always enumerate in a consistent order, and thus I'm able to sort them trivially (e.g. on macOS
/dev/cu.usbmodemmyproj1
,/dev/cu.usbmodemmyproj3
).However, Windows does not do this and will sometimes reorder the
COM
numbers, such that the lowerCOM
number may be the second port instantiated from TinyUSB. This is a problem as there seems to be no way withpyserial
'slist_ports
method to determine the correct ordering of the ports. I've tried to sort byusb_info
which includes thelocation
, butlocation
is only present on one of the two devices and it's not necessarily the first TinyUSB device. These are the two ports:I have a workaround using
pywin32
that queries for serial devices, and then sorts by theMI_#
string that's present in thePNPDeviceID
(which consistently orders the ports correctly). This guarantees I can always pick the correct port even if theCOM
ordering is reversed.I don't love this workaround since it requires an additional dependency on Windows (
pywin32
) and is a special code path to maintain and test only for Windows.I'm opening this issue to discuss other ways of capturing the device order in a way that can be exposed in
serial.tools.list_ports
. Exposing theMI_
number thatpywin32
has could solve the problem. Or if we could getLOCATION
included on both ports that would probably also solve the issue. Or possibly there's a more elegant solution I'm not informed enough to reason about!This issue has been cloned from: pyserial#767
The text was updated successfully, but these errors were encountered: