# C SDK

The C SDK is for gateways, embedded Linux, or device programs close to hardware interfaces. The package already handles MQTT connection, command subscription, command responses, status reports, telemetry reports, and event reports. Connect the commands and fields in the DeviceSpec to real hardware or existing business interfaces.

## Use Cases

- The device program runs on a gateway, embedded Linux, or a host close to hardware interfaces.
- The device needs serial ports, GPIO, driver libraries, C/C++ modules, or local services.
- The device-side program should stay lightweight and control MQTT connection and reporting timing directly.

## Package Contents

| File | Purpose |
| --- | --- |
| `src/main.c` | Device entry point for state, command handling, status reports, and events |
| `include/device_agent/client.h` | Core C SDK API for connection, subscription, responses, and reports |
| `include/device_agent/voice_client.h` / `src/voice_client.c` | Device-side voice WebSocket client |
| `include/device_agent/vision_client.h` / `src/vision_client.c` | Image upload and photo recognition client |
| `examples/voice_chat.c` | Voice conversation example for testing microphone, TTS, and WebSocket access |
| `device-spec.json` | Current DeviceSpec: commands, telemetry, and events |
| `.env.example` | MQTT, `namespace`, `productId`, `deviceId`, and connection settings |
| `CMakeLists.txt` | CMake build configuration |

For a real device, you mainly work in `src/main.c`. Keep command names, parameter names, telemetry fields, and event names aligned with `device-spec.json`.

## Access Steps

1. Download the C SDK package.
2. Copy `.env.example` to `.env` and update MQTT broker or credentials if needed.
3. Build and start the program.
4. Implement command handling, state updates, and event reporting in `src/main.c`.
5. Return to the Device Agent workspace, confirm the device is online, and test a control command.

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

## Implement Device Logic

Commands from the Device Agent enter `handle_command()`. Use it to parse parameters, call hardware interfaces, update state, and return results:

```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;
}
```

Common reporting APIs:

```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\"}");
```

Report online status and a state snapshot after startup; report telemetry when data changes; report events for alerts, button presses, mode changes, or task completion.

## Voice Access Code

The C SDK includes `voice_client.h` and `voice_client.c` for device-side voice conversations. The device connects to `/ws/voice`, sends 16 kHz mono Int16LE PCM audio, and receives ASR text, agent replies, and TTS audio through callbacks.

`examples/voice_chat.c` is a runnable voice example. It uses `VOICE_WS_URL` or `VOICE_CHAT_HOST` to connect to Agent Gateway and is useful for validating microphone capture, playback, and the voice channel.

```c
da_voice_options_t opts = {
    .ws_url = "ws://127.0.0.1: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);
```

Voice code is built by default and requires `libwebsockets`. If voice is not needed, disable `DA_BUILD_VOICE` in CMake.

## Vision Recognition Code

The C SDK includes `vision_client.h` and `vision_client.c` for photo recognition commands. The device captures one image, uploads it to `/api/vision/frames`, then calls `/api/chat` with `visionRefs`. The recognition result is returned as the command response.

The generated `src/main.c` enables this path when the DeviceSpec contains one of these commands:

- `capture_and_recognize`
- `take_photo_vision`
- `vision_recognize`
- `photo_identify`

For real access, add local camera, screenshot, or image-reading logic in `src/main.c`. Vision code requires `libcurl`; if photo recognition is not needed, disable `DA_BUILD_VISION` in CMake.

## Verify Access

After the program starts, return to the Device Agent workspace and confirm:

1. The device appears in the device list and is online.
2. Current state shows fields reported by the C program.
3. A conversation command reaches the C program and returns a result.
4. If `da_client_send_event()` is called, the event appears in recent events.
