package gecaoji;
|
import baseStation.BaseStation;
|
import set.Setsys;
|
import java.io.FileInputStream;
|
import java.io.IOException;
|
import java.util.Locale;
|
import java.util.Properties;
|
|
/**
|
* 设备信息类
|
*/
|
public class Device {
|
static Device gecaoji=new Device();
|
public static Device getGecaoji() {
|
return gecaoji;
|
}
|
|
public static void setGecaoji(Device gecaoji) {
|
Device.gecaoji = gecaoji;
|
}
|
|
static {
|
String id=Setsys.getPropertyValue("mowerId");
|
gecaoji.setMowerNumber(id);
|
}
|
// 用户标识
|
private String mowerName;
|
// 割草机名称
|
private String mowerModel;
|
// 割草机型号
|
private String mowerNumber;
|
// 割草机设备编号(唯一)
|
private String mowingWidth;
|
// 割草宽度,单位厘米
|
private String mowingHeight;
|
// 割草高度,单位厘米
|
private String baseStationNumber;
|
// 差分基站编号
|
private String baseStationCardNumber;
|
// 差分基站卡号
|
private String baseStationCoordinates;
|
// 差分基站坐标
|
private String deviceCardnumber;
|
// 设备卡号
|
private String createTime;
|
// 创建时间
|
private String GupdateTime;
|
// 割草机数据更新时间
|
private String BupdateTime;
|
// 基准站数据更新时间
|
private String realtimeLatitude;
|
// 实时纬度(度分)
|
private String realtimeLongitude;
|
// 实时经度(度分)
|
private String realtimeAltitude;
|
// 实时高程(米)
|
private String realtimeX;
|
// 实时X坐标(米)
|
private String realtimeY;
|
// 实时Y坐标(米)
|
private String realtimeSpeed;
|
// 实时速度
|
private String heading;
|
// 航向角
|
private String pitch;
|
// 俯仰角
|
private String battery;
|
// 实时电量
|
private String positioningStatus;
|
// 定位状态
|
private String satelliteCount;
|
// 卫星可数
|
private String differentialAge;
|
// 差分时间
|
|
private static final double METERS_PER_DEGREE_LAT = 111320.0d;
|
|
|
/**
|
* 初始化方法 - 从device.properties文件加载数据
|
*/
|
public void initFromProperties() { // 从属性文件初始化设备数据
|
Properties properties = new Properties();
|
try (FileInputStream input = new FileInputStream("device.properties")) {
|
// 从根目录加载device.properties文件
|
properties.load(input);
|
|
loadPropertiesInto(this, properties);
|
loadPropertiesInto(gecaoji, properties); // 保持共享实例同步
|
} catch (IOException e) {
|
// 如果文件不存在或读取失败,将所有属性设置为-1
|
System.err.println("无法读取device.properties文件: " + e.getMessage());
|
setDefaultValues();
|
}
|
}
|
|
/**
|
* 设置默认值-1
|
*/
|
private void setDefaultValues() { // 设置默认字段值
|
applyDefaults(this);
|
applyDefaults(gecaoji);
|
}
|
|
private void loadPropertiesInto(Device target, Properties properties) {
|
if (target == null) {
|
return;
|
}
|
|
target.mowerName = properties.getProperty("mowerName", "-1");
|
target.mowerModel = properties.getProperty("mowerModel", "-1");
|
target.mowerNumber = properties.getProperty("mowerNumber", "-1");
|
target.mowingWidth = properties.getProperty("mowingWidth", "-1");
|
target.mowingHeight = properties.getProperty("mowingHeight", "-1");
|
target.baseStationNumber = properties.getProperty("baseStationNumber", "-1");
|
target.baseStationCardNumber = properties.getProperty("baseStationCardNumber", "-1");
|
target.baseStationCoordinates = properties.getProperty("baseStationCoordinates", "-1");
|
target.deviceCardnumber = properties.getProperty("deviceCardnumber", "-1");
|
target.createTime = properties.getProperty("createTime", "-1");
|
target.GupdateTime = properties.getProperty("GupdateTime", "-1");
|
target.BupdateTime = properties.getProperty("BupdateTime", "-1");
|
target.realtimeLatitude = properties.getProperty("realtimeLatitude", "-1");
|
target.realtimeLongitude = properties.getProperty("realtimeLongitude", "-1");
|
target.realtimeAltitude = properties.getProperty("realtimeAltitude", "-1");
|
target.realtimeX = properties.getProperty("realtimeX", "-1");
|
target.realtimeY = properties.getProperty("realtimeY", "-1");
|
target.realtimeSpeed = properties.getProperty("realtimeSpeed", "-1");
|
target.heading = properties.getProperty("heading", "-1");
|
target.pitch = properties.getProperty("pitch", "-1");
|
target.battery = properties.getProperty("battery", "-1");
|
target.positioningStatus = properties.getProperty("positioningStatus", "-1");
|
target.satelliteCount = properties.getProperty("satelliteCount", "-1");
|
target.differentialAge = properties.getProperty("differentialAge", "-1");
|
}
|
|
private void applyDefaults(Device target) {
|
if (target == null) {
|
return;
|
}
|
|
target.mowerName = "-1";
|
target.mowerModel = "-1";
|
target.mowerNumber = "-1";
|
target.mowingWidth = "-1";
|
target.mowingHeight = "-1";
|
target.baseStationNumber = "-1";
|
target.baseStationCardNumber = "-1";
|
target.baseStationCoordinates = "-1";
|
target.deviceCardnumber = "-1";
|
target.createTime = "-1";
|
target.GupdateTime = "-1";
|
target.BupdateTime = "-1";
|
target.realtimeLatitude = "-1";
|
target.realtimeLongitude = "-1";
|
target.realtimeAltitude = "-1";
|
target.realtimeX = "-1";
|
target.realtimeY = "-1";
|
target.realtimeSpeed = "-1";
|
target.heading = "-1";
|
target.pitch = "-1";
|
target.battery = "-1";
|
target.positioningStatus = "-1";
|
target.satelliteCount = "-1";
|
target.differentialAge = "-1";
|
}
|
|
public static synchronized Device initializeActiveDevice(String mowerId) { // 根据设备ID初始化活跃设备
|
Device device = new Device();
|
gecaoji = device;
|
device.initFromProperties();
|
if (!isInvalidValue(mowerId)) {
|
device.setMowerNumber(mowerId.trim());
|
}
|
return device;
|
}
|
|
public static Device getActiveDevice() { // 获取当前活跃设备
|
return gecaoji;
|
}
|
|
|
|
/**
|
* 更新字段值
|
* @param fieldName 字段名
|
* @param value 新值
|
* @return 是否更新成功
|
*/
|
public boolean updateField(String fieldName, String value) { // 按字段更新属性值
|
switch (fieldName) {
|
case "mowerName":
|
this.mowerName = value;
|
return true;
|
case "mowerModel":
|
this.mowerModel = value;
|
return true;
|
case "mowerNumber":
|
this.mowerNumber = value;
|
return true;
|
case "mowingWidth":
|
this.mowingWidth = value;
|
return true;
|
case "mowingHeight":
|
this.mowingHeight = value;
|
return true;
|
case "baseStationNumber":
|
this.baseStationNumber = value;
|
return true;
|
case "baseStationCardNumber":
|
this.baseStationCardNumber = value;
|
return true;
|
case "baseStationCoordinates":
|
this.baseStationCoordinates = value;
|
return true;
|
case "deviceCardnumber":
|
this.deviceCardnumber = value;
|
return true;
|
case "createTime":
|
this.createTime = value;
|
return true;
|
case "GupdateTime":
|
this.GupdateTime = value;
|
return true;
|
case "BupdateTime":
|
this.BupdateTime = value;
|
return true;
|
case "realtimeLatitude":
|
this.realtimeLatitude = value;
|
return true;
|
case "realtimeLongitude":
|
this.realtimeLongitude = value;
|
return true;
|
case "realtimeAltitude":
|
this.realtimeAltitude = value;
|
return true;
|
case "realtimeX":
|
this.realtimeX = value;
|
return true;
|
case "realtimeY":
|
this.realtimeY = value;
|
return true;
|
case "realtimeSpeed":
|
this.realtimeSpeed = value;
|
return true;
|
case "heading":
|
this.heading = value;
|
return true;
|
case "pitch":
|
this.pitch = value;
|
return true;
|
case "battery":
|
this.battery = value;
|
return true;
|
case "positioningStatus":
|
this.positioningStatus = value;
|
return true;
|
case "satelliteCount":
|
this.satelliteCount = value;
|
return true;
|
case "differentialAge":
|
this.differentialAge = value;
|
return true;
|
default:
|
System.err.println("未知字段: " + fieldName);
|
return false;
|
}
|
}
|
|
public static synchronized void updateFromGNGGA(String gnggaData, String deviceId) { // 静态解析GNGGA数据更新设备
|
Device device = gecaoji;
|
if (device == null) {
|
return;
|
}
|
device.applyGNGGAUpdate(gnggaData, deviceId);
|
}
|
|
private void applyGNGGAUpdate(String gnggaData, String deviceId) { // 执行GNGGA更新逻辑
|
if (gnggaData == null) {
|
return;
|
}
|
|
String trimmed = gnggaData.trim();
|
if (trimmed.isEmpty() || !trimmed.startsWith("$GNGGA")) {
|
return;
|
}
|
|
String[] fields = trimmed.split(",");
|
if (fields.length < 21) {
|
System.err.println("GNGGA字段数量不足: " + fields.length);
|
return;
|
}
|
|
String sanitizedExpectedId = hasMeaningfulValue(deviceId) ? deviceId.trim() : null;
|
String incomingDeviceId = sanitizeField(fields, 15);
|
if (sanitizedExpectedId != null) {
|
if (!hasMeaningfulValue(incomingDeviceId) || !sanitizedExpectedId.equals(incomingDeviceId)) {
|
return;
|
}
|
}
|
if (hasMeaningfulValue(mowerNumber) && hasMeaningfulValue(incomingDeviceId) && !mowerNumber.equals(incomingDeviceId)) {
|
return;
|
}
|
if (hasMeaningfulValue(incomingDeviceId)) {
|
mowerNumber = incomingDeviceId;
|
}
|
|
String latitudeValue = sanitizeField(fields, 2);
|
String latitudeHemisphere = sanitizeField(fields, 3);
|
String longitudeValue = sanitizeField(fields, 4);
|
String longitudeHemisphere = sanitizeField(fields, 5);
|
|
realtimeLatitude = defaultIfEmpty(combineCoordinate(latitudeValue, latitudeHemisphere));
|
realtimeLongitude = defaultIfEmpty(combineCoordinate(longitudeValue, longitudeHemisphere));
|
realtimeAltitude = defaultIfEmpty(sanitizeField(fields, 9));
|
|
positioningStatus = defaultIfEmpty(sanitizeField(fields, 6));
|
satelliteCount = defaultIfEmpty(sanitizeField(fields, 7));
|
differentialAge = defaultIfEmpty(sanitizeField(fields, 13));
|
battery = defaultIfEmpty(sanitizeField(fields, 16));
|
pitch = defaultIfEmpty(sanitizeField(fields, 17));
|
realtimeSpeed = defaultIfEmpty(sanitizeField(fields, 18));
|
heading = defaultIfEmpty(sanitizeField(fields, 19));
|
GupdateTime = String.valueOf(System.currentTimeMillis());
|
|
updateRelativeCoordinates(latitudeValue, latitudeHemisphere, longitudeValue, longitudeHemisphere);
|
}
|
|
private void updateRelativeCoordinates(String latValue, String latHemisphere,
|
String lonValue, String lonHemisphere) { // 计算相对坐标
|
if (!hasMeaningfulValue(latValue) || !hasMeaningfulValue(lonValue)
|
|| !hasMeaningfulValue(latHemisphere) || !hasMeaningfulValue(lonHemisphere)) {
|
realtimeX = "-1";
|
realtimeY = "-1";
|
return;
|
}
|
|
double mowerLat = toDecimalDegrees(latValue, latHemisphere);
|
double mowerLon = toDecimalDegrees(lonValue, lonHemisphere);
|
if (Double.isNaN(mowerLat) || Double.isNaN(mowerLon)) {
|
realtimeX = "-1";
|
realtimeY = "-1";
|
return;
|
}
|
|
double[] baseLatLon = resolveBaseStationLatLon();
|
if (baseLatLon == null) {
|
realtimeX = "-1";
|
realtimeY = "-1";
|
return;
|
}
|
|
double meanLatRad = Math.toRadians((baseLatLon[0] + mowerLat) / 2.0d);
|
double deltaLatDeg = mowerLat - baseLatLon[0];
|
double deltaLonDeg = mowerLon - baseLatLon[1];
|
|
double metersPerLon = METERS_PER_DEGREE_LAT * Math.cos(meanLatRad);
|
double eastMeters = deltaLonDeg * metersPerLon;
|
double northMeters = deltaLatDeg * METERS_PER_DEGREE_LAT;
|
|
realtimeX = formatMeters(eastMeters);
|
realtimeY = formatMeters(northMeters);
|
}
|
|
private double[] resolveBaseStationLatLon() { // 解析基站经纬度
|
String coords = baseStationCoordinates;
|
if (isInvalidValue(coords)) {
|
BaseStation baseStation = new BaseStation();
|
baseStation.load();
|
coords = baseStation.getInstallationCoordinates();
|
if (!isInvalidValue(coords)) {
|
baseStationCoordinates = coords;
|
}
|
}
|
|
if (isInvalidValue(coords)) {
|
return null;
|
}
|
|
String[] parts = coords.split(",");
|
if (parts.length < 4) {
|
return null;
|
}
|
|
double baseLat = toDecimalDegrees(parts[0].trim(), parts[1].trim());
|
double baseLon = toDecimalDegrees(parts[2].trim(), parts[3].trim());
|
if (Double.isNaN(baseLat) || Double.isNaN(baseLon)) {
|
return null;
|
}
|
return new double[]{baseLat, baseLon};
|
}
|
|
private double toDecimalDegrees(String value, String hemisphere) { // 经纬度转换为十进制度
|
if (!hasMeaningfulValue(value)) {
|
return Double.NaN;
|
}
|
|
try {
|
double raw = Double.parseDouble(value);
|
double degrees = Math.floor(raw / 100d);
|
double minutes = raw - degrees * 100d;
|
double decimal = degrees + minutes / 60d;
|
|
if ("S".equalsIgnoreCase(hemisphere) || "W".equalsIgnoreCase(hemisphere)) {
|
return -decimal;
|
}
|
return decimal;
|
} catch (NumberFormatException ex) {
|
return Double.NaN;
|
}
|
}
|
|
private String combineCoordinate(String value, String hemisphere) { // 拼接坐标与方向标识
|
if (!hasMeaningfulValue(value)) {
|
return "-1";
|
}
|
if (hasMeaningfulValue(hemisphere)) {
|
return value + "," + hemisphere;
|
}
|
return value;
|
}
|
|
private String sanitizeField(String[] fields, int index) { // 清洗字段数据
|
if (fields == null || index < 0 || index >= fields.length) {
|
return "";
|
}
|
String value = fields[index];
|
return value == null ? "" : value.trim();
|
}
|
|
private String defaultIfEmpty(String value) { // 空值返还默认值
|
return hasMeaningfulValue(value) ? value : "-1";
|
}
|
|
private static boolean hasMeaningfulValue(String value) { // 判断值是否有效
|
return value != null && !value.trim().isEmpty() && !"-1".equals(value.trim());
|
}
|
|
private static boolean isInvalidValue(String value) { // 判断值是否无效
|
return value == null || value.trim().isEmpty() || "-1".equals(value.trim());
|
}
|
|
private String formatMeters(double value) { // 格式化米制数值
|
if (Double.isNaN(value) || Double.isInfinite(value)) {
|
return "-1";
|
}
|
return String.format(Locale.US, "%.3f", value);
|
}
|
|
// Getter 和 Setter 方法
|
public String getMowerName() { // 获取割草机名称
|
return mowerName;
|
}
|
|
public void setMowerName(String mowerName) { // 设置割草机名称
|
this.mowerName = mowerName;
|
}
|
|
public String getMowerModel() { // 获取割草机型号
|
return mowerModel;
|
}
|
|
public void setMowerModel(String mowerModel) { // 设置割草机型号
|
this.mowerModel = mowerModel;
|
}
|
|
public String getMowerNumber() { // 获取割草机编号
|
return mowerNumber;
|
}
|
|
public void setMowerNumber(String mowerNumber) { // 设置割草机编号
|
this.mowerNumber = mowerNumber;
|
}
|
|
public String getMowingWidth() { // 获取割草宽度
|
return mowingWidth;
|
}
|
|
public void setMowingWidth(String mowingWidth) { // 设置割草宽度
|
this.mowingWidth = mowingWidth;
|
}
|
|
public String getMowingHeight() { // 获取割草高度
|
return mowingHeight;
|
}
|
|
public void setMowingHeight(String mowingHeight) { // 设置割草高度
|
this.mowingHeight = mowingHeight;
|
}
|
|
public String getBaseStationNumber() { // 获取基站编号
|
return baseStationNumber;
|
}
|
|
public void setBaseStationNumber(String baseStationNumber) { // 设置基站编号
|
this.baseStationNumber = baseStationNumber;
|
}
|
|
public String getBaseStationCardNumber() { // 获取基站卡号
|
return baseStationCardNumber;
|
}
|
|
public void setBaseStationCardNumber(String baseStationCardNumber) { // 设置基站卡号
|
this.baseStationCardNumber = baseStationCardNumber;
|
}
|
|
public String getBaseStationCoordinates() { // 获取基站坐标
|
return baseStationCoordinates;
|
}
|
|
public void setBaseStationCoordinates(String baseStationCoordinates) { // 设置基站坐标
|
this.baseStationCoordinates = baseStationCoordinates;
|
}
|
|
public String getDeviceCardnumber() { // 获取设备卡号
|
return deviceCardnumber;
|
}
|
|
public void setDeviceCardnumber(String deviceCardnumber) { // 设置设备卡号
|
this.deviceCardnumber = deviceCardnumber;
|
}
|
|
public String getCreateTime() { // 获取创建时间
|
return createTime;
|
}
|
|
public void setCreateTime(String createTime) { // 设置创建时间
|
this.createTime = createTime;
|
}
|
|
public String getGupdateTime() { // 获取割草机更新时间
|
return GupdateTime;
|
}
|
|
public void setGupdateTime(String gupdateTime) { // 设置割草机更新时间
|
GupdateTime = gupdateTime;
|
}
|
|
public String getBupdateTime() { // 获取基站更新时间
|
return BupdateTime;
|
}
|
|
public void setBupdateTime(String bupdateTime) { // 设置基站更新时间
|
BupdateTime = bupdateTime;
|
}
|
|
public String getRealtimeLatitude() { // 获取实时纬度
|
return realtimeLatitude;
|
}
|
|
public void setRealtimeLatitude(String realtimeLatitude) { // 设置实时纬度
|
this.realtimeLatitude = realtimeLatitude;
|
}
|
|
public String getRealtimeLongitude() { // 获取实时经度
|
return realtimeLongitude;
|
}
|
|
public void setRealtimeLongitude(String realtimeLongitude) { // 设置实时经度
|
this.realtimeLongitude = realtimeLongitude;
|
}
|
|
public String getRealtimeAltitude() { // 获取实时高程
|
return realtimeAltitude;
|
}
|
|
public void setRealtimeAltitude(String realtimeAltitude) { // 设置实时高程
|
this.realtimeAltitude = realtimeAltitude;
|
}
|
|
public String getRealtimeX() { // 获取实时X坐标
|
return realtimeX;
|
}
|
|
public void setRealtimeX(String realtimeX) { // 设置实时X坐标
|
this.realtimeX = realtimeX;
|
}
|
|
public String getRealtimeY() { // 获取实时Y坐标
|
return realtimeY;
|
}
|
|
public void setRealtimeY(String realtimeY) { // 设置实时Y坐标
|
this.realtimeY = realtimeY;
|
}
|
|
public String getRealtimeSpeed() { // 获取实时速度
|
return realtimeSpeed;
|
}
|
|
public void setRealtimeSpeed(String realtimeSpeed) { // 设置实时速度
|
this.realtimeSpeed = realtimeSpeed;
|
}
|
|
public String getHeading() { // 获取航向角
|
return heading;
|
}
|
|
public void setHeading(String heading) { // 设置航向角
|
this.heading = heading;
|
}
|
|
public String getPitch() { // 获取俯仰角
|
return pitch;
|
}
|
|
public void setPitch(String pitch) { // 设置俯仰角
|
this.pitch = pitch;
|
}
|
|
public String getBattery() { // 获取实时电量
|
return battery;
|
}
|
|
public void setBattery(String battery) { // 设置实时电量
|
this.battery = battery;
|
}
|
|
public String getPositioningStatus() { // 获取定位状态
|
return positioningStatus;
|
}
|
|
public void setPositioningStatus(String positioningStatus) { // 设置定位状态
|
this.positioningStatus = positioningStatus;
|
}
|
|
public String getSatelliteCount() { // 获取卫星数量
|
return satelliteCount;
|
}
|
|
public void setSatelliteCount(String satelliteCount) { // 设置卫星数量
|
this.satelliteCount = satelliteCount;
|
}
|
|
public String getDifferentialAge() { // 获取差分时间
|
return differentialAge;
|
}
|
|
public void setDifferentialAge(String differentialAge) { // 设置差分时间
|
this.differentialAge = differentialAge;
|
}
|
|
@Override
|
public String toString() { // 输出对象信息
|
return "Device{" +
|
"mowerName='" + mowerName + '\'' +
|
", mowerModel='" + mowerModel + '\'' +
|
", mowerNumber='" + mowerNumber + '\'' +
|
", mowingWidth='" + mowingWidth + '\'' +
|
", mowingHeight='" + mowingHeight + '\'' +
|
", baseStationNumber='" + baseStationNumber + '\'' +
|
", baseStationCardNumber='" + baseStationCardNumber + '\'' +
|
", baseStationCoordinates='" + baseStationCoordinates + '\'' +
|
", deviceCardnumber='" + deviceCardnumber + '\'' +
|
", createTime='" + createTime + '\'' +
|
", GupdateTime='" + GupdateTime + '\'' +
|
", BupdateTime='" + BupdateTime + '\'' +
|
", realtimeLatitude='" + realtimeLatitude + '\'' +
|
", realtimeLongitude='" + realtimeLongitude + '\'' +
|
", realtimeAltitude='" + realtimeAltitude + '\'' +
|
", realtimeX='" + realtimeX + '\'' +
|
", realtimeY='" + realtimeY + '\'' +
|
", realtimeSpeed='" + realtimeSpeed + '\'' +
|
", heading='" + heading + '\'' +
|
", pitch='" + pitch + '\'' +
|
", battery='" + battery + '\'' +
|
", positioningStatus='" + positioningStatus + '\'' +
|
", satelliteCount='" + satelliteCount + '\'' +
|
", differentialAge='" + differentialAge + '\'' +
|
'}';
|
}
|
}
|