# 平台对接设计文档 本文档按当前项目代码反补,描述已落地的平台对接模块。相关实现主要位于: - `fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/platform` - `fastbee-open-api/src/main/java/com/fastbee/controller/platform` - `yack-web/src/views/platform` - `sql/platform-integration.sql` - `sql/platform-dcp-init-data.sql` ## 1. 背景与目标 FastBee 需要将设备上报数据推送到第三方监测平台,当前已落地 DCP 结构监测 SaaS。模块目标是把“平台、接口、流程、设备绑定、字段映射、推送日志”配置化,降低后续接入新平台或调整 DCP 接口的代码改动。 当前实现采用两条主链路: 1. 流程执行链路:用于平台初始化、Token 刷新、设备入网等多步骤调用。 2. 实时推送链路:设备上报后异步命中平台设备绑定,由 DCP 适配器组装请求体并推送。 设计边界: - 流程编排只负责顺序 HTTP 调用、上下文传递、结果持久化。 - 实时数据推送不走流程引擎,按设备绑定上的 `push_interface_id`、`field_mapping`、`extra_mapping` 直接组装请求。 - 当前只有 DCP 适配器实现,平台路由按 `platform_instance.code` 分发,`code=dcp` 时进入 `DcpPlatformAdapter`。 - 网关多子设备场景通过独立子表 `platform_device_sub_mapping` 管理,不再只依赖 `extra_mapping`。 --- ## 2. 三种执行模式 ### 2.1 流程编排 适用于多个接口必须顺序调用,且后续步骤依赖前序步骤返回值的场景。 | 流程 | 触发方式 | 典型步骤 | 结果落库 | |---|---|---|---| | 平台初始化 | 平台管理页手动初始化,或手动执行流程 | `dcp_auth` -> `dcp_get_user` -> `dcp_get_projects` | `access_token`、`token_expires_at`、`extra_config.userId`、`extra_config.projectId`、`extra_config.projectName` | | Token 刷新 | HTTP 调用前自动触发,也可手动执行 | `dcp_auth` | `access_token`、`token_expires_at` | | 直连设备入网 | 设备绑定页点击入网 | `dcp_create_point` -> 对应传感器绑定接口 | 主表 `platform_point_id`、`platform_device_id`、`net_status` | | 网关设备入网 | 设备绑定页点击入网 | 对每个 monitor 子设备逐个执行入网流程 | 子表 `platform_point_id`、`platform_device_id`、`net_status`;全部 monitor 成功后主表 `net_status=1` | 入口代码: - `PlatformInstanceServiceImpl.initialize(Long id)` - `PlatformFlowServiceImpl.executeManually(Long id, Long mappingId)` - `PlatformDeviceMappingServiceImpl.onboard(Long mappingId)` - `PlatformFlowExecutor.execute(PlatformFlow flow, FlowContext context)` ### 2.2 直接调用实时推送 设备上报后由 `DeviceReportTrigger.onDeviceReport(serialNumber, payload)` 异步触发: 1. `PlatformDeviceMappingMapper.selectBySerialNumber` 同时匹配直连主设备和网关子设备。 2. 过滤未启用的平台和绑定关系。 3. 按平台 `code` 分发,目前 `dcp` 进入 `DcpPlatformAdapter`。 4. 适配器按推送接口的 `request_schema` 与设备绑定字段映射组装请求体。 5. 检查并刷新 Token。 6. 发送 HTTP POST,写入 `platform_push_log`。 实时推送不经过 `PlatformFlowExecutor`,因此不会使用流程步骤的 `param_mapping`、`result_key`、`result_save`。 ### 2.3 Token 自动刷新 流程执行器和 DCP 实时推送适配器各自调用 `ensureToken`: - `access_token` 为空,或 `token_expires_at` 距当前时间不足 5 分钟时视为过期。 - 自动查找同平台 `flow_type=3` 且 `enable='1'` 的 Token 刷新流程。 - 刷新流程本身不注入 Authorization,避免递归。 - 刷新成功后重新读取或更新 `platform_instance.access_token` 和 `token_expires_at`。 --- ## 3. 数据库设计(7 张表) DDL 以 `sql/platform-integration.sql` 为准。 ### 3.1 `platform_instance` 平台实体 保存第三方平台实例、认证配置和初始化结果。 关键字段: | 字段 | 说明 | |---|---| | `name` | 平台名称 | | `code` | 平台唯一标识,当前 DCP 为 `dcp`,有唯一索引 | | `base_url` | 平台基础 URL | | `auth_type` | 认证类型:`1=密码Token`、`2=ApiKey`、`3=OAuth2` | | `auth_config` | 认证配置 JSON,例如 `userName`、`password`、`clientId`、`scope` | | `extra_config` | 初始化后保存的业务上下文,例如 `userId`、`projectId`、`projectName` | | `access_token` | 当前 Token | | `token_expires_at` | Token 过期时间 | | `init_status` | 初始化状态 | | `enable` | 是否启用 | | `tenant_id` | 租户 ID | ### 3.2 `platform_interface` 接口定义 保存第三方 HTTP 接口定义。 关键字段: | 字段 | 说明 | |---|---| | `platform_id` | 所属平台 | | `name` / `code` | 接口名称与接口标识 | | `method` | `GET`、`POST`、`PUT`、`DELETE` | | `path` | 接口路径,支持 `{userId}` 形式路径变量 | | `content_type` | 默认 `application/json`,认证接口可用 `application/x-www-form-urlencoded` | | `request_schema` | 入参字段定义 | | `response_schema` | 出参字段定义,支持按路径抽取 | | `sort_order` | 排序 | `request_schema` 在流程执行器中支持的 `source`: | source | 含义 | |---|---| | `fixed` | 固定值,取 `value` | | `uuid` | 每次请求生成新的 UUID | | `auth` | 从 `platform_instance.auth_config` 按 `field` 取值 | | `extra` | 从 `platform_instance.extra_config` 按 `field` 取值 | | `context` | 从 `FlowContext` 按 `contextKey` 取值 | | `device` | 从 `PlatformDeviceMapping` / 当前网关子设备上下文取 `platform_device_id`、`platform_point_id`、`serial_number`、`device_name`、`gateway_serial_number`、`monitor_serial_number` | | `thingsModel` | 从流程上下文 payload 按物模型标识取值,通常用于手动流程或扩展流程 | | `ts` | 从流程上下文 payload 取时间戳 | | `onboard_config` | 入网参数,直接取接口 `request_schema` 或步骤覆盖配置中的 `value`,不再读取子映射表 `onboard_config` | | `subDeviceSensorIds` | 收集子设备 sensorId 列表 | | `referenceSubDeviceSensorIdPairs` | 收集 `[基准点sensorId, 监测点sensorId]` 配对列表,可能展开为多次请求 | `onboard_config` 是设备入网专用的可配置入参。接口管理页或流程步骤覆盖页直接维护 `value`: ```json {"name":"sensorDepths","type":"array","source":"onboard_config","value":[1.7,3.4,5.1,6.8]} {"name":"holeDepth","type":"number","source":"onboard_config","value":[1.7,3.4,5.1,6.8]} ``` 网关多 monitor 入网时,`PlatformDeviceMappingServiceImpl` 按 `PlatformDeviceSubMappingMapper.selectByParentId` 返回顺序筛选 monitor,并把当前下标写入 `FlowContext.currentMonitorIndex`。流程执行器解析 `onboard_config` 时: - `value` 不是数组:每个子设备使用同一个值。 - `value` 是数组:按当前 monitor 下标取对应元素。 - schema `type=array` 且取到单值:最终请求体会包装为单元素数组,例如 `1.7` -> `[1.7]`。 - 数组长度小于待入网 monitor 数量:直接抛错,避免错绑。 实时推送适配器中支持的 `source`: | source | 含义 | |---|---| | `fixed` | 固定值 | | `device` | 从绑定关系取平台设备/测点/序列号 | | `auth` | 从认证 JSON 取值 | | `extra` | 从扩展 JSON 取值 | | `thingsModel` / `identifier` | 按 `field_mapping` 或 `itemFieldMappings` 从上报 payload 取物模型值 | | `ts` | 从物模型值的 `__ts` 派生时间,缺省为当前时间 | | `context` | 优先从 payload 的 `contextKey` 取值;`reportTime`/`epoch` 会按时间字段处理 | | `subDeviceId` | 数组元素内的子设备平台 ID,如 DCP `sensorId` | `response_schema.path` 支持对象路径、数组下标路径,例如 `id`、`[0].id`、`$.data.id`。 ### 3.3 `platform_flow` 流程定义 关键字段: | 字段 | 说明 | |---|---| | `platform_id` | 所属平台 | | `name` / `code` | 流程名称与标识 | | `flow_type` | `1=平台初始化`、`2=设备入网`、`3=Token刷新` | | `sensor_type` | 入网流程适用传感器类型,如 `inclino`、`deep_inclino`、`stress`、`hyeto`、`static_level` | | `enable` | 是否启用 | ### 3.4 `platform_flow_step` 流程步骤 关键字段: | 字段 | 说明 | |---|---| | `flow_id` | 所属流程 | | `step_order` | 执行顺序 | | `interface_id` | 关联接口 | | `param_mapping` | 覆盖接口默认入参来源 | | `result_key` | 步骤结果写入上下文的 key | | `result_save` | 将响应字段持久化到平台或设备绑定 | `result_save` 支持: - `extra_config.xxx` - `platform_instance.access_token` - `platform_instance.token_expires_at`,值按 `expires_in` 秒数转换为 Date - `device_mapping.platform_device_id` - `device_mapping.platform_point_id` ### 3.5 `platform_device_mapping` 设备绑定主表 保存 FastBee 设备与第三方平台的绑定关系。 关键字段: | 字段 | 说明 | |---|---| | `platform_id` | 所属平台 | | `device_id` / `serial_number` | FastBee 设备 ID 与序列号 | | `platform_device_id` | 平台侧 deviceId,直连设备入网后回填 | | `platform_point_id` | 平台侧 pointId,直连设备入网后回填 | | `sensor_type` | 传感器类型,来自 `platform_sensor_type` 字典;当前包含 `inclino`、`deep_inclino`、`stress`、`hyeto`、`static_level` | | `device_type` | `0=直连设备`、`1=网关设备` | | `push_interface_id` | 推送接口 ID,用于动态字段映射和推送路径 | | `field_mapping` | 标量字段映射,格式如 `[{identifier, platformField, transform}]` | | `extra_mapping` | 数组字段、静力水准、上报间隔等扩展配置 | | `net_status` | `0=未入网`、`1=已入网` | | `enable` | 是否启用 | ### 3.6 `platform_device_sub_mapping` 子设备映射表 用于网关多子设备场景,尤其是静力水准。 关键字段: | 字段 | 说明 | |---|---| | `parent_mapping_id` | 主绑定 ID | | `sub_serial_number` | 子设备序列号 | | `device_role` | `reference=基准点`、`monitor=监测点` | | `platform_device_id` | 平台分配给该监测点的 deviceId | | `platform_point_id` | 平台分配给该监测点的 pointId | | `onboard_config` | 子设备平台标识 JSON,例如 `sensorId`、`refSensorId`、`refSerialNumber`;普通绑定接口参数不放这里 | | `net_status` | 子设备入网状态 | 唯一约束:`parent_mapping_id + sub_serial_number`。 ### 3.7 `platform_push_log` 推送日志 记录流程步骤调用、实时数据推送和失败信息。 关键字段: | 字段 | 说明 | |---|---| | `platform_id` | 平台 ID | | `flow_id` / `step_order` | 流程调用时记录流程与步骤 | | `device_id` / `serial_number` | 设备维度 | | `interface_code` | 接口标识 | | `request_url` / `request_body` | 请求信息 | | `response_code` / `response_body` | 响应信息 | | `status` | `0=进行中`、`1=成功`、`2=失败` | | `error_msg` | 错误信息 | | `idempotency_key` | 幂等键,当前表结构保留 | | `log_type` | `1=数据推送`、`2=操作日志` | | `retry_count` | 重试次数 | | `cost_ms` | 耗时 | --- ## 4. 后端代码结构 ```text fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/platform/ ├── domain/ │ ├── PlatformInstance │ ├── PlatformInterface │ ├── PlatformFlow │ ├── PlatformFlowStep │ ├── PlatformDeviceMapping │ ├── PlatformDeviceSubMapping │ └── PlatformPushLog ├── mapper/ │ ├── PlatformInstanceMapper │ ├── PlatformInterfaceMapper │ ├── PlatformFlowMapper │ ├── PlatformFlowStepMapper │ ├── PlatformDeviceMappingMapper │ ├── PlatformDeviceSubMappingMapper │ └── PlatformPushLogMapper ├── service/ │ ├── IPlatformInstanceService │ ├── IPlatformFlowService │ ├── IPlatformDeviceMappingService │ ├── IPlatformDeviceSubMappingService │ ├── IPlatformPushLogService │ └── impl/ ├── flow/ │ ├── PlatformFlowExecutor │ └── FlowContext ├── adapter/ │ └── dcp/ │ ├── DcpPlatformAdapter │ └── StaticLevelBufferService └── trigger/ └── DeviceReportTrigger ``` ```text fastbee-open-api/src/main/java/com/fastbee/controller/platform/ ├── PlatformInstanceController # /platform/instance ├── PlatformInterfaceController # /platform/interface ├── PlatformFlowController # /platform/flow ├── PlatformDeviceMappingController # /platform/device-mapping └── PlatformPushLogController # /platform/push-log ``` --- ## 5. 核心逻辑 ### 5.1 流程执行器 `PlatformFlowExecutor` 的执行顺序: ```text execute(flow, context) 查询 flow 下所有 step,按 step_order 顺序执行 对每个 step: 1. 读取关联 platform_interface 2. 合并 request_schema 与 step.param_mapping 3. 按 source 解析参数 4. 若参数中存在 list-of-lists,展开为多批请求 5. 每批请求刷新 uuid 参数 6. 替换 path 中的 {变量} 7. GET 参数放 query;form 接口编码为 x-www-form-urlencoded;其他接口发 JSON body 8. 非认证步骤自动注入 Authorization: Bearer {token} 9. 执行 HTTP 10. 按 response_schema 抽取响应,写入 FlowContext 11. 按 result_save 持久化 12. 异步写 platform_push_log,log_type=2 ``` 批量展开用于 `referenceSubDeviceSensorIdPairs` 这类参数。例如静力水准入网时,一个网关下多个 monitor 子设备会拆成多次绑定请求。 ### 5.2 设备入网 入口:`PlatformDeviceMappingServiceImpl.onboard`。 直连设备: 1. 查找同平台、`flow_type=2`、`sensor_type` 匹配且启用的流程。 2. 创建 `FlowContext(platform, mapping, null)`。 3. 执行流程。 4. 若主表已有 `platform_device_id`,将主绑定 `net_status` 改为 `1`。 网关设备: 1. 读取 `platform_device_sub_mapping`。 2. 筛选 `device_role=monitor` 且未入网的子设备。 3. 对每个 monitor 创建独立 `FlowContext`: - `currentMonitorSerialNumber = monitor.sub_serial_number` - `currentMonitorDeviceName = monitor.sub_device_name` - `currentMonitorIndex = monitor 在待入网 monitor 列表中的下标` - `subMappingOnboardConfig = monitor.onboard_config` 4. 执行同一个入网流程。若绑定接口 schema 使用 `source=onboard_config` 且 `value` 为数组,会按 `currentMonitorIndex` 拆出当前子设备的值。 5. 从上下文 `step1.id`、`step2.id` 取 pointId/deviceId,写回当前 monitor 子表。 6. 所有 monitor 都入网后,主绑定 `net_status=1`。 7. 若部分成功部分失败,已成功子设备会保留结果,接口返回明确失败信息。 ### 5.3 设备上报触发 `DeviceReportTrigger.onDeviceReport` 使用异步线程池 `FastBeeConstant.TASK.PUSH_TO_THIRD_PLATFORM_ASYNC`。 匹配逻辑在 `PlatformDeviceMappingMapper.xml`: ```sql SELECT m.* FROM platform_device_mapping m WHERE m.serial_number = #{serialNumber} AND m.enable = '1' UNION SELECT m.* FROM platform_device_mapping m INNER JOIN platform_device_sub_mapping s ON s.parent_mapping_id = m.id WHERE s.sub_serial_number = #{serialNumber} AND m.enable = '1' ``` 分发规则: - `platform.code=dcp` 且 `device_type=0`:调用 `DcpPlatformAdapter.pushData`。 - `platform.code=dcp` 且 `device_type=1`:先在子表中按上报序列号找 `PlatformDeviceSubMapping`,找到后调用 `pushGatewayData`。 - 未知平台 code 只记录 warning,不推送。 ### 5.4 DCP 普通推送 DCP 实时推送必须在设备绑定中配置 `push_interface_id`: - 使用推送接口的 `path`、`code`、`request_schema` 组装并发送请求。 - 未配置推送接口时,`DcpPlatformAdapter.resolvePushPath` 直接抛错,不再按 `sensor_type` 回退到内置路径。 - `resolveInterfaceCode` 仍会在接口 `code` 为空时使用 `dcp_push_{sensorType}` 作为日志标识兜底。 请求体构建规则: - payload 支持 JSON 对象和数组两种格式。 - 数组格式按 `id` 或 `identifier` 转成 `{identifier: value}`,并把 `ts` 保存为 `{identifier}__ts`。 - 有 `request_schema` 时按 schema 组装。 - 若 schema 组装结果为空,或没有任何 payload 驱动字段,则回退到 legacy 组装: - `deviceId = platform_device_id` - `epoch = 当前时间` - 其他字段来自 `field_mapping` - 普通推送请求体最终是数组:`[ {...} ]`。 时间字段会统一转为带时区的 ISO-8601 毫秒格式,支持输入毫秒时间戳、秒时间戳、ISO 字符串、本地时间字符串。 ### 5.5 网关与数组字段推送 网关推送入口:`DcpPlatformAdapter.pushGatewayData`。 当推送接口没有 `type=array` 字段时: - 按普通子设备推送处理。 - `deviceId` 优先使用子表 `platform_device_id`。 - 字段映射仍复用主表 `field_mapping`。 当推送接口包含 `type=array` 字段时: - 当前实现以静力水准为主要落地场景。 - `extra_mapping` 可配置: - `fieldName`:数组字段名,默认 `sensorData` - `itemFieldMappings`:数组元素物模型字段映射 - `reportIntervalSec`:缓存有效时间,默认 300 秒 - 子设备 `onboard_config.sensorId` 作为数组元素的 `sensorId`。 - monitor 子设备 `platform_device_id` 作为请求体顶层 `deviceId`。 静力水准缓存逻辑: 1. 基准点 `device_role=reference` 上报时,只缓存当前 item,不立即推送。 2. 监测点 `device_role=monitor` 上报时,查找其 `onboard_config.refSerialNumber` 对应的基准点缓存。 3. 若基准点缓存新鲜,推送: ```json [ { "deviceId": "监测点平台deviceId", "sensorData": [ {"sensorId": "基准点sensorId", "height": 0.0, "temperature": 0.0, "epoch": "..."}, {"sensorId": "监测点sensorId", "height": 0.0, "temperature": 0.0, "epoch": "..."} ], "ct": 1 } ] ``` 4. 若监测点先到或基准点缓存过期,监测点数据会写入 Redis monitor 缓存。当前代码已有 monitor 缓存读写能力,但推送路径主要依赖“监测点到达时基准点已就绪”的分支。 缓存键: - `static_level:ref:{platformId}:{fieldName}:{serialNumber}` - `static_level:monitor:{platformId}:{fieldName}:{serialNumber}` Redis TTL 为 `reportIntervalSec * 2`,读取时超过 `reportIntervalSec * 1.5` 视为过期。 ### 5.6 日志与重试 - 流程步骤日志:`log_type=2`。 - 实时数据推送日志:`log_type=1`。 - HTTP 成功时记录 URL、请求体、响应体、耗时。 - HTTP 失败时记录 `status=2` 和 `error_msg`。 - `PlatformPushLogController` 暴露 `POST /platform/push-log/{id}/retry`,重试逻辑在 `IPlatformPushLogService.retry` 实现中扩展。 --- ## 6. 前端页面(yack-web) 菜单初始化见 `sql/platform-menu.sql`,页面位于 `yack-web/src/views/platform`。 ### 6.1 平台管理 路径:`yack-web/src/views/platform/instance/index.vue` 后端接口:`/platform/instance` 主要能力: - 查询平台列表。 - 新增、编辑、删除平台。 - 平台详情接口会清空 `access_token`,避免前端拿到 Token。 - 初始化平台:`POST /platform/instance/{id}/initialize`。 ### 6.2 接口定义 路径:`yack-web/src/views/platform/components/InterfaceDrawer.vue`、`HttpRequestDesigner.vue`。 后端接口:`/platform/interface` 主要能力: - 按平台维护接口。 - 配置 method、path、content-type、请求 schema、响应 schema。 - 请求 schema 用于流程执行和设备绑定页动态字段映射。 - `source=onboard_config` 的取值配置编辑 `value`,支持填写 JSON 数组或数字/字符串。保存时前端会把 `[1.7,3.4]` 转成数组,把 `6.8` 转成数字。 ### 6.3 流程编排 路径:`yack-web/src/views/platform/flow/index.vue` 后端接口:`/platform/flow` 主要能力: - 按平台查询流程。 - 新增、编辑流程及步骤。 - 查看流程详情时返回 `{flow, steps}`。 - 手动执行:`POST /platform/flow/{id}/execute`,可选 `mappingId`。 - 步骤入参覆盖同样支持 `source=onboard_config`,语义与接口管理一致:配置 `value`,不配置子映射字段名。 ### 6.4 设备绑定 路径:`yack-web/src/views/platform/device-mapping/index.vue` 后端接口:`/platform/device-mapping` 主要能力: - 管理平台、设备、传感器类型、设备类型、推送接口、字段映射。 - 入网:`POST /platform/device-mapping/{id}/onboard`。 - 子设备映射: - 查询:`GET /platform/device-mapping/{id}/sub-mappings` - 全量同步:`POST /platform/device-mapping/{id}/sub-mappings` 网关设备必须配置子映射,monitor 子设备才会执行入网并获得平台 deviceId。 ### 6.5 推送日志 路径:`yack-web/src/views/platform/push-log/index.vue` 后端接口:`/platform/push-log` 主要能力: - 查询推送/操作日志。 - 查看日志详情。 - 手动重推入口:`POST /platform/push-log/{id}/retry`。 --- ## 7. DCP 内置初始化数据 初始化 SQL:`sql/platform-dcp-init-data.sql`。 使用前需要先创建 DCP 平台实例: ```sql SET @dcp_platform_id = (SELECT id FROM platform_instance WHERE code = 'dcp' LIMIT 1); ``` ### 7.1 内置接口(12 个) | code | 方法 | 路径 | 用途 | |---|---|---|---| | `dcp_auth` | POST | `/connect/token` | 获取 Token | | `dcp_get_user` | GET | `/api/app/user/user-id` | 获取当前用户 | | `dcp_get_projects` | GET | `/api/app/project/by-user-id/{userId}` | 获取项目列表,默认取第一个 | | `dcp_create_point` | POST | `/api/app/point` | 创建测点 | | `dcp_bind_inclino` | POST | `/api/app/inclino-sensor` | 绑定倾角传感器 | | `dcp_bind_stress` | POST | `/api/app/stress-sensor` | 绑定轴力计 | | `dcp_bind_hyeto` | POST | `/api/app/hyeto-sensor` | 绑定雨量计 | | `dcp_bind_static_level` | POST | `/api/app/static-level-device` | 绑定静力水准 | | `dcp_push_inclino` | POST | `/api/app/inclino-data/many` | 推送倾角数据 | | `dcp_push_stress` | POST | `/api/app/stress-data/many` | 推送轴力计数据 | | `dcp_push_hyeto` | POST | `/api/app/hyeto-data/many` | 推送雨量计数据 | | `dcp_push_static_level` | POST | `/api/app/static-level-data/many` | 推送静力水准数据 | ### 7.2 内置流程(6 个) | code | flow_type | sensor_type | 步骤 | |---|---:|---|---| | `dcp_init` | 1 | - | `dcp_auth` -> `dcp_get_user` -> `dcp_get_projects` | | `dcp_token_refresh` | 3 | - | `dcp_auth` | | `dcp_onboard_inclino` | 2 | `inclino` | `dcp_create_point` -> `dcp_bind_inclino` | | `dcp_onboard_stress` | 2 | `stress` | `dcp_create_point` -> `dcp_bind_stress` | | `dcp_onboard_hyeto` | 2 | `hyeto` | `dcp_create_point` -> `dcp_bind_hyeto` | | `dcp_onboard_static_level` | 2 | `static_level` | `dcp_create_point` -> `dcp_bind_static_level` | ### 7.3 DCP 字段约定 - 入网接口中的 `moduleId`、`virtualId` 使用 `source=uuid`,每次请求生成新 UUID。 - 静力水准绑定接口的 `sensorIds` 使用 `source=referenceSubDeviceSensorIdPairs`。 - 静力水准推送接口定义了数组字段 `sensorData`,其 `itemSchema` 包含 `epoch`、`height`、`temperature`、`sensorId`。 - 轴力计和雨量计 DCP 文档要求累计值递增;当前代码未在适配器中实现“查询上次成功值并跳过非递增值”的通用校验,若目标平台严格校验,需要在推送前补充该逻辑或依赖平台返回失败日志。 ### 7.4 深部位移计扩展配置 `sql/platform-integration.sql` 已在 `platform_sensor_type` 字典中维护 `deep_inclino`,前端传感器类型下拉也支持从字典读取和手动输入。`sql/platform-dcp-init-data.sql` 当前未内置深部位移计绑定接口和入网流程,需要在接口管理和流程编排中配置。 DCP 深部位移绑定接口: | 项 | 值 | |---|---| | code 建议 | `dcp_bind_deep_inclino` | | method | `POST` | | path | `/api/app/deep-inclino-device` | | content-type | `application/json` | 典型 `request_schema`: ```json [ {"name":"projectId","type":"string","source":"extra","field":"projectId","required":true}, {"name":"pointId","type":"string","source":"context","contextKey":"step1.id","required":true}, {"name":"name","type":"string","source":"device","field":"serial_number","required":true}, {"name":"moduleId","type":"string","source":"uuid","required":true}, {"name":"virtualId","type":"string","source":"uuid","required":true}, {"name":"sensorDepths","type":"array","source":"onboard_config","value":[1.7,3.4,5.1,6.8],"required":true}, {"name":"holeDepth","type":"number","source":"onboard_config","value":[1.7,3.4,5.1,6.8],"required":true}, {"name":"sensorIds","type":"array","source":"subDeviceSensorIds","required":true}, {"name":"axisDirection","type":"string","source":"onboard_config","value":"X","required":false}, {"name":"holeElevation","type":"number","source":"onboard_config","value":0,"required":false}, {"name":"zipDuring","type":"number","source":"onboard_config","value":0,"required":false}, {"name":"frequency","type":"number","source":"onboard_config","value":2147483647,"required":false}, {"name":"remark","type":"string","source":"onboard_config","value":"","required":false} ] ``` 网关多子设备绑定深部位移计时,`sensorDepths` 与 `holeDepth` 这类数组值按待入网 monitor 子设备顺序逐个拆分: - 第 1 个 monitor:`sensorDepths` 取 `1.7`,因字段类型为 `array`,最终请求为 `"sensorDepths":[1.7]`;`holeDepth` 为 `1.7`。 - 第 2 个 monitor:`sensorDepths` 为 `[3.4]`,`holeDepth` 为 `3.4`。 - 依此类推。 深度类字段按工程习惯使用正数,表示距孔口向下的距离;若需要平台侧高程,按 `holeElevation - sensorDepth` 计算,不通过负深度表达方向。 --- ## 8. 关键复用点 | 资产 | 位置 | 用途 | |---|---|---| | `HttpClientFactory` | `fastbee-plugs/fastbee-http` | 发起 HTTP 请求 | | `HttpClientConfig` | `fastbee-plugs/fastbee-http` | 构建请求 URL、method、headers、body/query | | Forest HTTP | `com.dtflys.forest` | 底层 HTTP 执行 | | `RuleProcess` 调用方 | IoT 上报处理链路 | 设备上报后触发 `DeviceReportTrigger` | | Redis | `StaticLevelBufferService` | 静力水准基准点/监测点缓存 | | MyBatis-Plus `ServiceImpl` | 平台 service 实现 | 常规 CRUD | | `iot_things_model` | 物模型表 | 前端字段映射可选项来源 | --- ## 9. 当前实现限制与注意事项 - 当前适配器只有 DCP。新增平台需要新增 adapter,并在 `DeviceReportTrigger.dispatchPush` 中按平台 `code` 路由。 - 文档中的“可视化配置”已覆盖平台、接口、流程、设备绑定、子映射和日志,但平台适配器路由仍需要代码扩展。 - DCP 实时推送必须配置 `push_interface_id`,未配置时不会按传感器类型自动回退路径。 - 实时推送只支持 POST JSON,流程执行支持 GET、form、JSON。 - `idempotency_key` 字段已建表,但实时推送未生成幂等键。 - `PlatformInstanceController.getInfo` 只清空 `access_token`,注释提到密码脱敏,但当前代码未改写 `auth_config` 内密码。 - `platform_device_mapping.platform_device_id` 对网关设备不是主要数据来源;网关 monitor 的平台 deviceId 保存在 `platform_device_sub_mapping.platform_device_id`。 - 静力水准 monitor 先到时会缓存 monitor 数据,但当前主推送分支是在 monitor 到达时读取基准点缓存;若要实现“基准点后到自动补推所有等待 monitor”,需要在基准点上报分支补充扫描 monitor 缓存并推送。