把 IFU 接进现有系统
1. 集成方式总览
| 方式 | 传输 | 默认监听 | 特点 |
|---|---|---|---|
| HTTP | TCP | 0.0.0.0:42301 |
POST /api/v1/commands 下发命令;GET /api/v1/health|status|templates|scene/current|fonts|assets 查询;WebSocket /ws 订阅事件;同端口托管管理后台页面 |
| TCP | TCP | 0.0.0.0:42302 |
每行一条 JSON 命令(JSON Lines)长连接,单行建议 ≤8KB |
| UDP | UDP | 0.0.0.0:42303 |
单包一条 JSON 命令(≤512 字节),响应回至来源地址;承载局域网发现 |
三条通道共用同一命令总线:同一命令在任一传输上的校验、行为与响应结构完全一致。TCP/UDP 适合中控常驻对接与轻量触发;HTTP 适合脚本与第三方系统;WebSocket 用于管理界面实时刷新(scene-changed、settings-changed 事件)。
2. 统一返回格式
{
"cmd": "switch",
"status": "success | error | skipped",
"message": "已切换场景: tpl-festival-newyear-01",
"code": "机器错误码(仅 error/skipped 携带)",
"data": {}
}
success:执行成功,查询类命令带dataerror:执行失败(参数错误 / 未知命令 / 目标不存在 / 内部错误)skipped:命令已识别但跳过执行(如切换到已是当前的场景、set_text 文字未变化、命令暂未实现)
3. 鉴权
| 项 | 说明 |
|---|---|
| 默认 | 无鉴权(局域网使用) |
| 访问密码 | 系统设置中设置后,42301 全部 API 需携带(健康检查 /api/v1/health 与 /api/v1/verify 除外) |
| 携带方式 | 查询参数 ?token=<密码> 或请求头 X-Fox-Token: <密码> |
| 失败响应 | 401 {"status":"error","code":"UNAUTHORIZED","message":"需要访问密码"} |
| 中控通道 | TCP 42302 / UDP 42303 不做鉴权(内网使用,勿暴露公网) |
4. 命令清单
| 命令 | 请求示例 | 用途 |
|---|---|---|
| hello | {"cmd":"hello"} |
握手:版本、协议号、当前场景 |
| ping | {"cmd":"ping"} |
心跳 |
| discover | {"cmd":"discover"} |
发现应答:名称、版本、主机名、端口、当前场景(UDP 广播枚举设备) |
| status | {"cmd":"status"} |
运行状态:版本、运行时长、场景数、端口 |
| list_templates | {"cmd":"list_templates"} |
场景列表(含 builtin 标记与数量) |
| switch | {"cmd":"switch","id":"tpl-notice-01"} |
切换大屏显示并落盘;重复切换返回 skipped |
| get_scene | {"cmd":"get_scene"} / {"cmd":"get_scene","id":"..."} |
读完整场景 JSON |
| save_scene | {"cmd":"save_scene","scene":{...}} |
保存场景并应用为大屏当前显示 |
| create_scene | {"cmd":"create_scene","name":"...","templateId":"..."} |
新建(空白或以某场景为底稿),不切换显示 |
| duplicate_scene | {"cmd":"duplicate_scene","id":"...","name":"..."} |
复制为新场景 |
| rename_scene | {"cmd":"rename_scene","id":"...","name":"..."} |
重命名(内置模板生成同 id 覆盖文件) |
| delete_scene | {"cmd":"delete_scene","id":"..."} |
删除用户场景;内置模板不可删;删当前场景自动切到首个可用场景 |
| set_text | {"cmd":"set_text","block":"...","value":"..."} |
远程改字(见第 5 节匹配规则) |
| list_assets | {"cmd":"list_assets"} / {"kind":"backgrounds"} |
资产列表(背景含内置图库 30 张) |
| upload_asset | {"cmd":"upload_asset","kind":"fonts","name":"x.ttf","data":" |
上传资产(图片≤10MB / 字体≤20MB / 图标≤2MB) |
| delete_asset | {"cmd":"delete_asset","kind":"icons","name":"x.png"} |
删除上传资产(内置不可删) |
| list_fonts | {"cmd":"list_fonts"} |
字体列表(内置 + 用户,按文件名作字体名) |
| get_settings / save_settings | {"cmd":"get_settings"} / {"cmd":"save_settings","settings":{...}} |
读写设置;改端口自动热重启三服务;返回值不含密码本体 |
| get_logs | {"cmd":"get_logs","limit":120} |
最近运行日志(含每条命令的处理记录) |
5. set_text 匹配规则(远程改字)
block 字段按以下顺序匹配当前场景中的元素,命中即停:
- 元素 id 精确匹配(如
el-title,可在场景 JSON 中查到); - 文字内容完全一致(如
"欢迎领导莅临指导"); - 兜底:场景中首个文字类元素(text / icon-text)。
匹配后更新 content 并立即落盘应用(内置模板自动生成同 id 用户覆盖文件)。文字与原值相同返回 skipped(code UNCHANGED);场景中没有文字元素返回 error(code NOT_FOUND)。推荐用元素 id 对接,语义最稳。
6. 调用示例
6.1 切换场景(HTTP)
curl -X POST http://192.168.1.100:42301/api/v1/commands \
-H 'Content-Type: application/json' \
-d '{"cmd":"switch","id":"tpl-welcome-leader-01"}'
{"cmd":"switch","status":"success","message":"已切换场景: tpl-welcome-leader-01","data":{"currentSceneId":"tpl-welcome-leader-01"}}
6.2 远程改字(TCP 长连接,Node.js)
const net = require('net')
const c = net.connect(42302, '192.168.1.100')
c.setEncoding('utf8')
let buf = ''
c.on('data', d => {
buf += d
let i
while ((i = buf.indexOf('\n')) >= 0) {
console.log(JSON.parse(buf.slice(0, i)))
process.exit(0)
}
})
c.on('connect', () => c.write(JSON.stringify({
cmd: 'set_text', block: '欢迎领导莅临指导', value: '热烈欢迎XX集团领导莅临指导'
}) + '\n'))
6.3 局域网发现(UDP 广播)
const dgram = require('dgram')
const s = dgram.createSocket('udp4')
s.on('message', m => { console.log(JSON.parse(m.toString())) })
s.send(JSON.stringify({ cmd: 'discover' }), 42303, '255.255.255.255')
// 每台 FoxDisplay 单播回包:{ cmd:"discover", status:"success", data:{ hostname, ports, currentSceneId, ... } }
7. 错误码
| code | status | 含义 | 处理建议 |
|---|---|---|---|
| BAD_REQUEST | error | JSON 解析失败 / 缺字段 | 核对报文格式 |
| UNKNOWN_CMD | error | 命令不存在 | 核对 cmd 拼写 |
| NOT_FOUND | error | 场景 / 资源不存在 | 先 list_templates / list_assets 核对 id |
| NOT_ALLOWED | error | 内置模板或内置资产不可删除 | 复制副本后操作副本 |
| ALREADY_CURRENT | skipped | 切换目标已是当前场景 | 无需处理 |
| UNCHANGED | skipped | set_text 文字未变化 | 无需处理 |
| NOT_IMPLEMENTED | skipped | 命令预留未实现 | 关注版本更新 |
| TOO_LARGE | error | 上传文件超限 | 压缩后重试 |
| UNAUTHORIZED | error | 访问密码不匹配(HTTP) | 携带正确 token |
| INTERNAL | error | 服务内部错误 | 查看运行日志,联系技术支持 |
8. 集成注意事项
- TCP 建议每 30 秒发一次
ping作心跳;服务端不主动断开连接; - UDP 单包 ≤512 字节,超出请改走 TCP/HTTP;坏包静默丢弃(无响应即失败);
- 命令处理为串行内存操作,无需担心并发;多中控同时连接 42302 是允许的;
- 场景 id 只允许字母、数字、下划线与连字符;
- 所有写操作(switch / save_scene / set_text / delete_*)实时落盘,大屏断电不丢。