diff --git a/开发者文档/03-IoT领域/升级设计方案/00-升级设计总览.md b/开发者文档/03-IoT领域/升级设计方案/00-升级设计总览.md index 7b3b0e2..350f3e7 100644 --- a/开发者文档/03-IoT领域/升级设计方案/00-升级设计总览.md +++ b/开发者文档/03-IoT领域/升级设计方案/00-升级设计总览.md @@ -20,49 +20,50 @@ ## 二、设计原则 -| 原则 | 说明 | -|------|------| -| **南向屏蔽,北向统一** | 协议层允许混乱,业务层必须干净(继承现有铁律) | -| **JetLinks 为主骨架** | 规则引擎、条件引擎、SPI 扩展采用 JetLinks 模式 | -| **ThingsBoard 补关键设计** | 属性三元分类、RPC 状态机、EntityRelation、告警状态机 | -| **保留现有消息总线** | Local/Redis/RocketMQ 三实现不动,消费端接入新引擎 | -| **渐进式迁移** | 新旧规则可并行运行,不要求一次性切换 | +| 原则 | 说明 | +| --------------------- | ----------------------------------- | +| **南向屏蔽,北向统一** | 协议层允许混乱,业务层必须干净(继承现有铁律) | +| **JetLinks 为主骨架** | 规则引擎、条件引擎、SPI 扩展采用 JetLinks 模式 | +| **ThingsBoard 补关键设计** | 属性三元分类、RPC 状态机、告警状态机 | +| **保留现有消息总线** | Local/Redis/RocketMQ 三实现不动,消费端接入新引擎 | +| **渐进式迁移** | 新旧规则可并行运行,不要求一次性切换 | --- ## 三、文档索引 -| 编号 | 文档 | 内容 | -|------|------|------| -| 01 | [[01-整体架构设计]] | 模块划分、分层架构、依赖关系、部署拓扑 | -| 02 | [[02-子系统与设备归属模型]] | 租户→项目→子系统→设备层级、设备归属管理 | -| 03 | [[03-物模型规范v2]] | 属性三元分类、派生物模型、数据类型增强 | -| 04 | [[04-规则引擎方案]] | DAG 编排、SPI Provider、脚本节点、抖动抑制 | -| 05 | [[05-告警体系设计]] | 两级存储、状态机、传播机制、通知集成 | -| 06 | [[06-设备影子与RPC]] | Shared 属性同步、持久化 RPC 状态机、离线指令队列 | -| 07 | [[07-数据存储方案]] | 存储策略插件化、写入缓冲、Key 压缩、TDengine 优化 | -| 08 | [[08-协议与编解码扩展]] | 协议包热加载、Codec SPI、透传编解码 | +| 编号 | 文档 | 内容 | +| --- | ----------------- | ------------------------------- | +| 01 | [[01-整体架构设计]] | 模块划分、分层架构、依赖关系、部署拓扑 | +| 02 | [[02-子系统与设备归属模型]] | 租户→项目→子系统→设备层级、设备归属管理 | +| 03 | [[03-物模型规范v2]] | 属性三元分类、派生物模型、数据类型增强 | +| 04 | [[04-规则引擎方案]] | DAG 编排、SPI Provider、脚本节点、抖动抑制 | +| 05 | [[05-告警体系设计]] | 两级存储、状态机、传播机制、通知集成 | +| 06 | [[06-设备影子与RPC]] | Shared 属性同步、持久化 RPC 状态机、离线指令队列 | +| 07 | [[07-数据存储方案]] | 时序库双实现(CTSDB/TDengine)、写入缓冲、缓存优化 | +| 08 | [[08-协议与编解码扩展]] | 协议包热加载、Codec SPI、透传编解码 | --- ## 四、融合策略速查表 -| 设计点 | 取自 | 说明 | -| ------ | -------------------------- | ------------------------------------------ | -| 规则引擎框架 | JetLinks SceneRule DAG | 串行/并行/分支编排 | -| 条件引擎 | JetLinks ReactorQL 思路 | 编译期过滤器,支持指标对比 | -| 脚本节点 | TB TBEL 思路 | Aviator/QLExpress 实现,Action Provider 注册 | -| 抖动抑制 | JetLinks ShakeLimit | 7 参数模型,参数化配置 | -| 消息总线 | 保留现有 | Local/Redis/RocketMQ 三实现 | -| 子系统模型 | 简化层级:租户→项目→子系统→设备 | 设备 FK 归属子系统,本次只做设备-子系统关系 | -| 设备影子 | TB 属性三元分类 + RPC | Client/Server/Shared + 持久化状态机 | -| 告警系统 | JetLinks 两级存储 + TB 状态机 | Record + History + Create→Update→Clear→ACK | -| 物模型继承 | JetLinks 派生物模型 | 设备级覆盖产品定义 | -| 存储策略 | JetLinks 策略模式 | 产品级配置存储后端 | -| 协议扩展 | JetLinks 协议热加载 | JAR + ClassLoader 隔离 | -| SPI 扩展 | JetLinks Provider + TB 注解 | 动态注册 + 元数据自描述 | -| 可观测性 | JetLinks + TB Micrometer | 连接数/吞吐量/规则耗时 | -| 写入缓冲 | JetLinks PersistenceBuffer | 内存+文件双层批量写入 | +| 设计点 | 取自 | 说明 | +| -------- | -------------------------- | ------------------------------------------ | +| 规则引擎框架 | JetLinks SceneRule DAG | 串行/并行/分支编排 | +| 条件引擎 | JetLinks ReactorQL 思路 | 编译期过滤器,支持指标对比 | +| 脚本节点 | TB TBEL 思路 | Aviator/QLExpress 实现,Action Provider 注册 | +| 抖动抑制 | JetLinks ShakeLimit | 7 参数模型,参数化配置 | +| 消息总线 | 保留现有 | Local/Redis/RocketMQ 三实现 | +| 子系统模型 | 简化层级:租户→项目→子系统→设备 | 设备 FK 归属子系统,本次只做设备-子系统关系 | +| 设备影子 | TB 属性三元分类 + RPC | Client/Server/Shared + 持久化状态机 | +| 告警系统 | JetLinks 两级存储 + TB 状态机 | Record + History + Create→Update→Clear→ACK | +| 物模型继承 | JetLinks 派生物模型 | 设备级覆盖产品定义 | +| 存储策略 | 已有双实现 + JetLinks 策略模式 | CTSDB/TDengine 可切换,DAO 接口统一 | +| 协议扩展 | JetLinks 协议热加载 | JAR + ClassLoader 隔离 | +| SPI 扩展 | JetLinks Provider + TB 注解 | 动态注册 + 元数据自描述 | +| 可观测性 | JetLinks + TB Micrometer | 连接数/吞吐量/规则耗时 | +| 写入缓冲 | JetLinks PersistenceBuffer | 内存+文件双层批量写入 | +| Agent 协作 | TB 4.2 AI Node 思路 + ACP 协议 | IoT 内先实现 Agent 调用,后续抽取为平台 ai 模块 | --- @@ -75,6 +76,7 @@ | Edge 同步 | TB | 无边缘计算需求 | | 完整 87 节点 | TB | 20-25 个覆盖核心场景 | | 全栈响应式 | JetLinks | 现有 Spring MVC 生态稳定,不做全量迁移 | +| TB AI Node 直连 LLM | TB 4.2 | 不直接对接模型,改为 ACP 协议调用内部 Agent 服务 | | ReactorQL 原版 | JetLinks | 依赖 Project Reactor,改用表达式引擎替代核心思路 | | EntityRelation 图关系 | TB | 过度设计,改用简洁的 subsystem_id FK 归属 | diff --git a/开发者文档/03-IoT领域/升级设计方案/01-整体架构设计.md b/开发者文档/03-IoT领域/升级设计方案/01-整体架构设计.md index 247f7df..6659925 100644 --- a/开发者文档/03-IoT领域/升级设计方案/01-整体架构设计.md +++ b/开发者文档/03-IoT领域/升级设计方案/01-整体架构设计.md @@ -31,7 +31,7 @@ │ Codec SPI(Alink/JT808/Camera3D11/...) │ ├─────────────────────────────────────────────────────┤ │ 存储层(Storage) │ -│ MySQL(业务实体) │ TDengine(时序数据) │ Redis(缓存) │ +│ MySQL(业务实体) │ 时序库 CTSDB/TDengine │ Redis(缓存) │ └─────────────────────────────────────────────────────┘ ``` @@ -81,7 +81,7 @@ viewsh-module-iot/ │ │ └── statistics/ # 统计(增强) │ ├── dal/ # 数据访问 │ │ ├── mysql/ # 关系库 -│ │ ├── tdengine/ # 时序库(策略模式增强) +│ │ ├── tsdb/ # 时序库(CTSDB/TDengine 双实现) │ │ └── redis/ # 缓存 │ └── framework/ # 框架层 │ ├── observe/ # 【新增】可观测性(Micrometer) @@ -120,21 +120,226 @@ server 额外依赖: |------|------|------| | **IotProjectDO** | `iot_project` | 项目(架构预留,本次不开放 API) | | **IotSubsystemDO** | `iot_subsystem` | 子系统(设备归属单元) | -| **IotAlarmHistoryDO** | TDengine `alarm_history` | 告警时序归档 | +| **IotAlarmHistoryDO** | 时序库 `alarm_history` | 告警时序归档(CTSDB/TDengine) | | **IotDeviceRpcDO** | `iot_device_rpc` | 持久化 RPC 指令 | | **IotRuleChainDO** | `iot_rule_chain` | 规则链(DAG 图定义) | | **IotRuleNodeDO** | `iot_rule_node` | 规则节点 | --- -## 五、关键技术选型变更 +## 五、端到端业务链路 + +从设备上报到最终动作的完整链路,覆盖 v2.0 所有设计点: + +![[iot-e2e-business-flow.png]] + +``` +═══════════════════════════════════════════════════════════════════════════════ + 设备接入层(Gateway) +═══════════════════════════════════════════════════════════════════════════════ + + 物理设备 网关 + ┌──────┐ MQTT/HTTP/TCP ┌─────────────────────────────────────────┐ + │ 传感器 │ ──── 原始报文 ────→ │ Codec SPI │ + │ 控制器 │ │ ├── ALink Codec(阿里协议) │ + │ 摄像头 │ │ ├── JT808 Codec(定位协议) │ + │ 工牌 │ │ └── Camera3D11 Codec(摄像头协议) │ + └──────┘ │ ↓ 解码 │ + │ IotDeviceMessage(统一消息模型) │ + │ {deviceKey, productKey, type, │ + │ identifier, data, timestamp} │ + └──────────────┬──────────────────────────┘ + │ +═══════════════════════════════════════════════╪═══════════════════════════════ + 消息总线(Message Bus)│ +═══════════════════════════════════════════════╪═══════════════════════════════ + │ + ┌───────────────────────────────┤ + │ 三种实现按部署模式选择 │ + │ ├── LocalMessageBus(单机) │ + │ ├── RedisStreamMessageBus │ + │ └── RocketMQMessageBus │ + └───────────────────────────────┤ + ↓ +═══════════════════════════════════════════════════════════════════════════════ + 核心服务层(Core Services) +═══════════════════════════════════════════════════════════════════════════════ + + IotDeviceMessageSubscriber(统一消息消费者) + │ + ├──→ ① 设备状态更新 + │ └── 在线/离线状态 → Redis 标记 + │ └── 上线时触发: + │ ├── Shared 属性同步(pending → 下发) ← 06-设备影子 + │ └── Pending RPC 补发(限速 5 条/秒) ← 06-设备影子 + │ + ├──→ ② 属性三元分类写入 ← 03-物模型v2 + │ ├── CLIENT 属性 → Redis iot:device_property:{id}:client + │ ├── SERVER 属性 → Redis iot:device_property:{id}:server(规则引擎写) + │ └── SHARED 属性 → Redis iot:device_property:{id}:shared + MySQL + │ + ├──→ ③ 时序数据持久化 ← 07-数据存储 + │ └── PersistenceBuffer(内存+文件双层) + │ → 批量写入时序库(CTSDB 异步批量 / TDengine PersistenceBuffer) + │ + ├──→ ④ 派生物模型合并 ← 03-物模型v2 + │ └── 设备级覆盖产品定义(derive_metadata JSON) + │ + └──→ ⑤ 规则引擎触发 ← 04-规则引擎 + │ + ↓ +═══════════════════════════════════════════════════════════════════════════════ + 规则引擎层(Rule Engine) +═══════════════════════════════════════════════════════════════════════════════ + + IotRuleEngineMessageHandler(统一入口) + │ + │ 按 subsystemId + productId + deviceId 匹配规则链(全量缓存) + │ 同时匹配 subsystemId=NULL 的全局规则链 + │ + ↓ ← 链级 try-catch 隔离,单链异常不影响其他链(工程评审决议 #3) + ┌─────────────────────────────────────────────────────────────────┐ + │ RuleChain DAG 执行 │ + │ │ + │ ┌─────────┐ │ + │ │ Trigger │ 设备属性上报 / 设备事件 / 设备上下线 / 定时 / 手动 │ + │ └────┬────┘ │ + │ ↓ │ + │ ┌─────────┐ │ + │ │ Enrich │ 数据富化(可选) │ + │ │ │ ├── 读取设备最新属性(Redis) │ + │ │ │ ├── 读取属性历史(时序库) │ + │ │ │ └── 读取关联设备/资产信息 │ + │ │ │ 结果注入 → RuleContext.metadata │ + │ └────┬────┘ │ + │ ↓ │ + │ ┌──────────┐ │ + │ │ Condition │ 条件评估 │ + │ │ │ ├── Expression:Aviator 表达式 │ + │ │ │ │ temperature > 40 && humidity < 20 │ + │ │ │ ├── Script:脚本条件(复杂逻辑) │ + │ │ │ ├── TimeRange:时间范围过滤 │ + │ │ │ └── DeviceState:在线/离线判断 │ + │ └────┬────┘ │ + │ ↓ │ + │ ┌──────────────┐ │ + │ │ ShakeLimit │ 抖动抑制(可选) │ + │ │ │ 10 秒窗口内连续 3 次触发才真正执行 │ + │ │ │ ├── 固定窗口 / 滚动窗口 │ + │ │ │ ├── 取第一条 / 取最后一条 │ + │ │ │ └── 连续模式:不满足则重置计数 │ + │ └────┬────┘ │ + │ ↓ │ + │ ┌─────────────┐ │ + │ │ Branch │ 分支执行 │ + │ │ ├── 分支A │ executeAnyway=false → if/else-if 语义 │ + │ │ │ 条件组 │ executeAnyway=true → 重叠触发 │ + │ │ │ ↓ │ │ + │ │ │ Actions │ │ + │ │ ├── 分支B │ │ + │ │ │ ... │ │ + │ └──┴──┬──┴────┘ │ + │ ↓ │ + │ ┌───────────────────────────────────────────────────────────┐ │ + │ │ Actions(动作层) │ │ + │ │ │ │ + │ │ ┌── 设备控制 ──────────────────────────────────────────┐ │ │ + │ │ │ device_property_set 设置设备属性(Shared 属性下发) │ │ │ + │ │ │ device_service_invoke 调用设备服务(持久化 RPC) │ │ │ + │ │ │ ↓ │ │ │ + │ │ │ RPC 状态机:QUEUED → SENT → SUCCESS │ │ │ + │ │ │ 设备离线 → 持久化等待 → 上线补发 │ │ │ + │ │ └───────────────────────────────────────────────────────┘ │ │ + │ │ │ │ + │ │ ┌── 告警处理 ──────────────────────────────────────────┐ │ │ + │ │ │ alarm_trigger 触发告警(ACTIVE 状态) │ │ │ + │ │ │ ├── upsert AlarmRecord(MySQL 幂等) │ │ │ + │ │ │ ├── append AlarmHistory(时序库) │ │ │ + │ │ │ └── 告警传播(沿子系统层级向上) │ │ │ + │ │ │ alarm_clear 清除告警(CLEARED 状态) │ │ │ + │ │ │ 竞态保护:Redis 缓存 + 分布式锁 │ │ │ + │ │ └───────────────────────────────────────────────────────┘ │ │ + │ │ │ │ + │ │ ┌── 数据转发 ──────────────────────────────────────────┐ │ │ + │ │ │ http_push HTTP 推送(Webhook) │ │ │ + │ │ │ mq_push MQ 推送(RocketMQ/Kafka/RabbitMQ) │ │ │ + │ │ │ redis_push Redis 推送 │ │ │ + │ │ │ tcp_push TCP 推送 │ │ │ + │ │ └───────────────────────────────────────────────────────┘ │ │ + │ │ │ │ + │ │ ┌── 通知 ──────────────────────────────────────────────┐ │ │ + │ │ │ notify 短信 / 邮件 / 站内信 / 企业微信 / 钉钉 │ │ │ + │ │ │ 模板变量:${alarm.name} ${device.name} ... │ │ │ + │ │ └───────────────────────────────────────────────────────┘ │ │ + │ │ │ │ + │ │ ┌── 数据处理 ──────────────────────────────────────────┐ │ │ + │ │ │ script Aviator 脚本(数据转换、单位换算、字段映射) │ │ │ + │ │ │ 沙箱:超时 3s + 循环上限 1000 + 黑名单 │ │ │ + │ │ │ enrich 数据富化(读取属性/历史/关联设备) │ │ │ + │ │ │ delay 延迟执行 │ │ │ + │ │ │ log 日志记录 │ │ │ + │ │ └───────────────────────────────────────────────────────┘ │ │ + │ │ │ │ + │ │ ┌── Agent 协作(预留)─────────────────────────────────┐ │ │ + │ │ │ agent_request ACP 协议调用内部 Agent 服务 │ │ │ + │ │ │ ├── 异常检测 Agent │ │ │ + │ │ │ ├── 保洁质检 Agent │ │ │ + │ │ │ ├── 能耗分析 Agent │ │ │ + │ │ │ └── 结果注入 metadata → 后续节点引用 │ │ │ + │ │ └───────────────────────────────────────────────────────┘ │ │ + │ └───────────────────────────────────────────────────────────┘ │ + └─────────────────────────────────────────────────────────────────┘ + +═══════════════════════════════════════════════════════════════════════════════ + 存储层(Storage) +═══════════════════════════════════════════════════════════════════════════════ + + ┌─────────────────────────────────────────────────────────────────────┐ + │ MySQL │ 时序库(CTSDB/TDengine)│ Redis │ + │ ├── iot_subsystem │ ├── device_message │ ├── 属性缓存│ + │ ├── iot_device(+subsystem_id) │ ├── product_property │ │ (三元分类)│ + │ ├── iot_rule_chain/node/link │ ├── alarm_history │ ├── 设备在线│ + │ ├── iot_alarm_record │ ├── rule_debug_log │ ├── 告警缓存│ + │ ├── iot_device_rpc │ └── 通过 DAO 接口 │ ├── 规则缓存│ + │ ├── iot_agent_service │ 双实现可切换 │ └── RPC 超时│ + │ └── iot_project(预留) │ │ │ + └─────────────────────────────────────────────────────────────────────┘ +``` + +### 典型场景走读 + +**场景:温度传感器上报 → 异常检测 → 告警 → 通知** + +``` +1. 传感器通过 MQTT 上报 {"temperature": 52, "humidity": 18} +2. Gateway ALink Codec 解码 → IotDeviceMessage +3. 消息总线投递 → IotDeviceMessageSubscriber 消费 +4. 属性写入 Redis(CLIENT scope)+ 时序库存储 +5. 规则引擎匹配:该设备属于"安防子系统",命中 2 条规则链 +6. 规则链 A(场景联动): + ├── Trigger: device_property(温度上报) + ├── Enrich: 读取近 1 小时均值温度 → metadata.avgTemp = 38 + ├── Condition: temperature > 40 → true + ├── ShakeLimit: 30 秒内第 3 次触发 → 通过 + ├── AgentRequest: anomaly-detector → {"level":"critical","reason":"偏离均值 14°C"} + ├── AlarmTrigger: 创建 CRITICAL 告警(upsert Record + append History) + ├── 告警传播: 安防子系统 → 1 楼 → 楼宇 A + └── Notify: 短信通知安防负责人 +7. 规则链 B(数据转发): + ├── Trigger: device_property + └── HttpPush: 推送到第三方监控平台 +``` + +--- + +## 六、关键技术选型变更 | 领域 | v1.0(现有) | v2.0(目标) | |------|-------------|-------------| | 规则引擎条件 | SpEL 字符串表达式 | Aviator 表达式引擎(编译缓存+类型安全) | | 脚本执行 | 无 | Aviator/QLExpress(轻量+沙箱) | | 规则编排 | 平铺动作列表 | DAG(RuleModel,参考 JetLinks) | -| 告警存储 | 单表 MySQL | MySQL(AlarmRecord 当前)+ TDengine(AlarmHistory 时序) | +| 告警存储 | 单表 MySQL | MySQL(AlarmRecord 当前)+ 时序库(AlarmHistory,CTSDB/TDengine) | | 设备属性 | Redis Hash(无分类) | Redis Hash + AttributeScope 三元分类 | | RPC | 单次下发,丢失不重试 | 持久化 RPC + 状态机(QUEUED→SENT→DELIVERED→SUCCESS) | | 设备组织 | groupIds JSON 数组 | 子系统归属(subsystem_id FK)+ 分组保留并存 | diff --git a/开发者文档/03-IoT领域/升级设计方案/02-子系统与设备归属模型.md b/开发者文档/03-IoT领域/升级设计方案/02-子系统与设备归属模型.md index abed254..fb701c8 100644 --- a/开发者文档/03-IoT领域/升级设计方案/02-子系统与设备归属模型.md +++ b/开发者文档/03-IoT领域/升级设计方案/02-子系统与设备归属模型.md @@ -4,6 +4,8 @@ ## 一、组织层级架构 +![[diagram-subsystem-er.png]] + ``` 租户(Tenant) ← 已有,TenantBaseDO └── 项目(Project) ← 架构预留,本次不实现 diff --git a/开发者文档/03-IoT领域/升级设计方案/03-物模型规范v2.md b/开发者文档/03-IoT领域/升级设计方案/03-物模型规范v2.md index 360fb58..892d943 100644 --- a/开发者文档/03-IoT领域/升级设计方案/03-物模型规范v2.md +++ b/开发者文档/03-IoT领域/升级设计方案/03-物模型规范v2.md @@ -6,6 +6,8 @@ ## 一、属性三元分类(借鉴 ThingsBoard) +![[diagram-attribute-classification.png]] + ### 1.1 设计动机 现有系统所有属性不区分来源和可见性,设备上报的状态、平台计算的指标、下发给设备的配置混在一起。引入 **AttributeScope** 三元分类: @@ -40,7 +42,7 @@ iot:device_property:{deviceId}:server → {identifier: value} iot:device_property:{deviceId}:shared → {identifier: value} ``` -**TDengine 不变**:时序数据仍按 `product_property_{productId}` 超级表存储,scope 作为普通列(TINYINT)标记。 +**时序库不变**:时序数据仍按 `product_property_{productId}` 存储(CTSDB 为 measurement,TDengine 为超级表),scope 作为字段标记。 ### 1.4 物模型属性定义扩展 @@ -108,9 +110,9 @@ List getEffectiveThingModel(Long deviceId) { ### 3.1 新增 TIMESTAMP 类型 -| 物模型类型 | TDengine 类型 | 说明 | -|-----------|-------------|------| -| `timestamp` | TIMESTAMP | 毫秒级时间戳(新增) | +| 物模型类型 | CTSDB (InfluxDB) | TDengine | 说明 | +|-----------|-----------------|----------|------| +| `timestamp` | TIMESTAMP | TIMESTAMP | 毫秒级时间戳(新增) | ### 3.2 struct/array 支持嵌套校验 diff --git a/开发者文档/03-IoT领域/升级设计方案/04-规则引擎方案.md b/开发者文档/03-IoT领域/升级设计方案/04-规则引擎方案.md index f319dd9..9b4f082 100644 --- a/开发者文档/03-IoT领域/升级设计方案/04-规则引擎方案.md +++ b/开发者文档/03-IoT领域/升级设计方案/04-规则引擎方案.md @@ -12,6 +12,8 @@ ## 二、核心架构 +![[diagram-rule-action-tree.png]] + ``` 设备消息(IotDeviceMessage) ↓ 消息总线消费 @@ -139,6 +141,7 @@ interface ConditionEvaluator { | `delay` | DelayAction | **新增** | 延迟执行 | | `enrich` | EnrichAction | **新增** | 数据富化(读取属性/时序) | | `log` | LogAction | **新增** | 日志记录 | +| `agent_request` | AgentRequestAction | **预留** | 调用外部 Agent 服务(ACP 协议) | **条件评估器(Condition):** @@ -148,6 +151,7 @@ interface ConditionEvaluator { | `script` | ScriptCondition | 脚本条件(复杂逻辑) | | `time_range` | TimeRangeCondition | 时间范围(当日时间/日期区间) | | `device_state` | DeviceStateCondition | 设备在线/离线状态 | +| `agent_judge` | AgentConditionEvaluator | **预留** 调用 Agent 做复杂条件判断 | --- @@ -248,7 +252,7 @@ class ShakeLimitConfig { | 富化类型 | 配置 | 说明 | |---------|------|------| | `device_property` | deviceId + identifiers | 读取设备最新属性(从 Redis) | -| `device_history` | deviceId + identifier + timeRange | 读取属性历史(从 TDengine) | +| `device_history` | deviceId + identifier + timeRange | 读取属性历史(从时序库) | | `related_device` | relationType + identifiers | 读取关联设备属性 | | `asset_info` | assetId 或 relationType | 读取所属资产信息 | @@ -306,7 +310,7 @@ class ShakeLimitConfig { 规则链 `debug_mode=true` 时: - 每个节点执行前后记录 `RuleContext` 快照 -- 写入 TDengine `rule_debug_log` 表 +- 写入时序库 `rule_debug_log` 表 - 前端可回放执行路径,查看每步的输入/输出/耗时 - 生产环境建议关闭(性能开销) @@ -372,3 +376,319 @@ Map> ruleChainIndex; // key → ruleChainIds ``` 不使用延迟加载(@Cacheable),避免首次消息处理的延迟和 TTL 窗口期数据不一致。 + +--- + +## 十二、Agent 协作节点 + +> 参考:ThingsBoard 4.2 AI Request Node 思路 + ACP 智能体通信协议 +> 本阶段在 IoT 模块内实现 Agent 调用能力,后续成熟后再抽取为平台级 `viewsh-module-ai` 模块。 + +### 12.1 设计背景 + +TB 4.2 新增了 AI Request 规则节点,直接对接 LLM API(OpenAI/Gemini 等)。我们的场景不同:不直接对接模型,而是通过 **ACP(Agent Communication Protocol)协议** 调用内部已有的 Agent 服务(数字员工),由 Agent 内部决定调用哪个模型、如何处理。 + +``` +TB 方式: 规则节点 ──→ LLM API(OpenAI/Gemini) +我们的方式:规则节点 ──→ AgentCallService ──→ AcpClient ──→ Agent 服务(数字员工) + └── 全部在 IoT 模块内,后续抽取为独立 ai 模块 +``` + +### 12.2 模块内部结构 + +Agent 调用相关代码放在 `viewsh-module-iot-biz` 的 `agent` 包下,与规则引擎同模块部署: + +``` +viewsh-module-iot-biz/ +└── src/main/java/.../iot/ + ├── rule/ ← 规则引擎(已有) + │ └── action/ + │ └── AgentRequestAction.java ← 规则节点 + └── agent/ ← Agent 调用(新增) + ├── dal/ + │ ├── IotAgentServiceDO.java ← 实体 + │ └── IotAgentServiceMapper.java + ├── service/ + │ ├── IotAgentServiceService.java ← Agent 注册表 CRUD + │ └── IotAgentCallService.java ← 调用编排(组装请求 + 调 ACP + 解析响应) + ├── client/ + │ ├── AcpClient.java ← ACP 协议客户端接口 + │ └── AcpHttpClient.java ← HTTPS 实现(先做同步,后续加 WSS/SSE) + └── controller/ + └── IotAgentServiceController.java ← 管理后台 CRUD +``` + +**后续抽取路径**:当 Ops 等其他模块也需要调 Agent 时,将 `agent/` 包整体迁移到 `viewsh-module-ai`,IoT 侧改为 Feign 调用。接口不变,只是调用方式从本地变远程。 + +### 12.3 调用架构 + +``` +┌───────────────────────────────────────────────────────┐ +│ viewsh-module-iot-biz │ +│ │ +│ 规则引擎 Agent 调用 │ +│ ┌─────────────────────┐ ┌──────────────────┐ │ +│ │ AgentRequestAction │──调用──→│ IotAgentCallService│ │ +│ │ (ActionProvider) │ │ ├── 查询 Agent 配置│ │ +│ └─────────────────────┘ │ ├── 组装 ACP 请求 │ │ +│ │ └── 解析响应 │ │ +│ └────────┬─────────┘ │ +│ │ │ +│ ┌────────↓─────────┐ │ +│ │ AcpClient │ │ +│ │ HTTPS 同步调用 │ │ +│ └────────┬─────────┘ │ +│ │ │ +└──────────────────────────────────────────┼─────────────┘ + │ ACP 协议 + ┌─────────↓──────────┐ + │ 外部 Agent 服务 │ + │ ├── 异常检测 Agent │ + │ ├── 保洁质检 Agent │ + │ ├── 能耗分析 Agent │ + │ └── 工单派发 Agent │ + └────────────────────┘ +``` + +### 12.4 数据模型 + +```sql +CREATE TABLE iot_agent_service ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(128) NOT NULL COMMENT 'Agent 服务名称', + code VARCHAR(64) NOT NULL COMMENT 'Agent 编码(业务标识)', + description TEXT COMMENT 'Agent 能力描述', + -- ACP 连接 + acp_endpoint VARCHAR(512) NOT NULL COMMENT 'ACP 接入点地址', + agent_aid VARCHAR(256) NOT NULL COMMENT '目标 Agent AID(身份标识)', + auth_mode VARCHAR(32) DEFAULT 'free' COMMENT '认证方式(free/token/pki)', + auth_config JSON COMMENT '认证配置', + -- 能力声明 + input_format JSON COMMENT '输入格式说明(JSON Schema,可选)', + output_format JSON COMMENT '输出格式说明(JSON Schema,可选)', + capabilities JSON COMMENT '能力标签 ["anomaly_detection","time_series"]', + -- 调用约束 + timeout_seconds INT DEFAULT 60 COMMENT '默认超时(秒)', + max_concurrency INT DEFAULT 10 COMMENT '最大并发调用数', + -- 通用字段 + status TINYINT DEFAULT 1, + tenant_id BIGINT NOT NULL, + creator VARCHAR(64), + create_time DATETIME DEFAULT CURRENT_TIMESTAMP, + updater VARCHAR(64), + update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + deleted BIT DEFAULT 0, + UNIQUE KEY uk_code_tenant (code, tenant_id, deleted) +) COMMENT 'Agent 服务注册表(后续迁移至 ai 模块)'; +``` + +### 12.5 核心实现 + +#### AcpClient(ACP 协议客户端) + +```java +/** + * ACP 协议客户端 —— 封装与 Agent 的通信 + * 本阶段只实现 HTTPS 同步模式,后续按需扩展 WSS/SSE + */ +public interface AcpClient { + /** + * 同步调用:建 Session → 发消息 → 等响应 → 关 Session + */ + AcpResponse call(AcpRequest request); +} + +@Data @Builder +class AcpRequest { + private String endpoint; // ACP 接入点地址 + private String targetAid; // 目标 Agent AID + private String authMode; + private String authConfig; + private JsonNode payload; // 业务数据 + private Map metadata; // 附加上下文 + private int timeoutSeconds; +} + +@Data +class AcpResponse { + private boolean success; + private String sessionId; + private JsonNode data; // Agent 返回结果 + private String errorMessage; + private long latencyMs; +} +``` + +#### IotAgentCallService(调用编排) + +```java +@Service +public class IotAgentCallService { + + private final IotAgentServiceService agentServiceService; + private final AcpClient acpClient; + + /** + * 调用 Agent 服务 + * @param agentCode Agent 编码 + * @param payload 业务数据 + * @param context 调用上下文(来源、设备信息等) + * @param timeoutOverride 超时覆盖(null 则使用 Agent 默认超时) + */ + public AgentCallResult call(String agentCode, JsonNode payload, + Map context, Integer timeoutOverride) { + // 1. 查询 Agent 配置 + IotAgentServiceDO agent = agentServiceService.getByCode(agentCode); + if (agent == null || agent.getStatus() != 1) { + return AgentCallResult.failure("Agent not found or disabled: " + agentCode); + } + + // 2. ACP 调用 + AcpRequest request = AcpRequest.builder() + .endpoint(agent.getAcpEndpoint()) + .targetAid(agent.getAgentAid()) + .authMode(agent.getAuthMode()) + .authConfig(agent.getAuthConfig()) + .payload(payload) + .metadata(context) + .timeoutSeconds(timeoutOverride != null ? timeoutOverride : agent.getTimeoutSeconds()) + .build(); + + AcpResponse response = acpClient.call(request); + + // 3. 封装结果 + return AgentCallResult.of(response); + } +} +``` + +#### AgentRequestAction(规则引擎 SPI 节点) + +```java +@Component +public class AgentRequestAction implements ActionProvider { + + private final IotAgentCallService agentCallService; + + @Override + public String getType() { return "agent_request"; } + + @Override + public ActionResult execute(RuleContext ctx, JsonNode config) { + // 1. 解析配置 + String agentCode = config.get("agentCode").asText(); + JsonNode payload = resolvePayload(config.get("payload"), ctx); + Integer timeout = config.has("timeoutSeconds") + ? config.get("timeoutSeconds").asInt() : null; + + // 2. 构建调用上下文 + Map context = Map.of( + "source", "iot-rule-engine", + "deviceId", String.valueOf(ctx.getDeviceId()), + "productId", String.valueOf(ctx.getProductId()), + "subsystemId", String.valueOf(ctx.getSubsystemId()), + "ruleChainId", String.valueOf(ctx.getRuleChainId()) + ); + + // 3. 调用 + AgentCallResult result = agentCallService.call(agentCode, payload, context, timeout); + + // 4. 结果注入 + if (result.isSuccess()) { + String outputTo = config.path("outputTo").asText("metadata.agentResult"); + injectResult(ctx, outputTo, result.getData()); + return ActionResult.success(); + } + return ActionResult.failure(result.getErrorMessage()); + } +} +``` + +### 12.6 模板变量解析 + +规则引擎统一提供模板解析能力(Agent 节点与脚本节点共用),借鉴 TB 的 `TbNodeUtils.processPattern()`: + +| 模板语法 | 含义 | 示例 | +|---------|------|------| +| `$[identifier]` | 消息数据字段 | `$[temperature]` → 设备上报的温度值 | +| `$[*]` | 整个消息体 JSON | 传递全部上报数据 | +| `${key}` | 元数据字段 | `${deviceName}` → 设备名称 | + +### 12.7 节点配置格式 + +```json +{ + "type": "agent_request", + "config": { + "agentCode": "anomaly-detector", + "payload": { + "taskType": "anomaly_detection", + "deviceName": "${deviceName}", + "subsystem": "${subsystemCode}", + "data": { + "temperature": "$[temperature]", + "humidity": "$[humidity]" + }, + "context": { + "recentAvgTemp": "${avgTemp}", + "deviceModel": "${productName}" + } + }, + "timeoutSeconds": 60, + "outputTo": "metadata.agentResult" + } +} +``` + +### 12.8 Agent 结果在规则链中的使用 + +Agent 返回的结果注入 `metadata.agentResult` 后,后续节点可直接引用: + +``` +设备上报 → [Enrich: 读取近1小时均值] + → [AgentRequest: anomaly-detector] + → [Expression: metadata.agentResult.level == 'critical'] + ├── true → [AlarmTrigger: 严重告警] + └── false → [Expression: metadata.agentResult.level == 'warning'] + ├── true → [Notify: 发送预警通知] + └── false → 结束 +``` + +### 12.9 典型业务场景 + +| 场景 | Agent | 触发方式 | Agent 输入 | Agent 输出 | 后续动作 | +| ------ | ---------------------- | ------- | --------- | ----------------- | --------- | +| 设备异常检测 | anomaly-detector | 属性上报 | 温湿度+历史均值 | level + reason | 告警/通知 | +| 保洁质量验收 | clean-quality-checker | 保洁完成事件 | 区域图片+清洁标准 | pass/fail + score | 标记完成/派返工单 | +| 能耗优化 | energy-advisor | 定时(每小时) | 用电数据+设备列表 | 调度建议 | 设备控制指令 | +| 预测性维护 | predictive-maintenance | 定时(每天) | 30 天运行参数 | 剩余寿命+劣化趋势 | 提前告警 | + +### 12.10 与 TB AI Node 的差异 + +| 维度 | TB 4.2 AI Node | 我们的 Agent 节点 | +|------|---------------|-----------------| +| 对接对象 | LLM API(OpenAI 等 9 个 Provider) | 内部 Agent 服务(数字员工) | +| 协议 | 各厂商私有 HTTP API | ACP 统一协议 | +| 抽象层 | LangChain4j SDK | AcpClient(IoT 内置) | +| 管理对象 | AI Model(endpoint + apiKey) | Agent Service(ACP 地址 + 能力声明) | +| Prompt 管理 | 节点配置中写 SystemPrompt/UserPrompt | 由 Agent 内部管理,规则引擎只传业务 Payload | + +### 12.11 后续演进路径 + +``` +阶段 1(本次) 阶段 2(其他模块需要时) +┌─────────────────────┐ ┌──────────────────────────────┐ +│ iot-biz/agent/ │ │ viewsh-module-ai(独立模块) │ +│ ├── dal/ │ 迁移 │ ├── ai-api/(Feign 接口) │ +│ ├── service/ │ ─────→ │ ├── ai-biz/(实现) │ +│ ├── client/ │ │ │ ├── Agent 注册表 │ +│ └── controller/ │ │ │ ├── AcpClient │ +│ │ │ │ └── 调用日志审计 │ +│ iot_agent_service 表│ 改前缀 │ └── ai_agent_service 表 │ +└─────────────────────┘ └──────────────────────────────┘ + ↑ Feign 调用 + ┌─────┼─────────┐ + IoT Ops 其他模块 +``` + +**迁移原则**:接口不变,只改调用方式。`IotAgentCallService` 的方法签名保持一致,IoT 侧改为通过 Feign 代理调用即可。 diff --git a/开发者文档/03-IoT领域/升级设计方案/05-告警体系设计.md b/开发者文档/03-IoT领域/升级设计方案/05-告警体系设计.md index b9d3c18..63cb7e7 100644 --- a/开发者文档/03-IoT领域/升级设计方案/05-告警体系设计.md +++ b/开发者文档/03-IoT领域/升级设计方案/05-告警体系设计.md @@ -6,6 +6,8 @@ ## 一、告警状态机(5 状态) +![[diagram-alarm-state-machine.png]] + ``` ┌──── 持续触发 ────┐ ↓ │ @@ -72,7 +74,7 @@ CREATE TABLE iot_alarm_record ( **幂等策略**(工程评审决议):保持 BIGINT 自增 ID(与全局一致),通过 `record_key = MD5(deviceId + "-" + alarmConfigId)` 唯一索引实现幂等。写入时使用 `INSERT ... ON DUPLICATE KEY UPDATE`。 -### 2.2 AlarmHistory(TDengine,时序归档) +### 2.2 AlarmHistory(时序库,CTSDB/TDengine) 每次告警状态变化都追加一条记录,用于趋势分析和审计。 diff --git a/开发者文档/03-IoT领域/升级设计方案/06-设备影子与RPC.md b/开发者文档/03-IoT领域/升级设计方案/06-设备影子与RPC.md index 6b8a3c3..7b94bac 100644 --- a/开发者文档/03-IoT领域/升级设计方案/06-设备影子与RPC.md +++ b/开发者文档/03-IoT领域/升级设计方案/06-设备影子与RPC.md @@ -12,6 +12,10 @@ --- +![[diagram-rpc-state-machine.png]] + +--- + ## 二、Shared 属性同步机制 ### 2.1 流程 diff --git a/开发者文档/03-IoT领域/升级设计方案/07-数据存储方案.md b/开发者文档/03-IoT领域/升级设计方案/07-数据存储方案.md index 5713d66..449f1e7 100644 --- a/开发者文档/03-IoT领域/升级设计方案/07-数据存储方案.md +++ b/开发者文档/03-IoT领域/升级设计方案/07-数据存储方案.md @@ -1,187 +1,199 @@ # 07-数据存储方案 -> 存储策略插件化 + 写入缓冲 + TDengine 优化 +> 基于 aiot-iot-data-storage 已有实现演进:时序数据库可切换(CTSDB/TDengine) + 写入缓冲 + 缓存优化 --- -## 一、存储策略插件化(借鉴 JetLinks) +## 一、时序数据库现状 -### 1.1 设计动机 +![[diagram-tsdb-architecture.png]] -现有系统所有产品设备数据统一存 TDengine,无法针对不同场景选择最优存储。引入策略模式,支持产品级配置。 +![[diagram-write-buffer.png]] -### 1.2 策略接口 +### 1.1 已有双实现(aiot-iot-data-storage) + +`aiot-iot-data-storage` 项目已实现 **CTSDB 和 TDengine 双后端**,通过配置切换: + +```yaml +viewsh.iot.tsdb.type: ctsdb # 或 "tdengine" +``` + +``` +TsDbAutoConfiguration(策略选择器) + ├── tsdb.type = ctsdb → CTSDB DAO 实现(InfluxDB 协议) + └── tsdb.type = tdengine → TDengine DAO 实现(JDBC) +``` + +### 1.2 核心 DAO 接口(已定义) ```java -interface ThingsDataStorageStrategy { - String getId(); // "tdengine-column" / "tdengine-row" - int getOrder(); // 优先级 - - void saveProperties(Long deviceId, Map properties, LocalDateTime reportTime); - List queryHistory(Long deviceId, String identifier, TimeRange range, int limit); - Map getLatest(Long deviceId); - void defineTable(Long productId, List thingModels); - void alterTable(Long productId, List oldModels, List newModels); +// 设备属性时序存储 +interface IotTsDbDevicePropertyDao { + List getTableFields(Long productId); + void createPropertyTable(Long productId, List fields); + void alterPropertyTable(Long productId, List oldFields, List newFields); + void insert(IotDeviceDO device, Map properties, Long reportTime); + List> selectHistory(IotDevicePropertyHistoryReqVO reqVO, Long productId); +} + +// 设备消息日志存储 +interface IotTsDbDeviceMessageDao { + void createSchema(); + boolean schemaExists(); + void insert(IotDeviceMessageDO message); + PageResult selectPage(PageParam page, IotDeviceMessagePageReqVO reqVO); + Long selectCountByCreateTime(LocalDateTime createTime); + List selectListByRequestIdsAndReply(Long deviceId, List requestIds, Boolean reply); + List selectDeviceMessageCountGroupByDate(LocalDateTime startTime, LocalDateTime endTime); } ``` -### 1.3 内置策略 +### 1.3 CTSDB 实现(基于 InfluxDB 协议) -| 策略 ID | 说明 | 适用场景 | -| ----------------- | --------------- | -------------- | -| `tdengine-column` | 列模式(现有方案),每属性一列 | 属性固定、查询频繁 | -| `tdengine-row` | 行模式,每属性一行 | 属性动态变化、物模型频繁变更 | +| 维度 | 说明 | +|------|------| +| SDK | `influxdb-client-java` | +| 协议 | HTTP REST API(`http://host:8086`) | +| 认证 | Token 方式 | +| 查询语言 | Flux | +| 建表 | Schema-on-write(自动,无需预建) | +| 写入 | 异步批量:1000 条/批 + 1s 自动刷新 + 3 次重试 | +| 防注入 | `FluxQuerySanitizer` 转义特殊字符 | +| 多租户 | Flux 查询中 `tenant_id` 字段过滤 | -### 1.4 列模式 vs 行模式 - -**列模式(现有,保留为默认)**: -```sql -CREATE STABLE product_property_{productId} ( - ts TIMESTAMP, report_time TIMESTAMP, - temperature INT, humidity FLOAT, status TINYINT -- 每属性一列 -) TAGS (device_id BIGINT); -``` -- 优点:查询快,单行包含所有属性 -- 缺点:物模型变更需 ALTER TABLE,TDengine 不支持缩短字段 - -**行模式(新增)**: -```sql -CREATE STABLE product_property_row_{productId} ( - ts TIMESTAMP, report_time TIMESTAMP, - identifier NCHAR(64), -- 属性标识符 - value_int INT, -- 整型值 - value_float FLOAT, -- 浮点值 - value_double DOUBLE, -- 双精度值 - value_bool TINYINT, -- 布尔值 - value_str NCHAR(1024), -- 字符串值 - scope TINYINT -- 属性域(1=CLIENT, 2=SERVER, 3=SHARED) -) TAGS (device_id BIGINT); -``` -- 优点:物模型变更无需 DDL,属性可任意扩展 -- 缺点:查询需按 identifier 过滤,同时查多属性需 PIVOT - -### 1.5 产品级配置 - -```sql -ALTER TABLE iot_product ADD COLUMN store_policy VARCHAR(32) DEFAULT 'tdengine-column'; +```yaml +# CTSDB 连接配置 +viewsh.iot.tsdb.ctsdb: + url: http://${CTSDB_HOST:localhost}:${CTSDB_PORT:8086} + token: ${CTSDB_TOKEN:} + org: ${CTSDB_ORG:aiot} + bucket: ${CTSDB_BUCKET:aiot_platform} ``` -`ThingsDataStorageRouter` 按 productId 路由到对应策略: -```java -ThingsDataStorageStrategy getStrategy(Long productId) { - String policy = productService.getProduct(productId).getStorePolicy(); - return strategyMap.get(policy); // 策略注册表 -} +### 1.4 TDengine 实现 + +| 维度 | 说明 | +|------|------| +| SDK | `taos-jdbcdriver` 3.7.9 | +| 协议 | JDBC(WebSocket / REST) | +| 认证 | 用户名密码 | +| 查询语言 | TDengine SQL | +| 建表 | 需要预建超级表(CREATE STABLE) | +| 写入 | 同步写入(通过 Mapper XML) | +| 多租户 | `@InterceptorIgnore` 绕过 JSqlParser | + +### 1.5 数据模型(两套实现共用) + ``` +measurement/超级表: device_message +├── TAG: device_id +└── FIELDS: id, report_time, tenant_id, server_id, upstream, + reply, identifier, request_id, method, params, data, code, msg + +measurement/超级表: product_property_{productId} +├── TAG: device_id +└── FIELDS: report_time + 动态属性列(从物模型生成) +``` + +### 1.6 物模型类型映射 + +| 物模型类型 | CTSDB (InfluxDB) | TDengine | +|---------|-----------------|----------| +| INT | INT | INT | +| FLOAT | FLOAT | FLOAT | +| DOUBLE | DOUBLE | DOUBLE | +| ENUM | TINYINT | TINYINT | +| BOOL | BOOL | TINYINT | +| TEXT | STRING | VARCHAR(1024) | +| DATE | TIMESTAMP | TIMESTAMP | +| STRUCT | STRING (JSON) | VARCHAR(1024) | +| ARRAY | STRING (JSON) | VARCHAR(1024) | --- -## 二、写入缓冲(借鉴 JetLinks PersistenceBuffer) +## 二、v2.0 存储扩展 -### 2.1 设计动机 +### 2.1 新增时序表 -设备高频上报时(如 1Hz × 1000 台),每条消息直接写 TDengine 会产生大量小批次 INSERT。引入写入缓冲,批量合并后写入。 +在现有 `device_message` 和 `product_property_*` 基础上,v2.0 需新增两张时序表,同样遵循 DAO 接口双实现模式: -### 2.2 PersistenceBuffer 设计 +| 时序表 | 用途 | TAG | 关键字段 | +|--------|------|-----|---------| +| `alarm_history` | 告警状态变化归档 | device_id | alarm_record_id, severity, state, trigger_data | +| `rule_debug_log` | 规则调试日志 | device_id | rule_chain_id, node_id, input_data, output_data, duration_ms | + +需新增对应 DAO 接口: + +```java +// 告警历史时序存储 +interface IotTsDbAlarmHistoryDao { + void insert(AlarmHistoryDO history); + List selectByRecordId(Long alarmRecordId, TimeRange range); + List selectByDeviceId(Long deviceId, TimeRange range); +} + +// 规则调试日志时序存储 +interface IotTsDbRuleDebugLogDao { + void insert(RuleDebugLogDO log); + List selectByChainId(Long ruleChainId, TimeRange range); +} +``` + +### 2.2 写入缓冲 + +CTSDB 侧已有 InfluxDB WriteApi 的异步批量写入(1000 条/批 + 1s 刷新),TDengine 侧需补齐 PersistenceBuffer: ```java class PersistenceBuffer { - // 配置 - int bufferSize = 200; // 数量触发阈值 - Duration bufferTimeout = Duration.ofSeconds(3); // 时间触发阈值 - int parallelism = 4; // 并行写出线程数 + int bufferSize; // 数量触发阈值 + Duration bufferTimeout; // 时间触发阈值 + int parallelism; // 并行写出线程数 + BlockingQueue queue; // 内存队列 + ScheduledExecutorService timer;// 定时刷新 - // 内部结构 - BlockingQueue queue; // 内存队列 - ScheduledExecutorService timer; // 定时刷新 - - // 写入方法 void write(T item) { queue.add(item); - if (queue.size() >= bufferSize) { - flush(); - } + if (queue.size() >= bufferSize) { flush(); } } - // 批量刷出 void flush() { List batch = new ArrayList<>(); queue.drainTo(batch, bufferSize); - if (!batch.isEmpty()) { - batchWriter.accept(batch); // 回调:批量写入 TDengine - } + if (!batch.isEmpty()) { batchWriter.accept(batch); } } } ``` -### 2.3 应用点 +| 缓冲实例 | 写入目标 | bufferSize | timeout | 备注 | +|---------|---------|-----------|---------|------| +| 属性写入缓冲 | `product_property_*` | 200 | 3s | CTSDB 已内置批量,TDengine 需要 | +| 消息日志缓冲 | `device_message` | 500 | 5s | 同上 | +| 告警历史缓冲 | `alarm_history` | 100 | 3s | 新增 | +| 规则调试日志缓冲 | `rule_debug_log` | 100 | 5s | 新增 | -| 缓冲实例 | 写入目标 | bufferSize | timeout | -|---------|---------|-----------|---------| -| 属性写入缓冲 | TDengine `product_property_*` | 200 | 3s | -| 消息日志缓冲 | TDengine `device_message` | 500 | 5s | -| 告警历史缓冲 | TDengine `alarm_history` | 100 | 3s | -| 规则调试日志缓冲 | TDengine `rule_debug_log` | 100 | 5s | +### 2.3 数据保留策略 + +| 时序表 | 建议保留期 | CTSDB 实现 | TDengine 实现 | +|--------|----------|-----------|--------------| +| `device_message` | 90 天 | Bucket Retention Policy | `KEEP 90d` | +| `product_property_*` | 365 天 | Bucket Retention Policy | `KEEP 365d` | +| `alarm_history` | 365 天 | Bucket Retention Policy | `KEEP 365d` | +| `rule_debug_log` | 7 天 | Bucket Retention Policy | `KEEP 7d` | + +### 2.4 属性作用域扩展 + +v2.0 引入属性三元分类(CLIENT/SERVER/SHARED),时序数据需新增 `scope` 维度: + +- **CTSDB**:写入时增加 `scope` 字段(INT,作为 FIELD),查询时按 scope 过滤 +- **TDengine**:超级表增加 `scope TINYINT` 列 + +两套 DAO 实现的 `insert()` 方法均需接收 `AttributeScope` 参数。 --- -## 三、TDengine 优化 +## 三、Redis 缓存优化 -### 3.1 消息超级表优化 - -现有 `device_message` 表的 `params` 和 `data` 字段为 `NCHAR(2048)`,大消息会截断。 - -优化方案: -```sql --- 增大到 4096,覆盖绝大多数场景 -ALTER STABLE device_message MODIFY COLUMN params NCHAR(4096); -ALTER STABLE device_message MODIFY COLUMN data NCHAR(4096); -``` - -### 3.2 新增超级表 - -```sql --- 告警历史(两级告警的时序部分) -CREATE STABLE IF NOT EXISTS alarm_history ( - ts TIMESTAMP, - alarm_record_id NCHAR(64), - alarm_config_id BIGINT, - severity TINYINT, - state NCHAR(16), - trigger_data NCHAR(4096), - details NCHAR(2048), - operator NCHAR(64), - remark NCHAR(256) -) TAGS (device_id BIGINT); - --- 规则调试日志 -CREATE STABLE IF NOT EXISTS rule_debug_log ( - ts TIMESTAMP, - rule_chain_id BIGINT, - node_id BIGINT, - node_type NCHAR(64), - input_data NCHAR(4096), - output_data NCHAR(4096), - duration_ms INT, - success BOOL, - error_msg NCHAR(512) -) TAGS (device_id BIGINT); -``` - -### 3.3 数据保留策略 - -| 超级表 | 建议保留期 | 配置方式 | -|--------|----------|---------| -| `device_message` | 90 天 | TDengine `KEEP 90d` | -| `product_property_*` | 365 天 | TDengine `KEEP 365d` | -| `alarm_history` | 365 天 | TDengine `KEEP 365d` | -| `rule_debug_log` | 7 天 | TDengine `KEEP 7d` | - ---- - -## 四、Redis 缓存优化 - -### 4.1 修复生产隐患 +### 3.1 修复生产隐患 | 问题 | 现状 | 修复 | |------|------|------| @@ -189,7 +201,7 @@ CREATE STABLE IF NOT EXISTS rule_debug_log ( | 部分缓存无 TTL | `iot:device_property:*`、`iot:device_server_id` 常驻 | 设备删除时主动清理 | | 告警缓存竞态 | 无并发保护 | 分布式锁 + RecordCache | -### 4.2 新增 Redis Key +### 3.2 新增 Redis Key | Key | 类型 | 用途 | TTL | |-----|------|------|-----| @@ -201,9 +213,9 @@ CREATE STABLE IF NOT EXISTS rule_debug_log ( --- -## 五、可观测性埋点(Micrometer) +## 四、可观测性埋点(Micrometer) -### 5.1 核心指标 +### 4.1 核心指标 | 指标名 | 类型 | 标签 | 说明 | |--------|------|------|------| @@ -217,19 +229,17 @@ CREATE STABLE IF NOT EXISTS rule_debug_log ( | `iot.buffer.size` | Gauge | bufferName | 缓冲区当前大小 | | `iot.rpc.status` | Counter | status | RPC 状态分布 | -### 5.2 集成方式 +### 4.2 集成方式 ```java @Component class IotMetrics { private final MeterRegistry registry; - // 设备上线 void recordDeviceOnline(String protocol) { Metrics.gauge("iot.device.online", Tags.of("protocol", protocol), onlineCount); } - // 规则执行耗时 void recordRuleExecution(Long chainId, String nodeType, Duration duration) { Timer.builder("iot.rule.execution") .tag("ruleChainId", String.valueOf(chainId)) diff --git a/开发者文档/03-IoT领域/升级设计方案/08-协议与编解码扩展.md b/开发者文档/03-IoT领域/升级设计方案/08-协议与编解码扩展.md index 8fb214c..3465782 100644 --- a/开发者文档/03-IoT领域/升级设计方案/08-协议与编解码扩展.md +++ b/开发者文档/03-IoT领域/升级设计方案/08-协议与编解码扩展.md @@ -10,6 +10,10 @@ --- +![[diagram-protocol-hotload.png]] + +--- + ## 二、Codec SPI 增强 ### 2.1 现有接口保留 diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-alarm-state-machine.png b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-alarm-state-machine.png new file mode 100644 index 0000000..bac3ead Binary files /dev/null and b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-alarm-state-machine.png differ diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-alarm-state-machine.svg b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-alarm-state-machine.svg new file mode 100644 index 0000000..6aca280 --- /dev/null +++ b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-alarm-state-machine.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 告警状态机 Alarm State Machine + 05-告警体系设计 | 5 状态 + 竞态保护 + 层级传播 + + 告警触发 + + ACTIVE + 活跃 + + ACKNOWLEDGED + 已确认 + + CLEARED + 已清除 + + RESOLVED + 已解决 + + + 归档 + + + trigger + + + 用户确认 + + + 条件恢复 + + + 条件恢复 + + + 手动解决 + + + 手动解决 + + + 重复触发 + (计数+1) + 告警级别 + + CRITICAL + + MAJOR + + MINOR + + WARNING + + INFO + + 竞态保护机制 + Redis 缓存 + 分布式锁 (Redisson) + AlarmRecord record_key UK 幂等 + + MySQL AlarmRecord (当前状态 Upsert) + record_key = MD5(deviceId + alarmConfigId) + + TimeSeries AlarmHistory (审计轨迹 Append) + 每次状态变更追加记录 (ts, state, trigger_data) + \ No newline at end of file diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-attribute-classification.png b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-attribute-classification.png new file mode 100644 index 0000000..87b825f Binary files /dev/null and b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-attribute-classification.png differ diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-attribute-classification.svg b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-attribute-classification.svg new file mode 100644 index 0000000..f75ff7a --- /dev/null +++ b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-attribute-classification.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 属性三元分类数据流向 + 03-物模型规范 / 06-设备影子 | CLIENT / SERVER / SHARED 读写流向 + + IoT 设备 + 传感器数据上报 + 状态属性汇报 + 接收配置下发 + 执行 RPC 指令 + + IoT 平台 + 规则引擎计算 + 管理后台 UI + REST API + Agent 服务 + + CLIENT 属性 + 设备写入 | 平台只读 | Redis iot:device_property:{id}:client + + + 写入 + + + 读取 + + SERVER 属性 + 平台写入 | 平台只读 | Redis iot:device_property:{id}:server + + + 写入 + + SHARED 属性 + 平台写入 | 设备+平台读取 | Redis + MySQL 双写 + + + 写入 + + + 配置下发 + + 存储策略 + CLIENT/SERVER: 仅 Redis | SHARED: Redis + MySQL 双写 (持久化) + \ No newline at end of file diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-protocol-hotload.png b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-protocol-hotload.png new file mode 100644 index 0000000..89f81d4 Binary files /dev/null and b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-protocol-hotload.png differ diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-protocol-hotload.svg b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-protocol-hotload.svg new file mode 100644 index 0000000..93fa581 --- /dev/null +++ b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-protocol-hotload.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 协议包热加载流程 + 08-协议与编解码扩展 | JAR 上传 → ClassLoader → SPI 注册 + + 上传协议包 JAR + + 校验 JAR 完整性 + 签名验证 + META-INF 检查 + + 创建隔离 ClassLoader + 独立类加载器避免冲突 + + ServiceLoader 发现 Codec + 扫描 META-INF/services + + 注册到 CodecRegistry + codecId -> Codec 实例映射 + + + + + + 卸载协议包 + 关闭 ClassLoader + 移除注册 + + + 内置 Codec (Spring Bean) + ALink Codec + JT808 Codec + Camera3D11 Codec + Transparent Codec + + + 共存注册 + \ No newline at end of file diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-rpc-state-machine.png b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-rpc-state-machine.png new file mode 100644 index 0000000..fafe667 Binary files /dev/null and b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-rpc-state-machine.png differ diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-rpc-state-machine.svg b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-rpc-state-machine.svg new file mode 100644 index 0000000..3f41978 --- /dev/null +++ b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-rpc-state-machine.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RPC 状态机 (持久化指令投递) + 06-设备影子与RPC | 离线排队 + 上线补发 + 超时重试 + + 创建指令 + + QUEUED + 排队中 + + SENT + 已发送 + + DELIVERED + 已送达 + + SUCCESS + 成功 + + FAILURE + 失败 + + TIMEOUT + 超时 + + EXPIRED + 已过期 + + + + 设备在线 + + + 设备确认 + + + 执行成功 + + + 执行失败 + + + 响应超时 + + + 重试 (3次) + + + 超过上限 + + 上线补发机制 + 设备上线 -> 拉取 QUEUED -> 限速 5msg/s + 防止设备上线瞬间过载 + + 持久化保证 + 所有状态变更持久化到 iot_device_rpc + 支持审计追踪与断点续传 + + 过期策略 + expireTime 到达 -> 标记 EXPIRED + 过期指令不再下发设备 + \ No newline at end of file diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-rule-action-tree.png b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-rule-action-tree.png new file mode 100644 index 0000000..3d75e89 Binary files /dev/null and b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-rule-action-tree.png differ diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-rule-action-tree.svg b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-rule-action-tree.svg new file mode 100644 index 0000000..817560c --- /dev/null +++ b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-rule-action-tree.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 规则引擎动作分类 + 04-规则引擎方案 | 7 大类动作节点 + SPI 扩展 + + Actions 动作层 + SPI Provider 注册 + + 设备控制 + device_property_set + device_service_invoke + + + 告警处理 + alarm_trigger + alarm_clear + + + 消息通知 + notify (多通道) + + + 数据转发 + http_push + mq_push + redis_push + tcp_push + + + 数据处理 + script (Aviator) + enrich / delay / log + + + Agent 协作 (预留) + agent_request (ACP) + + \ No newline at end of file diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-subsystem-er.png b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-subsystem-er.png new file mode 100644 index 0000000..811f68c Binary files /dev/null and b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-subsystem-er.png differ diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-subsystem-er.svg b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-subsystem-er.svg new file mode 100644 index 0000000..1789168 --- /dev/null +++ b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-subsystem-er.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 子系统与设备归属 ER 关系图 + 02-子系统与设备归属模型 | 租户 → 项目 → 子系统 → 设备 + + + + iot_tenant + id BIGINT PK + name VARCHAR + status TINYINT + ... + + + + iot_project + id BIGINT PK + tenant_id BIGINT FK + name VARCHAR + code VARCHAR UK + status TINYINT + + + + iot_subsystem + id BIGINT PK + project_id BIGINT FK + tenant_id BIGINT FK + name VARCHAR + code VARCHAR UK NOT NULL + type TINYINT + status TINYINT + + + + iot_device + id BIGINT PK + product_id BIGINT FK + subsystem_id BIGINT FK + tenant_id BIGINT FK + device_key VARCHAR UK + device_name VARCHAR + status TINYINT + last_online_time DATETIME + + + + iot_product + id BIGINT PK + tenant_id BIGINT FK + product_key VARCHAR UK + name VARCHAR + protocol_type TINYINT + status TINYINT + + 1 : N + + 1 : N + + 1 : N + + 1 : N + + 设备通过 subsystem_id FK 归属子系统 | 子系统决定规则链匹配、告警传播、用户权限范围 | iot_project 本次架构预留 + \ No newline at end of file diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-tsdb-architecture.png b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-tsdb-architecture.png new file mode 100644 index 0000000..16ec410 Binary files /dev/null and b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-tsdb-architecture.png differ diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-tsdb-architecture.svg b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-tsdb-architecture.svg new file mode 100644 index 0000000..7cbf8e6 --- /dev/null +++ b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-tsdb-architecture.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 时序库双实现架构 + 07-数据存储方案 | CTSDB / TDengine 可切换 + DAO 接口统一 + + IotTimeSeriesDAO (统一接口) + saveDeviceMessage / queryHistory / createSchema + + + + CTSDB (InfluxDB 兼容) + + IotCtsdbTimeSeriesDAOImpl + 特点 + 异步批量写入 (1000条/批 + 1s 自动刷新) + HTTP REST API 交互 + 自动 schema 创建 (基于物模型) + 保留策略: 90天自动过期 + spring.profiles: ctsdb + + TDengine (JDBC) + + IotTdEngineTimeSeriesDAOImpl + 特点 + 同步 JDBC 写入 + PersistenceBuffer + 超级表 (STable) 自动建表 + 子表按设备自动创建 + 保留策略: DURATION + KEEP 配置 + spring.profiles: tdengine + 存储表结构 + + device_message + 设备上行消息 + + product_property_{id} + 产品属性时序 + + alarm_history + 告警状态变更 + + rule_debug_log + 规则调试日志 + \ No newline at end of file diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-write-buffer.png b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-write-buffer.png new file mode 100644 index 0000000..2d98230 Binary files /dev/null and b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-write-buffer.png differ diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/diagram-write-buffer.svg b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-write-buffer.svg new file mode 100644 index 0000000..b83ffdd --- /dev/null +++ b/开发者文档/03-IoT领域/升级设计方案/assets/diagram-write-buffer.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 写入缓冲管道 PersistenceBuffer + 07-数据存储方案 | 内存队列 + 文件持久化 + 批量写入时序库 + + 设备消息 + IotDeviceMessage + + + 内存队列 L1 + ConcurrentLinkedQueue + 最大 1000 条 / 1s 自动刷新 + + + 批量刷新 + + 批量写入器 + BatchInsert 1000条/批 + 异步/同步 (按实现) + + + + + + + TimeSeries DB + + + 文件持久化 L2 + 内存溢出 / 进程崩溃时写磁盘 + 重启后自动重放 + + + 重启重放 + + 溢出降级 + \ No newline at end of file diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/iot-e2e-business-flow.png b/开发者文档/03-IoT领域/升级设计方案/assets/iot-e2e-business-flow.png new file mode 100644 index 0000000..498933e Binary files /dev/null and b/开发者文档/03-IoT领域/升级设计方案/assets/iot-e2e-business-flow.png differ diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/iot-e2e-business-flow.svg b/开发者文档/03-IoT领域/升级设计方案/assets/iot-e2e-business-flow.svg new file mode 100644 index 0000000..df7983d --- /dev/null +++ b/开发者文档/03-IoT领域/升级设计方案/assets/iot-e2e-business-flow.svg @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IoT 平台端到端业务链路 + v2.0 架构 | 设备 → 网关 → 总线 → 核心处理 → 规则引擎 → 动作执行 → 存储 + + 物理设备层 DEVICE LAYER + + + + 温湿度传感器 + + + + 3D 摄像头 + + + + 智能控制器 + + + + GPS 定位器 + + + + Modbus 设备 + + + + 自定义设备 + + + + + + + + 设备接入层 DEVICE GATEWAY & CODEC + + MQTT Broker + MQTT 3.1 / 5.0 + + HTTP 网关 + REST / CoAP + + TCP 网关 + 自定义协议 + + EMQX 桥接 + 集群桥接 + + 协议解码 Codec SPI + ALink | JT808 | Camera3D + 热加载 JAR 扩展 + + + + + + + + IotDeviceMessage 统一消息模型 + + 消息总线 Message Bus + LocalMessageBus | RedisStreamMessageBus | RocketMQMessageBus + + + + + + + 核心处理层 IotDeviceMessageSubscriber + + 设备上下线 + Redis 状态标记 + + 属性三分类 + CLIENT|SERVER|SHARED + + 时序数据写入 + PersistenceBuffer + + 物模型合并 + 产品 + 设备扩展 + + 规则引擎触发 + 转发至规则链 + + + 写入 Redis + + + 写入 Redis + + + 写入 TSDB + + + 规则引擎层 RULE ENGINE — DAG 编排 + + 规则链匹配 + 子系统 + 产品 + 设备 + + 全局规则合并 + + 触发节点 + 设备状态 / 属性 + 事件 / 定时 / 手动 + + 数据丰富 + 读取历史均值 + 关联设备信息 + + 条件判断 + 表达式 / 脚本 + 时间范围 / 状态 + + 抖动过滤 + 窗口期 N 秒 + 触发 M 次通过 + + 分支执行 + 条件分流 + 并行动作链 + + + + + + 动作执行 ACTION NODES + + 告警触发 + alarm_trigger + + 告警清除 + alarm_clear + + 消息通知 + 短信/邮件/钉钉 + + 设备控制 + RPC / 属性下发 + + 数据转发 + HTTP/MQ/Redis/TCP + + 脚本处理 + Aviator 沙箱 + + Agent 协作 + ACP 智能体 + + + + + + + + + + + 告警状态机 ALARM STATE MACHINE + + 活跃 ACTIVE + + 已确认 ACK + + 已清除 + + 已解决 + + + + 双层存储: + + MySQL AlarmRecord 当前状态 (Upsert) + + TimeSeries AlarmHistory 审计轨迹 (Append) + + + + 通知体系 NOTIFICATION + + 短信 SMS + + 邮件 Email + + 钉钉机器人 + + 企业微信 + + 站内消息 + + 模板变量 + + + 设备控制 RPC 状态机 + + 排队 + + 已发送 + + 成功 + + + 离线排队 → 上线重发 (5msg/s) + 超时重试 (3次) → 过期清理 + Shared 属性同步 + 持久化 RPC + + + 组织架构 ORGANIZATION HIERARCHY + + 租户 Tenant + + 项目 Project + + 子系统 + + 设备 Device + + + + + 应用层 APPLICATION LAYER + + 管理后台 UI + + REST API + + WebSocket + + Feign 内部调用 + + 存储层 STORAGE LAYER + + + + + + MySQL + 设备 | 规则 | 告警 | RPC + 产品 | 子系统 | Agent + + + + + + TimeSeries DB + CTSDB / TDengine + 设备消息 | 告警历史 | 调试日志 + + + + + + Redis + CLIENT | SERVER | SHARED + 在线状态 | 规则缓存 | RPC 超时 + + 可观测性 Observability + Micrometer 指标采集 + 连接数 | 消息吞吐 | 规则执行耗时 + 告警延迟 | RPC 成功率 | 编解码错误 + + + 图例: + + 数据上行 + + 存储写入 + + 告警流 + + 控制/组织 + + 规则引擎 + + 异步/持久化 + + \ No newline at end of file diff --git a/开发者文档/03-IoT领域/升级设计方案/assets/端到端业务链路.drawio b/开发者文档/03-IoT领域/升级设计方案/assets/端到端业务链路.drawio new file mode 100644 index 0000000..f9fdfe2 --- /dev/null +++ b/开发者文档/03-IoT领域/升级设计方案/assets/端到端业务链路.drawio @@ -0,0 +1,481 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +