35 KiB
平台对接设计文档
本文档按当前项目代码反补,描述已落地的平台对接模块。相关实现主要位于:
fastbee-service/fastbee-iot-service/src/main/java/com/fastbee/iot/platformfastbee-open-api/src/main/java/com/fastbee/controller/platformyack-web/src/views/platformsql/platform-integration.sqlsql/platform-dcp-init-data.sql
1. 背景与目标
FastBee 需要将设备上报数据推送到第三方监测平台,当前已落地 DCP 结构监测 SaaS。模块目标是把“平台、接口、流程、设备绑定、字段映射、推送日志”配置化,降低后续接入新平台或调整 DCP 接口的代码改动。
当前实现采用两条主链路:
- 流程执行链路:用于平台初始化、Token 刷新、设备入网等多步骤调用。
- 实时推送链路:设备上报后异步命中平台设备绑定,由 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) 异步触发:
PlatformDeviceMappingMapper.selectBySerialNumber同时匹配直连主设备和网关子设备。- 过滤未启用的平台和绑定关系。
- 按平台
code分发,目前dcp进入DcpPlatformAdapter。 - 适配器按推送接口的
request_schema与设备绑定字段映射组装请求体。 - 检查并刷新 Token。
- 发送 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 分钟检查一次:
- 查询所有
enable='1'、push_mode=2、push_interval > 0的绑定。 - 逐条判断
now - last_push_time >= push_interval * 60 * 1000;从未推送过的立即触发。 - 从 Redis 缓存读取最新数据,按直连/网关分别调用
DcpPlatformAdapter推送。 - 推送成功后更新
last_push_time;失败时保留不变,下次继续尝试。
定时推送不经过 PlatformFlowExecutor,推送数据来自 Redis 缓存而非实时 payload,因此依赖设备数据及时更新到 Redis。
2.4 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 列表 |
cascadedSubDeviceSensorIds |
串联子设备入网:从当前 monitor 到末端 monitor 收集 sensorId,并按末端到当前倒序返回 |
cascadedSubDeviceDepths |
串联子设备入网:从配置的顺序数组中截取当前 monitor 到末端 monitor,并按末端到当前倒序返回 |
referenceSubDeviceSensorIdPairs |
收集 [基准点sensorId, 监测点sensorId] 配对列表,可能展开为多次请求 |
onboard_config 是设备入网专用的可配置入参。接口管理页或流程步骤覆盖页直接维护 value:
{"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 |
从认证 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.xxxplatform_instance.access_tokenplatform_instance.token_expires_at,值按expires_in秒数转换为 Datedevice_mapping.platform_device_iddevice_mapping.platform_point_id
3.5 platform_device_mapping 设备绑定主表
保存 FastBee 设备与第三方平台的绑定关系。
关键字段:
| 字段 | 说明 |
|---|---|
platform_id |
所属平台 |
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.6 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.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. 后端代码结构
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
└── job/
└── PlatformPushScheduledJob
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 的执行顺序:
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。
直连设备:
- 查找同平台、
flow_type=2、sensor_type匹配且启用的流程。 - 创建
FlowContext(platform, mapping, null)。 - 执行流程。
- 若主表已有
platform_device_id,将主绑定net_status改为1。
网关设备:
- 读取
platform_device_sub_mapping。 - 筛选
device_role=monitor且未入网的子设备。 - 对每个 monitor 创建独立
FlowContext:currentMonitorSerialNumber = monitor.sub_serial_numbercurrentMonitorDeviceName = monitor.sub_device_namecurrentMonitorIndex = monitor 在待入网 monitor 列表中的下标subMappingOnboardConfig = monitor.onboard_config
- 执行同一个入网流程。若绑定接口 schema 使用
source=onboard_config且value为数组,会按currentMonitorIndex拆出当前子设备的值。 - 从上下文
step1.id、step2.id取 pointId/deviceId,写回当前 monitor 子表。 - 所有 monitor 都入网后,主绑定
net_status=1。 - 若部分成功部分失败,已成功子设备会保留结果,接口返回明确失败信息。
5.3 设备上报触发
DeviceReportTrigger.onDeviceReport 使用异步线程池 FastBeeConstant.TASK.PUSH_TO_THIRD_PLATFORM_ASYNC。
遍历匹配的 PlatformDeviceMapping 时,先检查 push_mode:
push_mode=1或未配置:执行实时推送(原有行为)。push_mode=2:跳过实时推送,仅由PlatformPushScheduledJob定时推送。
匹配逻辑在 PlatformDeviceMappingMapper.xml:
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 定时推送调度器
PlatformPushScheduledJob 位于 com.fastbee.iot.platform.job,核心逻辑:
@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 从 Redis 缓存读取设备最新数据,按 device_type 分发:
- 直连设备(
device_type=0):调用DcpPlatformAdapter.pushData。 - 网关设备(
device_type=1):遍历所有子设备,逐个从 Redis 读取并调用DcpPlatformAdapter.pushGatewayData。
推送完成后调用 IPlatformDeviceMappingService.updateLastPushTime 更新 last_push_time。
数据流:
设备上报数据 → Redis 缓存更新
↓
┌──────────────────────────────────────┐
│ PlatformPushScheduledJob(每5分钟) │
│ push_mode=2 且达到时间间隔 │
│ → 从 Redis 读最新数据 │
│ → 推送到平台 │
│ → 更新 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 组装:
deviceId = platform_device_idepoch = 当前时间- 其他字段来自
field_mapping
- 普通推送请求体最终是数组:
[ {...} ]。
时间字段会统一转为带时区的 ISO-8601 毫秒格式,支持输入毫秒时间戳、秒时间戳、ISO 字符串、本地时间字符串。
5.6 网关与数组字段推送
网关推送入口:DcpPlatformAdapter.pushGatewayData。
当推送接口没有 type=array 字段时:
- 按普通子设备推送处理。
deviceId优先使用子表platform_device_id。- 字段映射仍复用主表
field_mapping。
当推送接口包含 type=array 字段时:
- 当前实现以静力水准为主要落地场景。
extra_mapping可配置:fieldName:数组字段名,默认sensorDataitemFieldMappings:数组元素物模型字段映射reportIntervalSec:缓存有效时间,默认 300 秒
- 子设备
onboard_config.sensorId作为数组元素的sensorId。 - monitor 子设备
platform_device_id作为请求体顶层deviceId。
静力水准缓存逻辑:
- 基准点
device_role=reference上报时,只缓存当前 item,不立即推送。 - 监测点
device_role=monitor上报时,查找其onboard_config.refSerialNumber对应的基准点缓存。 - 若基准点缓存新鲜,推送:
[
{
"deviceId": "监测点平台deviceId",
"sensorData": [
{"sensorId": "基准点sensorId", "height": 0.0, "temperature": 0.0, "epoch": "..."},
{"sensorId": "监测点sensorId", "height": 0.0, "temperature": 0.0, "epoch": "..."}
],
"ct": 1
}
]
- 若监测点先到或基准点缓存过期,监测点数据会写入 Redis monitor 缓存。当前代码已有 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 进入批量推送分支。该能力仍属于网关数组字段推送的一种特化形态,不单独走流程引擎。
核心行为:
- 查询当前绑定下所有
device_role=monitor的子设备,顺序以platform_device_sub_mapping返回顺序为准(深部位移场景为浅到深)。 - 当前上报子设备使用本次 payload,其余子设备从 Redis 读取缓存;读取 Redis 时使用子设备真实
product_id + sub_serial_number,避免误用网关主设备产品 ID。 - 每个 monitor 组装为一个请求体对象,
deviceId使用该 monitor 入网后回填的platform_device_id,xTotalBias、yTotalBias等主体字段使用该 monitor 自身数据。 - 每个对象中的
sensorData不是单点,而是从该 monitor 到末端 monitor 的后缀数组;深部位移中表现为“当前深度 + 更深点位”,顺序保持从浅到深。 - 最浅节点对象包含全孔从浅到深的点位数据,最深节点对象只包含自己。
- 最终一次 HTTP 请求推送整个数组。
批量推送不再从“数据推送接口”的 request_schema 读取入网参数 sensorDepths。sensorDepths、holeDepth 等仍属于深部位移入网/绑定接口配置;数据推送接口只需配置实际推送字段,例如 deviceId、sensorData、累计偏移量等。
示例请求体结构(4 个串联点,从浅到深为 A/B/C/D):
[
{
"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 日志与重试
- 流程步骤日志:
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 平台实例:
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:
[
{"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. 当前实现限制与注意事项
- 当前适配器只有 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 缓存并推送。
- 定时推送依赖 Redis 缓存数据,若设备数据未及时写入 Redis,定时推送可能推送过期数据或无数据可推。
- 定时推送网关设备时会遍历所有子设备,大量子设备场景需关注性能和外部接口调用频率。
- 定时推送当前使用
@Scheduled(fixedDelay),不支持 Cron 表达式;如需灵活调度需引入 Quartz。 - 生产环境建议定时推送间隔不低于 5 分钟,避免频繁调用外部接口。