Represents a persistent unique identifier for a spectrometer device (USB, BLE, TCP, whatever) which should remain valid for connected devices in spite of hotplug events around them.
More...
Represents a persistent unique identifier for a spectrometer device (USB, BLE, TCP, whatever) which should remain valid for connected devices in spite of hotplug events around them.
- Statement of the Problem
Assume we have four WP-785 spectrometers: A, B, C and D. We connect A, B and C, then launch ENLIGHTEN. A is the first on the USB chain, so in a positional listing A would be #1, B is #2, C is #3.
Now we unplug B. That leaves us with A (1) and C (3). Except that, positionally C is really now 2. Now we plug in D. Is D now 4th on the list, or did it slip into the unoccupied 2 slot? Or was C internally moved back to 2, and now D is 3, but C also thinks it's 3?
One solution would be to UPDATE the positional order in a master list on unplug events (detecting B's removal, and changing C from 3 to 2). ENLIGHTEN could do that, but note that it would therefore be a client- side operation, not within the driver itself. Or we could move the multi-process "Controller" ownership of the several WasatchDeviceWrapper processes into Wasatch.PY, such that Wasatch.PY provided a single-object Facade. We could possibly achieve that by maintaining a list of all WasatchDeviceWrapper instances in a static WasatchDeviceWrapper attribute (or WasatchDeviceWrappers or WasatchDeviceWrapperFactory as it were). But either would require some additional refactoring that I'm not diving into right now, although it seems an improved and reasonable architecture.
Or maybe we don't need a DeviceID at all, and just track "the
WasatchDeviceWrapper associated with this serial number", and simply assume that all spectrometers will have a unique spectrometer (or be assigned one at connection). So maybe my attempt to generate a UNIQUE and PERSISTENT DeviceID from the usb.device object is quixotic and unnecessary. That's probably the case.
Part of what drove this is that historically ENLIGHTEN supported a bus_order command-line argument which explicitly referenced spectrometers by their position on the USB bus. However, we're now trying to support hotplug use-cases, meaning that position is no longer reliable. But since we had a legacy expectation of being able to explicitly identify devices at the bus level, I'm trying to retain that capability by habit. It probably is no longer needed, and we can probably replace the old –bus-order option with –serial-number instead.
More to the point, the current architecture is such that ENLIGHTEN calls WasatchBus to detect hotplug events, and then ENLIGHTEN instantiates a new WasatchDeviceWrapper to support the new bus device. That means there really ought to be a way to pass the "id" of the device, which was detected by WasatchBus, down into WasatchDeviceWrapper (and hence WasatchDevice and FeatureIdentificationDevice) to be re-instantiated. I don't trust position, I'm not sure how to confirm "claim state" (ASSUMING we wanted the "first
eligible unclaimed") , "serial number" seems heavy-handed (and would still require a way to deliberately "skip" already-connected devices, again requiring some sort of key).
ALSO we want to eventually support BLE (which has unique UUID), and perhaps TCP/IP (which has IP addresses)...basically I think objects on a "bus" should be uniquely identifiable and addressable from their bus address, WITHOUT making guesses based on position or ordering or claim-state or anything like that.
So yeah, I think this is useful.
- USB
- .vid and .pid are stored as ints
- BLE
- populates .bleak_ble_device (bleak.BLEDevice from BleakScanner)
- populates .serial_number
Adding the non-pickleable .bleak_ble_device kind of defeats some of the original intent of this class, as ideally serialized (stringified) DeviceIDs were intended to be passable between processes and "re-instantiated" on the receiving end.
However, now that ENLIGHTEN is multi-threaded (instead of multi-process), we don't have to worry about that, and it seems convenient to simply stash a handle to the Bleak Device directly in the DeviceID, where it can be passed from DeviceFinderBLE to BLEManager to WasatchDeviceWrapper/WrapperWorker to BLEDevice.
Serial number is tracked in the DeviceID (rather than DiscoveredBLEDevice) because the current DeviceID architecture is to dynamically generate its stringified form, based on internal native types.
- See also
- BLEDevice for consolidated BLE docs
- TCP