跳转至

设备 API

所有设备接口需要认证,位于 /api/devices 路径前缀下。这些接口管理电子墨水屏设备的完整生命周期:列表查询、绑定、解绑、命令下发和状态读取。

设备模型

{
  "id": "01912345-6789-7abc-def0-123456789abc",
  "hwId": "a1b2c3d4-5678-9012-abcd-ef0123456789",
  "thingName": "inklet-a1b2c3d4",
  "firmware": "1.2.0",
  "battery": 85,
  "online": true,
  "lastSeenAt": "2026-01-16T08:30:00Z",
  "ownerId": "01912345-0000-7abc-def0-000000000001",
  "boundAt": "2026-01-15T14:00:00Z",
  "claimCode": null,
  "state": "{\"screen\":\"text\",\"lastCmd\":\"abc123\"}",
  "stateUpdatedAt": "2026-01-16T08:25:00Z"
}
字段 类型 描述
id UUID v7 数据库主键
hwId string 出厂时烧录到设备中的硬件 UUID
thingName string AWS IoT Core Thing 名称(在配网时分配)
firmware string 或 null 设备上报的固件版本
battery integer 或 null 电池百分比(0--100)
online boolean 设备当前是否连接到 IoT Core
lastSeenAt timestamp 或 null 最后一次心跳的时间戳
ownerId UUID 或 null 拥有此设备的用户(未绑定时为 null
boundAt timestamp 或 null 设备绑定到当前所有者的时间
claimCode string 或 null 6 位配对码(仅在设备未绑定时存在)
state JSON string 或 null 通过 MQTT 上报的任意设备状态
stateUpdatedAt timestamp 或 null 状态最后更新的时间

说明

claimCode 仅在设备未绑定时存在。设备绑定到用户后,配对码会被清除。

接口列表


GET /api/devices

:material-lock: 需要认证

列出当前认证用户绑定的所有设备。

请求头:

Authorization: Bearer {accessToken}

响应: 200 OK

[
  {
    "id": "01912345-6789-7abc-def0-123456789abc",
    "hwId": "a1b2c3d4-5678-9012-abcd-ef0123456789",
    "thingName": "inklet-a1b2c3d4",
    "firmware": "1.2.0",
    "battery": 85,
    "online": true,
    "lastSeenAt": "2026-01-16T08:30:00Z",
    "ownerId": "01912345-0000-7abc-def0-000000000001",
    "boundAt": "2026-01-15T14:00:00Z",
    "claimCode": null,
    "state": null,
    "stateUpdatedAt": null
  }
]

如果用户没有绑定任何设备,返回空数组 []


GET /api/devices/{thing}

:material-lock: 需要认证 --- 仅设备所有者

通过 Thing 名称获取指定设备的详细信息。

路径参数:

参数 描述
thing 设备的 thingName(例如 inklet-a1b2c3d4

响应: 200 OK

{
  "id": "01912345-6789-7abc-def0-123456789abc",
  "hwId": "a1b2c3d4-5678-9012-abcd-ef0123456789",
  "thingName": "inklet-a1b2c3d4",
  "firmware": "1.2.0",
  "battery": 85,
  "online": true,
  "lastSeenAt": "2026-01-16T08:30:00Z",
  "ownerId": "01912345-0000-7abc-def0-000000000001",
  "boundAt": "2026-01-15T14:00:00Z",
  "claimCode": null,
  "state": "{\"screen\":\"text\",\"lastCmd\":\"abc123\"}",
  "stateUpdatedAt": "2026-01-16T08:25:00Z"
}

错误:

状态码 原因
401 访问令牌缺失或无效
403 当前认证用户不是设备所有者
404 设备未找到

GET /api/devices/{thing}/state

:material-lock: 需要认证 --- 仅设备所有者

获取设备上报的原始 JSON 状态。此接口返回解析后的 JSON 对象,而非字符串形式的 state 字段。

路径参数:

参数 描述
thing 设备的 thingName

响应: 200 OK

{
  "screen": "text",
  "lastCmd": "abc123",
  "brightness": 50
}

提示

当需要以结构化 JSON 对象形式读取设备状态时,请使用此接口。GET /api/devices/{thing} 接口在设备对象中以转义 JSON 字符串的形式返回状态。

错误:

状态码 原因
401 访问令牌缺失或无效
403 当前认证用户不是设备所有者
404 设备未找到或尚未上报状态

POST /api/devices/bind/nfc

:material-lock: 需要认证

使用 NFC 载荷将设备绑定到当前认证用户。后端在绑定前会根据出厂密钥验证 HMAC 签名。

请求体:

{
  "hwId": "a1b2c3d4-5678-9012-abcd-ef0123456789",
  "signature": "3f7a8b2c1d9e0f4a"
}
字段 类型 必填 描述
hwId string 从 NFC 标签读取的硬件 UUID
signature string HMAC-SHA256(hwId, FACTORY_SECRET) 的前 16 个十六进制字符

响应: 200 OK

返回完整的设备对象,ownerId 设置为当前认证用户。

错误:

状态码 原因
400 字段缺失或签名无效
404 未找到对应 hwId 的设备
409 设备已被其他用户绑定

POST /api/devices/bind/code

:material-lock: 需要认证

使用设备屏幕上显示的 6 位配对码将设备绑定到当前认证用户。

请求体:

{
  "code": "A3X9K2"
}
字段 类型 必填 描述
code string 6 位配对码(不区分大小写)

响应: 200 OK

返回完整的设备对象,ownerId 设置为当前认证用户。

错误:

状态码 原因
400 配对码缺失或格式无效
404 未找到对应配对码的设备
409 设备已被其他用户绑定
410 配对码已过期

配对码从何而来?

当设备处于未绑定状态并开机时,会通过 MQTT 发布 request_claim 消息。后端生成一个 6 位配对码,存储到数据库,并通过 claim_code 命令发送回设备。设备将其渲染到电子墨水屏上。


POST /api/devices/{thing}/unbind

:material-lock: 需要认证 --- 仅设备所有者

将设备从当前认证用户解绑。设备将恢复为未绑定状态,并重新请求配对码。

路径参数:

参数 描述
thing 设备的 thingName

响应: 200 OK

{
  "message": "device unbound"
}

解绑后,后端通过 MQTT 向设备发送 unbound 命令。设备清除屏幕内容并重新请求配对码。

错误:

状态码 原因
401 访问令牌缺失或无效
403 当前认证用户不是设备所有者
404 设备未找到

POST /api/devices/{thing}/cmd

:material-lock: 需要认证 --- 仅设备所有者

向设备发送命令。命令通过 MQTT 发送到设备的 down/cmd 主题。

路径参数:

参数 描述
thing 设备的 thingName

请求体:

{
  "kind": "text",
  "text": "Hello from Inklet!"
}
字段 类型 必填 描述
kind string 命令类型(目前用户命令仅支持 text
text string 条件必填 kindtext 时必须提供

响应: 200 OK

{
  "id": "01912345-9999-7abc-def0-aaaaaaaaaaaa",
  "deviceId": "01912345-6789-7abc-def0-123456789abc",
  "kind": "text",
  "text": "Hello from Inklet!",
  "createdAt": "2026-01-16T09:00:00Z"
}

响应包含 DeviceCommand 记录,用于跟踪命令下发状态。

错误:

状态码 原因
400 命令字段缺失或无效
401 访问令牌缺失或无效
403 当前认证用户不是设备所有者
404 设备未找到

POST /api/devices/{thing}/refresh-code

:material-lock: 需要认证

重新生成设备的配对码。当当前配对码已过期或丢失时使用。

路径参数:

参数 描述
thing 设备的 thingName

响应: 200 OK

返回完整的设备对象,claimCode 已更新为新的配对码。

错误:

状态码 原因
401 访问令牌缺失或无效
404 设备未找到

错误响应

所有错误响应遵循统一的格式:

{
  "message": "device not found"
}
状态码 描述
400 请求无效 --- 请求体格式错误、缺少必填字段或格式无效
401 未授权 --- 访问令牌缺失、已过期或无效
403 禁止访问 --- 当前认证用户不是目标设备的所有者
404 未找到 --- 设备或资源不存在
409 冲突 --- 设备已被其他用户绑定
410 已失效 --- 配对码已过期,需要重新生成