Fixes
- Multi-device support: actually drive both coolers (#128, completes v9.4.9): v9.4.9 made the detector return both same-VID:PID devices, but the transport open path still bound to the first physical device — every send went to one cooler. Now every transport (
PyUsbTransport,HidApiTransport,UsbBotScsiTransportfor macOS/BSD, plusopen_usb_devicefor Bulk/LY) binds to the specific(bus, address)the detector observed via pyusb'scustom_match. Two same-ID coolers each get their own physical device.
Refactors
UsbAddressmodel incore/models/device.py— frozen-slots dataclass that parsesusb:bus:addressstrings, matches a pyusb device by(bus, address), and stringifies cleanly.DetectedDevice.addrexposes it as a property derived fromusb_path. Threaded throughUsbProtocol,_BulkLikeProtocol,BulkFrameDevice, and the SCSI transport factory so every USB-class adapter binds by physical address rather than VID:PID alone.