diff --git a/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java new file mode 100644 index 0000000..079e1d5 --- /dev/null +++ b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java @@ -0,0 +1,43 @@ +package com.casic.missiles.modular.system.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.Data; + +/** + * @author a203 + */ +@Data +@TableName("bus_task_route") +public class RoutePlan extends Model { + private static final long serialVersionUID = 1L; + + /** + * 数据库主键 + */ + @TableId(value = "ID", type = IdType.ASSIGN_ID) + private Long id; + /** + * 机器人ID + */ + @TableField("ROBOT_ID") + private Integer robotId; + /** + * 路线规划生成的时间 + */ + @TableField("PLAN_TIME") + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + @TableField("PLAN_TYPE") + private String planType; + /** + * 规划结果 + */ + @TableField("ROUTE_RESULT") + private String routeResult; +} diff --git a/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java new file mode 100644 index 0000000..079e1d5 --- /dev/null +++ b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java @@ -0,0 +1,43 @@ +package com.casic.missiles.modular.system.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.Data; + +/** + * @author a203 + */ +@Data +@TableName("bus_task_route") +public class RoutePlan extends Model { + private static final long serialVersionUID = 1L; + + /** + * 数据库主键 + */ + @TableId(value = "ID", type = IdType.ASSIGN_ID) + private Long id; + /** + * 机器人ID + */ + @TableField("ROBOT_ID") + private Integer robotId; + /** + * 路线规划生成的时间 + */ + @TableField("PLAN_TIME") + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + @TableField("PLAN_TYPE") + private String planType; + /** + * 规划结果 + */ + @TableField("ROUTE_RESULT") + private String routeResult; +} diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java index 83cba30..5bf8bcc 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java @@ -3,8 +3,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.modular.system.model.ShelterPosition; -import java.util.List; - /** * @author a203 */ @@ -12,7 +10,7 @@ /** * 获取最新的方舱位置 * - * @return {@link List} + * @return {@link ShelterPosition} */ ShelterPosition selectLastOne(); } diff --git a/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java new file mode 100644 index 0000000..079e1d5 --- /dev/null +++ b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java @@ -0,0 +1,43 @@ +package com.casic.missiles.modular.system.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.Data; + +/** + * @author a203 + */ +@Data +@TableName("bus_task_route") +public class RoutePlan extends Model { + private static final long serialVersionUID = 1L; + + /** + * 数据库主键 + */ + @TableId(value = "ID", type = IdType.ASSIGN_ID) + private Long id; + /** + * 机器人ID + */ + @TableField("ROBOT_ID") + private Integer robotId; + /** + * 路线规划生成的时间 + */ + @TableField("PLAN_TIME") + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + @TableField("PLAN_TYPE") + private String planType; + /** + * 规划结果 + */ + @TableField("ROUTE_RESULT") + private String routeResult; +} diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java index 83cba30..5bf8bcc 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java @@ -3,8 +3,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.modular.system.model.ShelterPosition; -import java.util.List; - /** * @author a203 */ @@ -12,7 +10,7 @@ /** * 获取最新的方舱位置 * - * @return {@link List} + * @return {@link ShelterPosition} */ ShelterPosition selectLastOne(); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java index 55c8156..3a08fd0 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java @@ -11,6 +11,10 @@ public static final byte BITS_OF_END = (byte) 0x0A; public static final byte SHELTER_ID = (byte) 0xFF; + public static final int MAX_RADIUS = 80; + public static final int MAX_AGE = 240; + public static final int MIN_AGE = 1; + /** * 洋流相关常量 */ diff --git a/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java new file mode 100644 index 0000000..079e1d5 --- /dev/null +++ b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java @@ -0,0 +1,43 @@ +package com.casic.missiles.modular.system.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.Data; + +/** + * @author a203 + */ +@Data +@TableName("bus_task_route") +public class RoutePlan extends Model { + private static final long serialVersionUID = 1L; + + /** + * 数据库主键 + */ + @TableId(value = "ID", type = IdType.ASSIGN_ID) + private Long id; + /** + * 机器人ID + */ + @TableField("ROBOT_ID") + private Integer robotId; + /** + * 路线规划生成的时间 + */ + @TableField("PLAN_TIME") + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + @TableField("PLAN_TYPE") + private String planType; + /** + * 规划结果 + */ + @TableField("ROUTE_RESULT") + private String routeResult; +} diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java index 83cba30..5bf8bcc 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java @@ -3,8 +3,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.modular.system.model.ShelterPosition; -import java.util.List; - /** * @author a203 */ @@ -12,7 +10,7 @@ /** * 获取最新的方舱位置 * - * @return {@link List} + * @return {@link ShelterPosition} */ ShelterPosition selectLastOne(); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java index 55c8156..3a08fd0 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java @@ -11,6 +11,10 @@ public static final byte BITS_OF_END = (byte) 0x0A; public static final byte SHELTER_ID = (byte) 0xFF; + public static final int MAX_RADIUS = 80; + public static final int MAX_AGE = 240; + public static final int MIN_AGE = 1; + /** * 洋流相关常量 */ diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java index ed3cabe..c06ee68 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.utils; import com.alibaba.fastjson.JSON; +import com.casic.missiles.modular.system.dto.PointDTO; import com.casic.missiles.modular.system.model.RobotInfo; import com.casic.missiles.modular.system.model.ShelterPosition; +import lombok.extern.slf4j.Slf4j; import java.text.SimpleDateFormat; import java.util.*; @@ -12,6 +14,7 @@ * * @author a203 */ +@Slf4j public class DecodeData { /** * 水下机器人信息 @@ -79,15 +82,15 @@ } /** - * 区域覆盖 + * 区域覆盖-已校验 */ public static String decodeRobotRegion(byte[] bytes) { - Map regionMap = new HashMap<>(); - int count = bytes[4]; - regionMap.put("count", String.valueOf(count)); + Map regionMap = new HashMap<>(7); + int count = bytes[5]; + regionMap.put("count", count); byte[] idsBytes = new byte[count]; - System.arraycopy(bytes, 5, idsBytes, 0, count); + System.arraycopy(bytes, 5 + 1, idsBytes, 0, count); StringBuilder builder = new StringBuilder(); for (int i = 0; i < idsBytes.length; i++) { if (i != idsBytes.length - 1) { @@ -98,49 +101,70 @@ } regionMap.put("robotIds", builder.toString()); - //经度和纬度,所以需要*2 - int targetSize = count * 2 * 4; + //经度(4)、纬度(4) + int targetSize = count * (4 + 4); byte[] targetBytes = new byte[targetSize]; - //起始4个字节,机器人个数1个字节 - System.arraycopy(bytes, 5 + idsBytes.length, targetBytes, 0, targetSize); - regionMap.put("robotTargets", formatLanLat(targetBytes)); + //起始5个字节,机器人个数1个字节 + System.arraycopy(bytes, 5 + 1 + idsBytes.length, targetBytes, 0, targetSize); + regionMap.put("robotTargets", formatLngLat(targetBytes)); - regionMap.put("pointCount", String.valueOf(bytes[5 + idsBytes.length + targetBytes.length])); + regionMap.put("pointCount", bytes[5 + 1 + idsBytes.length + targetBytes.length]); byte[] radiusBytes = new byte[2]; - System.arraycopy(bytes, 5 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); + System.arraycopy(bytes, 5 + 1 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); regionMap.put("regionRadius", covertTargetDistance(radiusBytes)); - int aByte = bytes[5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; + int aByte = bytes[5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; if (aByte == 0) { regionMap.put("contour", "轮廓标志位:多边形," + count + "个轮廓点"); } else { regionMap.put("contour", "轮廓标志位:圆形," + count + "个轮廓点"); } - //经度和纬度,所以需要*2 - int pointSize = count * 2 * 4; + //经度(4)、纬度(4) + int pointSize = count * (4 + 4); byte[] pointBytes = new byte[pointSize]; System.arraycopy(bytes, - 5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, + 5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, pointBytes, 0, pointSize); - regionMap.put("robotPoints", formatLanLat(pointBytes)); + regionMap.put("robotPoints", formatLngLat(pointBytes)); return JSON.toJSONString(regionMap); } /** - * 路径规划 + * 路径规划-已校验 */ public static String decodeRobotRoute(byte[] bytes) { - Map routeMap = new HashMap<>(2); + Map routeMap = new HashMap<>(2); - int count = bytes[4]; - routeMap.put("routeCount", String.valueOf(count)); + byte[] countBytes = new byte[2]; + System.arraycopy(bytes, 5, countBytes, 0, 2); + int count = covertToDec(countBytes); + routeMap.put("routeCount", covertToDec(countBytes)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + int routeSize = count * (4 + 4 + 2 + 2 + 2); byte[] routeBytes = new byte[routeSize]; - System.arraycopy(bytes, 5, routeBytes, 0, routeSize); - routeMap.put("robotRoutes", formatLanLat(routeBytes)); + System.arraycopy(bytes, 5 + countBytes.length, routeBytes, 0, routeSize); + routeMap.put("robotRoutes", formatRoute(routeBytes)); + + byte[] sumTimeBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length, + sumTimeBytes, 0, 2); + routeMap.put("sumTime", covertToDec(sumTimeBytes)); + + byte[] sumDistanceBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length, + sumDistanceBytes, 0, 2); + routeMap.put("sumDistance", covertToDec(sumDistanceBytes)); + + byte[] sumPowerBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length + sumDistanceBytes.length, + sumPowerBytes, 0, 2); + routeMap.put("sumPower", covertToDec(sumPowerBytes)); return JSON.toJSONString(routeMap); } @@ -163,7 +187,7 @@ * 航路点任务 */ public static String decodeTaskRoute(byte[] bytes) { - Map taskMap = new HashMap<>(3); + Map taskMap = new HashMap<>(3); byte[] depthBytes = new byte[2]; System.arraycopy(bytes, 4, depthBytes, 0, 2); @@ -172,10 +196,11 @@ int count = bytes[6]; taskMap.put("routeCount", String.valueOf(count)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4) + int routeSize = count * (4 + 4); byte[] routeBytes = new byte[routeSize]; System.arraycopy(bytes, 7, routeBytes, 0, routeSize); - taskMap.put("robotRoutes", formatLanLat(routeBytes)); + taskMap.put("robotRoutes", formatLngLat(routeBytes)); return JSON.toJSONString(taskMap); } @@ -268,20 +293,37 @@ } /** - * AIS数据请求 + * 环境数据请求-已校验 + */ +// public static String decodeEnvRequest(byte[] bytes) { +// +// } + + /** + * AIS数据请求-已校验 */ public static String decodeAISRequest(byte[] bytes) { - Map taskMap = new HashMap<>(2); - byte[] depthBytes = new byte[2]; - System.arraycopy(bytes, 4, depthBytes, 0, 2); - taskMap.put("radius", covertToDec(depthBytes) + "km"); + Map aisMap = new HashMap<>(2); + byte[] radiusBytes = new byte[2]; + System.arraycopy(bytes, 5, radiusBytes, 0, 2); + aisMap.put("radius", covertToDec(radiusBytes)); - taskMap.put("shipCount", String.valueOf(bytes[6])); - return JSON.toJSONString(taskMap); + byte[] lngBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length, lngBytes, 0, 4); + aisMap.put("lng", covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length, latBytes, 0, 4); + aisMap.put("lat", covertLngLat(latBytes)); + + byte[] ageBytes = new byte[2]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length + latBytes.length, ageBytes, 0, 2); + aisMap.put("age", covertToDec(ageBytes)); + return JSON.toJSONString(aisMap); } /** - * 方舱位置 + * 方舱位置-已校验 * 编码encode * 解码decode */ @@ -301,32 +343,73 @@ return shelter; } - public static String formatLanLat(byte[] targetBytes) { + /** + * 生成经纬度对象点 + */ + public static List formatLngLat(byte[] targetBytes) { List lnglat = new ArrayList<>(); for (int i = 0; i < targetBytes.length; i += 4) { byte[] target = new byte[4]; System.arraycopy(targetBytes, i, target, 0, 4); - //每4个字节转换一次经纬度 lnglat.add(covertLngLat(target)); } - List> pointList = new ArrayList<>(); + List pointList = new ArrayList<>(); for (int i = 0; i < lnglat.size(); i += 2) { - Map lnglatMap = new HashMap<>(2); + PointDTO point = new PointDTO(); for (int j = 0; j < 2; j++) { - lnglatMap.put("lng", lnglat.get(i)); - lnglatMap.put("lat", lnglat.get(i + 1)); + point.setLng(lnglat.get(i)); + point.setLat(lnglat.get(i + 1)); } - //每2个元素作为一个对象 - pointList.add(lnglatMap); + pointList.add(point); } - return JSON.toJSONString(pointList); + return pointList; + } + + /** + * 生成路线对象点 + * 经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + */ + public static List formatRoute(byte[] routeBytes) { + List pointList = new ArrayList<>(); + for (int i = 0; i < routeBytes.length; i += 14) { + PointDTO point = new PointDTO(); + //每14个字节转换一次 + byte[] lngBytes = new byte[4]; + System.arraycopy(routeBytes, i, lngBytes, 0, 4); + point.setLng(covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(routeBytes, lngBytes.length, latBytes, 0, 4); + point.setLat(covertLngLat(latBytes)); + + byte[] depthBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length, + depthBytes, 0, 2); + point.setDepth(covertDepth(depthBytes)); + + byte[] pitchBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length, + pitchBytes, 0, 2); + point.setPitchAngle(covertPitchAngle(pitchBytes)); + + byte[] headingBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length + pitchBytes.length, + headingBytes, 0, 2); + point.setHeadingAngle(covertHeadingAngle(headingBytes)); + + pointList.add(point); + } + return pointList; } /** * 十进制转换算法 */ - private static double covertToDec(byte[] bytes) { + private static int covertToDec(byte[] bytes) { return ((bytes[0] & 0xFF) << 8) + (bytes[1] & 0xFF); } diff --git a/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java new file mode 100644 index 0000000..079e1d5 --- /dev/null +++ b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java @@ -0,0 +1,43 @@ +package com.casic.missiles.modular.system.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.Data; + +/** + * @author a203 + */ +@Data +@TableName("bus_task_route") +public class RoutePlan extends Model { + private static final long serialVersionUID = 1L; + + /** + * 数据库主键 + */ + @TableId(value = "ID", type = IdType.ASSIGN_ID) + private Long id; + /** + * 机器人ID + */ + @TableField("ROBOT_ID") + private Integer robotId; + /** + * 路线规划生成的时间 + */ + @TableField("PLAN_TIME") + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + @TableField("PLAN_TYPE") + private String planType; + /** + * 规划结果 + */ + @TableField("ROUTE_RESULT") + private String routeResult; +} diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java index 83cba30..5bf8bcc 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java @@ -3,8 +3,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.modular.system.model.ShelterPosition; -import java.util.List; - /** * @author a203 */ @@ -12,7 +10,7 @@ /** * 获取最新的方舱位置 * - * @return {@link List} + * @return {@link ShelterPosition} */ ShelterPosition selectLastOne(); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java index 55c8156..3a08fd0 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java @@ -11,6 +11,10 @@ public static final byte BITS_OF_END = (byte) 0x0A; public static final byte SHELTER_ID = (byte) 0xFF; + public static final int MAX_RADIUS = 80; + public static final int MAX_AGE = 240; + public static final int MIN_AGE = 1; + /** * 洋流相关常量 */ diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java index ed3cabe..c06ee68 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.utils; import com.alibaba.fastjson.JSON; +import com.casic.missiles.modular.system.dto.PointDTO; import com.casic.missiles.modular.system.model.RobotInfo; import com.casic.missiles.modular.system.model.ShelterPosition; +import lombok.extern.slf4j.Slf4j; import java.text.SimpleDateFormat; import java.util.*; @@ -12,6 +14,7 @@ * * @author a203 */ +@Slf4j public class DecodeData { /** * 水下机器人信息 @@ -79,15 +82,15 @@ } /** - * 区域覆盖 + * 区域覆盖-已校验 */ public static String decodeRobotRegion(byte[] bytes) { - Map regionMap = new HashMap<>(); - int count = bytes[4]; - regionMap.put("count", String.valueOf(count)); + Map regionMap = new HashMap<>(7); + int count = bytes[5]; + regionMap.put("count", count); byte[] idsBytes = new byte[count]; - System.arraycopy(bytes, 5, idsBytes, 0, count); + System.arraycopy(bytes, 5 + 1, idsBytes, 0, count); StringBuilder builder = new StringBuilder(); for (int i = 0; i < idsBytes.length; i++) { if (i != idsBytes.length - 1) { @@ -98,49 +101,70 @@ } regionMap.put("robotIds", builder.toString()); - //经度和纬度,所以需要*2 - int targetSize = count * 2 * 4; + //经度(4)、纬度(4) + int targetSize = count * (4 + 4); byte[] targetBytes = new byte[targetSize]; - //起始4个字节,机器人个数1个字节 - System.arraycopy(bytes, 5 + idsBytes.length, targetBytes, 0, targetSize); - regionMap.put("robotTargets", formatLanLat(targetBytes)); + //起始5个字节,机器人个数1个字节 + System.arraycopy(bytes, 5 + 1 + idsBytes.length, targetBytes, 0, targetSize); + regionMap.put("robotTargets", formatLngLat(targetBytes)); - regionMap.put("pointCount", String.valueOf(bytes[5 + idsBytes.length + targetBytes.length])); + regionMap.put("pointCount", bytes[5 + 1 + idsBytes.length + targetBytes.length]); byte[] radiusBytes = new byte[2]; - System.arraycopy(bytes, 5 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); + System.arraycopy(bytes, 5 + 1 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); regionMap.put("regionRadius", covertTargetDistance(radiusBytes)); - int aByte = bytes[5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; + int aByte = bytes[5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; if (aByte == 0) { regionMap.put("contour", "轮廓标志位:多边形," + count + "个轮廓点"); } else { regionMap.put("contour", "轮廓标志位:圆形," + count + "个轮廓点"); } - //经度和纬度,所以需要*2 - int pointSize = count * 2 * 4; + //经度(4)、纬度(4) + int pointSize = count * (4 + 4); byte[] pointBytes = new byte[pointSize]; System.arraycopy(bytes, - 5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, + 5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, pointBytes, 0, pointSize); - regionMap.put("robotPoints", formatLanLat(pointBytes)); + regionMap.put("robotPoints", formatLngLat(pointBytes)); return JSON.toJSONString(regionMap); } /** - * 路径规划 + * 路径规划-已校验 */ public static String decodeRobotRoute(byte[] bytes) { - Map routeMap = new HashMap<>(2); + Map routeMap = new HashMap<>(2); - int count = bytes[4]; - routeMap.put("routeCount", String.valueOf(count)); + byte[] countBytes = new byte[2]; + System.arraycopy(bytes, 5, countBytes, 0, 2); + int count = covertToDec(countBytes); + routeMap.put("routeCount", covertToDec(countBytes)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + int routeSize = count * (4 + 4 + 2 + 2 + 2); byte[] routeBytes = new byte[routeSize]; - System.arraycopy(bytes, 5, routeBytes, 0, routeSize); - routeMap.put("robotRoutes", formatLanLat(routeBytes)); + System.arraycopy(bytes, 5 + countBytes.length, routeBytes, 0, routeSize); + routeMap.put("robotRoutes", formatRoute(routeBytes)); + + byte[] sumTimeBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length, + sumTimeBytes, 0, 2); + routeMap.put("sumTime", covertToDec(sumTimeBytes)); + + byte[] sumDistanceBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length, + sumDistanceBytes, 0, 2); + routeMap.put("sumDistance", covertToDec(sumDistanceBytes)); + + byte[] sumPowerBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length + sumDistanceBytes.length, + sumPowerBytes, 0, 2); + routeMap.put("sumPower", covertToDec(sumPowerBytes)); return JSON.toJSONString(routeMap); } @@ -163,7 +187,7 @@ * 航路点任务 */ public static String decodeTaskRoute(byte[] bytes) { - Map taskMap = new HashMap<>(3); + Map taskMap = new HashMap<>(3); byte[] depthBytes = new byte[2]; System.arraycopy(bytes, 4, depthBytes, 0, 2); @@ -172,10 +196,11 @@ int count = bytes[6]; taskMap.put("routeCount", String.valueOf(count)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4) + int routeSize = count * (4 + 4); byte[] routeBytes = new byte[routeSize]; System.arraycopy(bytes, 7, routeBytes, 0, routeSize); - taskMap.put("robotRoutes", formatLanLat(routeBytes)); + taskMap.put("robotRoutes", formatLngLat(routeBytes)); return JSON.toJSONString(taskMap); } @@ -268,20 +293,37 @@ } /** - * AIS数据请求 + * 环境数据请求-已校验 + */ +// public static String decodeEnvRequest(byte[] bytes) { +// +// } + + /** + * AIS数据请求-已校验 */ public static String decodeAISRequest(byte[] bytes) { - Map taskMap = new HashMap<>(2); - byte[] depthBytes = new byte[2]; - System.arraycopy(bytes, 4, depthBytes, 0, 2); - taskMap.put("radius", covertToDec(depthBytes) + "km"); + Map aisMap = new HashMap<>(2); + byte[] radiusBytes = new byte[2]; + System.arraycopy(bytes, 5, radiusBytes, 0, 2); + aisMap.put("radius", covertToDec(radiusBytes)); - taskMap.put("shipCount", String.valueOf(bytes[6])); - return JSON.toJSONString(taskMap); + byte[] lngBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length, lngBytes, 0, 4); + aisMap.put("lng", covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length, latBytes, 0, 4); + aisMap.put("lat", covertLngLat(latBytes)); + + byte[] ageBytes = new byte[2]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length + latBytes.length, ageBytes, 0, 2); + aisMap.put("age", covertToDec(ageBytes)); + return JSON.toJSONString(aisMap); } /** - * 方舱位置 + * 方舱位置-已校验 * 编码encode * 解码decode */ @@ -301,32 +343,73 @@ return shelter; } - public static String formatLanLat(byte[] targetBytes) { + /** + * 生成经纬度对象点 + */ + public static List formatLngLat(byte[] targetBytes) { List lnglat = new ArrayList<>(); for (int i = 0; i < targetBytes.length; i += 4) { byte[] target = new byte[4]; System.arraycopy(targetBytes, i, target, 0, 4); - //每4个字节转换一次经纬度 lnglat.add(covertLngLat(target)); } - List> pointList = new ArrayList<>(); + List pointList = new ArrayList<>(); for (int i = 0; i < lnglat.size(); i += 2) { - Map lnglatMap = new HashMap<>(2); + PointDTO point = new PointDTO(); for (int j = 0; j < 2; j++) { - lnglatMap.put("lng", lnglat.get(i)); - lnglatMap.put("lat", lnglat.get(i + 1)); + point.setLng(lnglat.get(i)); + point.setLat(lnglat.get(i + 1)); } - //每2个元素作为一个对象 - pointList.add(lnglatMap); + pointList.add(point); } - return JSON.toJSONString(pointList); + return pointList; + } + + /** + * 生成路线对象点 + * 经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + */ + public static List formatRoute(byte[] routeBytes) { + List pointList = new ArrayList<>(); + for (int i = 0; i < routeBytes.length; i += 14) { + PointDTO point = new PointDTO(); + //每14个字节转换一次 + byte[] lngBytes = new byte[4]; + System.arraycopy(routeBytes, i, lngBytes, 0, 4); + point.setLng(covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(routeBytes, lngBytes.length, latBytes, 0, 4); + point.setLat(covertLngLat(latBytes)); + + byte[] depthBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length, + depthBytes, 0, 2); + point.setDepth(covertDepth(depthBytes)); + + byte[] pitchBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length, + pitchBytes, 0, 2); + point.setPitchAngle(covertPitchAngle(pitchBytes)); + + byte[] headingBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length + pitchBytes.length, + headingBytes, 0, 2); + point.setHeadingAngle(covertHeadingAngle(headingBytes)); + + pointList.add(point); + } + return pointList; } /** * 十进制转换算法 */ - private static double covertToDec(byte[] bytes) { + private static int covertToDec(byte[] bytes) { return ((bytes[0] & 0xFF) << 8) + (bytes[1] & 0xFF); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java index 0c21182..8b95501 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java @@ -59,7 +59,7 @@ dto.setAzimuth(angle); //洋流数据 - String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, "2021-10-22", "0", "10"); + String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, date, days, hour); OceanDetailDTO oceanDetailDTO = null; if ("0".equals(HttpRequestHelper.getOceanCode(oceanData))) { OceanDetailRemoteData remoteData = JSON.parseObject(oceanData, new TypeReference() { diff --git a/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java new file mode 100644 index 0000000..079e1d5 --- /dev/null +++ b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java @@ -0,0 +1,43 @@ +package com.casic.missiles.modular.system.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.Data; + +/** + * @author a203 + */ +@Data +@TableName("bus_task_route") +public class RoutePlan extends Model { + private static final long serialVersionUID = 1L; + + /** + * 数据库主键 + */ + @TableId(value = "ID", type = IdType.ASSIGN_ID) + private Long id; + /** + * 机器人ID + */ + @TableField("ROBOT_ID") + private Integer robotId; + /** + * 路线规划生成的时间 + */ + @TableField("PLAN_TIME") + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + @TableField("PLAN_TYPE") + private String planType; + /** + * 规划结果 + */ + @TableField("ROUTE_RESULT") + private String routeResult; +} diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java index 83cba30..5bf8bcc 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java @@ -3,8 +3,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.modular.system.model.ShelterPosition; -import java.util.List; - /** * @author a203 */ @@ -12,7 +10,7 @@ /** * 获取最新的方舱位置 * - * @return {@link List} + * @return {@link ShelterPosition} */ ShelterPosition selectLastOne(); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java index 55c8156..3a08fd0 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java @@ -11,6 +11,10 @@ public static final byte BITS_OF_END = (byte) 0x0A; public static final byte SHELTER_ID = (byte) 0xFF; + public static final int MAX_RADIUS = 80; + public static final int MAX_AGE = 240; + public static final int MIN_AGE = 1; + /** * 洋流相关常量 */ diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java index ed3cabe..c06ee68 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.utils; import com.alibaba.fastjson.JSON; +import com.casic.missiles.modular.system.dto.PointDTO; import com.casic.missiles.modular.system.model.RobotInfo; import com.casic.missiles.modular.system.model.ShelterPosition; +import lombok.extern.slf4j.Slf4j; import java.text.SimpleDateFormat; import java.util.*; @@ -12,6 +14,7 @@ * * @author a203 */ +@Slf4j public class DecodeData { /** * 水下机器人信息 @@ -79,15 +82,15 @@ } /** - * 区域覆盖 + * 区域覆盖-已校验 */ public static String decodeRobotRegion(byte[] bytes) { - Map regionMap = new HashMap<>(); - int count = bytes[4]; - regionMap.put("count", String.valueOf(count)); + Map regionMap = new HashMap<>(7); + int count = bytes[5]; + regionMap.put("count", count); byte[] idsBytes = new byte[count]; - System.arraycopy(bytes, 5, idsBytes, 0, count); + System.arraycopy(bytes, 5 + 1, idsBytes, 0, count); StringBuilder builder = new StringBuilder(); for (int i = 0; i < idsBytes.length; i++) { if (i != idsBytes.length - 1) { @@ -98,49 +101,70 @@ } regionMap.put("robotIds", builder.toString()); - //经度和纬度,所以需要*2 - int targetSize = count * 2 * 4; + //经度(4)、纬度(4) + int targetSize = count * (4 + 4); byte[] targetBytes = new byte[targetSize]; - //起始4个字节,机器人个数1个字节 - System.arraycopy(bytes, 5 + idsBytes.length, targetBytes, 0, targetSize); - regionMap.put("robotTargets", formatLanLat(targetBytes)); + //起始5个字节,机器人个数1个字节 + System.arraycopy(bytes, 5 + 1 + idsBytes.length, targetBytes, 0, targetSize); + regionMap.put("robotTargets", formatLngLat(targetBytes)); - regionMap.put("pointCount", String.valueOf(bytes[5 + idsBytes.length + targetBytes.length])); + regionMap.put("pointCount", bytes[5 + 1 + idsBytes.length + targetBytes.length]); byte[] radiusBytes = new byte[2]; - System.arraycopy(bytes, 5 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); + System.arraycopy(bytes, 5 + 1 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); regionMap.put("regionRadius", covertTargetDistance(radiusBytes)); - int aByte = bytes[5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; + int aByte = bytes[5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; if (aByte == 0) { regionMap.put("contour", "轮廓标志位:多边形," + count + "个轮廓点"); } else { regionMap.put("contour", "轮廓标志位:圆形," + count + "个轮廓点"); } - //经度和纬度,所以需要*2 - int pointSize = count * 2 * 4; + //经度(4)、纬度(4) + int pointSize = count * (4 + 4); byte[] pointBytes = new byte[pointSize]; System.arraycopy(bytes, - 5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, + 5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, pointBytes, 0, pointSize); - regionMap.put("robotPoints", formatLanLat(pointBytes)); + regionMap.put("robotPoints", formatLngLat(pointBytes)); return JSON.toJSONString(regionMap); } /** - * 路径规划 + * 路径规划-已校验 */ public static String decodeRobotRoute(byte[] bytes) { - Map routeMap = new HashMap<>(2); + Map routeMap = new HashMap<>(2); - int count = bytes[4]; - routeMap.put("routeCount", String.valueOf(count)); + byte[] countBytes = new byte[2]; + System.arraycopy(bytes, 5, countBytes, 0, 2); + int count = covertToDec(countBytes); + routeMap.put("routeCount", covertToDec(countBytes)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + int routeSize = count * (4 + 4 + 2 + 2 + 2); byte[] routeBytes = new byte[routeSize]; - System.arraycopy(bytes, 5, routeBytes, 0, routeSize); - routeMap.put("robotRoutes", formatLanLat(routeBytes)); + System.arraycopy(bytes, 5 + countBytes.length, routeBytes, 0, routeSize); + routeMap.put("robotRoutes", formatRoute(routeBytes)); + + byte[] sumTimeBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length, + sumTimeBytes, 0, 2); + routeMap.put("sumTime", covertToDec(sumTimeBytes)); + + byte[] sumDistanceBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length, + sumDistanceBytes, 0, 2); + routeMap.put("sumDistance", covertToDec(sumDistanceBytes)); + + byte[] sumPowerBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length + sumDistanceBytes.length, + sumPowerBytes, 0, 2); + routeMap.put("sumPower", covertToDec(sumPowerBytes)); return JSON.toJSONString(routeMap); } @@ -163,7 +187,7 @@ * 航路点任务 */ public static String decodeTaskRoute(byte[] bytes) { - Map taskMap = new HashMap<>(3); + Map taskMap = new HashMap<>(3); byte[] depthBytes = new byte[2]; System.arraycopy(bytes, 4, depthBytes, 0, 2); @@ -172,10 +196,11 @@ int count = bytes[6]; taskMap.put("routeCount", String.valueOf(count)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4) + int routeSize = count * (4 + 4); byte[] routeBytes = new byte[routeSize]; System.arraycopy(bytes, 7, routeBytes, 0, routeSize); - taskMap.put("robotRoutes", formatLanLat(routeBytes)); + taskMap.put("robotRoutes", formatLngLat(routeBytes)); return JSON.toJSONString(taskMap); } @@ -268,20 +293,37 @@ } /** - * AIS数据请求 + * 环境数据请求-已校验 + */ +// public static String decodeEnvRequest(byte[] bytes) { +// +// } + + /** + * AIS数据请求-已校验 */ public static String decodeAISRequest(byte[] bytes) { - Map taskMap = new HashMap<>(2); - byte[] depthBytes = new byte[2]; - System.arraycopy(bytes, 4, depthBytes, 0, 2); - taskMap.put("radius", covertToDec(depthBytes) + "km"); + Map aisMap = new HashMap<>(2); + byte[] radiusBytes = new byte[2]; + System.arraycopy(bytes, 5, radiusBytes, 0, 2); + aisMap.put("radius", covertToDec(radiusBytes)); - taskMap.put("shipCount", String.valueOf(bytes[6])); - return JSON.toJSONString(taskMap); + byte[] lngBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length, lngBytes, 0, 4); + aisMap.put("lng", covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length, latBytes, 0, 4); + aisMap.put("lat", covertLngLat(latBytes)); + + byte[] ageBytes = new byte[2]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length + latBytes.length, ageBytes, 0, 2); + aisMap.put("age", covertToDec(ageBytes)); + return JSON.toJSONString(aisMap); } /** - * 方舱位置 + * 方舱位置-已校验 * 编码encode * 解码decode */ @@ -301,32 +343,73 @@ return shelter; } - public static String formatLanLat(byte[] targetBytes) { + /** + * 生成经纬度对象点 + */ + public static List formatLngLat(byte[] targetBytes) { List lnglat = new ArrayList<>(); for (int i = 0; i < targetBytes.length; i += 4) { byte[] target = new byte[4]; System.arraycopy(targetBytes, i, target, 0, 4); - //每4个字节转换一次经纬度 lnglat.add(covertLngLat(target)); } - List> pointList = new ArrayList<>(); + List pointList = new ArrayList<>(); for (int i = 0; i < lnglat.size(); i += 2) { - Map lnglatMap = new HashMap<>(2); + PointDTO point = new PointDTO(); for (int j = 0; j < 2; j++) { - lnglatMap.put("lng", lnglat.get(i)); - lnglatMap.put("lat", lnglat.get(i + 1)); + point.setLng(lnglat.get(i)); + point.setLat(lnglat.get(i + 1)); } - //每2个元素作为一个对象 - pointList.add(lnglatMap); + pointList.add(point); } - return JSON.toJSONString(pointList); + return pointList; + } + + /** + * 生成路线对象点 + * 经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + */ + public static List formatRoute(byte[] routeBytes) { + List pointList = new ArrayList<>(); + for (int i = 0; i < routeBytes.length; i += 14) { + PointDTO point = new PointDTO(); + //每14个字节转换一次 + byte[] lngBytes = new byte[4]; + System.arraycopy(routeBytes, i, lngBytes, 0, 4); + point.setLng(covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(routeBytes, lngBytes.length, latBytes, 0, 4); + point.setLat(covertLngLat(latBytes)); + + byte[] depthBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length, + depthBytes, 0, 2); + point.setDepth(covertDepth(depthBytes)); + + byte[] pitchBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length, + pitchBytes, 0, 2); + point.setPitchAngle(covertPitchAngle(pitchBytes)); + + byte[] headingBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length + pitchBytes.length, + headingBytes, 0, 2); + point.setHeadingAngle(covertHeadingAngle(headingBytes)); + + pointList.add(point); + } + return pointList; } /** * 十进制转换算法 */ - private static double covertToDec(byte[] bytes) { + private static int covertToDec(byte[] bytes) { return ((bytes[0] & 0xFF) << 8) + (bytes[1] & 0xFF); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java index 0c21182..8b95501 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java @@ -59,7 +59,7 @@ dto.setAzimuth(angle); //洋流数据 - String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, "2021-10-22", "0", "10"); + String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, date, days, hour); OceanDetailDTO oceanDetailDTO = null; if ("0".equals(HttpRequestHelper.getOceanCode(oceanData))) { OceanDetailRemoteData remoteData = JSON.parseObject(oceanData, new TypeReference() { diff --git a/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java b/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java index 38f2903..71ad079 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java +++ b/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java @@ -1,10 +1,13 @@ package com.casic.missiles.socket.service.impl; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.casic.missiles.modular.system.dto.ShipDTO; import com.casic.missiles.modular.system.dto.TyphoonDTO; import com.casic.missiles.modular.system.model.RobotInfo; +import com.casic.missiles.modular.system.model.RoutePlan; import com.casic.missiles.modular.system.model.ShelterPosition; +import com.casic.missiles.modular.system.service.IRoutePlanService; import com.casic.missiles.modular.system.service.IShelterPositionService; import com.casic.missiles.modular.system.service.IShipService; import com.casic.missiles.modular.system.service.ITyphoonService; @@ -16,9 +19,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.text.SimpleDateFormat; +import java.util.*; /** * @author a203 @@ -27,16 +29,20 @@ @Service public class SocketServiceImpl implements ISocketService { + private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA); private final ITyphoonService typhoonService; private final IShipService shipService; private final IShelterPositionService shelterPositionService; + private final IRoutePlanService routePlanService; public SocketServiceImpl(ITyphoonService typhoonService, IShipService shipService, - IShelterPositionService shelterPositionService) { + IShelterPositionService shelterPositionService, + IRoutePlanService routePlanService) { this.typhoonService = typhoonService; this.shipService = shipService; this.shelterPositionService = shelterPositionService; + this.routePlanService = routePlanService; } private boolean isCorrectData(byte[] bytes) { @@ -81,10 +87,34 @@ case 0x01: //水下机器人信息 RobotInfo robotInfo = DecodeData.decodeRobotInfo(data); + log.info("robotInfo ===> " + JSON.toJSONString(robotInfo)); break; case 0x02: //算法结果 - + RoutePlan routePlan = new RoutePlan(); + routePlan.setPlanTime(dateFormat.format(new Date())); + routePlan.setRobotId(robotId); + int taskType = data[3]; + switch (taskType) { + case 0x01: + String robotRegion = DecodeData.decodeRobotRegion(data); + log.info("区域覆盖 ===> " + robotRegion); + //区域覆盖 + routePlan.setPlanType("0"); + routePlan.setRouteResult(robotRegion); + routePlanService.save(routePlan); + break; + case 0x02: + //路径规划 + String robotRoute = DecodeData.decodeRobotRoute(data); + log.info("路径规划 ===> " + robotRoute); + routePlan.setPlanType("1"); + routePlan.setRouteResult(robotRoute); + routePlanService.save(routePlan); + break; + default: + break; + } break; case 0x03: //任务数据还需要细分 @@ -110,29 +140,50 @@ break; case 0x05: //环境数据请求 +// String envRequest = DecodeData.decodeEnvRequest(data); + List typhoonList = typhoonService.currentTyphoonList(); /** * 如果有多个台风,只返回距离当前机器人或者方舱最近的台风信息 * */ + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); + String date = dateFormat.format(new Date()); + Map objectMap = EncodeData.encodeEnvironment( robotId, JSON.toJSONString(typhoonList), - "2021-10-22", "0", "10"); + date, "0", "10"); ctx.writeAndFlush(JSON.toJSONString(objectMap)); break; case 0x06: //AIS数据请求 - List ships = shipService.shipsInCircle("10448984,68042960,50", 30); + String aisRequest = DecodeData.decodeAISRequest(data); + log.info("aisRequest ===> " + aisRequest); + //{"radius":58,"lng":109.32222199129043,"lat":17.39223199775081,"age":12} + JSONObject jsonObject = JSON.parseObject(aisRequest); + + int radius = jsonObject.getInteger("radius"); + if (radius > Constant.MAX_RADIUS) { + radius = Constant.MAX_RADIUS; + } + double lat = jsonObject.getDouble("lat"); + double lng = jsonObject.getDouble("lng"); + int age = jsonObject.getInteger("age"); + if (age > Constant.MAX_AGE) { + age = Constant.MAX_AGE; + } + if (age < Constant.MIN_AGE) { + age = Constant.MIN_AGE; + } + String requestValue = lat * 600000 + "," + lng * 600000 + "," + radius; + + List ships = shipService.shipsInCircle(requestValue, age); Map map = EncodeData.encodeAIS(robotId, JSON.toJSONString(ships)); ctx.writeAndFlush(JSON.toJSONString(map)); break; case 0x07: //方舱位置 - ShelterPosition shelterPosition = DecodeData.decodeShelterPosition( - new byte[]{(byte) 0x2A, (byte) 0x23, (byte) 0x07, (byte) 0x00, (byte) 0x00, - (byte) 0x4D, (byte) 0xBD, (byte) 0x80, (byte) 0xCF, - (byte) 0x0C, (byte) 0x5E, (byte) 0x28, (byte) 0xC2, - (byte) 0xC7, (byte) 0x16, (byte) 0x0A} - ); + ShelterPosition shelterPosition = DecodeData.decodeShelterPosition(data); + log.info("shelterPosition ===> " + JSON.toJSONString(shelterPosition)); shelterPositionService.save(shelterPosition); break; default: diff --git a/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java new file mode 100644 index 0000000..079e1d5 --- /dev/null +++ b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java @@ -0,0 +1,43 @@ +package com.casic.missiles.modular.system.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.Data; + +/** + * @author a203 + */ +@Data +@TableName("bus_task_route") +public class RoutePlan extends Model { + private static final long serialVersionUID = 1L; + + /** + * 数据库主键 + */ + @TableId(value = "ID", type = IdType.ASSIGN_ID) + private Long id; + /** + * 机器人ID + */ + @TableField("ROBOT_ID") + private Integer robotId; + /** + * 路线规划生成的时间 + */ + @TableField("PLAN_TIME") + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + @TableField("PLAN_TYPE") + private String planType; + /** + * 规划结果 + */ + @TableField("ROUTE_RESULT") + private String routeResult; +} diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java index 83cba30..5bf8bcc 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java @@ -3,8 +3,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.modular.system.model.ShelterPosition; -import java.util.List; - /** * @author a203 */ @@ -12,7 +10,7 @@ /** * 获取最新的方舱位置 * - * @return {@link List} + * @return {@link ShelterPosition} */ ShelterPosition selectLastOne(); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java index 55c8156..3a08fd0 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java @@ -11,6 +11,10 @@ public static final byte BITS_OF_END = (byte) 0x0A; public static final byte SHELTER_ID = (byte) 0xFF; + public static final int MAX_RADIUS = 80; + public static final int MAX_AGE = 240; + public static final int MIN_AGE = 1; + /** * 洋流相关常量 */ diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java index ed3cabe..c06ee68 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.utils; import com.alibaba.fastjson.JSON; +import com.casic.missiles.modular.system.dto.PointDTO; import com.casic.missiles.modular.system.model.RobotInfo; import com.casic.missiles.modular.system.model.ShelterPosition; +import lombok.extern.slf4j.Slf4j; import java.text.SimpleDateFormat; import java.util.*; @@ -12,6 +14,7 @@ * * @author a203 */ +@Slf4j public class DecodeData { /** * 水下机器人信息 @@ -79,15 +82,15 @@ } /** - * 区域覆盖 + * 区域覆盖-已校验 */ public static String decodeRobotRegion(byte[] bytes) { - Map regionMap = new HashMap<>(); - int count = bytes[4]; - regionMap.put("count", String.valueOf(count)); + Map regionMap = new HashMap<>(7); + int count = bytes[5]; + regionMap.put("count", count); byte[] idsBytes = new byte[count]; - System.arraycopy(bytes, 5, idsBytes, 0, count); + System.arraycopy(bytes, 5 + 1, idsBytes, 0, count); StringBuilder builder = new StringBuilder(); for (int i = 0; i < idsBytes.length; i++) { if (i != idsBytes.length - 1) { @@ -98,49 +101,70 @@ } regionMap.put("robotIds", builder.toString()); - //经度和纬度,所以需要*2 - int targetSize = count * 2 * 4; + //经度(4)、纬度(4) + int targetSize = count * (4 + 4); byte[] targetBytes = new byte[targetSize]; - //起始4个字节,机器人个数1个字节 - System.arraycopy(bytes, 5 + idsBytes.length, targetBytes, 0, targetSize); - regionMap.put("robotTargets", formatLanLat(targetBytes)); + //起始5个字节,机器人个数1个字节 + System.arraycopy(bytes, 5 + 1 + idsBytes.length, targetBytes, 0, targetSize); + regionMap.put("robotTargets", formatLngLat(targetBytes)); - regionMap.put("pointCount", String.valueOf(bytes[5 + idsBytes.length + targetBytes.length])); + regionMap.put("pointCount", bytes[5 + 1 + idsBytes.length + targetBytes.length]); byte[] radiusBytes = new byte[2]; - System.arraycopy(bytes, 5 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); + System.arraycopy(bytes, 5 + 1 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); regionMap.put("regionRadius", covertTargetDistance(radiusBytes)); - int aByte = bytes[5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; + int aByte = bytes[5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; if (aByte == 0) { regionMap.put("contour", "轮廓标志位:多边形," + count + "个轮廓点"); } else { regionMap.put("contour", "轮廓标志位:圆形," + count + "个轮廓点"); } - //经度和纬度,所以需要*2 - int pointSize = count * 2 * 4; + //经度(4)、纬度(4) + int pointSize = count * (4 + 4); byte[] pointBytes = new byte[pointSize]; System.arraycopy(bytes, - 5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, + 5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, pointBytes, 0, pointSize); - regionMap.put("robotPoints", formatLanLat(pointBytes)); + regionMap.put("robotPoints", formatLngLat(pointBytes)); return JSON.toJSONString(regionMap); } /** - * 路径规划 + * 路径规划-已校验 */ public static String decodeRobotRoute(byte[] bytes) { - Map routeMap = new HashMap<>(2); + Map routeMap = new HashMap<>(2); - int count = bytes[4]; - routeMap.put("routeCount", String.valueOf(count)); + byte[] countBytes = new byte[2]; + System.arraycopy(bytes, 5, countBytes, 0, 2); + int count = covertToDec(countBytes); + routeMap.put("routeCount", covertToDec(countBytes)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + int routeSize = count * (4 + 4 + 2 + 2 + 2); byte[] routeBytes = new byte[routeSize]; - System.arraycopy(bytes, 5, routeBytes, 0, routeSize); - routeMap.put("robotRoutes", formatLanLat(routeBytes)); + System.arraycopy(bytes, 5 + countBytes.length, routeBytes, 0, routeSize); + routeMap.put("robotRoutes", formatRoute(routeBytes)); + + byte[] sumTimeBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length, + sumTimeBytes, 0, 2); + routeMap.put("sumTime", covertToDec(sumTimeBytes)); + + byte[] sumDistanceBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length, + sumDistanceBytes, 0, 2); + routeMap.put("sumDistance", covertToDec(sumDistanceBytes)); + + byte[] sumPowerBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length + sumDistanceBytes.length, + sumPowerBytes, 0, 2); + routeMap.put("sumPower", covertToDec(sumPowerBytes)); return JSON.toJSONString(routeMap); } @@ -163,7 +187,7 @@ * 航路点任务 */ public static String decodeTaskRoute(byte[] bytes) { - Map taskMap = new HashMap<>(3); + Map taskMap = new HashMap<>(3); byte[] depthBytes = new byte[2]; System.arraycopy(bytes, 4, depthBytes, 0, 2); @@ -172,10 +196,11 @@ int count = bytes[6]; taskMap.put("routeCount", String.valueOf(count)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4) + int routeSize = count * (4 + 4); byte[] routeBytes = new byte[routeSize]; System.arraycopy(bytes, 7, routeBytes, 0, routeSize); - taskMap.put("robotRoutes", formatLanLat(routeBytes)); + taskMap.put("robotRoutes", formatLngLat(routeBytes)); return JSON.toJSONString(taskMap); } @@ -268,20 +293,37 @@ } /** - * AIS数据请求 + * 环境数据请求-已校验 + */ +// public static String decodeEnvRequest(byte[] bytes) { +// +// } + + /** + * AIS数据请求-已校验 */ public static String decodeAISRequest(byte[] bytes) { - Map taskMap = new HashMap<>(2); - byte[] depthBytes = new byte[2]; - System.arraycopy(bytes, 4, depthBytes, 0, 2); - taskMap.put("radius", covertToDec(depthBytes) + "km"); + Map aisMap = new HashMap<>(2); + byte[] radiusBytes = new byte[2]; + System.arraycopy(bytes, 5, radiusBytes, 0, 2); + aisMap.put("radius", covertToDec(radiusBytes)); - taskMap.put("shipCount", String.valueOf(bytes[6])); - return JSON.toJSONString(taskMap); + byte[] lngBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length, lngBytes, 0, 4); + aisMap.put("lng", covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length, latBytes, 0, 4); + aisMap.put("lat", covertLngLat(latBytes)); + + byte[] ageBytes = new byte[2]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length + latBytes.length, ageBytes, 0, 2); + aisMap.put("age", covertToDec(ageBytes)); + return JSON.toJSONString(aisMap); } /** - * 方舱位置 + * 方舱位置-已校验 * 编码encode * 解码decode */ @@ -301,32 +343,73 @@ return shelter; } - public static String formatLanLat(byte[] targetBytes) { + /** + * 生成经纬度对象点 + */ + public static List formatLngLat(byte[] targetBytes) { List lnglat = new ArrayList<>(); for (int i = 0; i < targetBytes.length; i += 4) { byte[] target = new byte[4]; System.arraycopy(targetBytes, i, target, 0, 4); - //每4个字节转换一次经纬度 lnglat.add(covertLngLat(target)); } - List> pointList = new ArrayList<>(); + List pointList = new ArrayList<>(); for (int i = 0; i < lnglat.size(); i += 2) { - Map lnglatMap = new HashMap<>(2); + PointDTO point = new PointDTO(); for (int j = 0; j < 2; j++) { - lnglatMap.put("lng", lnglat.get(i)); - lnglatMap.put("lat", lnglat.get(i + 1)); + point.setLng(lnglat.get(i)); + point.setLat(lnglat.get(i + 1)); } - //每2个元素作为一个对象 - pointList.add(lnglatMap); + pointList.add(point); } - return JSON.toJSONString(pointList); + return pointList; + } + + /** + * 生成路线对象点 + * 经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + */ + public static List formatRoute(byte[] routeBytes) { + List pointList = new ArrayList<>(); + for (int i = 0; i < routeBytes.length; i += 14) { + PointDTO point = new PointDTO(); + //每14个字节转换一次 + byte[] lngBytes = new byte[4]; + System.arraycopy(routeBytes, i, lngBytes, 0, 4); + point.setLng(covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(routeBytes, lngBytes.length, latBytes, 0, 4); + point.setLat(covertLngLat(latBytes)); + + byte[] depthBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length, + depthBytes, 0, 2); + point.setDepth(covertDepth(depthBytes)); + + byte[] pitchBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length, + pitchBytes, 0, 2); + point.setPitchAngle(covertPitchAngle(pitchBytes)); + + byte[] headingBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length + pitchBytes.length, + headingBytes, 0, 2); + point.setHeadingAngle(covertHeadingAngle(headingBytes)); + + pointList.add(point); + } + return pointList; } /** * 十进制转换算法 */ - private static double covertToDec(byte[] bytes) { + private static int covertToDec(byte[] bytes) { return ((bytes[0] & 0xFF) << 8) + (bytes[1] & 0xFF); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java index 0c21182..8b95501 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java @@ -59,7 +59,7 @@ dto.setAzimuth(angle); //洋流数据 - String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, "2021-10-22", "0", "10"); + String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, date, days, hour); OceanDetailDTO oceanDetailDTO = null; if ("0".equals(HttpRequestHelper.getOceanCode(oceanData))) { OceanDetailRemoteData remoteData = JSON.parseObject(oceanData, new TypeReference() { diff --git a/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java b/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java index 38f2903..71ad079 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java +++ b/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java @@ -1,10 +1,13 @@ package com.casic.missiles.socket.service.impl; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.casic.missiles.modular.system.dto.ShipDTO; import com.casic.missiles.modular.system.dto.TyphoonDTO; import com.casic.missiles.modular.system.model.RobotInfo; +import com.casic.missiles.modular.system.model.RoutePlan; import com.casic.missiles.modular.system.model.ShelterPosition; +import com.casic.missiles.modular.system.service.IRoutePlanService; import com.casic.missiles.modular.system.service.IShelterPositionService; import com.casic.missiles.modular.system.service.IShipService; import com.casic.missiles.modular.system.service.ITyphoonService; @@ -16,9 +19,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.text.SimpleDateFormat; +import java.util.*; /** * @author a203 @@ -27,16 +29,20 @@ @Service public class SocketServiceImpl implements ISocketService { + private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA); private final ITyphoonService typhoonService; private final IShipService shipService; private final IShelterPositionService shelterPositionService; + private final IRoutePlanService routePlanService; public SocketServiceImpl(ITyphoonService typhoonService, IShipService shipService, - IShelterPositionService shelterPositionService) { + IShelterPositionService shelterPositionService, + IRoutePlanService routePlanService) { this.typhoonService = typhoonService; this.shipService = shipService; this.shelterPositionService = shelterPositionService; + this.routePlanService = routePlanService; } private boolean isCorrectData(byte[] bytes) { @@ -81,10 +87,34 @@ case 0x01: //水下机器人信息 RobotInfo robotInfo = DecodeData.decodeRobotInfo(data); + log.info("robotInfo ===> " + JSON.toJSONString(robotInfo)); break; case 0x02: //算法结果 - + RoutePlan routePlan = new RoutePlan(); + routePlan.setPlanTime(dateFormat.format(new Date())); + routePlan.setRobotId(robotId); + int taskType = data[3]; + switch (taskType) { + case 0x01: + String robotRegion = DecodeData.decodeRobotRegion(data); + log.info("区域覆盖 ===> " + robotRegion); + //区域覆盖 + routePlan.setPlanType("0"); + routePlan.setRouteResult(robotRegion); + routePlanService.save(routePlan); + break; + case 0x02: + //路径规划 + String robotRoute = DecodeData.decodeRobotRoute(data); + log.info("路径规划 ===> " + robotRoute); + routePlan.setPlanType("1"); + routePlan.setRouteResult(robotRoute); + routePlanService.save(routePlan); + break; + default: + break; + } break; case 0x03: //任务数据还需要细分 @@ -110,29 +140,50 @@ break; case 0x05: //环境数据请求 +// String envRequest = DecodeData.decodeEnvRequest(data); + List typhoonList = typhoonService.currentTyphoonList(); /** * 如果有多个台风,只返回距离当前机器人或者方舱最近的台风信息 * */ + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); + String date = dateFormat.format(new Date()); + Map objectMap = EncodeData.encodeEnvironment( robotId, JSON.toJSONString(typhoonList), - "2021-10-22", "0", "10"); + date, "0", "10"); ctx.writeAndFlush(JSON.toJSONString(objectMap)); break; case 0x06: //AIS数据请求 - List ships = shipService.shipsInCircle("10448984,68042960,50", 30); + String aisRequest = DecodeData.decodeAISRequest(data); + log.info("aisRequest ===> " + aisRequest); + //{"radius":58,"lng":109.32222199129043,"lat":17.39223199775081,"age":12} + JSONObject jsonObject = JSON.parseObject(aisRequest); + + int radius = jsonObject.getInteger("radius"); + if (radius > Constant.MAX_RADIUS) { + radius = Constant.MAX_RADIUS; + } + double lat = jsonObject.getDouble("lat"); + double lng = jsonObject.getDouble("lng"); + int age = jsonObject.getInteger("age"); + if (age > Constant.MAX_AGE) { + age = Constant.MAX_AGE; + } + if (age < Constant.MIN_AGE) { + age = Constant.MIN_AGE; + } + String requestValue = lat * 600000 + "," + lng * 600000 + "," + radius; + + List ships = shipService.shipsInCircle(requestValue, age); Map map = EncodeData.encodeAIS(robotId, JSON.toJSONString(ships)); ctx.writeAndFlush(JSON.toJSONString(map)); break; case 0x07: //方舱位置 - ShelterPosition shelterPosition = DecodeData.decodeShelterPosition( - new byte[]{(byte) 0x2A, (byte) 0x23, (byte) 0x07, (byte) 0x00, (byte) 0x00, - (byte) 0x4D, (byte) 0xBD, (byte) 0x80, (byte) 0xCF, - (byte) 0x0C, (byte) 0x5E, (byte) 0x28, (byte) 0xC2, - (byte) 0xC7, (byte) 0x16, (byte) 0x0A} - ); + ShelterPosition shelterPosition = DecodeData.decodeShelterPosition(data); + log.info("shelterPosition ===> " + JSON.toJSONString(shelterPosition)); shelterPositionService.save(shelterPosition); break; default: diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java new file mode 100644 index 0000000..1288112 --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.missiles.modular.system.dto.RoutePlanDTO; +import com.casic.missiles.modular.system.model.RoutePlan; + +/** + * @author a203 + */ +public interface RoutePlanMapper extends BaseMapper { + /** + * 获取最新的规划结果 + * + * @return {@link RoutePlanDTO} + */ + RoutePlan selectLastOne(); +} diff --git a/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java new file mode 100644 index 0000000..079e1d5 --- /dev/null +++ b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java @@ -0,0 +1,43 @@ +package com.casic.missiles.modular.system.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.Data; + +/** + * @author a203 + */ +@Data +@TableName("bus_task_route") +public class RoutePlan extends Model { + private static final long serialVersionUID = 1L; + + /** + * 数据库主键 + */ + @TableId(value = "ID", type = IdType.ASSIGN_ID) + private Long id; + /** + * 机器人ID + */ + @TableField("ROBOT_ID") + private Integer robotId; + /** + * 路线规划生成的时间 + */ + @TableField("PLAN_TIME") + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + @TableField("PLAN_TYPE") + private String planType; + /** + * 规划结果 + */ + @TableField("ROUTE_RESULT") + private String routeResult; +} diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java index 83cba30..5bf8bcc 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java @@ -3,8 +3,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.modular.system.model.ShelterPosition; -import java.util.List; - /** * @author a203 */ @@ -12,7 +10,7 @@ /** * 获取最新的方舱位置 * - * @return {@link List} + * @return {@link ShelterPosition} */ ShelterPosition selectLastOne(); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java index 55c8156..3a08fd0 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java @@ -11,6 +11,10 @@ public static final byte BITS_OF_END = (byte) 0x0A; public static final byte SHELTER_ID = (byte) 0xFF; + public static final int MAX_RADIUS = 80; + public static final int MAX_AGE = 240; + public static final int MIN_AGE = 1; + /** * 洋流相关常量 */ diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java index ed3cabe..c06ee68 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.utils; import com.alibaba.fastjson.JSON; +import com.casic.missiles.modular.system.dto.PointDTO; import com.casic.missiles.modular.system.model.RobotInfo; import com.casic.missiles.modular.system.model.ShelterPosition; +import lombok.extern.slf4j.Slf4j; import java.text.SimpleDateFormat; import java.util.*; @@ -12,6 +14,7 @@ * * @author a203 */ +@Slf4j public class DecodeData { /** * 水下机器人信息 @@ -79,15 +82,15 @@ } /** - * 区域覆盖 + * 区域覆盖-已校验 */ public static String decodeRobotRegion(byte[] bytes) { - Map regionMap = new HashMap<>(); - int count = bytes[4]; - regionMap.put("count", String.valueOf(count)); + Map regionMap = new HashMap<>(7); + int count = bytes[5]; + regionMap.put("count", count); byte[] idsBytes = new byte[count]; - System.arraycopy(bytes, 5, idsBytes, 0, count); + System.arraycopy(bytes, 5 + 1, idsBytes, 0, count); StringBuilder builder = new StringBuilder(); for (int i = 0; i < idsBytes.length; i++) { if (i != idsBytes.length - 1) { @@ -98,49 +101,70 @@ } regionMap.put("robotIds", builder.toString()); - //经度和纬度,所以需要*2 - int targetSize = count * 2 * 4; + //经度(4)、纬度(4) + int targetSize = count * (4 + 4); byte[] targetBytes = new byte[targetSize]; - //起始4个字节,机器人个数1个字节 - System.arraycopy(bytes, 5 + idsBytes.length, targetBytes, 0, targetSize); - regionMap.put("robotTargets", formatLanLat(targetBytes)); + //起始5个字节,机器人个数1个字节 + System.arraycopy(bytes, 5 + 1 + idsBytes.length, targetBytes, 0, targetSize); + regionMap.put("robotTargets", formatLngLat(targetBytes)); - regionMap.put("pointCount", String.valueOf(bytes[5 + idsBytes.length + targetBytes.length])); + regionMap.put("pointCount", bytes[5 + 1 + idsBytes.length + targetBytes.length]); byte[] radiusBytes = new byte[2]; - System.arraycopy(bytes, 5 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); + System.arraycopy(bytes, 5 + 1 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); regionMap.put("regionRadius", covertTargetDistance(radiusBytes)); - int aByte = bytes[5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; + int aByte = bytes[5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; if (aByte == 0) { regionMap.put("contour", "轮廓标志位:多边形," + count + "个轮廓点"); } else { regionMap.put("contour", "轮廓标志位:圆形," + count + "个轮廓点"); } - //经度和纬度,所以需要*2 - int pointSize = count * 2 * 4; + //经度(4)、纬度(4) + int pointSize = count * (4 + 4); byte[] pointBytes = new byte[pointSize]; System.arraycopy(bytes, - 5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, + 5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, pointBytes, 0, pointSize); - regionMap.put("robotPoints", formatLanLat(pointBytes)); + regionMap.put("robotPoints", formatLngLat(pointBytes)); return JSON.toJSONString(regionMap); } /** - * 路径规划 + * 路径规划-已校验 */ public static String decodeRobotRoute(byte[] bytes) { - Map routeMap = new HashMap<>(2); + Map routeMap = new HashMap<>(2); - int count = bytes[4]; - routeMap.put("routeCount", String.valueOf(count)); + byte[] countBytes = new byte[2]; + System.arraycopy(bytes, 5, countBytes, 0, 2); + int count = covertToDec(countBytes); + routeMap.put("routeCount", covertToDec(countBytes)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + int routeSize = count * (4 + 4 + 2 + 2 + 2); byte[] routeBytes = new byte[routeSize]; - System.arraycopy(bytes, 5, routeBytes, 0, routeSize); - routeMap.put("robotRoutes", formatLanLat(routeBytes)); + System.arraycopy(bytes, 5 + countBytes.length, routeBytes, 0, routeSize); + routeMap.put("robotRoutes", formatRoute(routeBytes)); + + byte[] sumTimeBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length, + sumTimeBytes, 0, 2); + routeMap.put("sumTime", covertToDec(sumTimeBytes)); + + byte[] sumDistanceBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length, + sumDistanceBytes, 0, 2); + routeMap.put("sumDistance", covertToDec(sumDistanceBytes)); + + byte[] sumPowerBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length + sumDistanceBytes.length, + sumPowerBytes, 0, 2); + routeMap.put("sumPower", covertToDec(sumPowerBytes)); return JSON.toJSONString(routeMap); } @@ -163,7 +187,7 @@ * 航路点任务 */ public static String decodeTaskRoute(byte[] bytes) { - Map taskMap = new HashMap<>(3); + Map taskMap = new HashMap<>(3); byte[] depthBytes = new byte[2]; System.arraycopy(bytes, 4, depthBytes, 0, 2); @@ -172,10 +196,11 @@ int count = bytes[6]; taskMap.put("routeCount", String.valueOf(count)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4) + int routeSize = count * (4 + 4); byte[] routeBytes = new byte[routeSize]; System.arraycopy(bytes, 7, routeBytes, 0, routeSize); - taskMap.put("robotRoutes", formatLanLat(routeBytes)); + taskMap.put("robotRoutes", formatLngLat(routeBytes)); return JSON.toJSONString(taskMap); } @@ -268,20 +293,37 @@ } /** - * AIS数据请求 + * 环境数据请求-已校验 + */ +// public static String decodeEnvRequest(byte[] bytes) { +// +// } + + /** + * AIS数据请求-已校验 */ public static String decodeAISRequest(byte[] bytes) { - Map taskMap = new HashMap<>(2); - byte[] depthBytes = new byte[2]; - System.arraycopy(bytes, 4, depthBytes, 0, 2); - taskMap.put("radius", covertToDec(depthBytes) + "km"); + Map aisMap = new HashMap<>(2); + byte[] radiusBytes = new byte[2]; + System.arraycopy(bytes, 5, radiusBytes, 0, 2); + aisMap.put("radius", covertToDec(radiusBytes)); - taskMap.put("shipCount", String.valueOf(bytes[6])); - return JSON.toJSONString(taskMap); + byte[] lngBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length, lngBytes, 0, 4); + aisMap.put("lng", covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length, latBytes, 0, 4); + aisMap.put("lat", covertLngLat(latBytes)); + + byte[] ageBytes = new byte[2]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length + latBytes.length, ageBytes, 0, 2); + aisMap.put("age", covertToDec(ageBytes)); + return JSON.toJSONString(aisMap); } /** - * 方舱位置 + * 方舱位置-已校验 * 编码encode * 解码decode */ @@ -301,32 +343,73 @@ return shelter; } - public static String formatLanLat(byte[] targetBytes) { + /** + * 生成经纬度对象点 + */ + public static List formatLngLat(byte[] targetBytes) { List lnglat = new ArrayList<>(); for (int i = 0; i < targetBytes.length; i += 4) { byte[] target = new byte[4]; System.arraycopy(targetBytes, i, target, 0, 4); - //每4个字节转换一次经纬度 lnglat.add(covertLngLat(target)); } - List> pointList = new ArrayList<>(); + List pointList = new ArrayList<>(); for (int i = 0; i < lnglat.size(); i += 2) { - Map lnglatMap = new HashMap<>(2); + PointDTO point = new PointDTO(); for (int j = 0; j < 2; j++) { - lnglatMap.put("lng", lnglat.get(i)); - lnglatMap.put("lat", lnglat.get(i + 1)); + point.setLng(lnglat.get(i)); + point.setLat(lnglat.get(i + 1)); } - //每2个元素作为一个对象 - pointList.add(lnglatMap); + pointList.add(point); } - return JSON.toJSONString(pointList); + return pointList; + } + + /** + * 生成路线对象点 + * 经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + */ + public static List formatRoute(byte[] routeBytes) { + List pointList = new ArrayList<>(); + for (int i = 0; i < routeBytes.length; i += 14) { + PointDTO point = new PointDTO(); + //每14个字节转换一次 + byte[] lngBytes = new byte[4]; + System.arraycopy(routeBytes, i, lngBytes, 0, 4); + point.setLng(covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(routeBytes, lngBytes.length, latBytes, 0, 4); + point.setLat(covertLngLat(latBytes)); + + byte[] depthBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length, + depthBytes, 0, 2); + point.setDepth(covertDepth(depthBytes)); + + byte[] pitchBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length, + pitchBytes, 0, 2); + point.setPitchAngle(covertPitchAngle(pitchBytes)); + + byte[] headingBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length + pitchBytes.length, + headingBytes, 0, 2); + point.setHeadingAngle(covertHeadingAngle(headingBytes)); + + pointList.add(point); + } + return pointList; } /** * 十进制转换算法 */ - private static double covertToDec(byte[] bytes) { + private static int covertToDec(byte[] bytes) { return ((bytes[0] & 0xFF) << 8) + (bytes[1] & 0xFF); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java index 0c21182..8b95501 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java @@ -59,7 +59,7 @@ dto.setAzimuth(angle); //洋流数据 - String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, "2021-10-22", "0", "10"); + String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, date, days, hour); OceanDetailDTO oceanDetailDTO = null; if ("0".equals(HttpRequestHelper.getOceanCode(oceanData))) { OceanDetailRemoteData remoteData = JSON.parseObject(oceanData, new TypeReference() { diff --git a/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java b/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java index 38f2903..71ad079 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java +++ b/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java @@ -1,10 +1,13 @@ package com.casic.missiles.socket.service.impl; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.casic.missiles.modular.system.dto.ShipDTO; import com.casic.missiles.modular.system.dto.TyphoonDTO; import com.casic.missiles.modular.system.model.RobotInfo; +import com.casic.missiles.modular.system.model.RoutePlan; import com.casic.missiles.modular.system.model.ShelterPosition; +import com.casic.missiles.modular.system.service.IRoutePlanService; import com.casic.missiles.modular.system.service.IShelterPositionService; import com.casic.missiles.modular.system.service.IShipService; import com.casic.missiles.modular.system.service.ITyphoonService; @@ -16,9 +19,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.text.SimpleDateFormat; +import java.util.*; /** * @author a203 @@ -27,16 +29,20 @@ @Service public class SocketServiceImpl implements ISocketService { + private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA); private final ITyphoonService typhoonService; private final IShipService shipService; private final IShelterPositionService shelterPositionService; + private final IRoutePlanService routePlanService; public SocketServiceImpl(ITyphoonService typhoonService, IShipService shipService, - IShelterPositionService shelterPositionService) { + IShelterPositionService shelterPositionService, + IRoutePlanService routePlanService) { this.typhoonService = typhoonService; this.shipService = shipService; this.shelterPositionService = shelterPositionService; + this.routePlanService = routePlanService; } private boolean isCorrectData(byte[] bytes) { @@ -81,10 +87,34 @@ case 0x01: //水下机器人信息 RobotInfo robotInfo = DecodeData.decodeRobotInfo(data); + log.info("robotInfo ===> " + JSON.toJSONString(robotInfo)); break; case 0x02: //算法结果 - + RoutePlan routePlan = new RoutePlan(); + routePlan.setPlanTime(dateFormat.format(new Date())); + routePlan.setRobotId(robotId); + int taskType = data[3]; + switch (taskType) { + case 0x01: + String robotRegion = DecodeData.decodeRobotRegion(data); + log.info("区域覆盖 ===> " + robotRegion); + //区域覆盖 + routePlan.setPlanType("0"); + routePlan.setRouteResult(robotRegion); + routePlanService.save(routePlan); + break; + case 0x02: + //路径规划 + String robotRoute = DecodeData.decodeRobotRoute(data); + log.info("路径规划 ===> " + robotRoute); + routePlan.setPlanType("1"); + routePlan.setRouteResult(robotRoute); + routePlanService.save(routePlan); + break; + default: + break; + } break; case 0x03: //任务数据还需要细分 @@ -110,29 +140,50 @@ break; case 0x05: //环境数据请求 +// String envRequest = DecodeData.decodeEnvRequest(data); + List typhoonList = typhoonService.currentTyphoonList(); /** * 如果有多个台风,只返回距离当前机器人或者方舱最近的台风信息 * */ + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); + String date = dateFormat.format(new Date()); + Map objectMap = EncodeData.encodeEnvironment( robotId, JSON.toJSONString(typhoonList), - "2021-10-22", "0", "10"); + date, "0", "10"); ctx.writeAndFlush(JSON.toJSONString(objectMap)); break; case 0x06: //AIS数据请求 - List ships = shipService.shipsInCircle("10448984,68042960,50", 30); + String aisRequest = DecodeData.decodeAISRequest(data); + log.info("aisRequest ===> " + aisRequest); + //{"radius":58,"lng":109.32222199129043,"lat":17.39223199775081,"age":12} + JSONObject jsonObject = JSON.parseObject(aisRequest); + + int radius = jsonObject.getInteger("radius"); + if (radius > Constant.MAX_RADIUS) { + radius = Constant.MAX_RADIUS; + } + double lat = jsonObject.getDouble("lat"); + double lng = jsonObject.getDouble("lng"); + int age = jsonObject.getInteger("age"); + if (age > Constant.MAX_AGE) { + age = Constant.MAX_AGE; + } + if (age < Constant.MIN_AGE) { + age = Constant.MIN_AGE; + } + String requestValue = lat * 600000 + "," + lng * 600000 + "," + radius; + + List ships = shipService.shipsInCircle(requestValue, age); Map map = EncodeData.encodeAIS(robotId, JSON.toJSONString(ships)); ctx.writeAndFlush(JSON.toJSONString(map)); break; case 0x07: //方舱位置 - ShelterPosition shelterPosition = DecodeData.decodeShelterPosition( - new byte[]{(byte) 0x2A, (byte) 0x23, (byte) 0x07, (byte) 0x00, (byte) 0x00, - (byte) 0x4D, (byte) 0xBD, (byte) 0x80, (byte) 0xCF, - (byte) 0x0C, (byte) 0x5E, (byte) 0x28, (byte) 0xC2, - (byte) 0xC7, (byte) 0x16, (byte) 0x0A} - ); + ShelterPosition shelterPosition = DecodeData.decodeShelterPosition(data); + log.info("shelterPosition ===> " + JSON.toJSONString(shelterPosition)); shelterPositionService.save(shelterPosition); break; default: diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java new file mode 100644 index 0000000..1288112 --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.missiles.modular.system.dto.RoutePlanDTO; +import com.casic.missiles.modular.system.model.RoutePlan; + +/** + * @author a203 + */ +public interface RoutePlanMapper extends BaseMapper { + /** + * 获取最新的规划结果 + * + * @return {@link RoutePlanDTO} + */ + RoutePlan selectLastOne(); +} diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dao/mapping/RoutePlanMapper.xml b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/mapping/RoutePlanMapper.xml new file mode 100644 index 0000000..e347d2f --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/mapping/RoutePlanMapper.xml @@ -0,0 +1,21 @@ + + + + + + + ID AS id, + ROBOT_ID AS robotId, + PLAN_TIME AS planTime, + PLAN_TYPE AS planType, + ROUTE_RESULT AS routeResult + + + + \ No newline at end of file diff --git a/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java new file mode 100644 index 0000000..079e1d5 --- /dev/null +++ b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java @@ -0,0 +1,43 @@ +package com.casic.missiles.modular.system.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.Data; + +/** + * @author a203 + */ +@Data +@TableName("bus_task_route") +public class RoutePlan extends Model { + private static final long serialVersionUID = 1L; + + /** + * 数据库主键 + */ + @TableId(value = "ID", type = IdType.ASSIGN_ID) + private Long id; + /** + * 机器人ID + */ + @TableField("ROBOT_ID") + private Integer robotId; + /** + * 路线规划生成的时间 + */ + @TableField("PLAN_TIME") + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + @TableField("PLAN_TYPE") + private String planType; + /** + * 规划结果 + */ + @TableField("ROUTE_RESULT") + private String routeResult; +} diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java index 83cba30..5bf8bcc 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java @@ -3,8 +3,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.modular.system.model.ShelterPosition; -import java.util.List; - /** * @author a203 */ @@ -12,7 +10,7 @@ /** * 获取最新的方舱位置 * - * @return {@link List} + * @return {@link ShelterPosition} */ ShelterPosition selectLastOne(); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java index 55c8156..3a08fd0 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java @@ -11,6 +11,10 @@ public static final byte BITS_OF_END = (byte) 0x0A; public static final byte SHELTER_ID = (byte) 0xFF; + public static final int MAX_RADIUS = 80; + public static final int MAX_AGE = 240; + public static final int MIN_AGE = 1; + /** * 洋流相关常量 */ diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java index ed3cabe..c06ee68 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.utils; import com.alibaba.fastjson.JSON; +import com.casic.missiles.modular.system.dto.PointDTO; import com.casic.missiles.modular.system.model.RobotInfo; import com.casic.missiles.modular.system.model.ShelterPosition; +import lombok.extern.slf4j.Slf4j; import java.text.SimpleDateFormat; import java.util.*; @@ -12,6 +14,7 @@ * * @author a203 */ +@Slf4j public class DecodeData { /** * 水下机器人信息 @@ -79,15 +82,15 @@ } /** - * 区域覆盖 + * 区域覆盖-已校验 */ public static String decodeRobotRegion(byte[] bytes) { - Map regionMap = new HashMap<>(); - int count = bytes[4]; - regionMap.put("count", String.valueOf(count)); + Map regionMap = new HashMap<>(7); + int count = bytes[5]; + regionMap.put("count", count); byte[] idsBytes = new byte[count]; - System.arraycopy(bytes, 5, idsBytes, 0, count); + System.arraycopy(bytes, 5 + 1, idsBytes, 0, count); StringBuilder builder = new StringBuilder(); for (int i = 0; i < idsBytes.length; i++) { if (i != idsBytes.length - 1) { @@ -98,49 +101,70 @@ } regionMap.put("robotIds", builder.toString()); - //经度和纬度,所以需要*2 - int targetSize = count * 2 * 4; + //经度(4)、纬度(4) + int targetSize = count * (4 + 4); byte[] targetBytes = new byte[targetSize]; - //起始4个字节,机器人个数1个字节 - System.arraycopy(bytes, 5 + idsBytes.length, targetBytes, 0, targetSize); - regionMap.put("robotTargets", formatLanLat(targetBytes)); + //起始5个字节,机器人个数1个字节 + System.arraycopy(bytes, 5 + 1 + idsBytes.length, targetBytes, 0, targetSize); + regionMap.put("robotTargets", formatLngLat(targetBytes)); - regionMap.put("pointCount", String.valueOf(bytes[5 + idsBytes.length + targetBytes.length])); + regionMap.put("pointCount", bytes[5 + 1 + idsBytes.length + targetBytes.length]); byte[] radiusBytes = new byte[2]; - System.arraycopy(bytes, 5 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); + System.arraycopy(bytes, 5 + 1 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); regionMap.put("regionRadius", covertTargetDistance(radiusBytes)); - int aByte = bytes[5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; + int aByte = bytes[5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; if (aByte == 0) { regionMap.put("contour", "轮廓标志位:多边形," + count + "个轮廓点"); } else { regionMap.put("contour", "轮廓标志位:圆形," + count + "个轮廓点"); } - //经度和纬度,所以需要*2 - int pointSize = count * 2 * 4; + //经度(4)、纬度(4) + int pointSize = count * (4 + 4); byte[] pointBytes = new byte[pointSize]; System.arraycopy(bytes, - 5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, + 5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, pointBytes, 0, pointSize); - regionMap.put("robotPoints", formatLanLat(pointBytes)); + regionMap.put("robotPoints", formatLngLat(pointBytes)); return JSON.toJSONString(regionMap); } /** - * 路径规划 + * 路径规划-已校验 */ public static String decodeRobotRoute(byte[] bytes) { - Map routeMap = new HashMap<>(2); + Map routeMap = new HashMap<>(2); - int count = bytes[4]; - routeMap.put("routeCount", String.valueOf(count)); + byte[] countBytes = new byte[2]; + System.arraycopy(bytes, 5, countBytes, 0, 2); + int count = covertToDec(countBytes); + routeMap.put("routeCount", covertToDec(countBytes)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + int routeSize = count * (4 + 4 + 2 + 2 + 2); byte[] routeBytes = new byte[routeSize]; - System.arraycopy(bytes, 5, routeBytes, 0, routeSize); - routeMap.put("robotRoutes", formatLanLat(routeBytes)); + System.arraycopy(bytes, 5 + countBytes.length, routeBytes, 0, routeSize); + routeMap.put("robotRoutes", formatRoute(routeBytes)); + + byte[] sumTimeBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length, + sumTimeBytes, 0, 2); + routeMap.put("sumTime", covertToDec(sumTimeBytes)); + + byte[] sumDistanceBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length, + sumDistanceBytes, 0, 2); + routeMap.put("sumDistance", covertToDec(sumDistanceBytes)); + + byte[] sumPowerBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length + sumDistanceBytes.length, + sumPowerBytes, 0, 2); + routeMap.put("sumPower", covertToDec(sumPowerBytes)); return JSON.toJSONString(routeMap); } @@ -163,7 +187,7 @@ * 航路点任务 */ public static String decodeTaskRoute(byte[] bytes) { - Map taskMap = new HashMap<>(3); + Map taskMap = new HashMap<>(3); byte[] depthBytes = new byte[2]; System.arraycopy(bytes, 4, depthBytes, 0, 2); @@ -172,10 +196,11 @@ int count = bytes[6]; taskMap.put("routeCount", String.valueOf(count)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4) + int routeSize = count * (4 + 4); byte[] routeBytes = new byte[routeSize]; System.arraycopy(bytes, 7, routeBytes, 0, routeSize); - taskMap.put("robotRoutes", formatLanLat(routeBytes)); + taskMap.put("robotRoutes", formatLngLat(routeBytes)); return JSON.toJSONString(taskMap); } @@ -268,20 +293,37 @@ } /** - * AIS数据请求 + * 环境数据请求-已校验 + */ +// public static String decodeEnvRequest(byte[] bytes) { +// +// } + + /** + * AIS数据请求-已校验 */ public static String decodeAISRequest(byte[] bytes) { - Map taskMap = new HashMap<>(2); - byte[] depthBytes = new byte[2]; - System.arraycopy(bytes, 4, depthBytes, 0, 2); - taskMap.put("radius", covertToDec(depthBytes) + "km"); + Map aisMap = new HashMap<>(2); + byte[] radiusBytes = new byte[2]; + System.arraycopy(bytes, 5, radiusBytes, 0, 2); + aisMap.put("radius", covertToDec(radiusBytes)); - taskMap.put("shipCount", String.valueOf(bytes[6])); - return JSON.toJSONString(taskMap); + byte[] lngBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length, lngBytes, 0, 4); + aisMap.put("lng", covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length, latBytes, 0, 4); + aisMap.put("lat", covertLngLat(latBytes)); + + byte[] ageBytes = new byte[2]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length + latBytes.length, ageBytes, 0, 2); + aisMap.put("age", covertToDec(ageBytes)); + return JSON.toJSONString(aisMap); } /** - * 方舱位置 + * 方舱位置-已校验 * 编码encode * 解码decode */ @@ -301,32 +343,73 @@ return shelter; } - public static String formatLanLat(byte[] targetBytes) { + /** + * 生成经纬度对象点 + */ + public static List formatLngLat(byte[] targetBytes) { List lnglat = new ArrayList<>(); for (int i = 0; i < targetBytes.length; i += 4) { byte[] target = new byte[4]; System.arraycopy(targetBytes, i, target, 0, 4); - //每4个字节转换一次经纬度 lnglat.add(covertLngLat(target)); } - List> pointList = new ArrayList<>(); + List pointList = new ArrayList<>(); for (int i = 0; i < lnglat.size(); i += 2) { - Map lnglatMap = new HashMap<>(2); + PointDTO point = new PointDTO(); for (int j = 0; j < 2; j++) { - lnglatMap.put("lng", lnglat.get(i)); - lnglatMap.put("lat", lnglat.get(i + 1)); + point.setLng(lnglat.get(i)); + point.setLat(lnglat.get(i + 1)); } - //每2个元素作为一个对象 - pointList.add(lnglatMap); + pointList.add(point); } - return JSON.toJSONString(pointList); + return pointList; + } + + /** + * 生成路线对象点 + * 经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + */ + public static List formatRoute(byte[] routeBytes) { + List pointList = new ArrayList<>(); + for (int i = 0; i < routeBytes.length; i += 14) { + PointDTO point = new PointDTO(); + //每14个字节转换一次 + byte[] lngBytes = new byte[4]; + System.arraycopy(routeBytes, i, lngBytes, 0, 4); + point.setLng(covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(routeBytes, lngBytes.length, latBytes, 0, 4); + point.setLat(covertLngLat(latBytes)); + + byte[] depthBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length, + depthBytes, 0, 2); + point.setDepth(covertDepth(depthBytes)); + + byte[] pitchBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length, + pitchBytes, 0, 2); + point.setPitchAngle(covertPitchAngle(pitchBytes)); + + byte[] headingBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length + pitchBytes.length, + headingBytes, 0, 2); + point.setHeadingAngle(covertHeadingAngle(headingBytes)); + + pointList.add(point); + } + return pointList; } /** * 十进制转换算法 */ - private static double covertToDec(byte[] bytes) { + private static int covertToDec(byte[] bytes) { return ((bytes[0] & 0xFF) << 8) + (bytes[1] & 0xFF); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java index 0c21182..8b95501 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java @@ -59,7 +59,7 @@ dto.setAzimuth(angle); //洋流数据 - String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, "2021-10-22", "0", "10"); + String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, date, days, hour); OceanDetailDTO oceanDetailDTO = null; if ("0".equals(HttpRequestHelper.getOceanCode(oceanData))) { OceanDetailRemoteData remoteData = JSON.parseObject(oceanData, new TypeReference() { diff --git a/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java b/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java index 38f2903..71ad079 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java +++ b/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java @@ -1,10 +1,13 @@ package com.casic.missiles.socket.service.impl; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.casic.missiles.modular.system.dto.ShipDTO; import com.casic.missiles.modular.system.dto.TyphoonDTO; import com.casic.missiles.modular.system.model.RobotInfo; +import com.casic.missiles.modular.system.model.RoutePlan; import com.casic.missiles.modular.system.model.ShelterPosition; +import com.casic.missiles.modular.system.service.IRoutePlanService; import com.casic.missiles.modular.system.service.IShelterPositionService; import com.casic.missiles.modular.system.service.IShipService; import com.casic.missiles.modular.system.service.ITyphoonService; @@ -16,9 +19,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.text.SimpleDateFormat; +import java.util.*; /** * @author a203 @@ -27,16 +29,20 @@ @Service public class SocketServiceImpl implements ISocketService { + private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA); private final ITyphoonService typhoonService; private final IShipService shipService; private final IShelterPositionService shelterPositionService; + private final IRoutePlanService routePlanService; public SocketServiceImpl(ITyphoonService typhoonService, IShipService shipService, - IShelterPositionService shelterPositionService) { + IShelterPositionService shelterPositionService, + IRoutePlanService routePlanService) { this.typhoonService = typhoonService; this.shipService = shipService; this.shelterPositionService = shelterPositionService; + this.routePlanService = routePlanService; } private boolean isCorrectData(byte[] bytes) { @@ -81,10 +87,34 @@ case 0x01: //水下机器人信息 RobotInfo robotInfo = DecodeData.decodeRobotInfo(data); + log.info("robotInfo ===> " + JSON.toJSONString(robotInfo)); break; case 0x02: //算法结果 - + RoutePlan routePlan = new RoutePlan(); + routePlan.setPlanTime(dateFormat.format(new Date())); + routePlan.setRobotId(robotId); + int taskType = data[3]; + switch (taskType) { + case 0x01: + String robotRegion = DecodeData.decodeRobotRegion(data); + log.info("区域覆盖 ===> " + robotRegion); + //区域覆盖 + routePlan.setPlanType("0"); + routePlan.setRouteResult(robotRegion); + routePlanService.save(routePlan); + break; + case 0x02: + //路径规划 + String robotRoute = DecodeData.decodeRobotRoute(data); + log.info("路径规划 ===> " + robotRoute); + routePlan.setPlanType("1"); + routePlan.setRouteResult(robotRoute); + routePlanService.save(routePlan); + break; + default: + break; + } break; case 0x03: //任务数据还需要细分 @@ -110,29 +140,50 @@ break; case 0x05: //环境数据请求 +// String envRequest = DecodeData.decodeEnvRequest(data); + List typhoonList = typhoonService.currentTyphoonList(); /** * 如果有多个台风,只返回距离当前机器人或者方舱最近的台风信息 * */ + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); + String date = dateFormat.format(new Date()); + Map objectMap = EncodeData.encodeEnvironment( robotId, JSON.toJSONString(typhoonList), - "2021-10-22", "0", "10"); + date, "0", "10"); ctx.writeAndFlush(JSON.toJSONString(objectMap)); break; case 0x06: //AIS数据请求 - List ships = shipService.shipsInCircle("10448984,68042960,50", 30); + String aisRequest = DecodeData.decodeAISRequest(data); + log.info("aisRequest ===> " + aisRequest); + //{"radius":58,"lng":109.32222199129043,"lat":17.39223199775081,"age":12} + JSONObject jsonObject = JSON.parseObject(aisRequest); + + int radius = jsonObject.getInteger("radius"); + if (radius > Constant.MAX_RADIUS) { + radius = Constant.MAX_RADIUS; + } + double lat = jsonObject.getDouble("lat"); + double lng = jsonObject.getDouble("lng"); + int age = jsonObject.getInteger("age"); + if (age > Constant.MAX_AGE) { + age = Constant.MAX_AGE; + } + if (age < Constant.MIN_AGE) { + age = Constant.MIN_AGE; + } + String requestValue = lat * 600000 + "," + lng * 600000 + "," + radius; + + List ships = shipService.shipsInCircle(requestValue, age); Map map = EncodeData.encodeAIS(robotId, JSON.toJSONString(ships)); ctx.writeAndFlush(JSON.toJSONString(map)); break; case 0x07: //方舱位置 - ShelterPosition shelterPosition = DecodeData.decodeShelterPosition( - new byte[]{(byte) 0x2A, (byte) 0x23, (byte) 0x07, (byte) 0x00, (byte) 0x00, - (byte) 0x4D, (byte) 0xBD, (byte) 0x80, (byte) 0xCF, - (byte) 0x0C, (byte) 0x5E, (byte) 0x28, (byte) 0xC2, - (byte) 0xC7, (byte) 0x16, (byte) 0x0A} - ); + ShelterPosition shelterPosition = DecodeData.decodeShelterPosition(data); + log.info("shelterPosition ===> " + JSON.toJSONString(shelterPosition)); shelterPositionService.save(shelterPosition); break; default: diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java new file mode 100644 index 0000000..1288112 --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.missiles.modular.system.dto.RoutePlanDTO; +import com.casic.missiles.modular.system.model.RoutePlan; + +/** + * @author a203 + */ +public interface RoutePlanMapper extends BaseMapper { + /** + * 获取最新的规划结果 + * + * @return {@link RoutePlanDTO} + */ + RoutePlan selectLastOne(); +} diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dao/mapping/RoutePlanMapper.xml b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/mapping/RoutePlanMapper.xml new file mode 100644 index 0000000..e347d2f --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/mapping/RoutePlanMapper.xml @@ -0,0 +1,21 @@ + + + + + + + ID AS id, + ROBOT_ID AS robotId, + PLAN_TIME AS planTime, + PLAN_TYPE AS planType, + ROUTE_RESULT AS routeResult + + + + \ No newline at end of file diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dto/PointDTO.java b/casic-task/src/main/java/com/casic/missiles/modular/system/dto/PointDTO.java new file mode 100644 index 0000000..6a4e1e1 --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dto/PointDTO.java @@ -0,0 +1,24 @@ +package com.casic.missiles.modular.system.dto; + +import lombok.Data; + +/** + * @author a203 + */ +@Data +public class PointDTO { + private Double lng; + private Double lat; + /** + * 俯仰角: -40.43 + */ + private Float pitchAngle; + /** + * 航向角:124.66 + */ + private Float headingAngle; + /** + * 规划航路点深度 + */ + private Double depth; +} diff --git a/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java new file mode 100644 index 0000000..079e1d5 --- /dev/null +++ b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java @@ -0,0 +1,43 @@ +package com.casic.missiles.modular.system.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.Data; + +/** + * @author a203 + */ +@Data +@TableName("bus_task_route") +public class RoutePlan extends Model { + private static final long serialVersionUID = 1L; + + /** + * 数据库主键 + */ + @TableId(value = "ID", type = IdType.ASSIGN_ID) + private Long id; + /** + * 机器人ID + */ + @TableField("ROBOT_ID") + private Integer robotId; + /** + * 路线规划生成的时间 + */ + @TableField("PLAN_TIME") + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + @TableField("PLAN_TYPE") + private String planType; + /** + * 规划结果 + */ + @TableField("ROUTE_RESULT") + private String routeResult; +} diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java index 83cba30..5bf8bcc 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java @@ -3,8 +3,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.modular.system.model.ShelterPosition; -import java.util.List; - /** * @author a203 */ @@ -12,7 +10,7 @@ /** * 获取最新的方舱位置 * - * @return {@link List} + * @return {@link ShelterPosition} */ ShelterPosition selectLastOne(); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java index 55c8156..3a08fd0 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java @@ -11,6 +11,10 @@ public static final byte BITS_OF_END = (byte) 0x0A; public static final byte SHELTER_ID = (byte) 0xFF; + public static final int MAX_RADIUS = 80; + public static final int MAX_AGE = 240; + public static final int MIN_AGE = 1; + /** * 洋流相关常量 */ diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java index ed3cabe..c06ee68 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.utils; import com.alibaba.fastjson.JSON; +import com.casic.missiles.modular.system.dto.PointDTO; import com.casic.missiles.modular.system.model.RobotInfo; import com.casic.missiles.modular.system.model.ShelterPosition; +import lombok.extern.slf4j.Slf4j; import java.text.SimpleDateFormat; import java.util.*; @@ -12,6 +14,7 @@ * * @author a203 */ +@Slf4j public class DecodeData { /** * 水下机器人信息 @@ -79,15 +82,15 @@ } /** - * 区域覆盖 + * 区域覆盖-已校验 */ public static String decodeRobotRegion(byte[] bytes) { - Map regionMap = new HashMap<>(); - int count = bytes[4]; - regionMap.put("count", String.valueOf(count)); + Map regionMap = new HashMap<>(7); + int count = bytes[5]; + regionMap.put("count", count); byte[] idsBytes = new byte[count]; - System.arraycopy(bytes, 5, idsBytes, 0, count); + System.arraycopy(bytes, 5 + 1, idsBytes, 0, count); StringBuilder builder = new StringBuilder(); for (int i = 0; i < idsBytes.length; i++) { if (i != idsBytes.length - 1) { @@ -98,49 +101,70 @@ } regionMap.put("robotIds", builder.toString()); - //经度和纬度,所以需要*2 - int targetSize = count * 2 * 4; + //经度(4)、纬度(4) + int targetSize = count * (4 + 4); byte[] targetBytes = new byte[targetSize]; - //起始4个字节,机器人个数1个字节 - System.arraycopy(bytes, 5 + idsBytes.length, targetBytes, 0, targetSize); - regionMap.put("robotTargets", formatLanLat(targetBytes)); + //起始5个字节,机器人个数1个字节 + System.arraycopy(bytes, 5 + 1 + idsBytes.length, targetBytes, 0, targetSize); + regionMap.put("robotTargets", formatLngLat(targetBytes)); - regionMap.put("pointCount", String.valueOf(bytes[5 + idsBytes.length + targetBytes.length])); + regionMap.put("pointCount", bytes[5 + 1 + idsBytes.length + targetBytes.length]); byte[] radiusBytes = new byte[2]; - System.arraycopy(bytes, 5 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); + System.arraycopy(bytes, 5 + 1 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); regionMap.put("regionRadius", covertTargetDistance(radiusBytes)); - int aByte = bytes[5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; + int aByte = bytes[5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; if (aByte == 0) { regionMap.put("contour", "轮廓标志位:多边形," + count + "个轮廓点"); } else { regionMap.put("contour", "轮廓标志位:圆形," + count + "个轮廓点"); } - //经度和纬度,所以需要*2 - int pointSize = count * 2 * 4; + //经度(4)、纬度(4) + int pointSize = count * (4 + 4); byte[] pointBytes = new byte[pointSize]; System.arraycopy(bytes, - 5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, + 5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, pointBytes, 0, pointSize); - regionMap.put("robotPoints", formatLanLat(pointBytes)); + regionMap.put("robotPoints", formatLngLat(pointBytes)); return JSON.toJSONString(regionMap); } /** - * 路径规划 + * 路径规划-已校验 */ public static String decodeRobotRoute(byte[] bytes) { - Map routeMap = new HashMap<>(2); + Map routeMap = new HashMap<>(2); - int count = bytes[4]; - routeMap.put("routeCount", String.valueOf(count)); + byte[] countBytes = new byte[2]; + System.arraycopy(bytes, 5, countBytes, 0, 2); + int count = covertToDec(countBytes); + routeMap.put("routeCount", covertToDec(countBytes)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + int routeSize = count * (4 + 4 + 2 + 2 + 2); byte[] routeBytes = new byte[routeSize]; - System.arraycopy(bytes, 5, routeBytes, 0, routeSize); - routeMap.put("robotRoutes", formatLanLat(routeBytes)); + System.arraycopy(bytes, 5 + countBytes.length, routeBytes, 0, routeSize); + routeMap.put("robotRoutes", formatRoute(routeBytes)); + + byte[] sumTimeBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length, + sumTimeBytes, 0, 2); + routeMap.put("sumTime", covertToDec(sumTimeBytes)); + + byte[] sumDistanceBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length, + sumDistanceBytes, 0, 2); + routeMap.put("sumDistance", covertToDec(sumDistanceBytes)); + + byte[] sumPowerBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length + sumDistanceBytes.length, + sumPowerBytes, 0, 2); + routeMap.put("sumPower", covertToDec(sumPowerBytes)); return JSON.toJSONString(routeMap); } @@ -163,7 +187,7 @@ * 航路点任务 */ public static String decodeTaskRoute(byte[] bytes) { - Map taskMap = new HashMap<>(3); + Map taskMap = new HashMap<>(3); byte[] depthBytes = new byte[2]; System.arraycopy(bytes, 4, depthBytes, 0, 2); @@ -172,10 +196,11 @@ int count = bytes[6]; taskMap.put("routeCount", String.valueOf(count)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4) + int routeSize = count * (4 + 4); byte[] routeBytes = new byte[routeSize]; System.arraycopy(bytes, 7, routeBytes, 0, routeSize); - taskMap.put("robotRoutes", formatLanLat(routeBytes)); + taskMap.put("robotRoutes", formatLngLat(routeBytes)); return JSON.toJSONString(taskMap); } @@ -268,20 +293,37 @@ } /** - * AIS数据请求 + * 环境数据请求-已校验 + */ +// public static String decodeEnvRequest(byte[] bytes) { +// +// } + + /** + * AIS数据请求-已校验 */ public static String decodeAISRequest(byte[] bytes) { - Map taskMap = new HashMap<>(2); - byte[] depthBytes = new byte[2]; - System.arraycopy(bytes, 4, depthBytes, 0, 2); - taskMap.put("radius", covertToDec(depthBytes) + "km"); + Map aisMap = new HashMap<>(2); + byte[] radiusBytes = new byte[2]; + System.arraycopy(bytes, 5, radiusBytes, 0, 2); + aisMap.put("radius", covertToDec(radiusBytes)); - taskMap.put("shipCount", String.valueOf(bytes[6])); - return JSON.toJSONString(taskMap); + byte[] lngBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length, lngBytes, 0, 4); + aisMap.put("lng", covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length, latBytes, 0, 4); + aisMap.put("lat", covertLngLat(latBytes)); + + byte[] ageBytes = new byte[2]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length + latBytes.length, ageBytes, 0, 2); + aisMap.put("age", covertToDec(ageBytes)); + return JSON.toJSONString(aisMap); } /** - * 方舱位置 + * 方舱位置-已校验 * 编码encode * 解码decode */ @@ -301,32 +343,73 @@ return shelter; } - public static String formatLanLat(byte[] targetBytes) { + /** + * 生成经纬度对象点 + */ + public static List formatLngLat(byte[] targetBytes) { List lnglat = new ArrayList<>(); for (int i = 0; i < targetBytes.length; i += 4) { byte[] target = new byte[4]; System.arraycopy(targetBytes, i, target, 0, 4); - //每4个字节转换一次经纬度 lnglat.add(covertLngLat(target)); } - List> pointList = new ArrayList<>(); + List pointList = new ArrayList<>(); for (int i = 0; i < lnglat.size(); i += 2) { - Map lnglatMap = new HashMap<>(2); + PointDTO point = new PointDTO(); for (int j = 0; j < 2; j++) { - lnglatMap.put("lng", lnglat.get(i)); - lnglatMap.put("lat", lnglat.get(i + 1)); + point.setLng(lnglat.get(i)); + point.setLat(lnglat.get(i + 1)); } - //每2个元素作为一个对象 - pointList.add(lnglatMap); + pointList.add(point); } - return JSON.toJSONString(pointList); + return pointList; + } + + /** + * 生成路线对象点 + * 经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + */ + public static List formatRoute(byte[] routeBytes) { + List pointList = new ArrayList<>(); + for (int i = 0; i < routeBytes.length; i += 14) { + PointDTO point = new PointDTO(); + //每14个字节转换一次 + byte[] lngBytes = new byte[4]; + System.arraycopy(routeBytes, i, lngBytes, 0, 4); + point.setLng(covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(routeBytes, lngBytes.length, latBytes, 0, 4); + point.setLat(covertLngLat(latBytes)); + + byte[] depthBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length, + depthBytes, 0, 2); + point.setDepth(covertDepth(depthBytes)); + + byte[] pitchBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length, + pitchBytes, 0, 2); + point.setPitchAngle(covertPitchAngle(pitchBytes)); + + byte[] headingBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length + pitchBytes.length, + headingBytes, 0, 2); + point.setHeadingAngle(covertHeadingAngle(headingBytes)); + + pointList.add(point); + } + return pointList; } /** * 十进制转换算法 */ - private static double covertToDec(byte[] bytes) { + private static int covertToDec(byte[] bytes) { return ((bytes[0] & 0xFF) << 8) + (bytes[1] & 0xFF); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java index 0c21182..8b95501 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java @@ -59,7 +59,7 @@ dto.setAzimuth(angle); //洋流数据 - String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, "2021-10-22", "0", "10"); + String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, date, days, hour); OceanDetailDTO oceanDetailDTO = null; if ("0".equals(HttpRequestHelper.getOceanCode(oceanData))) { OceanDetailRemoteData remoteData = JSON.parseObject(oceanData, new TypeReference() { diff --git a/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java b/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java index 38f2903..71ad079 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java +++ b/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java @@ -1,10 +1,13 @@ package com.casic.missiles.socket.service.impl; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.casic.missiles.modular.system.dto.ShipDTO; import com.casic.missiles.modular.system.dto.TyphoonDTO; import com.casic.missiles.modular.system.model.RobotInfo; +import com.casic.missiles.modular.system.model.RoutePlan; import com.casic.missiles.modular.system.model.ShelterPosition; +import com.casic.missiles.modular.system.service.IRoutePlanService; import com.casic.missiles.modular.system.service.IShelterPositionService; import com.casic.missiles.modular.system.service.IShipService; import com.casic.missiles.modular.system.service.ITyphoonService; @@ -16,9 +19,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.text.SimpleDateFormat; +import java.util.*; /** * @author a203 @@ -27,16 +29,20 @@ @Service public class SocketServiceImpl implements ISocketService { + private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA); private final ITyphoonService typhoonService; private final IShipService shipService; private final IShelterPositionService shelterPositionService; + private final IRoutePlanService routePlanService; public SocketServiceImpl(ITyphoonService typhoonService, IShipService shipService, - IShelterPositionService shelterPositionService) { + IShelterPositionService shelterPositionService, + IRoutePlanService routePlanService) { this.typhoonService = typhoonService; this.shipService = shipService; this.shelterPositionService = shelterPositionService; + this.routePlanService = routePlanService; } private boolean isCorrectData(byte[] bytes) { @@ -81,10 +87,34 @@ case 0x01: //水下机器人信息 RobotInfo robotInfo = DecodeData.decodeRobotInfo(data); + log.info("robotInfo ===> " + JSON.toJSONString(robotInfo)); break; case 0x02: //算法结果 - + RoutePlan routePlan = new RoutePlan(); + routePlan.setPlanTime(dateFormat.format(new Date())); + routePlan.setRobotId(robotId); + int taskType = data[3]; + switch (taskType) { + case 0x01: + String robotRegion = DecodeData.decodeRobotRegion(data); + log.info("区域覆盖 ===> " + robotRegion); + //区域覆盖 + routePlan.setPlanType("0"); + routePlan.setRouteResult(robotRegion); + routePlanService.save(routePlan); + break; + case 0x02: + //路径规划 + String robotRoute = DecodeData.decodeRobotRoute(data); + log.info("路径规划 ===> " + robotRoute); + routePlan.setPlanType("1"); + routePlan.setRouteResult(robotRoute); + routePlanService.save(routePlan); + break; + default: + break; + } break; case 0x03: //任务数据还需要细分 @@ -110,29 +140,50 @@ break; case 0x05: //环境数据请求 +// String envRequest = DecodeData.decodeEnvRequest(data); + List typhoonList = typhoonService.currentTyphoonList(); /** * 如果有多个台风,只返回距离当前机器人或者方舱最近的台风信息 * */ + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); + String date = dateFormat.format(new Date()); + Map objectMap = EncodeData.encodeEnvironment( robotId, JSON.toJSONString(typhoonList), - "2021-10-22", "0", "10"); + date, "0", "10"); ctx.writeAndFlush(JSON.toJSONString(objectMap)); break; case 0x06: //AIS数据请求 - List ships = shipService.shipsInCircle("10448984,68042960,50", 30); + String aisRequest = DecodeData.decodeAISRequest(data); + log.info("aisRequest ===> " + aisRequest); + //{"radius":58,"lng":109.32222199129043,"lat":17.39223199775081,"age":12} + JSONObject jsonObject = JSON.parseObject(aisRequest); + + int radius = jsonObject.getInteger("radius"); + if (radius > Constant.MAX_RADIUS) { + radius = Constant.MAX_RADIUS; + } + double lat = jsonObject.getDouble("lat"); + double lng = jsonObject.getDouble("lng"); + int age = jsonObject.getInteger("age"); + if (age > Constant.MAX_AGE) { + age = Constant.MAX_AGE; + } + if (age < Constant.MIN_AGE) { + age = Constant.MIN_AGE; + } + String requestValue = lat * 600000 + "," + lng * 600000 + "," + radius; + + List ships = shipService.shipsInCircle(requestValue, age); Map map = EncodeData.encodeAIS(robotId, JSON.toJSONString(ships)); ctx.writeAndFlush(JSON.toJSONString(map)); break; case 0x07: //方舱位置 - ShelterPosition shelterPosition = DecodeData.decodeShelterPosition( - new byte[]{(byte) 0x2A, (byte) 0x23, (byte) 0x07, (byte) 0x00, (byte) 0x00, - (byte) 0x4D, (byte) 0xBD, (byte) 0x80, (byte) 0xCF, - (byte) 0x0C, (byte) 0x5E, (byte) 0x28, (byte) 0xC2, - (byte) 0xC7, (byte) 0x16, (byte) 0x0A} - ); + ShelterPosition shelterPosition = DecodeData.decodeShelterPosition(data); + log.info("shelterPosition ===> " + JSON.toJSONString(shelterPosition)); shelterPositionService.save(shelterPosition); break; default: diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java new file mode 100644 index 0000000..1288112 --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.missiles.modular.system.dto.RoutePlanDTO; +import com.casic.missiles.modular.system.model.RoutePlan; + +/** + * @author a203 + */ +public interface RoutePlanMapper extends BaseMapper { + /** + * 获取最新的规划结果 + * + * @return {@link RoutePlanDTO} + */ + RoutePlan selectLastOne(); +} diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dao/mapping/RoutePlanMapper.xml b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/mapping/RoutePlanMapper.xml new file mode 100644 index 0000000..e347d2f --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/mapping/RoutePlanMapper.xml @@ -0,0 +1,21 @@ + + + + + + + ID AS id, + ROBOT_ID AS robotId, + PLAN_TIME AS planTime, + PLAN_TYPE AS planType, + ROUTE_RESULT AS routeResult + + + + \ No newline at end of file diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dto/PointDTO.java b/casic-task/src/main/java/com/casic/missiles/modular/system/dto/PointDTO.java new file mode 100644 index 0000000..6a4e1e1 --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dto/PointDTO.java @@ -0,0 +1,24 @@ +package com.casic.missiles.modular.system.dto; + +import lombok.Data; + +/** + * @author a203 + */ +@Data +public class PointDTO { + private Double lng; + private Double lat; + /** + * 俯仰角: -40.43 + */ + private Float pitchAngle; + /** + * 航向角:124.66 + */ + private Float headingAngle; + /** + * 规划航路点深度 + */ + private Double depth; +} diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dto/RoutePlanDTO.java b/casic-task/src/main/java/com/casic/missiles/modular/system/dto/RoutePlanDTO.java new file mode 100644 index 0000000..93c432f --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dto/RoutePlanDTO.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.dto; + +import com.casic.missiles.modular.system.model.RoutePlan; +import lombok.Data; + +/** + * @author a203 + */ +@Data +public class RoutePlanDTO { + /** + * 路线规划ID,数据库主键自动生成 + */ + private Long routeId; + /** + * 机器人ID + */ + private Integer robotId; + /** + * 路线规划生成的时间 + */ + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + private String planType; + /** + * 规划结果 + */ + private String routeResult; + + public RoutePlanDTO(RoutePlan routePlan) { + this.routeId = routePlan.getId(); + this.planTime = routePlan.getPlanTime(); + this.planType = routePlan.getPlanType(); + this.routeResult = routePlan.getRouteResult(); + } +} diff --git a/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java new file mode 100644 index 0000000..079e1d5 --- /dev/null +++ b/casic-server-support/src/main/java/com/casic/missiles/modular/system/model/RoutePlan.java @@ -0,0 +1,43 @@ +package com.casic.missiles.modular.system.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import lombok.Data; + +/** + * @author a203 + */ +@Data +@TableName("bus_task_route") +public class RoutePlan extends Model { + private static final long serialVersionUID = 1L; + + /** + * 数据库主键 + */ + @TableId(value = "ID", type = IdType.ASSIGN_ID) + private Long id; + /** + * 机器人ID + */ + @TableField("ROBOT_ID") + private Integer robotId; + /** + * 路线规划生成的时间 + */ + @TableField("PLAN_TIME") + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + @TableField("PLAN_TYPE") + private String planType; + /** + * 规划结果 + */ + @TableField("ROUTE_RESULT") + private String routeResult; +} diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java index 83cba30..5bf8bcc 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/dao/ShelterPositionMapper.java @@ -3,8 +3,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.modular.system.model.ShelterPosition; -import java.util.List; - /** * @author a203 */ @@ -12,7 +10,7 @@ /** * 获取最新的方舱位置 * - * @return {@link List} + * @return {@link ShelterPosition} */ ShelterPosition selectLastOne(); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java index 55c8156..3a08fd0 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/Constant.java @@ -11,6 +11,10 @@ public static final byte BITS_OF_END = (byte) 0x0A; public static final byte SHELTER_ID = (byte) 0xFF; + public static final int MAX_RADIUS = 80; + public static final int MAX_AGE = 240; + public static final int MIN_AGE = 1; + /** * 洋流相关常量 */ diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java index ed3cabe..c06ee68 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/DecodeData.java @@ -1,8 +1,10 @@ package com.casic.missiles.modular.system.utils; import com.alibaba.fastjson.JSON; +import com.casic.missiles.modular.system.dto.PointDTO; import com.casic.missiles.modular.system.model.RobotInfo; import com.casic.missiles.modular.system.model.ShelterPosition; +import lombok.extern.slf4j.Slf4j; import java.text.SimpleDateFormat; import java.util.*; @@ -12,6 +14,7 @@ * * @author a203 */ +@Slf4j public class DecodeData { /** * 水下机器人信息 @@ -79,15 +82,15 @@ } /** - * 区域覆盖 + * 区域覆盖-已校验 */ public static String decodeRobotRegion(byte[] bytes) { - Map regionMap = new HashMap<>(); - int count = bytes[4]; - regionMap.put("count", String.valueOf(count)); + Map regionMap = new HashMap<>(7); + int count = bytes[5]; + regionMap.put("count", count); byte[] idsBytes = new byte[count]; - System.arraycopy(bytes, 5, idsBytes, 0, count); + System.arraycopy(bytes, 5 + 1, idsBytes, 0, count); StringBuilder builder = new StringBuilder(); for (int i = 0; i < idsBytes.length; i++) { if (i != idsBytes.length - 1) { @@ -98,49 +101,70 @@ } regionMap.put("robotIds", builder.toString()); - //经度和纬度,所以需要*2 - int targetSize = count * 2 * 4; + //经度(4)、纬度(4) + int targetSize = count * (4 + 4); byte[] targetBytes = new byte[targetSize]; - //起始4个字节,机器人个数1个字节 - System.arraycopy(bytes, 5 + idsBytes.length, targetBytes, 0, targetSize); - regionMap.put("robotTargets", formatLanLat(targetBytes)); + //起始5个字节,机器人个数1个字节 + System.arraycopy(bytes, 5 + 1 + idsBytes.length, targetBytes, 0, targetSize); + regionMap.put("robotTargets", formatLngLat(targetBytes)); - regionMap.put("pointCount", String.valueOf(bytes[5 + idsBytes.length + targetBytes.length])); + regionMap.put("pointCount", bytes[5 + 1 + idsBytes.length + targetBytes.length]); byte[] radiusBytes = new byte[2]; - System.arraycopy(bytes, 5 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); + System.arraycopy(bytes, 5 + 1 + idsBytes.length + targetBytes.length + 1, radiusBytes, 0, 2); regionMap.put("regionRadius", covertTargetDistance(radiusBytes)); - int aByte = bytes[5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; + int aByte = bytes[5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length]; if (aByte == 0) { regionMap.put("contour", "轮廓标志位:多边形," + count + "个轮廓点"); } else { regionMap.put("contour", "轮廓标志位:圆形," + count + "个轮廓点"); } - //经度和纬度,所以需要*2 - int pointSize = count * 2 * 4; + //经度(4)、纬度(4) + int pointSize = count * (4 + 4); byte[] pointBytes = new byte[pointSize]; System.arraycopy(bytes, - 5 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, + 5 + 1 + idsBytes.length + targetBytes.length + 1 + radiusBytes.length + 1, pointBytes, 0, pointSize); - regionMap.put("robotPoints", formatLanLat(pointBytes)); + regionMap.put("robotPoints", formatLngLat(pointBytes)); return JSON.toJSONString(regionMap); } /** - * 路径规划 + * 路径规划-已校验 */ public static String decodeRobotRoute(byte[] bytes) { - Map routeMap = new HashMap<>(2); + Map routeMap = new HashMap<>(2); - int count = bytes[4]; - routeMap.put("routeCount", String.valueOf(count)); + byte[] countBytes = new byte[2]; + System.arraycopy(bytes, 5, countBytes, 0, 2); + int count = covertToDec(countBytes); + routeMap.put("routeCount", covertToDec(countBytes)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + int routeSize = count * (4 + 4 + 2 + 2 + 2); byte[] routeBytes = new byte[routeSize]; - System.arraycopy(bytes, 5, routeBytes, 0, routeSize); - routeMap.put("robotRoutes", formatLanLat(routeBytes)); + System.arraycopy(bytes, 5 + countBytes.length, routeBytes, 0, routeSize); + routeMap.put("robotRoutes", formatRoute(routeBytes)); + + byte[] sumTimeBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length, + sumTimeBytes, 0, 2); + routeMap.put("sumTime", covertToDec(sumTimeBytes)); + + byte[] sumDistanceBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length, + sumDistanceBytes, 0, 2); + routeMap.put("sumDistance", covertToDec(sumDistanceBytes)); + + byte[] sumPowerBytes = new byte[2]; + System.arraycopy(bytes, + 5 + countBytes.length + routeBytes.length + sumTimeBytes.length + sumDistanceBytes.length, + sumPowerBytes, 0, 2); + routeMap.put("sumPower", covertToDec(sumPowerBytes)); return JSON.toJSONString(routeMap); } @@ -163,7 +187,7 @@ * 航路点任务 */ public static String decodeTaskRoute(byte[] bytes) { - Map taskMap = new HashMap<>(3); + Map taskMap = new HashMap<>(3); byte[] depthBytes = new byte[2]; System.arraycopy(bytes, 4, depthBytes, 0, 2); @@ -172,10 +196,11 @@ int count = bytes[6]; taskMap.put("routeCount", String.valueOf(count)); - int routeSize = count * 2 * 4; + //经度(4)、纬度(4) + int routeSize = count * (4 + 4); byte[] routeBytes = new byte[routeSize]; System.arraycopy(bytes, 7, routeBytes, 0, routeSize); - taskMap.put("robotRoutes", formatLanLat(routeBytes)); + taskMap.put("robotRoutes", formatLngLat(routeBytes)); return JSON.toJSONString(taskMap); } @@ -268,20 +293,37 @@ } /** - * AIS数据请求 + * 环境数据请求-已校验 + */ +// public static String decodeEnvRequest(byte[] bytes) { +// +// } + + /** + * AIS数据请求-已校验 */ public static String decodeAISRequest(byte[] bytes) { - Map taskMap = new HashMap<>(2); - byte[] depthBytes = new byte[2]; - System.arraycopy(bytes, 4, depthBytes, 0, 2); - taskMap.put("radius", covertToDec(depthBytes) + "km"); + Map aisMap = new HashMap<>(2); + byte[] radiusBytes = new byte[2]; + System.arraycopy(bytes, 5, radiusBytes, 0, 2); + aisMap.put("radius", covertToDec(radiusBytes)); - taskMap.put("shipCount", String.valueOf(bytes[6])); - return JSON.toJSONString(taskMap); + byte[] lngBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length, lngBytes, 0, 4); + aisMap.put("lng", covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length, latBytes, 0, 4); + aisMap.put("lat", covertLngLat(latBytes)); + + byte[] ageBytes = new byte[2]; + System.arraycopy(bytes, 5 + radiusBytes.length + lngBytes.length + latBytes.length, ageBytes, 0, 2); + aisMap.put("age", covertToDec(ageBytes)); + return JSON.toJSONString(aisMap); } /** - * 方舱位置 + * 方舱位置-已校验 * 编码encode * 解码decode */ @@ -301,32 +343,73 @@ return shelter; } - public static String formatLanLat(byte[] targetBytes) { + /** + * 生成经纬度对象点 + */ + public static List formatLngLat(byte[] targetBytes) { List lnglat = new ArrayList<>(); for (int i = 0; i < targetBytes.length; i += 4) { byte[] target = new byte[4]; System.arraycopy(targetBytes, i, target, 0, 4); - //每4个字节转换一次经纬度 lnglat.add(covertLngLat(target)); } - List> pointList = new ArrayList<>(); + List pointList = new ArrayList<>(); for (int i = 0; i < lnglat.size(); i += 2) { - Map lnglatMap = new HashMap<>(2); + PointDTO point = new PointDTO(); for (int j = 0; j < 2; j++) { - lnglatMap.put("lng", lnglat.get(i)); - lnglatMap.put("lat", lnglat.get(i + 1)); + point.setLng(lnglat.get(i)); + point.setLat(lnglat.get(i + 1)); } - //每2个元素作为一个对象 - pointList.add(lnglatMap); + pointList.add(point); } - return JSON.toJSONString(pointList); + return pointList; + } + + /** + * 生成路线对象点 + * 经度(4)、纬度(4)、深度(2)、俯仰角(2)、航向角(2) + */ + public static List formatRoute(byte[] routeBytes) { + List pointList = new ArrayList<>(); + for (int i = 0; i < routeBytes.length; i += 14) { + PointDTO point = new PointDTO(); + //每14个字节转换一次 + byte[] lngBytes = new byte[4]; + System.arraycopy(routeBytes, i, lngBytes, 0, 4); + point.setLng(covertLngLat(lngBytes)); + + byte[] latBytes = new byte[4]; + System.arraycopy(routeBytes, lngBytes.length, latBytes, 0, 4); + point.setLat(covertLngLat(latBytes)); + + byte[] depthBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length, + depthBytes, 0, 2); + point.setDepth(covertDepth(depthBytes)); + + byte[] pitchBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length, + pitchBytes, 0, 2); + point.setPitchAngle(covertPitchAngle(pitchBytes)); + + byte[] headingBytes = new byte[2]; + System.arraycopy(routeBytes, + lngBytes.length + latBytes.length + depthBytes.length + pitchBytes.length, + headingBytes, 0, 2); + point.setHeadingAngle(covertHeadingAngle(headingBytes)); + + pointList.add(point); + } + return pointList; } /** * 十进制转换算法 */ - private static double covertToDec(byte[] bytes) { + private static int covertToDec(byte[] bytes) { return ((bytes[0] & 0xFF) << 8) + (bytes[1] & 0xFF); } diff --git a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java index 0c21182..8b95501 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java +++ b/casic-shelter/src/main/java/com/casic/missiles/modular/system/utils/EncodeData.java @@ -59,7 +59,7 @@ dto.setAzimuth(angle); //洋流数据 - String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, "2021-10-22", "0", "10"); + String oceanData = HttpRequestHelper.obtainOceanData(115.6314213, 12.9691386, date, days, hour); OceanDetailDTO oceanDetailDTO = null; if ("0".equals(HttpRequestHelper.getOceanCode(oceanData))) { OceanDetailRemoteData remoteData = JSON.parseObject(oceanData, new TypeReference() { diff --git a/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java b/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java index 38f2903..71ad079 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java +++ b/casic-shelter/src/main/java/com/casic/missiles/socket/service/impl/SocketServiceImpl.java @@ -1,10 +1,13 @@ package com.casic.missiles.socket.service.impl; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.casic.missiles.modular.system.dto.ShipDTO; import com.casic.missiles.modular.system.dto.TyphoonDTO; import com.casic.missiles.modular.system.model.RobotInfo; +import com.casic.missiles.modular.system.model.RoutePlan; import com.casic.missiles.modular.system.model.ShelterPosition; +import com.casic.missiles.modular.system.service.IRoutePlanService; import com.casic.missiles.modular.system.service.IShelterPositionService; import com.casic.missiles.modular.system.service.IShipService; import com.casic.missiles.modular.system.service.ITyphoonService; @@ -16,9 +19,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.text.SimpleDateFormat; +import java.util.*; /** * @author a203 @@ -27,16 +29,20 @@ @Service public class SocketServiceImpl implements ISocketService { + private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA); private final ITyphoonService typhoonService; private final IShipService shipService; private final IShelterPositionService shelterPositionService; + private final IRoutePlanService routePlanService; public SocketServiceImpl(ITyphoonService typhoonService, IShipService shipService, - IShelterPositionService shelterPositionService) { + IShelterPositionService shelterPositionService, + IRoutePlanService routePlanService) { this.typhoonService = typhoonService; this.shipService = shipService; this.shelterPositionService = shelterPositionService; + this.routePlanService = routePlanService; } private boolean isCorrectData(byte[] bytes) { @@ -81,10 +87,34 @@ case 0x01: //水下机器人信息 RobotInfo robotInfo = DecodeData.decodeRobotInfo(data); + log.info("robotInfo ===> " + JSON.toJSONString(robotInfo)); break; case 0x02: //算法结果 - + RoutePlan routePlan = new RoutePlan(); + routePlan.setPlanTime(dateFormat.format(new Date())); + routePlan.setRobotId(robotId); + int taskType = data[3]; + switch (taskType) { + case 0x01: + String robotRegion = DecodeData.decodeRobotRegion(data); + log.info("区域覆盖 ===> " + robotRegion); + //区域覆盖 + routePlan.setPlanType("0"); + routePlan.setRouteResult(robotRegion); + routePlanService.save(routePlan); + break; + case 0x02: + //路径规划 + String robotRoute = DecodeData.decodeRobotRoute(data); + log.info("路径规划 ===> " + robotRoute); + routePlan.setPlanType("1"); + routePlan.setRouteResult(robotRoute); + routePlanService.save(routePlan); + break; + default: + break; + } break; case 0x03: //任务数据还需要细分 @@ -110,29 +140,50 @@ break; case 0x05: //环境数据请求 +// String envRequest = DecodeData.decodeEnvRequest(data); + List typhoonList = typhoonService.currentTyphoonList(); /** * 如果有多个台风,只返回距离当前机器人或者方舱最近的台风信息 * */ + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); + String date = dateFormat.format(new Date()); + Map objectMap = EncodeData.encodeEnvironment( robotId, JSON.toJSONString(typhoonList), - "2021-10-22", "0", "10"); + date, "0", "10"); ctx.writeAndFlush(JSON.toJSONString(objectMap)); break; case 0x06: //AIS数据请求 - List ships = shipService.shipsInCircle("10448984,68042960,50", 30); + String aisRequest = DecodeData.decodeAISRequest(data); + log.info("aisRequest ===> " + aisRequest); + //{"radius":58,"lng":109.32222199129043,"lat":17.39223199775081,"age":12} + JSONObject jsonObject = JSON.parseObject(aisRequest); + + int radius = jsonObject.getInteger("radius"); + if (radius > Constant.MAX_RADIUS) { + radius = Constant.MAX_RADIUS; + } + double lat = jsonObject.getDouble("lat"); + double lng = jsonObject.getDouble("lng"); + int age = jsonObject.getInteger("age"); + if (age > Constant.MAX_AGE) { + age = Constant.MAX_AGE; + } + if (age < Constant.MIN_AGE) { + age = Constant.MIN_AGE; + } + String requestValue = lat * 600000 + "," + lng * 600000 + "," + radius; + + List ships = shipService.shipsInCircle(requestValue, age); Map map = EncodeData.encodeAIS(robotId, JSON.toJSONString(ships)); ctx.writeAndFlush(JSON.toJSONString(map)); break; case 0x07: //方舱位置 - ShelterPosition shelterPosition = DecodeData.decodeShelterPosition( - new byte[]{(byte) 0x2A, (byte) 0x23, (byte) 0x07, (byte) 0x00, (byte) 0x00, - (byte) 0x4D, (byte) 0xBD, (byte) 0x80, (byte) 0xCF, - (byte) 0x0C, (byte) 0x5E, (byte) 0x28, (byte) 0xC2, - (byte) 0xC7, (byte) 0x16, (byte) 0x0A} - ); + ShelterPosition shelterPosition = DecodeData.decodeShelterPosition(data); + log.info("shelterPosition ===> " + JSON.toJSONString(shelterPosition)); shelterPositionService.save(shelterPosition); break; default: diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java new file mode 100644 index 0000000..1288112 --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/RoutePlanMapper.java @@ -0,0 +1,17 @@ +package com.casic.missiles.modular.system.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.casic.missiles.modular.system.dto.RoutePlanDTO; +import com.casic.missiles.modular.system.model.RoutePlan; + +/** + * @author a203 + */ +public interface RoutePlanMapper extends BaseMapper { + /** + * 获取最新的规划结果 + * + * @return {@link RoutePlanDTO} + */ + RoutePlan selectLastOne(); +} diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dao/mapping/RoutePlanMapper.xml b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/mapping/RoutePlanMapper.xml new file mode 100644 index 0000000..e347d2f --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dao/mapping/RoutePlanMapper.xml @@ -0,0 +1,21 @@ + + + + + + + ID AS id, + ROBOT_ID AS robotId, + PLAN_TIME AS planTime, + PLAN_TYPE AS planType, + ROUTE_RESULT AS routeResult + + + + \ No newline at end of file diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dto/PointDTO.java b/casic-task/src/main/java/com/casic/missiles/modular/system/dto/PointDTO.java new file mode 100644 index 0000000..6a4e1e1 --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dto/PointDTO.java @@ -0,0 +1,24 @@ +package com.casic.missiles.modular.system.dto; + +import lombok.Data; + +/** + * @author a203 + */ +@Data +public class PointDTO { + private Double lng; + private Double lat; + /** + * 俯仰角: -40.43 + */ + private Float pitchAngle; + /** + * 航向角:124.66 + */ + private Float headingAngle; + /** + * 规划航路点深度 + */ + private Double depth; +} diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/dto/RoutePlanDTO.java b/casic-task/src/main/java/com/casic/missiles/modular/system/dto/RoutePlanDTO.java new file mode 100644 index 0000000..93c432f --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/dto/RoutePlanDTO.java @@ -0,0 +1,38 @@ +package com.casic.missiles.modular.system.dto; + +import com.casic.missiles.modular.system.model.RoutePlan; +import lombok.Data; + +/** + * @author a203 + */ +@Data +public class RoutePlanDTO { + /** + * 路线规划ID,数据库主键自动生成 + */ + private Long routeId; + /** + * 机器人ID + */ + private Integer robotId; + /** + * 路线规划生成的时间 + */ + private String planTime; + /** + * 路线规划的类型-区域覆盖0/路径规划1 + */ + private String planType; + /** + * 规划结果 + */ + private String routeResult; + + public RoutePlanDTO(RoutePlan routePlan) { + this.routeId = routePlan.getId(); + this.planTime = routePlan.getPlanTime(); + this.planType = routePlan.getPlanType(); + this.routeResult = routePlan.getRouteResult(); + } +} diff --git a/casic-task/src/main/java/com/casic/missiles/modular/system/service/impl/RoutePlanServiceImpl.java b/casic-task/src/main/java/com/casic/missiles/modular/system/service/impl/RoutePlanServiceImpl.java new file mode 100644 index 0000000..82231cc --- /dev/null +++ b/casic-task/src/main/java/com/casic/missiles/modular/system/service/impl/RoutePlanServiceImpl.java @@ -0,0 +1,28 @@ +package com.casic.missiles.modular.system.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.casic.missiles.modular.system.dao.RoutePlanMapper; +import com.casic.missiles.modular.system.dto.RoutePlanDTO; +import com.casic.missiles.modular.system.model.RoutePlan; +import com.casic.missiles.modular.system.service.IRoutePlanService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author a203 + */ +@Service +public class RoutePlanServiceImpl extends ServiceImpl implements IRoutePlanService { + + @Override + public RoutePlanDTO selectCurrentPlan() { + RoutePlan plan = this.baseMapper.selectLastOne(); + return new RoutePlanDTO(plan); + } + + @Override + public List selectRoutes(String startDate, String endDate) { + return null; + } +}