静力水准跨设备推送

This commit is contained in:
zhugongping 2026-09-19 18:08:33 +08:00
parent 65abbabb3a
commit edb65ca44e
8 changed files with 241 additions and 35 deletions

View File

@ -6,15 +6,17 @@ from binascii import unhexlify
TARGET_HOST = 'localhost' # 请根据实际情况修改
TARGET_PORT = 8888 # 请根据实际情况修改
# 元数组 modbus 指令
# 元数组 modbus 指令 DEF7B23FD985 D9C6983D30F8
MODBUS_DATA_HEX = (
"7e80DCDC9891706E7e",
"0103204135317841ab8e39bf27bccd3f1fb19ac2b231bbc0b6f82040ae3207c3f9f80efa23",
"020320413b9fa441acd34dc0024a003fa2a59ac2af34a0c18e17ea413167dbc3f9c7fe6d40",
"0303204139565641ab21ddbff6af333fe26800c2aec626c18685244176ee82c3f9bd7568c8",
"040320413a0d3e41a534d3bf461ccd403d7e00c2ade1e4c0d819c441ce9ca7c3f9a4d260bf"
"7e80DEF7B23FD9857e"
"04031c41aa0c7941d78000402000220000000042b121523fb1fb373eb5668c4CDA",
"05031c419b24c741e18000400bf3910000000042a83e6840824127c08779583613",
"06031c418eb64a41cb00003ff8d8130000000042aaaa05bf95093cc090a1de5801"
)
# 重要-四川远德MQTT推送 (倾角计)
# "7e803042593632517e",
# "01033041011b7b0000000041eaafb742d19bd74513d545450dd9a4450ec53d00000000420ccf64420c74a9420c74a9c2d200009d99"
@ -28,6 +30,10 @@ MODBUS_DATA_HEX = (
# "01031c41aa0c7941d78000402000220000000042b121523fb1fb373eb5668c9cd8",
# "02031c419b24c741e18000400bf3910000000042a83e6840824127c0877958c7d0",
# "03031c418eb64a41cb00003ff8d8130000000042aaaa05bf95093cc090a1de8803"
# "04031c41aa0c7941d78000402000220000000042b121523fb1fb373eb5668c4CDA",
# "05031c419b24c741e18000400bf3910000000042a83e6840824127c08779583613",
# "06031c418eb64a41cb00003ff8d8130000000042aaaa05bf95093cc090a1de5801"
# 01 03 1c 4268 442f 41d3 0000 418b 6685 0000 0000 4026 f4ca c00d 1fd3 c2ad 2a9d 6311
# 从机地址 功能码 字节长度 2个字节 CRC校验

View File

@ -73,6 +73,14 @@ public class PlatformDeviceMappingController extends BaseController {
return success("入网成功");
}
@PreAuthorize("@ss.hasAnyPermi('platform:deviceMapping:query,platform:deviceMapping:list')")
@GetMapping("/static-level/reference-points")
@ApiOperation("查询已配置的静力水准基准点(跨网关基准点下拉框数据源)")
public AjaxResult listStaticLevelReferencePoints(@RequestParam Long platformId,
@RequestParam(required = false) Long excludeMappingId) {
return success(mappingService.listConfiguredReferencePoints(platformId, excludeMappingId));
}
// ==================== 子映射管理 ====================
@PreAuthorize("@ss.hasAnyPermi('platform:deviceMapping:query,platform:deviceMapping:list')")

View File

@ -18,6 +18,7 @@ import com.fastbee.iot.platform.flow.FlowContext;
import com.fastbee.iot.platform.model.json.*;
import com.fastbee.iot.platform.flow.PlatformFlowExecutor;
import com.fastbee.iot.platform.mapper.PlatformFlowMapper;
import com.fastbee.iot.platform.mapper.PlatformDeviceMappingMapper;
import com.fastbee.iot.platform.mapper.PlatformInterfaceMapper;
import com.fastbee.iot.platform.mapper.PlatformUserAuthMapper;
import com.fastbee.iot.platform.service.IPlatformDeviceSubMappingService;
@ -35,6 +36,7 @@ import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
@ -69,6 +71,8 @@ public class DcpPlatformAdapter {
private PlatformInterfaceMapper interfaceMapper;
@Autowired
private PlatformUserAuthMapper platformUserAuthMapper;
@Autowired
private PlatformDeviceMappingMapper mappingMapper;
@Autowired
private IPlatformInstanceService instanceService;
@ -198,7 +202,10 @@ public class DcpPlatformAdapter {
bufferService.saveReferenceData(platform.getId(), fieldName, reportSerialNumber, currentItem, reportIntervalSec);
int replayCount = replayPendingMonitorData(platform, userAuth, mapping, fieldName, currentItem,
reportIntervalSec, baseUrl, interfaceCode);
log.info("[DCP] 基准点 {} 已缓存,补推监测点 {} 条", reportSerialNumber, replayCount);
int crossCount = replaySiblingGatewayMonitors(platform, userAuth, mapping, fieldName, currentItem,
reportIntervalSec, reportSerialNumber);
log.info("[DCP] 基准点 {} 已缓存,补推监测点 {} 条(其中跨网关 {} 条)",
reportSerialNumber, replayCount + crossCount, crossCount);
return;
}
@ -294,8 +301,15 @@ public class DcpPlatformAdapter {
throw new RuntimeException("不支持的数组组包模式 arrayMode=" + mode);
}
/** 解析基准点序列号 */
/** 解析基准点序列号:跨网关配置 > 本网关基准点行 > onboard_config > 网关序列号 */
private String resolveRefSerialNumber(PlatformDeviceSubMapping subMapping, PlatformDeviceMapping mapping) {
// 跨网关基准点:前端在下拉框中选择的、属于其他网关的基准点序列号
ExtraMappingConfig extra = mapping.getExtraMappingParsed();
if (extra != null && extra.getStaticLevel() != null
&& StringUtils.hasText(extra.getStaticLevel().getReferenceSerialNumber())) {
return extra.getStaticLevel().getReferenceSerialNumber();
}
try {
PlatformDeviceSubMapping reference = subMappingService.findReference(mapping.getId());
if (reference != null && StringUtils.hasText(reference.getSubSerialNumber())) {
@ -315,17 +329,69 @@ public class DcpPlatformAdapter {
}
/**
* 基准点后到时,补推此前缓存的监测点数据。
* 基准点后到时,补推此前缓存的监测点数据(本网关 + 引用该基准点的其他网关)。
*/
private int replayPendingMonitorData(PlatformInstance platform, PlatformUserAuth userAuth,PlatformDeviceMapping mapping,
String fieldName, JSONObject referenceItem,
int reportIntervalSec, String baseUrl, String interfaceCode) {
return replayMonitorsOfMapping(platform, userAuth, mapping, fieldName, referenceItem,
reportIntervalSec, baseUrl, interfaceCode);
}
/**
* 跨网关补推:基准点上报后,补推其他网关中引用该基准点、且已缓存等待的监测点。
*
* @param refSerialNumber 本次上报的基准点序列号
*/
private int replaySiblingGatewayMonitors(PlatformInstance platform, PlatformUserAuth userAuth,
PlatformDeviceMapping refMapping, String fieldName,
JSONObject referenceItem, int reportIntervalSec,
String refSerialNumber) {
List<PlatformDeviceMapping> siblings = mappingMapper.selectList(Wrappers.<PlatformDeviceMapping>lambdaQuery()
.eq(PlatformDeviceMapping::getPlatformId, platform.getId())
.ne(PlatformDeviceMapping::getId, refMapping.getId())
.eq(PlatformDeviceMapping::getSensorType, "static_level")
.eq(PlatformDeviceMapping::getDeviceType, 1)
.eq(PlatformDeviceMapping::getNetStatus, 1));
if (siblings == null || siblings.isEmpty()) {
return 0;
}
int replayCount = 0;
for (PlatformDeviceMapping sibling : siblings) {
// 仅处理配置了跨网关基准点、且指向本次上报基准点的网关
ExtraMappingConfig extra = sibling.getExtraMappingParsed();
if (extra == null || extra.getStaticLevel() == null
|| !refSerialNumber.equals(extra.getStaticLevel().getReferenceSerialNumber())) {
continue;
}
PlatformInterface pushInterface = interfaceMapper.selectById(sibling.getPushInterfaceId());
if (pushInterface == null) {
log.warn("[DCP] 跨网关补推跳过:网关 {} 未配置推送接口", sibling.getSerialNumber());
continue;
}
String baseUrl = platform.getBaseUrl() + resolvePushPath(sibling, pushInterface);
String interfaceCode = resolveInterfaceCode(sibling.getSensorType(), pushInterface);
replayCount += replayMonitorsOfMapping(platform, userAuth, sibling, fieldName, referenceItem,
reportIntervalSec, baseUrl, interfaceCode);
}
return replayCount;
}
/**
* 补推指定网关下所有已缓存的监测点:合并为一次 HTTP 请求推送,
* 全部成功才清空缓存,失败则整批保留缓存等待下次基准点上报。
*/
private int replayMonitorsOfMapping(PlatformInstance platform, PlatformUserAuth userAuth, PlatformDeviceMapping mapping,
String fieldName, JSONObject referenceItem,
int reportIntervalSec, String baseUrl, String interfaceCode) {
List<PlatformDeviceSubMapping> subMappings = subMappingService.selectByParentId(mapping.getId());
if (subMappings == null || subMappings.isEmpty()) {
return 0;
}
int replayCount = 0;
JSONArray pushBodyArray = new JSONArray();
List<String> pushedSerials = new ArrayList<>();
for (PlatformDeviceSubMapping monitor : subMappings) {
if (monitor == null || !monitor.isMonitor() || !StringUtils.hasText(monitor.getSubSerialNumber())) {
continue;
@ -353,23 +419,32 @@ public class DcpPlatformAdapter {
JSONArray sensorData = new JSONArray();
sensorData.add(referenceItem);
sensorData.add(monitorItem);
JSONArray pushBody = buildArrayPushBody(mapping, bodyFields, fieldName,
JSONArray deviceBodyArr = buildArrayPushBody(mapping, bodyFields, fieldName,
sensorData, monitor.getPlatformDeviceId());
PlatformPushLog logEntry = createLogEntry(platform, mapping, interfaceCode, monitor.getSubSerialNumber());
doHttpPost(platform, userAuth, mapping, baseUrl, JSON.toJSONString(pushBody), logEntry);
pushLogService.asyncSave(logEntry);
if (logEntry.getStatus() != null && logEntry.getStatus() == 1) {
bufferService.removeMonitorData(platform.getId(), fieldName, monitor.getSubSerialNumber());
replayCount++;
log.info("[DCP] 基准点后到,已补推监测点 {} deviceId={}",
monitor.getSubSerialNumber(), monitor.getPlatformDeviceId());
} else {
log.warn("[DCP] 基准点后到,补推监测点 {} 失败,保留缓存等待下次基准点上报",
monitor.getSubSerialNumber());
if (!deviceBodyArr.isEmpty()) {
pushBodyArray.add(deviceBodyArr.get(0));
pushedSerials.add(monitor.getSubSerialNumber());
}
}
return replayCount;
if (pushBodyArray.isEmpty()) {
return 0;
}
PlatformPushLog logEntry = createLogEntry(platform, mapping, interfaceCode, mapping.getSerialNumber());
doHttpPost(platform, userAuth, mapping, baseUrl, JSON.toJSONString(pushBodyArray), logEntry);
pushLogService.asyncSave(logEntry);
if (logEntry.getStatus() != null && logEntry.getStatus() == 1) {
pushedSerials.forEach(serial -> bufferService.removeMonitorData(platform.getId(), fieldName, serial));
log.info("[DCP] 基准点后到,已合并补推监测点 {} 条 mappingId={} 序列号={}",
pushedSerials.size(), mapping.getId(), String.join(",", pushedSerials));
return pushedSerials.size();
}
log.warn("[DCP] 基准点后到,合并补推 {} 条失败,整批保留缓存等待下次基准点上报 mappingId={}",
pushedSerials.size(), mapping.getId());
return 0;
}
// ==================== 普通推送 ====================

View File

@ -223,7 +223,12 @@ public class PlatformPushScheduledJob {
}
for (PlatformDeviceSubMapping subMapping : subMappings) {
if (subMapping == null || subMapping.getPlatformDeviceId() == null) {
if (subMapping == null) {
continue;
}
// 基准点本身不单独推送(无平台设备ID),但仍需进入推送入口以刷新基准点缓冲,
// 否则跨网关/同网关的监测点配对时读不到新鲜基准点数据
if (subMapping.getPlatformDeviceId() == null && !subMapping.isReference()) {
continue;
}
try {

View File

@ -5,6 +5,7 @@ import com.fastbee.iot.platform.domain.PlatformDeviceMapping;
import java.util.Date;
import java.util.List;
import java.util.Map;
public interface IPlatformDeviceMappingService extends IService<PlatformDeviceMapping> {
@ -18,4 +19,11 @@ public interface IPlatformDeviceMappingService extends IService<PlatformDeviceMa
/** 更新最近已推送数据时间 */
void updateLastPushTime(Long id, Date lastPushTime);
/**
* 查询已配置的静力水准基准点列表(跨网关基准点下拉框数据源)。
* 范围:同平台下 sensorType=static_level 的网关绑定,排除 excludeMappingId 自身,
* 取其子映射中 deviceRole=reference 的行。
*/
List<Map<String, String>> listConfiguredReferencePoints(Long platformId, Long excludeMappingId);
}

View File

@ -12,6 +12,8 @@ import com.fastbee.iot.platform.mapper.PlatformDeviceMappingMapper;
import com.fastbee.iot.platform.mapper.PlatformFlowMapper;
import com.fastbee.iot.platform.mapper.PlatformInstanceMapper;
import com.fastbee.iot.platform.mapper.PlatformUserAuthMapper;
import com.fastbee.iot.platform.model.json.ExtraMappingConfig;
import com.fastbee.iot.platform.model.json.OnboardConfig;
import com.fastbee.iot.platform.service.IPlatformDeviceMappingService;
import com.fastbee.iot.platform.service.IPlatformDeviceSubMappingService;
import com.fastbee.iot.platform.service.IPlatformUserAuthService;
@ -221,13 +223,30 @@ public class PlatformDeviceMappingServiceImpl extends ServiceImpl<PlatformDevice
}
if (references.isEmpty()) {
if (staticLevel) {
throw new RuntimeException("静力水准网关入网需在子设备映射中指定一个基准点");
// 允许跨网关基准点:extra_mapping.staticLevel.referenceSerialNumber 指向其他网关的基准点
ExtraMappingConfig extra = mapping.getExtraMappingParsed();
if (extra != null && extra.getStaticLevel() != null
&& StringUtils.hasText(extra.getStaticLevel().getReferenceSerialNumber())) {
log.info("网关 {} 使用跨网关基准点 {}", mapping.getSerialNumber(),
extra.getStaticLevel().getReferenceSerialNumber());
return null;
}
throw new RuntimeException("静力水准网关入网需在子设备映射中指定一个基准点,或在扩展配置中选择跨网关基准点");
}
return null;
}
return references.get(0);
}
/** 子设备 sensorId:取 onboard_config.sensorId,缺失时回退序列号 */
private String resolveSubSensorId(PlatformDeviceSubMapping sub) {
OnboardConfig config = sub.getOnboardConfigParsed();
if (config != null && StringUtils.hasText(config.getSensorId())) {
return config.getSensorId();
}
return sub.getSubSerialNumber();
}
@Override
public void updateLastPushTime(Long id, Date lastPushTime) {
PlatformDeviceMapping mapping = new PlatformDeviceMapping();
@ -235,4 +254,35 @@ public class PlatformDeviceMappingServiceImpl extends ServiceImpl<PlatformDevice
mapping.setLastPushTime(lastPushTime);
this.updateById(mapping);
}
@Override
public List<Map<String, String>> listConfiguredReferencePoints(Long platformId, Long excludeMappingId) {
List<PlatformDeviceMapping> gateways = this.list(Wrappers.<PlatformDeviceMapping>lambdaQuery()
.eq(platformId != null, PlatformDeviceMapping::getPlatformId, platformId)
.ne(excludeMappingId != null, PlatformDeviceMapping::getId, excludeMappingId)
.eq(PlatformDeviceMapping::getSensorType, "static_level")
.eq(PlatformDeviceMapping::getDeviceType, 1));
List<Map<String, String>> result = new ArrayList<>();
for (PlatformDeviceMapping gateway : gateways) {
List<PlatformDeviceSubMapping> subs = subMappingService.selectByParentId(gateway.getId());
if (subs == null) {
continue;
}
for (PlatformDeviceSubMapping sub : subs) {
if (sub == null || !sub.isReference() || !StringUtils.hasText(sub.getSubSerialNumber())) {
continue;
}
Map<String, String> item = new java.util.LinkedHashMap<>();
item.put("referenceSerialNumber", sub.getSubSerialNumber());
item.put("referenceDeviceName", sub.getSubDeviceName());
// 供前端生成监测点入网参数 refSensorId,保持与历史数据一致
item.put("referenceSensorId", resolveSubSensorId(sub));
item.put("gatewaySerialNumber", gateway.getSerialNumber());
item.put("gatewayDeviceName", StringUtils.hasText(gateway.getDeviceName())
? gateway.getDeviceName() : gateway.getSerialNumber());
result.add(item);
}
}
return result;
}
}

View File

@ -36,3 +36,8 @@ export function listSubMappingsBatch(parentIds) {
export function syncSubMappings(parentId, data) {
return request({ url: `/platform/device-mapping/${parentId}/sub-mappings`, method: 'post', data })
}
// 查询已配置的静力水准基准点(跨网关基准点下拉框数据源)
export function listStaticLevelReferencePoints(params) {
return request({ url: '/platform/device-mapping/static-level/reference-points', method: 'get', params })
}

View File

@ -284,6 +284,17 @@
<el-form-item label="上报间隔" label-width="100px" style="margin-top:12px;margin-bottom:0">
<el-input-number v-model="form.reportIntervalSec" :min="10" :max="3600" :step="10" style="width:160px" /> 秒
</el-form-item>
<el-form-item v-if="form.sensorType === 'static_level'" label="跨网关基准点" label-width="100px" style="margin-top:12px;margin-bottom:0">
<el-select v-model="form.crossGatewayRefSerial" clearable filterable
placeholder="选择其他网关已配置的基准点" style="width:100%;max-width:420px" @change="onCrossGatewayRefChange">
<el-option v-for="refItem in referenceOptions" :key="refItem.referenceSerialNumber"
:label="`${refItem.referenceSerialNumber}(网关:${refItem.gatewayDeviceName})`"
:value="refItem.referenceSerialNumber" />
</el-select>
<div style="font-size:12px;color:#909399;margin-top:4px">
本网关子设备全部为监测点时使用:选择其他网关已配置的基准点后,本网关子设备无需再指定基准点。
</div>
</el-form-item>
<el-form-item v-if="itemFieldMappingRows.length > 0" label="数组项映射" label-width="100px" style="margin-top:12px;margin-bottom:0">
<el-table :data="itemFieldMappingRows" size="mini" border style="width:100%">
<el-table-column label="平台字段" width="140">
@ -335,7 +346,7 @@
</template>
<script>
import { listPlatformDeviceMapping, addPlatformDeviceMapping, updatePlatformDeviceMapping, delPlatformDeviceMapping, onboardDevice, listSubMappings, listSubMappingsBatch, syncSubMappings } from '@/api/platform/deviceMapping'
import { listPlatformDeviceMapping, addPlatformDeviceMapping, updatePlatformDeviceMapping, delPlatformDeviceMapping, onboardDevice, listSubMappings, listSubMappingsBatch, syncSubMappings, listStaticLevelReferencePoints } from '@/api/platform/deviceMapping'
import { listPlatformInstance } from '@/api/platform/instance'
import { getInitializedUsers, getProjectsByUserAuthId } from '@/api/platform/userAuth'
import { listPlatformInterface } from '@/api/platform/interface'
@ -363,6 +374,8 @@ export default {
subMappingRows: [],
// 网关数据映射
itemFieldMappingRows: [],
// 跨网关基准点下拉选项(static_level 专用)
referenceOptions: [],
// 子表缓存 (列表展开行使用)
subMappingCache: {},
sensorTypeDictOptions: [],
@ -467,11 +480,12 @@ export default {
this.form = {
enable: '1', deviceType: 0, pushInterfaceId: null, pushMode: 1, pushInterval: 5, reportIntervalSec: 300, deviceName: '',
platformId: null, platformUserAuthId: null, platformProjectId: null, platformProjectName: '',
deviceId: null, serialNumber: '', sensorType: '', remark: ''
deviceId: null, serialNumber: '', sensorType: '', remark: '', crossGatewayRefSerial: null
}
this.fieldMappingRows = []
this.subMappingRows = []
this.itemFieldMappingRows = []
this.referenceOptions = []
this.deviceOptions = []
this.subDeviceOptions = []
this.thingsModelOptions = []
@ -481,22 +495,27 @@ export default {
this.title = '新增设备绑定'; this.open = true
},
handleUpdate(row) {
this.form = { ...row, deviceName: row.deviceName || '', pushMode: row.pushMode || 1, pushInterval: row.pushInterval || 5, reportIntervalSec: 300 }
this.form = { ...row, deviceName: row.deviceName || '', pushMode: row.pushMode || 1, pushInterval: row.pushInterval || 5, reportIntervalSec: 300, crossGatewayRefSerial: null }
this.fieldMappingRows = this.safeParseJson(row.fieldMapping, [])
this.subMappingRows = []
this.itemFieldMappingRows = []
this.referenceOptions = []
// 解析 extra_mapping 中的数据映射配置
if (row.extraMapping) {
try {
const extra = JSON.parse(row.extraMapping)
this.form.reportIntervalSec = extra.reportIntervalSec || 300
this.itemFieldMappingRows = extra.itemFieldMappings || []
if (extra.staticLevel && extra.staticLevel.referenceSerialNumber) {
this.form.crossGatewayRefSerial = extra.staticLevel.referenceSerialNumber
}
} catch (e) { /* ignore */ }
}
// 加载该平台的接口列表和用户列表
if (row.platformId) {
this.loadInterfaces(row.platformId)
this.loadInitializedUsers(row.platformId)
this.loadReferenceOptions(row.platformId, row.id)
}
// 加载用户的项目列表
if (row.platformUserAuthId) {
@ -541,9 +560,12 @@ export default {
this.projectOptions = []
this.form.platformProjectId = null
this.form.platformProjectName = ''
this.referenceOptions = []
this.form.crossGatewayRefSerial = null
if (platformId) {
this.loadInterfaces(platformId)
this.loadInitializedUsers(platformId)
this.loadReferenceOptions(platformId, this.form.id)
}
},
loadInitializedUsers(platformId) {
@ -552,6 +574,13 @@ export default {
this.initializedUserList = res.data || []
}).catch(() => { this.initializedUserList = [] })
},
// 加载同平台其他静力水准网关已配置的基准点(跨网关基准点下拉框数据源)
loadReferenceOptions(platformId, excludeMappingId) {
if (!platformId) { this.referenceOptions = []; return }
listStaticLevelReferencePoints({ platformId, excludeMappingId: excludeMappingId || undefined }).then(res => {
this.referenceOptions = res.data || []
}).catch(() => { this.referenceOptions = [] })
},
onUserAuthChange(userAuthId) {
this.projectOptions = []
this.form.platformProjectId = null
@ -776,7 +805,17 @@ export default {
if (this.form.sensorType === 'deep_inclino') this.refreshOnboardConfig()
},
findReferenceRow(rows = this.subMappingRows) {
return (rows || []).find(r => r.deviceRole === 'reference' && r.subSerialNumber)
return (rows || []).find(r => r.deviceRole === 'reference' && r.subSerialNumber) || this.crossGatewayRefRow()
},
// 跨网关基准点(由下拉框选择,不在子表中)构造为虚拟基准点行,用于生成监测点入网参数
crossGatewayRefRow() {
if (this.form.sensorType !== 'static_level' || !this.form.crossGatewayRefSerial) return null
const option = this.referenceOptions.find(o => o.referenceSerialNumber === this.form.crossGatewayRefSerial)
const sensorId = (option && option.referenceSensorId) || this.form.crossGatewayRefSerial
return { subSerialNumber: this.form.crossGatewayRefSerial, onboardConfig: JSON.stringify({ sensorId }) }
},
onCrossGatewayRefChange() {
this.refreshSubMappingOnboardConfigs()
},
buildOnboardConfig(row, refRow) {
const config = this.safeParseJson(row.onboardConfig, {})
@ -846,9 +885,16 @@ export default {
this.$modal.msgError('只能指定一个基准点')
return null
}
if (this.form.sensorType === 'static_level' && (references.length !== 1 || monitors.length === 0)) {
this.$modal.msgError('静力水准需配置 1 个基准点和至少 1 个监测点')
return null
if (this.form.sensorType === 'static_level') {
const hasCrossRef = !!this.form.crossGatewayRefSerial
if (hasCrossRef && references.length === 1) {
this.$modal.msgError('已选择跨网关基准点,子设备中不能再指定基准点')
return null
}
if ((references.length !== 1 && !hasCrossRef) || monitors.length === 0) {
this.$modal.msgError('静力水准需配置 1 个基准点(或选择跨网关基准点)和至少 1 个监测点')
return null
}
}
if (this.form.sensorType === 'deep_inclino') {
if (monitors.length === 0) {
@ -861,7 +907,7 @@ export default {
return null
}
}
const refRow = references[0] || null
const refRow = references[0] || this.crossGatewayRefRow()
return rows.map(row => {
const onboardConfig = this.safeParseJson(this.buildOnboardConfig(row, refRow), {})
if (this.form.sensorType === 'deep_inclino' && row.deviceRole === 'monitor') {
@ -904,7 +950,10 @@ export default {
if (this.form.deviceType === 1) {
this.form.extraMapping = JSON.stringify({
reportIntervalSec: this.form.reportIntervalSec || 300,
itemFieldMappings: this.itemFieldMappingRows.filter(im => im.identifier)
itemFieldMappings: this.itemFieldMappingRows.filter(im => im.identifier),
staticLevel: this.form.crossGatewayRefSerial
? { referenceSerialNumber: this.form.crossGatewayRefSerial }
: undefined
})
} else {
this.form.extraMapping = null