构建

设备固件

设备 SDK · nexting_device.h · C99

用 portable C99 核心解析受限的 BLE 分片、驱动审批 UI 与重试,并应用 Agent 状态;固件无需引入分配器或操作系统。

1. 设计契约

SDK 是 portable C99,不做堆分配,也不拥有传输层。所有缓冲区都由调用方持有、提供并固定容量。你只需送入无线分片、渲染通过验证的状态,再通过 BLE 栈发送编码结果。完整逻辑帧最多 4096 字节且包含 LF;编码缓冲区因此需要 4097 字节,才能再容纳 C NUL。

名称类型说明
NEXTING_DEVICE_REQUEST_ID_CAPACITY必填
65 bytes64 字节 ASCII ID,加一个 C NUL。
NEXTING_DEVICE_SUMMARY_CAPACITY必填
241 bytes240 字节 UTF-8 摘要,加一个 C NUL。
NEXTING_DEVICE_DEFAULT_MAX_MESSAGE_BYTES必填
4096 bytes紧凑 JSON 及其结尾 LF。
encode output buffer必填
4097 bytes最大帧,再加编码器写入的 C NUL。
NEXTING_DEVICE_MAX_TTL_MS必填
300000 ms允许的最大相对审批寿命。
NEXTING_DEVICE_ANSWER_RETRY_MS必填
1000 ms未收到 resolution 时的重试间隔。
NEXTING_DEVICE_STATUS_LABEL_CAPACITY必填
65 bytes64 字节 UTF-8 标签,加一个 C NUL。

2. 消息

nexting_device_message_t 是唯一的解码结果。带标签的字段覆盖全部五类 Wire 消息;status 最多携带八个唯一 Agent 槽。

NEXTING_DEVICE_MESSAGE_PRESENT
NEXTING_DEVICE_MESSAGE_ANSWER
NEXTING_DEVICE_MESSAGE_RESOLVED
NEXTING_DEVICE_MESSAGE_ERROR
NEXTING_DEVICE_MESSAGE_STATUS

3. 编解码

解码和编码都遵循失败即关闭。无效 UTF-8、重复已知字段、未知枚举、非规范整数、越界值和内嵌 NUL 都不会进入状态或渲染代码。

nexting_device.hc
nexting_device_result_t nexting_device_decode(
    const char *wire,
    size_t wire_length,
    nexting_device_message_t *output);

nexting_device_result_t nexting_device_encode(
    const nexting_device_message_t *message,
    char *output,
    size_t output_capacity,
    size_t *output_length);

同一个 nexting_device_message_t 通过固定容量 interaction payload 承载 navigation/1、keys/1、rotary/1、voice/1、 text/1、usage/1 与 config/1。Device Info 为每个 Profile 暴露独立支持布尔值。带序号的实体输入按来源单调递增,并随连接重置。

通用按键事件c
nexting_device_message_t event = {0};
event.type = NEXTING_DEVICE_MESSAGE_KEY_EVENT;
event.interaction.slot = 3;
event.interaction.gesture = NEXTING_DEVICE_GESTURE_PRESS;
event.interaction.sequence = ++key_sequence;
nexting_device_encode(&event, wire, sizeof wire, &wire_length);

4. 换行流式拼帧

ATT write 可能拆开或合并消息。流解析器把字节追加到你提供的 4096 字节存储中,每遇到 LF 就产出一条已移除分隔符的 JSON 消息;它绝不执行部分消息,并会丢弃超长输入直到下一个 LF。断连时必须 reset。

调用方拥有的流c
uint8_t storage[NEXTING_DEVICE_DEFAULT_MAX_MESSAGE_BYTES];
nexting_device_stream_t stream;

nexting_device_stream_init(&stream, storage, sizeof storage);
nexting_device_stream_push(&stream, chunk, chunk_length, on_message, context);
nexting_device_stream_reset(&stream);

5. 审批状态机

三个阶段是 NEXTING_DEVICE_PHASE_IDLE、NEXTING_DEVICE_PHASE_PENDING 与NEXTING_DEVICE_PHASE_WAITING_RESOLUTION。present 会替换当前请求;本地选择把 Pending 推进到 Waiting Resolution,并每 1000 ms 重试同一个 answer。匹配的nexting_device_state_on_resolved 可从 Pending 或 Waiting Resolution 清空请求;ID 不匹配时不改变状态。周期循环中必须先调用nexting_device_state_tick,再调用nexting_device_state_retry_answer:retry_answer 遇到已经过期的 Waiting Resolution 也会清空状态,却返回 false;若先调用它,UI 就观察不到过期转换。按键也可能恰好撞上截止时间:nexting_device_state_choose 会自行检查 TTL,把过期的 SDK 状态清为 Idle,并返回错误。choose 返回错误时,只有这次调用从 Pending 开始、并把阶段变成 Idle,才清除可见 UI;若阶段仍是 Pending,或按键到来前已经是 Idle,则保留当前 UI,让下一次有效按键可以重试。

名称类型说明
nexting_device_state_on_present
Idle → Pending复制请求并设置单调时钟截止时间。
nexting_device_state_choose
Pending → Waiting / Idle生成第一次 answer;若 TTL 已过期则清为 Idle。
nexting_device_state_retry_answer
Waiting到达重试时刻时生成相同 answer。
nexting_device_state_on_resolved
Pending / Waiting → Idle只清除 ID 匹配的请求。
nexting_device_state_tick
任意活跃态 → Idle按单调经过时间执行过期。

6. 状态槽

有效 status 消息采用全量替换:数组中缺失的槽会清空,空数组清空全部槽。校验在修改前完成,因此畸形帧会原子地保留之前的状态。断连也会清空所有易失槽。只有设备同时声明 status/1 与正数statusSlots 时,才应应用状态。

原子应用状态c
nexting_device_status_state_t status;
nexting_device_status_init(&status);

if (nexting_device_status_on_message(&status, message) == NEXTING_DEVICE_OK) {
  render_status(&status);
}

nexting_device_status_disconnect(&status);

7. 完整集成

这个 translation unit 把严格串行的 App 事件循环写进契约:BLE、GPIO、定时器和断连回调只负责入队,绝不直接进入 SDK 状态。平台队列必须在返回前复制事件与 BLE payload。只有一个事件循环上下文可以调用app_event_loop_init 与app_event_loop_dispatch,并且绝不重入。这个平台中立的队列 hook 不承诺 ISR 安全;请按目标 RTOS 或裸机平台适配回调上下文与唤醒机制。补上单调时钟、BLE Notify、UI 与队列 hook 后,这些精确的公开 API 即可与 SDK 源码一起按 C99 编译。

device_integration.cc
#include "nexting_device.h"

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

typedef enum {
  APP_EVENT_BLE_BYTES,

在导出的源码树上直接执行下面三条精确命令,即可配置、构建并运行全部 C SDK 测试。

C SDK 验证sh
cmake -S /path/to/nexting/devices/sdk/c -B build/c-sdk -DCMAKE_BUILD_TYPE=Debug
cmake --build build/c-sdk --parallel
ctest --test-dir build/c-sdk --output-on-failure
当前 Zephyr 参考固件使用这套 C 核心,但只声明approval/1。增加状态渲染前,必须完成真实槽位映射、声明statusSlots,并通过真板验证。