Skip to content

SSE 实时事件推送 ​

登录后的 Web 页面通过 GET /api/events 接收单向事件。SSE 更新采集和协议状态;系统健康指标仍通过对应 REST 接口读取。心跳只证明连接收到消息,不证明传感器采集、规则执行或 MQTT 上报正常。

事件与数据 ​

事件内容
sensor-data外设执行的采集结果;根据实际数据源字段和质量更新页面
modbus-dataModbus 数据记录数组;大数组按完整记录分包
mqtt-statusMQTT 状态 JSON
modbus-statusModbus 状态 JSON
resync推送分包失败时的恢复提示,应通过 REST 重新取得当前快照
heartbeat文本 ping;维护周期达到 60 秒后发送

业务消息是 event.data 中的 JSON 字符串,须先 JSON.parse。具名事件使用 addEventListener;onmessage 不接收全部具名事件。传感器字段随配置变化,不保证存在顶层 temperature、humidity。失效、过期或读取失败不能以零值替代;有效零值可以正常显示。

Modbus 单包预算为 512 字节。超长记录数组按记录边界发送;单条记录不能分包或发送队列失败时可能已经收到部分记录,随后请求 resync。客户端应回读快照补齐,不能拼接这些数组当作一个原始 JSON 文档,也不能依靠事件 ID 重放所有漏失消息。

连接和内存限制 ​

连接预算来自 ResourceProfile::TCP_SSE_BUDGET:

芯片SSE 连接预算
ESP32、ESP32-C3、ESP32-C61
ESP32-S32

内部可按字节访问的 DRAM 最大连续块小于 8192 字节,或内存保护处于 SEVERE/CRITICAL 时,新连接返回 503,业务广播也会暂停。预算已满时通常拒绝新连接;连接建立时的并发竞争仍有驱逐旧连接的兜底处理。资源门控在认证检查之前执行,因此未登录请求也可能先得到 503;资源允许但会话无效时返回 401。

服务器以正长度 TCP ACK 更新连接活跃时间,120 秒未得到活跃确认时清理连接;将心跳入队不会刷新该时间。实际发送还受维护调度影响,60 秒不是严格定时或业务时效保证。内存和连接开销包含 TCP 缓冲、消息队列与客户端追踪,不能按固定 500 字节估算。

浏览器接入 ​

同源 EventSource('/api/events') 自动携带设备会话 Cookie。下面的最小示例在错误后等待 5 秒重连,重连或 resync 时提醒重新获取业务快照,并在离页后取消定时器:

javascript
let source = null;
let retryTimer = null;
let stopped = false;

function recoverSnapshot(reason) {
  // 集成方在此串行读取所需的 REST 数据,并核对质量与采样时间。
  console.info('需要刷新业务快照:', reason);
}

function connectEvents() {
  if (stopped || source) return;
  const current = new EventSource('/api/events');
  source = current;
  current.addEventListener('sensor-data', event => {
    if (source !== current || stopped) return;
    try {
      const payload = JSON.parse(event.data);
      console.log('本次采集:', payload);
    } catch (error) {
      recoverSnapshot('invalid_sensor_json');
    }
  });
  current.addEventListener('resync', () => recoverSnapshot('server_resync'));
  current.onopen = () => {
    if (source === current && !stopped) recoverSnapshot('connected');
  };
  current.onerror = () => {
    if (source !== current || stopped) return;
    current.close();
    source = null;
    if (retryTimer !== null) clearTimeout(retryTimer);
    retryTimer = setTimeout(() => {
      retryTimer = null;
      connectEvents();
    }, 5000);
  };
}

function stopEvents() {
  stopped = true;
  if (retryTimer !== null) clearTimeout(retryTimer);
  retryTimer = null;
  if (source) source.close();
  source = null;
}

window.addEventListener('pagehide', stopEvents);
connectEvents();

页面恢复时重新建立连接并刷新快照。项目现有 Web 客户端还提供指数退避和连接停滞检测,集成时优先复用 AppState 的事件注册及离页清理。

排障 ​

现象核对项
401重新登录,确认同源会话 Cookie
503 或连接被关闭关闭多余标签页,观察内部 DRAM 和保护状态,保持退避
只有心跳、无业务更新检查已启用的采集规则、协议任务与数据有效性
重连后数据缺失串行回读业务快照;心跳不补齐业务数据
收不到具名事件使用对应的 addEventListener 并解析 event.data

SSE 使用不需要先执行 /api/mqtt/test;该测试接口会暂存配置、断连和重建 MQTT。普通读取和页面恢复请使用状态接口。当前源码边界与旧设备版本分别核对,接口连通也不代表实物或长期稳定通过。

相关内容:API 参考、健康监控、MQTT 配置。

蜂信物联 | fastbee.cn