外观
事件与遥测接入
现场的事实从两条路进虹元:离散的事件(识别到一次违章、一次入侵)和连续的遥测(气体浓度每秒一读)。事件接入已经是生产链路,遥测接入是规划中的契约草案。这一页先讲节点怎么接上,再讲事件怎么上报。
节点配对
接入由虹元主动发起。虹元在同网段 UDP 广播自己的存在,报文不带任何密钥。广播是明文,收到就接入等于伪造一个广播就能劫走事件流,所以接入必须过一次人工确认:
- 运营在虹元控制台生成配对码,10 分钟有效,一次性。
- 智眸在配置页填虹元地址(同网段自动发现,不用填)与配对码,提交。
- 双方以 X25519 交换密钥,用配对码做盐派生会话密钥,换码即换密钥。
- 之后上行事件用会话密钥签名并加密,下行裁定回流用会话密钥派生的另一把密钥签名。
配对码起的是授权作用,本身不算保密手段。NAT 阻断广播时智眸手填虹元地址,走同一条握手。
配对不跨租户抢节点。节点名已经属于别的租户时,配对回 409,配对码不作废,换个节点名再配;同租户重新配对照常。生成配对码时撞上别人还没用、没过期的码,虹元自动重抽。配对成功后节点出现在控制台"已接入节点"里,可以切测试模式分流联调事件。未配对的节点可以用环境变量里预置的固定密钥接入。
事件接入接口
POST /api/uancore/events唯一的接收方是虹元。智眸到业务平台的直连已废止,任何两个系统之间都不直连。
鉴权与签名
| 请求头 | 内容 |
|---|---|
X-Uan-Node | 节点标识 |
X-Uan-Ts | 毫秒时间戳,与服务器时间相差不超过 300 秒 |
X-Uan-Sign | 十六进制小写的 HMAC-SHA256,密钥为节点会话密钥,签名对象是"时间戳、换行、请求体原始字节" |
X-Uan-Nonce | 可选。带上时请求体是加密后的密文,12 字节十六进制 |
签名基于原始字节,不能反序列化后再序列化,键序与空白会变。加密时签名对象就是密文,接收侧先验签再解密。不带随机数头即明文链路。
请求体
| 字段 | 必填 | 说明 |
|---|---|---|
dedup_key | 是 | 幂等键,构成 {节点}_{摄像头}_{事件类型}_{窗口起始秒} |
event_type | 是 | 叶子类型,如 ppe.no_helmet、fire.smoke、intrusion.area |
occurred_at | 是 | 发生时刻,毫秒时间戳 |
severity | 否 | 严重度提示,最终定级以人工确认为准 |
category | 否 | alarm 告警(默认)或 observation 观测,其他值拒绝 |
source.camera / source.camera_name | 否 | 摄像头编码与名称 |
site_ref | 否 | 场域编码 |
evidence | 否 | 证据数组,每项带地址与指纹;图片存在节点或对象存储,事件里只带引用 |
model | 否 | 产生它的模型与版本,能回答"当时是哪个模型判的" |
trace_id | 否 | 追踪号,缺则生成 |
test | 否 | 测试事件 |
callback_url | 否 | 裁定回流地址 |
source_alarm_id | 否 | 节点本地的告警编号,回流时用它定位 |
响应
json
{ "code": 200, "message": "success",
"data": { "eventId": 123, "duplicate": false, "traceId": "tr_…" } }幂等与去重
幂等键的作用域是"租户加幂等键"复合唯一,跨租户可以重复。重复上报不改写既有事实,只回既有编号,duplicate 为真,追踪号沿用库里那条。连续告警在智眸侧按算法冷却时间去抖后再上报,虹元不收告警风暴。
同一个幂等键但节点、摄像头或时刻对不上时,虹元返回冲突并记错误日志。这多半是两个站的节点重名,上线前逐站核对节点名。建议命名 {项目}-{站场}-{序号}。
发送侧重试
节点侧外发箱指数退避,最多 8 次,超期丢弃并留痕。接口一次一条事件,批量只出现在站端向总部的级联上行。
错误码
| HTTP | 业务码 | 含义 |
|---|---|---|
| 400 | 40000 | 请求不合法 |
| 401 | 40100 | 未通过鉴权 |
| 403 | 40300 | 无权限 |
| 404 | 40400 | 对象不存在,或不归这个租户 |
| 409 | 40900 | 冲突,回包另带 retryable |
| 429 | 42900 | 请求过频 |
| 500 | 50000 | 服务异常,不透内部细节 |
| 503 | 50300 | 暂时不可用,比如租户库连不上、统计超时 |
全站统一这一套映射,/api/ 下不存在的路径返回 JSON 形式的 404。
409 回包一律带 retryable。为真只有一种情况:几路并发撞车,服务端重来几次还不行,原样再发即可。为假是状态已经变了(别人先流转、先改了一版、对象已关闭),先重新读一次再决定。
边缘裁定上行
POST /api/uancore/events/edge_verdict值守人员在现场节点上直接确认或驳回的,节点把结果上行:本地告警编号、裁定(属实或误报)、操作者、备注。虹元按节点与本地告警编号定位事件,已裁定的不改写,不再回流。边缘确认真警后,该事件的待接手任务自动视为已接手。
证据取回
GET /api/uancore/events/{id}/evidence/{idx}虹元只存证据引用,图在节点。云端系统要看现场画面时经虹元按事件与证据序号取回,凭管理密钥;虹元在本地留一份缓存,可重取,不进备份。不要把节点直接暴露给云端。
证据直传
现场虹元不对公网开口时,云端进不来取图。推送是现场往外发,走得通,所以反方向再加一条:
- 消费方在推送回执里点名要哪几张,每张给一个对象存储的上传预签名:
{"code":200,"data":{"evidenceUploads":[{"eventId":123,"idx":0,"putUrl":"https://…","contentType":"image/jpeg"}]}}。事件编号必须是这一批推过去的,一批最多 300 张。 - 虹元从智眸取图,校验指纹,直接上传到
putUrl,失败重试两次。 - 传完向
{推送地址}/evidence报一次,签名同推送,体里逐张带事件编号、序号、指纹与字节数。
图片字节不经过消费方的服务器,虹元也拿不到消费方的对象存储密钥。直传失败只记日志,不重推事件,消费方仍可退回"经虹元取"。回执里没有 evidenceUploads 的老消费方,虹元什么都不做。
配置对账与托管
GET /api/uancore/sense/config?node=<节点键>
POST /api/uancore/sense/config/report节点定期上报本地实际生效的五段配置(算法清单、阈值、作用区域、模型版本、去抖参数),虹元与登记版本比对算差异。只接受五段,其余一律丢弃:下发错一个视频流地址当场断流,阈值错顶多漏报多报。
迁移三步:节点自动对账,一切照旧;运营点"采纳节点现状"作基线;差异归零后切托管,服务端强制校验差异已归零。节点在托管状态下自动应用下发配置在规划中,当前仍按本地配置运行。
遥测接入(规划中)
遥测契约是 v1 草案,虹元当前没有实现,先记设计要点:
- 设备先注册后推数,挂在场域或资产上,带告警上下限。设备类型:可燃与有毒气体、液位、压力、温度、人员定位越界。
- 平台判阈,设备只推原始值,阈值可改、可分级、可审计。
- 超限读数派生一条
iot.threshold事件进待确认队列,同设备同方向越限在冷却窗内不重复派。 - DCS / SCADA 只读采集,不做控制回写。
- 时序库、降采样、分级阈值在下一版。