IoT Devices · 超级大屏

Super Screen API 示例:局域网 WebSocket

通过已记录的局域网 WebSocket 查询区域,按 mid 匹配回复并处理超时,再发布内容。示例使用大屏协议,与设备 API 分开。

运行示例前

在与客户端相同网络使用 Node.js 24 或具有兼容 WebSocket 客户端的运行环境。先通过 /ping 确认监听端口,再通过进程环境提供 SCREEN_IP、SCREEN_PORT、SCREEN_CONTROL_CODE。控制码必须是该设备已启用的六位码,不是 /api/iot/v1 的 API Key。

第一个请求只读,查询显示区域列表。代码中八秒超时只是示例取值,不是服务时限承诺。示例只输出匹配的回复,不记录连接网址或控制码;应先在项目测试屏上运行,再扩展到控制动作。

Node.js:查询区域并匹配回复

将代码保存为 screen-query.mjs,设置环境变量后执行 node screen-query.mjs。mid 保持八个字符,ts 使用毫秒时间戳;其他请求的回复不会使本次请求完成。

协议示例
import { randomBytes } from 'node:crypto';

const host = process.env.SCREEN_IP;
const port = Number(process.env.SCREEN_PORT);
const token = process.env.SCREEN_CONTROL_CODE ?? '';
if (!host || !/^[a-zA-Z0-9.-]+$/.test(host) ||
    !Number.isInteger(port) || port < 1 || port > 65535 ||
    !/^\d{6}$/.test(token)) {
  throw new Error('Set SCREEN_IP, SCREEN_PORT and SCREEN_CONTROL_CODE');
}
const endpoint = new URL(`ws://${host}:${port}/order`);
endpoint.search = new URLSearchParams({ token, rid: 'energy-pilot', rname: 'Energy pilot' }).toString();
const mid = randomBytes(4).toString('hex');
const socket = new WebSocket(endpoint);
let done = false;
function finish(failed) {
  if (done) return;
  done = true;
  clearTimeout(timer);
  process.exitCode = failed ? 1 : 0;
  socket.close();
}
const timer = setTimeout(() => {
  console.error('Reply timeout; verify state before retrying a control action');
  finish(true);
}, 8000);
socket.addEventListener('open', () => {
  if (!done) socket.send(JSON.stringify({
    mid, data: { screen: { action: 'list' } }, ts: Date.now(),
  }));
});
socket.addEventListener('message', (event) => {
  if (done) return;
  let reply;
  try { reply = JSON.parse(String(event.data)); } catch { return; }
  if (!reply || typeof reply !== 'object' || reply.mid !== mid) return;
  console.log(JSON.stringify(reply, null, 2));
  finish(reply.ret === 'error');
});
socket.addEventListener('error', () => {
  if (!done) console.error('Connection failed; check network, port and control code');
  finish(true);
});
socket.addEventListener('close', () => {
  if (!done) {
    console.error('Connection closed before a correlated reply');
    finish(true);
  }
});

查询区域后再发布内容

使用查询返回的实际区域 ID。以下命令数据以本站能源指南页面验证内容连通性,测试后再换成项目看板网址。局域网请求使用新的 mid 与 ts 封装,云端则按项目交付的传输字段封装;不要把大屏命令发到设备 API。

协议示例
{"web":{"area":"a1","url":"https://iotdevices.org/zh/solutions/energy-management","interval":60}}
{"web":{"area":"a1"}}

处理错误时不要假设动作已完成

ret: error 表示失败,例如 invalid param、unsupported 或 device is in remote mode。超时意味着结果未知;重试改变状态的动作前先查询当前内容,不要盲目重复语音等有副作用的动作。排查记录保留 mid、设备 ID、时间与脱敏回复,实体屏幕显示另行确认。

WhatsApp 联系我们