20260627:接入深度位移计,单个数据值推送
This commit is contained in:
parent
4e467edb2b
commit
8c12a70df2
@ -51,12 +51,15 @@ import java.util.Map;
|
|||||||
@Component
|
@Component
|
||||||
public class DcpPlatformAdapter {
|
public class DcpPlatformAdapter {
|
||||||
|
|
||||||
private static final DateTimeFormatter ISO_OFFSET_MILLIS =
|
// 组包形势
|
||||||
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
|
// 成对
|
||||||
private static final DateTimeFormatter DATE_TIME_MILLIS =
|
private static final String ARRAY_MODE_REFERENCE_PAIR = "reference_pair";
|
||||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
|
// 单个
|
||||||
private static final DateTimeFormatter DATE_TIME_SECONDS =
|
private static final String ARRAY_MODE_SINGLE = "single";
|
||||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
||||||
|
private static final DateTimeFormatter ISO_OFFSET_MILLIS = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
|
||||||
|
private static final DateTimeFormatter DATE_TIME_MILLIS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
|
||||||
|
private static final DateTimeFormatter DATE_TIME_SECONDS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IPlatformInstanceService instanceService;
|
private IPlatformInstanceService instanceService;
|
||||||
@ -105,7 +108,8 @@ public class DcpPlatformAdapter {
|
|||||||
* 推送网关子设备上报数据到 DCP
|
* 推送网关子设备上报数据到 DCP
|
||||||
* <p>
|
* <p>
|
||||||
* deviceId 直接从子映射行获取,不再解析 JSON。
|
* deviceId 直接从子映射行获取,不再解析 JSON。
|
||||||
* reference 角色仅缓存基准数据,monitor 角色组装 [refItem, monitorItem] 推送。
|
* 数组字段由 requestSchema.arrayMode 控制组包方式:
|
||||||
|
* single 只推当前子设备,reference_pair 组装 [refItem, monitorItem] 推送。
|
||||||
*/
|
*/
|
||||||
public void pushGatewayData(PlatformInstance platform, PlatformDeviceMapping mapping,
|
public void pushGatewayData(PlatformInstance platform, PlatformDeviceMapping mapping,
|
||||||
PlatformDeviceSubMapping subMapping,
|
PlatformDeviceSubMapping subMapping,
|
||||||
@ -140,15 +144,18 @@ public class DcpPlatformAdapter {
|
|||||||
// 解析 extra_mapping 中的 itemFieldMappings 和 reportIntervalSec
|
// 解析 extra_mapping 中的 itemFieldMappings 和 reportIntervalSec
|
||||||
int reportIntervalSec = 300;
|
int reportIntervalSec = 300;
|
||||||
JSONArray itemFieldMappings = null;
|
JSONArray itemFieldMappings = null;
|
||||||
String fieldName = "sensorData";
|
String fieldName = resolveArrayFieldName(requestSchema, null);
|
||||||
|
JSONObject extra = null;
|
||||||
if (StringUtils.hasText(mapping.getExtraMapping())) {
|
if (StringUtils.hasText(mapping.getExtraMapping())) {
|
||||||
JSONObject extra = JSON.parseObject(mapping.getExtraMapping());
|
extra = JSON.parseObject(mapping.getExtraMapping());
|
||||||
reportIntervalSec = extra.getIntValue("reportIntervalSec", 300);
|
reportIntervalSec = extra.getIntValue("reportIntervalSec", 300);
|
||||||
itemFieldMappings = extra.getJSONArray("itemFieldMappings");
|
itemFieldMappings = extra.getJSONArray("itemFieldMappings");
|
||||||
if (StringUtils.hasText(extra.getString("fieldName"))) {
|
if (StringUtils.hasText(extra.getString("fieldName"))) {
|
||||||
fieldName = extra.getString("fieldName");
|
fieldName = extra.getString("fieldName");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
JSONObject arrayFieldSchema = findArrayFieldSchema(requestSchema, fieldName);
|
||||||
|
String arrayMode = resolveArrayMode(arrayFieldSchema, extra);
|
||||||
|
|
||||||
// 从 onboard_config 取 sensorId
|
// 从 onboard_config 取 sensorId
|
||||||
String sensorId = reportSerialNumber;
|
String sensorId = reportSerialNumber;
|
||||||
@ -170,6 +177,13 @@ public class DcpPlatformAdapter {
|
|||||||
|
|
||||||
JSONObject currentBodyFields = buildObjectBySchema(platform, mapping, requestSchema, reportData, fieldMappings);
|
JSONObject currentBodyFields = buildObjectBySchema(platform, mapping, requestSchema, reportData, fieldMappings);
|
||||||
|
|
||||||
|
// 单点数组推送:sensorData 中只包含当前上报子设备这一条数据。
|
||||||
|
if (ARRAY_MODE_SINGLE.equals(arrayMode)) {
|
||||||
|
pushSingleArrayData(platform, mapping, subMapping, reportSerialNumber, baseUrl,
|
||||||
|
interfaceCode, fieldName, currentItem, currentBodyFields);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (subMapping.isReference()) {
|
if (subMapping.isReference()) {
|
||||||
// 基准点上报:缓存当前基准点,并补推此前已缓存的监测点
|
// 基准点上报:缓存当前基准点,并补推此前已缓存的监测点
|
||||||
bufferService.saveReferenceData(
|
bufferService.saveReferenceData(
|
||||||
@ -216,6 +230,25 @@ public class DcpPlatformAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void pushSingleArrayData(PlatformInstance platform, PlatformDeviceMapping mapping,
|
||||||
|
PlatformDeviceSubMapping subMapping, String reportSerialNumber,
|
||||||
|
String baseUrl, String interfaceCode, String fieldName,
|
||||||
|
JSONObject currentItem, JSONObject currentBodyFields) {
|
||||||
|
String deviceId = subMapping.getPlatformDeviceId();
|
||||||
|
if (!StringUtils.hasText(deviceId)) {
|
||||||
|
log.warn("[DCP] 子设备 {} 未分配平台设备ID,跳过单点数组推送", reportSerialNumber);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JSONArray sensorData = new JSONArray();
|
||||||
|
sensorData.add(currentItem);
|
||||||
|
JSONArray pushBody = buildArrayPushBody(mapping, currentBodyFields, fieldName, sensorData, deviceId);
|
||||||
|
|
||||||
|
PlatformPushLog logEntry = createLogEntry(platform, mapping, interfaceCode, reportSerialNumber);
|
||||||
|
doHttpPost(platform, baseUrl, JSON.toJSONString(pushBody), logEntry);
|
||||||
|
pushLogService.asyncSave(logEntry);
|
||||||
|
log.info("[DCP] 子设备 {} 单点数组已推送 deviceId={}", reportSerialNumber, deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求 schema 是否包含数组字段
|
* 请求 schema 是否包含数组字段
|
||||||
*/
|
*/
|
||||||
@ -232,6 +265,33 @@ public class DcpPlatformAdapter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String resolveArrayFieldName(JSONArray requestSchema, String fallback) {
|
||||||
|
if (StringUtils.hasText(fallback)) {
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
JSONObject firstArrayField = findFirstArrayFieldSchema(requestSchema);
|
||||||
|
if (firstArrayField != null && StringUtils.hasText(firstArrayField.getString("name"))) {
|
||||||
|
return firstArrayField.getString("name");
|
||||||
|
}
|
||||||
|
return "sensorData";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveArrayMode(JSONObject arrayFieldSchema, JSONObject extra) {
|
||||||
|
String mode = null;
|
||||||
|
if (extra != null && StringUtils.hasText(extra.getString("arrayMode"))) {
|
||||||
|
mode = extra.getString("arrayMode");
|
||||||
|
} else if (arrayFieldSchema != null && StringUtils.hasText(arrayFieldSchema.getString("arrayMode"))) {
|
||||||
|
mode = arrayFieldSchema.getString("arrayMode");
|
||||||
|
}
|
||||||
|
if (!StringUtils.hasText(mode)) {
|
||||||
|
return ARRAY_MODE_REFERENCE_PAIR;
|
||||||
|
}
|
||||||
|
if (ARRAY_MODE_SINGLE.equals(mode) || ARRAY_MODE_REFERENCE_PAIR.equals(mode)) {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
throw new RuntimeException("不支持的数组组包模式 arrayMode=" + mode);
|
||||||
|
}
|
||||||
|
|
||||||
/** 解析基准点序列号 */
|
/** 解析基准点序列号 */
|
||||||
private String resolveRefSerialNumber(PlatformDeviceSubMapping subMapping, PlatformDeviceMapping mapping) {
|
private String resolveRefSerialNumber(PlatformDeviceSubMapping subMapping, PlatformDeviceMapping mapping) {
|
||||||
try {
|
try {
|
||||||
@ -633,6 +693,19 @@ public class DcpPlatformAdapter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JSONObject findFirstArrayFieldSchema(JSONArray requestSchema) {
|
||||||
|
if (requestSchema == null || requestSchema.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < requestSchema.size(); i++) {
|
||||||
|
JSONObject schemaField = requestSchema.getJSONObject(i);
|
||||||
|
if ("array".equalsIgnoreCase(schemaField.getString("type"))) {
|
||||||
|
return schemaField;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private JSONObject copyJsonObject(JSONObject source) {
|
private JSONObject copyJsonObject(JSONObject source) {
|
||||||
if (source == null || source.isEmpty()) {
|
if (source == null || source.isEmpty()) {
|
||||||
return new JSONObject();
|
return new JSONObject();
|
||||||
|
|||||||
@ -295,7 +295,7 @@ public class PlatformFlowExecutor {
|
|||||||
if (StringUtils.hasText(ctx.getCurrentMonitorSerialNumber())) {
|
if (StringUtils.hasText(ctx.getCurrentMonitorSerialNumber())) {
|
||||||
return ctx.getCurrentMonitorSerialNumber();
|
return ctx.getCurrentMonitorSerialNumber();
|
||||||
}
|
}
|
||||||
return resolveGatewaySerialNumber(ctx.getDeviceMapping());
|
return normalizeValueByType(fd.getString("type"), resolveGatewaySerialNumber(ctx.getDeviceMapping()));
|
||||||
}
|
}
|
||||||
if ("gateway_serial_number".equals(df)) {
|
if ("gateway_serial_number".equals(df)) {
|
||||||
return resolveGatewaySerialNumber(ctx.getDeviceMapping());
|
return resolveGatewaySerialNumber(ctx.getDeviceMapping());
|
||||||
|
|||||||
@ -127,13 +127,7 @@ public class PlatformDeviceMappingServiceImpl extends ServiceImpl<PlatformDevice
|
|||||||
ctx.setReferenceSubMappingOnboardConfig(reference.getOnboardConfig());
|
ctx.setReferenceSubMappingOnboardConfig(reference.getOnboardConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
flowExecutor.execute(onboardFlow, ctx);
|
flowExecutor.execute(onboardFlow, ctx);
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("[Onboard] 网关子设备 {} 入网失败: {}", monitor.getSubSerialNumber(), e.getMessage(), e);
|
|
||||||
failedMessages.add(monitor.getSubSerialNumber() + ": " + e.getMessage());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从流程上下文取回平台分配的 ID
|
// 从流程上下文取回平台分配的 ID
|
||||||
Object pointId = ctx.getFromContext("step1.id");
|
Object pointId = ctx.getFromContext("step1.id");
|
||||||
|
|||||||
@ -99,7 +99,7 @@
|
|||||||
<el-divider content-position="left">入参定义(request_schema)</el-divider>
|
<el-divider content-position="left">入参定义(request_schema)</el-divider>
|
||||||
<div class="schema-tip">
|
<div class="schema-tip">
|
||||||
定义接口需要的入参字段。参数来源使用业务化名称:
|
定义接口需要的入参字段。参数来源使用业务化名称:
|
||||||
固定值、认证参数、平台参数、上一步结果、当前设备、自动UUID、子设备传感器列表、基准点成对传感器列表、设备物模型、上报时间。
|
固定值、认证参数、平台参数、上一步结果、当前设备、自动UUID、子设备传感器列表、基准点成对传感器列表、设备物模型、上报时间。数组字段可配置组包模式。
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="requestSchemaRows" size="mini" border style="width:100%;margin-top:8px">
|
<el-table :data="requestSchemaRows" size="mini" border style="width:100%;margin-top:8px">
|
||||||
<el-table-column label="字段名" width="130">
|
<el-table-column label="字段名" width="130">
|
||||||
@ -171,6 +171,14 @@
|
|||||||
<el-checkbox v-model="scope.row.required" />
|
<el-checkbox v-model="scope.row.required" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="组包模式" width="130">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-select v-if="scope.row.type === 'array'" v-model="scope.row.arrayMode" size="mini" clearable placeholder="默认配对" style="width:100%">
|
||||||
|
<el-option label="单条" value="single" />
|
||||||
|
<el-option label="基准配对" value="reference_pair" />
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="说明" width="140">
|
<el-table-column label="说明" width="140">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-input v-model="scope.row.desc" size="mini" placeholder="字段说明" />
|
<el-input v-model="scope.row.desc" size="mini" placeholder="字段说明" />
|
||||||
@ -424,7 +432,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
addRequestField() {
|
addRequestField() {
|
||||||
this.requestSchemaRows.push({ name: '', type: 'string', source: 'fixed', value: '', field: '', contextKey: '', required: false, desc: '', itemSchema: [] })
|
this.requestSchemaRows.push({ name: '', type: 'string', source: 'fixed', value: '', field: '', contextKey: '', required: false, desc: '', arrayMode: '', itemSchema: [] })
|
||||||
},
|
},
|
||||||
addResponseField() {
|
addResponseField() {
|
||||||
this.responseSchemaRows.push({ name: '', type: 'string', path: '', desc: '' })
|
this.responseSchemaRows.push({ name: '', type: 'string', path: '', desc: '' })
|
||||||
@ -457,6 +465,7 @@ export default {
|
|||||||
// 将表格行序列化为 JSON 存入 form
|
// 将表格行序列化为 JSON 存入 form
|
||||||
this.form.requestSchema = JSON.stringify(this.requestSchemaRows.filter(r => r.name).map(r => {
|
this.form.requestSchema = JSON.stringify(this.requestSchemaRows.filter(r => r.name).map(r => {
|
||||||
const field = { name: r.name, type: r.type, source: r.source, required: !!r.required, desc: r.desc }
|
const field = { name: r.name, type: r.type, source: r.source, required: !!r.required, desc: r.desc }
|
||||||
|
if (r.type === 'array' && r.arrayMode) field.arrayMode = r.arrayMode
|
||||||
if (r.type === 'array' && r.itemSchema && r.itemSchema.length > 0) {
|
if (r.type === 'array' && r.itemSchema && r.itemSchema.length > 0) {
|
||||||
field.itemSchema = r.itemSchema.filter(s => s.name).map(s => {
|
field.itemSchema = r.itemSchema.filter(s => s.name).map(s => {
|
||||||
const item = { name: s.name, type: s.type || 'string', source: s.source || 'thingsModel', desc: s.desc }
|
const item = { name: s.name, type: s.type || 'string', source: s.source || 'thingsModel', desc: s.desc }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user