正在显示
14 个修改的文件
包含
350 行增加
和
47 行删除
| @@ -2,7 +2,9 @@ package com.zhonglai.luhui.smart.feeder; | @@ -2,7 +2,9 @@ package com.zhonglai.luhui.smart.feeder; | ||
| 2 | 2 | ||
| 3 | import com.zhonglai.luhui.smart.feeder.config.OpenCVConfig; | 3 | import com.zhonglai.luhui.smart.feeder.config.OpenCVConfig; |
| 4 | 4 | ||
| 5 | +import com.zhonglai.luhui.smart.feeder.config.OperatingData; | ||
| 5 | import com.zhonglai.luhui.smart.feeder.service.InitService; | 6 | import com.zhonglai.luhui.smart.feeder.service.InitService; |
| 7 | +import com.zhonglai.luhui.smart.spare.feeder.service.SerialPortService; | ||
| 6 | import org.bytedeco.javacv.FFmpegFrameGrabber; | 8 | import org.bytedeco.javacv.FFmpegFrameGrabber; |
| 7 | import org.slf4j.Logger; | 9 | import org.slf4j.Logger; |
| 8 | import org.slf4j.LoggerFactory; | 10 | import org.slf4j.LoggerFactory; |
| @@ -17,6 +19,14 @@ public class Main { | @@ -17,6 +19,14 @@ public class Main { | ||
| 17 | logger.info("配置参数"); | 19 | logger.info("配置参数"); |
| 18 | InitService.initConfig(); | 20 | InitService.initConfig(); |
| 19 | 21 | ||
| 22 | + logger.info("开始加载FFmpeg"); | ||
| 23 | + try { | ||
| 24 | + FFmpegFrameGrabber.tryLoad(); | ||
| 25 | + } catch (FFmpegFrameGrabber.Exception e) { | ||
| 26 | + throw new RuntimeException(e); | ||
| 27 | + } | ||
| 28 | + logger.info("FFmpeg加载完成"); | ||
| 29 | + | ||
| 20 | logger.info("启动服务"); | 30 | logger.info("启动服务"); |
| 21 | InitService.startService(); | 31 | InitService.startService(); |
| 22 | 32 |
| @@ -14,9 +14,9 @@ import com.zhonglai.luhui.smart.feeder.dto.mqtt.CmdDto; | @@ -14,9 +14,9 @@ import com.zhonglai.luhui.smart.feeder.dto.mqtt.CmdDto; | ||
| 14 | import com.zhonglai.luhui.smart.feeder.dto.mqtt.Condata; | 14 | import com.zhonglai.luhui.smart.feeder.dto.mqtt.Condata; |
| 15 | import com.zhonglai.luhui.smart.feeder.dto.mqtt.DevicedatRequest; | 15 | import com.zhonglai.luhui.smart.feeder.dto.mqtt.DevicedatRequest; |
| 16 | import com.zhonglai.luhui.smart.feeder.dto.mqtt.Info; | 16 | import com.zhonglai.luhui.smart.feeder.dto.mqtt.Info; |
| 17 | -import com.zhonglai.luhui.smart.feeder.service.device.SerialPortService; | ||
| 18 | import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil; | 17 | import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil; |
| 19 | import com.zhonglai.luhui.smart.feeder.util.MessageUtil; | 18 | import com.zhonglai.luhui.smart.feeder.util.MessageUtil; |
| 19 | +import com.zhonglai.luhui.smart.spare.feeder.service.SerialPortService; | ||
| 20 | import org.slf4j.Logger; | 20 | import org.slf4j.Logger; |
| 21 | import org.slf4j.LoggerFactory; | 21 | import org.slf4j.LoggerFactory; |
| 22 | 22 | ||
| @@ -42,6 +42,7 @@ public class DateListenService { | @@ -42,6 +42,7 @@ public class DateListenService { | ||
| 42 | 42 | ||
| 43 | public void run() | 43 | public void run() |
| 44 | { | 44 | { |
| 45 | + logger.info("数据上报"); | ||
| 45 | //更新投料机数据 | 46 | //更新投料机数据 |
| 46 | ScheduledConfig.scheduler.scheduleWithFixedDelay(() -> { | 47 | ScheduledConfig.scheduler.scheduleWithFixedDelay(() -> { |
| 47 | ModbusDto modbusDto = serialPortService.sendHexData(FeederCommdUtil.readAll()); | 48 | ModbusDto modbusDto = serialPortService.sendHexData(FeederCommdUtil.readAll()); |
| @@ -67,6 +67,7 @@ public class FishGroupImageRecognitionService { | @@ -67,6 +67,7 @@ public class FishGroupImageRecognitionService { | ||
| 67 | 67 | ||
| 68 | public void run() | 68 | public void run() |
| 69 | { | 69 | { |
| 70 | + logger.info("图像识别"); | ||
| 70 | scheduledFuture = ScheduledConfig.scheduler.scheduleWithFixedDelay(() -> { | 71 | scheduledFuture = ScheduledConfig.scheduler.scheduleWithFixedDelay(() -> { |
| 71 | if (!OperatingData.cameraData.getFishGroupImageRecognIsRun()) | 72 | if (!OperatingData.cameraData.getFishGroupImageRecognIsRun()) |
| 72 | { | 73 | { |
| @@ -85,10 +86,11 @@ public class FishGroupImageRecognitionService { | @@ -85,10 +86,11 @@ public class FishGroupImageRecognitionService { | ||
| 85 | 86 | ||
| 86 | if(!cameraHandle.isOpen()) | 87 | if(!cameraHandle.isOpen()) |
| 87 | { | 88 | { |
| 88 | - if (!cameraHandle.init()) | ||
| 89 | - { | ||
| 90 | return; | 89 | return; |
| 91 | - } | 90 | +// if (!cameraHandle.init()) |
| 91 | +// { | ||
| 92 | +// return; | ||
| 93 | +// } | ||
| 92 | } | 94 | } |
| 93 | OperatingData.cameraData.setFishGroupImageRecognIsRun(true); | 95 | OperatingData.cameraData.setFishGroupImageRecognIsRun(true); |
| 94 | brightnessIdentifyFishRegion(); | 96 | brightnessIdentifyFishRegion(); |
| 1 | package com.zhonglai.luhui.smart.feeder.service; | 1 | package com.zhonglai.luhui.smart.feeder.service; |
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | +import com.zhonglai.luhui.smart.feeder.config.OperatingData; | ||
| 4 | import com.zhonglai.luhui.smart.feeder.service.device.CameraHandle; | 5 | import com.zhonglai.luhui.smart.feeder.service.device.CameraHandle; |
| 5 | -import com.zhonglai.luhui.smart.feeder.service.device.SerialPortService; | ||
| 6 | import com.zhonglai.luhui.smart.feeder.service.device.handle.CameraRtspHandle; | 6 | import com.zhonglai.luhui.smart.feeder.service.device.handle.CameraRtspHandle; |
| 7 | -import com.zhonglai.luhui.smart.feeder.service.netty.NettyClient; | 7 | +import com.zhonglai.luhui.smart.spare.feeder.service.NettyClient; |
| 8 | +import com.zhonglai.luhui.smart.spare.feeder.service.SerialPortService; | ||
| 8 | 9 | ||
| 9 | import java.io.BufferedReader; | 10 | import java.io.BufferedReader; |
| 10 | import java.io.InputStreamReader; | 11 | import java.io.InputStreamReader; |
| @@ -36,13 +37,17 @@ public class InitService { | @@ -36,13 +37,17 @@ public class InitService { | ||
| 36 | /** | 37 | /** |
| 37 | * 串口服务器启动 | 38 | * 串口服务器启动 |
| 38 | */ | 39 | */ |
| 40 | + String portName = OperatingData.feederConfig.getSerialPortConfig().getPortName(); | ||
| 39 | serialPortService = new SerialPortService(); | 41 | serialPortService = new SerialPortService(); |
| 42 | + serialPortService.connect(portName); | ||
| 43 | + // 启动重连线程 | ||
| 44 | + new Thread(() -> serialPortService.reconnect(portName, 5000)).start(); // 每5秒尝试重连一次 | ||
| 40 | 45 | ||
| 41 | /** | 46 | /** |
| 42 | * mq远程登录 | 47 | * mq远程登录 |
| 43 | */ | 48 | */ |
| 44 | - nettyClient = new NettyClient(); | ||
| 45 | - nettyClient.run(); | 49 | + nettyClient = new NettyClient(OperatingData.sysConfig.getNettyConfig().getHost(), OperatingData.sysConfig.getNettyConfig().getPort()); |
| 50 | + nettyClient.start(); | ||
| 46 | 51 | ||
| 47 | /** | 52 | /** |
| 48 | * 初始化海康的摄像头 | 53 | * 初始化海康的摄像头 |
| @@ -67,6 +72,5 @@ public class InitService { | @@ -67,6 +72,5 @@ public class InitService { | ||
| 67 | mqttService = new MqttService(); | 72 | mqttService = new MqttService(); |
| 68 | mqttService.start(); | 73 | mqttService.start(); |
| 69 | 74 | ||
| 70 | - | ||
| 71 | } | 75 | } |
| 72 | } | 76 | } |
| @@ -4,9 +4,11 @@ import com.ruoyi.common.utils.DateUtils; | @@ -4,9 +4,11 @@ import com.ruoyi.common.utils.DateUtils; | ||
| 4 | import com.zhonglai.luhui.smart.feeder.config.OperatingData; | 4 | import com.zhonglai.luhui.smart.feeder.config.OperatingData; |
| 5 | import com.zhonglai.luhui.smart.feeder.config.ScheduledConfig; | 5 | import com.zhonglai.luhui.smart.feeder.config.ScheduledConfig; |
| 6 | import com.zhonglai.luhui.smart.feeder.dto.mqtt.Condata; | 6 | import com.zhonglai.luhui.smart.feeder.dto.mqtt.Condata; |
| 7 | -import com.zhonglai.luhui.smart.feeder.service.device.SerialPortService; | ||
| 8 | import com.zhonglai.luhui.smart.feeder.util.FeederCommd06ResponseType; | 7 | import com.zhonglai.luhui.smart.feeder.util.FeederCommd06ResponseType; |
| 9 | import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil; | 8 | import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil; |
| 9 | +import com.zhonglai.luhui.smart.spare.feeder.service.SerialPortService; | ||
| 10 | +import org.slf4j.Logger; | ||
| 11 | +import org.slf4j.LoggerFactory; | ||
| 10 | 12 | ||
| 11 | import java.util.Date; | 13 | import java.util.Date; |
| 12 | import java.util.concurrent.ScheduledFuture; | 14 | import java.util.concurrent.ScheduledFuture; |
| @@ -16,6 +18,8 @@ import java.util.concurrent.TimeUnit; | @@ -16,6 +18,8 @@ import java.util.concurrent.TimeUnit; | ||
| 16 | * 尺度步长法 | 18 | * 尺度步长法 |
| 17 | */ | 19 | */ |
| 18 | public class ScaleStepMethodService { | 20 | public class ScaleStepMethodService { |
| 21 | + private static final Logger logger = LoggerFactory.getLogger(ScaleStepMethodService.class); | ||
| 22 | + | ||
| 19 | private Integer logTady = Integer.parseInt(DateUtils.parseDateToStr("yyyyMMdd",new Date())); | 23 | private Integer logTady = Integer.parseInt(DateUtils.parseDateToStr("yyyyMMdd",new Date())); |
| 20 | private ScheduledFuture scheduledFuture; | 24 | private ScheduledFuture scheduledFuture; |
| 21 | 25 | ||
| @@ -28,6 +32,7 @@ public class ScaleStepMethodService { | @@ -28,6 +32,7 @@ public class ScaleStepMethodService { | ||
| 28 | 32 | ||
| 29 | public void run() | 33 | public void run() |
| 30 | { | 34 | { |
| 35 | + logger.info("鱼群图像识别控制投料控制"); | ||
| 31 | scheduledFuture = ScheduledConfig.scheduler.scheduleWithFixedDelay(() -> { | 36 | scheduledFuture = ScheduledConfig.scheduler.scheduleWithFixedDelay(() -> { |
| 32 | Integer nowTady = Integer.parseInt(DateUtils.parseDateToStr("yyyyMMdd",new Date())); | 37 | Integer nowTady = Integer.parseInt(DateUtils.parseDateToStr("yyyyMMdd",new Date())); |
| 33 | if( OperatingData.cameraData.getScaleAreaList().size()==0) | 38 | if( OperatingData.cameraData.getScaleAreaList().size()==0) |
| @@ -69,7 +74,7 @@ public class ScaleStepMethodService { | @@ -69,7 +74,7 @@ public class ScaleStepMethodService { | ||
| 69 | if (OperatingData.cameraConfig.getFeedingControl()) | 74 | if (OperatingData.cameraConfig.getFeedingControl()) |
| 70 | { | 75 | { |
| 71 | //发送停止投料指令 | 76 | //发送停止投料指令 |
| 72 | - if (serialPortService.isOpen()) | 77 | + if (serialPortService.isConnected()) |
| 73 | { | 78 | { |
| 74 | if(OperatingData.feederConfig.getCondata().getRunmode()==1) | 79 | if(OperatingData.feederConfig.getCondata().getRunmode()==1) |
| 75 | { | 80 | { |
| @@ -62,6 +62,7 @@ public class SerialPortService { | @@ -62,6 +62,7 @@ public class SerialPortService { | ||
| 62 | } | 62 | } |
| 63 | OperatingData.feederData.setInfo(info); | 63 | OperatingData.feederData.setInfo(info); |
| 64 | } | 64 | } |
| 65 | + logger.info("端口启动情况:{}",serialPort.isOpen()); | ||
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | private SerialPort findSerialPort() | 68 | private SerialPort findSerialPort() |
| @@ -70,10 +71,8 @@ public class SerialPortService { | @@ -70,10 +71,8 @@ public class SerialPortService { | ||
| 70 | SerialPort[] serialPorts = SerialPort.getCommPorts();//查找所有串口 | 71 | SerialPort[] serialPorts = SerialPort.getCommPorts();//查找所有串口 |
| 71 | 72 | ||
| 72 | for(SerialPort port:serialPorts){ | 73 | for(SerialPort port:serialPorts){ |
| 73 | - System.out.println("Port:"+port.getSystemPortName());//打印串口名称,如COM4 | ||
| 74 | - System.out.println("PortDesc:"+port.getPortDescription());//打印串口类型,如USB Serial | ||
| 75 | - System.out.println("PortDesc:"+port.getDescriptivePortName());//打印串口的完整类型,如USB-SERIAL CH340(COM4) | ||
| 76 | - if(port.getPortDescription().indexOf("USB")>=0) | 74 | + logger.info("Port:{},PortDesc:{},PortDesc:{}",port.getSystemPortName(),port.getPortDescription(),port.getDescriptivePortName());//打印串口名称,如COM4;打印串口类型,如USB Serial;打印串口的完整类型,如USB-SERIAL CH340(COM4) |
| 75 | + if(port.getSystemPortName().indexOf("ttyS0")>=0) | ||
| 77 | { | 76 | { |
| 78 | serialPort = port; | 77 | serialPort = port; |
| 79 | break; | 78 | break; |
| @@ -35,6 +35,7 @@ public class CameraRtspHandle implements CameraHandle { | @@ -35,6 +35,7 @@ public class CameraRtspHandle implements CameraHandle { | ||
| 35 | 35 | ||
| 36 | public CameraRtspHandle() | 36 | public CameraRtspHandle() |
| 37 | { | 37 | { |
| 38 | + logger.info("初始化海康的摄像头"); | ||
| 38 | init(); | 39 | init(); |
| 39 | 40 | ||
| 40 | } | 41 | } |
| @@ -46,10 +47,8 @@ public class CameraRtspHandle implements CameraHandle { | @@ -46,10 +47,8 @@ public class CameraRtspHandle implements CameraHandle { | ||
| 46 | { | 47 | { |
| 47 | return true; | 48 | return true; |
| 48 | } | 49 | } |
| 49 | - | ||
| 50 | try { | 50 | try { |
| 51 | - FFmpegFrameGrabber.tryLoad(); | ||
| 52 | - | 51 | + logger.info("配置的视频源类型"+OperatingData.cameraConfig.getCameraInterfaceType().toLowerCase()); |
| 53 | switch (OperatingData.cameraConfig.getCameraInterfaceType().toLowerCase()) | 52 | switch (OperatingData.cameraConfig.getCameraInterfaceType().toLowerCase()) |
| 54 | { | 53 | { |
| 55 | case "rtsp": | 54 | case "rtsp": |
| @@ -138,6 +137,7 @@ public class CameraRtspHandle implements CameraHandle { | @@ -138,6 +137,7 @@ public class CameraRtspHandle implements CameraHandle { | ||
| 138 | } | 137 | } |
| 139 | 138 | ||
| 140 | private boolean initRtsp() throws FFmpegFrameGrabber.Exception, InterruptedException { | 139 | private boolean initRtsp() throws FFmpegFrameGrabber.Exception, InterruptedException { |
| 140 | + logger.error("加载Rtsp"); | ||
| 141 | String ip = findCameraIp(); | 141 | String ip = findCameraIp(); |
| 142 | if(StringUtils.isEmpty(ip)) | 142 | if(StringUtils.isEmpty(ip)) |
| 143 | { | 143 | { |
| @@ -327,7 +327,7 @@ public class CameraRtspHandle implements CameraHandle { | @@ -327,7 +327,7 @@ public class CameraRtspHandle implements CameraHandle { | ||
| 327 | while (addresses.hasMoreElements()) { | 327 | while (addresses.hasMoreElements()) { |
| 328 | InetAddress addr = addresses.nextElement(); | 328 | InetAddress addr = addresses.nextElement(); |
| 329 | if (addr.isSiteLocalAddress()) { // Checks if this address is a "site local" address. | 329 | if (addr.isSiteLocalAddress()) { // Checks if this address is a "site local" address. |
| 330 | - | 330 | + logger.info("主机的IP:{}",addr.getHostAddress()); |
| 331 | if(addr.getHostAddress().contains("192.168")) | 331 | if(addr.getHostAddress().contains("192.168")) |
| 332 | { | 332 | { |
| 333 | return addr.getHostAddress(); | 333 | return addr.getHostAddress(); |
| @@ -342,6 +342,7 @@ public class CameraRtspHandle implements CameraHandle { | @@ -342,6 +342,7 @@ public class CameraRtspHandle implements CameraHandle { | ||
| 342 | 342 | ||
| 343 | public static String findCameraIp() { | 343 | public static String findCameraIp() { |
| 344 | String localIP = getLocalIp(); | 344 | String localIP = getLocalIp(); |
| 345 | + logger.info("找到的主机ip:"+localIP); | ||
| 345 | if(null == localIP) | 346 | if(null == localIP) |
| 346 | { | 347 | { |
| 347 | return null; | 348 | return null; |
| @@ -366,7 +367,7 @@ public class CameraRtspHandle implements CameraHandle { | @@ -366,7 +367,7 @@ public class CameraRtspHandle implements CameraHandle { | ||
| 366 | while (StringUtils.isEmpty(ip[0])) | 367 | while (StringUtils.isEmpty(ip[0])) |
| 367 | { | 368 | { |
| 368 | findCamera(localIP); | 369 | findCamera(localIP); |
| 369 | - Thread.sleep(1000); | 370 | + Thread.sleep(10000); |
| 370 | } | 371 | } |
| 371 | } catch (InterruptedException e) { | 372 | } catch (InterruptedException e) { |
| 372 | e.printStackTrace(); | 373 | e.printStackTrace(); |
| @@ -381,6 +382,7 @@ public class CameraRtspHandle implements CameraHandle { | @@ -381,6 +382,7 @@ public class CameraRtspHandle implements CameraHandle { | ||
| 381 | } | 382 | } |
| 382 | return ip[0]; | 383 | return ip[0]; |
| 383 | } catch (InterruptedException e) { | 384 | } catch (InterruptedException e) { |
| 385 | + logger.error("查找摄像头失败",e); | ||
| 384 | } | 386 | } |
| 385 | return null; | 387 | return null; |
| 386 | } | 388 | } |
| @@ -412,24 +414,32 @@ public class CameraRtspHandle implements CameraHandle { | @@ -412,24 +414,32 @@ public class CameraRtspHandle implements CameraHandle { | ||
| 412 | 414 | ||
| 413 | 415 | ||
| 414 | private static String getCameraIp(String ip) throws Exception { | 416 | private static String getCameraIp(String ip) throws Exception { |
| 417 | + logger.info("开始查找摄像头的ip"); | ||
| 415 | // 1.创建组播socket,加入指定的组播地址和端口 | 418 | // 1.创建组播socket,加入指定的组播地址和端口 |
| 416 | InetAddress group = InetAddress.getByName("239.255.255.250"); | 419 | InetAddress group = InetAddress.getByName("239.255.255.250"); |
| 417 | MulticastSocket multicastSocket = new MulticastSocket(37020); | 420 | MulticastSocket multicastSocket = new MulticastSocket(37020); |
| 418 | 421 | ||
| 419 | multicastSocket.joinGroup(new InetSocketAddress(group,37020),NetworkInterface.getByInetAddress(InetAddress.getByName(ip))); | 422 | multicastSocket.joinGroup(new InetSocketAddress(group,37020),NetworkInterface.getByInetAddress(InetAddress.getByName(ip))); |
| 420 | - multicastSocket.setSoTimeout(100000); | 423 | + multicastSocket.setSoTimeout(10000); |
| 421 | // 2.创建接收的数据包 | 424 | // 2.创建接收的数据包 |
| 422 | byte[] buf = new byte[1024]; | 425 | byte[] buf = new byte[1024]; |
| 423 | 426 | ||
| 424 | - | ||
| 425 | // 4.解析数据包,并打印出来 | 427 | // 4.解析数据包,并打印出来 |
| 426 | HCCameraRepose probe = null; | 428 | HCCameraRepose probe = null; |
| 427 | while (ObjectUtil.isEmpty(probe)) | 429 | while (ObjectUtil.isEmpty(probe)) |
| 428 | { | 430 | { |
| 429 | DatagramPacket dpReceive = new DatagramPacket(buf, buf.length); | 431 | DatagramPacket dpReceive = new DatagramPacket(buf, buf.length); |
| 432 | + logger.info("发送组播查找信息"); | ||
| 430 | // 3.调用socket对象的接收方法接收数据包 | 433 | // 3.调用socket对象的接收方法接收数据包 |
| 434 | + try { | ||
| 431 | multicastSocket.receive(dpReceive); | 435 | multicastSocket.receive(dpReceive); |
| 436 | + }catch (Exception e) | ||
| 437 | + { | ||
| 438 | + logger.error("组播查找异常",e); | ||
| 439 | + } | ||
| 440 | + | ||
| 432 | String receivedXml = new String(dpReceive.getData(), 0, dpReceive.getLength()); | 441 | String receivedXml = new String(dpReceive.getData(), 0, dpReceive.getLength()); |
| 442 | + logger.info("查找海康摄像头的结果:{}",receivedXml); | ||
| 433 | 443 | ||
| 434 | String startTag = "<IPv4Address>"; | 444 | String startTag = "<IPv4Address>"; |
| 435 | String endTag = "</IPv4Address>"; | 445 | String endTag = "</IPv4Address>"; |
| @@ -5,8 +5,8 @@ import com.ruoyi.common.utils.GsonConstructor; | @@ -5,8 +5,8 @@ import com.ruoyi.common.utils.GsonConstructor; | ||
| 5 | import com.zhonglai.luhui.smart.feeder.config.OperatingData; | 5 | import com.zhonglai.luhui.smart.feeder.config.OperatingData; |
| 6 | import com.zhonglai.luhui.smart.feeder.dto.mqtt.CmdDto; | 6 | import com.zhonglai.luhui.smart.feeder.dto.mqtt.CmdDto; |
| 7 | import com.zhonglai.luhui.smart.feeder.dto.mqtt.HeadDto; | 7 | import com.zhonglai.luhui.smart.feeder.dto.mqtt.HeadDto; |
| 8 | -import com.zhonglai.luhui.smart.feeder.service.netty.NettyClient; | ||
| 9 | import com.zhonglai.luhui.smart.feeder.util.MessageUtil; | 8 | import com.zhonglai.luhui.smart.feeder.util.MessageUtil; |
| 9 | +import com.zhonglai.luhui.smart.spare.feeder.service.NettyClient; | ||
| 10 | import io.netty.channel.ChannelHandlerContext; | 10 | import io.netty.channel.ChannelHandlerContext; |
| 11 | import io.netty.handler.codec.MessageToMessageDecoder; | 11 | import io.netty.handler.codec.MessageToMessageDecoder; |
| 12 | import org.apache.commons.lang3.StringUtils; | 12 | import org.apache.commons.lang3.StringUtils; |
| @@ -14,6 +14,7 @@ import org.slf4j.Logger; | @@ -14,6 +14,7 @@ import org.slf4j.Logger; | ||
| 14 | import org.slf4j.LoggerFactory; | 14 | import org.slf4j.LoggerFactory; |
| 15 | 15 | ||
| 16 | import java.util.List; | 16 | import java.util.List; |
| 17 | +import java.util.concurrent.TimeUnit; | ||
| 17 | import java.util.regex.Matcher; | 18 | import java.util.regex.Matcher; |
| 18 | import java.util.regex.Pattern; | 19 | import java.util.regex.Pattern; |
| 19 | 20 | ||
| @@ -29,28 +30,7 @@ public class AgreementHandler extends MessageToMessageDecoder<String> { | @@ -29,28 +30,7 @@ public class AgreementHandler extends MessageToMessageDecoder<String> { | ||
| 29 | 30 | ||
| 30 | private CameracontrolService cameracontrolService = new CameracontrolService(); | 31 | private CameracontrolService cameracontrolService = new CameracontrolService(); |
| 31 | 32 | ||
| 32 | - private NettyClient nettyClient; | ||
| 33 | 33 | ||
| 34 | - public AgreementHandler(NettyClient nettyClient) | ||
| 35 | - { | ||
| 36 | - this.nettyClient = nettyClient; | ||
| 37 | - } | ||
| 38 | - | ||
| 39 | - @Override | ||
| 40 | - public void channelActive(ChannelHandlerContext ctx) throws Exception { | ||
| 41 | - logger.info("设备上线"); | ||
| 42 | - nettyClient.setCtx(ctx); | ||
| 43 | - // 连接建立时的处理,发送请求注册消息给服务器 | ||
| 44 | - JsonObject jsonObject = new JsonObject(); | ||
| 45 | - jsonObject.addProperty("cmd","manualcontrol"); | ||
| 46 | - jsonObject.addProperty("type","4G.hs"); | ||
| 47 | - MessageUtil.sendMessage(ctx, new CmdDto().setImei(OperatingData.sysConfig.getNettyConfig().getClientId()).setJsonObject(jsonObject).generateCmd(),true); | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | - @Override | ||
| 51 | - public void channelInactive(ChannelHandlerContext ctx) { | ||
| 52 | - logger.info("设备离线"); | ||
| 53 | - } | ||
| 54 | 34 | ||
| 55 | private static boolean checkAgreement(String data) | 35 | private static boolean checkAgreement(String data) |
| 56 | { | 36 | { |
| @@ -65,6 +45,7 @@ public class AgreementHandler extends MessageToMessageDecoder<String> { | @@ -65,6 +45,7 @@ public class AgreementHandler extends MessageToMessageDecoder<String> { | ||
| 65 | return rs; | 45 | return rs; |
| 66 | } | 46 | } |
| 67 | 47 | ||
| 48 | + | ||
| 68 | @Override | 49 | @Override |
| 69 | protected void decode(ChannelHandlerContext ctx, String msg, List<Object> out) throws Exception { | 50 | protected void decode(ChannelHandlerContext ctx, String msg, List<Object> out) throws Exception { |
| 70 | try { | 51 | try { |
| @@ -81,6 +62,7 @@ public class AgreementHandler extends MessageToMessageDecoder<String> { | @@ -81,6 +62,7 @@ public class AgreementHandler extends MessageToMessageDecoder<String> { | ||
| 81 | break; | 62 | break; |
| 82 | case "cfgdata": | 63 | case "cfgdata": |
| 83 | cfgdataService.noticeFeeder(ctx,cmdDto); | 64 | cfgdataService.noticeFeeder(ctx,cmdDto); |
| 65 | + logger.info("cfgdata数据通知结束"); | ||
| 84 | break; | 66 | break; |
| 85 | case "manualcontrol": | 67 | case "manualcontrol": |
| 86 | manualcontrolService.noticeFeeder(ctx,cmdDto); | 68 | manualcontrolService.noticeFeeder(ctx,cmdDto); |
| @@ -31,7 +31,7 @@ public class CfgdataService { | @@ -31,7 +31,7 @@ public class CfgdataService { | ||
| 31 | private static final Logger logger = LoggerFactory.getLogger(CfgdataService.class); | 31 | private static final Logger logger = LoggerFactory.getLogger(CfgdataService.class); |
| 32 | public void noticeFeeder(ChannelHandlerContext ctx,CmdDto cmdDto) | 32 | public void noticeFeeder(ChannelHandlerContext ctx,CmdDto cmdDto) |
| 33 | { | 33 | { |
| 34 | - if(!InitService.serialPortService.open()) | 34 | + if(!InitService.serialPortService.isConnected()) |
| 35 | { | 35 | { |
| 36 | MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.serialPortErr,0); | 36 | MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.serialPortErr,0); |
| 37 | return; | 37 | return; |
| @@ -25,7 +25,7 @@ public class ManualcontrolService { | @@ -25,7 +25,7 @@ public class ManualcontrolService { | ||
| 25 | 25 | ||
| 26 | public void noticeFeeder(ChannelHandlerContext ctx,CmdDto cmdDto) | 26 | public void noticeFeeder(ChannelHandlerContext ctx,CmdDto cmdDto) |
| 27 | { | 27 | { |
| 28 | - if(!InitService.serialPortService.open()) | 28 | + if(!InitService.serialPortService.isConnected()) |
| 29 | { | 29 | { |
| 30 | MessageUtil.sendFeederResponseMessage(ctx,"manualcontrolOK", FeederBackstateTtpe.serialPortErr,0); | 30 | MessageUtil.sendFeederResponseMessage(ctx,"manualcontrolOK", FeederBackstateTtpe.serialPortErr,0); |
| 31 | return; | 31 | return; |
| @@ -104,7 +104,7 @@ public class NettyClient { | @@ -104,7 +104,7 @@ public class NettyClient { | ||
| 104 | ChannelPipeline pipeline = ch.pipeline(); | 104 | ChannelPipeline pipeline = ch.pipeline(); |
| 105 | pipeline.addLast("StringEncoder", new StringEncoder(Charset.forName("gb2312"))); | 105 | pipeline.addLast("StringEncoder", new StringEncoder(Charset.forName("gb2312"))); |
| 106 | pipeline.addLast("StringDecoder", new StringDecoder(Charset.forName("gb2312"))); | 106 | pipeline.addLast("StringDecoder", new StringDecoder(Charset.forName("gb2312"))); |
| 107 | - pipeline.addLast("AgreementHandler", new AgreementHandler(nettyClient)); | 107 | + pipeline.addLast("AgreementHandler", new AgreementHandler()); |
| 108 | } | 108 | } |
| 109 | } | 109 | } |
| 110 | 110 |
| 1 | +package com.zhonglai.luhui.smart.spare.feeder.service; | ||
| 2 | + | ||
| 3 | +import com.google.gson.JsonObject; | ||
| 4 | +import com.zhonglai.luhui.smart.feeder.config.OperatingData; | ||
| 5 | +import com.zhonglai.luhui.smart.feeder.dto.mqtt.CmdDto; | ||
| 6 | +import com.zhonglai.luhui.smart.feeder.service.feeder.AgreementHandler; | ||
| 7 | +import com.zhonglai.luhui.smart.feeder.util.MessageUtil; | ||
| 8 | +import io.netty.bootstrap.Bootstrap; | ||
| 9 | +import io.netty.channel.*; | ||
| 10 | +import io.netty.channel.nio.NioEventLoopGroup; | ||
| 11 | +import io.netty.channel.socket.SocketChannel; | ||
| 12 | +import io.netty.channel.socket.nio.NioSocketChannel; | ||
| 13 | +import io.netty.handler.codec.string.StringDecoder; | ||
| 14 | +import io.netty.handler.codec.string.StringEncoder; | ||
| 15 | +import org.slf4j.Logger; | ||
| 16 | +import org.slf4j.LoggerFactory; | ||
| 17 | + | ||
| 18 | +import java.nio.charset.Charset; | ||
| 19 | +import java.util.concurrent.TimeUnit; | ||
| 20 | +import java.util.concurrent.atomic.AtomicInteger; | ||
| 21 | + | ||
| 22 | +public class NettyClient { | ||
| 23 | + private static final Logger logger = LoggerFactory.getLogger(NettyClient.class); | ||
| 24 | + private final String host; | ||
| 25 | + private final int port; | ||
| 26 | + private Bootstrap bootstrap; | ||
| 27 | + private EventLoopGroup group; | ||
| 28 | + private Channel channel; | ||
| 29 | + | ||
| 30 | + private ChannelHandlerContext ctx; | ||
| 31 | + | ||
| 32 | + private ChannelFuture future; | ||
| 33 | + private final AtomicInteger retryCount = new AtomicInteger(); | ||
| 34 | + | ||
| 35 | + public NettyClient(String host, int port) { | ||
| 36 | + this.host = host; | ||
| 37 | + this.port = port; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + public void start() { | ||
| 41 | + group = new NioEventLoopGroup(); | ||
| 42 | + try { | ||
| 43 | + bootstrap = new Bootstrap(); | ||
| 44 | + bootstrap.group(group) | ||
| 45 | + .channel(NioSocketChannel.class) | ||
| 46 | + .handler(new ChannelInitializer<SocketChannel>() { | ||
| 47 | + @Override | ||
| 48 | + protected void initChannel(SocketChannel ch) throws Exception { | ||
| 49 | + ch.pipeline().addLast("StringEncoder", new StringEncoder(Charset.forName("gb2312"))); | ||
| 50 | + ch.pipeline().addLast("StringDecoder", new StringDecoder(Charset.forName("gb2312"))); | ||
| 51 | + ch.pipeline().addLast(new AgreementHandler()); | ||
| 52 | + ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){ | ||
| 53 | + @Override | ||
| 54 | + public void channelActive(ChannelHandlerContext ctx) throws Exception { | ||
| 55 | + logger.info("设备上线"); | ||
| 56 | + setCtx(ctx); | ||
| 57 | + // 连接建立时的处理,发送请求注册消息给服务器 | ||
| 58 | + JsonObject jsonObject = new JsonObject(); | ||
| 59 | + jsonObject.addProperty("cmd","manualcontrol"); | ||
| 60 | + jsonObject.addProperty("type","4G.hs"); | ||
| 61 | + MessageUtil.sendMessage(ctx, new CmdDto().setImei(OperatingData.sysConfig.getNettyConfig().getClientId()).setJsonObject(jsonObject).generateCmd(),true); | ||
| 62 | + } | ||
| 63 | + @Override | ||
| 64 | + public void channelInactive(ChannelHandlerContext ctx) { | ||
| 65 | + logger.info("设备离线"); | ||
| 66 | + future.channel().eventLoop().schedule(NettyClient.this::connect, 5, TimeUnit.SECONDS); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + @Override | ||
| 70 | + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { | ||
| 71 | + cause.printStackTrace(); | ||
| 72 | + ctx.close(); | ||
| 73 | + } | ||
| 74 | + }); | ||
| 75 | + } | ||
| 76 | + }); | ||
| 77 | + | ||
| 78 | + connect(); | ||
| 79 | + } catch (Exception e) { | ||
| 80 | + e.printStackTrace(); | ||
| 81 | + } | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + public void shutdown() { | ||
| 85 | + group.shutdownGracefully(); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + private void connect() { | ||
| 89 | + if (channel != null && channel.isActive()) { | ||
| 90 | + return; | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + | ||
| 94 | + try { | ||
| 95 | + future = bootstrap.connect(host, port); | ||
| 96 | + future.addListener(new ChannelFutureListener() { | ||
| 97 | + @Override | ||
| 98 | + public void operationComplete(ChannelFuture future) throws Exception { | ||
| 99 | + if (future.isSuccess()) { | ||
| 100 | + channel = future.channel(); | ||
| 101 | + logger.info("运程连接成功"); | ||
| 102 | + } else { | ||
| 103 | + logger.info("运程连接失败,尝试重连..."); | ||
| 104 | + retryCount.incrementAndGet(); | ||
| 105 | + future.channel().eventLoop().schedule(NettyClient.this::connect, 5, TimeUnit.SECONDS); | ||
| 106 | + } | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + }).sync(); | ||
| 110 | + } catch (InterruptedException e) { | ||
| 111 | + logger.error("连接失败",e); | ||
| 112 | + future.channel().eventLoop().schedule(NettyClient.this::connect, 5, TimeUnit.SECONDS); | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + | ||
| 119 | + | ||
| 120 | + public ChannelHandlerContext getCtx() { | ||
| 121 | + return ctx; | ||
| 122 | + } | ||
| 123 | + public void setCtx(ChannelHandlerContext ctx) | ||
| 124 | + { | ||
| 125 | + this.ctx = ctx; | ||
| 126 | + } | ||
| 127 | +} |
| 1 | +package com.zhonglai.luhui.smart.spare.feeder.service; | ||
| 2 | + | ||
| 3 | +import com.fazecast.jSerialComm.SerialPort; | ||
| 4 | +import com.fazecast.jSerialComm.SerialPortEvent; | ||
| 5 | +import com.ruoyi.common.utils.ByteUtil; | ||
| 6 | +import com.zhonglai.luhui.smart.feeder.config.OperatingData; | ||
| 7 | +import com.zhonglai.luhui.smart.feeder.dto.ModbusDto; | ||
| 8 | +import com.zhonglai.luhui.smart.feeder.dto.SerialPortConfig; | ||
| 9 | +import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommdDto; | ||
| 10 | +import org.slf4j.Logger; | ||
| 11 | +import org.slf4j.LoggerFactory; | ||
| 12 | + | ||
| 13 | +import java.util.concurrent.BlockingQueue; | ||
| 14 | +import java.util.concurrent.LinkedBlockingQueue; | ||
| 15 | +import java.util.concurrent.TimeUnit; | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * 端口服务 | ||
| 19 | + */ | ||
| 20 | +public class SerialPortService implements com.fazecast.jSerialComm.SerialPortDataListener { | ||
| 21 | + private static final Logger logger = LoggerFactory.getLogger(SerialPortService.class); | ||
| 22 | + private SerialPort serialPort; | ||
| 23 | + private boolean isConnected = false; | ||
| 24 | + private final Object lock = new Object(); | ||
| 25 | + | ||
| 26 | + private BlockingQueue<ModbusDto> dataQueue = new LinkedBlockingQueue<>(); | ||
| 27 | + | ||
| 28 | + public void connect(String portName) { | ||
| 29 | + serialPort = findSerialPort(portName); | ||
| 30 | + // 尝试打开串口 | ||
| 31 | + logger.info("尝试打开串口:"+portName); | ||
| 32 | +// serialPort = SerialPort.getCommPort(portName); | ||
| 33 | + if (serialPort == null) { | ||
| 34 | + logger.error("无法找到串口: " + portName); | ||
| 35 | + return; | ||
| 36 | + } | ||
| 37 | + logger.info("串口尝试打开成功,准备连接:"+portName); | ||
| 38 | + | ||
| 39 | + try { | ||
| 40 | + SerialPortConfig serialPortConfig = OperatingData.feederConfig.getSerialPortConfig(); | ||
| 41 | + | ||
| 42 | + // 配置串口参数 | ||
| 43 | + serialPort.setBaudRate(serialPortConfig.getBaudrate()); | ||
| 44 | + serialPort.setNumDataBits(serialPortConfig.getDataBits()); | ||
| 45 | + serialPort.setNumStopBits(serialPortConfig.getStopBits()); | ||
| 46 | + serialPort.setParity(serialPortConfig.getParity()); | ||
| 47 | + | ||
| 48 | + // 打开串口 | ||
| 49 | + serialPort.openPort(); | ||
| 50 | + serialPort.addDataListener(this); | ||
| 51 | + | ||
| 52 | + // 设置串口为非阻塞模式,以便可以异步接收数据 | ||
| 53 | + serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 0, 0); | ||
| 54 | + | ||
| 55 | + isConnected = true; | ||
| 56 | + logger.info("串口已连接: " + portName); | ||
| 57 | + | ||
| 58 | + } catch (Exception e) { | ||
| 59 | + logger.error("串口连接失败: " , e); | ||
| 60 | + } | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + @Override | ||
| 64 | + public int getListeningEvents() { | ||
| 65 | + // 监听数据到达事件 | ||
| 66 | + return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;//返回要监听的事件类型,以供回调函数使用。可发回的事件包括:SerialPort.LISTENING_EVENT_DATA_AVAILABLE,SerialPort.LISTENING_EVENT_DATA_WRITTEN,SerialPort.LISTENING_EVENT_DATA_RECEIVED。分别对应有数据在串口(不论是读的还是写的),有数据写入串口,从串口读取数据。如果AVAILABLE和RECEIVED同时被监听,优先触发RECEIVED | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + @Override | ||
| 70 | + public void serialEvent(SerialPortEvent event) { | ||
| 71 | + if (event.getEventType() == SerialPort.LISTENING_EVENT_DATA_AVAILABLE) { | ||
| 72 | + try { | ||
| 73 | + // 读取串口数据 | ||
| 74 | + byte[] newData = new byte[serialPort.bytesAvailable()]; | ||
| 75 | + int numRead = serialPort.readBytes(newData, newData.length); | ||
| 76 | + | ||
| 77 | + logger.info("串口返回{}字节数据:{}",numRead, ByteUtil.toHexString(newData)); | ||
| 78 | + FeederCommdDto commdDto = new FeederCommdDto(newData); | ||
| 79 | + dataQueue.offer(commdDto); // 将数据添加到队列中// 处理串口返回的数据 | ||
| 80 | + } catch (Exception e) { | ||
| 81 | + logger.error("读取串口数据时出错: " , e); | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + | ||
| 87 | + public void disconnect() { | ||
| 88 | + if (isConnected) { | ||
| 89 | + try { | ||
| 90 | + serialPort.removeDataListener(); | ||
| 91 | + serialPort.closePort(); | ||
| 92 | + isConnected = false; | ||
| 93 | + logger.info("串口已断开连接"); | ||
| 94 | + } catch (Exception e) { | ||
| 95 | + logger.error("串口断开失败: " , e); | ||
| 96 | + } | ||
| 97 | + } | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + public boolean isConnected() { | ||
| 101 | + return isConnected; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + // 实现掉线重连逻辑 | ||
| 105 | + public void reconnect(String portName, int reconnectIntervalMillis) { | ||
| 106 | + while (!isConnected) { | ||
| 107 | + try { | ||
| 108 | + Thread.sleep(reconnectIntervalMillis); | ||
| 109 | + connect(portName); | ||
| 110 | + } catch (InterruptedException e) { | ||
| 111 | + logger.error("重连线程被中断: " , e); | ||
| 112 | + Thread.currentThread().interrupt(); | ||
| 113 | + return; | ||
| 114 | + } | ||
| 115 | + } | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + public ModbusDto sendByte(byte[] bytes) | ||
| 119 | + { | ||
| 120 | + synchronized (lock) | ||
| 121 | + { | ||
| 122 | + if(isConnected) | ||
| 123 | + { | ||
| 124 | + serialPort.writeBytes(bytes,bytes.length); | ||
| 125 | + try { | ||
| 126 | + ModbusDto reStr = dataQueue.poll(15, TimeUnit.SECONDS); | ||
| 127 | + logger.info("接串口通知数据:{}",reStr); | ||
| 128 | + return reStr; | ||
| 129 | + } catch (InterruptedException e) { | ||
| 130 | + logger.error("等待串口返回数据异常!" + e); | ||
| 131 | + disconnect(); | ||
| 132 | + } | ||
| 133 | + }else{ | ||
| 134 | + logger.error("串口未打开!" ); | ||
| 135 | + return null; | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + } | ||
| 139 | + return null; | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + private SerialPort findSerialPort(String portName) | ||
| 143 | + { | ||
| 144 | + SerialPort[] serialPorts = SerialPort.getCommPorts();//查找所有串口 | ||
| 145 | + logger.info("总串口数"+serialPorts.length); | ||
| 146 | + for(SerialPort port:serialPorts){ | ||
| 147 | + logger.info("Port:{},PortDesc:{},PortDesc:{}",port.getSystemPortName(),port.getPortDescription(),port.getDescriptivePortName());//打印串口名称,如COM4;打印串口类型,如USB Serial;打印串口的完整类型,如USB-SERIAL CH340(COM4) | ||
| 148 | + if(port.getSystemPortName().equals(portName)) | ||
| 149 | + { | ||
| 150 | + return port; | ||
| 151 | + } | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + return null; | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + public ModbusDto sendHexData(String hexStr) { | ||
| 158 | + logger.info("串口写入:{}",hexStr); | ||
| 159 | + byte[] bytes = ByteUtil.hexStringToByte(hexStr.replace(" ","").trim().toUpperCase()); | ||
| 160 | + return sendByte(bytes); | ||
| 161 | + } | ||
| 162 | +} |
-
请 注册 或 登录 后发表评论