ard-work/src/main/java/com/ard/tianyu/controller/UavSettingsController.java
New file @@ -0,0 +1,60 @@ package com.ard.tianyu.controller; import com.ard.common.core.domain.AjaxResult; 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.settings.ReturnHeightSettingDTO; import com.ard.tianyu.model.dto.settings.ReturnPointSettingDTO; import com.ard.tianyu.model.dto.settings.VideoStreamSettingDTO; import com.ard.tianyu.model.receiver.BoxHistoryReceiver; import com.ard.tianyu.model.receiver.BoxInfoReceiver; import com.ard.tianyu.model.receiver.BoxPhotosReceiver; import com.ard.tianyu.model.receiver.BoxStreamUrlReceiver; import com.ard.tianyu.service.ITyService; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.github.xiaoymin.knife4j.annotations.ApiSort; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; /** * UavBaseController * * @author liusuyi * @date 2024年10月21日13:52 **/ @Api(tags = "无人机设置接口") @ApiSort(value = 3) @RequestMapping("/uav/settings") @RestController public class UavSettingsController { @Resource private ITyService tyService; @ApiOperation(value = "设置返航高度",notes = "高度【取值范围:20~1500,单位/米】") @ApiOperationSupport(order = 1) @PostMapping("/updateReturnHeight") public AjaxResult updateReturnHeight(@RequestBody ReturnHeightSettingDTO returnHeightSettingDTO) { tyService.updateReturnHeight(returnHeightSettingDTO); return AjaxResult.success(); } @ApiOperation("设置返航点") @ApiOperationSupport(order = 2) @PostMapping("/updateReturnPoint") public AjaxResult updateReturnPoint(@RequestBody ReturnPointSettingDTO returnPointSettingDTO) { tyService.updateReturnPoint(returnPointSettingDTO); return AjaxResult.success(); } @ApiOperation(value = "设置视频码流",notes = "帧率【建议值:25或30】 码率【不超过10000】") @ApiOperationSupport(order = 3) @PostMapping("/updateVideoStream") public AjaxResult updateVideoStream(@RequestBody VideoStreamSettingDTO videoStreamSettingDTO) { tyService.updateVideoStream(videoStreamSettingDTO); return AjaxResult.success(); } } ard-work/src/main/java/com/ard/tianyu/model/dto/camera/CameraModeDTO.java
@@ -16,7 +16,6 @@ @Builder @AllArgsConstructor @NoArgsConstructor @Validated public class CameraModeDTO { private String boxSn; private Byte actionParam; ard-work/src/main/java/com/ard/tianyu/model/dto/camera/CapturePicDTO.java
@@ -16,7 +16,6 @@ @Builder @AllArgsConstructor @NoArgsConstructor @Validated public class CapturePicDTO { private String boxSn; } ard-work/src/main/java/com/ard/tianyu/model/dto/camera/SwitchCameraDTO.java
@@ -19,7 +19,6 @@ @Builder @AllArgsConstructor @NoArgsConstructor @Validated public class SwitchCameraDTO { private String boxSn; // 0x00 FPV 0x01 载荷 ard-work/src/main/java/com/ard/tianyu/model/dto/settings/ReturnHeightSettingDTO.java
New file @@ -0,0 +1,29 @@ package com.ard.tianyu.model.dto.settings; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.validation.annotation.Validated; import javax.validation.constraints.Max; import javax.validation.constraints.Min; /** * 返航高度实体对象 * * @author liusuyi * @date 2024年11月01日10:55 **/ @Data @Builder @AllArgsConstructor @NoArgsConstructor @Validated public class ReturnHeightSettingDTO { private String boxSn; //取值范围:20~1500,单位/米 @Min(value = 20, message = "返航高度 最小值为 20") @Max(value = 1500, message = "返航高度 最大值为 1500") private Short height; } ard-work/src/main/java/com/ard/tianyu/model/dto/settings/ReturnPointSettingDTO.java
New file @@ -0,0 +1,26 @@ package com.ard.tianyu.model.dto.settings; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.validation.annotation.Validated; import javax.validation.constraints.Max; import javax.validation.constraints.Min; /** * 返航点实体对象 * * @author liusuyi * @date 2024年11月01日10:55 **/ @Data @Builder @AllArgsConstructor @NoArgsConstructor public class ReturnPointSettingDTO { private String boxSn; private Double longitude; private Double latitude; } ard-work/src/main/java/com/ard/tianyu/model/dto/settings/VideoStreamSettingDTO.java
New file @@ -0,0 +1,41 @@ package com.ard.tianyu.model.dto.settings; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.validation.annotation.Validated; import javax.validation.constraints.Max; /** * 返航点实体对象 * * @author liusuyi * @date 2024年11月01日10:55 **/ @Data @Builder @AllArgsConstructor @NoArgsConstructor @Validated public class VideoStreamSettingDTO { private String boxSn; /** * 分辨率宽度 */ private Integer resolutionWidth; /** * 分辨率高度 */ private Integer resolutionHeight; /** * 帧率 (建议值:25或30) */ private Byte frameRate; /** * 码率 */ @Max(value = 10000, message = "码率 最大值为 10000") private Integer bitrate; } ard-work/src/main/java/com/ard/tianyu/netty/command/manual/ReturnHomeCancelReplyCmd.java
@@ -14,7 +14,7 @@ public class ReturnHomeCancelReplyCmd extends BaseCmd { private final byte encryptFlag = 0x00; // 加密标志 private final byte actionCode = 0x13; // 动作编号 private final byte actionCode = 0x21; // 动作编号 private final byte result; // 执行结果 private final Integer errorCode; // 错误码 ard-work/src/main/java/com/ard/tianyu/netty/command/settings/ReturnHeightSettingCmd.java
New file @@ -0,0 +1,35 @@ package com.ard.tianyu.netty.command.settings; import com.ard.tianyu.model.dto.settings.ReturnHeightSettingDTO; import com.ard.tianyu.netty.command.BaseCmd; import io.netty.buffer.ByteBuf; import lombok.Data; /** * 修改返航高度指令 * * @author liusuyi * @date 2024年10月30日16:20 **/ public class ReturnHeightSettingCmd extends BaseCmd { private final Short height; public ReturnHeightSettingCmd(ReturnHeightSettingDTO returnHeightSettingDTO) { setDataHeader((short) 0x7479); setDataLength((short) 20); setBoxSn(returnHeightSettingDTO.getBoxSn().getBytes()); setCmdCode((byte) 0xD1); this.height = returnHeightSettingDTO.getHeight(); } public void encode(ByteBuf out) { out.writeShort(getDataHeader()); // 写入数据头 out.writeShort(getDataLength()); // 写入数据长度 out.writeBytes(getBoxSn()); // 写入盒子SN out.writeByte(getCmdCode()); // 写入命令码 out.writeByte(0x00); // 写入加密标志 out.writeByte(0x21); // 写入动作编号 out.writeShort(height); // 写入返航高度 } } ard-work/src/main/java/com/ard/tianyu/netty/command/settings/ReturnHeightSettingReplyCmd.java
New file @@ -0,0 +1,33 @@ package com.ard.tianyu.netty.command.settings; import com.ard.tianyu.netty.command.BaseCmd; import io.netty.buffer.ByteBuf; import lombok.Data; /** * 修改返航高度回复指令 * * @author liusuyi * @date 2024年10月30日16:20 **/ @Data public class ReturnHeightSettingReplyCmd extends BaseCmd { private final byte encryptFlag = 0x00; // 加密标志 private final byte actionCode = 0x21; // 动作编号 private final byte result; // 执行结果 private final Integer errorCode; // 错误码 public ReturnHeightSettingReplyCmd(String boxSn, Byte result, Integer errorCode) { setDataHeader((short) 0x6A77); //setDataLength((short) 18); setCmdCode((byte) 0xD1); setBoxSn(boxSn.getBytes()); this.result = result; this.errorCode = errorCode; } public void encode(ByteBuf out) { } } ard-work/src/main/java/com/ard/tianyu/netty/command/settings/ReturnPointSettingCmd.java
New file @@ -0,0 +1,38 @@ package com.ard.tianyu.netty.command.settings; import com.ard.tianyu.model.dto.settings.ReturnHeightSettingDTO; import com.ard.tianyu.model.dto.settings.ReturnPointSettingDTO; import com.ard.tianyu.netty.command.BaseCmd; import io.netty.buffer.ByteBuf; /** * 修改返航点指令 * * @author liusuyi * @date 2024年10月30日16:20 **/ public class ReturnPointSettingCmd extends BaseCmd { private final Double longitude; private final Double latitude; public ReturnPointSettingCmd(ReturnPointSettingDTO returnPointSettingDTO) { setDataHeader((short) 0x7479); setDataLength((short) 34); setBoxSn(returnPointSettingDTO.getBoxSn().getBytes()); setCmdCode((byte) 0xD1); this.longitude= returnPointSettingDTO.getLongitude(); this.latitude= returnPointSettingDTO.getLatitude(); } public void encode(ByteBuf out) { out.writeShort(getDataHeader()); // 写入数据头 out.writeShort(getDataLength()); // 写入数据长度 out.writeBytes(getBoxSn()); // 写入盒子SN out.writeByte(getCmdCode()); // 写入命令码 out.writeByte(0x00); // 写入加密标志 out.writeByte(0x31); // 写入动作编号 out.writeDouble(longitude); // 写入经度 out.writeDouble(latitude); // 写入纬度 } } ard-work/src/main/java/com/ard/tianyu/netty/command/settings/ReturnPointSettingReplyCmd.java
New file @@ -0,0 +1,33 @@ package com.ard.tianyu.netty.command.settings; import com.ard.tianyu.netty.command.BaseCmd; import io.netty.buffer.ByteBuf; import lombok.Data; /** * 修改返航高度回复指令 * * @author liusuyi * @date 2024年10月30日16:20 **/ @Data public class ReturnPointSettingReplyCmd extends BaseCmd { private final byte encryptFlag = 0x00; // 加密标志 private final byte actionCode = 0x31; // 动作编号 private final byte result; // 执行结果 private final Integer errorCode; // 错误码 public ReturnPointSettingReplyCmd(String boxSn, Byte result, Integer errorCode) { setDataHeader((short) 0x6A77); //setDataLength((short) 18); setCmdCode((byte) 0xD1); setBoxSn(boxSn.getBytes()); this.result = result; this.errorCode = errorCode; } public void encode(ByteBuf out) { } } ard-work/src/main/java/com/ard/tianyu/netty/command/settings/VideoStreamSettingCmd.java
New file @@ -0,0 +1,44 @@ package com.ard.tianyu.netty.command.settings; import com.ard.tianyu.model.dto.settings.ReturnPointSettingDTO; import com.ard.tianyu.model.dto.settings.VideoStreamSettingDTO; import com.ard.tianyu.netty.command.BaseCmd; import io.netty.buffer.ByteBuf; /** * 设置视频码流指令 * * @author liusuyi * @date 2024年10月30日16:20 **/ public class VideoStreamSettingCmd extends BaseCmd { private final int resolutionWidth; // 水平像素 private final int resolutionHeight; // 垂直像素 private final int bitrate; // 码率 private final byte frameRate; // 帧率 public VideoStreamSettingCmd(VideoStreamSettingDTO videoStreamSettingDTO) { setDataHeader((short) 0x7479); setDataLength((short) 27); setBoxSn(videoStreamSettingDTO.getBoxSn().getBytes()); setCmdCode((byte) 0xD2); this.bitrate = videoStreamSettingDTO.getBitrate(); this.resolutionWidth = videoStreamSettingDTO.getResolutionWidth(); this.resolutionHeight = videoStreamSettingDTO.getResolutionHeight(); this.frameRate = videoStreamSettingDTO.getFrameRate(); } public void encode(ByteBuf out) { out.writeShort(getDataHeader()); // 写入数据头 out.writeShort(getDataLength()); // 写入数据长度 out.writeBytes(getBoxSn()); // 写入盒子SN out.writeByte(getCmdCode()); // 写入命令码 out.writeByte(0x00); // 写入加密标志 out.writeByte(0x05); // 写入动作编号 out.writeInt(resolutionWidth); // 写入水平像素 out.writeInt(resolutionHeight); // 写入垂直像素 out.writeByte(frameRate); // 写入帧率 out.writeInt(bitrate); // 写入码率 } } ard-work/src/main/java/com/ard/tianyu/netty/command/settings/VideoStreamSettingReplyCmd.java
New file @@ -0,0 +1,33 @@ package com.ard.tianyu.netty.command.settings; import com.ard.tianyu.netty.command.BaseCmd; import io.netty.buffer.ByteBuf; import lombok.Data; /** * 设置视频码流回复指令 * * @author liusuyi * @date 2024年10月30日16:20 **/ @Data public class VideoStreamSettingReplyCmd extends BaseCmd { private final byte encryptFlag = 0x00; // 加密标志 private final byte actionCode = 0x05; // 动作编号 private final byte result; // 执行结果 private final Integer errorCode; // 错误码 public VideoStreamSettingReplyCmd(String boxSn, Byte result, Integer errorCode) { setDataHeader((short) 0x6A77); //setDataLength((short) 18); setCmdCode((byte) 0XD2); setBoxSn(boxSn.getBytes()); this.result = result; this.errorCode = errorCode; } public void encode(ByteBuf out) { } } ard-work/src/main/java/com/ard/tianyu/netty/handler/MessageProtocolDecoder.java
@@ -16,6 +16,9 @@ import com.ard.tianyu.netty.command.register.HeartbeatReplyCmd; import com.ard.tianyu.netty.command.register.RegisterReplyCmd; import com.ard.tianyu.netty.command.register.UavInitReplyCmd; import com.ard.tianyu.netty.command.settings.ReturnHeightSettingReplyCmd; import com.ard.tianyu.netty.command.settings.ReturnPointSettingReplyCmd; import com.ard.tianyu.netty.command.settings.VideoStreamSettingReplyCmd; import com.ard.tianyu.netty.command.wayline.*; import com.ard.tianyu.netty.protobuf.TelemetryDataPB; import com.google.protobuf.InvalidProtocolBufferException; @@ -93,6 +96,11 @@ actionCode = in.readByte();//动作编号 baseCmd = processD1ReplyCmd(in, actionCode); break; case (byte) 0xD2: in.readByte();//加密标志 actionCode = in.readByte();//动作编号 baseCmd = processD2ReplyCmd(in, actionCode); break; default: in.readByte();//加密标志 actionCode = in.readByte(); @@ -134,8 +142,12 @@ return new WayLineResumeReplyCmd(boxSn, result, errorCode); case 0x20: return new WayLineEndReplyCmd(boxSn, result, errorCode); case 0x21: return new ReturnHeightSettingReplyCmd(boxSn, result, errorCode); case 0x29: return new LandForcedReplyCmd(boxSn, result, errorCode); case 0x31: return new ReturnPointSettingReplyCmd(boxSn, result, errorCode); case 0x32: return new EmergencyBrakeReplyCmd(boxSn, result, errorCode); case 0x39: @@ -156,11 +168,26 @@ return processSpecialD1ReplyCmd(in, actionCode, boxSn); // Add other cases... default: log.warn("无法识别的动作编号:{}", ByteUtils.byteToHex(actionCode)); log.warn("无法识别D1的动作编号:{}", ByteUtils.byteToHex(actionCode)); } return null; } //处理D1指令回复 private BaseCmd processD2ReplyCmd(ByteBuf in, byte actionCode) { byte result = in.readByte(); int errorCode = in.readInt(); byte[] uavData = new byte[15]; in.readBytes(uavData); String boxSn = new String(uavData); switch (actionCode) { case 0x05: return new VideoStreamSettingReplyCmd(boxSn, result, errorCode); // Add other cases... default: log.warn("无法识别D2的动作编号:{}", ByteUtils.byteToHex(actionCode)); } return null; } //处理特殊D1指令回复 private BaseCmd processSpecialD1ReplyCmd(ByteBuf in, byte actionCode, String boxSn) { switch (actionCode) { ard-work/src/main/java/com/ard/tianyu/service/ITyService.java
@@ -8,6 +8,9 @@ import com.ard.tianyu.model.dto.control.AngleControlDTO; import com.ard.tianyu.model.dto.control.SpeedControlDTO; import com.ard.tianyu.model.dto.manual.*; import com.ard.tianyu.model.dto.settings.ReturnHeightSettingDTO; import com.ard.tianyu.model.dto.settings.ReturnPointSettingDTO; import com.ard.tianyu.model.dto.settings.VideoStreamSettingDTO; import com.ard.tianyu.model.dto.signal.SignalInfo; import com.ard.tianyu.model.dto.speaker.*; import com.ard.tianyu.model.dto.state.UavState; @@ -65,6 +68,24 @@ Boolean updateBoxSettings(BoxSettingsDTO boxSettingsDTO); /** * 设置返航高度 * @return */ void updateReturnHeight(ReturnHeightSettingDTO returnHeightSettingDTO); /** * 设置视频码流 * @return */ void updateVideoStream(VideoStreamSettingDTO videoStreamSettingDTO); /** * 设置返航点 * @return */ void updateReturnPoint(ReturnPointSettingDTO returnPointSettingDTO); /** * 注册 */ void registerMessage(); ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java
@@ -19,6 +19,9 @@ import com.ard.tianyu.model.dto.converter.UavTelemetryDataConverter; import com.ard.tianyu.model.dto.converter.wayline.PlanLineDataConverter; import com.ard.tianyu.model.dto.manual.*; import com.ard.tianyu.model.dto.settings.ReturnHeightSettingDTO; import com.ard.tianyu.model.dto.settings.ReturnPointSettingDTO; import com.ard.tianyu.model.dto.settings.VideoStreamSettingDTO; import com.ard.tianyu.model.dto.signal.SignalInfo; import com.ard.tianyu.model.dto.speaker.*; import com.ard.tianyu.model.dto.state.UavState; @@ -39,6 +42,7 @@ import com.ard.tianyu.netty.command.real.UavStateCmd; import com.ard.tianyu.netty.command.real.UavTelemetryDataCmd; import com.ard.tianyu.netty.command.register.*; import com.ard.tianyu.netty.command.settings.*; import com.ard.tianyu.netty.command.speaker.*; import com.ard.tianyu.netty.command.wayline.*; import com.ard.tianyu.netty.handler.ErrorCodeEnum; @@ -146,6 +150,33 @@ public Boolean updateBoxSettings(BoxSettingsDTO boxSettingsDTO) { TyHttpCommonReceiver<?> result = tyClient.updateBoxSettings(boxSettingsDTO, tyConfiguration.getAccessToken().convertFromDTO()); return result.getState() == 1; } /** * 设置返航高度 */ @Override public void updateReturnHeight(ReturnHeightSettingDTO returnHeightSettingDTO) { ReturnHeightSettingCmd returnHeightSettingCmd = new ReturnHeightSettingCmd(returnHeightSettingDTO); this.sendMessage(tyConfiguration.getIpPort(), returnHeightSettingCmd); } /** * 设置返航点 */ @Override public void updateReturnPoint(ReturnPointSettingDTO returnPointSettingDTO) { ReturnPointSettingCmd returnPointSettingCmd = new ReturnPointSettingCmd(returnPointSettingDTO); this.sendMessage(tyConfiguration.getIpPort(), returnPointSettingCmd); } /** * 设置视频码流 */ @Override public void updateVideoStream(VideoStreamSettingDTO videoStreamSettingDTO) { VideoStreamSettingCmd videoStreamSettingCmd = new VideoStreamSettingCmd(videoStreamSettingDTO); this.sendMessage(tyConfiguration.getIpPort(), videoStreamSettingCmd); } /** @@ -704,6 +735,23 @@ WayLineEndReplyCmd wayLineEndReplyCmd = (WayLineEndReplyCmd) tyCommand; logPrint("结束航线", wayLineEndReplyCmd.getResult(), wayLineEndReplyCmd.getErrorCode()); } //设置返航高度回复 if (tyCommand instanceof ReturnHeightSettingReplyCmd) { ReturnHeightSettingReplyCmd returnHeightSettingReplyCmd = (ReturnHeightSettingReplyCmd) tyCommand; logPrint("设置返航高度", returnHeightSettingReplyCmd.getResult(), returnHeightSettingReplyCmd.getErrorCode()); } //设置返航点回复 if (tyCommand instanceof ReturnPointSettingReplyCmd) { ReturnPointSettingReplyCmd returnPointSettingReplyCmd = (ReturnPointSettingReplyCmd) tyCommand; logPrint("设置返航点", returnPointSettingReplyCmd.getResult(), returnPointSettingReplyCmd.getErrorCode()); } break; case (byte) 0xD2: //设置视频码流回复 if (tyCommand instanceof VideoStreamSettingReplyCmd) { VideoStreamSettingReplyCmd videoStreamSettingReplyCmd = (VideoStreamSettingReplyCmd) tyCommand; logPrint("设置视频码流", videoStreamSettingReplyCmd.getResult(), videoStreamSettingReplyCmd.getErrorCode()); } break; default: // 处理其他消息