Skip to content

Configuration ​

After connecting, you can change settings such as LED brightness by sending commands to the device.

Sending a command ​

Use the SDK's low-level sending API to send raw command bytes to process ID 0. Include a trailing null byte (\0). Awaiting the send does not wait for the command's result. Handle that result through process output callbacks.

A payload sent to a PID above 0 goes to that process's stdin; an empty payload closes it (end of file). An empty payload to PID 0 is an error.

The following example sets LED brightness to 10:

python
# Set LED brightness to 10.
command = b"set led_brght 10\0"

await device.send(command)
kotlin
// Set LED brightness to 10.
val command = "set led_brght 10"

val payload = "$command\u0000".toByteArray(Charsets.UTF_8)
lifecycleScope.launch { device.send(payload, processId = 0) }
swift
// Set LED brightness to 10.
let command = "set led_brght 10"

let payload: [UInt8] = Array("\(command)\0".utf8)
try await device.send(payload, processId: 0)
dart
import 'dart:convert';
import 'dart:typed_data';

// Set LED brightness to 10.
const command = 'set led_brght 10';

final payload = Uint8List.fromList([...utf8.encode(command), 0]);
await device.send(payload, processId: 0);
csharp
using UnityEngine;

public class ConfigureAidlab : MonoBehaviour {
    private Aidlab.AidlabSDK sdk;

    void Start() {
        Aidlab.AidlabSDK.init();
        sdk = FindAnyObjectByType<Aidlab.AidlabSDK>();
        if (sdk == null) {
            return;
        }

        sdk.Connected += Configure;
        if (sdk.IsSdkInitialized) {
            Configure();
        }
    }

    async void Configure() {
        // Set LED brightness to 10.
        await sdk.SendCommandAsync("set led_brght 10");
    }
}

Receiving the response ​

Listen for process output callbacks in your delegate and interpret the response according to the command you sent. For the LED command above, the response is UTF-8 text followed by a newline:

text
led_brght = 10

The SDK preserves the response bytes. The examples below log them in hexadecimal so binary responses can be inspected too:

python
def did_receive_process_output(self, device, pid, payload, options=0):
    print(f"PID {pid}: {payload.hex(' ')} (options={options})")
kotlin
override fun didReceiveProcessOutput(
    device: Device,
    pid: Int,
    payload: ByteArray,
    options: Long,
) {
    val hex = payload.joinToString(" ") { "%02x".format(it.toInt() and 0xff) }
    println("PID $pid: $hex (options=$options)")
}
swift
import Foundation

func didReceiveProcessOutput(_ device: Device, pid: UInt16, payload: Data, options: UInt64) {
    let hex = payload.map { String(format: "%02x", $0) }.joined(separator: " ")
    print("PID \(pid): \(hex) (options=\(options))")
}
dart
@override
void didReceiveProcessOutput(Device device, int pid, Uint8List payload, int options) {
  final hex = payload.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(' ');
  print('PID $pid: $hex (options=$options)');
}
csharp
sdk.ProcessOutputReceived += (pid, payload, options) => {
    var hex = System.BitConverter.ToString(payload).Replace("-", " ");
    UnityEngine.Debug.Log($"PID {pid}: {hex} (options={options})");
};

One command can produce several callbacks. The LED command produces an accepted notification on PID 0, the text response on the assigned PID, and an exited notification on PID 0.

Lifecycle notifications on PID 0 start with a status byte: 0 accepted, 1 rejected, 2 exited, 3 kill failed (Aidlab 1). Bytes 1–2 hold the PID, little-endian. Aidlab 1 rejects an unknown command with the single byte 1. Send the next command after the previous one is accepted or rejected.

Output from child processes retains the PID of the process whose output they inherited. Before firmware 2.2.18, all responses use PID 0; interpret them in the context of the command you sent.

Each callback delivers the original bytes and options. Chunks may split text lines and UTF-8 characters. Combine chunks by PID and decode incrementally when you need a text response.

Process stderr is delivered separately through didReceiveProcessError (did_receive_process_error in Python, ProcessErrorReceived in Unity), with the same device, PID, payload and options arguments. Aidlab 1 does not emit stderr. processDidExit(device, pid, exitStatus) (process_did_exit in Python, ProcessExited in Unity) reports that a process exited, after all its output. exitStatus is 0 on success, or null when the firmware does not report it.

Command compatibility ​

The table below shows command examples and their availability on each device.

CommandWhat it doesAidlab 1Aidlab 2
set led_brght <value>Sets LED brightness from 1 to 16.YesYes
set ecg_fs <value>Sets ECG sampling frequency to 250, 500, or 1000 Hz.YesYes
pingReturns a ping response.YesYes
ls /dataLists files in the device's /data directory.NoYes
echo hello > /data/example.txtCreates or overwrites a file with hello.NoYes
echo again >> /data/example.txtAppends again to the file.NoYes
cat /data/example.txtReturns the file's contents through process output callbacks.NoYes
psLists running processes and their PIDs.NoYes
kill <pid>Requests termination of a process.YesYes
timeout 10 pingRuns ping with a ten-second time limit.NoYes

ECG sampling frequency

Changing the ECG sampling frequency may break compatibility with official apps. The device restarts to apply a new value. On Aidlab 2, heart rate, RR and respiration are unaffected.