添加信息
This commit is contained in:
parent
b997cc4899
commit
406a1e9e5f
|
|
@ -100,18 +100,34 @@ public class AttributeKey<T> {
|
||||||
if (v instanceof Boolean) return (Boolean) v;
|
if (v instanceof Boolean) return (Boolean) v;
|
||||||
return Boolean.parseBoolean(v.toString());
|
return Boolean.parseBoolean(v.toString());
|
||||||
});
|
});
|
||||||
} else if (value instanceof Long || value instanceof Integer) {
|
} else if (value instanceof Integer) {
|
||||||
|
// Integer 类型优先处理
|
||||||
|
return (AttributeKey<T>) new AttributeKey<>(name, Integer.class, v -> {
|
||||||
|
if (v == null) return null;
|
||||||
|
if (v instanceof Number) return ((Number) v).intValue();
|
||||||
|
return Integer.parseInt(v.toString());
|
||||||
|
});
|
||||||
|
} else if (value instanceof Long) {
|
||||||
|
// Long 类型
|
||||||
return (AttributeKey<T>) new AttributeKey<>(name, Long.class, v -> {
|
return (AttributeKey<T>) new AttributeKey<>(name, Long.class, v -> {
|
||||||
if (v == null) return null;
|
if (v == null) return null;
|
||||||
if (v instanceof Number) return ((Number) v).longValue();
|
if (v instanceof Number) return ((Number) v).longValue();
|
||||||
return Long.parseLong(v.toString());
|
return Long.parseLong(v.toString());
|
||||||
});
|
});
|
||||||
} else if (value instanceof Double || value instanceof Float) {
|
} else if (value instanceof Double) {
|
||||||
|
// Double 类型优先处理
|
||||||
return (AttributeKey<T>) new AttributeKey<>(name, Double.class, v -> {
|
return (AttributeKey<T>) new AttributeKey<>(name, Double.class, v -> {
|
||||||
if (v == null) return null;
|
if (v == null) return null;
|
||||||
if (v instanceof Number) return ((Number) v).doubleValue();
|
if (v instanceof Number) return ((Number) v).doubleValue();
|
||||||
return Double.parseDouble(v.toString());
|
return Double.parseDouble(v.toString());
|
||||||
});
|
});
|
||||||
|
} else if (value instanceof Float) {
|
||||||
|
// Float 类型
|
||||||
|
return (AttributeKey<T>) new AttributeKey<>(name, Float.class, v -> {
|
||||||
|
if (v == null) return null;
|
||||||
|
if (v instanceof Number) return ((Number) v).floatValue();
|
||||||
|
return Float.parseFloat(v.toString());
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// 默认为 String 类型
|
// 默认为 String 类型
|
||||||
return (AttributeKey<T>) new AttributeKey<>(name, String.class, v -> v != null ? v.toString() : null);
|
return (AttributeKey<T>) new AttributeKey<>(name, String.class, v -> v != null ? v.toString() : null);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.ruoyi.device.domain.model.thingsboard;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.ruoyi.device.domain.model.thingsboard.attributes.psdk.PsdkDevice;
|
import com.ruoyi.device.domain.model.thingsboard.attributes.psdk.PsdkDevice;
|
||||||
|
import com.ruoyi.device.domain.model.thingsboard.attributes.battery.BatteryData;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -103,6 +104,11 @@ public class TelemetryKey<T> {
|
||||||
return (TelemetryKey<T>) createPsdkWidgetValuesKeyWithoutRegistering();
|
return (TelemetryKey<T>) createPsdkWidgetValuesKeyWithoutRegistering();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 特殊处理:battery 字段
|
||||||
|
if ("battery".equals(name)) {
|
||||||
|
return (TelemetryKey<T>) createBatteryKeyWithoutRegistering();
|
||||||
|
}
|
||||||
|
|
||||||
// 根据值的实际类型推断
|
// 根据值的实际类型推断
|
||||||
if (value instanceof Boolean) {
|
if (value instanceof Boolean) {
|
||||||
return (TelemetryKey<T>) new TelemetryKey<>(name, Boolean.class, v -> {
|
return (TelemetryKey<T>) new TelemetryKey<>(name, Boolean.class, v -> {
|
||||||
|
|
@ -110,18 +116,34 @@ public class TelemetryKey<T> {
|
||||||
if (v instanceof Boolean) return (Boolean) v;
|
if (v instanceof Boolean) return (Boolean) v;
|
||||||
return Boolean.parseBoolean(v.toString());
|
return Boolean.parseBoolean(v.toString());
|
||||||
});
|
});
|
||||||
} else if (value instanceof Long || value instanceof Integer) {
|
} else if (value instanceof Integer) {
|
||||||
|
// Integer 类型优先处理
|
||||||
|
return (TelemetryKey<T>) new TelemetryKey<>(name, Integer.class, v -> {
|
||||||
|
if (v == null) return null;
|
||||||
|
if (v instanceof Number) return ((Number) v).intValue();
|
||||||
|
return Integer.parseInt(v.toString());
|
||||||
|
});
|
||||||
|
} else if (value instanceof Long) {
|
||||||
|
// Long 类型
|
||||||
return (TelemetryKey<T>) new TelemetryKey<>(name, Long.class, v -> {
|
return (TelemetryKey<T>) new TelemetryKey<>(name, Long.class, v -> {
|
||||||
if (v == null) return null;
|
if (v == null) return null;
|
||||||
if (v instanceof Number) return ((Number) v).longValue();
|
if (v instanceof Number) return ((Number) v).longValue();
|
||||||
return Long.parseLong(v.toString());
|
return Long.parseLong(v.toString());
|
||||||
});
|
});
|
||||||
} else if (value instanceof Double || value instanceof Float) {
|
} else if (value instanceof Double) {
|
||||||
|
// Double 类型优先处理
|
||||||
return (TelemetryKey<T>) new TelemetryKey<>(name, Double.class, v -> {
|
return (TelemetryKey<T>) new TelemetryKey<>(name, Double.class, v -> {
|
||||||
if (v == null) return null;
|
if (v == null) return null;
|
||||||
if (v instanceof Number) return ((Number) v).doubleValue();
|
if (v instanceof Number) return ((Number) v).doubleValue();
|
||||||
return Double.parseDouble(v.toString());
|
return Double.parseDouble(v.toString());
|
||||||
});
|
});
|
||||||
|
} else if (value instanceof Float) {
|
||||||
|
// Float 类型
|
||||||
|
return (TelemetryKey<T>) new TelemetryKey<>(name, Float.class, v -> {
|
||||||
|
if (v == null) return null;
|
||||||
|
if (v instanceof Number) return ((Number) v).floatValue();
|
||||||
|
return Float.parseFloat(v.toString());
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// 默认为 String 类型
|
// 默认为 String 类型
|
||||||
return (TelemetryKey<T>) new TelemetryKey<>(name, String.class, v -> v != null ? v.toString() : null);
|
return (TelemetryKey<T>) new TelemetryKey<>(name, String.class, v -> v != null ? v.toString() : null);
|
||||||
|
|
@ -183,6 +205,55 @@ public class TelemetryKey<T> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 battery 的遥测键(不注册到 REGISTRY)
|
||||||
|
* 用于解析 Python 风格的字典字符串为 BatteryData
|
||||||
|
* 注意:不能调用 of() 方法,避免递归更新
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static TelemetryKey<BatteryData> createBatteryKeyWithoutRegistering() {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
// 配置 ObjectMapper 忽略未知字段
|
||||||
|
objectMapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
|
||||||
|
return new TelemetryKey<>(
|
||||||
|
"battery",
|
||||||
|
BatteryData.class,
|
||||||
|
value -> {
|
||||||
|
if (value == null) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 如果已经是 BatteryData 类型,直接返回
|
||||||
|
if (value instanceof BatteryData) {
|
||||||
|
return (BatteryData) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是字符串,需要处理 Python 风格的字典格式
|
||||||
|
if (value instanceof String) {
|
||||||
|
String jsonStr = (String) value;
|
||||||
|
|
||||||
|
// 将 Python 风格的字典转换为标准 JSON 格式
|
||||||
|
// 1. 将单引号替换为双引号
|
||||||
|
jsonStr = jsonStr.replace("'", "\"");
|
||||||
|
|
||||||
|
// 2. 处理 True/False/None (如果有的话)
|
||||||
|
jsonStr = jsonStr.replace(": True", ": true")
|
||||||
|
.replace(": False", ": false")
|
||||||
|
.replace(": None", ": null");
|
||||||
|
|
||||||
|
return objectMapper.readValue(jsonStr, BatteryData.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是其他对象(如 JsonNode),转换为 JSON 再解析
|
||||||
|
String json = objectMapper.writeValueAsString(value);
|
||||||
|
return objectMapper.readValue(json, BatteryData.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to parse battery: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 值解析器接口
|
* 值解析器接口
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.ruoyi.device.domain.model.thingsboard.AttributeKey;
|
import com.ruoyi.device.domain.model.thingsboard.AttributeKey;
|
||||||
import com.ruoyi.device.domain.model.thingsboard.TelemetryKey;
|
import com.ruoyi.device.domain.model.thingsboard.TelemetryKey;
|
||||||
import com.ruoyi.device.domain.model.thingsboard.attributes.psdk.PsdkDevice;
|
import com.ruoyi.device.domain.model.thingsboard.attributes.psdk.PsdkDevice;
|
||||||
|
import com.ruoyi.device.domain.model.thingsboard.attributes.battery.BatteryData;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
@ -272,6 +273,46 @@ public class DeviceTelemetry {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电池信息
|
||||||
|
* 包含电池列表、电量百分比、降落电量、剩余飞行时间、返航电量等信息
|
||||||
|
*/
|
||||||
|
public static final TelemetryKey<BatteryData> BATTERY = TelemetryKey.of(
|
||||||
|
"battery",
|
||||||
|
BatteryData.class,
|
||||||
|
value -> {
|
||||||
|
if (value == null) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 如果已经是 BatteryData 类型,直接返回
|
||||||
|
if (value instanceof BatteryData) {
|
||||||
|
return (BatteryData) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是字符串,需要处理 Python 风格的字典格式
|
||||||
|
if (value instanceof String) {
|
||||||
|
String jsonStr = (String) value;
|
||||||
|
|
||||||
|
// 将 Python 风格的字典转换为标准 JSON 格式
|
||||||
|
// 1. 将单引号替换为双引号
|
||||||
|
jsonStr = jsonStr.replace("'", "\"");
|
||||||
|
|
||||||
|
// 2. 处理 True/False/None (如果有的话)
|
||||||
|
jsonStr = jsonStr.replace(": True", ": true")
|
||||||
|
.replace(": False", ": false")
|
||||||
|
.replace(": None", ": null");
|
||||||
|
|
||||||
|
return OBJECT_MAPPER.readValue(jsonStr, BatteryData.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是其他对象(如 JsonNode),转换为 JSON 再解析
|
||||||
|
String json = OBJECT_MAPPER.writeValueAsString(value);
|
||||||
|
return OBJECT_MAPPER.readValue(json, BatteryData.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to parse battery: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 限高
|
* 限高
|
||||||
|
|
@ -343,6 +384,7 @@ public class DeviceTelemetry {
|
||||||
TEMPERATURE,
|
TEMPERATURE,
|
||||||
HUMIDITY,
|
HUMIDITY,
|
||||||
PSDK_WIDGET_VALUES,
|
PSDK_WIDGET_VALUES,
|
||||||
|
BATTERY,
|
||||||
FlightTask_Step_Code,
|
FlightTask_Step_Code,
|
||||||
Sub_Device_Online_Status,
|
Sub_Device_Online_Status,
|
||||||
Total_Flight_Sorties,
|
Total_Flight_Sorties,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue