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:
# Set LED brightness to 10.
command = b"set led_brght 10\0"
await device.send(command)// 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) }// 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)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);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:
led_brght = 10The SDK preserves the response bytes. The examples below log them in hexadecimal so binary responses can be inspected too:
def did_receive_process_output(self, device, pid, payload, options=0):
print(f"PID {pid}: {payload.hex(' ')} (options={options})")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)")
}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))")
}@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)');
}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.
| Command | What it does | Aidlab 1 | Aidlab 2 |
|---|---|---|---|
set led_brght <value> | Sets LED brightness from 1 to 16. | Yes | Yes |
set ecg_fs <value> | Sets ECG sampling frequency to 250, 500, or 1000 Hz. | Yes | Yes |
ping | Returns a ping response. | Yes | Yes |
ls /data | Lists files in the device's /data directory. | No | Yes |
echo hello > /data/example.txt | Creates or overwrites a file with hello. | No | Yes |
echo again >> /data/example.txt | Appends again to the file. | No | Yes |
cat /data/example.txt | Returns the file's contents through process output callbacks. | No | Yes |
ps | Lists running processes and their PIDs. | No | Yes |
kill <pid> | Requests termination of a process. | Yes | Yes |
timeout 10 ping | Runs ping with a ten-second time limit. | No | Yes |
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.