Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connection params #211

Merged
merged 5 commits into from
Jan 11, 2024
Merged

Connection params #211

merged 5 commits into from
Jan 11, 2024

Conversation

aykevl
Copy link
Member

@aykevl aykevl commented Dec 25, 2023

Work in progress: I haven't added macOS support yet. done

This is a PR that changes a few things to make Device objects usable in peripheral mode (when another device connects to it):

  • It changes *Device to Device. This is a breaking change, but makes things a lot easier to deal with on a SoftDevice (no difficult workarounds needed to avoid allocating a heap object in the interrupt handler).
  • It changes SetConnectHandler so that a Device is passed instead of just the address of the connecting device. This is another breaking change, but necessary to support this feature (without ugly hacks). Hopefully this is the last breaking change to SetConnectHandler.
  • It now loads the connecting device MAC address, which was previously empty.
  • It adds SetConnectionLatency which is necessary for battery operated devices to lower the connection latency and with that lower the current consumption (for example, it lowers the current consumed from 85µA to 10µA according to the online power profiler). This change was my original motivation for this PR.

Discovering services and characteristics was already implemented for central mode, and I've found it works just as well in peripheral mode on the SoftDevice.

Tested:

  • This works well on the Circuit Playground Bluefruit.
  • This doesn't work correctly on Linux (but it doesn't crash either): it doesn't seem to call the connection handler callback.
  • Same for macOS. I don't think it would be very difficult to implement, but preferably it would need advertising support first.
  • I haven't tested it on Windows because I don't have easy access to a Windows installation with Bluetooth access. Might try this in my Windows VM though. The smoke test says it compiles.

@aykevl aykevl force-pushed the connection-params branch 3 times, most recently from 5376bd2 to 3e7fbab Compare December 26, 2023 13:25
@aykevl aykevl marked this pull request as ready for review December 26, 2023 13:32
@aykevl
Copy link
Member Author

aykevl commented Dec 26, 2023

This PR is ready for review.

@aykevl aykevl force-pushed the connection-params branch from 3e7fbab to b7e1e1c Compare January 4, 2024 14:01
@aykevl
Copy link
Member Author

aykevl commented Jan 4, 2024

Rebased after #216 was merged.

This PR is essential to keep the PineTime connected at low power. The default connection latency drains too much power.

@aykevl aykevl force-pushed the connection-params branch from b7e1e1c to 5c15b8e Compare January 4, 2024 14:04
@aykevl
Copy link
Member Author

aykevl commented Jan 4, 2024

Oops, messed up the rebase. I'll fix this PR soon.

@aykevl aykevl force-pushed the connection-params branch from 5c15b8e to 31d0fec Compare January 5, 2024 15:07
@aykevl
Copy link
Member Author

aykevl commented Jan 5, 2024

This should now be fixed. Changes:

  • Rebased on the dev branch and fixed the merge conflicts.
  • Merged ConnectionLatency struct into ConnectionParams, and renamed SetConnectionLatency to RequestConnectionParams. The reason is that these are connection parameters and in fact all fields (except ConnectionTimeout do have the same meaning in both cases.
  • Added stub support for NINA.

@deadprogram
Copy link
Member

@aykevl can you please rebase this branch and resolve merge conflict?

aykevl added 5 commits January 6, 2024 14:01
This is very useful for debugging, though we should probably expose this
in some way to users of the bluetooth package without changing a
constant.
I thought it wasn't available, but in fact it is. So let's make it
available in the connect handler.
This is a refactor that is necessary to make it easier to work with
connected central devices on a SoftDevice.
This makes it possible to discover services on a connected central while
in peripheral mode, for example.
This allows changing the connection latency, slave latency, and
connection timeout of an active connection - whether in the central or
peripheral role. This is especially helpful on battery operated BLE
devices that don't have a lot of power and need to lower the connection
latency for improved speed. It might also be useful for devices that
need high speed, as the defaults might be too low.
@aykevl aykevl force-pushed the connection-params branch from 31d0fec to f6af395 Compare January 6, 2024 13:14
@aykevl
Copy link
Member Author

aykevl commented Jan 6, 2024

I've fixed the merge conflicts.

@deadprogram
Copy link
Member

@Ayke, notifications on the ninafw do not work unless this patch is applied to your PR:

--- a/adapter_ninafw.go
+++ b/adapter_ninafw.go
@@ -21,7 +21,7 @@ type Adapter struct {
 
        connectHandler func(device Device, connected bool)
 
-       connectedDevices     []Device
+       connectedDevices     []*Device
        notificationsStarted bool
 }
 
@@ -33,7 +33,7 @@ var DefaultAdapter = &Adapter{
        connectHandler: func(device Device, connected bool) {
                return
        },
-       connectedDevices: make([]Device, 0, maxConnections),
+       connectedDevices: make([]*Device, 0, maxConnections),
 }
 
 // Enable configures the BLE stack. It must be called before any
@@ -197,7 +197,7 @@ func (a *Adapter) startNotifications() {
        }()
 }
 
-func (a *Adapter) findDevice(handle uint16) Device {
+func (a *Adapter) findDevice(handle uint16) *Device {
        for _, d := range a.connectedDevices {
                if d.handle == handle {
                        if _debug {
@@ -208,5 +208,5 @@ func (a *Adapter) findDevice(handle uint16) Device {
                }
        }
 
-       return Device{}
+       return nil
 }
diff --git a/gap_ninafw.go b/gap_ninafw.go
index 5cf7840..61d743e 100644
--- a/gap_ninafw.go
+++ b/gap_ninafw.go
@@ -176,7 +176,7 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, err
                                        notificationRegistrations: make([]notificationRegistration, 0),
                                },
                        }
-                       a.connectedDevices = append(a.connectedDevices, d)
+                       a.connectedDevices = append(a.connectedDevices, &d)
 
                        return d, nil
 
@@ -226,7 +226,7 @@ func (d Device) Disconnect() error {
                return err
        }
 
-       d.adapter.connectedDevices = []Device{}
+       d.adapter.connectedDevices = []*Device{}
        return nil
 }

@aykevl
Copy link
Member Author

aykevl commented Jan 11, 2024

@Ayke, notifications on the ninafw do not work unless this patch is applied to your PR:

Huh that's odd.
How did you test this? I'd like to try to reproduce this.

@deadprogram
Copy link
Member

OK just tried again and now I cannot repro this myself. I tried on both nano-rp2040 and pyportal, and it worked as expected.

Maybe my local config was messed up at the time? Sounds like time to merge. Thanks for working on this @aykevl

@deadprogram deadprogram merged commit d74f6a1 into dev Jan 11, 2024
5 checks passed
@deadprogram deadprogram deleted the connection-params branch January 11, 2024 14:53
@aykevl
Copy link
Member Author

aykevl commented Jan 11, 2024

Thank you! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants