Detecting a desired peripheral before starting firmware update
xaviergspintly opened this issue · 5 comments
So the below is where a peripheral is set before initiating the firmware process:
let controller = initiator.start(target: peripheral)
I understand that this is after a device has been put into DFU mode.
If i'm already connected to a device and I know that I want to upload to that device, but after putting in DFU, the device gets disconnected.
Now if there are more that one device in DFU mode while I'm scanning for a device for firmware update, how do I select my device of interest without having a UI selection of a peripheral?
Does the peripheral Id change when in DFU mode as compared to normal mode?
So, 'device put into DFU mode'. I just got back from vacation so I might get things wrong. But, 'DFU Mode' is really that the Device advertises that it supports the Legacy DFU system, which is the one this library addresses. If you're trying to DFU using the more modern McuMgr / Zephyr derived system, this is the wrong library. The correct one is this: https://github.com/NordicSemiconductor/IOS-nRF-Connect-Device-Manager
Yes, the device getting disconnected when DFU starts is a normal thing. This is because to finish DFU, the device must restart into the new uploaded firmware to finish. Therefore, disconnection is expected.
As for 'peripheral id', you mean the Device's UUID or MAC Address ? This is not visible from iOS / Apple libraries. But if memory serves me right, the MAC Address is derived from physical hardware not software, so it should not change. But the ID or UUID Apple exposes through APIs, is not the MAC Address of a device. It's a randomised value that doesn't offer much value, except inform the user whether 'it's the same device', for example, if you want to connect to a device you were previously connected to between app restarts. I presume the surfaced UUID exposed by CoreBluetooth will change if we flash the firmware, or if the user goes to Settings -> Bluetooth and turns off and on Bluetooth, since this clears the device cache.
I understand that this is after a device has been put into DFU mode.
If i'm already connected to a device and I know that I want to upload to that device, but after putting in DFU, the device gets disconnected.
No, it can be also a device in app mode, with Buttonless service. The buttonless service or characteristic have changed over different nRF5 SDK versions, but all are supported. The device can also be connected, no need to disconnect.
Now if there are more that one device in DFU mode while I'm scanning for a device for firmware update, how do I select my device of interest without having a UI selection of a peripheral?
Does the peripheral Id change when in DFU mode as compared to normal mode?
If your device is based on nRF5 SDK v15 or newer it will do a "smart jump". Before sending the command to trigger the jump to bootloader mode the library is sending a random 5-digit ID. The device will start advertising with this ID as Local Name. The library will scan until this name is found. You may customize this behavior using DfuServiceInitiator
, here:
The device can also be connected, no need to disconnect.
I mean, the library will automatically send the "jump to bootlaoder" mode command and the optional name, so you don't have to worry about it.
Just start the library with the device you already have selected and connected.
If your device is based on an SDK older than 15 (or 14?), which doesn't support this alternative name, the library will use a DfuDeviceSelector
to choose the right device.
You set it here:
By default if uses the first found device advertising the correct DFU Service UUID, but you assign your own selector based on advertising data or RSSI.
@philips77 So the way we currently do it in Android is that we connect to a device in normal mode. We send it a command to put it into DFU (bootloader) mode. In Android the device shows up as the mac id of the device in normal mode +1 bit. So XX:XX:XX:XX:AB will show up as XX:XX:XX:XX:AC. We specifically connect to XX:XX:XX:XX:AC and start firmware update using nRF DFU library, since we know that it is the device we put into DFU. Now iOS doesn't have MAC IDs. All we have is peripheral IDs. How do we move through the landscape for iOS. Does the peripheral ID remain same for the same device in normal and DFU mode? Or does it increment? Or there is some other method to accurately target the device we are interested in (which we put into DFU using a command)?
In Android the device shows up as the mac id of the device in normal mode +1 bit. So XX:XX:XX:XX:AB will show up as XX:XX:XX:XX:AC. We specifically connect to XX:XX:XX:XX:AC and start firmware update using nRF DFU library, since we know that it is the device we put into DFU.
Do you use your custom way of switching to DFU bootloader mode? The library can do this on its own if you're using the DFU Buttonless Service. This works for both Legacy and Secure DFU, where in Secure DFU there's a variant with and without bonding.
Does the peripheral ID remain same for the same device in normal and DFU mode? Or does it increment?
No, it's a random one each time a device changes MAC.
Or there is some other method to accurately target the device we are interested in (which we put into DFU using a command)?
I replied here: #508 (comment)
If you're using own implementation for jumping to the bootloader mode, you may also have similar feature implemented, depending on your nRF5 SDK version and how did you implement buttonless feature. In Nordic's impl the client sends 0x02-[random name]
to the device:
https://github.com/NordicSemiconductor/IOS-DFU-Library/blob/main/Library/Classes/Implementation/SecureDFU/Services/SecureDFUService.swift#L624-L626
followed by 0x01
- the jump command. After restarting the device will advertising with the random name as Complete Local Name.