Skip to content

Establishing Connections ​

Aidlab SDK lets you discover and connect to Aidlab, Aidlab 2, and Aidmed One. Typical workflow: import the SDK, initialize the manager and delegate, scan for available devices, then establish a connection and start collecting data.

Imports ​

Import the SDK into the file that will manage device connections and handle events.

python
from aidlab import AidlabManager, DeviceDelegate, DataType
kotlin
import com.aidlab.sdk.*
swift
import Aidlab
import Foundation
dart
import 'dart:async';

import 'package:aidlab_sdk/aidlab_sdk.dart';
csharp
using UnityEngine;
using Aidlab;

Create the manager ​

The manager discovers nearby devices. Your delegate or event handlers receive connection and data events. Implement the connection, disconnection, and error callbacks; all other callbacks are optional. In Flutter, mix in or extend DeviceDelegate to inherit the optional callbacks.

Callbacks run synchronously. Return quickly and move slow work elsewhere: the SDK acknowledges device data after its callbacks return, and Aidlab 2 disconnects when an acknowledgement is late.

python
class MainManager(DeviceDelegate):
    async def did_connect(self, device):
        print("Connected to:", device.address)

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

    def did_receive_error(self, device, error):
        print("Error:", error)
kotlin
class MainActivity : ComponentActivity(), DeviceDelegate, AidlabManagerDelegate {
    private lateinit var aidlabManager: AidlabManager
    private var device: Device? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        aidlabManager = AidlabManager(this, this)
    }

    override fun didConnect(device: Device) {
        println("Connected to: ${device.address()}")
    }

    override fun didDisconnect(device: Device, disconnectReason: DisconnectReason) {
        if (this.device === device) this.device = null
    }

    override fun didReceiveError(device: Device, error: AidlabError) {
        println("Error: $error")
    }
}
swift
final class DeviceController: AidlabManagerDelegate, DeviceDelegate {
    private lazy var aidlabManager = AidlabManager(delegate: self)
    private var device: Device?

    func didConnect(_ device: Device) {
        print("Connected to: \(device.address)")
    }

    func didDisconnect(_ device: Device, reason: DisconnectReason) {
        if self.device === device { self.device = nil }
    }

    func didReceiveError(_ device: Device, error: AidlabError) {
        print("Error: \(error)")
    }
}
dart
class _HomePageState extends State<HomePage>
    with DeviceDelegate, AidlabManagerDelegate {
  late final AidlabManager aidlabManager = AidlabManager(this);
  Device? device;

  @override
  Future<void> didConnect(Device device) async {
    print('Connected to: ${device.address}');
  }

  @override
  void didDisconnect(Device device, DisconnectReason reason) {
    if (identical(this.device, device)) this.device = null;
  }

  @override
  void didReceiveError(Device device, AidlabError error) {
    print('Error: $error');
  }
}
csharp
// Android, iOS, macOS, and Windows:
Aidlab.AidlabSDK.init();           // scans for the default "Aidlab" name
Aidlab.AidlabSDK.init("Aidlab 2"); // optional device name filter

If your app already handles Bluetooth discovery or connections, see Custom Transport to use that setup with the SDK.

Scan and connect ​

With Bluetooth enabled and the required permissions granted, scan for nearby devices and connect to one of the results. Wait for the connection event before starting data collection.

python
import asyncio

class MainManager(DeviceDelegate):
    async def run(self):
        devices = await AidlabManager().scan()
        if devices:
            print("Connecting to:", devices[0].address)
            await devices[0].connect(self)
            while True:
                await asyncio.sleep(1)

asyncio.run(MainManager().run())
kotlin
fun onBluetoothRequestsGranted() {
    aidlabManager.scan()
}

override fun didDiscover(device: Device, rssi: Int) {
    // Every advertisement reports a new Device: connect only to the first one.
    if (this.device != null) return
    this.device = device
    aidlabManager.stopScan()
    lifecycleScope.launch {
        try {
            device.connect(this@MainActivity)
        } catch (error: IllegalStateException) {
            this@MainActivity.device = null
            println("Connection failed: ${error.message}")
        }
    }
}

override fun onDeviceScanFailed(errorCode: Int) {
    println("Scan failed: $errorCode")
}
// Ensure Bluetooth/location permissions are granted before calling scan()
swift
func startScan() {
    aidlabManager.scan()
}

func didDiscover(_ device: Device) {
    // Every advertisement reports the device again: connect only once.
    guard self.device == nil else { return }
    self.device = device
    aidlabManager.stopScan()
    Task {
        do {
            try await device.connect(delegate: self)
        } catch {
            self.device = nil
            print("Connection failed: \(error)")
        }
    }
}
dart
Future<void> startScan() async {
  await aidlabManager.scan(ScanMode.aggressive);
}

@override
void didDiscover(Device device, int rssi) {
  // Every advertisement reports a new Device: connect only to the first one.
  if (this.device != null) return;
  this.device = device;
  unawaited(connectTo(device));
}

@override
void onScanFailed(int errorCode) {
  print('Scan failed: $errorCode');
}

Future<void> connectTo(Device device) async {
  try {
    await aidlabManager.stopScan();
    await device.connect(this);
  } catch (error) {
    if (identical(this.device, device)) this.device = null;
    print('Connection failed: $error');
  }
}
csharp
void Start() {
    Aidlab.AidlabSDK.init("Aidlab");
    // The Android backend requests runtime BLE permission before scanning.
}

connect returns after didConnect and throws when the connection cannot be established; didDisconnect follows only a connection that succeeded. Connect each physical device through one Device at a time: connecting another Device to the same address throws. In Python and Flutter, each Device supports one connection attempt. To retry or reconnect, scan again and connect using a newly discovered Device.

Device discovery

Bluetooth scanning relies on radio signals, so immediate discovery is not guaranteed. Keep the scan active and report scan failures instead of assuming that a device will appear immediately.

After connecting, firmwareRevision, hardwareRevision and serialNumber (firmware_revision, hardware_revision, serial_number in Python) identify the device. Compare firmwareRevision with the minimum firmware in Data Types and Events.

To connect to a specific device, see Connecting to a Specified Device.

Disconnect ​

Call disconnect() when you no longer need the connection. The delegate then receives the disconnection callback. In Unity, disable the AidlabSDK component; enabling it scans and connects again.

python
try:
    await device.connect(self)
    await asyncio.sleep(60)  # receive data for one minute
finally:
    await device.disconnect()
kotlin
override fun onDestroy() {
    device?.disconnect()
    super.onDestroy()
}
swift
func stop() {
    device?.disconnect()
}
dart
@override
void dispose() {
  unawaited(device?.disconnect());
  super.dispose();
}
csharp
public void Disconnect() {
    var sdk = FindAnyObjectByType<Aidlab.AidlabSDK>();
    if (sdk != null) sdk.enabled = false;
}