915 lines
44 KiB
Markdown
915 lines
44 KiB
Markdown
# 平台对接设计文档
|
||
|
||
本文档按当前项目代码反补,描述已落地的平台对接模块。相关实现主要位于:
|
||
|
||
- `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`。
|
||
- **Token/认证已从平台级(PlatformInstance)迁移到用户级(PlatformUserAuth)**,每个用户有独立的 Token、过期时间和项目权限。
|
||
|
||
---
|
||
|
||
## 2. 四种执行模式
|
||
|
||
### 2.1 流程编排
|
||
|
||
适用于多个接口必须顺序调用,且后续步骤依赖前序步骤返回值的场景。
|
||
|
||
| 流程 | 触发方式 | 典型步骤 | 结果落库 |
|
||
|---|---|---|---|
|
||
| 用户初始化 | 用户管理页点击初始化 | `dcp_auth` -> `dcp_get_user` -> `dcp_get_projects` | `platform_user_auth.access_token`、`platform_user_auth.platform_user_id`、`platform_user_auth.platform_user_name`、`platform_user_auth.extra_config` |
|
||
| Token 刷新 | HTTP 调用前自动触发 | `dcp_auth` | `platform_user_auth.access_token`、`platform_user_auth.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` |
|
||
|
||
入口代码:
|
||
|
||
- `PlatformUserAuthServiceImpl.initialize(Long userAuthId)` - 用户初始化
|
||
- `PlatformDeviceMappingServiceImpl.onboard(Long mappingId)` - 设备入网
|
||
- `PlatformFlowExecutor.execute(PlatformFlow flow, FlowContext context)`
|
||
|
||
> **注意:** 流程手动执行端点(`POST /platform/flow/{id}/execute`)已移除,流程执行只能通过业务入口(初始化/入网/Token 刷新)触发。
|
||
|
||
### 2.2 直接调用实时推送
|
||
|
||
设备上报后由 `DeviceReportTrigger.onDeviceReport(serialNumber, payload)` 异步触发:
|
||
|
||
1. `PlatformDeviceMappingMapper.selectBySerialNumber` 同时匹配直连主设备和网关子设备。
|
||
2. 过滤未启用的平台和绑定关系。
|
||
3. 按平台 `code` 分发,目前 `dcp` 进入 `DcpPlatformAdapter`。
|
||
4. 加载 `PlatformUserAuth`,传入适配器用于 Token 获取和字段映射。
|
||
5. 适配器按推送接口的 `request_schema` 与设备绑定字段映射组装请求体。
|
||
6. 检查并刷新 Token(从 userAuth 获取)。
|
||
7. 发送 HTTP POST,写入 `platform_push_log`。
|
||
|
||
实时推送不经过 `PlatformFlowExecutor`,因此不会使用流程步骤的 `param_mapping`、`result_key`、`result_save`。
|
||
|
||
### 2.3 定时推送
|
||
|
||
在实时推送基础上,新增按时间间隔推送最新数据的模式。通过 `platform_device_mapping.push_mode` 字段控制:
|
||
|
||
| push_mode | 模式 | 行为 |
|
||
|---|---|---|
|
||
| `1`(默认) | 实时推送 | 设备上报后立即推送,沿用原有链路 |
|
||
| `2` | 定时推送 | 仅由调度器按 `push_interval`(分钟)推送,`DeviceReportTrigger` 跳过实时推送 |
|
||
|
||
调度器 `PlatformPushScheduledJob` 使用 Spring `@Scheduled(fixedDelay = 300_000)` 每 5 分钟检查一次:
|
||
|
||
1. 查询所有 `enable='1'`、`push_mode=2`、`push_interval > 0` 的绑定。
|
||
2. 加载绑定关联的 `PlatformUserAuth`,逐条判断 `now - last_push_time >= push_interval * 60 * 1000`;从未推送过的立即触发。
|
||
3. 从 Redis 缓存读取最新数据,按直连/网关分别调用 `DcpPlatformAdapter` 推送。
|
||
4. 推送成功后更新 `last_push_time`;失败时保留不变,下次继续尝试。
|
||
|
||
定时推送不经过 `PlatformFlowExecutor`,推送数据来自 Redis 缓存而非实时 payload,因此依赖设备数据及时更新到 Redis。
|
||
|
||
### 2.4 Token 自动刷新
|
||
|
||
流程执行器调用 `ensureToken(FlowContext ctx)`:
|
||
|
||
- 从 `FlowContext.platformUserAuth` 获取用户认证信息。
|
||
- `access_token` 为空,或 `token_expires_at` 距当前时间不足 5 分钟时视为过期。
|
||
- 自动查找同平台 `flow_type=3` 且 `enable='1'` 的 Token 刷新流程。
|
||
- 刷新流程本身不注入 Authorization,避免递归。
|
||
- 刷新成功后更新 `platform_user_auth.access_token` 和 `token_expires_at`(不再是 `platform_instance`)。
|
||
|
||
> **架构变更:** Token 管理已从 `PlatformInstance` 迁移到 `PlatformUserAuth`。`PlatformInstance.access_token` / `PlatformInstance.token_expires_at` 字段不再使用,所有 Token 读写都通过 `platform_user_auth` 表。
|
||
|
||
---
|
||
|
||
## 3. 数据库设计(8 张表)
|
||
|
||
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` | 平台级业务参数,如站点编码 |
|
||
| `enable` | 是否启用 |
|
||
| `tenant_id` | 租户 ID |
|
||
|
||
**废弃字段:** `access_token`、`token_expires_at`、`init_status` 为历史遗留,实际不再使用。Token 和初始化状态现在存储在 `platform_user_auth` 表。
|
||
|
||
**架构说明:** 一个平台可以对应多个用户认证(`platform_user_auth`),每个用户有独立的 Token、项目权限。`platform_instance.auth_config` 仅作为新增用户时的默认模板。
|
||
|
||
### 3.2 `platform_user_auth` 平台用户认证
|
||
|
||
支持一个平台对应多个用户认证,每个用户有独立的 Token 和项目权限。
|
||
|
||
关键字段:
|
||
|
||
| 字段 | 说明 |
|
||
|---|---|
|
||
| `platform_id` | 平台实例 ID |
|
||
| `platform_user_id` | 平台侧用户 ID(如 DCP 的 userId),初始化流程执行后回填,允许为空 |
|
||
| `platform_user_name` | 平台侧用户名,初始化流程执行后回填 |
|
||
| `auth_config` | 用户认证凭证 JSON,例如 `{userName, password, clientId, scope}` |
|
||
| `access_token` | 该用户的 Token |
|
||
| `token_expires_at` | Token 过期时间 |
|
||
| `init_status` | 初始化状态:`0=未初始化`、`1=已初始化` |
|
||
| `extra_config` | 用户级配置,如项目信息等 |
|
||
| `enable` | 是否启用 |
|
||
|
||
**使用流程:**
|
||
|
||
1. 新增用户认证:仅输入认证配置(用户名/密码/clientId/scope)
|
||
2. 用户记录处于 `init_status=0`,`platform_user_id` 为空
|
||
3. 执行初始化流程:
|
||
- 用认证配置获取 Token
|
||
- 用 Token 获取 `userId` 和用户名
|
||
- 自动回填 `platform_user_id` 和 `platform_user_name`
|
||
- 标记 `init_status=1`
|
||
4. 设备绑定时选择已初始化的用户,再获取项目列表
|
||
|
||
**唯一约束:** `uk_platform_user (platform_id, platform_user_id)`,注意 `platform_user_id` 允许为空(未初始化时)。
|
||
|
||
### 3.3 `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_user_auth.auth_config` 取值,fallback 到 `platform_instance.auth_config` |
|
||
| `extra` | 优先从 `platform_user_auth.extra_config` 取值,fallback 到 `platform_instance.extra_config` |
|
||
| `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 列表 |
|
||
| `cascadedSubDeviceSensorIds` | 串联子设备入网:从当前 monitor 到末端 monitor 收集 sensorId,并按末端到当前倒序返回 |
|
||
| `cascadedSubDeviceDepths` | 串联子设备入网:从配置的顺序数组中截取当前 monitor 到末端 monitor,并按末端到当前倒序返回 |
|
||
| `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":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` | 优先从 `platform_user_auth` 认证 JSON 取值 |
|
||
| `extra` | 优先从 `platform_user_auth` 扩展 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.4 `platform_flow` 流程定义
|
||
|
||
关键字段:
|
||
|
||
| 字段 | 说明 |
|
||
|---|---|
|
||
| `platform_id` | 所属平台 |
|
||
| `name` / `code` | 流程名称与标识 |
|
||
| `flow_type` | `1=平台初始化`、`2=设备入网`、`3=Token刷新` |
|
||
| `sensor_type` | 入网流程适用传感器类型,如 `inclino`、`deep_inclino`、`stress`、`hyeto`、`static_level` |
|
||
| `enable` | 是否启用 |
|
||
|
||
### 3.5 `platform_flow_step` 流程步骤
|
||
|
||
关键字段:
|
||
|
||
| 字段 | 说明 |
|
||
|---|---|
|
||
| `flow_id` | 所属流程 |
|
||
| `step_order` | 执行顺序 |
|
||
| `interface_id` | 关联接口 |
|
||
| `param_mapping` | 覆盖接口默认入参来源 |
|
||
| `result_key` | 步骤结果写入上下文的 key |
|
||
| `result_save` | 将响应字段持久化到用户认证或设备绑定 |
|
||
|
||
`result_save` 支持:
|
||
|
||
- `platform_user_auth.access_token` - 用户级 Token
|
||
- `platform_user_auth.token_expires_at` - 值按 `expires_in` 秒数转换为 Date
|
||
- `platform_user_auth.platform_user_id` - 平台侧用户 ID
|
||
- `platform_user_auth.platform_user_name` - 平台侧用户名
|
||
- `extra_config.xxx` - 用户级配置
|
||
- `device_mapping.platform_device_id`
|
||
- `device_mapping.platform_point_id`
|
||
|
||
> **注意:** `result_save` 已从写 `platform_instance.*` 改为写 `platform_user_auth.*`。配置中的 `platform_instance.access_token` 等旧值应更新为 `platform_user_auth.access_token`。
|
||
|
||
### 3.6 `platform_device_mapping` 设备绑定主表
|
||
|
||
保存 FastBee 设备与第三方平台的绑定关系。
|
||
|
||
关键字段:
|
||
|
||
| 字段 | 说明 |
|
||
|---|---|
|
||
| `platform_id` | 所属平台 |
|
||
| `platform_user_auth_id` | 关联用户认证 ID,选择已初始化的用户 |
|
||
| `platform_project_id` | 平台侧项目 ID,用户选择后存储 |
|
||
| `platform_project_name` | 平台侧项目名称 |
|
||
| `device_id` / `serial_number` | FastBee 设备 ID 与序列号 |
|
||
| `device_name` | 推送给平台的设备名称,默认取平台设备名称,可手动修改 |
|
||
| `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` | 是否启用 |
|
||
| `push_mode` | 推送模式:`1=实时`、`2=定时`,默认 `1` |
|
||
| `push_interval` | 定时推送间隔(分钟),`0` 表示不自动推送 |
|
||
| `last_push_time` | 最近推送时间,由定时调度器更新 |
|
||
|
||
**级联选择流程:** 新增设备绑定时,先选择平台 → 加载已初始化用户列表 → 选择用户 → 加载项目列表 → 选择项目。
|
||
|
||
### 3.7 `platform_device_sub_mapping` 子设备映射表
|
||
|
||
用于网关多子设备场景,尤其是静力水准和深部位移。
|
||
|
||
关键字段:
|
||
|
||
| 字段 | 说明 |
|
||
|---|---|
|
||
| `parent_mapping_id` | 主绑定 ID |
|
||
| `sub_serial_number` | 子设备序列号 |
|
||
| `sub_device_name` | 子设备名称 |
|
||
| `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.8 `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
|
||
│ ├── PlatformUserAuth # 平台用户认证,Token/认证从这里获取
|
||
│ ├── PlatformInterface
|
||
│ ├── PlatformFlow
|
||
│ ├── PlatformFlowStep
|
||
│ ├── PlatformDeviceMapping
|
||
│ ├── PlatformDeviceSubMapping
|
||
│ └── PlatformPushLog
|
||
├── mapper/
|
||
│ ├── PlatformInstanceMapper
|
||
│ ├── PlatformUserAuthMapper # 用户认证 Mapper
|
||
│ ├── PlatformInterfaceMapper
|
||
│ ├── PlatformFlowMapper
|
||
│ ├── PlatformFlowStepMapper
|
||
│ ├── PlatformDeviceMappingMapper
|
||
│ ├── PlatformDeviceSubMappingMapper
|
||
│ └── PlatformPushLogMapper
|
||
├── service/
|
||
│ ├── IPlatformInstanceService # 仅保留 selectList
|
||
│ ├── IPlatformUserAuthService # 用户认证(新增,接管初始化/项目/Token)
|
||
│ ├── IPlatformFlowService # 移除 executeManually
|
||
│ ├── IPlatformDeviceMappingService
|
||
│ ├── IPlatformDeviceSubMappingService
|
||
│ ├── IPlatformPushLogService
|
||
│ └── impl/
|
||
├── flow/
|
||
│ ├── PlatformFlowExecutor # Token 从 userAuth 获取
|
||
│ └── FlowContext # platformUserAuth 为必填字段
|
||
├── adapter/
|
||
│ └── dcp/
|
||
│ ├── DcpPlatformAdapter # 所有推送方法增加 userAuth 参数
|
||
│ └── StaticLevelBufferService
|
||
├── trigger/
|
||
│ └── DeviceReportTrigger # 加载 userAuth 传入适配器
|
||
└── job/
|
||
└── PlatformPushScheduledJob # 加载 userAuth 传入适配器
|
||
```
|
||
|
||
```text
|
||
fastbee-open-api/src/main/java/com/fastbee/controller/platform/
|
||
├── PlatformInstanceController # /platform/instance(移除 initialize、getProjects)
|
||
├── PlatformUserAuthController # /platform/user-auth(新增,接管初始化/项目/用户管理)
|
||
├── PlatformInterfaceController # /platform/interface
|
||
├── PlatformFlowController # /platform/flow(移除 execute 端点)
|
||
├── 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 解析参数(优先从 userAuth 获取,fallback 到 platform.authConfig)
|
||
4. 若参数中存在 list-of-lists,展开为多批请求
|
||
5. 每批请求刷新 uuid 参数
|
||
6. 替换 path 中的 {变量}
|
||
7. GET 参数放 query;form 接口编码为 x-www-form-urlencoded;其他接口发 JSON body
|
||
8. 非认证步骤自动注入 Authorization: Bearer {token}(从 userAuth 获取)
|
||
9. 执行 HTTP
|
||
10. 按 response_schema 抽取响应,写入 FlowContext
|
||
11. 按 result_save 持久化到 platform_user_auth 或 device_mapping
|
||
12. 异步写 platform_push_log,log_type=2
|
||
```
|
||
|
||
**FlowContext 构造:** `platformUserAuth` 是必填字段,所有构造函数都需要传入。旧的 `FlowContext(PlatformInstance)` 构造函数已移除。
|
||
|
||
**重要变更:** `persistResultSave` 不再向 `platform_instance` 表写 Token/过期时间,而是写入 `platform_user_auth` 表。`result_save` 配置中的 `saveTo` 路径应使用 `platform_user_auth.*` 前缀而非 `platform_instance.*`。
|
||
|
||
`auth` 和 `extra` 参数来源优先级:
|
||
- `auth source`:`PlatformUserAuth.auth_config` → `PlatformInstance.auth_config`
|
||
- `extra source`:`PlatformUserAuth.extra_config` → `PlatformInstance.extra_config`
|
||
|
||
批量展开用于 `referenceSubDeviceSensorIdPairs` 这类参数。例如静力水准入网时,一个网关下多个 monitor 子设备会拆成多次绑定请求。
|
||
|
||
### 5.2 设备入网
|
||
|
||
入口:`PlatformDeviceMappingServiceImpl.onboard`。
|
||
|
||
直连设备:
|
||
|
||
1. 根据设备绑定的 `platformUserAuthId` 查询用户认证信息。
|
||
2. 查找同平台、`flow_type=2`、`sensor_type` 匹配且启用的流程。
|
||
3. 创建 `FlowContext(platform, mapping, userAuth)`。
|
||
4. 执行流程。
|
||
5. 若主表已有 `platform_device_id`,将主绑定 `net_status` 改为 `1`。
|
||
|
||
网关设备:
|
||
|
||
1. 读取 `platform_device_sub_mapping`。
|
||
2. 筛选 `device_role=monitor` 且未入网的子设备。
|
||
3. 对每个 monitor 创建独立 `FlowContext`,通过构造函数一次性传入所有上下文字段:
|
||
- `platformUserAuth` = 设备绑定关联的用户认证
|
||
- `currentMonitorSerialNumber`、`currentMonitorDeviceName`
|
||
- `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. 若部分成功部分失败,已成功子设备会保留结果,接口返回明确失败信息。
|
||
|
||
> **注意:** 入网不再校验 `platformProjectId` 是否为空。网关子设备 `FlowContext` 现在通过构造函数一次性设置所有字段,不再使用 `setXxx` 逐个设置。
|
||
|
||
### 5.3 设备上报触发
|
||
|
||
`DeviceReportTrigger.onDeviceReport` 使用异步线程池 `FastBeeConstant.TASK.PUSH_TO_THIRD_PLATFORM_ASYNC`。
|
||
|
||
遍历匹配的 `PlatformDeviceMapping` 时,先检查 `push_mode`:
|
||
|
||
- `push_mode=1` 或未配置:执行实时推送(原有行为)。
|
||
- `push_mode=2`:跳过实时推送,仅由 `PlatformPushScheduledJob` 定时推送。
|
||
|
||
匹配逻辑在 `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'
|
||
```
|
||
|
||
分发规则:
|
||
|
||
- 加载 `PlatformUserAuth`,未启用或无用户认证时跳过。
|
||
- `platform.code=dcp` 且 `device_type=0`:调用 `DcpPlatformAdapter.pushData(platform, userAuth, mapping, ...)`。
|
||
- `platform.code=dcp` 且 `device_type=1`:先在子表中按上报序列号找 `PlatformDeviceSubMapping`,找到后调用 `pushGatewayData(platform, userAuth, mapping, subMapping, ...)`。
|
||
- 未知平台 code 只记录 warning,不推送。
|
||
|
||
### 5.4 定时推送调度器
|
||
|
||
`PlatformPushScheduledJob` 位于 `com.fastbee.iot.platform.job`,核心逻辑:
|
||
|
||
```java
|
||
@Scheduled(fixedDelay = 300_000)
|
||
public void execute() {
|
||
// 1. 查询所有启用的定时推送配置(pushMode=2)
|
||
List<PlatformDeviceMapping> mappings = mappingService.list(
|
||
Wrappers.<PlatformDeviceMapping>lambdaQuery()
|
||
.eq(PlatformDeviceMapping::getEnable, "1")
|
||
.eq(PlatformDeviceMapping::getPushMode, 2)
|
||
.gt(PlatformDeviceMapping::getPushInterval, 0)
|
||
);
|
||
// 2. 遍历检查是否到达推送时间
|
||
for (PlatformDeviceMapping mapping : mappings) {
|
||
if (isDue(mapping, now)) {
|
||
pushLatestData(mapping);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
`isDue` 判断:`push_interval` 转换为毫秒后,若 `nowMs - lastPushTime.getTime() >= intervalMs` 则触发。`lastPushTime` 为空时立即触发。
|
||
|
||
`pushLatestData` 加载 `PlatformUserAuth`,从 Redis 缓存读取设备最新数据,按 `device_type` 分发:
|
||
|
||
- 直连设备(`device_type=0`):调用 `DcpPlatformAdapter.pushData(platform, userAuth, mapping, ...)`。
|
||
- 网关设备(`device_type=1`):遍历所有子设备,逐个从 Redis 读取并调用 `DcpPlatformAdapter.pushGatewayData(platform, userAuth, mapping, subMapping, ...)`。
|
||
|
||
推送完成后调用 `IPlatformDeviceMappingService.updateLastPushTime` 更新 `last_push_time`。
|
||
|
||
数据流:
|
||
|
||
```
|
||
设备上报数据 → Redis 缓存更新
|
||
↓
|
||
┌──────────────────────────────────────┐
|
||
│ PlatformPushScheduledJob(每5分钟) │
|
||
│ push_mode=2 且达到时间间隔 │
|
||
│ → 加载 PlatformUserAuth │
|
||
│ → 从 Redis 读最新数据 │
|
||
│ → 推送到平台(传入 userAuth) │
|
||
│ → 更新 last_push_time │
|
||
└──────────────────────────────────────┘
|
||
```
|
||
|
||
### 5.5 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 组装。
|
||
- 普通推送请求体最终是数组:`[ {...} ]`。
|
||
|
||
所有推送方法签名增加了 `PlatformUserAuth userAuth` 参数,用于 Token 获取:
|
||
|
||
```java
|
||
// 变更后
|
||
dcpAdapter.pushData(platform, userAuth, mapping, reportSerialNumber, payload);
|
||
dcpAdapter.pushGatewayData(platform, userAuth, mapping, subMapping, reportSerialNumber, payload);
|
||
```
|
||
|
||
时间字段会统一转为带时区的 ISO-8601 毫秒格式,支持输入毫秒时间戳、秒时间戳、ISO 字符串、本地时间字符串。
|
||
|
||
### 5.6 网关与数组字段推送
|
||
|
||
网关推送入口:`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 缓存。
|
||
|
||
缓存键:
|
||
|
||
- `static_level:ref:{platformId}:{fieldName}:{serialNumber}`
|
||
- `static_level:monitor:{platformId}:{fieldName}:{serialNumber}`
|
||
|
||
Redis TTL 为 `reportIntervalSec * 2`,读取时超过 `reportIntervalSec * 1.5` 视为过期。
|
||
|
||
### 5.7 深部位移整孔批量推送
|
||
|
||
深部位移等整孔场景可在推送接口上开启 `is_batch_push=1`,由 `DcpPlatformAdapter.pushGatewayData` 进入批量推送分支。该能力仍属于网关数组字段推送的一种特化形态,不单独走流程引擎。
|
||
|
||
核心行为:
|
||
|
||
1. 查询当前绑定下所有 `device_role=monitor` 的子设备,顺序以 `platform_device_sub_mapping` 返回顺序为准(深部位移场景为浅到深)。
|
||
2. 当前上报子设备使用本次 payload,其余子设备从 Redis 读取缓存;读取 Redis 时使用子设备真实 `product_id + sub_serial_number`,避免误用网关主设备产品 ID。
|
||
3. 每个 monitor 组装为一个请求体对象,`deviceId` 使用该 monitor 入网后回填的 `platform_device_id`,`xTotalBias`、`yTotalBias` 等主体字段使用该 monitor 自身数据。
|
||
4. 每个对象中的 `sensorData` 不是单点,而是从该 monitor 到末端 monitor 的后缀数组;深部位移中表现为"当前深度 + 更深点位",顺序保持从浅到深。
|
||
5. 最浅节点对象包含全孔从浅到深的点位数据,最深节点对象只包含自己。
|
||
6. 最终一次 HTTP 请求推送整个数组。
|
||
|
||
批量推送不再从"数据推送接口"的 `request_schema` 读取入网参数 `sensorDepths`。`sensorDepths`、`holeDepth` 等仍属于深部位移入网/绑定接口配置;数据推送接口只需配置实际推送字段,例如 `deviceId`、`sensorData`、累计偏移量等。
|
||
|
||
示例请求体结构(4 个串联点,从浅到深为 A/B/C/D):
|
||
|
||
```json
|
||
[
|
||
{
|
||
"deviceId": "A平台deviceId",
|
||
"xTotalBias": "A累计X偏移",
|
||
"yTotalBias": "A累计Y偏移",
|
||
"sensorData": ["A点数据", "B点数据", "C点数据", "D点数据"],
|
||
"ct": 1
|
||
},
|
||
{
|
||
"deviceId": "B平台deviceId",
|
||
"xTotalBias": "B累计X偏移",
|
||
"yTotalBias": "B累计Y偏移",
|
||
"sensorData": ["B点数据", "C点数据", "D点数据"],
|
||
"ct": 1
|
||
},
|
||
{
|
||
"deviceId": "C平台deviceId",
|
||
"xTotalBias": "C累计X偏移",
|
||
"yTotalBias": "C累计Y偏移",
|
||
"sensorData": ["C点数据", "D点数据"],
|
||
"ct": 1
|
||
},
|
||
{
|
||
"deviceId": "D平台deviceId",
|
||
"xTotalBias": "D累计X偏移",
|
||
"yTotalBias": "D累计Y偏移",
|
||
"sensorData": ["D点数据"],
|
||
"ct": 1
|
||
}
|
||
]
|
||
```
|
||
|
||
配置与排查要点:
|
||
|
||
- 在平台接口管理中,为需要整孔推送的"数据推送接口"开启批量推送,即 `platform_interface.is_batch_push=1`。
|
||
- 推送接口 `request_schema` 必须包含实际数据推送字段;不要把入网接口的 `sensorDepths` 当作批量推送前置条件。
|
||
- 子设备必须已入网,monitor 子表行必须有 `platform_device_id`。
|
||
- Redis 中需要有各 monitor 子设备的最新物模型缓存;缺失数据的点位不会进入对应后缀 `sensorData`,若某 monitor 自身无数据则该 monitor 对象会被跳过。
|
||
- 推送日志可在 `platform_push_log` 查看;成功日志会出现 `[DCP] 批量推送完成`。
|
||
|
||
### 5.8 Token 管理
|
||
|
||
**架构变更:** Token 管理已从平台级迁移到用户级。`PlatformInstance` 上的 `access_token`、`token_expires_at` 字段不再使用。
|
||
|
||
`PlatformFlowExecutor.ensureToken(FlowContext ctx)`:
|
||
|
||
- 从 `ctx.getPlatformUserAuth()` 获取用户认证信息。
|
||
- `access_token` 为空,或 `token_expires_at` 距当前时间不足 5 分钟时视为过期。
|
||
- 自动查找同平台 `flow_type=3` 且 `enable='1'` 的 Token 刷新流程。
|
||
- 创建带有 `platform` 和 `userAuth` 的 `FlowContext` 执行刷新流程。
|
||
- 刷新流程本身不注入 Authorization,避免递归。
|
||
- 刷新成功后更新 `platform_user_auth.access_token` 和 `token_expires_at`。
|
||
- Token 刷新流程最后步骤应配置 `result_key=tokenStep`,以便 `refreshToken` 方法提取 `access_token` 和 `expires_in`。
|
||
|
||
`DcpPlatformAdapter.ensureToken`(适配器层):
|
||
|
||
- 读取 `platformUserAuth.access_token` 和 `token_expires_at` 判断是否过期。
|
||
- 过期时查找 `flow_type=3` 流程并执行 `flowExecutor.execute(tokenFlow, ctx)`。
|
||
- 刷新后重新从数据库读取最新 `platform_user_auth` 记录。
|
||
- 返回 `platformUserAuth.access_token`。
|
||
|
||
### 5.9 日志与重试
|
||
|
||
- 流程步骤日志:`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。
|
||
- `initStatus` 通过查询 `platform_user_auth` 表计算:存在有效用户则显示已初始化。
|
||
|
||
**用户管理:**
|
||
|
||
点击"用户"按钮打开用户管理弹窗,后端接口:`/platform/user-auth`
|
||
|
||
- 查询用户认证列表:`GET /platform/user-auth/list?platformId={id}`
|
||
- 新增用户:仅输入认证配置(用户名/密码/clientId/scope),`platformUserId` 和 `platformUserName` 为空
|
||
- 初始化用户:`POST /platform/user-auth/{id}/initialize`
|
||
- 执行初始化流程获取 Token
|
||
- 从 Token 解析或调用接口获取 `userId` 和用户名
|
||
- 自动回填 `platformUserId` 和 `platformUserName`
|
||
- 标记 `initStatus=1`
|
||
- 编辑用户:显示 `platformUserId` 和 `platformUserName`(只读)
|
||
- 删除用户:`DELETE /platform/user-auth/{ids}`
|
||
|
||
用户初始化流程配置(flow_type=1)需要在 `result_save` 中指定:
|
||
|
||
```json
|
||
[
|
||
{"field": "access_token", "saveTo": "platform_user_auth.access_token"},
|
||
{"field": "expires_in", "saveTo": "platform_user_auth.token_expires_at"},
|
||
{"field": "userId", "saveTo": "platform_user_auth.platform_user_id"},
|
||
{"field": "userName", "saveTo": "platform_user_auth.platform_user_name"}
|
||
]
|
||
```
|
||
|
||
> **注意:** `saveTo` 应使用 `platform_user_auth.*` 前缀而非旧的 `platform_instance.*`。
|
||
|
||
### 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}`。
|
||
- 步骤入参覆盖同样支持 `source=onboard_config`,语义与接口管理一致:配置 `value`,不配置子映射字段名。
|
||
|
||
> **注意:** 流程手动执行按钮已移除,流程只能通过业务入口触发。
|
||
|
||
### 6.4 设备绑定
|
||
|
||
路径:`yack-web/src/views/platform/device-mapping/index.vue`
|
||
|
||
后端接口:`/platform/device-mapping`
|
||
|
||
主要能力:
|
||
|
||
- 管理平台、用户、项目、设备、传感器类型、设备类型、推送接口、字段映射。
|
||
- 级联选择(新增):
|
||
- 选择平台 → 加载已初始化用户列表:`GET /platform/user-auth/initialized/{platformId}`
|
||
- 选择用户 → 加载项目列表:`GET /platform/user-auth/{id}/projects`
|
||
- 选择项目 → 回填 `platformProjectId` 和 `platformProjectName`
|
||
- 入网:`POST /platform/device-mapping/{id}/onboard`。
|
||
- 子设备映射:
|
||
- 查询:`GET /platform/device-mapping/{id}/sub-mappings`
|
||
- 全量同步:`POST /platform/device-mapping/{id}/sub-mappings`
|
||
|
||
网关设备必须配置子映射,monitor 子设备才会执行入网并获得平台 deviceId。
|
||
|
||
**级联选择接口权限:** 使用 `hasAnyPermi` 支持跨页面调用:
|
||
- `/platform/user-auth/initialized/{platformId}` - 允许 `platform:userAuth:list` 或 `platform:deviceMapping:*`
|
||
- `/platform/user-auth/{id}/projects` - 同上
|
||
|
||
### 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=cascadedSubDeviceSensorIds`,`sensorDepths` 使用 `source=cascadedSubDeviceDepths`。
|
||
- 静力水准绑定接口的 `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":"sensorIds","type":"array","source":"cascadedSubDeviceSensorIds","required":true},
|
||
{"name":"sensorDepths","type":"array","source":"cascadedSubDeviceDepths","value":[1.7,3.4,5.1,6.8],"required":true},
|
||
{"name":"holeDepth","type":"number","source":"fixed","value":6.8,"required":true},
|
||
{"name":"axisDirection","type":"string","source":"onboard_config","value":"X","required":false},
|
||
{"name":"holeElevation","type":"number","source":"fixed","value":1900,"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}
|
||
]
|
||
```
|
||
|
||
网关多子设备绑定深部位移计时,子映射表中的 monitor 顺序表示从浅到深。`sensorDepths.value` 也按浅到深配置完整孔深数组,例如 `[1.7,3.4,5.1,6.8]`。流程执行器会按当前 monitor 截取"当前节点 + 更深节点",再倒序成 DCP 要求的"最深到当前":
|
||
|
||
- 第 1 个 monitor(1.7m):`sensorDepths=[6.8,5.1,3.4,1.7]`,`sensorIds=[6.8m sensorId,5.1m sensorId,3.4m sensorId,1.7m sensorId]`。
|
||
- 第 2 个 monitor(3.4m):`sensorDepths=[6.8,5.1,3.4]`,`sensorIds=[6.8m sensorId,5.1m sensorId,3.4m sensorId]`。
|
||
- 第 3 个 monitor(5.1m):`sensorDepths=[6.8,5.1]`,`sensorIds=[6.8m sensorId,5.1m sensorId]`。
|
||
- 第 4 个 monitor(6.8m):`sensorDepths=[6.8]`,`sensorIds=[6.8m sensorId]`。
|
||
|
||
`sensorIds` 从每个子映射的 `onboard_config.sensorId` 读取;未配置时回退为子设备序列号。`holeDepth` 是整孔深度,配置为固定数字即可,不再按 monitor 拆分。
|
||
|
||
深度类字段按工程习惯使用正数,表示距孔口向下的距离;若需要平台侧高程,按 `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. 当前实现限制与注意事项
|
||
|
||
- **Token 迁移:** Token/认证已从 `PlatformInstance`(平台级)迁移到 `PlatformUserAuth`(用户级)。旧的 `result_save` 配置如果使用了 `platform_instance.*` 前缀,需要更新为 `platform_user_auth.*`。`PlatformInstance.access_token`/`token_expires_at` 字段已废弃。
|
||
- **Service 简化:** `PlatformInstanceServiceImpl` 仅保留 `selectList`;初始化、Token 管理、项目查询等功能已迁移到 `PlatformUserAuthServiceImpl`。
|
||
- **Controller 拆分:** `PlatformInstanceController` 移除了 `initialize` 和 `getProjects` 端点,这些功能已迁移到 `PlatformUserAuthController`。
|
||
- **FlowContext 变更:** `platformUserAuth` 现在是必填字段。旧的 `FlowContext(PlatformInstance)` 构造函数已移除。
|
||
- **流程手动执行移除:** `POST /platform/flow/{id}/execute` 端点已移除,流程只能通过业务入口(初始化/入网/Token 刷新)触发。
|
||
- **入网校验变更:** 入网时不再校验 `platformProjectId` 是否为空,改为校验 `platformUserAuth` 是否存在。
|
||
- 当前适配器只有 DCP。新增平台需要新增 adapter,并在 `DeviceReportTrigger.dispatchPush` 中按平台 `code` 路由。
|
||
- 文档中的"可视化配置"已覆盖平台、接口、流程、设备绑定、子映射和日志,但平台适配器路由仍需要代码扩展。
|
||
- DCP 实时推送必须配置 `push_interface_id`,未配置时不会按传感器类型自动回退路径。
|
||
- 实时推送只支持 POST JSON,流程执行支持 GET、form、JSON。
|
||
- `idempotency_key` 字段已建表,但实时推送未生成幂等键。
|
||
- `PlatformUserAuthController.getInfo` 会清空 `access_token`。
|
||
- `platform_device_mapping.platform_device_id` 对网关设备不是主要数据来源;网关 monitor 的平台 deviceId 保存在 `platform_device_sub_mapping.platform_device_id`。
|
||
- 静力水准 monitor 先到时会缓存 monitor 数据,但当前主推送分支是在 monitor 到达时读取基准点缓存;若要实现"基准点后到自动补推所有等待 monitor",需要在基准点上报分支补充扫描 monitor 缓存并推送。
|
||
- 定时推送依赖 Redis 缓存数据,若设备数据未及时写入 Redis,定时推送可能推送过期数据或无数据可推。
|
||
- 定时推送网关设备时会遍历所有子设备,大量子设备场景需关注性能和外部接口调用频率。
|
||
- 定时推送当前使用 `@Scheduled(fixedDelay)`,不支持 Cron 表达式;如需灵活调度需引入 Quartz。
|
||
- 生产环境建议定时推送间隔不低于 5 分钟,避免频繁调用外部接口。
|