# C SDK

C SDK 适合网关、嵌入式 Linux 或靠近硬件接口的设备程序。代码包已处理 MQTT 连接、命令订阅、命令响应、状态上报、遥测上报和事件上报；接入时只需把设备规格中的命令和字段连接到真实硬件或已有业务接口。

## 适用场景

- 设备程序运行在网关、嵌入式 Linux 或靠近硬件接口的环境中。
- 需要对接串口、GPIO、驱动库、C/C++ 模块或本地服务。
- 需要轻量的设备端程序，并直接控制 MQTT 连接和上报时机。

## 代码包内容

| 内容 | 作用 |
| --- | --- |
| `src/main.c` | 设备入口，维护状态、处理命令、上报状态和事件 |
| `include/device_agent/client.h` | C SDK 核心接口，负责连接、订阅、响应和上报 |
| `include/device_agent/voice_client.h` / `src/voice_client.c` | 设备端语音 WebSocket 客户端 |
| `include/device_agent/vision_client.h` / `src/vision_client.c` | 图像上传和拍照识别客户端 |
| `examples/voice_chat.c` | 语音对话示例，可用于验证麦克风、TTS 和 WebSocket 连接 |
| `device-spec.json` | 当前设备规格，定义命令、遥测和事件 |
| `.env.example` | MQTT、`namespace`、`productId`、`deviceId` 等连接配置 |
| `CMakeLists.txt` | CMake 构建配置 |

真实接入时，修改 `src/main.c`。命令名、参数名、遥测字段和事件名都应与 `device-spec.json` 保持一致。

## 接入步骤

1. 下载 C SDK 代码包。
2. 复制 `.env.example` 为 `.env`，按需替换 MQTT 地址和认证信息。
3. 编译并启动程序。
4. 在 `src/main.c` 中实现命令处理、状态更新和事件上报。
5. 回到设备智能体工作区，确认设备上线并测试控制命令。

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

## 实现设备逻辑

设备智能体下发的命令会进入 `handle_command()`。在这里解析参数、调用硬件接口、更新状态，并返回结果：

```c
static int handle_command(const da_command_t *cmd,
                          da_response_t *out,
                          void *user_data) {
    if (strcmp(cmd->cmd, "power") == 0) {
        // 解析 cmd->params_json，调用真实硬件接口。
        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;
}
```

常用上报接口：

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

启动后上报在线状态和当前状态快照；数据变化后上报遥测；发生告警、按键、模式切换或任务完成时上报事件。

## 语音接入代码

C SDK 包含 `voice_client.h` 和 `voice_client.c`，用于接入设备端语音对话。设备端连接 `/ws/voice`，发送 16 kHz 单声道 Int16LE PCM 音频，并通过回调接收识别文本、智能体回复和 TTS 音频。

`examples/voice_chat.c` 是可运行的语音示例。它使用 `VOICE_WS_URL` 或 `VOICE_CHAT_HOST` 连接 Agent Gateway，适合先验证麦克风采集、播放和语音通道是否可用。

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

语音代码默认随工程构建，需要 `libwebsockets`。不需要语音时，可以在 CMake 中关闭 `DA_BUILD_VOICE`。

## 视觉识别代码

C SDK 包含 `vision_client.h` 和 `vision_client.c`，用于拍照识别类命令。设备端获取一张图片后，先上传到 `/api/vision/frames`，再调用 `/api/chat` 并携带 `visionRefs`，最终把识别结果作为命令响应返回。

生成的 `src/main.c` 会在设备规格中存在以下命令时启用这条流程：

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

真实接入时，把本地拍照、截图或图像读取逻辑补到 `src/main.c` 中。视觉代码需要 `libcurl`；不需要拍照识别时，可以在 CMake 中关闭 `DA_BUILD_VISION`。

## 验证接入

程序启动后，回到设备智能体工作区确认：

1. 设备列表中出现这台设备，并且状态为在线。
2. 当前数据能看到 C 程序上报的字段。
3. 通过对话下发命令后，C 程序能收到命令并返回结果。
4. 如果调用了 `da_client_send_event()`，最近上报事件中能看到对应记录。
