Merge remote-tracking branch 'origin/dev' into dev
3 files added
10 files modified
| | |
| | | @Excel(name = "负载类型") |
| | | private String payload; |
| | | |
| | | /** 是否只读 是否只读0:否 1:是 */ |
| | | /** |
| | | * 是否只读 是否只读 |
| | | * 0:否 |
| | | * 1:是 |
| | | */ |
| | | @Excel(name = "是否只读") |
| | | private String readOnly; |
| | | |
| | | /** 时间排序 |
| | | /** |
| | | * 时间排序 |
| | | * 0:正序 |
| | | * 1:倒序 |
| | | */ |
| | |
| | | /** 文件路径 */ |
| | | private String path; |
| | | |
| | | /** 文件路径 */ |
| | | private String pathDock; |
| | | |
| | | /** 返回数据 */ |
| | | private String data; |
| | | |
| | |
| | | import com.ard.data.noflyzone.domain.Vertex; |
| | | import com.ard.data.noflyzone.service.IArdNoFlyZoneService; |
| | | import com.ard.data.noflyzone.utils.NoFlyZoneUtils; |
| | | import com.ard.framework.web.service.TokenService; |
| | | import com.ard.oss.model.MinioUploadResult; |
| | | import com.ard.oss.service.impl.OssServiceContext; |
| | | import com.ard.ossdock.service.impl.OssDockServiceContext; |
| | |
| | | import com.ard.work.domain.dto.state.PointData; |
| | | import com.ard.work.domain.dto.wayline.*; |
| | | import com.ard.work.service.ITyService; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | import static com.ard.route.util.InitializationUtils.divided_6; |
| | | import static com.ard.route.util.ToolUtils.*; |
| | | import static com.ard.route.util.UavRouteReqUtils.fileConversionEntity; |
| | | |
| | |
| | | */ |
| | | @Service |
| | | public class ArdRouteInfoServiceImpl implements IArdRouteInfoService { |
| | | |
| | | private static final Logger log = LoggerFactory.getLogger(TokenService.class); |
| | | |
| | | @Autowired |
| | | private ArdRouteInfoMapper ardRouteInfoMapper; |
| | |
| | | } |
| | | for (RoutePointReq routePointReq : ardRouteInfo.getUavRouteReq().getRoutePointList()) { |
| | | routePointReq.setHeight(routePointReq.getHeight() + getDoublePoint(ardRouteInfo.getUavRouteReq().getTakeOffRefPoint(),"alt")); |
| | | // 判断无人机类型 |
| | | if (ardRouteInfo.getUavRouteReq().getDroneType().equals(89)){ |
| | | for (ActionGroupReq actionGroupReq : routePointReq.getActionGroupList()) { |
| | | for (PointActionReq action : actionGroupReq.getActions()) { |
| | | action.setZoom(divided_6(action.getZoom())); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return ardRouteInfo; |
| | | } |
| | |
| | | } |
| | | ardRouteInfo.setPath(kmzResult.getPath()); |
| | | } |
| | | ardRouteInfo.setReadOnly("0"); |
| | | return ardRouteInfoMapper.updateArdRouteInfo(dataProcessing(ardRouteInfo)); |
| | | } |
| | | |
| | |
| | | ardRouteInfo.setType(templateTypeData(uavRouteReq)); |
| | | ardRouteInfo.setAircraft(droneTypeData(uavRouteReq)); |
| | | } |
| | | |
| | | // 判断禁飞区 |
| | | // List<RoutePointReq> routePointList = ardRouteInfo.getUavRouteReq().getRoutePointList(); |
| | | // for (RoutePointReq routePointReq : routePointList) { |
| | | // ArdNoflyDto ardNoflyDto = new ArdNoflyDto(); |
| | | // ardNoflyDto.setCurrent(new Vertex(routePointReq.getLongitude(), routePointReq.getLatitude())); |
| | | // verifyNoFlyZone(ardNoflyDto); |
| | | // } |
| | | try { |
| | | arrayWithinNoFlyZone(ardRouteInfo.getUavRouteReq().getRoutePointList()); |
| | | } catch (ControlException e) { |
| | | // 返回包含禁飞区错误信息的特定结果 |
| | | return MinioUploadResult.builder() |
| | | .originalFilename("禁飞区错误.航线航点在禁飞区!") |
| | | .build(); |
| | | } |
| | | |
| | | String url = ossService.upload("kmz",file); |
| | | String urlDock = ossDockService.upload("kmz",file); |
| | | ardRouteInfo.setName(file.getOriginalFilename()); |
| | |
| | | .originalFilename(file.getOriginalFilename()) |
| | | .build(); |
| | | }catch (Exception e){ |
| | | log.error("上传航线文件失败", e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 判断一组数组,是否包含禁飞区 |
| | | */ |
| | | private void arrayWithinNoFlyZone(List<RoutePointReq> routePointList) { |
| | | if (routePointList == null || routePointList.isEmpty()) { |
| | | return; |
| | | } |
| | | // 检查第一个航点 |
| | | ArdNoflyDto firstDto = new ArdNoflyDto(); |
| | | firstDto.setTarget(new Vertex( |
| | | routePointList.get(0).getLongitude(), |
| | | routePointList.get(0).getLatitude())); |
| | | verifyNoFlyZone(firstDto); |
| | | |
| | | // 检查后续航点及与前一个航点的线段 |
| | | for (int i = 1; i < routePointList.size(); i++) { |
| | | ArdNoflyDto dto = new ArdNoflyDto(); |
| | | dto.setCurrent(new Vertex( |
| | | routePointList.get(i - 1).getLongitude(), |
| | | routePointList.get(i - 1).getLatitude())); |
| | | dto.setTarget(new Vertex( |
| | | routePointList.get(i).getLongitude(), |
| | | routePointList.get(i).getLatitude())); |
| | | verifyNoFlyZone(dto); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据名称查询航线信息 |
| | | * |
| | | * @param name 文件名称 |
| | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import cn.hutool.core.collection.CollectionUtil; |
| | | import com.ard.oss.service.impl.OssServiceContext; |
| | | import com.ard.ossdock.service.impl.OssDockServiceContext; |
| | | import com.ard.route.constant.FileTypeConstants; |
| | | import com.ard.route.domain.djuav.RoutePointReq; |
| | | import com.ard.route.domain.djuav.UavRouteReq; |
| | |
| | | import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.mock.web.MockMultipartFile; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | |
| | | |
| | | @Resource |
| | | private OssServiceContext ossService; |
| | | |
| | | @Resource |
| | | private OssDockServiceContext ossDockService; |
| | | |
| | | @Resource |
| | | private IArdRouteInfoService ardRouteInformationService; |
| | |
| | | } |
| | | } |
| | | // 删除文件 |
| | | if ("100".equals(kmlInfo.getDocument().getKmlMissionConfig().getDroneInfo().getDroneEnumValue()) |
| | | ||"91".equals(kmlInfo.getDocument().getKmlMissionConfig().getDroneInfo().getDroneEnumValue())){ |
| | | ossDockService.deleteObject(kmzPath,minioUrlName); |
| | | } |
| | | ossService.deleteObject(kmzPath, minioUrlName); |
| | | return buildKmzMethod(routeInformation.getName(), kmlInfo, wpmlInfo); |
| | | } catch (Exception e) { |
| | |
| | | "application/vnd.google-earth.kmz", |
| | | new ByteArrayInputStream(baos.toByteArray()) |
| | | ); |
| | | // 通过无人机类型,判断上传文件 |
| | | if ("100".equals(kmlInfo.getDocument().getKmlMissionConfig().getDroneInfo().getDroneEnumValue()) |
| | | ||"91".equals(kmlInfo.getDocument().getKmlMissionConfig().getDroneInfo().getDroneEnumValue())){ |
| | | String kmzFilePathDock = ossDockService.upload(kmzPath,multipartFile); |
| | | result.setPathDock(kmzFilePathDock); |
| | | } |
| | | String kmzFilePath = ossService.upload(kmzPath,multipartFile); |
| | | result.setPath(kmzFilePath); |
| | | return result; |
| | |
| | | public class InitializationUtils { |
| | | |
| | | // 禅思H20T 公倍数 |
| | | private static final Double CHANSI_H20 = 23.76237623; |
| | | private static final Double CHANSI_H20T = 23.76237623; |
| | | |
| | | // 禅思H20T 焦距值 |
| | | private static final Double CHANSI_H20_FOCUS = 6.83; |
| | |
| | | for (ActionGroupReq actionGroupReq : routePointReq.getActionGroupList()) { |
| | | for (PointActionReq action : actionGroupReq.getActions()) { |
| | | if (action.getZoom() != null){ |
| | | //action.setZoom(action.getZoom() * CHANSI_H20); |
| | | action.setZoom(action.getZoom() * CHANSI_H20_FOCUS); |
| | | action.setZoom(multiple_23(action.getZoom())); |
| | | //action.setZoom(multiple_6(action.getZoom())); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static Double multiple_23(Double zoom){ |
| | | return zoom * CHANSI_H20T; |
| | | } |
| | | |
| | | public static Double multiple_6(Double zoom){ |
| | | return zoom * CHANSI_H20_FOCUS; |
| | | } |
| | | |
| | | public static Double divided_23(Double zoom){ |
| | | return zoom / CHANSI_H20T; |
| | | } |
| | | |
| | | public static Double divided_6(Double zoom){ |
| | | return zoom / CHANSI_H20_FOCUS; |
| | | } |
| | | |
| | | /** |
| | | * 初始化数据 |
| | | */ |
| | |
| | | |
| | | public class NoFlyZoneUtils { |
| | | |
| | | |
| | | /** |
| | | * 计算点到多边形的最近距离(米) |
| | | */ |
| | | public static double pointToPolygonDistance(Vertex point, List<Vertex> polygon) { |
| | | |
| | | // 如果在多边形内部,距离为 0 |
| | | if (isPointInPolygon(point, polygon)) { |
| | | return 0; |
| | | } |
| | | |
| | | double minDistance = Double.MAX_VALUE; |
| | | int n = polygon.size(); |
| | | |
| | | for (int i = 0; i < n; i++) { |
| | | Vertex a = polygon.get(i); |
| | | Vertex b = polygon.get((i + 1) % n); // 下一点,最后一条边连接第一个点 |
| | | |
| | | double dist = pointToSegmentDistanceHaversine(point, a, b); |
| | | minDistance = Math.min(minDistance, dist); |
| | | } |
| | | |
| | | return minDistance; |
| | | } |
| | | |
| | | /** |
| | | * 计算点到线段的距离(米)使用Haversine公式 |
| | | */ |
| | | public static double pointToSegmentDistanceHaversine(Vertex p, Vertex a, Vertex b) { |
| | | // 将经纬度换算成以 p 点为参考的局部平面米坐标 |
| | | double[] pa = latLonToXY(a, p.y, p.x); |
| | | double[] pb = latLonToXY(b, p.y, p.x); |
| | | double[] pp = latLonToXY(p, p.y, p.x); |
| | | |
| | | double dx = pb[0] - pa[0]; |
| | | double dy = pb[1] - pa[1]; |
| | | |
| | | double t = ((pp[0] - pa[0]) * dx + (pp[1] - pa[1]) * dy) / (dx * dx + dy * dy); |
| | | |
| | | double nearestX, nearestY; |
| | | if (t < 0) { |
| | | nearestX = pa[0]; |
| | | nearestY = pa[1]; |
| | | } else if (t > 1) { |
| | | nearestX = pb[0]; |
| | | nearestY = pb[1]; |
| | | } else { |
| | | nearestX = pa[0] + t * dx; |
| | | nearestY = pa[1] + t * dy; |
| | | } |
| | | |
| | | double distX = pp[0] - nearestX; |
| | | double distY = pp[1] - nearestY; |
| | | |
| | | return Math.sqrt(distX * distX + distY * distY); |
| | | } |
| | | |
| | | /** |
| | | * 将经纬度转换为局部平面坐标(米) |
| | | * originLat、originLon 是参考点,经纬度转换到以参考点为原点的平面坐标 |
| | | */ |
| | | public static double[] latLonToXY(Vertex point, double originLat, double originLon) { |
| | | double R = 6371000; // 地球半径,单位米 |
| | | double dLat = Math.toRadians(point.y - originLat); |
| | | double dLon = Math.toRadians(point.x - originLon); |
| | | double x = R * dLon * Math.cos(Math.toRadians(originLat)); |
| | | double y = R * dLat; |
| | | return new double[]{x, y}; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 判断点是否在多边形内(射线法) |
| | | */ |
| | |
| | | private static boolean onSegment(Vertex p1, Vertex p2, Vertex q) { |
| | | return q.x <= Math.max(p1.x, p2.x) && q.x >= Math.min(p1.x, p2.x) |
| | | && q.y <= Math.max(p1.y, p2.y) && q.y >= Math.min(p1.y, p2.y); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 判断点是否在矩形内 |
| | | */ |
| | | public static boolean isInsideBox(Vertex point, ArdNoFlyBox box) { |
| | | if (point == null || box == null) return false; |
| | | return point.x >= box.getMinx() && |
| | | point.x <= box.getMaxx() && |
| | | point.y >= box.getMiny() && |
| | | point.y <= box.getMaxy(); |
| | | } |
| | | |
| | | |
| | |
| | | return vertexes; |
| | | } |
| | | |
| | | |
| | | public static double degDistanceToMeter(double deg, double lat) { |
| | | // 1° ≈ 111320 米,但是经度和纬度不一样,这里用纬度做修正 |
| | | return deg * 111320.0 * Math.cos(Math.toRadians(lat)); |
| | | } |
| | | } |
| | |
| | | |
| | | /** 屏幕空间误差 */ |
| | | @Excel(name = "屏幕空间误差") |
| | | private Double screenSpaceError; |
| | | private Double maximumScreenSpaceError; |
| | | |
| | | /** 内存最大使用量 */ |
| | | @Excel(name = "内存最大使用量") |
| | |
| | | |
| | | /** 自动超清化模型 */ |
| | | @Excel(name = "自动超清化模型") |
| | | private Double automaticSuperCleaningModel; |
| | | private Double cullRequestsWhileMovingMultiplier; |
| | | |
| | | /** 加载速度 */ |
| | | @Excel(name = "加载速度") |
| | | private Double loadingSpeed; |
| | | @Excel(name = "模型加载速度") |
| | | private Double dynamicScreenSpaceErrorDensity; |
| | | |
| | | /** 用户ID */ |
| | | @Excel(name = "用户ID") |
| | |
| | | <result property="tilesName" column="tiles_name" /> |
| | | <result property="tilesHeight" column="tiles_height" /> |
| | | <result property="tileAddress" column="tile_address" /> |
| | | <result property="screenSpaceError" column="screen_space_error" /> |
| | | <result property="maximumScreenSpaceError" column="maximum_screen_space_error" /> |
| | | <result property="maximumMemoryUsage" column="maximum_memory_usage" /> |
| | | <result property="automaticSuperCleaningModel" column="automatic_super_cleaning_model" /> |
| | | <result property="loadingSpeed" column="loading_speed" /> |
| | | <result property="cullRequestsWhileMovingMultiplier" column="cull_requests_while_moving_multiplier" /> |
| | | <result property="dynamicScreenSpaceErrorDensity" column="dynamic_screen_space_error_density" /> |
| | | <result property="userId" column="user_id" /> |
| | | <result property="deptId" column="dept_id" /> |
| | | <result property="defaultLoading" column="default_loading" /> |
| | |
| | | tiles_name, |
| | | tiles_height, |
| | | tile_address, |
| | | screen_space_error, |
| | | maximum_screen_space_error, |
| | | maximum_memory_usage, |
| | | automatic_super_cleaning_model, |
| | | loading_speed, |
| | | cull_requests_while_moving_multiplier, |
| | | dynamic_screen_space_error_density, |
| | | user_id, |
| | | dept_id, |
| | | default_loading |
| | |
| | | <if test="tilesName != null">tiles_name,</if> |
| | | <if test="tilesHeight != null">tiles_height,</if> |
| | | <if test="tileAddress != null">tile_address,</if> |
| | | <if test="screenSpaceError != null">screen_space_error,</if> |
| | | <if test="maximumScreenSpaceError != null">maximum_screen_space_error,</if> |
| | | <if test="maximumMemoryUsage != null">maximum_memory_usage,</if> |
| | | <if test="automaticSuperCleaningModel != null">automatic_super_cleaning_model,</if> |
| | | <if test="loadingSpeed != null">loading_speed,</if> |
| | | <if test="cullRequestsWhileMovingMultiplier != null">cull_requests_while_moving_multiplier,</if> |
| | | <if test="dynamicScreenSpaceErrorDensity != null">dynamic_screen_space_error_density,</if> |
| | | <if test="userId != null">user_id,</if> |
| | | <if test="deptId != null">dept_id,</if> |
| | | <if test="defaultLoading != null">default_loading,</if> |
| | |
| | | <if test="tilesName != null">#{tilesName},</if> |
| | | <if test="tilesHeight != null">#{tilesHeight},</if> |
| | | <if test="tileAddress != null">#{tileAddress},</if> |
| | | <if test="screenSpaceError != null">#{screenSpaceError},</if> |
| | | <if test="maximumScreenSpaceError != null">#{maximumScreenSpaceError},</if> |
| | | <if test="maximumMemoryUsage != null">#{maximumMemoryUsage},</if> |
| | | <if test="automaticSuperCleaningModel != null">#{automaticSuperCleaningModel},</if> |
| | | <if test="loadingSpeed != null">#{loadingSpeed},</if> |
| | | <if test="cullRequestsWhileMovingMultiplier != null">#{cullRequestsWhileMovingMultiplier},</if> |
| | | <if test="dynamicScreenSpaceErrorDensity != null">#{dynamicScreenSpaceErrorDensity},</if> |
| | | <if test="userId != null">#{userId},</if> |
| | | <if test="deptId != null">#{deptId},</if> |
| | | <if test="defaultLoading != null">#{defaultLoading},</if> |
| | |
| | | <if test="tilesName != null">tiles_name = #{tilesName},</if> |
| | | <if test="tilesHeight != null">tiles_height = #{tilesHeight},</if> |
| | | <if test="tileAddress != null">tile_address = #{tileAddress},</if> |
| | | <if test="screenSpaceError != null">screen_space_error = #{screenSpaceError},</if> |
| | | <if test="maximumScreenSpaceError != null">maximum_screen_space_error = #{maximumScreenSpaceError},</if> |
| | | <if test="maximumMemoryUsage != null">maximum_memory_usage = #{maximumMemoryUsage},</if> |
| | | <if test="automaticSuperCleaningModel != null">automatic_super_cleaning_model = #{automaticSuperCleaningModel},</if> |
| | | <if test="loadingSpeed != null">loading_speed = #{loadingSpeed},</if> |
| | | <if test="cullRequestsWhileMovingMultiplier != null">cull_requests_while_moving_multiplier = #{cullRequestsWhileMovingMultiplier},</if> |
| | | <if test="dynamicScreenSpaceErrorDensity != null">dynamic_screen_space_error_density = #{dynamicScreenSpaceErrorDensity},</if> |
| | | <if test="userId != null">user_id = #{userId},</if> |
| | | <if test="deptId != null">dept_id = #{deptId},</if> |
| | | <if test="defaultLoading != null">default_loading = #{defaultLoading},</if> |
| New file |
| | |
| | | package com.ard.work.component.websocket.handler; |
| | | |
| | | import com.ard.data.noflyzone.domain.ArdNoFlyBox; |
| | | import com.ard.data.noflyzone.domain.ArdNoFlyZone; |
| | | import com.ard.data.noflyzone.domain.Vertex; |
| | | import com.ard.data.noflyzone.service.IArdNoFlyZoneService; |
| | | import com.ard.data.noflyzone.utils.NoFlyZoneUtils; |
| | | import com.ard.work.domain.cache.UavTelemetryDataCache; |
| | | import com.ard.work.domain.dto.NoFlyDistanceDTO; |
| | | import com.ard.work.domain.dto.telemetry.TelemetryData; |
| | | import org.springframework.stereotype.Component; |
| | | import javax.annotation.Resource; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 禁飞区距离管理器 |
| | | * @author liuyaping |
| | | * @date 2021/3/22 |
| | | */ |
| | | @Component |
| | | public class NoFlyDistanceManager extends BaseSubscriptionManager<NoFlyDistanceDTO> { |
| | | |
| | | @Resource |
| | | private IArdNoFlyZoneService ardNoFlyZoneService; |
| | | |
| | | @Override |
| | | protected NoFlyDistanceDTO getData(String boxSn) { |
| | | TelemetryData telemetryData = UavTelemetryDataCache.get(boxSn); |
| | | if (telemetryData == null) return null; |
| | | |
| | | Vertex current = new Vertex(telemetryData.getLng(), telemetryData.getLat()); |
| | | |
| | | List<ArdNoFlyZone> zones = ardNoFlyZoneService.selectArdNoFlyZoneList(new ArdNoFlyZone()); |
| | | if (zones.isEmpty()) return null; |
| | | |
| | | double minDistance = Double.MAX_VALUE; |
| | | ArdNoFlyZone nearestZone = null; |
| | | |
| | | for (ArdNoFlyZone zone : zones) { |
| | | |
| | | ArdNoFlyBox box = zone.getArdNoFlyBox(); |
| | | if (box == null) continue; |
| | | |
| | | // ⭐ 外扩 50 米 |
| | | ArdNoFlyBox expanded = expandBoxByMeter(box, 50); |
| | | |
| | | // ⭐ 包围盒快速排除必须使用 expanded,而不是 box |
| | | if (current.x < expanded.getMinx() || current.x > expanded.getMaxx() || |
| | | current.y < expanded.getMiny() || current.y > expanded.getMaxy()) { |
| | | continue; |
| | | } |
| | | |
| | | // 计算 polygon 距离 |
| | | List<Vertex> polygon = zone.getVertices(); |
| | | if (polygon == null || polygon.size() < 3) continue; |
| | | |
| | | double distance = NoFlyZoneUtils.pointToPolygonDistance(current, polygon); |
| | | |
| | | if (distance < minDistance) { |
| | | minDistance = distance; |
| | | nearestZone = zone; |
| | | } |
| | | } |
| | | |
| | | if (nearestZone == null) return null; |
| | | |
| | | return NoFlyDistanceDTO.builder() |
| | | .boxSn(boxSn) |
| | | .zoneName(nearestZone.getName()) |
| | | .distance(minDistance) // 米 |
| | | .inNoFlyZone(minDistance == 0) |
| | | .build(); |
| | | } |
| | | |
| | | // 外扩包围盒多少米 |
| | | private ArdNoFlyBox expandBoxByMeter(ArdNoFlyBox box, double meter) { |
| | | |
| | | // 计算经纬度偏移 |
| | | double latShift = meter / 111320.0; // 纬度方向 |
| | | double lngShift = meter / (111320.0 * Math.cos(Math.toRadians( |
| | | (box.getMiny() + box.getMaxy()) / 2 |
| | | ))); // 经度方向与纬度相关 |
| | | |
| | | return new ArdNoFlyBox( |
| | | box.getMinx() - lngShift, |
| | | box.getMiny() - latShift, |
| | | box.getMaxx() + lngShift, |
| | | box.getMaxy() + latShift |
| | | ); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | protected String getMessageType() { |
| | | return "noFlyZoneDistance"; |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | @Resource |
| | | private UavAllManager uavAllManager; |
| | | @Resource |
| | | private NoFlyDistanceManager noFlyDistanceManager; |
| | | @Resource |
| | | private TokenService tokenService; |
| | | private final Map<Long, Long> lastDisconnectTime = new ConcurrentHashMap<>(); |
| | | |
| | |
| | | break; |
| | | case CONTROLLER: |
| | | handleControlMessage(payload, userId); |
| | | break; |
| | | case NO_FLY_DISTANCE: |
| | | handleNoFlyDistanceMessage(payload, userId); |
| | | break; |
| | | case ALL: |
| | | handleAllMessage(payload, userId); |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理禁飞区距离 |
| | | * |
| | | * @param payload 消息负载,包含订阅信息 |
| | | * @param userId 用户ID,用于标识用户 |
| | | */ |
| | | private void handleNoFlyDistanceMessage(String payload, Long userId) { |
| | | // 解析接收到的JSON消息,将其转换为BaseMessage对象 |
| | | BaseMessage<NoFlyDistanceMessage> baseMessage = JSON.parseObject(payload, |
| | | new TypeReference<BaseMessage<NoFlyDistanceMessage>>() { |
| | | }); |
| | | // 获取消息的有效载荷部分 |
| | | NoFlyDistanceMessage noFlyDistanceMessage = baseMessage.getPayload(); |
| | | |
| | | // 检查有效载荷是否存在 |
| | | if (noFlyDistanceMessage != null) { |
| | | // 获取无人机盒子的序列号 |
| | | String boxSn = noFlyDistanceMessage.getBoxSn(); |
| | | // 根据消息中的订阅标志,决定是订阅还是退订无人机状态 |
| | | Boolean subscribe = noFlyDistanceMessage.getSubscribe(); |
| | | if (subscribe) { |
| | | // 执行订阅操作 |
| | | noFlyDistanceManager.subscribe(boxSn, userId, 1); |
| | | } else { |
| | | // 执行退订操作 |
| | | noFlyDistanceManager.unsubscribe(boxSn, userId); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void afterConnectionEstablished(WebSocketSession session) { |
| | | String userIdStr = (String) session.getAttributes().get("userId"); |
| New file |
| | |
| | | package com.ard.work.domain.dto; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | @Data |
| | | @Builder |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class NoFlyDistanceDTO { |
| | | private String boxSn; |
| | | private String zoneName; |
| | | private double distance; // 米 |
| | | private boolean inNoFlyZone; |
| | | // getters/setters |
| | | } |
| | |
| | | TELEMETRY("telemetry"), |
| | | SIGNAL("signal"), |
| | | CONTROLLER("controller"), |
| | | NO_FLY_DISTANCE("noFlyDistance"), |
| | | ALL("all"); |
| | | |
| | | private final String type; |
| New file |
| | |
| | | package com.ard.work.domain.message; |
| | | |
| | | import com.ard.work.domain.dto.signal.SignalInfo; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | /** |
| | | * Description: 禁飞距离消息 |
| | | * Author: liusuyi |
| | | * Date: 2025年03月10日11:49 |
| | | **/ |
| | | @Data |
| | | @Builder |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | public class NoFlyDistanceMessage { |
| | | |
| | | /** |
| | | * 盒子编号 |
| | | */ |
| | | private String boxSn; |
| | | |
| | | /** |
| | | * 是否订阅 |
| | | */ |
| | | private Boolean subscribe; |
| | | |
| | | } |