diff --git a/casic-shelter/src/main/java/com/casic/missiles/socket/BootNettyServer.java b/casic-shelter/src/main/java/com/casic/missiles/socket/BootNettyServer.java index 5da2f4e..103eea3 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/socket/BootNettyServer.java +++ b/casic-shelter/src/main/java/com/casic/missiles/socket/BootNettyServer.java @@ -50,15 +50,15 @@ .option(ChannelOption.SO_BACKLOG, 1024) //长连接 .childOption(ChannelOption.SO_KEEPALIVE, true) - //缓冲大小,initial要介于minimum和maximum之间 - .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(512, 1024, 2048)) + //缓冲大小 + .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator()) /** * 设置 I/O处理类,主要用于网络I/O事件,记录日志,编码、解码消息 */ .childHandler(new ChannelInitializer() { @Override - protected void initChannel(SocketChannel socketChannel) throws Exception { + protected void initChannel(SocketChannel socketChannel) { ChannelPipeline pipeline = socketChannel.pipeline(); //接收消息格式-byte[] pipeline.addLast("decoder", new ByteArrayDecoder()); diff --git a/casic-shelter/src/main/java/com/casic/missiles/socket/BootNettyServer.java b/casic-shelter/src/main/java/com/casic/missiles/socket/BootNettyServer.java index 5da2f4e..103eea3 100644 --- a/casic-shelter/src/main/java/com/casic/missiles/socket/BootNettyServer.java +++ b/casic-shelter/src/main/java/com/casic/missiles/socket/BootNettyServer.java @@ -50,15 +50,15 @@ .option(ChannelOption.SO_BACKLOG, 1024) //长连接 .childOption(ChannelOption.SO_KEEPALIVE, true) - //缓冲大小,initial要介于minimum和maximum之间 - .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(512, 1024, 2048)) + //缓冲大小 + .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator()) /** * 设置 I/O处理类,主要用于网络I/O事件,记录日志,编码、解码消息 */ .childHandler(new ChannelInitializer() { @Override - protected void initChannel(SocketChannel socketChannel) throws Exception { + protected void initChannel(SocketChannel socketChannel) { ChannelPipeline pipeline = socketChannel.pipeline(); //接收消息格式-byte[] pipeline.addLast("decoder", new ByteArrayDecoder()); 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 a0c8b95..27e5684 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 @@ -83,6 +83,8 @@ private NRSerialPort serialPort; private ChannelHandlerContext channelHandler; + private LinkedList temp = new LinkedList<>(); + private boolean isComplete = false; public SocketServiceImpl(IRobotService robotService, ITyphoonService typhoonService, IOceanService oceanService, IShipService shipService, @@ -248,217 +250,242 @@ byte[] data = (byte[]) msg; log.info("channelRead message ===> " + Arrays.toString(data)); - /** - * 回应客户端 - * */ if (ByteUtils.isCorrectData(data)) { - int dataType = data[2]; - int robotId = ByteUtils.decodeRobotId(data); /** - * 先解析再回应 + * 有头有尾的数据,直接处理 * */ - switch (dataType) { - case 0x01: - RobotInfo robotInfo = DecodeData.decodeRobotInfo(data); - saveDataLog(0, String.valueOf(robotId), robotInfo, "0"); - robotService.save(robotInfo); - break; - case 0x02: - //算法结果 - int planType = data[3]; - switch (planType) { - case 0x01: - String robotRegion = DecodeData.decodeRobotRegion(data); - saveDataLog(0, String.valueOf(robotId), robotRegion, "0"); - RegionPlan regionPlan = new RegionPlan(); - regionPlan.setPlanTime(TimeUtil.getCurrentTime()); - regionPlan.setRegionResult(robotRegion); - regionPlanService.save(regionPlan); - break; - case 0x02: - String robotRoute = DecodeData.decodeRobotRoute(data); - saveDataLog(0, String.valueOf(robotId), robotRoute, "0"); - RoutePlan routePlan = new RoutePlan(); - routePlan.setRobotId(robotId); - routePlan.setPlanTime(TimeUtil.getCurrentTime()); - routePlan.setRouteResult(robotRoute); - routePlanService.save(routePlan); - break; - default: - break; - } - break; - case 0x03: - //任务数据还需要细分 - int taskType = data[3]; - Task task = new Task(); - task.setRobotId(robotId); - task.setCreateTime(TimeUtil.getCurrentTime()); - switch (taskType) { - case 0x01: - String directedTask = DecodeData.decodeDirectedTask(data); - saveDataLog(0, String.valueOf(robotId), directedTask, "0"); - task.setTaskType("1"); - task.setTaskData(directedTask); - taskService.save(task); - break; - case 0x02: - String routeTask = DecodeData.decodeTaskRoute(data); - saveDataLog(0, String.valueOf(robotId), routeTask, "0"); - task.setTaskType("2"); - task.setTaskData(routeTask); - taskService.save(task); - break; - case 0x03: - String flightTask = DecodeData.decodeDirectFlightTask(data); - saveDataLog(0, String.valueOf(robotId), flightTask, "0"); - task.setTaskType("3"); - task.setTaskData(flightTask); - taskService.save(task); - break; - case 0x04: - String resideTask = DecodeData.decodeResideTask(data); - saveDataLog(0, String.valueOf(robotId), resideTask, "0"); - task.setTaskType("4"); - task.setTaskData(resideTask); - taskService.save(task); - break; - case 0x05: - String putTask = DecodeData.decodePutTask(data); - saveDataLog(0, String.valueOf(robotId), putTask, "0"); - task.setTaskType("5"); - task.setTaskData(putTask); - taskService.save(task); - break; - case 0x0F: - saveDataLog(0, String.valueOf(robotId), "任务终止", "0"); - taskService.updateTaskById(robotId); - break; - default: - break; - } - break; - case 0x04: - /** - * 短信内容 - * - * 方舱通过Socket发送短信给203后台,然后203后台将短信内容加密之后用卫星发送给203自己的岸基软件,然后解密之后再传给西工大岸基软件 - * */ - String sms = DecodeData.decodeSMS(data); - saveDataLog(0, String.valueOf(robotId), sms, "0"); - - byte[] bytes; - if (sms.startsWith("*") || sms.startsWith("?")) { - /** - * 查看配置等直接通信即可 - * */ - bytes = sms.getBytes(StandardCharsets.UTF_8); - } else { - /** - * 数据加密之后再与卫星通信 - * */ - if (isClient) { - bytes = CommandManager.createClientMessageCmd(sms); - } else { - bytes = CommandManager.createServerMessageCmd( - sms, serverAccount, serverPassword, clientAccount - ); - } - } - if (serialPort != null && serialPort.isConnected()) { - SerialPortManager.sendToPort(serialPort, bytes); - saveDataLog(3, String.valueOf(robotId), sms, "0"); - } - break; - case 0x05: - String envRequest = DecodeData.decodeEnvRequest(data); - saveDataLog(0, String.valueOf(robotId), envRequest, "0"); - //{"hour":"12","lng":109.32222199129043,"lat":17.39223199775081} - JSONObject envJsonObject = JSON.parseObject(envRequest); - - String hour = envJsonObject.getString("hour"); - double envLng = envJsonObject.getDouble("lng"); - double envLat = envJsonObject.getDouble("lat"); - - List typhoonList = typhoonService.currentTyphoonList(); - - String date = TimeUtil.getCurrentTime(); - OceanDetailDTO oceanDetail = oceanService.oceanDetail(envLng, envLat, date, "0", hour); - - Map objectMap; - if (typhoonList.isEmpty()) { - objectMap = EncodeData.encodeEnvironment(envLng, envLat, null, oceanDetail); - } else if (typhoonList.size() == 1) { - TyphoonDetailDTO detailDTO = typhoonService.typhoonDetail(typhoonList.get(0).getTyphoonId()); - objectMap = EncodeData.encodeEnvironment(envLng, envLat, detailDTO, oceanDetail); - } else { - /** - * 如果有多个台风,只返回距离当前机器人或者方舱最近的台风信息 - * */ - //记录每个台风和当前机器人之间的距离 - List disLinkedList = new LinkedList<>(); - for (TyphoonDTO dto : typhoonList) { - double distance = EncodeData.distance(dto.getLng(), dto.getLat(), envLng, envLat); - disLinkedList.add(distance); - } - //找出LinkedList中的最小值所在的位置 - double min = disLinkedList.get(0); - int pos = 0; - for (int i = 0; i < disLinkedList.size(); i++) { - if (disLinkedList.get(i) < min) { - min = disLinkedList.get(i); - pos = i; - } - } - - TyphoonDetailDTO detailDTO = typhoonService.typhoonDetail(typhoonList.get(pos).getTyphoonId()); - objectMap = EncodeData.encodeEnvironment(envLng, envLat, detailDTO, oceanDetail); - } - ctx.writeAndFlush(JSON.toJSONString(objectMap)); - saveDataLog(1, String.valueOf(robotId), objectMap, "0"); - break; - case 0x06: - String aisRequest = DecodeData.decodeAISRequest(data); - saveDataLog(0, String.valueOf(robotId), aisRequest, "0"); - //{"radius":50,"lng":109.32219994688509,"lat":17.392199978880676,"age":30} - JSONObject aisJsonObject = JSON.parseObject(aisRequest); - - int radius = aisJsonObject.getInteger("radius"); - if (radius > Constant.MAX_RADIUS) { - radius = Constant.MAX_RADIUS; - } - double aisLat = aisJsonObject.getDouble("lat"); - double aisLng = aisJsonObject.getDouble("lng"); - int age = aisJsonObject.getInteger("age"); - if (age > Constant.MAX_AGE) { - age = Constant.MAX_AGE; - } - if (age < Constant.MIN_AGE) { - age = Constant.MIN_AGE; - } - - //AIS不能有小数 - DecimalFormat df = new DecimalFormat("#"); - String requestValue = - df.format(aisLat * 600000) + "," + - df.format(aisLng * 600000) + "," + - radius; - - List ships = shipService.shipsInCircle(requestValue, age); - Map map = EncodeData.encodeAIS(aisLng, aisLat, ships); - ctx.writeAndFlush(JSON.toJSONString(map)); - saveDataLog(1, String.valueOf(robotId), map, "0"); - break; - case 0x07: - ShelterPosition shelterPosition = DecodeData.decodeShelterPosition(data); - saveDataLog(0, String.valueOf(robotId), shelterPosition, "0"); - shelterPositionService.save(shelterPosition); - break; - default: - break; - } + handleData(ctx, data); } else { - saveDataLog(0, "", "数据格式不对,无法解析", "1"); + /** + * 有头无尾,有尾无头,或者头尾都无的数据,先按照顺序放到链表,再处理 + * */ + temp.add(data); + if (data[data.length - 1] == Constant.BITS_OF_END) { + isComplete = true; + } + //计算实际长度 + if (isComplete) { + int realLen = 0; + for (byte[] bytes : temp) { + realLen += bytes.length; + } + byte[] tempArray = new byte[realLen]; + System.arraycopy(temp.get(0), 0, tempArray, 0, temp.get(0).length); + System.arraycopy(temp.get(1), 0, tempArray, temp.get(0).length, temp.get(1).length); + handleData(ctx, tempArray); + } + } + } + + private void handleData(ChannelHandlerContext ctx, byte[] data) { + int dataType = data[2]; + int robotId = ByteUtils.decodeRobotId(data); + /** + * 先解析再回应 + * */ + switch (dataType) { + case 0x01: + RobotInfo robotInfo = DecodeData.decodeRobotInfo(data); + saveDataLog(0, String.valueOf(robotId), robotInfo, "0"); + robotService.save(robotInfo); + break; + case 0x02: + //算法结果 + int planType = data[3]; + switch (planType) { + case 0x01: + String robotRegion = DecodeData.decodeRobotRegion(data); + saveDataLog(0, String.valueOf(robotId), robotRegion, "0"); + RegionPlan regionPlan = new RegionPlan(); + regionPlan.setPlanTime(TimeUtil.getCurrentTime()); + regionPlan.setRegionResult(robotRegion); + regionPlanService.save(regionPlan); + break; + case 0x02: + String robotRoute = DecodeData.decodeRobotRoute(data); + saveDataLog(0, String.valueOf(robotId), robotRoute, "0"); + RoutePlan routePlan = new RoutePlan(); + routePlan.setRobotId(robotId); + routePlan.setPlanTime(TimeUtil.getCurrentTime()); + routePlan.setRouteResult(robotRoute); + routePlanService.save(routePlan); + break; + default: + break; + } + break; + case 0x03: + //任务数据还需要细分 + int taskType = data[3]; + Task task = new Task(); + task.setRobotId(robotId); + task.setCreateTime(TimeUtil.getCurrentTime()); + switch (taskType) { + case 0x01: + String directedTask = DecodeData.decodeDirectedTask(data); + saveDataLog(0, String.valueOf(robotId), directedTask, "0"); + task.setTaskType("1"); + task.setTaskData(directedTask); + taskService.save(task); + break; + case 0x02: + String routeTask = DecodeData.decodeTaskRoute(data); + saveDataLog(0, String.valueOf(robotId), routeTask, "0"); + task.setTaskType("2"); + task.setTaskData(routeTask); + taskService.save(task); + break; + case 0x03: + String flightTask = DecodeData.decodeDirectFlightTask(data); + saveDataLog(0, String.valueOf(robotId), flightTask, "0"); + task.setTaskType("3"); + task.setTaskData(flightTask); + taskService.save(task); + break; + case 0x04: + String resideTask = DecodeData.decodeResideTask(data); + saveDataLog(0, String.valueOf(robotId), resideTask, "0"); + task.setTaskType("4"); + task.setTaskData(resideTask); + taskService.save(task); + break; + case 0x05: + String putTask = DecodeData.decodePutTask(data); + saveDataLog(0, String.valueOf(robotId), putTask, "0"); + task.setTaskType("5"); + task.setTaskData(putTask); + taskService.save(task); + break; + case 0x0F: + saveDataLog(0, String.valueOf(robotId), "任务终止", "0"); + taskService.updateTaskById(robotId); + break; + default: + break; + } + break; + case 0x04: + /** + * 短信内容 + * + * 方舱通过Socket发送短信给203后台,然后203后台将短信内容加密之后用卫星发送给203自己的岸基软件,然后解密之后再传给西工大岸基软件 + * */ + String sms = DecodeData.decodeSMS(data); + saveDataLog(0, String.valueOf(robotId), sms, "0"); + + byte[] bytes; + if (sms.startsWith("*") || sms.startsWith("?")) { + /** + * 查看配置等直接通信即可 + * */ + bytes = sms.getBytes(StandardCharsets.UTF_8); + } else { + /** + * 数据加密之后再与卫星通信 + * */ + if (isClient) { + bytes = CommandManager.createClientMessageCmd(sms); + } else { + bytes = CommandManager.createServerMessageCmd( + sms, serverAccount, serverPassword, clientAccount + ); + } + } + if (serialPort != null && serialPort.isConnected()) { + SerialPortManager.sendToPort(serialPort, bytes); + saveDataLog(3, String.valueOf(robotId), sms, "0"); + } + break; + case 0x05: + String envRequest = DecodeData.decodeEnvRequest(data); + saveDataLog(0, String.valueOf(robotId), envRequest, "0"); + //{"hour":"12","lng":109.32222199129043,"lat":17.39223199775081} + JSONObject envJsonObject = JSON.parseObject(envRequest); + + String hour = envJsonObject.getString("hour"); + double envLng = envJsonObject.getDouble("lng"); + double envLat = envJsonObject.getDouble("lat"); + + List typhoonList = typhoonService.currentTyphoonList(); + + String date = TimeUtil.getCurrentTime(); + OceanDetailDTO oceanDetail = oceanService.oceanDetail(envLng, envLat, date, "0", hour); + + Map objectMap; + if (typhoonList.isEmpty()) { + objectMap = EncodeData.encodeEnvironment(envLng, envLat, null, oceanDetail); + } else if (typhoonList.size() == 1) { + TyphoonDetailDTO detailDTO = typhoonService.typhoonDetail(typhoonList.get(0).getTyphoonId()); + objectMap = EncodeData.encodeEnvironment(envLng, envLat, detailDTO, oceanDetail); + } else { + /** + * 如果有多个台风,只返回距离当前机器人或者方舱最近的台风信息 + * */ + //记录每个台风和当前机器人之间的距离 + List disLinkedList = new LinkedList<>(); + for (TyphoonDTO dto : typhoonList) { + double distance = EncodeData.distance(dto.getLng(), dto.getLat(), envLng, envLat); + disLinkedList.add(distance); + } + //找出LinkedList中的最小值所在的位置 + double min = disLinkedList.get(0); + int pos = 0; + for (int i = 0; i < disLinkedList.size(); i++) { + if (disLinkedList.get(i) < min) { + min = disLinkedList.get(i); + pos = i; + } + } + + TyphoonDetailDTO detailDTO = typhoonService.typhoonDetail(typhoonList.get(pos).getTyphoonId()); + objectMap = EncodeData.encodeEnvironment(envLng, envLat, detailDTO, oceanDetail); + } + ctx.writeAndFlush(JSON.toJSONString(objectMap)); + saveDataLog(1, String.valueOf(robotId), objectMap, "0"); + break; + case 0x06: + String aisRequest = DecodeData.decodeAISRequest(data); + saveDataLog(0, String.valueOf(robotId), aisRequest, "0"); + //{"radius":50,"lng":109.32219994688509,"lat":17.392199978880676,"age":30} + JSONObject aisJsonObject = JSON.parseObject(aisRequest); + + int radius = aisJsonObject.getInteger("radius"); + if (radius > Constant.MAX_RADIUS) { + radius = Constant.MAX_RADIUS; + } + double aisLat = aisJsonObject.getDouble("lat"); + double aisLng = aisJsonObject.getDouble("lng"); + int age = aisJsonObject.getInteger("age"); + if (age > Constant.MAX_AGE) { + age = Constant.MAX_AGE; + } + if (age < Constant.MIN_AGE) { + age = Constant.MIN_AGE; + } + + //AIS不能有小数 + DecimalFormat df = new DecimalFormat("#"); + String requestValue = + df.format(aisLat * 600000) + "," + + df.format(aisLng * 600000) + "," + + radius; + + List ships = shipService.shipsInCircle(requestValue, age); + Map map = EncodeData.encodeAIS(aisLng, aisLat, ships); + ctx.writeAndFlush(JSON.toJSONString(map)); + saveDataLog(1, String.valueOf(robotId), map, "0"); + break; + case 0x07: + ShelterPosition shelterPosition = DecodeData.decodeShelterPosition(data); + saveDataLog(0, String.valueOf(robotId), shelterPosition, "0"); + shelterPositionService.save(shelterPosition); + break; + default: + break; + } + //处理完数据,清空链表缓存 + if (temp != null) { + temp.clear(); } }