Merge remote-tracking branch 'origin/dev' into dev
1 files added
14 files modified
1 files renamed
| | |
| | | import com.ard.common.enums.BusinessType; |
| | | import com.ard.common.utils.poi.ExcelUtil; |
| | | import com.ard.route.domain.route.ArdRouteGroup; |
| | | import com.ard.route.domain.vo.ArdRouteGroupVo; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 分组列表 |
| | | */ |
| | | @ApiOperation("分组列表") |
| | | @GetMapping("/groupList") |
| | | public TableDataInfo groupList(ArdRouteGroup ardRouteGroup) { |
| | | List<ArdRouteGroupVo> list = ardRouteGroupService.selectGroupList(ardRouteGroup); |
| | | return getDataTable(list); |
| | | } |
| | | |
| | | } |
| | |
| | | { |
| | | return Constants.LOGIN_USERID_KEY + userId; |
| | | } |
| | | |
| | | public LoginUser getLoginUserByUserId(Long userId) { |
| | | String userIdKey = getUserIdKey(userId); |
| | | String tokenKey = redisCache.getCacheObject(userIdKey); |
| | | if (tokenKey == null) return null; |
| | | return redisCache.getCacheObject(tokenKey); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.ard.route.domain.vo; |
| | | |
| | | import com.ard.common.annotation.Excel; |
| | | import com.ard.common.core.domain.BaseEntity; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class ArdRouteGroupVo extends BaseEntity { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** ID */ |
| | | private String id; |
| | | |
| | | /** 分组名称 */ |
| | | @Excel(name = "分组名称") |
| | | private String groupName; |
| | | |
| | | /** 序列号 */ |
| | | @Excel(name = "序列号") |
| | | private Integer serialNumber; |
| | | |
| | | } |
| File was renamed from ard-route/src/main/java/com/ard/route/domain/vo/KmzInfoVO.java |
| | |
| | | * Date: 2024/12/22 10:46 |
| | | **/ |
| | | @Data |
| | | public class KmzInfoVO implements Serializable { |
| | | public class KmzInfoVo implements Serializable { |
| | | |
| | | /** |
| | | * 航线kml信息 |
| | |
| | | import java.util.Map; |
| | | |
| | | import com.ard.route.domain.route.ArdRouteGroup; |
| | | import com.ard.route.domain.vo.ArdRouteGroupVo; |
| | | |
| | | /** |
| | | * 分组Service接口 |
| | |
| | | * @return 结果 |
| | | */ |
| | | public int deleteArdRouteGroupById(String id); |
| | | |
| | | /** |
| | | * 分组列表 |
| | | * |
| | | * @param ardRouteGroup 分组 |
| | | * @return 分组集合 |
| | | */ |
| | | public List<ArdRouteGroupVo> selectGroupList(ArdRouteGroup ardRouteGroup); |
| | | |
| | | } |
| | |
| | | package com.ard.route.service; |
| | | |
| | | import com.ard.route.domain.UavRouteReq; |
| | | import com.ard.route.domain.vo.KmzInfoVO; |
| | | import com.ard.route.domain.vo.KmzInfoVo; |
| | | import com.ard.route.domain.vo.KmzResultVo; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | |
| | | public interface UavRouteService { |
| | |
| | | /** |
| | | * 解析kmz文件 |
| | | */ |
| | | public KmzInfoVO parseKmz(String file); |
| | | public KmzInfoVo parseKmz(String file); |
| | | |
| | | /** |
| | | * 编辑kmz文件 |
| | |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import com.ard.common.annotation.DataScope; |
| | | import com.ard.common.utils.DateUtils; |
| | | import com.ard.common.utils.uuid.IdUtils; |
| | | import com.ard.route.domain.route.ArdRouteGroup; |
| | | import com.ard.route.domain.vo.ArdRouteGroupVo; |
| | | import com.ard.route.mapper.ArdRouteGroupMapper; |
| | | import com.ard.route.mapper.ArdRouteInfoMapper; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import com.ard.route.service.IArdRouteGroupService; |
| | |
| | | return ardRouteGroupMapper.deleteArdRouteGroupById(id); |
| | | } |
| | | |
| | | /** |
| | | * 分组列表 |
| | | * |
| | | * @param ardRouteGroup 分组 |
| | | * @return 分组集合 |
| | | */ |
| | | @Override |
| | | public List<ArdRouteGroupVo> selectGroupList(ArdRouteGroup ardRouteGroup) { |
| | | return ardRouteGroupMapper.selectArdRouteGroupList(ardRouteGroup).stream() |
| | | .map(entity -> { |
| | | ArdRouteGroupVo vo = new ArdRouteGroupVo(); |
| | | BeanUtils.copyProperties(entity, vo); |
| | | return vo; |
| | | }) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | } |
| | |
| | | import com.ard.data.noflyzone.utils.NoFlyZoneUtils; |
| | | import com.ard.oss.model.MinioUploadResult; |
| | | import com.ard.oss.service.impl.OssServiceContext; |
| | | import com.ard.route.domain.CoordinatePointReq; |
| | | import com.ard.route.domain.UavRouteReq; |
| | | import com.ard.route.domain.route.ArdRouteInfo; |
| | | import com.ard.route.domain.vo.KmzResultVo; |
| | |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | ardRouteInfo.getUavRouteReq().setDroneType(subStringDroneType(ardRouteInfo.getAircraft())); |
| | | ardRouteInfo.setRouteData(routeData); |
| | | KmzResultVo kmzResult = routeService.buildKmz(ardRouteInfo.getUavRouteReq(), ardRouteInfo.getName()); |
| | | ardRouteInfo.setPath(kmzResult.getPath()); |
| | |
| | | @Override |
| | | public int updateArdRouteInfo(ArdRouteInfo ardRouteInfo) { |
| | | ardRouteInfo.setUpdateTime(DateUtils.getNowDate()); |
| | | KmzResultVo kmzResult = new KmzResultVo(); |
| | | // 获取源文件名字 |
| | | ArdRouteInfo route = ardRouteInfoMapper.selectArdRouteInfoById(ardRouteInfo.getId()); |
| | | if (route.getName().equals(ardRouteInfo.getName())) { |
| | | kmzResult = routeService.updateKmz(ardRouteInfo.getUavRouteReq(), ardRouteInfo.getName()); |
| | | }else { |
| | | kmzResult = routeService.updateKmzNew(ardRouteInfo.getUavRouteReq(), route.getName(), ardRouteInfo.getName()); |
| | | // 判断生成kmz文件实体类是否为空,为空就修改航信信息,不修改行点信息。 |
| | | if (ardRouteInfo.getUavRouteReq() != null) { |
| | | KmzResultVo kmzResult; |
| | | // 获取源文件名字 |
| | | ArdRouteInfo route = ardRouteInfoMapper.selectArdRouteInfoById(ardRouteInfo.getId()); |
| | | if (route.getName().equals(ardRouteInfo.getName())) { |
| | | kmzResult = routeService.updateKmz(ardRouteInfo.getUavRouteReq(), ardRouteInfo.getName()); |
| | | }else { |
| | | kmzResult = routeService.updateKmzNew(ardRouteInfo.getUavRouteReq(), route.getName(), ardRouteInfo.getName()); |
| | | } |
| | | if ("更新航线kmz文件失败".equals(kmzResult.getData())) { |
| | | return 0; |
| | | } |
| | | ardRouteInfo.setPath(kmzResult.getPath()); |
| | | } |
| | | if ("更新航线kmz文件失败".equals(kmzResult.getData())) { |
| | | return 0; |
| | | } |
| | | ardRouteInfo.setPath(kmzResult.getPath()); |
| | | return ardRouteInfoMapper.updateArdRouteInfo(ardRouteInfo); |
| | | } |
| | | |
| | |
| | | throw new ControlException("方法参数中未找到有效经纬度字段,无法判断禁飞区!"); |
| | | } |
| | | List<ArdNoFlyZone> ardNoFlyZones = ardNoFlyZoneService.selectArdNoFlyZoneList(new ArdNoFlyZone()); |
| | | |
| | | |
| | | |
| | | if (!ardNoFlyZones.isEmpty()) { |
| | | Vertex vertex = new Vertex(longitude, latitude); |
| | | // boolean inNoFlyZones = NoFlyZoneUtils.isPointInPolygon(vertex, ardNoFlyZones); |
| | |
| | | ardRouteInfoMapper.insertArdRouteInfo(ardRouteInfo); |
| | | } |
| | | |
| | | private void verifyNoFlyZone(CoordinatePointReq a,CoordinatePointReq b){ |
| | | |
| | | } |
| | | |
| | | } |
| | |
| | | import com.ard.route.domain.WaypointTurnReq; |
| | | import com.ard.route.domain.kml.*; |
| | | import com.ard.route.domain.route.ArdRouteInfo; |
| | | import com.ard.route.domain.vo.KmzInfoVO; |
| | | import com.ard.route.domain.vo.KmzInfoVo; |
| | | import com.ard.route.domain.vo.KmzResultVo; |
| | | import com.ard.route.enums.kml.ExitOnRCLostEnums; |
| | | import com.ard.route.service.IArdRouteInfoService; |
| | |
| | | * 解析kmz文件 |
| | | */ |
| | | @Override |
| | | public KmzInfoVO parseKmz(String fileUrl){ |
| | | KmzInfoVO kmzInfoVO = new KmzInfoVO(); |
| | | public KmzInfoVo parseKmz(String fileUrl){ |
| | | KmzInfoVo kmzInfoVO = new KmzInfoVo(); |
| | | try (InputStream inputStream = ossService.getObject(kmzPath,fileUrl); |
| | | ArchiveInputStream archiveInputStream = new ZipArchiveInputStream(inputStream)){ |
| | | ArchiveEntry entry; |
| | |
| | | return url.substring(kmzIndex + 5); // +5 是为了跳过 "/kmz/" |
| | | } |
| | | |
| | | /** |
| | | * 截取字符串 |
| | | * 参数: "0-89-0" |
| | | */ |
| | | public static Integer subStringDroneType(String str) { |
| | | String[] parts = str.split("-"); |
| | | return Integer.valueOf(parts[1]); |
| | | } |
| | | |
| | | } |
| | |
| | | <select id="selectArdRouteInfoList" parameterType="ArdRouteInfo" resultMap="ArdRouteInfoResult"> |
| | | <include refid="selectArdRouteInfoVo"/> |
| | | <where> |
| | | <if test="name != null and kmzName != ''"> and name like concat('%', #{name}, '%')</if> |
| | | <if test="name != null and name != ''"> and name like concat('%', #{name}, '%')</if> |
| | | <if test="aircraft != null and aircraft != ''"> and aircraft = #{aircraft}</if> |
| | | <if test="payload != null and payload != ''"> and payload = #{payload}</if> |
| | | <if test="type != null and type != ''"> and type = #{type}</if> |
| | |
| | | <if test="id != null">id,</if> |
| | | <if test="name != null">name,</if> |
| | | <if test="path != null">path,</if> |
| | | <if test="GroupId != null">group_id,</if> |
| | | <if test="groupId != null">group_id,</if> |
| | | <if test="type != null">type,</if> |
| | | <if test="aircraft != null">aircraft,</if> |
| | | <if test="payload != null">payload,</if> |
| | |
| | | <if test="id != null">#{id},</if> |
| | | <if test="name != null">#{name},</if> |
| | | <if test="path != null">#{path},</if> |
| | | <if test="GroupId != null">#{GroupId},</if> |
| | | <if test="groupId != null">#{groupId},</if> |
| | | <if test="type != null">#{type},</if> |
| | | <if test="aircraft != null">#{aircraft},</if> |
| | | <if test="payload != null">#{payload},</if> |
| | |
| | | <trim prefix="SET" suffixOverrides=","> |
| | | <if test="name != null">name = #{name},</if> |
| | | <if test="path != null">path = #{path},</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="payload != null">payload = #{payload},</if> |
| | |
| | | <groupId>com.ard</groupId> |
| | | <artifactId>ard-common</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- framework框架核心--> |
| | | <dependency> |
| | | <groupId>com.ard</groupId> |
| | | <artifactId>ard-framework</artifactId> |
| | | </dependency> |
| | | <!-- Forest --> |
| | | <dependency> |
| | | <groupId>com.dtflys.forest</groupId> |
| | |
| | | public static int getOnlineUserCount() { |
| | | return ONLINE_USER_SESSIONS.size(); |
| | | } |
| | | |
| | | public static boolean containsUser(Long userId) { |
| | | return ONLINE_USER_SESSIONS.containsKey(userId); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.TypeReference; |
| | | import com.ard.common.core.domain.model.LoginUser; |
| | | import com.ard.framework.web.service.TokenService; |
| | | import com.ard.work.component.websocket.WebSocketSessionManager; |
| | | import com.ard.work.component.websocket.utils.WebSocketUtil; |
| | | import com.ard.work.domain.enums.MessageType; |
| | | import com.ard.work.domain.message.*; |
| | | import com.ard.work.service.control.UavControlService; |
| | |
| | | import org.springframework.web.socket.handler.TextWebSocketHandler; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.concurrent.CompletableFuture; |
| | | |
| | | |
| | | @Component |
| | |
| | | private UavControlManager uavControlManager; |
| | | @Resource |
| | | private UavAllManager uavAllManager; |
| | | @Resource |
| | | private TokenService tokenService; |
| | | |
| | | @Override |
| | | public void handleTextMessage(WebSocketSession session, TextMessage message) { |
| | |
| | | BaseMessage<?> baseMessage = JSON.parseObject(payload, BaseMessage.class); |
| | | MessageType messageType = MessageType.fromString(baseMessage.getType()); |
| | | switch (messageType) { |
| | | case HEARTBEAT: |
| | | handleHeartbeatMessage(payload, userId); |
| | | break; |
| | | case STREAM: |
| | | handleStreamMessage(payload, userId); |
| | | break; |
| | |
| | | } catch (Exception e) { |
| | | log.error("Error handling message: {}", message, e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理心跳消息 |
| | | * <p> |
| | | * 该方法解析给定的负载数据,以获取无人机流消息,并根据消息类型决定是否开始或停止流 |
| | | * |
| | | * @param payload 消息的负载数据,通常为JSON字符串 |
| | | * @param userId 接收消息的用户ID |
| | | */ |
| | | private void handleHeartbeatMessage(String payload, Long userId) { |
| | | |
| | | WebSocketUtil.sendMessage(userId, payload); |
| | | } |
| | | |
| | | /** |
| | |
| | | uavTelemetryManager.removeSubscribe(userId); |
| | | uavSignalManager.removeSubscribe(userId); |
| | | uavControlManager.removeSubscribe(userId); |
| | | |
| | | // 延迟10秒删除token(若期间没重连) |
| | | CompletableFuture.runAsync(() -> { |
| | | try { |
| | | Thread.sleep(10_000); // 延迟10秒 |
| | | } catch (InterruptedException ignored) { |
| | | } |
| | | |
| | | if (!WebSocketSessionManager.containsUser(userId)) { |
| | | LoginUser loginUser = tokenService.getLoginUserByUserId(userId); |
| | | if (loginUser != null) { |
| | | tokenService.delLoginUser(loginUser.getToken(), userId); |
| | | log.info("【cmd】用户 [{}] 超时未重连,已删除 token", userId); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | package com.ard.work.domain.enums; |
| | | |
| | | public enum MessageType { |
| | | HEARTBEAT("heartbeat"), |
| | | STREAM("stream"), |
| | | STATE("state"), |
| | | TELEMETRY("telemetry"), |
| | |
| | | case 0x02: |
| | | // 处理注册消息 |
| | | HeartbeatReplyCmd heartbeatReplyCmd = (HeartbeatReplyCmd) tyCommand; |
| | | logPrint("心跳消息", heartbeatReplyCmd.getTimestamp()); |
| | | //logPrint("心跳消息", heartbeatReplyCmd.getTimestamp()); |
| | | break; |
| | | case 0x03: |
| | | // 处理订阅消息 |