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.
from aidlab import AidlabManager, DeviceDelegate, DataTypeimport com.aidlab.sdk.*import Aidlab
import Foundationimport 'dart:async';
import 'package:aidlab_sdk/aidlab_sdk.dart';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.
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)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")
}
}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)")
}
}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');
}
}// Android, iOS, macOS, and Windows:
Aidlab.AidlabSDK.init(); // scans for the default "Aidlab" name
Aidlab.AidlabSDK.init("Aidlab 2"); // optional device name filterIf 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.
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())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()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)")
}
}
}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');
}
}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.
try:
await device.connect(self)
await asyncio.sleep(60) # receive data for one minute
finally:
await device.disconnect()override fun onDestroy() {
device?.disconnect()
super.onDestroy()
}func stop() {
device?.disconnect()
}@override
void dispose() {
unawaited(device?.disconnect());
super.dispose();
}public void Disconnect() {
var sdk = FindAnyObjectByType<Aidlab.AidlabSDK>();
if (sdk != null) sdk.enabled = false;
}