Merge remote-tracking branch 'origin/dev' into dev
2 files added
21 files modified
| | |
| | | * 开始航线 |
| | | */ |
| | | @ApiOperation("开始航线") |
| | | @PostMapping("/routeBegins/{boxSn}") |
| | | public AjaxResult routeBegins(@PathVariable("boxSn") String boxSn) { |
| | | ardRouteInfoService.routeBegins(boxSn); |
| | | @PostMapping("/routeBegins/{id}/{boxSn}") |
| | | public AjaxResult routeBegins(@PathVariable("id") String id, |
| | | @PathVariable("boxSn") String boxSn) { |
| | | ardRouteInfoService.routeBegins(id,boxSn); |
| | | return AjaxResult.success(); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * 查询服务器管理列表 |
| | | */ |
| | | @ApiOperation("查询服务器管理列表") |
| | | @PreAuthorize("@ss.hasPermi('work:server:listNo')") |
| | | @GetMapping("/listNo") |
| | | public TableDataInfo listNo(ArdServerInfo ardServerInfo) { |
| | | startPage(); |
| | | List<ArdServerInfo> list = ardServerInfoService.selectArdServerInfoListNo(ardServerInfo); |
| | | return getDataTable(list); |
| | | } |
| | | |
| | | /** |
| | | * 导出服务器管理列表 |
| | | */ |
| | | @ApiOperation("导出服务器管理列表") |
| | |
| | | import com.ard.common.core.controller.BaseController; |
| | | import com.ard.common.core.domain.AjaxResult; |
| | | import com.ard.common.core.page.TableDataInfo; |
| | | import com.ard.work.domain.dto.BoxHistoryDTO; |
| | | import com.ard.work.domain.dto.BoxPhotosDTO; |
| | | import com.ard.work.domain.dto.BoxSettingsDTO; |
| | | import com.ard.work.domain.dto.UavFlightStateDTO; |
| | | import com.ard.work.domain.dto.*; |
| | | import com.ard.work.domain.dto.telemetry.TelemetryData; |
| | | import com.ard.work.domain.entity.ArdFlightTask; |
| | | import com.ard.work.domain.entity.ArdFlightTaskPart; |
| | | import com.ard.work.domain.entity.ArdMedia; |
| | | import com.ard.work.domain.receiver.BoxHistoryReceiver; |
| | | import com.ard.work.domain.receiver.BoxInfoReceiver; |
| | | import com.ard.work.domain.receiver.BoxPhotosReceiver; |
| | | import com.ard.work.domain.receiver.BoxStreamUrlReceiver; |
| | | import com.ard.work.domain.receiver.*; |
| | | import com.ard.work.service.IArdFlightTaskPartService; |
| | | import com.ard.work.service.IArdFlightTaskService; |
| | | import com.ard.work.service.IArdMediaService; |
| | |
| | | List<BoxHistoryReceiver> boxHistory = tyService.getBoxHistory(boxHistoryDTO); |
| | | return AjaxResult.success(boxHistory); |
| | | } |
| | | |
| | | @ApiOperation("获取飞行架次") |
| | | @ApiOperationSupport(order = 4) |
| | | @GetMapping("/getFlightTask") |
| | |
| | | @ApiOperation("获取架次飞行轨迹") |
| | | @ApiOperationSupport(order = 4) |
| | | @GetMapping("/getCompleteFlightData") |
| | | public TableDataInfo getCompleteFlightData(ArdFlightTaskPart ardFlightTaskPart){ |
| | | public TableDataInfo getCompleteFlightData(ArdFlightTaskPart ardFlightTaskPart) { |
| | | List<UavFlightStateDTO> completeFlightData = ardFlightTaskPartService.getCompleteFlightData(ardFlightTaskPart); |
| | | return getDataTable(completeFlightData); |
| | | } |
| | |
| | | return AjaxResult.success(boxPhotos); |
| | | } |
| | | |
| | | @ApiOperation("获取任务视频") |
| | | @ApiOperationSupport(order = 5) |
| | | @PostMapping("/getBoxVideos") |
| | | public AjaxResult getBoxVideos(@RequestBody BoxVideosDTO boxVideosDTO) { |
| | | List<BoxVideosReceiver> boxVideos = tyService.getBoxVideos(boxVideosDTO); |
| | | return AjaxResult.success(boxVideos); |
| | | } |
| | | |
| | | @ApiOperation("获取直播地址") |
| | | @ApiOperationSupport(order = 6) |
| | | @GetMapping("/getBoxLiveUrl/{boxSn}") |
| | |
| | | @Resource |
| | | private ITyService tyService; |
| | | |
| | | @ApiOperation(value = "设置相机模式", notes = "actionParam值:1-拍照,2-录像") |
| | | @ApiOperationSupport(order = 1) |
| | | @PostMapping("/updateCameraMode") |
| | | public AjaxResult updateCameraMode(@RequestBody CameraModeDTO cameraModeDTO) { |
| | | tyService.updateCameraMode(cameraModeDTO); |
| | | return AjaxResult.success(); |
| | | } |
| | | |
| | | @ApiOperation("拍照") |
| | | @ApiOperationSupport(order = 1) |
| | |
| | | import com.ard.work.service.control.UavControlService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.annotation.Resource; |
| | |
| | | * 申请控制权(请求通过 WebSocket 发送给当前控制者) |
| | | */ |
| | | @ApiOperation("申请控制权") |
| | | @PreAuthorize("@ss.hasPermi('uav:control:request')") |
| | | @PostMapping("/request") |
| | | public AjaxResult requestControl(@RequestParam String boxSn, @RequestParam String type) { |
| | | return AjaxResult.success(uavControlService.requestControl(boxSn, type)); |
| | |
| | | import io.minio.errors.*; |
| | | import io.minio.http.Method; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import okhttp3.ConnectionPool; |
| | | import okhttp3.ConnectionSpec; |
| | | import okhttp3.OkHttpClient; |
| | | import okhttp3.TlsVersion; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.net.ssl.SSLContext; |
| | |
| | | import java.security.ProviderException; |
| | | import java.security.SecureRandom; |
| | | import java.security.cert.X509Certificate; |
| | | import java.util.Collections; |
| | | import java.util.Objects; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | import static com.ard.common.config.OssConfiguration.*; |
| | | |
| | |
| | | }; |
| | | SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); |
| | | sslContext.init(null, trustAllCerts, new SecureRandom()); |
| | | |
| | | ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) |
| | | .tlsVersions(TlsVersion.TLS_1_2) |
| | | .allEnabledCipherSuites() |
| | | .build(); |
| | | |
| | | OkHttpClient httpClient = new OkHttpClient.Builder() |
| | | .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0]) |
| | | .sslSocketFactory(sslContext.getSocketFactory(), |
| | | (X509TrustManager) trustAllCerts[0]) |
| | | .hostnameVerifier((hostname, session) -> true) |
| | | .connectionSpecs(Collections.singletonList(spec)) // ⭐关键 |
| | | .connectionPool(new ConnectionPool(0, 1, TimeUnit.SECONDS)) // ⭐禁用复用 |
| | | .build(); |
| | | |
| | | // 构建 AssumeRoleProvider,使用自定义 httpClient |
| | |
| | | OkHttpClient httpClient = new OkHttpClient.Builder() |
| | | .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]) |
| | | .hostnameVerifier((hostname, session) -> true) |
| | | .connectionSpecs(Collections.singletonList( |
| | | new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) |
| | | .tlsVersions(TlsVersion.TLS_1_2) // 强制 TLS1.2 |
| | | .build() |
| | | )) |
| | | .build(); |
| | | |
| | | this.client = MinioClient.builder() |
| | |
| | | @Excel(name = "文件路径") |
| | | private String path; |
| | | |
| | | // /** 文件路径1 */ |
| | | // @Excel(name = "文件路径1") |
| | | // private String path1; |
| | | |
| | | /** 分组ID */ |
| | | @Excel(name = "分组ID") |
| | | private String groupId; |
| | |
| | | private String payload; |
| | | |
| | | /** |
| | | * 是否只读 是否只读 |
| | | * 是否只读 |
| | | * 0:否 |
| | | * 1:是 |
| | | */ |
| | |
| | | private String orderByTime; |
| | | |
| | | /** |
| | | * 是否循环 isLoop |
| | | * 0:否 |
| | | * 1:是 |
| | | */ |
| | | @Excel(name = "是否循环") |
| | | private String isLoop; |
| | | |
| | | /** |
| | | * 生成kmz文件实体类 |
| | | */ |
| | | private UavRouteReq uavRouteReq; |
| | |
| | | * @param boxSn 云盒SN编号 |
| | | * @return 结果 |
| | | */ |
| | | public Boolean routeBegins(String boxSn); |
| | | public Boolean routeBegins(String id, String boxSn); |
| | | |
| | | /** |
| | | * 暂停航线 |
| | |
| | | import com.ard.route.mapper.ArdRouteInfoMapper; |
| | | import com.ard.route.service.IArdRouteInfoService; |
| | | import com.ard.route.service.UavRouteService; |
| | | import com.ard.work.domain.cache.UavTelemetryDataCache; |
| | | import com.ard.work.domain.cache.UavWaylineCache; |
| | | import com.ard.work.domain.dto.state.PointData; |
| | | import com.ard.work.domain.dto.telemetry.TelemetryData; |
| | | import com.ard.work.domain.dto.wayline.*; |
| | | import com.ard.work.service.ITyService; |
| | | import org.slf4j.Logger; |
| | |
| | | throw new RuntimeException(e); |
| | | } |
| | | |
| | | // 主逻辑优化 |
| | | double altitudeOffset = getDoublePoint(ardRouteInfo.getUavRouteReq().getTakeOffRefPoint(), "alt"); |
| | | // 如果参考起飞点不为空,将每个航点高度进行加工。 |
| | | if (ardRouteInfo.getUavRouteReq().getTakeOffRefPoint() != null){ |
| | | |
| | | for (RoutePointReq routePointReq : ardRouteInfo.getUavRouteReq().getRoutePointList()) { |
| | | // 调整航点高度 |
| | | adjustRoutePointHeight(routePointReq, altitudeOffset); |
| | | double altitudeOffset = getDoublePoint(ardRouteInfo.getUavRouteReq().getTakeOffRefPoint(), "alt"); |
| | | |
| | | for (RoutePointReq routePointReq : ardRouteInfo.getUavRouteReq().getRoutePointList()) { |
| | | // 调整每个航点高度 |
| | | adjustRoutePointHeight(routePointReq, altitudeOffset); |
| | | } |
| | | }else { |
| | | // 如果没有设置参考起飞点,将第一个航点设置为参考起飞点。 |
| | | ardRouteInfo.getUavRouteReq().setTakeOffRefPoint( |
| | | ardRouteInfo.getUavRouteReq().getRoutePointList().get(0).getLatitude().toString() +"," + |
| | | ardRouteInfo.getUavRouteReq().getRoutePointList().get(0).getLongitude().toString()+","+ |
| | | ardRouteInfo.getUavRouteReq().getRoutePointList().get(0).getHeight().toString()); |
| | | } |
| | | |
| | | return ardRouteInfo; |
| | | } |
| | | |
| | | // 提取航点高度调整逻辑到方法中 |
| | | private void adjustRoutePointHeight(RoutePointReq routePointReq, double altitudeOffset) { |
| | | routePointReq.setHeight(routePointReq.getHeight() + altitudeOffset); |
| | | } |
| | |
| | | */ |
| | | @Override |
| | | public int deleteArdRouteInfoById(String id) { |
| | | // 删除航线(kmz)文件 |
| | | ArdRouteInfo information = ardRouteInfoMapper.selectArdRouteInfoById(id); |
| | | delOssService(information); |
| | | return ardRouteInfoMapper.deleteArdRouteInfoById(id); |
| | | } |
| | | |
| | |
| | | |
| | | /** |
| | | * 上传航线到边缘服务器 |
| | | * |
| | | * ardNoflyDto |
| | | * @return 结果 |
| | | */ |
| | |
| | | } catch (IOException | ClassNotFoundException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | |
| | | // 获取第一个点 |
| | | double firstPointLng = route.getUavRouteReq().getRoutePointList().get(0).getLongitude(); |
| | | double firstPointLat = route.getUavRouteReq().getRoutePointList().get(0).getLatitude(); |
| | | |
| | | // 获取最后一个点 |
| | | double lastPointLng = route.getUavRouteReq().getRoutePointList().get(route.getUavRouteReq().getRoutePointList().size()-1).getLongitude(); |
| | | double lastPointLat = route.getUavRouteReq().getRoutePointList().get(route.getUavRouteReq().getRoutePointList().size()-1).getLatitude(); |
| | | |
| | | // 无人机遥测数据,用于校验真实起飞点和第一个点是否在禁飞区 |
| | | TelemetryData telemetryData = UavTelemetryDataCache.get(boxSn); |
| | | double telemetryDataLng = 0; |
| | | double telemetryDataLat = 0; |
| | | if (telemetryData != null){ |
| | | telemetryDataLng = telemetryData.getLng(); |
| | | telemetryDataLat = telemetryData.getLat(); |
| | | } |
| | | |
| | | ArdNoflyDto dto1 = new ArdNoflyDto(); |
| | | dto1.setCurrent(new Vertex(telemetryDataLng,telemetryDataLat)); |
| | | dto1.setTarget(new Vertex(firstPointLng,firstPointLat)); |
| | | verifyNoFlyZone(dto1); |
| | | |
| | | ArdNoflyDto dto2 = new ArdNoflyDto(); |
| | | dto2.setCurrent(new Vertex(lastPointLng,lastPointLat)); |
| | | dto2.setTarget(new Vertex(telemetryDataLng,telemetryDataLat)); |
| | | verifyNoFlyZone(dto2); |
| | | |
| | | // 判断禁飞区 |
| | | arrayWithinNoFlyZone(route.getUavRouteReq().getRoutePointList()); |
| | | // 1.2通过minio获取航线信息 |
| | |
| | | * @return 结果 |
| | | */ |
| | | @Override |
| | | public Boolean routeBegins(String boxSn) { |
| | | public Boolean routeBegins(String id,String boxSn) { |
| | | ArdRouteInfo route = ardRouteInfoMapper.selectArdRouteInfoById(id); |
| | | // 判断是否循环航线 |
| | | if ("1".equals(route.getIsLoop())) { |
| | | deleteArdRouteInfoById(id); |
| | | } |
| | | WayLineBeginDTO wayLineBeginDTO = new WayLineBeginDTO(boxSn); |
| | | tyService.wayLineBegin(wayLineBeginDTO); |
| | | return true; |
| | |
| | | <result property="id" column="id" /> |
| | | <result property="name" column="name" /> |
| | | <result property="path" column="path" /> |
| | | <!-- <result property="path1" column="path1" />--> |
| | | <result property="groupId" column="group_id" /> |
| | | <result property="type" column="type" /> |
| | | <result property="aircraft" column="aircraft" /> |
| | |
| | | <result property="updateBy" column="update_by" /> |
| | | <result property="updateTime" column="update_time" /> |
| | | <result property="pointCount" column="point_count" /> |
| | | <result property="isLoop" column="is_loop" /> |
| | | </resultMap> |
| | | |
| | | <sql id="selectArdRouteInfoVo"> |
| | | select id, |
| | | name, |
| | | path, |
| | | <!-- path1,--> |
| | | group_id, |
| | | type, |
| | | aircraft, |
| | |
| | | create_time, |
| | | update_by, |
| | | update_time, |
| | | point_count |
| | | point_count, |
| | | is_loop |
| | | from ard_route_info |
| | | </sql> |
| | | |
| | |
| | | <if test="type != null and type != ''"> and type = #{type}</if> |
| | | <if test="path != null and path != ''"> and path = #{path}</if> |
| | | <if test="groupId != null"> and group_id = #{groupId}</if> |
| | | <if test="isLoop != null"> and is_loop = #{isLoop}</if> |
| | | </where> |
| | | <if test="orderByTime == null and orderByTime == ''"> |
| | | ORDER BY update_time DESC |
| | |
| | | <if test="id != null">id,</if> |
| | | <if test="name != null">name,</if> |
| | | <if test="path != null">path,</if> |
| | | <!-- <if test="path1 != null">path1,</if>--> |
| | | <if test="groupId != null">group_id,</if> |
| | | <if test="type != null">type,</if> |
| | | <if test="aircraft != null">aircraft,</if> |
| | |
| | | <if test="updateBy != null">update_by,</if> |
| | | <if test="updateTime != null">update_time,</if> |
| | | <if test="pointCount != null">point_count,</if> |
| | | <if test="isLoop != null">is_loop,</if> |
| | | </trim> |
| | | <trim prefix="values (" suffix=")" suffixOverrides=","> |
| | | <if test="id != null">#{id},</if> |
| | | <if test="name != null">#{name},</if> |
| | | <if test="path != null">#{path},</if> |
| | | <!-- <if test="path1 != null">#{path1},</if>--> |
| | | <if test="groupId != null">#{groupId},</if> |
| | | <if test="type != null">#{type},</if> |
| | | <if test="aircraft != null">#{aircraft},</if> |
| | |
| | | <if test="updateBy != null">#{updateBy},</if> |
| | | <if test="updateTime != null">#{updateTime},</if> |
| | | <if test="pointCount != null">#{pointCount},</if> |
| | | <if test="isLoop != null">#{isLoop},</if> |
| | | </trim> |
| | | </insert> |
| | | |
| | |
| | | <trim prefix="SET" suffixOverrides=","> |
| | | <if test="name != null">name = #{name},</if> |
| | | <if test="path != null">path = #{path},</if> |
| | | <!-- <if test="path1 != null">path1 = #{path1},</if>--> |
| | | <if test="groupId != null">group_id = #{groupId},</if> |
| | | <if test="type != null">type = #{type},</if> |
| | | <if test="aircraft != null">aircraft = #{aircraft},</if> |
| | |
| | | <if test="updateBy != null">update_by = #{updateBy},</if> |
| | | <if test="updateTime != null">update_time = #{updateTime},</if> |
| | | <if test="pointCount != null">point_count = #{pointCount},</if> |
| | | <if test="isLoop != null">is_loop = #{isLoop},</if> |
| | | </trim> |
| | | where id = #{id} |
| | | </update> |
| | |
| | | </delete> |
| | | |
| | | <select id="selectArdRouteInfoByGroupId" parameterType="String" resultMap="ArdRouteInfoResult"> |
| | | select id,name,path,group_id,type,aircraft,payload,read_only,create_by,create_time,update_by,update_time,point_count from ard_route_info |
| | | select id,name,path,group_id,type,aircraft,payload,read_only,create_by,create_time,update_by,update_time,point_count,is_loop from ard_route_info |
| | | <where> |
| | | <if test="groupId != null "> and group_id = #{groupId}</if> |
| | | </where> |
| | |
| | | package com.ard.work.component.forest; |
| | | |
| | | import com.ard.work.domain.dto.BoxHistoryDTO; |
| | | import com.ard.work.domain.dto.BoxPhotosDTO; |
| | | import com.ard.work.domain.dto.BoxSettingsDTO; |
| | | import com.ard.work.domain.dto.TokenDTO; |
| | | import com.ard.work.domain.dto.*; |
| | | import com.ard.work.domain.receiver.*; |
| | | import com.dtflys.forest.annotation.*; |
| | | |
| | |
| | | @Post(value = TyConst.POST_BOX_HISTORY, interceptor = TokenInterceptor.class) |
| | | TyHttpCommonReceiver<List<BoxHistoryReceiver>> getBoxHistory(@Var("serverId") String serverId, |
| | | @JSONBody BoxHistoryDTO boxHistoryDTO); |
| | | |
| | | /** |
| | | * 获取任务照片 |
| | | */ |
| | | @Post(value = TyConst.POST_BOX_PHOTOS, interceptor = TokenInterceptor.class) |
| | | TyHttpCommonReceiver<List<BoxPhotosReceiver>> getBoxPhotos(@Var("serverId") String serverId, |
| | | @JSONBody BoxPhotosDTO boxPhotosDTO); |
| | | /** |
| | | * 获取任务视频 |
| | | */ |
| | | @Post(value = TyConst.POST_BOX_VIDEOS, interceptor = TokenInterceptor.class) |
| | | TyHttpCommonReceiver<List<BoxVideosReceiver>> getBoxVideos(@Var("serverId") String serverId, |
| | | @JSONBody BoxVideosDTO boxVideosDTO); |
| | | |
| | | /** |
| | | * 修改云盒设置 |
| | |
| | | public static final String POST_UPDATE_LIVE = "/eapi/update/live"; |
| | | public static final String GET_BOX_LIVE_URL = "/eapi/box/pullUrl/{boxSn}"; |
| | | public static final String POST_BOX_PHOTOS = "/eapi/box/photos"; |
| | | public static final String POST_BOX_VIDEOS = "/eapi/box/videos"; |
| | | public static final String GET_OPEN_LIVE = "/eapi/box/openlive/{boxSn}"; |
| | | public static final String GET_CLOSE_LIVE = "/eapi/box/closelive/{boxSn}"; |
| | | } |
| New file |
| | |
| | | package com.ard.work.domain.dto; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonProperty; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class BoxVideosDTO { |
| | | |
| | | @JsonProperty("boxSn") |
| | | private String boxSn; |
| | | |
| | | @JsonProperty("taskId") |
| | | private Integer taskId; |
| | | |
| | | @JsonProperty("pageIndex") |
| | | private Integer pageIndex; |
| | | |
| | | @JsonProperty("pageSize") |
| | | private Integer pageSize; |
| | | |
| | | } |
| | |
| | | import com.ard.common.core.domain.BaseEntity; |
| | | import lombok.*; |
| | | |
| | | import java.util.Date; |
| | | |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @Data |
| | | @Builder |
| | |
| | | private String boxSn; |
| | | private Integer count; |
| | | private byte[] dataPart; |
| | | private Date startTime; |
| | | private Date endTime; |
| | | |
| | | } |
| New file |
| | |
| | | package com.ard.work.domain.receiver; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
| | | import com.fasterxml.jackson.annotation.JsonProperty; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @JsonIgnoreProperties(ignoreUnknown = true) |
| | | public class BoxVideosReceiver { |
| | | |
| | | @JsonProperty("id") |
| | | private Long id; |
| | | |
| | | @JsonProperty("taskId") |
| | | private Long taskId; |
| | | |
| | | @JsonProperty("name") |
| | | private String name; |
| | | |
| | | @JsonProperty("spanSeconds") |
| | | private String spanSeconds; |
| | | |
| | | @JsonProperty("uri") |
| | | private String imgUrl; |
| | | |
| | | @JsonProperty("startTime") |
| | | private String startTime; |
| | | |
| | | @JsonProperty("endTime") |
| | | private String endTime; |
| | | |
| | | } |
| | |
| | | public interface ArdFlightTaskPartMapper { |
| | | |
| | | /** |
| | | * 根据 taskId 查询分片 |
| | | */ |
| | | List<ArdFlightTaskPart> selectByTaskId(int taskId); |
| | | /** |
| | | * 根据 boxSn 和航线开始结束时间查询分片 |
| | | * 根据开始结束时间查询分片 |
| | | * @return 对应时间段的分片列表 |
| | | */ |
| | | List<ArdFlightTaskPart> selectByTaskStartTime(ArdFlightTaskPart ardFlightTaskPart); |
| | | List<ArdFlightTaskPart> selectByTimeRange(ArdFlightTaskPart ardFlightTaskPart); |
| | | |
| | | int insert(ArdFlightTaskPart entity); |
| | | } |
| | |
| | | */ |
| | | public List<ArdServerInfo> selectArdServerInfoList(ArdServerInfo ardServerInfo); |
| | | |
| | | public List<ArdServerInfo> selectArdServerInfoListNo(ArdServerInfo ardServerInfo); |
| | | |
| | | /** |
| | | * 新增服务器管理 |
| | | * |
| | |
| | | import com.ard.work.domain.dto.BoxHistoryDTO; |
| | | import com.ard.work.domain.dto.BoxPhotosDTO; |
| | | import com.ard.work.domain.dto.BoxSettingsDTO; |
| | | import com.ard.work.domain.dto.BoxVideosDTO; |
| | | import com.ard.work.domain.dto.camera.*; |
| | | import com.ard.work.domain.dto.manual.*; |
| | | import com.ard.work.domain.dto.speaker.*; |
| | |
| | | |
| | | /** |
| | | * 获取边缘服务器token信息 |
| | | * |
| | | * @return |
| | | */ |
| | | AccessTokenReceiver getAccessToken(String ServerId); |
| | | |
| | | /** |
| | | * 获取全部服务器云盒列表 |
| | | * |
| | | * @return |
| | | */ |
| | | List<BoxInfoReceiver> getBoxList(); |
| | |
| | | |
| | | /** |
| | | * 获取直播地址 |
| | | * |
| | | * @return |
| | | */ |
| | | BoxStreamUrlReceiver getBoxLiveUrl(@Var("boxSn") String boxSn); |
| | | |
| | | /** |
| | | * 获取飞行历史 |
| | | * |
| | | * @return |
| | | */ |
| | | List<BoxHistoryReceiver> getBoxHistory(BoxHistoryDTO boxHistoryDTO); |
| | | |
| | | /** |
| | | * 获取盒子图片 |
| | | * 获取任务图片 |
| | | * |
| | | * @return |
| | | */ |
| | | List<BoxPhotosReceiver> getBoxPhotos(BoxPhotosDTO boxPhotosDTO); |
| | | |
| | | /** |
| | | * 获取任务视频 |
| | | * |
| | | * @return |
| | | */ |
| | | List<BoxVideosReceiver> getBoxVideos(BoxVideosDTO boxVideosDTO); |
| | | |
| | | /** |
| | | * 修改云盒设置 |
| | | * |
| | | * @return |
| | | */ |
| | | Boolean updateBoxSettings(BoxSettingsDTO boxSettingsDTO); |
| | | |
| | | /** |
| | | * 设置返航高度 |
| | | * |
| | | * @return |
| | | */ |
| | | Boolean updateReturnHeight(ReturnHeightSettingDTO returnHeightSettingDTO); |
| | | |
| | | /** |
| | | * 设置视频码流 |
| | | * |
| | | * @return |
| | | */ |
| | | Boolean updateVideoStream(VideoStreamSettingDTO videoStreamSettingDTO); |
| | | |
| | | /** |
| | | * 设置返航点 |
| | | * |
| | | * @return |
| | | */ |
| | | Boolean updateReturnPoint(ReturnPointSettingDTO returnPointSettingDTO); |
| | |
| | | import org.springframework.scheduling.annotation.Async; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Comparator; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | /** |
| | | * 轨迹分片处理业务 |
| | | */ |
| | |
| | | public class ArdFlightTaskPartServiceImpl implements IArdFlightTaskPartService { |
| | | |
| | | private final ArdFlightTaskPartMapper ardflightTaskPartMapper; |
| | | |
| | | // 上一次飞行状态缓存 |
| | | private final ConcurrentHashMap<String, Integer> lastFlightStatusMap = new ConcurrentHashMap<>(); |
| | | /** |
| | | * 缓存:boxSn -> 当前分片数据 |
| | | */ |
| | |
| | | return; // 超过 3 秒没有新遥测 → 认为已离线或冻结,不记录 |
| | | } |
| | | |
| | | // 3️⃣ 飞行状态必须是飞行中 |
| | | if(uavState.getFlightControllerState().getFlightStatus()!=2) |
| | | { |
| | | return; // 飞行状态不是飞行中,不记录 |
| | | } |
| | | int currentStatus = uavState.getFlightControllerState().getFlightStatus(); |
| | | Integer lastStatus = lastFlightStatusMap.get(boxSn); |
| | | |
| | | // 仅在“飞行中 → 非飞行中”状态变化时 flush |
| | | if (lastStatus != null && lastStatus == 2 && currentStatus != 2) { |
| | | flushRemaining(boxSn); |
| | | } |
| | | lastFlightStatusMap.put(boxSn, currentStatus); |
| | | |
| | | // 只有飞行中才添加缓存 |
| | | if (currentStatus == 2) { |
| | | UavFlightStateDTO dto = new UavFlightStateDTO(uavState, telemetryData, dataTs); |
| | | addTelemetryData(dto); |
| | | } |
| | | UavFlightStateDTO dto = new UavFlightStateDTO( |
| | | uavState, |
| | | telemetryData, |
| | |
| | | |
| | | try { |
| | | byte[] blobData = SerializeUtil.serialize(dataList); |
| | | |
| | | // 取第一个和最后一个状态时间 |
| | | long startTs = dataList.get(0).getTimestamp(); |
| | | long endTs = dataList.get(dataList.size() - 1).getTimestamp(); |
| | | ArdFlightTaskPart part = ArdFlightTaskPart.builder() |
| | | .boxSn(boxSn) |
| | | .count(dataList.size()) |
| | | .dataPart(blobData) |
| | | .startTime(new Date(startTs)) |
| | | .endTime(new Date(endTs)) |
| | | .build(); |
| | | // 使用 list 中第一条数据的时间作为 createTime |
| | | long firstTimeMillis = dataList.get(0).getTimestamp(); |
| | | Date createTime = new Date(firstTimeMillis); |
| | | part.setCreateTime(createTime); |
| | | part.setCreateTime(new Date()); |
| | | ardflightTaskPartMapper.insert(part); |
| | | |
| | | log.info("设备 {} 分片保存 {} 条飞行数据到数据库成功", boxSn, dataList.size()); |
| | |
| | | public List<UavFlightStateDTO> getCompleteFlightData(ArdFlightTaskPart ardFlightTaskPart) { |
| | | List<UavFlightStateDTO> allData = new ArrayList<>(); |
| | | String boxSn = ardFlightTaskPart.getBoxSn(); |
| | | List<ArdFlightTaskPart> parts = ardflightTaskPartMapper.selectByTaskStartTime(ardFlightTaskPart); |
| | | List<ArdFlightTaskPart> parts = ardflightTaskPartMapper.selectByTimeRange(ardFlightTaskPart); |
| | | for (ArdFlightTaskPart part : parts) { |
| | | try { |
| | | List<UavFlightStateDTO> partData = SerializeUtil.deserialize(part.getDataPart()); |
| | |
| | | import com.ard.work.component.forest.TyClient; |
| | | import com.ard.work.component.netty.TyTcpClientManager; |
| | | import com.ard.work.domain.dto.TokenDTO; |
| | | import com.ard.work.domain.entity.ArdDroneInfo; |
| | | import com.ard.work.domain.entity.ArdServerInfo; |
| | | import com.ard.work.domain.receiver.AccessTokenReceiver; |
| | | import com.ard.work.domain.receiver.TyHttpCommonReceiver; |
| | | import com.ard.work.mapper.ArdDroneInfoMapper; |
| | | import com.ard.work.mapper.ArdServerInfoMapper; |
| | | import com.ard.work.service.IArdServerInfoService; |
| | | import com.dtflys.forest.exceptions.ForestRuntimeException; |
| | |
| | | public class ArdServerInfoServiceImpl implements IArdServerInfoService { |
| | | |
| | | @Resource |
| | | private ArdServerInfoMapper ardServerInfoMapper; |
| | | @Resource |
| | | private TyClient tyClient; |
| | | |
| | | @Resource |
| | | private ArdServerInfoMapper ardServerInfoMapper; |
| | | |
| | | @Resource |
| | | private TyTcpClientManager tyTcpClientManager; |
| | | |
| | | @Resource |
| | | private ArdDroneInfoMapper ArdDroneInfoMapper; |
| | | |
| | | /** |
| | | * 查询服务器管理 |
| | |
| | | return ardServerInfoMapper.selectArdServerInfoList(ardServerInfo); |
| | | } |
| | | |
| | | @Override |
| | | @DataScope(deptAlias = "d", userAlias = "u") |
| | | public List<ArdServerInfo> selectArdServerInfoListNo(ArdServerInfo ardServerInfo) { |
| | | |
| | | // List<ArdDroneInfo> ardDroneInfos = ArdDroneInfoMapper.selectArdDroneList(new ArdDroneInfo()); |
| | | // for (ArdDroneInfo ardDroneInfo : ardDroneInfos) { |
| | | // ardDroneInfo.getBoxSn(); |
| | | // } |
| | | // List<ArdServerInfo> servers = ardServerInfoMapper.selectArdServerInfoList(ardServerInfo); |
| | | // for (ArdServerInfo server : servers) { |
| | | // for (ArdDroneInfo ardDroneInfo : server.getArdDroneInfoList()) { |
| | | // ardDroneInfo.getBoxSn(); |
| | | // } |
| | | // } |
| | | |
| | | return ardServerInfoMapper.selectArdServerInfoList(ardServerInfo); |
| | | } |
| | | |
| | | /** |
| | | * 新增服务器管理 |
| | | * |
| | |
| | | import com.ard.work.domain.dto.BoxHistoryDTO; |
| | | import com.ard.work.domain.dto.BoxPhotosDTO; |
| | | import com.ard.work.domain.dto.BoxSettingsDTO; |
| | | import com.ard.work.domain.dto.BoxVideosDTO; |
| | | import com.ard.work.domain.dto.camera.*; |
| | | import com.ard.work.domain.dto.control.AbsAngleControlDTO; |
| | | import com.ard.work.domain.dto.control.AngleControlDTO; |
| | |
| | | } |
| | | |
| | | /** |
| | | * 获取盒子图片 |
| | | * 获取任务图片 |
| | | * |
| | | * @return List<BoxPhotosReceiver> |
| | | */ |
| | |
| | | boxPhotosDTO); |
| | | return boxPhotos == null ? null : boxPhotos.getContent(); |
| | | } |
| | | |
| | | /** |
| | | * 获取任务视频 |
| | | * |
| | | * @return List<BoxVideosReceiver> |
| | | */ |
| | | @Override |
| | | public List<BoxVideosReceiver> getBoxVideos(BoxVideosDTO boxVideosDTO) { |
| | | String boxSn = boxVideosDTO.getBoxSn(); |
| | | ArdDroneInfo ardDroneInfo = ardDroneService.selectArdDroneByboxSn(boxSn); |
| | | if (ardDroneInfo == null) { |
| | | throw new ControlException("未找到对应的飞行器信息,boxSn:{}" + boxSn); |
| | | } |
| | | TyHttpCommonReceiver<List<BoxVideosReceiver>> boxVideos = tyClient.getBoxVideos(ardDroneInfo.getServerId(), |
| | | boxVideosDTO); |
| | | return boxVideos == null ? null : boxVideos.getContent(); |
| | | } |
| | | /** |
| | | * 修改云盒设置 |
| | | */ |
| | |
| | | throw new ControlException("未找到对应的飞行器信息,boxSn:{}" + boxSn); |
| | | } |
| | | //设置相机模式为拍照模式 |
| | | updateCameraMode(CameraModeDTO.builder().boxSn(capturePicDto.getBoxSn()).actionParam((byte) 0x01).build()); |
| | | //updateCameraMode(CameraModeDTO.builder().boxSn(capturePicDto.getBoxSn()).actionParam((byte) 0x01).build()); |
| | | //设置拍照回传 |
| | | photoReturnToggle(PhotoReturnToggleDTO.builder().boxSn(capturePicDto.getBoxSn()).actionParam((byte) 0x01).build()); |
| | | //photoReturnToggle(PhotoReturnToggleDTO.builder().boxSn(capturePicDto.getBoxSn()).actionParam((byte) 0x01) |
| | | // .build()); |
| | | |
| | | CapturePicCmd capturePicCommand = new CapturePicCmd(capturePicDto); |
| | | this.sendMessage(ardDroneInfo.getServerId(), capturePicCommand); |
| | |
| | | } |
| | | BaseCmd baseCmd; |
| | | if (recordDto.getIsRecord()) { |
| | | updateCameraMode(CameraModeDTO.builder().boxSn(recordDto.getBoxSn()).actionParam((byte) 0x02).build()); |
| | | //updateCameraMode(CameraModeDTO.builder().boxSn(recordDto.getBoxSn()).actionParam((byte) 0x02).build()); |
| | | baseCmd = new RecordStartCmd(recordDto); |
| | | } else { |
| | | baseCmd = new RecordStopCmd(recordDto); |
| | |
| | | AND aft.create_time >= #{params.beginTime} |
| | | </if> |
| | | <if test="params.endTime != null"><!-- 结束时间检索 --> |
| | | ANDaft.create_time <= #{params.endTime} |
| | | AND aft.create_time <= #{params.endTime} |
| | | </if> |
| | | </trim> |
| | | </where> |
| | |
| | | <!-- 插入一条分片数据 --> |
| | | <insert id="insert" parameterType="ArdFlightTaskPart" useGeneratedKeys="true" keyProperty="id"> |
| | | INSERT INTO ard_flight_task_part |
| | | (box_sn, count, data_part, create_time) |
| | | VALUES |
| | | (#{boxSn}, #{count}, #{dataPart}, #{createTime}) |
| | | (box_sn, count, data_part, start_time, end_time, create_time) |
| | | VALUES (#{boxSn}, #{count}, #{dataPart}, #{startTime}, #{endTime}, #{createTime}) |
| | | </insert> |
| | | <select id="selectByTaskStartTime" resultType="ArdFlightTaskPart"> |
| | | <select id="selectByTimeRange" resultType="ArdFlightTaskPart"> |
| | | SELECT * |
| | | FROM ard_flight_task_part u |
| | | WHERE u.box_sn = #{boxSn} |
| | | <if test="params.beginTime != null"><!-- 开始时间检索 --> |
| | | AND u.create_time >= #{params.beginTime} |
| | | </if> |
| | | <if test="params.endTime != null"><!-- 结束时间检索 --> |
| | | AND u.create_time <= #{params.endTime} |
| | | </if> |
| | | ORDER BY u.create_time asc |
| | | <where> |
| | | u.box_sn = #{boxSn} |
| | | <!-- 动态参数中的开始时间 --> |
| | | <if test="params.beginTime != null"> |
| | | AND u.end_time >= #{params.beginTime} <!-- blob 内最后状态 >= 架次起飞 --> |
| | | </if> |
| | | <!-- 动态参数中的结束时间 --> |
| | | <if test="params.endTime != null"> |
| | | AND u.start_time <= #{params.endTime} <!-- blob 内第一状态 <= 架次降落 --> |
| | | </if> |
| | | </where> |
| | | ORDER BY u.start_time ASC |
| | | </select> |
| | | |
| | | |
| | | |
| | | |
| | | </mapper> |