03. 设备与配置¶
1. 设备动态码绑定(公开 + JWT)¶
POST /api/device/pre-check(公开)¶
请求:
{
"mac": "AA:BB:CC:DD:EE:FF",
"username": "alice",
"device_password": "Ab12Cd34"
}
返回(已认证):
{ "code": 200, "data": { "status": "authenticated", "call_sign": "BG7XXX" } }
返回(需绑定):
{ "code": 200, "data": { "status": "need_bind", "message": "请使用动态码绑定设备" } }
POST /api/device/request-code(公开)¶
请求:
{ "mac": "AA:BB:CC:DD:EE:FF" }
返回:
{ "code": 200, "data": { "dynamic_code": "735921", "expires_in": 60 } }
POST /api/device/confirm-bind(公开)¶
请求:
{ "mac": "AA:BB:CC:DD:EE:FF" }
返回(等待中):
{ "code": 200, "data": { "status": "waiting", "message": "等待用户完成绑定" } }
返回(已就绪):
{
"code": 200,
"data": {
"status": "ready",
"username": "alice",
"device_password": "Ab12Cd34",
"ssid": 11,
"dmr_id": 4601234
}
}
POST /api/device/bind(JWT)¶
请求:
{ "dynamic_code": "735921" }
返回:
{
"code": 200,
"data": {
"device_mac": "AA:BB:CC:DD:EE:FF",
"call_sign": "BG7XXX",
"message": "绑定成功,请配置设备参数",
"available_ssids": [1, 2, 3, 4, 5, 106],
"recommended_ssid": 1
}
}
POST /api/device/submit-config(JWT)¶
请求:
{ "device_mac": "AA:BB:CC:DD:EE:FF", "ssid": 11 }
返回:
{
"code": 200,
"data": {
"message": "配置已保存",
"udp_auth_info": {
"username": "alice",
"device_password": "Ab12Cd34"
},
"dmr_id": 4601234
}
}
说明:
ssid仅允许普通设备范围:1-99、106-254。100-105为幽灵设备保留段,255为系统历史特殊保留值,均不可用于动态绑定。available_ssids/recommended_ssid已自动排除当前用户已有设备与待绑定配置,并按从小到大推荐。- 普通设备运行时唯一键为
owner_id + ssid;同一用户同一 SSID 同时只允许一台在线设备。 - 设备端动态绑定接口里的
mac仅用于“设备绑定 / 设备确认配置”流程;普通 UDP 设备上线后的快速重连判据由心跳包DATA扩展区中的可选 MAC 提供。
1.1 普通 UDP 设备快速重连补充说明¶
- 心跳包固定
header不变;MAC 不会写入 header,只会可选追加在心跳DATA的GPS(24B)之后。 - 服务端在普通 UDP 设备在线时,会记录
owner_id + ssid -> mac的运行时映射。 - 如果设备短暂断线后重新建立了新的 UDP 源端口,但心跳包携带的 MAC 与当前在线实例一致,服务端会视为同一物理设备重连,允许直接接管新地址。
- 如果 MAC 不同,则仍按“同一用户同一 SSID 已有在线设备”拒绝新实例。
- 当设备被彻底判定离线后,这条运行时 MAC 映射会被删除。
2. 用户设备密码(JWT)¶
GET /api/user/device-password¶
PUT /api/user/device-password¶
请求:
{ "new_password": "Ab12Cd34" }
POST /api/user/device-password/regenerate¶
返回示例:
{ "code": 200, "message": "设备密码已重新生成", "data": { "device_password": "Xy98Lm12" } }
3. 设备管理(JWT + Approved)¶
说明:设备收发控制仅设备级生效,统一通过 PUT /api/devices/:id 的
disable_send / disable_recv 字段更新。
GET /api/devices¶
参数:page、limit、callsign、group_id
返回项补充:
last_online_ip:设备最近一次上线客户端 IPlast_online_ip_location:根据 IP 计算的归属地(实时计算)
GET /api/devices/list(兼容旧路径)¶
GET /api/device/get?id=123¶
GET /api/device/qth?id=123(兼容)¶
GET /api/device/qths¶
返回:设备位置列表。
PUT /api/devices/:id¶
请求示例:
{
"name": "My ESP32",
"group_id": 1001,
"status": 1,
"priority": 100,
"note": "备用机",
"disable_send": false,
"disable_recv": false
}
说明:
dev_model由设备客户端通过 UDP 协议上报并由服务端校验后写入。- 该接口不支持设置/修改
dev_model(传入也会被忽略)。
DELETE /api/devices/:id¶
POST /api/device/changegroup¶
PUT /api/devices/:id/group¶
请求体(以 body device_id 为准):
{
"device_id": 123,
"group_id": 1002,
"password": "private_group_pwd"
}
说明:私有群组且用户未验证时,需要 password。
4. 设备配置同步(UDP 普通设备)¶
GET /api/devices/:id/config¶
PUT /api/devices/:id/config¶
请求示例:
{
"rx_freq": "439500000",
"tx_freq": "431500000",
"rx_ctcss": "88.5",
"tx_ctcss": "88.5",
"rx_tone_mode": "ctcss",
"rx_tone_value": "88.5",
"tx_tone_mode": "ctcss",
"tx_tone_value": "88.5",
"sql_level": "4",
"power_level": "3",
"tx_bandwidth": "1",
"rf_guard_enabled": "1",
"rf_guard_single_tx_limit_s": "30",
"rf_guard_window_s": "300",
"rf_guard_max_tx_in_window_s": "60"
}
说明:
power_level当前按设备能力归一化为1(低)或3(高),历史值2会兼容映射为3。rx_tone_mode/tx_tone_mode支持off、ctcss、cdcss_n、cdcss_i;对应的*_tone_value为 CTCSS 频率或 3 位 DCS 码值。rf_guard_enabled支持0/1;为空时按默认开启处理。rf_guard_single_tx_limit_s范围1-1800,默认30。rf_guard_window_s范围5-3600,默认300。rf_guard_max_tx_in_window_s范围1-rf_guard_window_s,默认60,超过窗口值时会自动收敛到窗口上限。
POST /api/devices/:id/config/sync¶
返回示例:
{ "code": 200, "message": "配置已发送到设备" }
离线时:
{ "code": 200, "message": "设备离线,配置将在设备上线时自动同步" }
5. 管理员设备配置(Admin)¶
GET /api/admin/devices/:id/configPUT /api/admin/devices/:id/configPOST /api/admin/devices/:id/config/sync
与前台配置接口字段一致,但无设备归属限制。
6. 固件管理¶
POST /api/firmware(Admin)¶
multipart/form-data 字段:
file:固件二进制文件(最大 16MB)dev_model:设备型号(白名单:1=ESP32 1W射频版, 2=ESP32 无射频版)version:版本号,semver 格式如1.0.0或1.0.0-beta.1changelog:更新日志(可选)
返回示例:
{
"code": 200,
"message": "固件上传成功",
"data": {
"id": 1,
"dev_model": 1,
"version": "1.2.0",
"changelog": "修复WiFi重连问题",
"file_name": "firmware.bin",
"minio_path": "uploads/firmware/2026/04/xxx.bin",
"file_size": 1048576,
"file_hash": "sha256hex...",
"is_latest": true,
"created_by": 1,
"create_time": "2026-04-20T10:00:00Z"
}
}
说明:
- 同一
dev_model+version组合不可重复,否则返回409。 - 上传新版本后,该型号旧版本的
is_latest自动置为false。
GET /api/firmware(Admin)¶
参数:dev_model(可选,0=全部)、page、page_size
每条记录额外返回 download_url 字段(MinIO 永久链接)。
DELETE /api/firmware/:id(Admin)¶
删除固件记录及 MinIO 文件。若删除的是最新版本,自动将次新版本提升为 is_latest。
GET /api/public/firmware/latest(Public)¶
参数:dev_model(必填)
返回示例:
{
"code": 200,
"message": "成功",
"data": {
"id": 1,
"dev_model": 1,
"version": "1.2.0",
"changelog": "修复WiFi重连问题",
"file_name": "firmware.bin",
"file_size": 1048576,
"file_hash": "sha256hex...",
"download_url": "https://...presigned...",
"create_time": "2026-04-20T10:00:00Z"
}
}
说明:
download_url通过 MinIOBasePath(若已配置)拼接生成;未配置时回退为 MinIO 直链。file_hash为 SHA-256,设备端可用于校验下载完整性。- 该型号无固件时返回
404。
7. 设备 AT/参数接口(JWT + Approved,历史业务码)¶
POST /api/device/atPOST /api/device/queryPOST /api/device/changePOST /api/device/change1wPOST /api/device/change2w
示例(/api/device/at):
{
"callsign": "BG7XXX",
"ssid": 11,
"type": 1,
"atcommand": "AT+VERSION?"
}
返回示例:
{
"code": 20000,
"data": {
"message": "AT命令执行成功",
"items": { "callsign": "BG7XXX", "ssid": 11, "version": "DraARL AT V1.0" }
}
}