intercreate / smpclient

Simple Management Protocol (SMP) Client for remotely managing MCU firmware
Apache License 2.0
9 stars 6 forks source link

Add Bumble as BLE backend #15

Open JPHutchins opened 7 months ago

JPHutchins commented 7 months ago

https://google.github.io/bumble/index.html

Having multiple BLE backends available is comprised of a few steps:

  1. Add HW unit tests that perform SMP BLE operations
  2. Define the common protocol required for an SMP BLE transport
  3. Implement the protocol with Bleak and confirm no regression
  4. Implement the protocol with Bumble and add to the HW unit tests

HW that I currently have available for HW unit tests:

I also have a Boradcom BCM2070 USB BLE dongle (Plugable brand) that would be a good candidate for testing Bumble.

Sadly HW tests cannot run in GitHub workflow because this is a public repo: https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#self-hosted-runner-security

I'd love to find a way!

vChavezB commented 4 months ago

Hi @JPHutchins , Im not sure if this would be of interest but I added sometime ago support to use bumble with native posix in Zephyr. More specifically, I added an HCI TCP channel that allows an application (e.g. Android Emulator, Bleak, bumble) to communicate over a virtual channel.

This means that in theory some SMP BLE commands could be tested without hardware directly with Zephyr´s BLE SMP Transport. The limitation is that you need a linux host that is compiled with Bluetooth support (not possible with native github runners). For CI this means a dedicated machine.

JPHutchins commented 4 months ago

It seems not very likely, but my preferred approach will be to add Bumble as a backend for Bleak: https://github.com/hbldh/bleak/discussions/1588

vChavezB commented 4 months ago

that sounds like a nice approach as it would also allow to do integration tests without hardware!

vChavezB commented 4 months ago

Attached just a small test I did. Bumble controller over VHCI.

Perhaps not that practical as image management depends on MCUBoot which is not supported by native posix.

https://github.com/user-attachments/assets/a3aa19e5-e12e-4c7c-9857-a0a1371fc689

JPHutchins commented 4 months ago

Whoa, this is amazing! And you're 100% the GitHub runner can't run it?

JPHutchins commented 4 months ago

Evil question: could I host that VHCI myself and have the GitHub runner talk to remotely?

vChavezB commented 4 months ago

This is more or less the setup

graph LR
    A[Zephyr\nposix app] <-->|socket| B[Bumble\nController]<--> C[VHCI]<-->|Bluez dbus| D[Bleak]

And you're 100% the GitHub runner can't run it?

Yes, the github runner image (ubuntu) does not have the vhci linux module enabled. This requires that the kernel has enabled CONFIG_BT.

could I host that VHCI myself and have the GitHub runner talk to remotely?

As I understand it, the VHCI is just a file descriptor, so I think you could just add it as a remote service, perhaps accessible with github secrets. Then add a custom bumble transport so bumble can access it or instead just make the bumble controller remotely accessible.

graph LR
    subgraph Self-hosted vhci

        C[VHCI]
    end

    subgraph Runner
            D[Bleak]
            B[Bumble\nController]
        A[Zephyr\nposix app] 
    end

    A <-->|socket| B <--> |remote\nsocket| C
    D <-->|remote\nDBus ?| C

Edit: Just some minor changes on what I think could be done with non-self-hosted github runners.

But to be honest for practical reasons I would host my own runners (Gitlab, Github, etc).

vChavezB commented 4 months ago

Just another thought, perhaps for the HW runners you could just add a Web hook so your local server runs the test for a specific commit, then reports back the result. How the result is reported back is up to you.

JPHutchins commented 4 months ago

This is a good idea as it gives more control. Yet, the goal is for contributors to be able to run a suite of hardware integration tests, and that still opens me up to arbitrary code execution. Specifically, I want to run the hardware integration tests at the contributors' commit, and they could simply commit whatever they want so that Python runs something nasty on import.

There's the possibility of manual review + run, though. I'd only submit the HW integration workflow once it's clear that the commit is OK.

It's a good idea!

vChavezB commented 1 week ago

I have been experimenting with my bumble backend for bleak and renode.

After some modifications and tinkering around with renode, I am able to emulate firmware (nrf52840) upgrades over BLE with smp client and renode. No batteries required (or in this case no Hardware) 😎

https://github.com/user-attachments/assets/89ba64aa-4dcb-4189-afd9-3e736074c3a8

I am typically able to get around 9 KB/s transfer speed, but seems that for the video the emulation performance degraded.

What I am doing is uploading the binary, write image for test , resetting the device, wait for mcuboot to do the swap and check that the version changed.

JPHutchins commented 1 week ago

I have been experimenting with my bumble backend for bleak and renode.

After some modifications and tinkering around with renode, I am able to emulate firmware (nrf52840) upgrades over BLE with smp client and renode. No batteries required (or in this case no Hardware) 😎

https://github.com/user-attachments/assets/89ba64aa-4dcb-4189-afd9-3e736074c3a8

I am typically able to get around 9 KB/s transfer speed, but seems that for the video the emulation performance degraded.

What I am doing is uploading the binary, write image for test , resetting the device, wait for mcuboot to do the swap and check that the version changed.

Wow, this is incredible! I haven't tried Renode yet, partially because it sounded "too good to be true" - what do you think about it?

We are maintaining HW regression tests here, https://github.com/intercreate/smpclient/tree/main/examples, they may be useful.

I'd love to get this working in a GitHub workflow at smpclient.

Reminds me to review the Bleak PR again.

vChavezB commented 1 week ago

what do you think about it?

I think that it is a quite handy tool if the peripherals you are interested are supported. You can also write your own drivers (C# and Iron Python). For Bluetooth I find it quite nice (with certain limitations) to emulate connection between different MCUs.

Renode doesnt support exposing a bluetooth radio PHY over a port. I had to use an HCI UART in my Zephyr App and expose this over a port in renode. Then I connected it to the bumble bleak backend.

I tried doing firmware upgrade with the NRF Connect app with Android emulator over bumble but it did not work. The transmission always failed midway. Probably have to tinker with emulation settings.

I'd love to get this working in a GitHub workflow at smpclient.

The integration was not straight forward. I had to develop my own Renode drivers as the Flash controller is not supported. With out it, mcuboot does not work. If you just want to test communication (without bootloader) I think you dont need the extra drivers. In addition I had to tweak with emulation settings to make bluetooth work nicely. If I have some time I will send a PR to the folks of Renode to get support for the Flash controller.

I am currently running this in a pipeline and it works. However, I need to sync the execution of renode and smp client. If the firmware in renode starts too fast and bumble hasnt started yet it will crash as the BT host from zephyr (emulated in renode) will assert.

If I find a nicer way to make it run on a pipeline stabily I will keep you updated. There is a renode python library but so far I havent been able to make it work.