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; it arrives through process output callbacks. Send the next command after the device answers the previous one.
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})");
};Command compatibility
The table below shows command examples and their availability on each device.
| Command | What it does | Aidlab 1, Aidmed One | 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. Never send kill 0: Aidlab 1 and Aidmed One restart. | 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. On Aidlab 1 and Aidmed One, 1000 Hz turns off the motion sensor.
Advanced: process protocol
Each command runs as a process on the device. You need these details only to work with raw command output beyond simple text responses.
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.
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 and Aidmed One). Bytes 1–2 hold the PID, little-endian. Byte 4, when present, holds the rejection reason. Aidlab 1 and Aidmed One reject 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.
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 and Aidmed One do 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.