liusuyi
2024-10-24 e9ad2e18fcff1e6adcf4dd624a8ec02f9cb6c13e
增加protobuf映射实体解析数据
22 files added
8 files modified
1 files renamed
10655 ■■■■■ changed files
ard-work/src/main/java/com/ard/tianyu/controller/UavController.java 31 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/cache/UavSignalInfoCache.java 32 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/cache/UavStateCache.java 31 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/cache/UavTelemetryDataCache.java 33 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/converter/UavSignalInfoConverter.java 19 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/converter/UavStateConverter.java 139 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/converter/UavTelemetryDataConverter.java 20 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/init/UavInitInfo.java 16 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/signal/SignalInfo.java 74 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/state/AvoidanceData.java 23 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/state/BatteryState.java 19 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/state/BatteryStateInfo.java 30 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/state/CameraState.java 21 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/state/FlightControllerState.java 23 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/state/HmsAlarmData.java 11 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/state/MissionState.java 22 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/state/PointData.java 10 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/state/PtzState.java 12 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/state/UavState.java 24 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/model/dto/telemetry/TelemetryData.java 46 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/netty/command/ControlAngleCommand.java 4 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/netty/command/DroneReadyNotificationCommand.java 31 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/netty/command/SignalInfoCommand.java 25 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/netty/command/UavInitInfoCommand.java 37 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/netty/command/UavStateCommand.java 3 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/netty/command/UavTelemetryDataCommand.java 7 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolDecoder.java 43 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/netty/protobuf/TelemetryDataBuf-new.proto 11 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/netty/protobuf/TelemetryDataPB.java 9773 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/service/ITyService.java 19 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java 66 ●●●●● patch | view | raw | blame | history
ard-work/src/main/java/com/ard/tianyu/controller/UavController.java
@@ -4,6 +4,9 @@
import com.ard.tianyu.model.dto.BoxHistoryDTO;
import com.ard.tianyu.model.dto.BoxPhotosDTO;
import com.ard.tianyu.model.dto.BoxSettingsDTO;
import com.ard.tianyu.model.dto.signal.SignalInfo;
import com.ard.tianyu.model.dto.state.UavState;
import com.ard.tianyu.model.dto.telemetry.TelemetryData;
import com.ard.tianyu.model.receiver.BoxHistoryReceiver;
import com.ard.tianyu.model.receiver.BoxPhotosReceiver;
import com.ard.tianyu.model.receiver.BoxInfoReceiver;
@@ -63,22 +66,46 @@
        List<BoxPhotosReceiver> boxPhotos = tyService.getBoxPhotos(boxPhotosDTO);
        return AjaxResult.success(boxPhotos);
    }
    @ApiOperation("修改云盒设置")
    @PostMapping("/updateBoxSettings")
    public AjaxResult updateBoxSettings(@RequestBody BoxSettingsDTO boxSettingsDTO) {
        Boolean state = tyService.updateBoxSettings(boxSettingsDTO);
        return AjaxResult.success(state);
    }
    @ApiOperation("无人机控制订阅")
    @GetMapping("/uavControlSubscribe")
    public AjaxResult uavControlSubscribe(String boxSn) {
        tyService.uavControlSubscribe(boxSn);
        return AjaxResult.success();
    }
    @ApiOperation("云台转动(基于角度)")
    @GetMapping("/controlAngle")
    public AjaxResult controlAngle(String boxSn) {
        tyService.controlAngle(boxSn);
    public AjaxResult controlAngle(String boxSn,Integer actionId,Integer rotationAngle) {
        tyService.controlAngle(boxSn,actionId,rotationAngle);
        return AjaxResult.success();
    }
    @ApiOperation("获取无人机状态")
    @GetMapping("/getUavState")
    public AjaxResult getUavState(String boxSn) {
        UavState uavState = tyService.getUavState(boxSn);
        return AjaxResult.success(uavState);
    }
    @ApiOperation("获取无人机遥测数据")
    @GetMapping("/getUavTelemetryData")
    public AjaxResult getUavTelemetryData(String boxSn) {
        TelemetryData telemetryData = tyService.getUavTelemetryData(boxSn);
        return AjaxResult.success(telemetryData);
    }
    @ApiOperation("获取无人机信道质量数据")
    @GetMapping("/getSignalInfo")
    public AjaxResult getSignalInfo(String boxSn) {
        SignalInfo signalInfo = tyService.getSignalInfo(boxSn);
        return AjaxResult.success(signalInfo);
    }
}
ard-work/src/main/java/com/ard/tianyu/model/cache/UavSignalInfoCache.java
New file
@@ -0,0 +1,32 @@
package com.ard.tianyu.model.cache;
import com.ard.tianyu.model.dto.signal.SignalInfo;
import java.util.concurrent.ConcurrentHashMap;
/**
 * 无人机遥测数据缓存
 *
 * @author 刘苏义
 * @date 2024/10/24 8:55
 */
public class UavSignalInfoCache {
    // 使用 ConcurrentHashMap 来缓存无人机信道质量数据,key 是 boxSn(无人机序列号)
    private static final ConcurrentHashMap<String, SignalInfo> uavSignalInfoCache = new ConcurrentHashMap<>();
    // 存储无人机信道质量数据到缓存
    public static void putUavSignalInfoCache(SignalInfo signalInfo) {
        uavSignalInfoCache.put(signalInfo.getBoxSn(), signalInfo);
    }
    // 从缓存中获取信道质量数据
    public static SignalInfo getUavSignalInfo(String boxSn) {
        return uavSignalInfoCache.get(boxSn);
    }
    // 删除缓存中的信道质量数据
    public static void removeUavSignalInfo(String boxSn) {
        uavSignalInfoCache.remove(boxSn);
    }
}
ard-work/src/main/java/com/ard/tianyu/model/cache/UavStateCache.java
New file
@@ -0,0 +1,31 @@
package com.ard.tianyu.model.cache;
import com.ard.tianyu.model.dto.state.UavState;
import java.util.concurrent.ConcurrentHashMap;
/**
 * 无人机状态缓存
 *
 * @author 刘苏义
 * @date 2024/10/24 8:55
 */
public class UavStateCache {
    // 使用 ConcurrentHashMap 来缓存无人机状态数据,key 是 boxSn(无人机序列号)
    private static final ConcurrentHashMap<String, UavState> uavStateCache = new ConcurrentHashMap<>();
    // 存储无人机状态数据到缓存
    public static void putUavState(UavState uavState) {
        uavStateCache.put(uavState.getBoxSn(), uavState);
    }
    // 从缓存中获取无人机状态数据
    public static UavState getUavState(String boxSn) {
        return uavStateCache.get(boxSn);
    }
    // 删除缓存中的无人机状态数据
    public static void removeUavState(String boxSn) {
        uavStateCache.remove(boxSn);
    }
}
ard-work/src/main/java/com/ard/tianyu/model/cache/UavTelemetryDataCache.java
New file
@@ -0,0 +1,33 @@
package com.ard.tianyu.model.cache;
import com.ard.tianyu.model.dto.state.UavState;
import com.ard.tianyu.model.dto.telemetry.TelemetryData;
import java.util.concurrent.ConcurrentHashMap;
/**
 * 无人机遥测数据缓存
 *
 * @author 刘苏义
 * @date 2024/10/24 8:55
 */
public class UavTelemetryDataCache {
    // 使用 ConcurrentHashMap 来缓存无人机遥测数据,key 是 boxSn(无人机序列号)
    private static final ConcurrentHashMap<String, TelemetryData> uavTelemetryDataCache = new ConcurrentHashMap<>();
    // 存储无人机遥测数据到缓存
    public static void putUavTelemetryData(TelemetryData telemetryData) {
        uavTelemetryDataCache.put(telemetryData.getBoxSn(), telemetryData);
    }
    // 从缓存中获取无人机遥测数据
    public static TelemetryData getUavTelemetryData(String boxSn) {
        return uavTelemetryDataCache.get(boxSn);
    }
    // 删除缓存中的无人机遥测数据
    public static void removeUavTelemetryData(String boxSn) {
        uavTelemetryDataCache.remove(boxSn);
    }
}
ard-work/src/main/java/com/ard/tianyu/model/dto/converter/UavSignalInfoConverter.java
New file
@@ -0,0 +1,19 @@
package com.ard.tianyu.model.dto.converter;
import com.ard.tianyu.model.dto.signal.SignalInfo;
import com.ard.tianyu.netty.protobuf.TelemetryDataPB;
import org.springframework.beans.BeanUtils;
/**
 * SignalInfoConverter
 *
 * @author liusuyi
 * @date 2024年10月24日10:38
 **/
public class UavSignalInfoConverter {
    public static SignalInfo convertProtoToEntity(TelemetryDataPB.SignalInfo proto) {
        SignalInfo signalInfo = new SignalInfo();
        BeanUtils.copyProperties(proto, signalInfo);
        return signalInfo;
    }
}
ard-work/src/main/java/com/ard/tianyu/model/dto/converter/UavStateConverter.java
New file
@@ -0,0 +1,139 @@
package com.ard.tianyu.model.dto.converter;
import com.ard.tianyu.model.dto.state.*;
import com.ard.tianyu.netty.protobuf.TelemetryDataPB;
import org.springframework.beans.BeanUtils;
import java.util.List;
import java.util.stream.Collectors;
public class UavStateConverter {
    // 将 Protobuf UavState 转换为 Java 实体类 UavState
    public static UavState convertProtoToEntity(TelemetryDataPB.UavState protobufUavState) {
        UavState uavState = new UavState();
        // 复制简单字段
        uavState.setBoxSn(protobufUavState.getBoxSn());
        // 处理嵌套的 FlightControllerState
        if (protobufUavState.hasFlightControllerState()) {
            uavState.setFlightControllerState(convertFlightControllerState(protobufUavState.getFlightControllerState()));
        }
        // 处理嵌套的 BatteryState
        if (protobufUavState.hasBatteryState()) {
            uavState.setBatteryState(convertBatteryState(protobufUavState.getBatteryState()));
        }
        // 处理嵌套的 PtzState
        if (protobufUavState.hasPtzState()) {
            uavState.setPtzState(convertPtzState(protobufUavState.getPtzState()));
        }
        // 处理嵌套的 CameraState
        if (protobufUavState.hasCameraState()) {
            uavState.setCameraState(convertCameraState(protobufUavState.getCameraState()));
        }
        // 处理嵌套的 MissionState
        if (protobufUavState.hasMissionState()) {
            uavState.setMissionState(convertMissionState(protobufUavState.getMissionState()));
        }
        // 处理 AvoidanceData
        if (protobufUavState.hasAvoidanceData()) {
            uavState.setAvoidanceData(convertAvoidanceData(protobufUavState.getAvoidanceData()));
        }
        // 处理 List<HmsAlarmData>
        List<HmsAlarmData> hmsAlarmDataList = protobufUavState.getHmsAlarmDataList().stream()
                .map(UavStateConverter::convertHmsAlarmData)
                .collect(Collectors.toList());
        uavState.setHmsAlarmData(hmsAlarmDataList);
        return uavState;
    }
    // 其他转换方法如下:
    // 处理 BatteryState 逻辑
    public static BatteryState convertBatteryState(TelemetryDataPB.BatteryState protobufBatteryState) {
        BatteryState batteryState = new BatteryState();
        // 复制简单字段
        batteryState.setBatteryNum(protobufBatteryState.getBatteryNum());
        batteryState.setBatteryPower(protobufBatteryState.getBatteryPower());
        batteryState.setBatteryVoltage(protobufBatteryState.getBatteryVoltage());
        // 处理嵌套的 BatteryStateInfo
        if (protobufBatteryState.hasFirstBatteryInfo()) {
            batteryState.setFirstBatteryInfo(convertBatteryStateInfo(protobufBatteryState.getFirstBatteryInfo()));
        }
        if (protobufBatteryState.hasSecondBatteryInfo()) {
            batteryState.setSecondBatteryInfo(convertBatteryStateInfo(protobufBatteryState.getSecondBatteryInfo()));
        }
        return batteryState;
    }
    // 处理 BatteryStateInfo 逻辑
    public static BatteryStateInfo convertBatteryStateInfo(TelemetryDataPB.BatteryStateInfo protobufBatteryStateInfo) {
        BatteryStateInfo batteryStateInfo = new BatteryStateInfo();
        BeanUtils.copyProperties(protobufBatteryStateInfo, batteryStateInfo);
        return batteryStateInfo;
    }
    // 处理 FlightControllerState 逻辑
    public static FlightControllerState convertFlightControllerState(TelemetryDataPB.FlightControllerState proto) {
        FlightControllerState flightControllerState = new FlightControllerState();
        // 处理 PointData(起飞点和返航点)
        if (proto.hasStartPoint()) {
            flightControllerState.setStartPoint(convertPointData(proto.getStartPoint()));
        }
        if (proto.hasHomePoint()) {
            flightControllerState.setHomePoint(convertPointData(proto.getHomePoint()));
        }
        BeanUtils.copyProperties(proto, flightControllerState);
        return flightControllerState;
    }
    // 处理 PointData 逻辑
    public static PointData convertPointData(TelemetryDataPB.PointData protoPoint) {
        PointData pointData = new PointData();
        pointData.setLat(protoPoint.getLat());
        pointData.setLng(protoPoint.getLng());
        return pointData;
    }
    public static PtzState convertPtzState(TelemetryDataPB.PtzState proto) {
        PtzState ptzState = new PtzState();
        BeanUtils.copyProperties(proto, ptzState);
        return ptzState;
    }
    public static CameraState convertCameraState(TelemetryDataPB.CameraState proto) {
        CameraState cameraState = new CameraState();
        BeanUtils.copyProperties(proto, cameraState);
        return cameraState;
    }
    public static MissionState convertMissionState(TelemetryDataPB.MissionState proto) {
        MissionState missionState = new MissionState();
        BeanUtils.copyProperties(proto, missionState);
        return missionState;
    }
    public static AvoidanceData convertAvoidanceData(TelemetryDataPB.AvoidanceData proto) {
        AvoidanceData avoidanceData = new AvoidanceData();
        BeanUtils.copyProperties(proto, avoidanceData);
        return avoidanceData;
    }
    public static HmsAlarmData convertHmsAlarmData(TelemetryDataPB.HmsAlarmData proto) {
        HmsAlarmData hmsAlarmData = new HmsAlarmData();
        BeanUtils.copyProperties(proto, hmsAlarmData);
        return hmsAlarmData;
    }
}
ard-work/src/main/java/com/ard/tianyu/model/dto/converter/UavTelemetryDataConverter.java
New file
@@ -0,0 +1,20 @@
package com.ard.tianyu.model.dto.converter;
import com.ard.tianyu.model.dto.state.UavState;
import com.ard.tianyu.model.dto.telemetry.TelemetryData;
import com.ard.tianyu.netty.protobuf.TelemetryDataPB;
import org.springframework.beans.BeanUtils;
/**
 * UavTelemetryDataConverter
 *
 * @author liusuyi
 * @date 2024年10月24日10:38
 **/
public class UavTelemetryDataConverter {
    public static TelemetryData convertProtoToEntity(TelemetryDataPB.TelemetryData proto) {
        TelemetryData telemetryData = new TelemetryData();
        BeanUtils.copyProperties(proto, telemetryData);
        return telemetryData;
    }
}
ard-work/src/main/java/com/ard/tianyu/model/dto/init/UavInitInfo.java
New file
@@ -0,0 +1,16 @@
package com.ard.tianyu.model.dto.init;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class UavInitInfo {
    private String uavModel;       // 无人机型号
    private String uavSn;          // 无人机SN
    private String uavVersion;     // 无人机固件版本号
    private String ptModel;        // 挂载相机型号
    private String ptVersion;      // 挂载相机固件版本号
    private int ptPosition;        // 挂载相机psdk日位置
    private String moduleVersion;   // 模组固件版本号
}
ard-work/src/main/java/com/ard/tianyu/model/dto/signal/SignalInfo.java
New file
@@ -0,0 +1,74 @@
package com.ard.tianyu.model.dto.signal;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class SignalInfo {
    private String mode;               // 入网模式: NR5G-SA, NR5G-NSA,LTE
    private String mcc;                // NR5G-SA, NR5G-NSA, LTE
    private String mnc;                // NR5G-SA, NR5G-NSA, LTE
    private String cellid;             // NR5G-SA, LTE
    private String pcid;               // NR5G-SA, NR5G-NSA, LTE
    private String tac;                // NR5G-SA, LTE
    private String arfcn;              // NR5G-SA, NR5G-NSA
    private String band;               // NR5G-SA, NR5G-NSA
    @JsonProperty("nr_dl_bandwidth")
    private String nrDlBandwidth;      // NR5G-SA
    private String rsrp;               // NR5G-SA, NR5G-NSA, LTE
    private String rsrq;               // NR5G-SA, NR5G-NSA, LTE
    private String sinr;               // NR5G-SA, NR5G-NSA, LTE
    @JsonProperty("tx_power")
    private String txPower;            // NR5G-SA, LTE
    private String srxlev;             // NR5G-SA, LTE
    private String cqi;                // LTE
    private String earfcn;             // LTE
    @JsonProperty("freq_band_ind")
    private String freqBandInd;        // LTE
    @JsonProperty("ul_bandwidth")
    private String ulBandwidth;        // LTE
    @JsonProperty("dl_bandwidth")
    private String dlBandwidth;        // LTE
    @JsonProperty("is_tdd")
    private String isTdd;              // LTE
    private String rssi;               // LTE
    @JsonProperty("duplex_mode")
    private String duplexMode;         // NR5G-SA
    private double lng;                // 经度
    private double lat;                // 纬度
    private float height;              // 高度(单位:米)
    private int timestamp;             // 时间戳(单位:秒)
    private int boxstate;              // 1=线缆故障,2=OSDK未激活,3=正常,4=云盒固件更新
    private String isp;                // 运营商
    private int tempMax;               // 模组芯片温度(单位:摄氏度)
    @JsonProperty("prx_rsrp")
    private String prxRsrp;            // prx路径的rsrp值
    @JsonProperty("drx_rsrp")
    private String drxRsrp;            // drx路径的rsrp值
    @JsonProperty("rx2_rsrp")
    private String rx2Rsrp;            // rx2路径的rsrp值
    @JsonProperty("rx3_rsrp")
    private String rx3Rsrp;            // rx3路径的rsrp值
    @JsonProperty("box_sn")
    private String boxSn;              // 云盒编号
    @JsonProperty("sim_use_seat")
    private int simUseSeat;            // 当前使用的SIM卡在卡槽中的位置:1或2
}
ard-work/src/main/java/com/ard/tianyu/model/dto/state/AvoidanceData.java
New file
@@ -0,0 +1,23 @@
package com.ard.tianyu.model.dto.state;
import lombok.Data;
// 避障数据类
@Data
public class AvoidanceData {
    private int downHealth;                        // 下方健康状态
    private float down;                            // 距下障碍物的距离(单位:米),downHealth 为 1 时值有效
    private int frontHealth;                       // 前方健康状态
    private float front;                           // 距前障碍物的距离(单位:米),frontHealth 为 1 时值有效
    private int rightHealth;                       // 右方健康状态
    private float right;                           // 距右障碍物的距离(单位:米),rightHealth 为 1 时值有效
    private int backHealth;                        // 后方健康状态
    private float back;                            // 距后障碍物的距离(单位:米),backHealth 为 1 时值有效
    private int leftHealth;                        // 左方健康状态
    private float left;                            // 距左障碍物的距离(单位:米),leftHealth 为 1 时值有效
    private int upHealth;                          // 上方健康状态
    private float up;                              // 距上障碍物的距离(单位:米),upHealth 为 1 时值有效
    private int avoidanceEnableStatusDown;        // 下视觉避障开关状态:0-关闭,1-打开
    private int avoidanceEnableStatusUp;          // 上视觉避障开关状态:0-关闭,1-打开
    private int avoidanceEnableStatusHorizontal;   // 水平视觉避障开关状态:0-关闭,1-打开
}
ard-work/src/main/java/com/ard/tianyu/model/dto/state/BatteryState.java
New file
@@ -0,0 +1,19 @@
package com.ard.tianyu.model.dto.state;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BatteryState {
    private int batteryNum;                // 电池数量
    private String batteryPower;           // 电池电量,多个电池用下划线分割
    private String batteryVoltage;         // 电池电压,多个电池用下划线分割(单位: V)
    private BatteryStateInfo firstBatteryInfo;  // 第一块电池状态信息
    private BatteryStateInfo secondBatteryInfo; // 第二块电池状态信息
}
ard-work/src/main/java/com/ard/tianyu/model/dto/state/BatteryStateInfo.java
New file
@@ -0,0 +1,30 @@
package com.ard.tianyu.model.dto.state;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * BatteryStateDto
 *
 * @author liusuyi
 * @date 2024年10月24日9:45
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BatteryStateInfo {
    private int isBatteryEmbed;        // 电池插入飞机状态:0=插入,1=未插入
    private int batteryCapacityPercent; // 电池电量百分比
    private int currentVoltage;         // 电池电压 (单位: mV)
    private int currentElectric;        // 当前电池电流 (单位: mA)
    private int fullCapacity;           // 满电池容量 (单位: mAh)
    private int remainedCapacity;       // 剩余电池容量 (单位: mAh)
    private float batteryTemperature;   // 电池温度 (单位: 摄氏度)
    private int cellCount;              // 电池组数
    private int batSOHState;            // 电池循环健康状态:0=正常,1=警报,2=注意安全
    private int sop;                    // 相对功率百分比 (Relative power percentage)
    private int heatState;              // 电池加热状态:0=未加热,1=加热中,2=保持恒温
    private int socState;               // 电池 SOC 荷电状态:0=正常,1=高,2=下降,3=上升,4=无效
    private int selfCheckError;         // 电池自检错误标志:0=正常,其他值表示错误
}
ard-work/src/main/java/com/ard/tianyu/model/dto/state/CameraState.java
New file
@@ -0,0 +1,21 @@
package com.ard.tianyu.model.dto.state;
import lombok.Data;
// 相机状态类
@Data
public class CameraState {
    private int mode;                  // 相机模式:1=拍照模式,2=录像模式,0=未知
    private int isRecording;           // 是否录制中:1=录制中,0=未录制
    private int recordDuration;        // 录制时长(单位:秒)
    private int source;                // 相机视源:0=可见,1=变焦,2=红外
    private int camera;                // 相机:0=FPV,1=相机(1),2=相机(2)
    private float zoomFactor;          // 相机当前变焦倍数
    private int width;                 // 水平像素(例如:1920)
    private int height;                // 垂直像素(例如:1080)
    private int frameRate;             // 帧率(例如:30)
    private int bitstream;             // 码率(单位:0.001)(例如:6兆设置值为6000)
    private int pointThermometrying;   // 单点测温状态:0=非单点测温中,1=单点测温中
    private int areaThermometrying;    // 区域测温状态:0=非区域测温中,1=区域测温中
    private int laserRanging;          // 激光测距状态:0=非激光测距中,1=激光测距中
}
ard-work/src/main/java/com/ard/tianyu/model/dto/state/FlightControllerState.java
New file
@@ -0,0 +1,23 @@
package com.ard.tianyu.model.dto.state;
import lombok.Data;
@Data
public class FlightControllerState {
    private int satelliteCount; // 卫星计数
    private int gpsSignalLevel; // GPS信号级别 (0-5)
    private int flightMode; // 飞行模式
    private int flightStatus; // 飞行状态
    private PointData startPoint; // 起飞点(包含经纬度)
    private PointData homePoint; // 返航点(包含经纬度)
    private int homeHeight; // 返航高度(单位:米)
    private int safeLine; // 飞行模式安全线
    private int deviceStatus; // 控制权状态
    private int uwbNodeCount; // UWB星数
    private String rcMode; // 遥控器档位模式
    private int isEmergencyBraking; // 是否紧急制动中
    private int outFlyAreaFlag; // 是否在电子围栏外
    private int inNoFlyAreaFlag; // 是否在禁飞区内
}
ard-work/src/main/java/com/ard/tianyu/model/dto/state/HmsAlarmData.java
New file
@@ -0,0 +1,11 @@
package com.ard.tianyu.model.dto.state;
import lombok.Data;
// Hms报警信息类
@Data
public class HmsAlarmData {
    private int alarmId;        // 报警信息ID
    private int reportLevel;    // 等级 [1/2-警告 3/4/5-错误]
    private String alarmMssInfo; // 报警信息描述(支持中文和英文版本,默认中文,如需切换请联系技术支持)
}
ard-work/src/main/java/com/ard/tianyu/model/dto/state/MissionState.java
New file
@@ -0,0 +1,22 @@
package com.ard.tianyu.model.dto.state;
import lombok.Data;
// 任务状态类
@Data
public class MissionState {
    private int isPause;                // 航线是否暂停中:0=未暂停,1=暂停中
    private int targetWaypointIndex;     // 目标航点下标
    private int isWaypointFinished;      // 是否航点完成:1完成、0未完成(此值废弃)
    private int pushVideo;               // 云盒是否发送视频数据:0=不发送,1=发送
    private int lock4g;                 // 是否锁定4G:0=不锁定,1=锁定
    private int boxModel;                // 是否开通图片自动回传功能:0=未开通,1=已开通
    private int mapPlay;                 // 自动拍照间隔:0未开始,3~255间隔时间
    private int loseAction;              // 网络失联后动作:0=返回HOME点,1=继续航线
    private int isPointControl;          // 是否打点飞行控制中:0=否,1=是
    private int isUwbLanding;            // 是否UWB精准降落中:0=不是,1=是
    private int isPushVideoing;          // 视频是否推流中:0=不是,1=是
    private int isDLanding;              // 是否二维码精准降落中:0=不是,1=是
    private int perceptionFlag;          // 二维码精准降落模式:0=载荷降落,1=下视降落
    private int isPositionControl;       // 是否指定距离飞行控制中:0=否,1=是
}
ard-work/src/main/java/com/ard/tianyu/model/dto/state/PointData.java
New file
@@ -0,0 +1,10 @@
package com.ard.tianyu.model.dto.state;
import lombok.Data;
// 假设 PointData 类定义如下
@Data
public class PointData {
    private double lat; // 纬度
    private double lng; // 经度
}
ard-work/src/main/java/com/ard/tianyu/model/dto/state/PtzState.java
New file
@@ -0,0 +1,12 @@
package com.ard.tianyu.model.dto.state;
import lombok.Data;
// 云台状态类
@Data
public class PtzState {
    private float pitch; // 俯仰角,范围:-120° ~ 30°
    private float roll;  // 横滚角,范围:-90° ~ 60°
    private float yaw;   // 偏航角,范围:-180° ~ 180°
    private int gimbalMode; // 云台模式:1=自由模式,2=跟随模式,3=FPV模式
}
ard-work/src/main/java/com/ard/tianyu/model/dto/state/UavState.java
New file
@@ -0,0 +1,24 @@
package com.ard.tianyu.model.dto.state;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UavState {
    private FlightControllerState flightControllerState;  // 飞控状态
    private BatteryState batteryState;                    // 电池状态
    private PtzState ptzState;                            // 云台状态
    private CameraState cameraState;                      // 相机状态
    private MissionState missionState;                    // 任务状态
    private String boxSn;                                 // 云盒编号
    private AvoidanceData avoidanceData;                  // 避障数据
    private List<HmsAlarmData> hmsAlarmData;              // HMS报警信息 (飞机告警信息)
}
ard-work/src/main/java/com/ard/tianyu/model/dto/telemetry/TelemetryData.java
New file
@@ -0,0 +1,46 @@
package com.ard.tianyu.model.dto.telemetry;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TelemetryData {
    private double lng;              // 经度
    private double lat;              // 纬度
    private float altitude;          // 海拔高度 (椭球高) (单位: 米)
    private float ultrasonic;        // 相对高度 (单位: 米)
    private float pitch;             // 俯仰角
    private float roll;              // 横滚角
    private float yaw;               // 偏航角
    private float airspeed;          // 空速 (单位: 米/秒)
    private float velocity;          // 地速 (单位: 米/秒)
    private long timestamp;          // 时间戳
    private float ptpitch;           // 载荷俯仰角
    private float ptroll;            // 载荷横滚角
    private float ptyaw;             // 载荷航向角
    private float zoomfactor;        // 载荷当前倍数
    private String boxSn;            // 云盒编号
    private String batteryPower;     // 电池电量 (多个电池以下划线分割)
    private int satelliteCount;      // 卫星计数
    private long taskId;             // 任务编号
    private double rtkLng;           // RTK 经度
    private double rtkLat;           // RTK 纬度
    private float rtkHFSL;           // RTK 海拔高度 (平均海平面高度) (单位: 米)
    private int rtkPositionInfo;     // RTK 状态
    private int airFlyTimes;         // 当前架次飞行时长 (单位: 秒)
    private float airFlyDistance;    // 当前架次飞行实际距离 (单位: 米)
    private String uavSn;            // 无人机编号
    private String uavModel;         // 无人机型号
    private float homeRange;         // 距降落点水平直线距离 (单位: 米)
    private int flightMode;          // 飞行模式
    private float targetDistance;    // 距目标点实际距离 (单位: 米)
    private int predictFlyTime;      // 预计剩余飞行时间
    private float ultrasonicMax;     // 本架次最大相对高度值
    private float ultrasonicMin;     // 本架次最小相对高度值
}
ard-work/src/main/java/com/ard/tianyu/netty/command/ControlAngleCommand.java
@@ -32,14 +32,14 @@
    public short getDataLength() {
        // 计算数据长度: 云盒编号 + 指令编号 + 加密标志 + 动作编号 + 转动角度
        return (short) (2 + 15 + 1 + 1 + 1); // 帧头 + 数据内容
        return (short) (1 + 15 + 1 + 1 + 1); // 帧头 + 数据内容
    }
    public void encode(ByteBuf out) {
        out.writeShort(getDataHeader());    // 写入帧头
        out.writeShort(getDataLength());    // 写入数据长度
        out.writeByte(getCmdCode());        // 写入指令编号
        out.writeBytes(boxSn); // 写入云盒编号
        out.writeByte(getCmdCode());        // 写入指令编号
        out.writeByte(encryptFlag); // 写入加密标志
        out.writeByte(actionId); // 写入动作编号
        out.writeByte(rotationAngle); // 写入转动角度
ard-work/src/main/java/com/ard/tianyu/netty/command/DroneReadyNotificationCommand.java
New file
@@ -0,0 +1,31 @@
package com.ard.tianyu.netty.command;
import com.ard.tianyu.netty.protobuf.TelemetryDataPB;
import io.netty.buffer.ByteBuf;
import lombok.Data;
/**
 *  无人机就绪通知命令
 *
 * @author 刘苏义
 * @date 2024/10/24 17:18
 */
@Data
public class DroneReadyNotificationCommand extends BaseCommand {
    private byte actionCode;
    private TelemetryDataPB.UavInitInfo uavInitInfo;
    public DroneReadyNotificationCommand(TelemetryDataPB.UavInitInfo uavInitInfo, byte actionCode) {
        setDataHeader((short) 0x6A77); // 设置帧头
        // setDataLength((short) (1 + uavState.toByteArray().length)); // 数据长度
        setCmdCode((byte) 0xD1); // 设置命令编号
        this.uavInitInfo = uavInitInfo;
        this.actionCode = actionCode;
    }
    @Override
    public void encode(ByteBuf out) {
    }
}
ard-work/src/main/java/com/ard/tianyu/netty/command/SignalInfoCommand.java
New file
@@ -0,0 +1,25 @@
package com.ard.tianyu.netty.command;
import com.ard.tianyu.netty.protobuf.TelemetryDataPB;
import io.netty.buffer.ByteBuf;
import lombok.Data;
@Data
public class SignalInfoCommand extends BaseCommand {
    private int delayTime;
    private TelemetryDataPB.SignalInfo signalInfo;
    // 构造函数
    public SignalInfoCommand(TelemetryDataPB.SignalInfo signalInfo) {
        setDataHeader((short) 0x6A77); // 设置帧头
       // setDataLength((short) (1 + uavState.toByteArray().length)); // 数据长度
        setCmdCode((byte) 0x0C); // 设置命令编号
        this.signalInfo = signalInfo;
    }
    // 实现 encode 方法,如果需要
    @Override
    public void encode(ByteBuf out) {
        // 根据需要实现编码
    }
}
ard-work/src/main/java/com/ard/tianyu/netty/command/UavInitInfoCommand.java
New file
@@ -0,0 +1,37 @@
package com.ard.tianyu.netty.command;
import io.netty.buffer.ByteBuf;
import lombok.Data;
/**
 * 无人机初始化回复命令
 *
 * @author 刘苏义
 * @date 2024/10/22 16:36
 */
@Data
public class UavInitInfoCommand extends BaseCommand{
    private final byte encryptFlag; // 加密标志
    private final byte actionId; // 动作编号
    private final byte result; // 执行结果
    public UavInitInfoCommand(byte encryptFlag, byte actionId, byte result) {
        setDataHeader((short)0x7479);
        setDataLength((short) 3);
        setCmdCode((byte)0xD1);
        this.encryptFlag = encryptFlag;
        this.actionId = actionId;
        this.result = result;
    }
    public void encode(ByteBuf out) {
        out.writeShort(getDataHeader());    // 写入帧头
        out.writeShort(getDataLength());    // 写入数据长度
        out.writeByte(getCmdCode());        // 写入指令编号
        out.writeByte(encryptFlag);         // 写入加密标志
        out.writeByte(actionId);            // 写入动作编号
        out.writeByte(result);              // 写入执行结果
    }
}
ard-work/src/main/java/com/ard/tianyu/netty/command/UavStateCommand.java
@@ -9,6 +9,9 @@
    // 构造函数
    public UavStateCommand(TelemetryDataPB.UavState uavState) {
        setDataHeader((short) 0x6A77); // 设置帧头
       // setDataLength((short) (1 + uavState.toByteArray().length)); // 数据长度
        setCmdCode((byte) 0xA8); // 设置命令编号
        this.uavState = uavState;
    }
ard-work/src/main/java/com/ard/tianyu/netty/command/UavTelemetryDataCommand.java
File was renamed from ard-work/src/main/java/com/ard/tianyu/netty/command/UavDataCommand.java
@@ -9,10 +9,13 @@
 * @author liusuyi
 * @date 2024年10月23日9:33
 **/
public class UavDataCommand extends BaseCommand{
public class UavTelemetryDataCommand extends BaseCommand{
    private TelemetryDataPB.TelemetryData telemetryData;
    // 构造函数
    public UavDataCommand(TelemetryDataPB.TelemetryData telemetryData) {
    public UavTelemetryDataCommand(TelemetryDataPB.TelemetryData telemetryData) {
        setDataHeader((short) 0x6A77); // 设置帧头
        // setDataLength((short) (1 + uavState.toByteArray().length)); // 数据长度
        setCmdCode((byte) 0xA9); // 设置命令编号
        this.telemetryData = telemetryData;
    }
ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolDecoder.java
@@ -54,17 +54,52 @@
                in.readBytes(uavStatus);  // 读取 ProtoBuf 数据
                TelemetryDataPB.UavState uavState = TelemetryDataPB.UavState.parseFrom(uavStatus);
                baseCommand = new UavStateCommand(uavState);
                log.warn("无人机状态数据: {}", uavState.getBoxSn());
                log.debug("无人机状态数据: {}", uavState.getBoxSn());
                break;
            case (byte) 0xA9:
                byte[] uavData = new byte[dataLength - 1];
                in.readBytes(uavData);
                TelemetryDataPB.TelemetryData telemetryData = TelemetryDataPB.TelemetryData.parseFrom(uavData);
                baseCommand = new UavDataCommand(telemetryData);
                log.warn("无人机遥测数据: {}", telemetryData.getBoxSn());
                baseCommand = new UavTelemetryDataCommand(telemetryData);
                log.debug("遥测数据: {}", telemetryData.getBoxSn());
                break;
            case (byte) 0x0C:
                int delayTime = in.readInt();
                uavData = new byte[15];
                in.readBytes(uavData);
                //  String boxSn12 = new String(uavData);
                uavData = new byte[dataLength - 20];
                in.readBytes(uavData);
                TelemetryDataPB.SignalInfo signalInfo = TelemetryDataPB.SignalInfo.parseFrom(uavData);
                baseCommand = new SignalInfoCommand(signalInfo);
                log.debug("信道质量数据: {}", delayTime);
                break;
            case (byte) 0xD1:
                byte encryptionFlag = in.readByte();
                byte actionCode = in.readByte();
                switch (actionCode) {
                    case 0x42:
                        byte[] uavData1 = new byte[dataLength - 18];
                        in.readBytes(uavData1);
                        byte[] uavData2 = new byte[15];
                        in.readBytes(uavData2);
                        TelemetryDataPB.UavInitInfo uavInitInfo = TelemetryDataPB.UavInitInfo.parseFrom(uavData1);
                        baseCommand = new DroneReadyNotificationCommand(uavInitInfo, actionCode);
                        log.info("无人机初始化数据: {}", uavInitInfo.getUavModel());
                break;
            default:
                log.warn("无法识别的命令码: {}", String.format("0x%02X", cmdCode & 0xFF));//String.format("0x%02X", cmdCode & 0xFF)
                        log.warn("无法识别的命令码动作编号:{}", String.format("0x%02X", actionCode & 0xFF));
                        break;
                }
                break;
            default:
                encryptionFlag = in.readByte();
                actionCode = in.readByte();
                log.warn("无法识别的命令码: {},加密标志:{},动作编号:{}",
                        String.format("0x%02X", cmdCode & 0xFF),
                        String.format("0x%02X", encryptionFlag & 0xFF),
                        String.format("0x%02X", actionCode & 0xFF));//String.format("0x%02X", cmdCode & 0xFF)
        }
        if (baseCommand != null) {
            out.add(baseCommand);
ard-work/src/main/java/com/ard/tianyu/netty/protobuf/TelemetryDataBuf-new.proto
@@ -278,3 +278,14 @@
   uint32 cameraId=3;//相机编号
   uint32 isModeling=4;//是否实时建模:0=不,1=是
}
//无人机初始化详情
message UavInitInfo{
  string uavModel = 1;      //无人机型号
  string uavSn=2;           //无人机SN
  string uavVersion = 3;    //无人机固件版本号
  string ptModel = 4;       //挂载相机型号
  string ptVersion = 5;     //挂载相机固件版本号
  uint32 ptPosition = 6;    //挂载相机psdk日位置
  string moduleVersion = 7; //模组固件版本号
}
ard-work/src/main/java/com/ard/tianyu/netty/protobuf/TelemetryDataPB.java
Diff too large
ard-work/src/main/java/com/ard/tianyu/service/ITyService.java
@@ -3,6 +3,9 @@
import com.ard.tianyu.model.dto.BoxHistoryDTO;
import com.ard.tianyu.model.dto.BoxPhotosDTO;
import com.ard.tianyu.model.dto.BoxSettingsDTO;
import com.ard.tianyu.model.dto.signal.SignalInfo;
import com.ard.tianyu.model.dto.state.UavState;
import com.ard.tianyu.model.dto.telemetry.TelemetryData;
import com.ard.tianyu.model.receiver.*;
import com.ard.tianyu.netty.command.BaseCommand;
import com.dtflys.forest.annotation.Var;
@@ -67,9 +70,23 @@
    /**
     * 云台转动(基于角度)
     */
    void controlAngle(String boxSn);
    void controlAngle(String boxSn,Integer actionId,Integer rotationAngle) ;
    /**
     * 获取无人机状态
     */
    UavState getUavState(String boxSn);
    /**
     * 获取无人机遥测
     */
    TelemetryData getUavTelemetryData(String boxSn);
    /**
     * 获取信道质量遥测
     */
    SignalInfo getSignalInfo(String boxSn);
    /**
     * 解析天宇服务端发来的消息
     */
    void processMessage(String key, BaseCommand tyMessage);
ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java
@@ -2,9 +2,18 @@
import com.ard.tianyu.config.TyConfiguration;
import com.ard.tianyu.http.TyClient;
import com.ard.tianyu.model.cache.UavSignalInfoCache;
import com.ard.tianyu.model.cache.UavStateCache;
import com.ard.tianyu.model.cache.UavTelemetryDataCache;
import com.ard.tianyu.model.dto.BoxHistoryDTO;
import com.ard.tianyu.model.dto.BoxPhotosDTO;
import com.ard.tianyu.model.dto.BoxSettingsDTO;
import com.ard.tianyu.model.dto.converter.UavSignalInfoConverter;
import com.ard.tianyu.model.dto.converter.UavStateConverter;
import com.ard.tianyu.model.dto.converter.UavTelemetryDataConverter;
import com.ard.tianyu.model.dto.signal.SignalInfo;
import com.ard.tianyu.model.dto.state.UavState;
import com.ard.tianyu.model.dto.telemetry.TelemetryData;
import com.ard.tianyu.model.receiver.*;
import com.ard.tianyu.netty.command.*;
import com.ard.tianyu.netty.TyNettyTcpClient;
@@ -154,9 +163,33 @@
     * 云台控制基于角度
     */
    @Override
    public void controlAngle(String boxSn) {
        ControlAngleCommand controlAngleCommand = new ControlAngleCommand(boxSn.getBytes(), (byte) 0x00, (byte) 0x00, (byte) 0x05);
    public void controlAngle(String boxSn, Integer actionId, Integer rotationAngle) {
        ControlAngleCommand controlAngleCommand = new ControlAngleCommand(boxSn.getBytes(), (byte) 0x00, actionId.byteValue(), rotationAngle.byteValue());
        this.sendMessage(tyConfiguration.getIpPort(), controlAngleCommand);
    }
    /**
     * 获取无人机状态
     */
    @Override
    public UavState getUavState(String boxSn) {
        return UavStateCache.getUavState(boxSn);
    }
    /**
     * 获取无人机遥测数据
     */
    @Override
    public TelemetryData getUavTelemetryData(String boxSn) {
        return UavTelemetryDataCache.getUavTelemetryData(boxSn);
    }
    /**
     * 获取无人机遥测数据
     */
    @Override
    public SignalInfo getSignalInfo(String boxSn) {
        return UavSignalInfoCache.getUavSignalInfo(boxSn);
    }
    @Override
@@ -176,7 +209,7 @@
            case 0x02:
                // 处理注册消息
                HeartbeatReplyCommand heartbeatReplyCommand = (HeartbeatReplyCommand) tyCommand;
                log.info("收到心跳消息-->处理心跳消息{}", heartbeatReplyCommand.getTimestamp());
                log.debug("收到心跳消息-->处理心跳消息{}", heartbeatReplyCommand.getTimestamp());
                break;
            case 0x03:
                // 处理订阅消息
@@ -190,14 +223,37 @@
                break;
            case (byte) 0xA8:
                // 处理无人机状态消息
                log.info("收到无人机状态消息-->无人机状态消息");
                log.debug("收到无人机状态消息-->无人机状态消息");
                UavStateCommand uavStateCommand = (UavStateCommand) tyCommand;
                UavState uavState = UavStateConverter.convertProtoToEntity(uavStateCommand.getUavState());
                UavStateCache.putUavState(uavState);
                break;
            case (byte) 0xA9:
                // 处理无人机遥测消息
                log.info("收到无人机遥测消息-->无人机遥测消息");
                log.debug("收到无人机遥测消息-->无人机遥测消息");
                UavTelemetryDataCommand uavTelemetryDataCommand = (UavTelemetryDataCommand) tyCommand;
                TelemetryData telemetryData = UavTelemetryDataConverter.convertProtoToEntity(uavTelemetryDataCommand.getTelemetryData());
                UavTelemetryDataCache.putUavTelemetryData(telemetryData);
                break;
            case (byte) 0x0C:
                // 处理无人机信道质量数据
                log.debug("收到无人机信道质量数据消息-->无人机信道质量数据消息");
                SignalInfoCommand signalInfoCommand = (SignalInfoCommand) tyCommand;
                SignalInfo signalInfo = UavSignalInfoConverter.convertProtoToEntity(signalInfoCommand.getSignalInfo());
                UavSignalInfoCache.putUavSignalInfoCache(signalInfo);
                break;
            case (byte) 0xD1:
                // 处理无人机
                DroneReadyNotificationCommand droneReadyNotificationCommand = (DroneReadyNotificationCommand) tyCommand;
                if (droneReadyNotificationCommand.getActionCode() == (byte) 0x42) {
                    UavInitInfoCommand uavInitCommand = new UavInitInfoCommand((byte) 0x00, (byte) 0x42, (byte) 0x01);
                    this.sendMessage(tyConfiguration.getIpPort(), uavInitCommand);
                    log.info("收到无人机初始化详情-回复防止再次发送");
                }
                break;
            default:
                // 处理其他消息
                log.debug("收到其他消息-->其他消息");
        }
    }