20260611:平台对接bug修复(接口写死问题,轴力计无法推送数据)
This commit is contained in:
parent
972ebb36a9
commit
bcc0dcf37c
@ -13,7 +13,10 @@
|
|||||||
"Bash(python3 -c \"import fitz; print\\(''fitz ok''\\)\")",
|
"Bash(python3 -c \"import fitz; print\\(''fitz ok''\\)\")",
|
||||||
"Bash(python3:*)",
|
"Bash(python3:*)",
|
||||||
"Bash(grep -A 5 \"INSERT INTO \\\\`sys_menu\\\\`\" /Users/admin/IdeaProjects/fastbee/sql/yack.sql)",
|
"Bash(grep -A 5 \"INSERT INTO \\\\`sys_menu\\\\`\" /Users/admin/IdeaProjects/fastbee/sql/yack.sql)",
|
||||||
"Bash(mvn compile:*)"
|
"Bash(mvn compile:*)",
|
||||||
|
"Bash(mvn test:*)",
|
||||||
|
"Bash(mysql -hlocalhost -uroot -pfastbee fastbee -e \"SELECT id, serial_number, platform_id, device_type, enable FROM platform_device_mapping LIMIT 5;\")",
|
||||||
|
"Bash(mvn test-compile:*)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,16 +6,23 @@ from binascii import unhexlify
|
|||||||
TARGET_HOST = 'localhost' # 请根据实际情况修改
|
TARGET_HOST = 'localhost' # 请根据实际情况修改
|
||||||
TARGET_PORT = 8888 # 请根据实际情况修改
|
TARGET_PORT = 8888 # 请根据实际情况修改
|
||||||
|
|
||||||
# 你的注册指令数据
|
# 元数组 modbus 指令
|
||||||
REGISTER_DATA_HEX = "7e80D2DA725711FB7e"
|
MODBUS_DATA_HEX = (
|
||||||
|
"7e80D55746B29F687e",
|
||||||
|
"010310c07ffffe45217c3d41dfe9964140686641f4"
|
||||||
|
)
|
||||||
|
# "01031c4268442f41d30000418b6685000000004026f4cac00d1fd3c2ad2a9d6311",
|
||||||
|
# "02031c42488fd041c5800041865ab7000000003f364458c03f765ec2add9722da5",
|
||||||
|
# "03031c42ffdad541c78000421529b8000000003d5f38f94082080dc2abdf4f1f94"
|
||||||
|
# 01 03 1c 4268 442f 41d3 0000 418b 6685 0000 0000 4026 f4ca c00d 1fd3 c2ad 2a9d 6311
|
||||||
|
# 从机地址 功能码 字节长度 2个字节 CRC校验
|
||||||
|
|
||||||
|
# 在计算机中一个字节1Byte=8bit 而16进制表示法中,刚好 2位数表示一个字节 2^4=16
|
||||||
|
# Modbus 协议传输数据的基本单位是 16位的寄存器(2个字节)。
|
||||||
|
# 但是,像温度、压力这种带有小数点的数值,用 16 位(2个字节)来表示精度不够。因此,工业上通常会把 2 个连续的寄存器(即 4 个字节,32 bit) 捆绑在一起,用来表示一个 32位浮点数(Float32)
|
||||||
|
|
||||||
# 你的Modbus指令数据 01034040fb6f6141bd5555bfc82e00bd7d2000c2b0e1063e90c9983c9df308be91110041d9e3753fedf7df44789610c1d60000bf555555c477900041e1058342e1b9874f50
|
|
||||||
MODBUS_DATA_HEX = "01034040fb6f6141bd5555bfc82e00bd7d2000c2b0e1063e90c9983c9df308be91110041d9e3753fedf7df44789610c1d60000bf555555c477900041e1058342e1b9874f50"
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# 将十六进制字符串转换为字节
|
|
||||||
register_bytes = unhexlify(REGISTER_DATA_HEX)
|
|
||||||
modbus_bytes = unhexlify(MODBUS_DATA_HEX)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 创建TCP套接字
|
# 创建TCP套接字
|
||||||
@ -26,20 +33,20 @@ def main():
|
|||||||
sock.connect((TARGET_HOST, TARGET_PORT))
|
sock.connect((TARGET_HOST, TARGET_PORT))
|
||||||
print("已连接。")
|
print("已连接。")
|
||||||
|
|
||||||
|
for hex_bytes in MODBUS_DATA_HEX:
|
||||||
|
|
||||||
|
# 0.将十六进制字符串转换为字节
|
||||||
|
modbus_bytes = unhexlify(hex_bytes)
|
||||||
|
|
||||||
# 1. 发送注册包
|
# 1. 发送注册包
|
||||||
print("发送注册包...")
|
print("发送注册包...")
|
||||||
sock.sendall(register_bytes)
|
sock.sendall(modbus_bytes)
|
||||||
print("注册包已发送。")
|
print("注册包已发送。")
|
||||||
|
|
||||||
# 2. 等待0.5秒
|
# 2. 等待0.5秒
|
||||||
print("等待 0.5 秒...")
|
print("等待 0.1 秒...")
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
# 3. 发送Modbus数据包
|
|
||||||
print("发送Modbus数据包...")
|
|
||||||
sock.sendall(modbus_bytes)
|
|
||||||
print("Modbus数据包已发送。")
|
|
||||||
|
|
||||||
# (可选)接收最终响应
|
# (可选)接收最终响应
|
||||||
try:
|
try:
|
||||||
final_response = sock.recv(1024)
|
final_response = sock.recv(1024)
|
||||||
|
|||||||
@ -24,8 +24,8 @@ public enum ModbusDataType {
|
|||||||
FLOAT_CDAB("float-CDAB", "32位 浮点数(CDAB)"),
|
FLOAT_CDAB("float-CDAB", "32位 浮点数(CDAB)"),
|
||||||
BIT("bit", "位");
|
BIT("bit", "位");
|
||||||
|
|
||||||
String type;
|
final String type;
|
||||||
String msg;
|
final String msg;
|
||||||
|
|
||||||
public static ModbusDataType convert(String type) {
|
public static ModbusDataType convert(String type) {
|
||||||
for (ModbusDataType value : ModbusDataType.values()) {
|
for (ModbusDataType value : ModbusDataType.values()) {
|
||||||
|
|||||||
@ -343,13 +343,19 @@ public class CalculateUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 转32位浮点数 CDAB
|
* 转32位浮点数 CDAB
|
||||||
*
|
* 转32位浮点数 CDAB模式 (寄存器交换,字节不交换)
|
||||||
|
* 例如: 传输顺序 [Reg1: 0x4268][Reg2: 0x442F] -> 实际内存 [0x442F4268]
|
||||||
* @param bytes
|
* @param bytes
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static Float toFloat32_DCBA(byte[] bytes) {
|
public static float toFloat32_CDAB(byte[] bytes) {
|
||||||
int intValue = ((bytes[3] & 0xFF) << 24) | ((bytes[2] & 0xFF) << 16) | ((bytes[1] & 0xFF) << 8)
|
if (bytes.length < 4) throw new IllegalArgumentException("字节数组长度不足4");
|
||||||
| ((bytes[0] & 0xFF));
|
// 假设 bytes[0-1] 是第一个寄存器,bytes[2-3] 是第二个寄存器
|
||||||
|
// CDAB: 将第二个寄存器放到高16位,第一个寄存器放到低16位
|
||||||
|
int intValue = ((bytes[2] & 0xFF) << 24) |
|
||||||
|
((bytes[3] & 0xFF) << 16) |
|
||||||
|
((bytes[0] & 0xFF) << 8) |
|
||||||
|
((bytes[1] & 0xFF));
|
||||||
return Float.intBitsToFloat(intValue);
|
return Float.intBitsToFloat(intValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,8 +392,8 @@ public class CalculateUtils {
|
|||||||
case FLOAT_ABCD:
|
case FLOAT_ABCD:
|
||||||
value = CalculateUtils.toFloat32_ABCD(bytes) + "";
|
value = CalculateUtils.toFloat32_ABCD(bytes) + "";
|
||||||
break;
|
break;
|
||||||
case FLOAT_CDAB: // todo:待改枚举页面枚举
|
case FLOAT_CDAB:
|
||||||
value = CalculateUtils.toFloat32_DCBA(bytes) + "";
|
value = CalculateUtils.toFloat32_CDAB(bytes) + "";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -478,6 +484,8 @@ public class CalculateUtils {
|
|||||||
byte[] bytes2 = intToBytes2(val1);
|
byte[] bytes2 = intToBytes2(val1);
|
||||||
int i1 = bytesToInt2(bytes2);
|
int i1 = bytesToInt2(bytes2);
|
||||||
System.out.println(i1);*/
|
System.out.println(i1);*/
|
||||||
|
|
||||||
|
System.out.println("parseValue = " + parseValue("float-ABCD", "4268442f"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -141,7 +141,7 @@ public class CRC16Utils {
|
|||||||
byte[] byte8 = ByteUtils.hexToByte(crc8);
|
byte[] byte8 = ByteUtils.hexToByte(crc8);
|
||||||
int b = CRC8(byte8);
|
int b = CRC8(byte8);
|
||||||
System.out.println(b);
|
System.out.println(b);
|
||||||
float v = CalculateUtils.toFloat32_DCBA(bytes);
|
float v = CalculateUtils.toFloat32_CDAB(bytes);
|
||||||
System.out.println(v);
|
System.out.println(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,6 @@ import java.time.format.DateTimeFormatter;
|
|||||||
import java.time.format.DateTimeParseException;
|
import java.time.format.DateTimeParseException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,6 +139,14 @@ public class DcpPlatformAdapter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 无数组字段 → 简单推送,使用子设备 platformDeviceId 和主表 fieldMapping
|
||||||
|
if (!hasArrayField(requestSchema)) {
|
||||||
|
// 如果只有一个设备完全可以走
|
||||||
|
handleSubDeviceSimplePush(platform, mapping, subMapping, reportSerialNumber,
|
||||||
|
payload, pushPath, interfaceCode, requestSchema);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
JSONArray fieldMappings = parseJsonArray(mapping.getFieldMapping());
|
JSONArray fieldMappings = parseJsonArray(mapping.getFieldMapping());
|
||||||
String baseUrl = platform.getBaseUrl() + pushPath;
|
String baseUrl = platform.getBaseUrl() + pushPath;
|
||||||
|
|
||||||
@ -220,6 +227,22 @@ public class DcpPlatformAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求 schema 是否包含数组字段
|
||||||
|
*/
|
||||||
|
private boolean hasArrayField(JSONArray requestSchema) {
|
||||||
|
if (requestSchema == null || requestSchema.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < requestSchema.size(); i++) {
|
||||||
|
JSONObject field = requestSchema.getJSONObject(i);
|
||||||
|
if ("array".equalsIgnoreCase(field.getString("type"))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从子映射的 onboard_config 解析基准点序列号
|
* 从子映射的 onboard_config 解析基准点序列号
|
||||||
*/
|
*/
|
||||||
@ -266,12 +289,12 @@ public class DcpPlatformAdapter {
|
|||||||
|
|
||||||
JSONArray fieldMappings = parseJsonArray(mapping.getFieldMapping());
|
JSONArray fieldMappings = parseJsonArray(mapping.getFieldMapping());
|
||||||
if (requestSchema == null || requestSchema.isEmpty()) {
|
if (requestSchema == null || requestSchema.isEmpty()) {
|
||||||
return buildLegacyPushBody(mapping, fieldMappings, reportData);
|
return buildLegacyPushBody(mapping.getPlatformDeviceId(), fieldMappings, reportData);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject dcpData = buildObjectBySchema(platform, mapping, requestSchema, reportData, fieldMappings);
|
JSONObject dcpData = buildObjectBySchema(platform, mapping, requestSchema, reportData, fieldMappings);
|
||||||
if (dcpData.isEmpty() || !hasPayloadDrivenValue(dcpData, requestSchema)) {
|
if (dcpData.isEmpty() || hasPayloadDrivenValue(dcpData, requestSchema)) {
|
||||||
return buildLegacyPushBody(mapping, fieldMappings, reportData);
|
return buildLegacyPushBody(mapping.getPlatformDeviceId(), fieldMappings, reportData);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONArray arr = new JSONArray();
|
JSONArray arr = new JSONArray();
|
||||||
@ -279,13 +302,13 @@ public class DcpPlatformAdapter {
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object buildLegacyPushBody(PlatformDeviceMapping mapping, JSONArray fieldMappings, JSONObject reportData) {
|
private Object buildLegacyPushBody(String platformDeviceId, JSONArray fieldMappings, JSONObject reportData) {
|
||||||
if (fieldMappings == null || fieldMappings.isEmpty()) {
|
if (fieldMappings == null || fieldMappings.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject dcpData = new JSONObject();
|
JSONObject dcpData = new JSONObject();
|
||||||
dcpData.put("deviceId", mapping.getPlatformDeviceId());
|
dcpData.put("deviceId", platformDeviceId);
|
||||||
dcpData.put("epoch", nowIsoTimestamp());
|
dcpData.put("epoch", nowIsoTimestamp());
|
||||||
|
|
||||||
for (int i = 0; i < fieldMappings.size(); i++) {
|
for (int i = 0; i < fieldMappings.size(); i++) {
|
||||||
@ -310,6 +333,64 @@ public class DcpPlatformAdapter {
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关子设备简单推送(推送接口无数组字段时走此路径)
|
||||||
|
* <p>
|
||||||
|
* 使用子设备 platformDeviceId 和主表 fieldMapping 组装请求体
|
||||||
|
*/
|
||||||
|
private void handleSubDeviceSimplePush(PlatformInstance platform, PlatformDeviceMapping mapping,
|
||||||
|
PlatformDeviceSubMapping subMapping,
|
||||||
|
String reportSerialNumber, String payload,
|
||||||
|
String pushPath, String interfaceCode,
|
||||||
|
JSONArray requestSchema) {
|
||||||
|
Object body = buildSubDevicePushBody(platform, mapping, subMapping, payload, requestSchema);
|
||||||
|
if (body == null) {
|
||||||
|
log.warn("[DCP] 网关子设备 {} 字段映射结果为空,跳过推送", reportSerialNumber);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PlatformPushLog logEntry = createLogEntry(platform, mapping, interfaceCode, reportSerialNumber);
|
||||||
|
doHttpPost(platform, platform.getBaseUrl() + pushPath, JSON.toJSONString(body), logEntry);
|
||||||
|
pushLogService.asyncSave(logEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建网关子设备的简单请求体
|
||||||
|
* <p>
|
||||||
|
* 复用主表 fieldMapping 进行物模型字段映射,deviceId 取自子映射行
|
||||||
|
*/
|
||||||
|
private Object buildSubDevicePushBody(PlatformInstance platform, PlatformDeviceMapping mapping,
|
||||||
|
PlatformDeviceSubMapping subMapping, String payload,
|
||||||
|
JSONArray requestSchema) {
|
||||||
|
JSONObject reportData = parsePayloadToMap(payload);
|
||||||
|
if (reportData == null || reportData.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 平台设备ID
|
||||||
|
String platformDeviceId = StringUtils.hasText(subMapping.getPlatformDeviceId())
|
||||||
|
? subMapping.getPlatformDeviceId() : mapping.getPlatformDeviceId();
|
||||||
|
|
||||||
|
JSONArray fieldMappings = parseJsonArray(mapping.getFieldMapping());
|
||||||
|
if (requestSchema == null || requestSchema.isEmpty()) {
|
||||||
|
return buildLegacyPushBody(platformDeviceId, fieldMappings, reportData);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject dcpData = buildObjectBySchema(platform, mapping, requestSchema, reportData, fieldMappings);
|
||||||
|
if (dcpData.isEmpty() || hasPayloadDrivenValue(dcpData, requestSchema)) {
|
||||||
|
|
||||||
|
return buildLegacyPushBody(platformDeviceId, fieldMappings, reportData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 覆写 deviceId 为子设备的平台 ID
|
||||||
|
if (StringUtils.hasText(subMapping.getPlatformDeviceId())) {
|
||||||
|
dcpData.put("deviceId", subMapping.getPlatformDeviceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONArray arr = new JSONArray();
|
||||||
|
arr.add(dcpData);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== 构建辅助 ====================
|
// ==================== 构建辅助 ====================
|
||||||
|
|
||||||
private JSONArray buildArrayPushBody(PlatformDeviceMapping mapping, JSONObject bodyFields,
|
private JSONArray buildArrayPushBody(PlatformDeviceMapping mapping, JSONObject bodyFields,
|
||||||
@ -505,7 +586,7 @@ public class DcpPlatformAdapter {
|
|||||||
|
|
||||||
private boolean hasPayloadDrivenValue(JSONObject body, JSONArray requestSchema) {
|
private boolean hasPayloadDrivenValue(JSONObject body, JSONArray requestSchema) {
|
||||||
if (body == null || body.isEmpty() || requestSchema == null || requestSchema.isEmpty()) {
|
if (body == null || body.isEmpty() || requestSchema == null || requestSchema.isEmpty()) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < requestSchema.size(); i++) {
|
for (int i = 0; i < requestSchema.size(); i++) {
|
||||||
JSONObject schemaField = requestSchema.getJSONObject(i);
|
JSONObject schemaField = requestSchema.getJSONObject(i);
|
||||||
@ -514,11 +595,11 @@ public class DcpPlatformAdapter {
|
|||||||
}
|
}
|
||||||
if (usesPayload(schemaField.getString("source"))
|
if (usesPayload(schemaField.getString("source"))
|
||||||
&& body.containsKey(schemaField.getString("name"))) {
|
&& body.containsKey(schemaField.getString("name"))) {
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean usesPayload(String source) {
|
private boolean usesPayload(String source) {
|
||||||
return isThingsModelSource(source) || "context".equals(source) || "ts".equals(source);
|
return isThingsModelSource(source) || "context".equals(source) || "ts".equals(source);
|
||||||
@ -681,8 +762,6 @@ public class DcpPlatformAdapter {
|
|||||||
|
|
||||||
// ==================== HTTP 执行 ====================
|
// ==================== HTTP 执行 ====================
|
||||||
|
|
||||||
// ==================== HTTP 执行 ====================
|
|
||||||
|
|
||||||
private void doHttpPost(PlatformInstance platform, String url, String bodyStr, PlatformPushLog logEntry) {
|
private void doHttpPost(PlatformInstance platform, String url, String bodyStr, PlatformPushLog logEntry) {
|
||||||
long startMs = System.currentTimeMillis();
|
long startMs = System.currentTimeMillis();
|
||||||
logEntry.setRequestUrl(url);
|
logEntry.setRequestUrl(url);
|
||||||
@ -717,10 +796,9 @@ public class DcpPlatformAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlatformPushLog createLogEntry(PlatformInstance platform, PlatformDeviceMapping mapping, String ifaceCode) {
|
/**
|
||||||
return createLogEntry(platform, mapping, ifaceCode, mapping.getSerialNumber());
|
* 创建记录日志
|
||||||
}
|
*/
|
||||||
|
|
||||||
private PlatformPushLog createLogEntry(PlatformInstance platform, PlatformDeviceMapping mapping,
|
private PlatformPushLog createLogEntry(PlatformInstance platform, PlatformDeviceMapping mapping,
|
||||||
String ifaceCode, String serialNumber) {
|
String ifaceCode, String serialNumber) {
|
||||||
PlatformPushLog logEntry = new PlatformPushLog();
|
PlatformPushLog logEntry = new PlatformPushLog();
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package com.fastbee.iot.platform.service.impl;
|
package com.fastbee.iot.platform.service.impl;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.fastbee.iot.platform.domain.PlatformDeviceSubMapping;
|
import com.fastbee.iot.platform.domain.PlatformDeviceSubMapping;
|
||||||
import com.fastbee.iot.platform.mapper.PlatformDeviceSubMappingMapper;
|
import com.fastbee.iot.platform.mapper.PlatformDeviceSubMappingMapper;
|
||||||
|
|||||||
@ -129,7 +129,6 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
@Resource
|
@Resource
|
||||||
private IPAddressService ipAddressService;
|
private IPAddressService ipAddressService;
|
||||||
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private EventLogMapper eventLogMapper;
|
private EventLogMapper eventLogMapper;
|
||||||
@Resource
|
@Resource
|
||||||
@ -464,6 +463,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
// 删除网关绑定子设备关系
|
// 删除网关绑定子设备关系
|
||||||
if (DeviceType.GATEWAY.getCode() == device.getDeviceType()) {
|
if (DeviceType.GATEWAY.getCode() == device.getDeviceType()) {
|
||||||
subGatewayMapper.deleteGatewayByGwDeviceId(deviceId);
|
subGatewayMapper.deleteGatewayByGwDeviceId(deviceId);
|
||||||
|
// todo 需要删子设备
|
||||||
}
|
}
|
||||||
// 删除modbus轮询指令
|
// 删除modbus轮询指令
|
||||||
String keyModbus = RedisKeyBuilder.buildModbusRuntimeCacheKey(device.getSerialNumber());
|
String keyModbus = RedisKeyBuilder.buildModbusRuntimeCacheKey(device.getSerialNumber());
|
||||||
|
|||||||
@ -155,7 +155,7 @@
|
|||||||
<div v-if="form.deviceType === 1" class="array-fields-section">
|
<div v-if="form.deviceType === 1" class="array-fields-section">
|
||||||
<div class="section-label">子设备映射</div>
|
<div class="section-label">子设备映射</div>
|
||||||
<div class="schema-tip" style="margin-bottom:8px">
|
<div class="schema-tip" style="margin-bottom:8px">
|
||||||
配置网关下参与上报的子设备,指定基准点和监测点角色。入网时每个监测点独立创建测点和绑定。
|
配置网关下参与上报的子设备,指定基准点(不会单独推送,与基准点一起推送)和监测点角色。入网时每个监测点独立创建测点和绑定。
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="subMappingRows" size="mini" border style="width:100%">
|
<el-table :data="subMappingRows" size="mini" border style="width:100%">
|
||||||
<el-table-column label="子设备编号" min-width="160">
|
<el-table-column label="子设备编号" min-width="160">
|
||||||
@ -431,29 +431,35 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
onPushInterfaceChange(interfaceId) {
|
onPushInterfaceChange(interfaceId) {
|
||||||
// 从推送接口的 requestSchema 提取字段作为数据映射模板
|
// 从推送接口的 requestSchema 提取字段作为数据映射模板,切换接口时全量刷新
|
||||||
if (!interfaceId) return
|
if (!interfaceId) return
|
||||||
const iface = this.interfaceOptions.find(x => x.id === interfaceId)
|
const iface = this.interfaceOptions.find(x => x.id === interfaceId)
|
||||||
if (!iface || !iface.requestSchema) return
|
if (!iface || !iface.requestSchema) return
|
||||||
try {
|
try {
|
||||||
const schema = JSON.parse(iface.requestSchema)
|
const schema = JSON.parse(iface.requestSchema)
|
||||||
|
const oldFields = this.fieldMappingRows || []
|
||||||
|
const oldItemFields = this.itemFieldMappingRows || []
|
||||||
|
|
||||||
// 网关设备:提取 array 类型字段的 itemSchema 作为数组项映射模板
|
// 标量字段映射(body 层):所有设备类型都提取,同名平台字段保留已选标识
|
||||||
const arrayField = schema.find(f => f.type === 'array' && f.itemSchema && f.itemSchema.length > 0)
|
|
||||||
if (arrayField && this.form.deviceType === 1) {
|
|
||||||
const identifierFields = (arrayField.itemSchema || []).filter(s => s.source === 'thingsModel' || s.source === 'identifier')
|
|
||||||
if (identifierFields.length > 0 && this.itemFieldMappingRows.length === 0) {
|
|
||||||
this.itemFieldMappingRows = identifierFields.map(s => ({ platformField: s.name, identifier: '' }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 直连设备:提取标量字段(非 array)作为字段映射模板
|
|
||||||
if (this.form.deviceType !== 1) {
|
|
||||||
const scalarFields = schema.filter(f =>
|
const scalarFields = schema.filter(f =>
|
||||||
f.type !== 'array' && (f.source === 'thingsModel' || f.source === 'identifier')
|
f.type !== 'array' && (f.source === 'thingsModel' || f.source === 'identifier')
|
||||||
)
|
)
|
||||||
if (scalarFields.length > 0 && this.fieldMappingRows.length === 0) {
|
this.fieldMappingRows = scalarFields.map(s => ({
|
||||||
this.fieldMappingRows = scalarFields.map(s => ({ identifier: '', platformField: s.name }))
|
identifier: (oldFields.find(r => r.platformField === s.name) || {}).identifier || '',
|
||||||
|
platformField: s.name
|
||||||
|
}))
|
||||||
|
|
||||||
|
// 网关设备额外提取数组字段的 itemSchema
|
||||||
|
if (this.form.deviceType === 1) {
|
||||||
|
const arrayField = schema.find(f => f.type === 'array' && f.itemSchema && f.itemSchema.length > 0)
|
||||||
|
if (arrayField) {
|
||||||
|
const identifierFields = (arrayField.itemSchema || []).filter(s => s.source === 'thingsModel' || s.source === 'identifier')
|
||||||
|
this.itemFieldMappingRows = identifierFields.map(s => ({
|
||||||
|
platformField: s.name,
|
||||||
|
identifier: (oldItemFields.find(r => r.platformField === s.name) || {}).identifier || ''
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
this.itemFieldMappingRows = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) { /* ignore */ }
|
} catch (e) { /* ignore */ }
|
||||||
@ -514,6 +520,10 @@ export default {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
this.subDeviceOptions = Array.from(optionMap.values())
|
this.subDeviceOptions = Array.from(optionMap.values())
|
||||||
|
// 新增模式下,根据是否有子设备自动推断设备类型,减少人工选择出错
|
||||||
|
if (!this.form.id) {
|
||||||
|
this.form.deviceType = this.subDeviceOptions.length > 0 ? 1 : 0
|
||||||
|
}
|
||||||
// 网关设备且子映射为空时,自动预填所有子设备,第一个为基准点
|
// 网关设备且子映射为空时,自动预填所有子设备,第一个为基准点
|
||||||
if (this.form.deviceType === 1 && this.subMappingRows.length === 0 && this.subDeviceOptions.length > 0) {
|
if (this.form.deviceType === 1 && this.subMappingRows.length === 0 && this.subDeviceOptions.length > 0) {
|
||||||
this.subMappingRows = this.subDeviceOptions.map((device, idx) => {
|
this.subMappingRows = this.subDeviceOptions.map((device, idx) => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user