From ca544ca61ab1dbd5a7add5ddb0f3adf9cf2dccf8 Mon Sep 17 00:00:00 2001 From: lzh Date: Mon, 6 Apr 2026 23:11:55 +0800 Subject: [PATCH] =?UTF-8?q?docs(iot):=20=E5=9F=BA=E4=BA=8E=E7=9C=9F?= =?UTF-8?q?=E5=AE=9E=E4=BB=A3=E7=A0=81=E9=87=8D=E7=BD=AEIoT=E6=96=87?= =?UTF-8?q?=E6=A1=A3=EF=BC=8C=E5=BC=95=E5=85=A5Codec=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E3=80=81=E7=89=A9=E6=A8=A1=E5=9E=8B=E5=85=83=E7=B4=A0=E3=80=81?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E8=A7=84=E5=88=99=E5=BC=95=E6=93=8E=E7=AD=89?= =?UTF-8?q?=E5=BA=95=E5=B1=82=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../03-IoT领域/01-设备接入与控制主链路.md | 85 +++++++++---------- 开发者文档/03-IoT领域/02-物模型标准设计.md | 63 +++++--------- .../03-IoT领域/03-规则引擎与联动策略.md | 59 +++++++------ 3 files changed, 95 insertions(+), 112 deletions(-) diff --git a/开发者文档/03-IoT领域/01-设备接入与控制主链路.md b/开发者文档/03-IoT领域/01-设备接入与控制主链路.md index 5c9db8b..c5e8902 100644 --- a/开发者文档/03-IoT领域/01-设备接入与控制主链路.md +++ b/开发者文档/03-IoT领域/01-设备接入与控制主链路.md @@ -1,59 +1,58 @@ # 01-设备接入与控制主链路 -IoT 系统的命脉在于可靠的通信机制。本链路基于 MQTT 协议,设计了设备从上线建连到数据双向交互的完整闭环。 +在 AIOT 平台中,IoT 设备接入由 `viewsh-module-iot-gateway` 统一处理,支持多种协议栈。这是物理世界数据流向业务系统的第一道关口。 -## 一、设备接入完整交互时序图 +## 一、支持的接入协议栈 + +根据底层网关编解码器(Codec)的实现,平台当前支持以下协议的设备接入: +- **MQTT**:主流通讯协议,配合 EMQX 等 Broker 进行上下行流转。 +- **JT808**:部标车载终端通信协议。 +- **Alink**:阿里标准物联网协议。 +- **TCP**:支持自定义的 TCP Binary(透传)与 TCP JSON 格式。 + +设备的网络通信类型 (`IotNetTypeEnum`) 抽象为:`WIFI`, `CELLULAR` (蜂窝), `ETHERNET` (以太网), `OTHER`。 + +## 二、MQTT 接入与状态流转 + +以最典型的 MQTT 接入为例,设备的状态流转受严格的网关路由管理: ```mermaid sequenceDiagram participant Device as IoT设备 - participant Gateway as MQTT Broker(网关) - participant IoTModule as module-iot(业务后服务) + participant EMQX as EMQX (Broker) + participant Gateway as module-iot-gateway - == 第一阶段:设备注册与认证 == - Device->>Gateway: CONNECT (Client ID, User, Password) - activate Gateway - Gateway->>IoTModule: 鉴权 Hook (校验 Token/秘钥) - IoTModule-->>Gateway: 鉴权通过 - Gateway-->>Device: CONNACK (连接接受) - deactivate Gateway + == 1. 设备鉴权与上线 == + Device->>EMQX: CONNECT + EMQX->>Gateway: 触发 AuthEventProtocol + Gateway->>Gateway: IotEmqxAuthEventHandler 校验 Token/秘钥 + Gateway-->>EMQX: 鉴权结果 + EMQX-->>Device: CONNACK - Device->>Gateway: SUBSCRIBE (Topic: /down/device/{id}) - Gateway-->>Device: SUBACK + Note over Gateway: 鉴权通过后,状态变更为 ONLINE(1) - == 第二阶段:保活与状态同步 == - loop 心跳周期 (如 30s) - Device->>Gateway: PINGREQ - Gateway-->>Device: PINGRESP - end + == 2. 上行数据 (Upstream) == + Device->>EMQX: PUBLISH (/up/telemetry) + EMQX->>Gateway: 推送数据 + Gateway->>Gateway: IotMqttUpstreamHandler 根据 Codec 解码 + Gateway->>Gateway: IotEmqxUpstreamProtocol 解析数据抛出事件 - == 第三阶段:数据上报 (Telemetry) == - Device->>Gateway: PUBLISH (Topic: /up/telemetry/{id}, Payload: JSON) - Gateway->>IoTModule: 消息路由/桥接 - IoTModule->>IoTModule: 根据设备品类物模型进行解析 - IoTModule->>IoTModule: 属性落库 / 存入时序数据库 + == 3. 下行指令 (Downstream) == + Gateway->>EMQX: PUBLISH (/down/command) via IotMqttDownstreamHandler + EMQX->>Device: 投递指令 + Device-->>EMQX: ACK / 结果返回 - == 第四阶段:指令下发 (Command) == - IoTModule->>Gateway: PUBLISH (Topic: /down/device/{id}, Payload: 控制指令) - Gateway->>Device: 推送下行消息 - activate Device - Device->>Device: 执行硬件动作 (如关阀门) - Device->>Gateway: PUBLISH (Topic: /up/reply/{id}, Payload: 执行结果) - deactivate Device - Gateway->>IoTModule: 结果回调 - IoTModule->>IoTModule: 更新指令状态及设备影子 + == 4. 断开与离线 == + Device->>EMQX: DISCONNECT 或 心跳超时 + EMQX->>Gateway: 触发离线事件 + Note over Gateway: 状态变更为 OFFLINE(2) ``` -## 二、通信链路设计红线与规范 +## 三、设备生命周期 (IotDeviceStateEnum) -### 1. QoS (服务质量) 策略 -- **数据上报 (Telemetry)**:推荐使用 **QoS 0**。传感器高频数据允许丢失单点,追求高吞吐量;若属于关键状态跳变(如火警触发),必须使用 **QoS 1**。 -- **指令下发 (Command)**:强制使用 **QoS 1**。云端下发的开关门、断电指令必须确保到达,依靠 MQTT 协议级 ACK 进行重传保证。 +系统对设备的在线状态维护极其严格,分为三种终态: +1. **`INACTIVE(0)` (未激活)**:设备在平台已建档,但从未与云端建立过通信。 +2. **`ONLINE(1)` (在线)**:TCP 连接保持中,或心跳周期内正常。 +3. **`OFFLINE(2)` (离线)**:网关层面检测到连接断开或心跳超时抛出的事件。 -### 2. 异常断连与重连退避 -- 硬件网络天然不可靠。设备端在断连后,重连机制必须包含**指数退避(Exponential Backoff)加随机抖动(Jitter)算法**。 -- **严禁**:断网后设备以固定的 1 秒频率死循环重连。这将在基站恢复或 Broker 重启时引发“重连风暴”,直接导致网关雪崩。 - -### 3. 上下线状态管理 -- 严禁通过轮询设备或单纯依赖心跳报文在业务代码里算超时。 -- 必须依赖 MQTT Broker 的 **连接/断开 Webhook (或遗嘱消息 Will Message)** 机制,由 Broker 主动回调 `module-iot` 通知设备上下线,业务侧被动更新 DB 状态。 \ No newline at end of file +严禁在业务层写死轮询来判断设备在线,必须监听 `IotDeviceStateEnum` 的状态翻转事件。 \ No newline at end of file diff --git a/开发者文档/03-IoT领域/02-物模型标准设计.md b/开发者文档/03-IoT领域/02-物模型标准设计.md index cc802b8..5158244 100644 --- a/开发者文档/03-IoT领域/02-物模型标准设计.md +++ b/开发者文档/03-IoT领域/02-物模型标准设计.md @@ -1,52 +1,31 @@ # 02-物模型标准设计 -如果你让一个做业务的程序员去处理设备发来的 `01 03 00 00 00 01 84 0A` (Modbus RTU),他会崩溃。 -**物模型(Thing Specification)**的作用就是把物理世界的设备抽象成程序员能看懂的“对象”。 +底层网关屏蔽了 JT808、MQTT、TCP Binary 等各种异构协议后,所有推入平台核心业务流的数据必须服从统一的「物模型(Thing Model)」规范。 -## 一、物模型三要素 (Property, Event, Service) +## 一、物模型三要素 (IotThingModelTypeEnum) -所有接入 AIOT 平台的设备,无论是摄像头、烟感还是水表,都必须在这三层结构下被抽象。 +根据系统的定义,任何设备的物模型结构被强制约束为三大类型: -### 1. 属性 (Property) -描述设备的运行状态(通常是只读或可读写的连续数据)。 -- **示例**:当前温度 (25.5℃)、工作模式 (Auto)、电池电量 (80%)。 -- **特点**:业务系统随时可以查询,云端需维护一份最新的副本(设备影子)。 +### 1. `PROPERTY(1)` (属性) +- 描述:反映设备连续的运行状态数据(如温度、电量、当前档位)。 +- 上报:对应网关的方法 `DEVICE_PROPERTY_POST`。 +- 业务处理:存入实时库或影子库。属性的设定可通过场景规则触发(`DEVICE_PROPERTY_SET`)。 -### 2. 事件 (Event) -设备在运行期间主动向云端发出的瞬时通知。 -事件分为三个等级: -- **INFO (信息)**:如“设备重启完成”。 -- **WARN (告警)**:如“网络延迟过高”。 -- **ERROR (故障)**:如“传感器短路”,此类事件通常直接触发规则引擎派生 Ops 工单。 +### 2. `SERVICE(2)` (服务) +- 描述:平台主动下发给设备的指令,设备执行后需要响应结果(如开阀、设置重启参数)。 +- 调用:对应 `DEVICE_SERVICE_INVOKE`。这更像一种双向 RPC 调用,通常会携带参数 (`IotThingModelParamDirectionEnum`)。 -### 3. 服务 (Service) / 指令 -云端向设备下发的要求设备执行某个动作的操作,且该操作通常需要硬件执行完毕后返回结果。 -- **示例**:开门 (openDoor)、设置重启定时 (setRebootTimer)。 -- **与属性的区别**:设置温度阈值是“写属性”,要求设备清空历史记录是“调服务”。服务更像是一个 RPC 调用。 +### 3. `EVENT(3)` (事件) +- 描述:设备主动上报的瞬时、非连续通知(如硬件故障、越界告警)。 +- 上报:对应 `DEVICE_EVENT_POST`。 +- 业务处理:通常直接送入规则引擎(`IotSceneRuleTriggerTypeEnum`)作为触发源。 -## 二、标准 JSON Payload 规范 +## 二、数据消费去向 (IotDataSinkTypeEnum) -网关接收到底层报文后,无论是何种私有协议,经过“协议解析脚本”后,推送到业务主逻辑的 JSON 必须符合以下规范: +物模型解析后的数据并非只是存在 MySQL 中,系统支持将数据分发到各种目标(Sink)供不同业务消费: +- **消息队列**:`ROCKETMQ(30)`, `RABBITMQ(31)`, `KAFKA(32)` —— 适合大数据量的数仓抽取。 +- **高速缓存**:`REDIS(21)` —— 适合大屏实时展示和设备影子。 +- **协议转发**:`HTTP(1)`, `TCP(2)`, `WEBSOCKET(3)`, `MQTT(10)` —— 适合外部系统对接。 +- **持久化**:`DATABASE(20)` —— 适合历史轨迹和报表查询。 -```json -{ - "device_id": "SN_12345678", - "timestamp": 1712419200000, - "type": "property_report", - "data": { - "temperature": 26.5, - "humidity": 45, - "battery_level": 88 - } -} -``` - -## 三、设备影子 (Device Shadow) 机制 - -**痛点**:由于设备可能休眠(如 NB-IoT 水表一天只醒一次),App 用户如果在这个时候去点“开阀”或者查询状态,是无法立刻得到设备回应的。 - -**解法:设备影子** -- 云端在 Redis/MySQL 中永久维护一份该设备最后一次上报的属性镜像。 -- 用户查询时:直接返回“影子”中的数据。 -- 用户下发控制时:指令先更新到“影子”的期望值(Expected Value)中,并缓存指令。 -- 当休眠设备下一次唤醒并上报心跳时,云端比对影子的“实际值”和“期望值”,发现不一致,立刻将缓存的控制指令下发给设备。 \ No newline at end of file +开发新业务时,请通过配置 Sink 来订阅数据,**不要在核心解析链路里直接写死 DB 插入代码**。 \ No newline at end of file diff --git a/开发者文档/03-IoT领域/03-规则引擎与联动策略.md b/开发者文档/03-IoT领域/03-规则引擎与联动策略.md index a916060..5d6d05e 100644 --- a/开发者文档/03-IoT领域/03-规则引擎与联动策略.md +++ b/开发者文档/03-IoT领域/03-规则引擎与联动策略.md @@ -1,37 +1,42 @@ -# 03-规则引擎与联动策略 +# 03-规则引擎与告警联动 -有了设备接入和物模型后,IoT 系统算跑通了单机,但 AIOT 的威力在于**联动**。 -本章节描述大量无序的设备数据如何安全、有效地转化为 Ops 系统的工单任务。 +规则引擎(Scene Rule)是打通设备感知(IoT)与人工干预(Ops)的桥梁。系统通过灵活的触发器和执行器组合,实现自动化的业务闭环。 -## 一、数据洪流与防抖过滤 +## 一、规则触发与执行架构 -在将设备异常转化为实际告警或工单之前,**防抖(Debounce)与收敛**是第一道防线。 +在 `IotSceneRule` 体系下,一个完整的规则包含**触发器 (Trigger)** 和 **执行器 (Action)**。 -### 1. 为什么要做防抖? -如果一个温湿度传感器发生故障,它可能会以 1 秒 1 次的频率疯狂上报 `[ERROR] 探头短路`。如果不做拦截直接联动 Ops,安保大叔的手机一分钟内会被弹 60 个“派单通知”,系统也会因为瞬间的数据库写入被压死。 +### 1. 触发类型 (`IotSceneRuleTriggerTypeEnum`) +系统支持 5 种维度的触发方式: +- **`DEVICE_STATE_UPDATE(1)`**:设备上下线翻转触发。 +- **`DEVICE_PROPERTY_POST(2)`**:属性上报触发(如温湿度数值变化)。由于属性可能批量上报,引擎会做拆解匹配。 +- **`DEVICE_EVENT_POST(3)`**:事件上报触发(如故障事件)。 +- **`DEVICE_SERVICE_INVOKE(4)`**:服务调用触发。 +- **`TIMER(100)`**:定时触发(如每天早上 8 点自动执行)。 -### 2. 规则引擎防抖策略 -- **时间窗口去重**:同一台设备的同一种事件(如烟感报警),在 5 分钟内无论上报多少次,规则引擎只向后置业务流抛出**一次**告警事件。 -- **状态跳变判断**:只有当属性值从“正常阈值”跨越到“告警阈值”的那个瞬间(Edge Trigger),才触发规则。一直在告警线以上的数据点不重复触发。 +### 2. 动作类型 (`IotSceneRuleActionTypeEnum`) +触发条件满足后,系统可执行如下动作组合: +- **联动反控**: + - `DEVICE_PROPERTY_SET(1)`:修改另一台设备的属性。 + - `DEVICE_SERVICE_INVOKE(2)`:调用另一台设备的服务(如温度高触发开风扇)。 +- **告警流转**: + - `ALERT_TRIGGER(100)`:触发告警(生成 `IotAlertRecordDO`)。 + - `ALERT_RECOVER(101)`:解除告警。 -## 二、IoT 到 Ops 的正向联动链路 +## 二、告警系统与 Ops 的联动 -从设备端发现问题,到现场人员赶到处理。 +告警 (`ALERT`) 是连接 Ops 派单引擎的关键介质。 -1. **规则命中**:设备上报数据解析出 `water_leak = true`,触发 `规则ID=102: 水管漏水告警`。 -2. **事件转换**:规则引擎组装一个标准的「内部系统事件(Internal Event)」,包含 `设备ID`、`发生时间`、`发生物理位置(查设备表获得)`、`告警级别`。 -3. **跨域调用**:`module-iot` 通过内部 API(禁止通过外网网关)调用 `module-ops` 的 `生成紧急工单` 接口。 -4. **接力执行**:Ops 系统接管,按照其内部的抢单、强推播逻辑(参见 [[../02-Ops领域/03-安保业务核心链路.md]]),将任务压给最近的安保或维修工。 +### 1. 告警产生 +当规则引擎执行了 `ALERT_TRIGGER` 动作,系统会在 `IotAlertRecord` 表中写入一条告警记录。该记录包含触发的规则 ID、设备 ID 和严重等级。 -## 三、Ops 到 IoT 的逆向状态闭环(反写) +### 2. 联动派单 (`EventDomainEnum.RULE`) +告警生成后,将向外抛出事件(领域标识为 `RULE`)。 +此时,`module-ops` 监听到告警事件,并根据内部逻辑: +- 如果属于紧急安保事件 -> 派发 `SECURITY` 类型的抢单任务给就近保安。 +- 如果属于设备故障 -> 派发 `REPAIR` 类型的工单给工程组。 -仅仅把单派出去是不够的,还需要实现信息闭环,防止 IoT 控制台和 Ops 控制台两张皮。 - -### 1. 告警状态解绑 -- IoT 侧的告警大屏上,该设备的告警状态会亮起红灯。 -- 这盏红灯何时熄灭?不能仅仅依赖传感器下一次上报“正常”(因为传感器可能坏死)。 -- **必须由 Ops 侧驱动**:当维修工人在手机 App 上提交了现场修复照片,并将维修工单流转为 `COMPLETED` 状态时,Ops 系统回调 IoT 的接口,将对应的那条告警记录状态变更为【人工已解除】。 - -### 2. 现场反控配合 -- 维修工到达现场处理故障时,由于控制箱被锁,他可以在 App 的工单详情页,点击「临时断电调试」。 -- 这个点击动作,穿透 Ops 域,直接调用 IoT 领域的“服务下发(Service Call)”接口,实现对现场断路器的远程切断。这证明了我们在架构中采用统一后端底座的优越性。 \ No newline at end of file +### 3. 告警处理闭环 (`IotAlertRecordProcessReqVO`) +当维修工或保安在现场处理完毕,通过移动端(App / 智能工牌)提交完工(状态变为 `COMPLETED`)后,Ops 系统必须调用 IoT 领域的处理接口。 +- 调用 `IotAlertRecordController.processAlert()` 进行状态核销。 +- 或者由设备恢复正常状态后,触发规则引擎的 `ALERT_RECOVER(101)` 动作实现自动核销。 \ No newline at end of file