跳转至

05. 无线电与实时通信

1. 在线收发 API(JWT + Approved)

GET /api/radio/config

返回示例:

{
  "code": 200,
  "data": { "ssid": 105, "default_group": 999, "enabled": true },
  "connected": true
}

PUT /api/radio/ssid

说明:

{ "ssid": 105 }
  • 已废弃。
  • Web 幽灵设备 SSID 固定为 105
  • 当前接口返回 410,用于提示旧客户端停止修改 SSID。

GET /api/radio/status

返回示例:

{
  "code": 200,
  "data": {
    "connected": true,
    "group_id": 999,
    "online_since": "2026-04-05 15:10:00",
    "callsign": "BG7XXX",
    "ssid": 105,
    "is_speaking": false,
    "voice_sending": false
  }
}

GET /api/radio/groups/stats

返回用户可访问群组的实时在线统计(含 WS 设备)。

GET /api/radio/groups/:id/devices

返回该群组在线设备(UDP + WS),字段含:

  • is_ghost
  • disable_send(设备级)
  • disable_recv(设备级)
  • last_activity

PUT /api/radio/group

请求:

{ "group_id": 1001, "dev_model": 105 }

说明:

  • dev_model=105:WebSocket 幽灵设备。
  • 101-104:UDP 幽灵设备(安卓/iOS/Windows/macOS)。

GET /api/radio/conflict

功能:连接前检查幽灵设备冲突。

返回(冲突):

{ "code": 409, "message": "您的账号已在其他页面建立了电台连接,请先断开其他页面的连接", "data": { "conflict": true } }

2. WebSocket /ws

2.1 鉴权

  • 必须携带 ws_token HttpOnly Cookie。
  • 若用户已有在线幽灵设备连接,返回 409 ghost_device_conflict

2.2 消息格式

  • 仅接受二进制消息。
  • 协议头 90 字节,采用 DraARLv1 帧格式。
  • 常用类型:
  • 2 心跳
  • 4 文本消息
  • 5 Opus 语音

2.3 示例(伪代码)

const ws = new WebSocket('wss://server.example.com/ws');
ws.binaryType = 'arraybuffer';
// 认证依赖 Cookie,无需在 URL 附 token

3. UDP 协议(设备侧)

设备与服务器 UDP 通信遵循 DraARLv1:

  • 规范文档:docs 目录 Protocol.md
  • 核心点:
  • 固定头 90 字节
  • 大端序
  • 最大包长 800 字节
  • 心跳包固定 header 不变;设备 MAC 如需上报,只能可选追加在心跳 DATA[24:]
  • 支持 TypeConfig 配置同步 TLV
  • 普通设备 SSID 仅允许 1-99106-254
  • 幽灵设备 SSID 固定为 100-105,且 ssid = devmodel
  • 普通 UDP 设备同用户同 SSID 冲突时,新设备被拒绝,旧设备保持在线
  • 普通 UDP 设备若心跳携带的 MAC 与当前在线实例一致,则允许按“同一物理设备快速重连”直接接管新地址
  • UDP 幽灵设备同用户同平台冲突时,新设备认证失败,旧设备保持在线