NordicSemiconductor / IOS-nRF-Connect-Device-Manager

A mobile management library for devices supporting nRF Connect Device Manager.
https://www.nordicsemi.com/Software-and-tools/Software/nRF-Connect-SDK
Apache License 2.0
86 stars 37 forks source link

SUIT version does not update device #200

Closed algom-gchauvelin closed 3 months ago

algom-gchauvelin commented 4 months ago

Hi, I have tested v1.4.3 updating device using mcumgr, it was working. Now I am testing version v1.6 including SUIT, so I had SHA256 of my binary file into start method :

try self.dfuManager!.start(hash: hash256, data: self.imageData!, using: configuration)

With this new method upload is done until 100% then I have the status "COMPLETED", the device reboot but it is still with previous version. Do you know why?

The SHA256 of the signed binary file is calculated as follow :

shasum -a 256 binary.signed.bin

This return string and string is convert as hex and the as Data like this :

    func hexToData(hex: String) -> Data? {
        var hexWithoutPrefix = hex
        if hex.hasPrefix("0x") || hex.hasPrefix("0X") {
            hexWithoutPrefix = String(hex.dropFirst(2))
        }

        let len = hexWithoutPrefix.count
        guard len % 2 == 0 else { return nil }

        var data = Data(capacity: len / 2)
        var index = hexWithoutPrefix.startIndex

        for _ in 0 ..< len / 2 {
            let byteString = String(hexWithoutPrefix[index ..< hexWithoutPrefix.index(index, offsetBy: 2)])
            if let byte = UInt8(byteString, radix: 16) {
                data.append(byte)
            } else {
                return nil // Invalid hex string
            }
            index = hexWithoutPrefix.index(index, offsetBy: 2)
        }

        return data
    }

By advanced, thanks

algom-gchauvelin commented 4 months ago

I missed to indicate that on Android version, start method does not ask for hash.

dinesharjani commented 3 months ago

So it has the previous version and the hash matches?

I've done a round of testing after reading your issue, and it seems to work with the sample firmware / SUIT file that I have. Both version and hash values change after checking with LIST Command.

algom-gchauvelin commented 3 months ago

In my side I have only binary file, not firmware/SUIT.

Now it worked using following configuration :

        // Initialize the BLE transporter using a scanned peripheral
        self.bleTransport = McuMgrBleTransport(self.cbPeripheral!)

        // Initialize the FirmwareUpgradeManager using the transport and a delegate
        self.dfuManager = FirmwareUpgradeManager(transporter: self.bleTransport!, delegate: self)

        // Set Configuration for SUIT
        var configuration = FirmwareUpgradeConfiguration()
        // Other Upgrade Modes can be set, but upgrade will fail since
        // SUIT doesn't support TEST and CONFIRM commands for example.
        configuration.upgradeMode = .testAndConfirm
        configuration.estimatedSwapTime = 45
        configuration.eraseAppSettings = false
        configuration.suitMode = false

        // Start the firmware upgrade with the image data
        do{
            let mcuMgrImage:McuMgrImage = try McuMgrImage(data: self.imageData!)
            var image: [ImageManager.Image] = []
            image.append(ImageManager.Image(image: 0, hash: mcuMgrImage.hash, data: mcuMgrImage.data))
            try self.dfuManager!.start(images: image)
        }catch let error {
            print(error.localizedDescription)
        }

but COMPLETED status is given just after RESET status, it seems that does not wait for estimatedSwapTime

dinesharjani commented 3 months ago

ah, but then this is regular McuMgr single core / image update, correct?

algom-gchauvelin commented 3 months ago

Yes correct

dinesharjani commented 3 months ago

The hash envelope methods are for SUIT, not 'normal' mcumgr image update. For those, the hash can be obtained this way:

let imageHash = try McuMgrImage(data: imageData).hash

I updated the Readme just yesterday to include this, among other things.

Also, the "suitMode" is false by default, so if you remove that line, it should work exactly the same as before.

algom-gchauvelin commented 3 months ago

Ok, many thanks for your help. And concerning COMPLETED status which is given just after reset, do you know if it is normal? With Android version COMPLETED status is given after RESET then waiting for swap time then CONFIRMED and COMPLETED.

dinesharjani commented 3 months ago

So, looking at your code... you're setting up a configuration variable, but you're not giving it to the FirmwareUpgradeManager to use. The API call is:

try self.dfuManager?.start(images: images, using: configuration)

Also, none of my business, but if possible don't use force-unwraps (the !) in Swift ;)

algom-gchauvelin commented 3 months ago

Oupss sorry, effectively it was a big mistake. Sorry for this question. Work better now, same behavior as Android version.

Thank you!