Skip to content

Connecting to Multiple Devices

Example: stream Respiration from two devices at once.

  1. Turn on devices and wait for the pulsating green LED (ready to connect).
  2. Run the routine below.
  3. Wait for both connections to establish.

Examples

dart
import 'package:aidlab_sdk/aidlab_sdk.dart';

const firstAddress = '<FIRST DEVICE ADDRESS>';
const secondAddress = '<SECOND DEVICE ADDRESS>';

final class MultiDeviceController
    implements AidlabManagerDelegate, DeviceDelegate {
  MultiDeviceController() : manager = AidlabManager(null) {
    manager.delegate = this;
  }

  final AidlabManager manager;
  final Set<String> connecting = <String>{};

  Future<void> run() async {
    await manager.scan(ScanMode.aggressive);
  }

  @override
  void didDiscover(Device device, int rssi) {
    final bool isTarget =
        device.address == firstAddress || device.address == secondAddress;
    if (!isTarget || !connecting.add(device.address)) {
      return;
    }
    device.connect(this);
  }

  @override
  Future<void> didConnect(Device device) async {
    await device.collect([DataType.respiration], []);
  }

  @override
  void didDisconnect(Device device, DisconnectReason reason) {
    connecting.remove(device.address);
    print('Disconnected from: ${device.address}');
  }

  @override
  void didReceiveRespiration(Device device, int timestamp, double value) {
    print('Respiration: $value from ${device.address}');
  }
}
python
import asyncio
from aidlab import AidlabManager, DataType, DeviceDelegate

FIRST_ADDRESS = "<FIRST DEVICE ADDRESS>"
SECOND_ADDRESS = "<SECOND DEVICE ADDRESS>"

class MainManager(DeviceDelegate):
    async def run(self):
        devices = await AidlabManager().scan()
        first = next((d for d in devices if d.address == FIRST_ADDRESS), None)
        second = next((d for d in devices if d.address == SECOND_ADDRESS), None)
        if first:
            await first.connect(self)
        if second:
            await second.connect(self)
        while True:
            await asyncio.sleep(1)

    async def did_connect(self, device):
        await device.collect([DataType.RESPIRATION], [])

    def did_disconnect(self, device):
        print("Disconnected from:", device.address)

    def did_receive_respiration(self, device, _, value):
        print("Respiration:", value, device.address)

asyncio.run(MainManager().run())
swift
let firstDeviceAddress = "<FIRST DEVICE UUID>"
let secondDeviceAddress = "<SECOND DEVICE UUID>"

@MainActor
final class MainManager: AidlabManagerDelegate, DeviceDelegate {
    private let aidlabManager: AidlabManager
    private var connected: Set<UUID> = []

    init() {
        aidlabManager = AidlabManager(delegate: self)
    }

    func run() { aidlabManager.scan() }

    func didDiscover(_ device: Device) {
        let addr = device.address.uuidString
        guard addr == firstDeviceAddress || addr == secondDeviceAddress else { return }
        guard connected.insert(device.address).inserted else { return }
        device.connect(delegate: self) // errors via didReceiveError / didDisconnect
    }

    func didConnect(_ device: Device) {
        device.collect(dataTypes: [.respiration], dataTypesToStore: [])
    }

    func didDisconnect(_ device: Device, reason _: DisconnectReason) {
        connected.remove(device.address)
        print("Disconnected from: \(device.address.uuidString)")
    }

    func didReceiveRespiration(_ device: Device, timestamp: UInt64, value: Float) {
        print("Respiration: \(value) from \(device.address.uuidString)")
    }
}

Tip: filter by address to avoid connecting to unintended devices when many are nearby.

Troubleshooting

  • Connection stability depends on the Bluetooth chipset. More than ~5 devices per dongle can get flaky.
  • In tests, each BT dongle on a Raspberry Pi held ~5 devices; total stable connections scale with the number of dongles.
  • Real-world limits vary by hardware and chipset version.