Skip to content

C SDK

The C SDK is for gateways, embedded Linux, and device programs that call serial ports, GPIO, driver libraries, or C/C++ modules directly. The generated package handles MQTT connectivity, command responses, and data reporting; connect the real hardware logic in src/main.c.

Start withPurpose
src/main.cImplement command handling, hardware calls, and reports
device-spec.jsonCheck command, property, and event definitions
.env.exampleConfigure the MQTT endpoint and device identity
CMakeLists.txt / README.mdCheck dependencies, build options, and platform notes

Build and Start

  1. Download and extract the package, then open its root directory.
  2. Copy .env.example to .env and fill in the connection settings.
  3. Install dependencies and complete the first CMake build.
  4. Connect the real hardware logic in src/main.c, then rebuild.
  5. Start build/device and verify it in the Device Agent workspace.

The minimum build and start commands are:

bash
cp .env.example .env
set -a && source .env && set +a
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
./build/device

The MQTT client requires libmosquitto. CMake uses the system cJSON when available and fetches it otherwise. Voice requires libwebsockets and OpenSSL, while vision requires libcurl. Disable either module when it is not needed:

bash
cmake -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DDA_BUILD_VOICE=OFF \
  -DDA_BUILD_VISION=OFF

The C program does not load .env itself. Export it into the current environment before startup, as shown above. Keep command names, parameter names, property fields, and event names aligned with device-spec.json. The generated initial state uses each property's defaultValue, or a type-based fallback when no default is present. Replace these values with real device state during integration.

Implement Commands, State, and Events

Device commands enter handle_command() in src/main.c. Parse parameters, call the hardware interface, update state, and return the result here:

c
static int handle_command(const da_command_t *cmd,
                          da_response_t *out,
                          void *user_data) {
    if (strcmp(cmd->cmd, "power") == 0) {
        // Parse cmd->params_json and call the real hardware interface.
        da_client_send_status(g_client, "online", "{\"power\":true}");
        da_client_send_telemetry(g_client, "state", "{\"power\":true}");

        out->code = 0;
        out->msg = "ok";
        return 0;
    }

    out->code = 501;
    out->msg = "command not implemented";
    return 0;
}

The three report types serve different purposes:

TypeUse it forC API
StatusOnline state or a changed state snapshotda_client_send_status()
TelemetryCurrent values such as temperature or powerda_client_send_telemetry()
EventDiscrete occurrences such as alerts or button pressesda_client_send_event()

Event names and data fields must also be defined in device-spec.json:

c
da_client_send_status(client, "online", "{\"power\":true}");
da_client_send_telemetry(client, "state", "{\"temperature\":22.5}");
da_client_send_event(client, "button_pressed", "{\"button\":\"A\"}");

Add Voice and Vision

Voice

include/device_agent/voice_client.h and src/voice_client.c provide the device-side voice client. examples/voice_chat.c includes the URL selected when the package was generated. Export VOICE_WS_URL before startup only when you need to override it. Connect microphone capture, speaker playback, and callbacks to the client for a real device:

c
da_voice_options_t opts = {
    .ws_url = "ws://<gateway>:3001/ws/voice",
    .device_id = "device-001",
    .product_id = "agent-001",
};

da_voice_client_t *voice = da_voice_client_new(&opts, &callbacks);
da_voice_client_connect(voice);
da_voice_client_start_listening(voice, "manual");
da_voice_client_send_audio(voice, pcm_samples, sample_count);
da_voice_client_stop_listening(voice);

Vision

include/device_agent/vision_client.h and src/vision_client.c provide the generated package's preset single-photo recognition flow; see the package README for its trigger commands. Implement camera, screenshot, or image-file input in capture_local_vision_image() in src/main.c, and set the service host with VOICE_CHAT_HOST. The generated code returns the recognition result as the command response.

See Voice Interaction and Camera and Vision for complete media settings. After startup, use the checks in SDK Access to verify online state, commands, state reports, and events.