作者 钟来

模块整理

正在显示 22 个修改的文件 包含 1168 行增加154 行删除
@@ -81,7 +81,7 @@ public class YudadaGrabTask { @@ -81,7 +81,7 @@ public class YudadaGrabTask {
81 fishPriceCollection.setCollection_source("鱼大大"); 81 fishPriceCollection.setCollection_source("鱼大大");
82 fishPriceCollection.setCollection_data(fishObject.toString()); 82 fishPriceCollection.setCollection_data(fishObject.toString());
83 83
84 - if(maxTime>time) 84 + if(maxTime>=time)
85 { 85 {
86 pageNo = -1; 86 pageNo = -1;
87 break; 87 break;
@@ -92,7 +92,10 @@ public class YudadaGrabTask { @@ -92,7 +92,10 @@ public class YudadaGrabTask {
92 logger.error("数据解析错误:"+jsonArray.get(i).toString(),e); 92 logger.error("数据解析错误:"+jsonArray.get(i).toString(),e);
93 } 93 }
94 } 94 }
95 - publicService.insertAll(fishPriceCollectionList); 95 + if(null != fishPriceCollectionList && fishPriceCollectionList.size() !=0 )
  96 + {
  97 + publicService.insertAll(fishPriceCollectionList);
  98 + }
96 99
97 } 100 }
98 } 101 }
1 package com.zhonglai.luhui.device.analysis.comm.agreement; 1 package com.zhonglai.luhui.device.analysis.comm.agreement;
2 2
  3 +import com.ruoyi.common.utils.bean.BeanUtils;
3 import com.zhonglai.luhui.device.analysis.comm.factory.BusinessAgreement; 4 import com.zhonglai.luhui.device.analysis.comm.factory.BusinessAgreement;
4 import com.zhonglai.luhui.device.analysis.comm.factory.BusinessAgreementFactory; 5 import com.zhonglai.luhui.device.analysis.comm.factory.BusinessAgreementFactory;
5 import com.zhonglai.luhui.device.analysis.comm.factory.Topic; 6 import com.zhonglai.luhui.device.analysis.comm.factory.Topic;
@@ -37,6 +37,7 @@ public class CacheServiceImpl implements CacheService { @@ -37,6 +37,7 @@ public class CacheServiceImpl implements CacheService {
37 37
38 @Override 38 @Override
39 public boolean updateCache(Topic topic, ServerDto serverDto) { 39 public boolean updateCache(Topic topic, ServerDto serverDto) {
  40 +
40 IotDevice iotDevice = serverDto.getIotDevice(); 41 IotDevice iotDevice = serverDto.getIotDevice();
41 if(null == iotDevice) 42 if(null == iotDevice)
42 { 43 {
1 package com.zhonglai.luhui.mqtt; 1 package com.zhonglai.luhui.mqtt;
2 2
  3 +import com.zhonglai.luhui.mqtt.comm.service.TerminalService;
  4 +import com.zhonglai.luhui.mqtt.service.ClienNoticeService;
3 import org.slf4j.Logger; 5 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory; 6 import org.slf4j.LoggerFactory;
  7 +import org.springframework.beans.factory.annotation.Autowired;
5 import org.springframework.boot.autoconfigure.SpringBootApplication; 8 import org.springframework.boot.autoconfigure.SpringBootApplication;
6 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 9 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
7 import org.springframework.boot.builder.SpringApplicationBuilder; 10 import org.springframework.boot.builder.SpringApplicationBuilder;
@@ -10,10 +13,10 @@ import org.springframework.context.annotation.ComponentScan; @@ -10,10 +13,10 @@ import org.springframework.context.annotation.ComponentScan;
10 13
11 @ComponentScan(basePackages = { 14 @ComponentScan(basePackages = {
12 "com.zhonglai.luhui.device.analysis", 15 "com.zhonglai.luhui.device.analysis",
  16 + "com.zhonglai.luhui.mqtt.service",
13 "com.zhonglai.luhui.mqtt.comm.service", 17 "com.zhonglai.luhui.mqtt.comm.service",
14 "com.zhonglai.luhui.mqtt.comm.rocketMq", 18 "com.zhonglai.luhui.mqtt.comm.rocketMq",
15 "com.zhonglai.luhui.mqtt.config", 19 "com.zhonglai.luhui.mqtt.config",
16 - "com.zhonglai.luhui.mqtt.service",  
17 "com.zhonglai.luhui.mqtt.controller", 20 "com.zhonglai.luhui.mqtt.controller",
18 }) 21 })
19 @SpringBootApplication(exclude= {DataSourceAutoConfiguration.class}) 22 @SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@@ -24,7 +27,6 @@ public class MqttApplication { @@ -24,7 +27,6 @@ public class MqttApplication {
24 log.info("启动服务"); 27 log.info("启动服务");
25 SpringApplicationBuilder builder = new SpringApplicationBuilder(MqttApplication.class); 28 SpringApplicationBuilder builder = new SpringApplicationBuilder(MqttApplication.class);
26 builder.run( args); 29 builder.run( args);
27 -  
28 } 30 }
29 31
30 } 32 }
@@ -6,6 +6,7 @@ import com.zhonglai.luhui.device.analysis.comm.dto.business.BusinessDtoClassNew; @@ -6,6 +6,7 @@ import com.zhonglai.luhui.device.analysis.comm.dto.business.BusinessDtoClassNew;
6 import com.zhonglai.luhui.device.analysis.comm.service.CacheService; 6 import com.zhonglai.luhui.device.analysis.comm.service.CacheService;
7 import com.zhonglai.luhui.device.analysis.comm.service.DataPersistenceService; 7 import com.zhonglai.luhui.device.analysis.comm.service.DataPersistenceService;
8 import com.zhonglai.luhui.device.analysis.comm.util.ByteUtil; 8 import com.zhonglai.luhui.device.analysis.comm.util.ByteUtil;
  9 +import com.zhonglai.luhui.device.analysis.dto.topic.OnlineDto;
9 import com.zhonglai.luhui.device.domain.IotDevice; 10 import com.zhonglai.luhui.device.domain.IotDevice;
10 import com.zhonglai.luhui.device.analysis.comm.factory.BusinessAgreement; 11 import com.zhonglai.luhui.device.analysis.comm.factory.BusinessAgreement;
11 import com.zhonglai.luhui.device.analysis.comm.factory.BusinessAgreementFactory; 12 import com.zhonglai.luhui.device.analysis.comm.factory.BusinessAgreementFactory;
@@ -104,6 +105,14 @@ public class MqttCallback implements MqttCallbackExtended { @@ -104,6 +105,14 @@ public class MqttCallback implements MqttCallbackExtended {
104 BusinessAgreement businessAgreement = businessAgreementFactory.createBusinessAgreement(topic); 105 BusinessAgreement businessAgreement = businessAgreementFactory.createBusinessAgreement(topic);
105 //解析为业务对象 106 //解析为业务对象
106 ServerDto dto = businessAgreement.analysis(topic,businessAgreement.toData(businessDto)); 107 ServerDto dto = businessAgreement.analysis(topic,businessAgreement.toData(businessDto));
  108 + if(dto instanceof OnlineDto)
  109 + {
  110 + OnlineDto onlineDto = (OnlineDto) dto;
  111 + if(1!=onlineDto.getState()) //离线
  112 + {
  113 + return;
  114 + }
  115 + }
107 if(null == dto) 116 if(null == dto)
108 { 117 {
109 terminalService.publish(TopicUtil.generateSendMessageTopic(topic),"2"); 118 terminalService.publish(TopicUtil.generateSendMessageTopic(topic),"2");
@@ -46,7 +46,7 @@ mqtt: @@ -46,7 +46,7 @@ mqtt:
46 clientId: ${random.uuid} 46 clientId: ${random.uuid}
47 #公司id 47 #公司id
48 roleid: 2 48 roleid: 2
49 - mqtt_usernames: 6_WP 49 + mqtt_usernames: 6_WP,12_BPQ,10_TLJ,NWDB_2023,WLJ_1,YWB_A700E,12_ZNZY
50 #订阅的topic 50 #订阅的topic
51 topics: ADD_POST,ALL_POST,DB_TOPIC_DISTRIBUTE,GET/+,online,PUT_REQ/+,READ_REQ/+ 51 topics: ADD_POST,ALL_POST,DB_TOPIC_DISTRIBUTE,GET/+,online,PUT_REQ/+,READ_REQ/+
52 sub_clientid: '+' 52 sub_clientid: '+'
@@ -33,5 +33,9 @@ @@ -33,5 +33,9 @@
33 <artifactId>slf4j-simple</artifactId> 33 <artifactId>slf4j-simple</artifactId>
34 </dependency> 34 </dependency>
35 35
  36 + <dependency>
  37 + <groupId>com.zhonglai.luhui</groupId>
  38 + <artifactId>ruoyi-common</artifactId>
  39 + </dependency>
36 </dependencies> 40 </dependencies>
37 </project> 41 </project>
  1 +package com.zhonglai.luhui.smart.feeder.pureness.config;
  2 +
  3 +import org.slf4j.Logger;
  4 +import org.slf4j.LoggerFactory;
  5 +
  6 +import java.io.FileInputStream;
  7 +import java.io.IOException;
  8 +import java.util.HashMap;
  9 +import java.util.Map;
  10 +import java.util.Properties;
  11 +
  12 +public class SysConfig {
  13 + private static final Logger log = LoggerFactory.getLogger(SysConfig.class);
  14 + private static Map<String,String> map = new HashMap<>();
  15 +
  16 + private void loadconfig(String configpath) throws IOException {
  17 + log.info("加载系统配置文件:{}",configpath);
  18 + Properties p = new Properties();
  19 + //创建一个字节输入流对象读取文件默认在当前项目下查找
  20 + FileInputStream in = new FileInputStream(configpath);
  21 + //Properties类的load()方法进行配置文件的加载
  22 + p.load(in);
  23 +
  24 + for(String key:p.stringPropertyNames())
  25 + {
  26 +
  27 + p.getProperty(key);
  28 +
  29 + }
  30 + }
  31 +
  32 + public static String sys_srs_push_address;
  33 + public static String sys_mp4_file_path;
  34 +
  35 + public static String mqtt_broke;
  36 + public static String mqtt_clientId;
  37 + public static String mqtt_topics;
  38 + public static String mqtt_username;
  39 + public static String mqtt_password;
  40 + public static String mqtt_client_operationTime;
  41 +
  42 +
  43 +}
1 package com.zhonglai.luhui.smart.feeder.pureness.service; 1 package com.zhonglai.luhui.smart.feeder.pureness.service;
2 2
3 -import cn.hutool.json.JSONObject; 3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.ruoyi.common.utils.ip.IpUtils;
4 import org.eclipse.paho.client.mqttv3.*; 5 import org.eclipse.paho.client.mqttv3.*;
5 import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; 6 import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
6 7
7 import org.slf4j.Logger; 8 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory; 9 import org.slf4j.LoggerFactory;
9 10
  11 +import java.io.FileInputStream;
10 import java.util.HashMap; 12 import java.util.HashMap;
11 import java.util.List; 13 import java.util.List;
12 import java.util.Map; 14 import java.util.Map;
  15 +import java.util.Properties;
13 16
14 public class TerminalService { 17 public class TerminalService {
15 private static final Logger log = LoggerFactory.getLogger(TerminalService.class); 18 private static final Logger log = LoggerFactory.getLogger(TerminalService.class);
16 19
17 private MqttClient mqttclient; 20 private MqttClient mqttclient;
18 private MqttConnectOptions options; 21 private MqttConnectOptions options;
19 -  
20 private MqttCallback mqttCallback; 22 private MqttCallback mqttCallback;
21 -  
22 private String broker; 23 private String broker;
23 private String clientId; 24 private String clientId;
24 -  
25 private List<String> topics; 25 private List<String> topics;
26 26
27 -  
28 private List<String> mqtt_usernames; 27 private List<String> mqtt_usernames;
29 28
30 private String username; 29 private String username;
31 private String password; 30 private String password;
32 31
  32 +
  33 +
33 public void startMqttListenerService() throws MqttException { 34 public void startMqttListenerService() throws MqttException {
34 log.info("-----------开始启动mqtt监听服务--------------------"); 35 log.info("-----------开始启动mqtt监听服务--------------------");
35 init(); 36 init();
@@ -39,11 +40,11 @@ public class TerminalService { @@ -39,11 +40,11 @@ public class TerminalService {
39 Map<String,Object> dmap = new HashMap<>(); 40 Map<String,Object> dmap = new HashMap<>();
40 Map<String,Object> map = new HashMap<>(); 41 Map<String,Object> map = new HashMap<>();
41 dmap.put("summary",map); 42 dmap.put("summary",map);
42 -// map.put("localhostIp",IpUtils.getLocalHost()); 43 + map.put("localhostIp", IpUtils.getLocalHost());
43 JSONObject jsonObject = new JSONObject(); 44 JSONObject jsonObject = new JSONObject();
44 jsonObject.put("0",dmap); 45 jsonObject.put("0",dmap);
45 String topic = "ADD_POST"; 46 String topic = "ADD_POST";
46 -// publish(topic,jsonObject.toJSONString()); 47 + publish(topic,jsonObject.toJSONString());
47 } 48 }
48 49
49 50
@@ -99,4 +100,5 @@ public class TerminalService { @@ -99,4 +100,5 @@ public class TerminalService {
99 log.error("关闭失败",e); 100 log.error("关闭失败",e);
100 } 101 }
101 } 102 }
  103 +
102 } 104 }
  1 +sys.srs_push_address=rtmp://119.23.218.181:21935/live/${mqtt.clientId}
  2 +sys.mp4_file_path=D:/lh-smart-feeder/2.mp4
  3 +
  4 +
  5 +mqtt.broker=tcp://175.24.61.68:1883
  6 +mqtt.clientId=70094a59d1d991d
  7 +mqtt.topics=PUT/+,GET_REQ/+, READ/+,POST_REQ/+
  8 +mqtt.username=12_ZNZY
  9 +mqtt.password=Luhui586
  10 +mqtt.client.operationTime=10
1 package com.zhonglai.luhui.smart.feeder.dto; 1 package com.zhonglai.luhui.smart.feeder.dto;
2 2
  3 +import org.bytedeco.javacv.OpenCVFrameConverter;
3 import org.opencv.core.Mat; 4 import org.opencv.core.Mat;
4 5
5 import java.io.Serializable; 6 import java.io.Serializable;
@@ -11,6 +12,16 @@ public class VeiwDto implements Serializable { @@ -11,6 +12,16 @@ public class VeiwDto implements Serializable {
11 private Integer size; //面积大小 12 private Integer size; //面积大小
12 private Double absValue; //变化的斜率 13 private Double absValue; //变化的斜率
13 14
  15 + private Integer push_camera;
  16 +
  17 + public Integer getPush_camera() {
  18 + return push_camera;
  19 + }
  20 +
  21 + public void setPush_camera(Integer push_camera) {
  22 + this.push_camera = push_camera;
  23 + }
  24 +
14 public VeiwDto(Mat frame, Integer size) { 25 public VeiwDto(Mat frame, Integer size) {
15 this.frame = frame; 26 this.frame = frame;
16 this.size = size; 27 this.size = size;
@@ -6,6 +6,7 @@ import com.zhonglai.luhui.smart.feeder.dto.VeiwDto; @@ -6,6 +6,7 @@ import com.zhonglai.luhui.smart.feeder.dto.VeiwDto;
6 import com.zhonglai.luhui.smart.feeder.service.CameraService; 6 import com.zhonglai.luhui.smart.feeder.service.CameraService;
7 import com.zhonglai.luhui.smart.feeder.service.impl.HtmllVeiwServiceImpl; 7 import com.zhonglai.luhui.smart.feeder.service.impl.HtmllVeiwServiceImpl;
8 import com.zhonglai.luhui.smart.feeder.service.impl.JFrameVeiwServiceImpl; 8 import com.zhonglai.luhui.smart.feeder.service.impl.JFrameVeiwServiceImpl;
  9 +import org.bytedeco.javacv.FrameGrabber;
9 import org.opencv.core.*; 10 import org.opencv.core.*;
10 import org.opencv.highgui.HighGui; 11 import org.opencv.highgui.HighGui;
11 import org.opencv.videoio.VideoCapture; 12 import org.opencv.videoio.VideoCapture;
@@ -13,6 +14,7 @@ import org.opencv.imgproc.Imgproc; @@ -13,6 +14,7 @@ import org.opencv.imgproc.Imgproc;
13 import org.slf4j.Logger; 14 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory; 15 import org.slf4j.LoggerFactory;
15 16
  17 +import java.io.File;
16 import java.io.IOException; 18 import java.io.IOException;
17 import java.util.ArrayList; 19 import java.util.ArrayList;
18 import java.util.Collections; 20 import java.util.Collections;
@@ -24,74 +26,49 @@ public class OpenCVUtil { @@ -24,74 +26,49 @@ public class OpenCVUtil {
24 26
25 public static void main(String[] args) { 27 public static void main(String[] args) {
26 System.out.println(DESUtil.decode("5F06AAC657B2E2B287289D25D950A829", "EXU5RUhI1"));; 28 System.out.println(DESUtil.decode("5F06AAC657B2E2B287289D25D950A829", "EXU5RUhI1"));;
27 -// OpenCVConfig.loadOpenCv(args);  
28 -// VideoCapture videoCapture = OpenCVUtil.readVideoCaptureForVideo(0);  
29 -// // 检查视频是否成功打开  
30 -// if (!videoCapture.isOpened()) {  
31 -// System.out.println("无法打开视频文件");  
32 -// return;  
33 -// }  
34 -//  
35 -// Mat previousFrame = new Mat();  
36 -// if (!videoCapture.read(previousFrame)) {  
37 -// System.out.println("无法读取视频帧");  
38 -// return;  
39 -// }  
40 -//  
41 -// JFrameVeiwServiceImpl dsplayVeiwService = new JFrameVeiwServiceImpl();  
42 -// // 逐帧处理视频  
43 -// Mat frame = new Mat();  
44 -// while (videoCapture.read(frame)) {  
45 -// dsplayVeiwService.veiw(new VeiwDto(frame,null,null));  
46 -// try {  
47 -// String str = new HtmllVeiwServiceImpl().matToString(frame,"jpg");  
48 -// System.out.println(str);  
49 -// } catch (IOException e) {  
50 -// throw new RuntimeException(e);  
51 -// }  
52 -// }  
53 } 29 }
54 30
55 public static VideoCapture readVideoCaptureForVideo(int i) 31 public static VideoCapture readVideoCaptureForVideo(int i)
56 { 32 {
57 logger.info("初始化摄像头"); 33 logger.info("初始化摄像头");
58 - // 创建VideoCapture对象  
59 - VideoCapture videoCapture = new VideoCapture();  
60 try { 34 try {
61 - Thread.sleep(1000); 35 + Thread.sleep(3000);
62 } catch (InterruptedException e) { 36 } catch (InterruptedException e) {
63 throw new RuntimeException(e); 37 throw new RuntimeException(e);
64 } 38 }
  39 + VideoCapture videoCapture = new VideoCapture();
65 boolean isopen = videoCapture.open(i); 40 boolean isopen = videoCapture.open(i);
66 if(isopen) 41 if(isopen)
67 { 42 {
68 logger.info("打开化摄像头"+i+"成功"); 43 logger.info("打开化摄像头"+i+"成功");
69 return videoCapture; 44 return videoCapture;
  45 + }else {
  46 + logger.info("打开化摄像头"+i+"失败");
70 } 47 }
71 - logger.info("打开化摄像头"+i+"失败");  
72 return null; 48 return null;
73 } 49 }
74 - 50 + private static final String MP4_FILE_PATH = "D:/lh-smart-feeder/mp4/2.mp4";
75 public static VideoCapture openCapture() 51 public static VideoCapture openCapture()
76 { 52 {
77 for(int i=0;i<10;i++) 53 for(int i=0;i<10;i++)
78 { 54 {
79 - try {  
80 - Thread.sleep(3000);  
81 - } catch (InterruptedException e) {  
82 - throw new RuntimeException(e);  
83 - }  
84 - VideoCapture videoCapture = new VideoCapture();  
85 - boolean isopen = videoCapture.open(i);  
86 - if(isopen) 55 + VideoCapture videoCapture = readVideoCaptureForVideo(i);
  56 + if(null != videoCapture)
87 { 57 {
88 - logger.info("打开化摄像头"+i+"成功");  
89 - return videoCapture;  
90 - }else {  
91 - logger.info("打开化摄像头"+i+"失败"); 58 + return videoCapture; //拿到的第一个摄像头返回
92 } 59 }
93 } 60 }
94 - throw new RuntimeException("未检测到摄像头"); 61 + logger.info("未检测到摄像头{},尝试打开本地视频",MP4_FILE_PATH);
  62 + //如果找不到摄像头就找本地视频文件
  63 + File file = new File(MP4_FILE_PATH);
  64 + if(file.exists() && file.isFile())
  65 + {
  66 + VideoCapture videoCapture = OpenCVUtil.readVideoCaptureForVideo(MP4_FILE_PATH);
  67 + return videoCapture;
  68 + }
  69 +
  70 + logger.info("未检测到摄像头!!!");
  71 + return null;
95 } 72 }
96 73
97 public static VideoCapture readVideoCaptureForVideo(String videoPath ) 74 public static VideoCapture readVideoCaptureForVideo(String videoPath )
  1 +package com.zhonglai.luhui.smart.feeder.opencv;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.bytedeco.ffmpeg.global.avcodec;
  5 +import org.bytedeco.ffmpeg.global.avutil;
  6 +import org.bytedeco.javacpp.Loader;
  7 +import org.bytedeco.javacv.*;
  8 +import org.bytedeco.opencv.opencv_core.IplImage;
  9 +import org.bytedeco.opencv.presets.opencv_objdetect;
  10 +import org.slf4j.Logger;
  11 +import org.slf4j.LoggerFactory;
  12 +
  13 +import javax.swing.*;
  14 +
  15 +/**
  16 + * @author will
  17 + * @email zq2599@gmail.com
  18 + * @date 2021/11/19 8:07 上午
  19 + * @description 功能介绍
  20 + */
  21 +public class PushCamera {
  22 + private static final Logger log = LoggerFactory.getLogger(PushCamera.class);
  23 + /**
  24 + * 保存MP4文件的完整路径(两分零五秒的视频)
  25 + */
  26 + private static final String MP4_FILE_PATH = "/Users/zhaoqin/temp/202111/21/camera.mp4";
  27 +
  28 + /**
  29 + * SRS的推流地址
  30 + */
  31 + private static final String SRS_PUSH_ADDRESS = "rtmp://192.168.50.43:11935/live/livestream";
  32 +
  33 + /**
  34 + * 摄像头序号,如果只有一个摄像头,那就是0
  35 + */
  36 + private static final int CAMERA_INDEX = 0;
  37 +
  38 + /**
  39 + * 本机窗口
  40 + */
  41 + private CanvasFrame previewCanvas;
  42 +
  43 + /**
  44 + * 帧抓取器
  45 + */
  46 + private FrameGrabber grabber;
  47 +
  48 + /**
  49 + * 帧录制器
  50 + */
  51 + private FrameRecorder recorder;
  52 +
  53 + /**
  54 + * 转换类
  55 + */
  56 + private OpenCVFrameConverter.ToIplImage converter;
  57 +
  58 + /**
  59 + * 输出帧率
  60 + */
  61 + private static final double FRAME_RATE = 30.0;
  62 +
  63 + /**
  64 + * 摄像头视频的宽
  65 + */
  66 + private int cameraImageWidth;
  67 +
  68 + /**
  69 + * 摄像头视频的高
  70 + */
  71 + private int cameraImageHeight;
  72 +
  73 + /**
  74 + * 每一次从摄像头抓取的帧都暂存在这里
  75 + */
  76 + private IplImage grabbedImage;
  77 +
  78 + /**
  79 + * 初始化帧抓取器
  80 + * @throws Exception
  81 + */
  82 + private void initGrabber() throws Exception {
  83 + // 本机摄像头默认0,这里使用javacv的抓取器,至于使用的是ffmpeg还是opencv,请自行查看源码
  84 + grabber = FrameGrabber.createDefault(CAMERA_INDEX);
  85 +
  86 + // 开启抓取器
  87 + grabber.start();
  88 + }
  89 +
  90 + /**
  91 + * 初始化帧录制器
  92 + * @throws Exception
  93 + */
  94 + private void initRecorder() throws Exception {
  95 + // 实例化帧录制器
  96 + recorder = FrameRecorder.createDefault(SRS_PUSH_ADDRESS, cameraImageWidth, cameraImageHeight);
  97 +
  98 + // 设置编码器
  99 + recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
  100 +
  101 + // 封装格式
  102 + recorder.setFormat("flv");
  103 +
  104 + // 设置帧录制器的帧率
  105 + recorder.setFrameRate(FRAME_RATE);
  106 +
  107 + // 初始化帧录制器
  108 + recorder.start();
  109 + }
  110 +
  111 + /**
  112 + * 初始化转换器
  113 + * @throws Exception
  114 + */
  115 + private void initConverter() throws Exception {
  116 + // 实例化转换器
  117 + converter = new OpenCVFrameConverter.ToIplImage();
  118 +
  119 + // 抓取一帧视频并将其转换为图像,至于用这个图像用来做什么?加水印,人脸识别等等自行添加
  120 + grabbedImage = converter.convert(grabber.grab());
  121 +
  122 + // 将视频图像的宽度存储在成员变量cameraImageWidth
  123 + cameraImageWidth = grabbedImage.width();
  124 +
  125 + // 将视频图像的高度存储在成员变量cameraImageHeight
  126 + cameraImageHeight = grabbedImage.height();
  127 + }
  128 +
  129 + /**
  130 + * 实例化、初始化窗口
  131 + */
  132 + private void initWindow() {
  133 + previewCanvas = new CanvasFrame("摄像头预览", CanvasFrame.getDefaultGamma() / grabber.getGamma());
  134 + previewCanvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  135 + previewCanvas.setAlwaysOnTop(true);
  136 + }
  137 +
  138 + /**
  139 + * 预览和推送
  140 + * @throws Exception
  141 + */
  142 + private void grabAndPush() throws Exception {
  143 + // 假设一秒钟15帧,那么两帧间隔就是(1000/15)毫秒
  144 + double interVal = 1000/ FRAME_RATE;
  145 + // 发送完一帧后sleep的时间,不能完全等于(1000/frameRate),不然会卡顿,
  146 + // 要更小一些,这里取八分之一
  147 + interVal/=8.0;
  148 +
  149 + // 不知道为什么这里不做转换就不能推到rtmp
  150 + Frame rotatedFrame;
  151 + long startTime = System.currentTimeMillis();
  152 +
  153 + while ((grabbedImage = converter.convert(grabber.grab())) != null) {
  154 + rotatedFrame = converter.convert(grabbedImage);
  155 +
  156 + // 预览窗口上显示当前帧
  157 +// previewCanvas.showImage(rotatedFrame);
  158 +
  159 + // 推送的时候,给当前帧加上时间戳
  160 + recorder.setTimestamp(1000 * (System.currentTimeMillis() - startTime));
  161 +
  162 + // 推送到SRS
  163 + recorder.record(rotatedFrame);
  164 +
  165 + Thread.sleep((int)interVal);
  166 + }
  167 + }
  168 +
  169 + /**
  170 + * 释放所有资源
  171 + * @throws Exception
  172 + */
  173 + private void safeRelease() {
  174 + if (null!= previewCanvas) {
  175 + previewCanvas.dispose();
  176 + }
  177 +
  178 + if (null!=recorder) {
  179 + try {
  180 + recorder.close();
  181 + } catch (Exception exception) {
  182 + log.error("close recorder error", exception);
  183 + }
  184 + }
  185 +
  186 + if (null!=grabber) {
  187 + try {
  188 + grabber.close();
  189 + } catch (Exception exception) {
  190 + log.error("close grabber error", exception);
  191 + }
  192 + }
  193 + }
  194 +
  195 + /**
  196 + * 整合了所有初始化操作
  197 + * @throws Exception
  198 + */
  199 + private void init() throws Exception {
  200 + long startTime = System.currentTimeMillis();
  201 +
  202 + // 设置ffmepg日志级别
  203 + avutil.av_log_set_level(avutil.AV_LOG_INFO);
  204 + FFmpegLogCallback.set();
  205 +
  206 + // 加载检测
  207 + Loader.load(opencv_objdetect.class);
  208 +
  209 + // 实例化、初始化帧抓取器
  210 + initGrabber();
  211 +
  212 + // 实例化、初始化转换工具,里面会取得摄像头图像的宽度和高度
  213 + initConverter();
  214 +
  215 + // 实例化、初始化帧录制器
  216 + initRecorder();
  217 +
  218 + // 实例化、初始化窗口
  219 +// initWindow();
  220 +
  221 + log.info("初始化完成,耗时[{}]毫秒,图像宽度[{}],图像高度[{}]",
  222 + System.currentTimeMillis()-startTime,
  223 + cameraImageWidth,
  224 + cameraImageWidth);
  225 + }
  226 +
  227 + /**
  228 + * 直播
  229 + */
  230 + public void live() {
  231 + try {
  232 + // 初始化操作
  233 + init();
  234 + // 持续拉取和推送
  235 + grabAndPush();
  236 + } catch (Exception exception) {
  237 + log.error("execute live error", exception);
  238 + } finally {
  239 + // 无论如何都要释放资源
  240 + safeRelease();
  241 + }
  242 + }
  243 +
  244 + public static void main(String[] args) {
  245 + new PushCamera().live();
  246 + }
  247 +}
  1 +package com.zhonglai.luhui.smart.feeder.opencv;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.bytedeco.ffmpeg.avcodec.AVCodecParameters;
  5 +import org.bytedeco.ffmpeg.avformat.AVFormatContext;
  6 +import org.bytedeco.ffmpeg.avformat.AVStream;
  7 +import org.bytedeco.ffmpeg.global.avcodec;
  8 +import org.bytedeco.ffmpeg.global.avutil;
  9 +import org.bytedeco.javacv.FFmpegFrameGrabber;
  10 +import org.bytedeco.javacv.FFmpegFrameRecorder;
  11 +import org.bytedeco.javacv.FFmpegLogCallback;
  12 +import org.bytedeco.javacv.Frame;
  13 +
  14 +/**
  15 + * @author willzhao
  16 + * @version 1.0
  17 + * @description 读取指定的mp4文件,推送到SRS服务器
  18 + * @date 2021/11/19 8:49
  19 + */
  20 +@Slf4j
  21 +public class PushMp4 {
  22 + /**
  23 + * 本地MP4文件的完整路径(两分零五秒的视频)
  24 + */
  25 +// private static final String MP4_FILE_PATH = "/Users/zhaoqin/temp/202111/20/sample-mp4-file.mp4";
  26 + private static final String MP4_FILE_PATH = "C:\\Users\\123\\Videos\\抖音\\莱堃科技\\20230901\\f3bb11df0711125aefdd9a16e67323fb.mp4";
  27 +
  28 + /**
  29 + * SRS的推流地址
  30 + */
  31 + private static final String SRS_PUSH_ADDRESS = "rtmp://119.23.218.181:21935/live/f3bb11df0711125aefdd9a16e67323fb";
  32 +
  33 + /**
  34 + * 读取指定的mp4文件,推送到SRS服务器
  35 + * @param sourceFilePath 视频文件的绝对路径
  36 + * @param PUSH_ADDRESS 推流地址
  37 + * @throws Exception
  38 + */
  39 + private static void grabAndPush(String sourceFilePath, String PUSH_ADDRESS) throws Exception {
  40 + // ffmepg日志级别
  41 + avutil.av_log_set_level(avutil.AV_LOG_INFO);
  42 + FFmpegLogCallback.set();
  43 +
  44 + // 实例化帧抓取器对象,将文件路径传入
  45 + FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(MP4_FILE_PATH);
  46 +
  47 + long startTime = System.currentTimeMillis();
  48 +
  49 + log.info("开始初始化帧抓取器");
  50 +
  51 + // 初始化帧抓取器,例如数据结构(时间戳、编码器上下文、帧对象等),
  52 + // 如果入参等于true,还会调用avformat_find_stream_info方法获取流的信息,放入AVFormatContext类型的成员变量oc中
  53 + grabber.start(true);
  54 +
  55 + log.info("帧抓取器初始化完成,耗时[{}]毫秒", System.currentTimeMillis()-startTime);
  56 +
  57 + // grabber.start方法中,初始化的解码器信息存在放在grabber的成员变量oc中
  58 + AVFormatContext avFormatContext = grabber.getFormatContext();
  59 +
  60 + // 文件内有几个媒体流(一般是视频流+音频流)
  61 + int streamNum = avFormatContext.nb_streams();
  62 +
  63 + // 没有媒体流就不用继续了
  64 + if (streamNum<1) {
  65 + log.error("文件内不存在媒体流");
  66 + return;
  67 + }
  68 +
  69 + // 取得视频的帧率
  70 + int frameRate = (int)grabber.getVideoFrameRate();
  71 +
  72 + log.info("视频帧率[{}],视频时长[{}]秒,媒体流数量[{}]",
  73 + frameRate,
  74 + avFormatContext.duration()/1000000,
  75 + avFormatContext.nb_streams());
  76 +
  77 + // 遍历每一个流,检查其类型
  78 + for (int i=0; i< streamNum; i++) {
  79 + AVStream avStream = avFormatContext.streams(i);
  80 + AVCodecParameters avCodecParameters = avStream.codecpar();
  81 + log.info("流的索引[{}],编码器类型[{}],编码器ID[{}]", i, avCodecParameters.codec_type(), avCodecParameters.codec_id());
  82 + }
  83 +
  84 + // 视频宽度
  85 + int frameWidth = grabber.getImageWidth();
  86 + // 视频高度
  87 + int frameHeight = grabber.getImageHeight();
  88 + // 音频通道数量
  89 + int audioChannels = grabber.getAudioChannels();
  90 +
  91 + log.info("视频宽度[{}],视频高度[{}],音频通道数[{}]",
  92 + frameWidth,
  93 + frameHeight,
  94 + audioChannels);
  95 +
  96 + // 实例化FFmpegFrameRecorder,将SRS的推送地址传入
  97 + FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(SRS_PUSH_ADDRESS,
  98 + frameWidth,
  99 + frameHeight,
  100 + audioChannels);
  101 +
  102 + // 设置编码格式
  103 + recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
  104 +
  105 + // 设置封装格式
  106 + recorder.setFormat("flv");
  107 +
  108 + // 一秒内的帧数
  109 + recorder.setFrameRate(frameRate);
  110 +
  111 + // 两个关键帧之间的帧数
  112 + recorder.setGopSize(frameRate);
  113 +
  114 + // 设置音频通道数,与视频源的通道数相等
  115 + recorder.setAudioChannels(grabber.getAudioChannels());
  116 +
  117 + startTime = System.currentTimeMillis();
  118 + log.info("开始初始化帧抓取器");
  119 +
  120 + // 初始化帧录制器,例如数据结构(音频流、视频流指针,编码器),
  121 + // 调用av_guess_format方法,确定视频输出时的封装方式,
  122 + // 媒体上下文对象的内存分配,
  123 + // 编码器的各项参数设置
  124 + recorder.start();
  125 +
  126 + log.info("帧录制初始化完成,耗时[{}]毫秒", System.currentTimeMillis()-startTime);
  127 +
  128 + Frame frame;
  129 +
  130 + startTime = System.currentTimeMillis();
  131 +
  132 + log.info("开始推流");
  133 +
  134 + long videoTS = 0;
  135 +
  136 + int videoFrameNum = 0;
  137 + int audioFrameNum = 0;
  138 + int dataFrameNum = 0;
  139 +
  140 + // 假设一秒钟15帧,那么两帧间隔就是(1000/15)毫秒
  141 + int interVal = 1000/frameRate;
  142 + // 发送完一帧后sleep的时间,不能完全等于(1000/frameRate),不然会卡顿,
  143 + // 要更小一些,这里取八分之一
  144 + interVal/=8;
  145 +
  146 + // 持续从视频源取帧
  147 + while (null!=(frame=grabber.grab())) {
  148 + videoTS = 1000 * (System.currentTimeMillis() - startTime);
  149 +
  150 + // 时间戳
  151 +// recorder.setTimestamp(videoTS);
  152 +
  153 + // 有图像,就把视频帧加一
  154 + if (null!=frame.image) {
  155 + videoFrameNum++;
  156 + }
  157 +
  158 + // 有声音,就把音频帧加一
  159 + if (null!=frame.samples) {
  160 + audioFrameNum++;
  161 + }
  162 +
  163 + // 有数据,就把数据帧加一
  164 + if (null!=frame.data) {
  165 + dataFrameNum++;
  166 + }
  167 +
  168 + // 取出的每一帧,都推送到SRS
  169 + recorder.record(frame);
  170 +
  171 + // 停顿一下再推送
  172 + Thread.sleep(interVal);
  173 + }
  174 +
  175 + log.info("推送完成,视频帧[{}],音频帧[{}],数据帧[{}],耗时[{}]秒",
  176 + videoFrameNum,
  177 + audioFrameNum,
  178 + dataFrameNum,
  179 + (System.currentTimeMillis()-startTime)/1000);
  180 +
  181 + // 关闭帧录制器
  182 + recorder.close();
  183 + // 关闭帧抓取器
  184 + grabber.close();
  185 + }
  186 +
  187 + public static void main(String[] args) throws Exception {
  188 + grabAndPush(MP4_FILE_PATH, SRS_PUSH_ADDRESS);
  189 + }
  190 +}
@@ -2,17 +2,21 @@ package com.zhonglai.luhui.smart.feeder.service; @@ -2,17 +2,21 @@ package com.zhonglai.luhui.smart.feeder.service;
2 2
3 import com.zhonglai.luhui.smart.feeder.dto.ConfigurationParameter; 3 import com.zhonglai.luhui.smart.feeder.dto.ConfigurationParameter;
4 import com.zhonglai.luhui.smart.feeder.opencv.OpenCVUtil; 4 import com.zhonglai.luhui.smart.feeder.opencv.OpenCVUtil;
  5 +import org.bytedeco.javacv.FrameGrabber;
5 import org.opencv.videoio.VideoCapture; 6 import org.opencv.videoio.VideoCapture;
6 import org.slf4j.Logger; 7 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory; 8 import org.slf4j.LoggerFactory;
8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.beans.factory.annotation.Autowired;
9 import org.springframework.stereotype.Service; 10 import org.springframework.stereotype.Service;
10 11
  12 +import java.net.DatagramSocket;
11 import java.util.concurrent.ScheduledExecutorService; 13 import java.util.concurrent.ScheduledExecutorService;
12 import java.util.concurrent.ScheduledFuture; 14 import java.util.concurrent.ScheduledFuture;
13 import java.util.concurrent.TimeUnit; 15 import java.util.concurrent.TimeUnit;
14 -  
15 - 16 +import java.net.DatagramPacket;
  17 +import java.net.InetAddress;
  18 +import java.net.MulticastSocket;
  19 +import java.io.IOException;
16 /** 20 /**
17 * 摄像头 21 * 摄像头
18 */ 22 */
@@ -118,4 +122,125 @@ public class CameraService { @@ -118,4 +122,125 @@ public class CameraService {
118 return videoIsOpen; 122 return videoIsOpen;
119 } 123 }
120 124
  125 +
  126 + public static void main(String[] args) throws Exception{
  127 +
  128 + MulticastSocket socket = null;
  129 + try {
  130 + // 创建 MulticastSocket 对象
  131 + socket = new MulticastSocket();
  132 +
  133 + // 指定多播地址和端口
  134 + InetAddress group = InetAddress.getByName("239.255.255.250");
  135 + int port = 37020;
  136 +
  137 + while (true)
  138 + {
  139 + // 创建要发送的消息
  140 + String message = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Probe><Uuid>B0F5E9C7-EBD5-4A03-99F7-B069B141C619</Uuid><Types>inquiry</Types></Probe>";
  141 + byte[] buffer = message.getBytes();
  142 +
  143 + // 创建 DatagramPacket 对象
  144 + DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, port);
  145 +
  146 + // 发送数据包
  147 + socket.send(packet);
  148 +
  149 + Thread.sleep(10000);
  150 + }
  151 +
  152 + } catch (IOException e) {
  153 + e.printStackTrace();
  154 + } finally {
  155 + if (socket != null) {
  156 + socket.close();
  157 + }
  158 + }
  159 + }
  160 +
  161 + private static void sendclien()
  162 + {
  163 + try {
  164 + // 创建组播Socket
  165 + MulticastSocket multicastSocket = new MulticastSocket();
  166 +
  167 + // 创建组播地址
  168 + InetAddress group = InetAddress.getByName("239.255.255.250");
  169 + // 发送消息
  170 + String message = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Probe><Uuid>B0F5E9C7-EBD5-4A03-99F7-B069B141C619</Uuid><Types>inquiry</Types></Probe>";
  171 + byte[] buffer = message.getBytes();
  172 + DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, 37020);
  173 + multicastSocket.send(packet);
  174 + // 关闭Socket
  175 + multicastSocket.close();
  176 + } catch (IOException e) {
  177 + e.printStackTrace();
  178 + }
  179 + }
  180 +
  181 + public static void onClien()
  182 + {
  183 + DatagramSocket socket = null;
  184 + try {
  185 + // 创建 DatagramSocket 对象,监听指定的端口
  186 + socket = new DatagramSocket(37020);
  187 +
  188 + while (true) {
  189 + // 创建 DatagramPacket 对象,用于接收数据
  190 + byte[] buffer = new byte[1024];
  191 + DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
  192 +
  193 + // 接收数据
  194 + socket.receive(packet);
  195 +
  196 + // 转换并打印接收到的数据
  197 + String received = new String(packet.getData(), 0, packet.getLength());
  198 + System.out.println("Received data: " + received);
  199 + }
  200 + } catch (IOException e) {
  201 + e.printStackTrace();
  202 + } finally {
  203 + if (socket != null) {
  204 + socket.close();
  205 + }
  206 + }
  207 + }
  208 +
  209 + public static void clien()
  210 + {
  211 + try {
  212 + // 创建组播Socket
  213 + MulticastSocket multicastSocket = new MulticastSocket(37020);
  214 +
  215 + // 加入组播地址
  216 + InetAddress group = InetAddress.getByName("239.255.255.250");
  217 + multicastSocket.joinGroup(group);
  218 +
  219 + boolean isip = true;
  220 + while (isip)
  221 + {
  222 + // 接收消息
  223 + byte[] buffer = new byte[1024];
  224 + DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
  225 + multicastSocket.receive(packet);
  226 +
  227 + // 处理消息
  228 + String message = new String(packet.getData(), packet.getOffset(), packet.getLength());
  229 + System.out.println("Received: " + message);
  230 +
  231 + if(message.indexOf("ip")>=0)
  232 + {
  233 + isip = false;
  234 + }
  235 +
  236 + }
  237 +
  238 + // 关闭Socket
  239 + multicastSocket.leaveGroup(group);
  240 + multicastSocket.close();
  241 + } catch (IOException e) {
  242 + e.printStackTrace();
  243 + }
  244 + }
  245 +
121 } 246 }
@@ -8,9 +8,11 @@ import com.zhonglai.luhui.smart.feeder.Main; @@ -8,9 +8,11 @@ import com.zhonglai.luhui.smart.feeder.Main;
8 import com.zhonglai.luhui.smart.feeder.dto.ConfigurationParameter; 8 import com.zhonglai.luhui.smart.feeder.dto.ConfigurationParameter;
9 import com.zhonglai.luhui.smart.feeder.dto.ModbusDto; 9 import com.zhonglai.luhui.smart.feeder.dto.ModbusDto;
10 import com.zhonglai.luhui.smart.feeder.dto.StateData; 10 import com.zhonglai.luhui.smart.feeder.dto.StateData;
  11 +import com.zhonglai.luhui.smart.feeder.dto.VeiwDto;
11 import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommd03Response; 12 import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommd03Response;
12 import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommdDto; 13 import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommdDto;
13 import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil; 14 import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil;
  15 +import org.eclipse.paho.client.mqttv3.MqttException;
14 import org.slf4j.Logger; 16 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory; 17 import org.slf4j.LoggerFactory;
16 import org.springframework.beans.factory.annotation.Autowired; 18 import org.springframework.beans.factory.annotation.Autowired;
@@ -43,31 +45,89 @@ public class DateListenService { @@ -43,31 +45,89 @@ public class DateListenService {
43 @Autowired 45 @Autowired
44 private ConfigurationParameterService configurationParameterService; 46 private ConfigurationParameterService configurationParameterService;
45 47
  48 + @Autowired
  49 + private FishGroupImageRecognitionService fishGroupImageRecognitionService;
  50 +
46 public void run() 51 public void run()
47 { 52 {
48 scheduledExecutorService.scheduleAtFixedRate(() -> { 53 scheduledExecutorService.scheduleAtFixedRate(() -> {
49 54
50 - if(null == configurationParameterService.getConfig(ConfigurationParameter.ifUpLoadData) || !(Boolean) configurationParameterService.getConfig(ConfigurationParameter.ifUpLoadData))  
51 - {  
52 - return; 55 + try {
  56 + gatherDevice0();
  57 + Thread.sleep(1000);
  58 + } catch (MqttException e) {
  59 + logger.error("采集主机信息失败",e);
  60 + } catch (InterruptedException e) {
  61 + throw new RuntimeException(e);
53 } 62 }
54 try { 63 try {
55 - ModbusDto modbusDto = serialPortService.sendHexData(FeederCommdUtil.readAll());  
56 - Map<String,Object> data = analysisDataService.analysis(modbusDto);  
57 - if(null != data && data.size() != 0)  
58 - {  
59 - StateData stateData = BeanUtil.mapToBean(data, StateData.class,false,null);  
60 - configurationParameterService.setStateData(stateData);  
61 -  
62 - JSONObject jsonObject = new JSONObject();  
63 - jsonObject.put("1",data);  
64 - terminalService.scheduledSubmissionData(jsonObject.toJSONString());  
65 - }  
66 - } catch (Exception e) {  
67 - logger.error("数据采集失败",e); 64 + gatherDevice1();
  65 + Thread.sleep(1000);
  66 + } catch (MqttException e) {
  67 + logger.error("采集投料机数据失败",e);
  68 + }catch (InterruptedException e) {
  69 + throw new RuntimeException(e);
  70 + }
  71 + try {
  72 + gatherDevice2();
  73 + } catch (MqttException e) {
  74 + logger.error("采集摄像头信息失败",e);
68 } 75 }
69 76
70 },1,60, TimeUnit.SECONDS); 77 },1,60, TimeUnit.SECONDS);
71 } 78 }
72 79
  80 + /**
  81 + * 采集投料机数据
  82 + */
  83 + private void gatherDevice1() throws MqttException {
  84 + if(null == configurationParameterService.getConfig(ConfigurationParameter.ifUpLoadData) || !(Boolean) configurationParameterService.getConfig(ConfigurationParameter.ifUpLoadData))
  85 + {
  86 + return;
  87 + }
  88 + ModbusDto modbusDto = serialPortService.sendHexData(FeederCommdUtil.readAll());
  89 + Map<String,Object> data = analysisDataService.analysis(modbusDto);
  90 + if(null != data && data.size() != 0)
  91 + {
  92 + StateData stateData = BeanUtil.mapToBean(data, StateData.class,false,null);
  93 + configurationParameterService.setStateData(stateData);
  94 +
  95 + JSONObject jsonObject = new JSONObject();
  96 + jsonObject.put("10_1",data);
  97 + String topic = "ALL_POST";
  98 + terminalService.publish(topic,jsonObject.toJSONString());
  99 + }
  100 + }
  101 +
  102 + /**
  103 + * 采集主机信息
  104 + */
  105 + private void gatherDevice0() throws MqttException {
  106 + Map<String, Object> map = configurationParameterService.getAll();
  107 +
  108 + if(null != map && map.size() !=0)
  109 + {
  110 + JSONObject jsonObject = new JSONObject();
  111 + jsonObject.put("0",map);
  112 + String topic = "ADD_POST";
  113 + terminalService.publish(topic,jsonObject.toJSONString());
  114 + }
  115 + }
  116 +
  117 + /**
  118 + * 采集摄像头信息
  119 + */
  120 + private void gatherDevice2() throws MqttException {
  121 + VeiwDto veiwDto = fishGroupImageRecognitionService.getVeiwDto();
  122 + if(null != veiwDto && BeanUtil.isNotEmpty(veiwDto,"size","absValue"))
  123 + {
  124 + veiwDto = BeanUtil.copyProperties(veiwDto,VeiwDto.class,"frame","binaryImage");
  125 +
  126 + JSONObject jsonObject = new JSONObject();
  127 + jsonObject.put("1_1",veiwDto);
  128 + String topic = "ALL_POST";
  129 + terminalService.publish(topic,jsonObject.toJSONString());
  130 + }
  131 +
  132 + }
73 } 133 }
@@ -6,8 +6,6 @@ import com.zhonglai.luhui.smart.feeder.dto.VeiwDto; @@ -6,8 +6,6 @@ import com.zhonglai.luhui.smart.feeder.dto.VeiwDto;
6 import com.zhonglai.luhui.smart.feeder.dto.VeiwType; 6 import com.zhonglai.luhui.smart.feeder.dto.VeiwType;
7 import com.zhonglai.luhui.smart.feeder.opencv.OpenCVUtil; 7 import com.zhonglai.luhui.smart.feeder.opencv.OpenCVUtil;
8 import com.zhonglai.luhui.smart.feeder.service.impl.HtmllVeiwServiceImpl; 8 import com.zhonglai.luhui.smart.feeder.service.impl.HtmllVeiwServiceImpl;
9 -import com.zhonglai.luhui.smart.feeder.service.impl.JFrameVeiwServiceImpl;  
10 -import io.swagger.models.auth.In;  
11 import org.opencv.core.Mat; 9 import org.opencv.core.Mat;
12 import org.opencv.core.MatOfPoint; 10 import org.opencv.core.MatOfPoint;
13 import org.opencv.core.Scalar; 11 import org.opencv.core.Scalar;
@@ -19,12 +17,10 @@ import org.slf4j.LoggerFactory; @@ -19,12 +17,10 @@ import org.slf4j.LoggerFactory;
19 import org.springframework.beans.factory.annotation.Autowired; 17 import org.springframework.beans.factory.annotation.Autowired;
20 import org.springframework.stereotype.Service; 18 import org.springframework.stereotype.Service;
21 19
22 -import javax.annotation.PostConstruct;  
23 import java.util.ArrayList; 20 import java.util.ArrayList;
24 import java.util.Arrays; 21 import java.util.Arrays;
25 import java.util.List; 22 import java.util.List;
26 import java.util.concurrent.ScheduledExecutorService; 23 import java.util.concurrent.ScheduledExecutorService;
27 -import java.util.concurrent.ScheduledFuture;  
28 import java.util.concurrent.TimeUnit; 24 import java.util.concurrent.TimeUnit;
29 25
30 /** 26 /**
@@ -37,9 +33,6 @@ public class FishGroupImageRecognitionService { @@ -37,9 +33,6 @@ public class FishGroupImageRecognitionService {
37 @Autowired 33 @Autowired
38 private CameraService cameraService; 34 private CameraService cameraService;
39 35
40 - private DisplayVeiwService dsplayVeiwService;  
41 -  
42 -  
43 @Autowired 36 @Autowired
44 private ScheduledExecutorService scheduledExecutorService; 37 private ScheduledExecutorService scheduledExecutorService;
45 38
@@ -49,43 +42,29 @@ public class FishGroupImageRecognitionService { @@ -49,43 +42,29 @@ public class FishGroupImageRecognitionService {
49 @Autowired 42 @Autowired
50 private DeviceService deviceService; 43 private DeviceService deviceService;
51 44
52 -  
53 private static Boolean isRun = false; 45 private static Boolean isRun = false;
54 46
  47 + private VeiwDto veiwDto;
55 48
56 public void run() 49 public void run()
57 { 50 {
58 scheduledExecutorService.scheduleWithFixedDelay(() -> { 51 scheduledExecutorService.scheduleWithFixedDelay(() -> {
59 if (!isRun) 52 if (!isRun)
60 { 53 {
61 - start(VeiwType.html); 54 + start();
62 } 55 }
63 },1,1,TimeUnit.SECONDS); 56 },1,1,TimeUnit.SECONDS);
64 57
65 } 58 }
66 59
67 - public void start(VeiwType veiwType) 60 + public void start()
68 { 61 {
69 if(cameraService.getVideoIsOpen()) //摄像头打开才能识别 62 if(cameraService.getVideoIsOpen()) //摄像头打开才能识别
70 { 63 {
71 isRun = true; 64 isRun = true;
72 configurationParameterService.setConfig(ConfigurationParameter.FishGroupImageRecognition,true); 65 configurationParameterService.setConfig(ConfigurationParameter.FishGroupImageRecognition,true);
73 - switch (veiwType)  
74 - {  
75 - case html:  
76 - dsplayVeiwService = new HtmllVeiwServiceImpl(configurationParameterService);  
77 - break;  
78 - case jfram:  
79 - dsplayVeiwService = new JFrameVeiwServiceImpl(configurationParameterService);  
80 - break;  
81 - default:  
82 - dsplayVeiwService = new HtmllVeiwServiceImpl(configurationParameterService);  
83 - break;  
84 - }  
85 VideoCapture videoCapture = cameraService.getVideoCapture(); 66 VideoCapture videoCapture = cameraService.getVideoCapture();
86 brightnessIdentifyFishRegion(videoCapture); 67 brightnessIdentifyFishRegion(videoCapture);
87 - }else {  
88 - logger.info("摄像头未打开");  
89 } 68 }
90 } 69 }
91 70
@@ -123,7 +102,6 @@ public class FishGroupImageRecognitionService { @@ -123,7 +102,6 @@ public class FishGroupImageRecognitionService {
123 return largestContour; 102 return largestContour;
124 } 103 }
125 104
126 -  
127 /** 105 /**
128 * 亮度查找水面,透明度过滤鱼群 106 * 亮度查找水面,透明度过滤鱼群
129 */ 107 */
@@ -140,7 +118,7 @@ public class FishGroupImageRecognitionService { @@ -140,7 +118,7 @@ public class FishGroupImageRecognitionService {
140 // 获取水域轮廓 118 // 获取水域轮廓
141 MatOfPoint largestContour = getDefaultMatOfPoint(previousFrame); 119 MatOfPoint largestContour = getDefaultMatOfPoint(previousFrame);
142 120
143 - Long time =1000l; 121 + Long time =66l;
144 if(null != configurationParameterService.getConfig(ConfigurationParameter.IdentificationFrequency)) 122 if(null != configurationParameterService.getConfig(ConfigurationParameter.IdentificationFrequency))
145 { 123 {
146 time = (Long) configurationParameterService.getConfig(ConfigurationParameter.IdentificationFrequency); 124 time = (Long) configurationParameterService.getConfig(ConfigurationParameter.IdentificationFrequency);
@@ -148,29 +126,33 @@ public class FishGroupImageRecognitionService { @@ -148,29 +126,33 @@ public class FishGroupImageRecognitionService {
148 // 逐帧处理视频 126 // 逐帧处理视频
149 Mat frame = new Mat(); 127 Mat frame = new Mat();
150 scheduledExecutorService.scheduleWithFixedDelay(() -> { 128 scheduledExecutorService.scheduleWithFixedDelay(() -> {
151 - Boolean fishGroupImageRecognition = ((Boolean)configurationParameterService.getConfig(ConfigurationParameter.FishGroupImageRecognition));  
152 - Boolean isread = videoCapture.read(frame);  
153 - logger.info("逐帧处理视频,开始处理的判断参数:鱼群图像识别是否开启 {}、摄像头是否可读取 {}",fishGroupImageRecognition,isread);  
154 - if(!isread )  
155 - {  
156 - logger.info("摄像头不可读取");  
157 - if(cameraService.getVideoIsOpen()) 129 + try {
  130 + Boolean fishGroupImageRecognition = ((Boolean)configurationParameterService.getConfig(ConfigurationParameter.FishGroupImageRecognition));
  131 + Boolean isread = videoCapture.read(frame);
  132 + logger.info("逐帧处理视频,开始处理的判断参数:鱼群图像识别是否开启 {}、摄像头是否可读取 {}",fishGroupImageRecognition,isread);
  133 + if(!isread )
158 { 134 {
159 - logger.info("重新初始化");  
160 - cameraService.clean();  
161 - }  
162 - return; 135 + logger.info("摄像头不可读取");
  136 + if(cameraService.getVideoIsOpen())
  137 + {
  138 + logger.info("重新初始化");
  139 + cameraService.clean();
  140 + }
  141 + return;
163 142
  143 + }
  144 + if (fishGroupImageRecognition && isread) {
  145 + identify(frame,largestContour);
  146 + }
  147 + }catch (Exception e)
  148 + {
  149 + logger.error("识别错误",e);
164 } 150 }
165 - if (fishGroupImageRecognition && isread) {  
166 - identify(frame,largestContour);  
167 - } 151 +
168 },0,time, TimeUnit.MILLISECONDS); 152 },0,time, TimeUnit.MILLISECONDS);
169 153
170 } 154 }
171 155
172 -  
173 -  
174 /** 156 /**
175 * 识别 157 * 识别
176 * @param frame 158 * @param frame
@@ -206,13 +188,15 @@ public class FishGroupImageRecognitionService { @@ -206,13 +188,15 @@ public class FishGroupImageRecognitionService {
206 double absValue = deviceService.controlDevice(area); 188 double absValue = deviceService.controlDevice(area);
207 configurationParameterService.setConfig(ConfigurationParameter.absValue,absValue); 189 configurationParameterService.setConfig(ConfigurationParameter.absValue,absValue);
208 190
  191 + veiwDto = new VeiwDto(frame,binaryImage,new Double(area).intValue(),absValue);
  192 +
209 // 显示图像 193 // 显示图像
210 logger.info("是否显示{},客户端数量{}",configurationParameterService.getConfig(ConfigurationParameter.ifVeiw),WebSocketClien.webSocketSet.size()); 194 logger.info("是否显示{},客户端数量{}",configurationParameterService.getConfig(ConfigurationParameter.ifVeiw),WebSocketClien.webSocketSet.size());
211 // 在图像上显示结果 195 // 在图像上显示结果
  196 + logger.info("socket数量{}",WebSocketClien.webSocketSet.size());
212 if((Boolean)configurationParameterService.getConfig(ConfigurationParameter.ifVeiw) && WebSocketClien.webSocketSet.size()>0) 197 if((Boolean)configurationParameterService.getConfig(ConfigurationParameter.ifVeiw) && WebSocketClien.webSocketSet.size()>0)
213 { 198 {
214 - logger.info("socket数量{}",WebSocketClien.webSocketSet.size());  
215 - dsplayVeiwService.veiw(new VeiwDto(frame,binaryImage,new Double(area).intValue(),absValue)); 199 + new HtmllVeiwServiceImpl(configurationParameterService).veiw(veiwDto);
216 } 200 }
217 } 201 }
218 202
@@ -267,4 +251,12 @@ public class FishGroupImageRecognitionService { @@ -267,4 +251,12 @@ public class FishGroupImageRecognitionService {
267 251
268 return binaryImage; 252 return binaryImage;
269 } 253 }
  254 +
  255 + public VeiwDto getVeiwDto() {
  256 + return veiwDto;
  257 + }
  258 +
  259 + public void setVeiwDto(VeiwDto veiwDto) {
  260 + this.veiwDto = veiwDto;
  261 + }
270 } 262 }
@@ -3,38 +3,52 @@ package com.zhonglai.luhui.smart.feeder.service; @@ -3,38 +3,52 @@ package com.zhonglai.luhui.smart.feeder.service;
3 import com.google.gson.JsonObject; 3 import com.google.gson.JsonObject;
4 import com.ruoyi.common.utils.GsonConstructor; 4 import com.ruoyi.common.utils.GsonConstructor;
5 import com.zhonglai.luhui.smart.feeder.domain.Register; 5 import com.zhonglai.luhui.smart.feeder.domain.Register;
  6 +import com.zhonglai.luhui.smart.feeder.dto.ConfigDto;
  7 +import com.zhonglai.luhui.smart.feeder.dto.VeiwDto;
6 import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommd06Response; 8 import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommd06Response;
7 import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommdDto; 9 import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommdDto;
8 import com.zhonglai.luhui.smart.feeder.dto.commd.FeederTimer; 10 import com.zhonglai.luhui.smart.feeder.dto.commd.FeederTimer;
9 import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil; 11 import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil;
10 import com.zhonglai.luhui.smart.feeder.util.PenetrateUtil; 12 import com.zhonglai.luhui.smart.feeder.util.PenetrateUtil;
11 -import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;  
12 -import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;  
13 -import org.eclipse.paho.client.mqttv3.MqttException;  
14 -import org.eclipse.paho.client.mqttv3.MqttMessage; 13 +import org.eclipse.paho.client.mqttv3.*;
15 import org.slf4j.Logger; 14 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory; 15 import org.slf4j.LoggerFactory;
17 import org.springframework.beans.factory.annotation.Autowired; 16 import org.springframework.beans.factory.annotation.Autowired;
  17 +import org.springframework.beans.factory.annotation.Value;
18 import org.springframework.stereotype.Component; 18 import org.springframework.stereotype.Component;
19 19
20 import java.util.HashMap; 20 import java.util.HashMap;
21 import java.util.List; 21 import java.util.List;
22 import java.util.Map; 22 import java.util.Map;
  23 +import java.util.concurrent.ScheduledExecutorService;
23 24
24 @Component 25 @Component
25 public class MqttCallback implements MqttCallbackExtended { 26 public class MqttCallback implements MqttCallbackExtended {
26 27
  28 + private static final Logger log = LoggerFactory.getLogger(MqttCallback.class);
27 @Autowired 29 @Autowired
28 private ConfigurationParameterService configurationParameterService; 30 private ConfigurationParameterService configurationParameterService;
29 31
30 @Autowired 32 @Autowired
31 private SerialPortService serialPortService; 33 private SerialPortService serialPortService;
32 34
33 - private static final Logger log = LoggerFactory.getLogger(MqttCallback.class); 35 + @Autowired
  36 + private SrsService srsService;
  37 +
  38 + private MqttClient mqttclient;
  39 +
  40 +
  41 + @Value("#{'${mqtt.topics}'.split(',')}")
  42 + private List<String> topics;
34 43
35 @Override 44 @Override
36 public void connectComplete(boolean b, String s) { 45 public void connectComplete(boolean b, String s) {
37 log.info("连接成功"); 46 log.info("连接成功");
  47 + try {
  48 + subscribe();
  49 + } catch (MqttException e) {
  50 + throw new RuntimeException(e);
  51 + }
38 } 52 }
39 53
40 @Override 54 @Override
@@ -42,6 +56,12 @@ public class MqttCallback implements MqttCallbackExtended { @@ -42,6 +56,12 @@ public class MqttCallback implements MqttCallbackExtended {
42 log.error("连接丢失",cause); 56 log.error("连接丢失",cause);
43 } 57 }
44 58
  59 + public MqttCallback setMqttClient(MqttClient mqttclient)
  60 + {
  61 + this.mqttclient = mqttclient;
  62 + return this;
  63 + }
  64 +
45 @Override 65 @Override
46 public void messageArrived(String topic, MqttMessage message) throws Exception { 66 public void messageArrived(String topic, MqttMessage message) throws Exception {
47 log.info("收到消息 {}",message); 67 log.info("收到消息 {}",message);
@@ -53,9 +73,9 @@ public class MqttCallback implements MqttCallbackExtended { @@ -53,9 +73,9 @@ public class MqttCallback implements MqttCallbackExtended {
53 { 73 {
54 String str = new String(bs); 74 String str = new String(bs);
55 JsonObject jsonObject = GsonConstructor.get().fromJson(str, JsonObject.class); 75 JsonObject jsonObject = GsonConstructor.get().fromJson(str, JsonObject.class);
56 - if(jsonObject.has("1")) 76 + if(jsonObject.has("10_1")) //投料机控制
57 { 77 {
58 - JsonObject controlData = jsonObject.get("1").getAsJsonObject(); 78 + JsonObject controlData = jsonObject.get("10_1").getAsJsonObject();
59 79
60 Map<Integer, FeederTimer> timerMap = new HashMap<>(); 80 Map<Integer, FeederTimer> timerMap = new HashMap<>();
61 for (String key:controlData.keySet()) 81 for (String key:controlData.keySet())
@@ -85,24 +105,23 @@ public class MqttCallback implements MqttCallbackExtended { @@ -85,24 +105,23 @@ public class MqttCallback implements MqttCallbackExtended {
85 } 105 }
86 } 106 }
87 } 107 }
88 - else if(jsonObject.has("armbian")) 108 + else if(jsonObject.has("0")) //主机
  109 + {
  110 + ConfigDto configDto = GsonConstructor.get().fromJson(jsonObject.get("0").toString(),ConfigDto.class);
  111 + configurationParameterService.setConfig(configDto.getConfigurationParameter(),configDto.getValue());
  112 + }
  113 + else if(jsonObject.has("1_1")) //探头
89 { 114 {
90 - JsonObject armbian = jsonObject.get("armbian").getAsJsonObject();  
91 - for (String key:armbian.keySet()) 115 + VeiwDto veiwDto = GsonConstructor.get().fromJson(jsonObject.get("1_1").toString(),VeiwDto.class);
  116 + if(null != veiwDto.getPush_camera())
92 { 117 {
93 - switch (key) 118 + switch (veiwDto.getPush_camera())
94 { 119 {
95 - case "penetrate":  
96 - int penetrate = armbian.get("penetrate").getAsInt();  
97 - switch (penetrate)  
98 - {  
99 - case 0:  
100 - PenetrateUtil.stop();  
101 - break;  
102 - case 1:  
103 - PenetrateUtil.start();  
104 - break;  
105 - } 120 + case 0:
  121 + srsService.stop();
  122 + break;
  123 + case 1:
  124 + srsService.run(300);
106 break; 125 break;
107 } 126 }
108 } 127 }
@@ -117,4 +136,8 @@ public class MqttCallback implements MqttCallbackExtended { @@ -117,4 +136,8 @@ public class MqttCallback implements MqttCallbackExtended {
117 // 成功发出消息 136 // 成功发出消息
118 log.info("成功发出消息 messageid{}",token); 137 log.info("成功发出消息 messageid{}",token);
119 } 138 }
  139 +
  140 + private void subscribe() throws MqttException {
  141 + mqttclient.subscribe(topics.toArray(new String[topics.size()]));
  142 + }
120 } 143 }
  1 +package com.zhonglai.luhui.smart.feeder.service;
  2 +
  3 +import com.ruoyi.common.utils.DateUtils;
  4 +import com.zhonglai.luhui.smart.feeder.config.OpenCVConfig;
  5 +import com.zhonglai.luhui.smart.feeder.draw.FishRegionPanel;
  6 +import com.zhonglai.luhui.smart.feeder.dto.VeiwDto;
  7 +import com.zhonglai.luhui.smart.feeder.opencv.OpenCVUtil;
  8 +import com.zhonglai.luhui.smart.feeder.util.OpenCVUtils;
  9 +import org.bytedeco.ffmpeg.global.avcodec;
  10 +import org.bytedeco.javacv.*;
  11 +import org.bytedeco.javacv.Frame;
  12 +import org.opencv.core.*;
  13 +import org.opencv.core.Point;
  14 +import org.opencv.imgproc.Imgproc;
  15 +import org.opencv.videoio.VideoCapture;
  16 +import org.slf4j.Logger;
  17 +import org.slf4j.LoggerFactory;
  18 +import org.springframework.beans.factory.annotation.Autowired;
  19 +import org.springframework.beans.factory.annotation.Value;
  20 +import org.springframework.stereotype.Service;
  21 +
  22 +import javax.swing.*;
  23 +import java.awt.*;
  24 +import java.awt.image.BufferedImage;
  25 +import java.util.ArrayList;
  26 +import java.util.List;
  27 +import java.util.concurrent.ScheduledExecutorService;
  28 +import java.util.concurrent.TimeUnit;
  29 +
  30 +@Service
  31 +public class SrsService {
  32 + private static final Logger log = LoggerFactory.getLogger(SrsService.class);
  33 +
  34 + private static final String MP4_FILE_PATH = "C:\\Users\\123\\Pictures\\2.mp4";
  35 + @Value("${sys.srs_push_address}")
  36 + private String SRS_PUSH_ADDRESS;
  37 +// private String SRS_PUSH_ADDRESS="rtmp://119.23.218.181:21935/live/70094a59d1d991d";
  38 + @Autowired
  39 + private ScheduledExecutorService scheduledExecutorService;
  40 +
  41 + @Autowired
  42 + private FishGroupImageRecognitionService fishGroupImageRecognitionService;
  43 +
  44 + private FFmpegFrameRecorder recorder;
  45 +
  46 + private OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();
  47 + public Frame getOpencvFrame(Mat frame)
  48 + {
  49 + return converter.convert(frame);
  50 + }
  51 +
  52 +
  53 + private boolean isPush = false;
  54 +
  55 + private int endTime = 0;
  56 + public void run(int time) throws Exception {
  57 + endTime = DateUtils.getNowTimeMilly()+time;
  58 + if(!isPush)
  59 + {
  60 + VeiwDto veiwDto = fishGroupImageRecognitionService.getVeiwDto();
  61 + init(veiwDto.getFrame().width(),veiwDto.getFrame().height()+200);
  62 + scheduledExecutorService.schedule(() -> {
  63 + while (endTime-DateUtils.getNowTimeMilly()>0)
  64 + {
  65 + Mat mat = drawChart(fishGroupImageRecognitionService.getVeiwDto().getFrame(),fishGroupImageRecognitionService.getVeiwDto().getAbsValue());
  66 + push(mat);
  67 + }
  68 + stop();
  69 + },1, TimeUnit.SECONDS);
  70 + }
  71 + }
  72 + public void stop()
  73 + {
  74 + endTime = 0;
  75 + isPush =false;
  76 + close();
  77 + }
  78 +
  79 +
  80 + public SrsService init(int frameWidth,int frameHeight) throws Exception
  81 + {
  82 + log.info("视频宽度[{}],视频高度[{}]",
  83 + frameWidth,
  84 + frameHeight
  85 + );
  86 +
  87 + // 实例化FFmpegFrameRecorder,将SRS的推送地址传入
  88 + recorder = new FFmpegFrameRecorder(SRS_PUSH_ADDRESS,
  89 + frameWidth,
  90 + frameHeight);
  91 +
  92 + // 设置编码格式
  93 + recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
  94 +
  95 + // 设置封装格式
  96 + recorder.setFormat("flv");
  97 +
  98 + // 初始化帧录制器,例如数据结构(音频流、视频流指针,编码器),
  99 + // 调用av_guess_format方法,确定视频输出时的封装方式,
  100 + // 媒体上下文对象的内存分配,
  101 + // 编码器的各项参数设置
  102 + recorder.start();
  103 +
  104 + return this;
  105 + }
  106 +
  107 + public Mat drawChart(Mat src,double area)
  108 + {
  109 + // 创建一个新的Mat对象,它的高度为200,它的宽度与原来的Mat对象相同
  110 + Mat curveArea = Mat.zeros(200, src.cols(), src.type());
  111 +
  112 + // 计算曲线的y坐标
  113 + int y = (int) (200 - (area * 200) / (src.cols() * src.rows()));
  114 +
  115 + System.out.println(y);
  116 + // 声明曲线的控制点
  117 + MatOfPoint curve = new MatOfPoint();
  118 +
  119 + // 创建曲线的控制点数组
  120 + List<Point> points = addPoint(curveArea,area);
  121 +
  122 + // 将控制点数组设置给曲线
  123 + Point[] pointArray = points.toArray(new Point[0]);
  124 + curve.fromArray(pointArray);
  125 +
  126 + // 绘制曲线
  127 + List<MatOfPoint> curveList = new ArrayList<>();
  128 + curveList.add(curve);
  129 + Imgproc.polylines(curveArea, curveList, false, new Scalar(255, 255, 255), 2);
  130 +
  131 + // 将curveArea拼接到原来的Mat对象上
  132 + Mat pushmat = new Mat();
  133 + List<Mat> mats = new ArrayList<>();
  134 + mats.add(src);
  135 + mats.add(curveArea);
  136 + Core.vconcat(mats, pushmat);
  137 + return pushmat;
  138 + }
  139 +
  140 + public void push(Mat pushmat) {
  141 + OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();
  142 + Frame frame = converter.convert(pushmat);
  143 + push(frame);
  144 + }
  145 +
  146 + public void push(Frame frame) {
  147 + // 取出的每一帧,都推送到SRS
  148 + try {
  149 + recorder.record(frame);
  150 + } catch (FrameRecorder.Exception e) {
  151 + throw new RuntimeException(e);
  152 + }
  153 + }
  154 +
  155 + public void close()
  156 + {
  157 + if(null != recorder)
  158 + {
  159 + // 关闭帧录制器
  160 + try {
  161 + recorder.close();
  162 + } catch (FrameRecorder.Exception e) {
  163 + throw new RuntimeException(e);
  164 + }
  165 + recorder = null;
  166 + }
  167 +
  168 + }
  169 + // 创建一个MatOfPoint对象来表示曲线
  170 + private List<Integer> listArea = new ArrayList<>();
  171 +
  172 + /**
  173 + * 根据反光查找水面
  174 + * @return
  175 + */
  176 + public Mat fish(Mat src) {
  177 +
  178 + //读取和预处理图像
  179 + Mat gray = new Mat();
  180 + Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY); // 转为灰度图像
  181 +
  182 + //水面反射检测
  183 + Mat threshold = new Mat();
  184 + double maxValue = 255; // 阈值
  185 + Imgproc.threshold(gray, threshold,100, maxValue, Imgproc.THRESH_BINARY); // 阈值化
  186 +
  187 + //鱼群检测
  188 + Mat hierarchy = new Mat();
  189 + List<MatOfPoint> contours = new ArrayList<>();
  190 + Imgproc.findContours(threshold, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE); // 寻找轮廓
  191 +
  192 + //计算鱼群区域大小
  193 + double area = getArea(contours);
  194 +
  195 + Mat mat = drawChart(src,area);
  196 +
  197 + return mat;
  198 + }
  199 +
  200 + private static Image convertMatToImage(Mat mat) {
  201 + BufferedImage bufferedImage = OpenCVUtils.matToBufferedImage(mat);
  202 + return bufferedImage.getScaledInstance(mat.width(), mat.height(), Image.SCALE_SMOOTH);
  203 + }
  204 +
  205 + int maxSize = 100;
  206 +
  207 + private List<Point> addPoint(Mat src, double area)
  208 + {
  209 + int panelWidth = src.width();
  210 + int panelHeight = src.height();
  211 + if(listArea.size()==maxSize)
  212 + {
  213 + listArea.remove(0);
  214 + }
  215 +
  216 + int max = new Double(area).intValue();
  217 + int min = new Double(area).intValue();
  218 + if(listArea.size()>0)
  219 + {
  220 + max = listArea.stream().max(Integer::compare).get();
  221 + min = listArea.stream().min(Integer::compare).get();
  222 + }
  223 +
  224 + List<Point> points= new ArrayList<>();
  225 +
  226 + for (int i = 0; i < listArea.size(); i++) {
  227 + int dataPoint = listArea.get(i);
  228 + int x = (int) ((double) i / listArea.size() * panelWidth);
  229 + int y = (int) ((double) (dataPoint - min) / (max - min) * panelHeight);
  230 +
  231 + if (i != 0) {
  232 + points.add(new Point(x,y));
  233 + }
  234 + }
  235 + listArea.add(new Double(area).intValue());
  236 + return points;
  237 +
  238 + }
  239 +
  240 + /**
  241 + * 计算鱼群面积
  242 + * @param contours
  243 + * @return
  244 + */
  245 + private double getArea(List<MatOfPoint> contours) {
  246 + // 找到最大区域
  247 + double maxArea = 0;
  248 + int maxAreaIndex = -1;
  249 + double allArea = 0;
  250 + for (int i = 0; i < contours.size(); i++) {
  251 + double area = Imgproc.contourArea(contours.get(i));
  252 + if (area > maxArea) {
  253 + maxArea = area;
  254 + maxAreaIndex = i;
  255 + }
  256 + allArea += area;
  257 + }
  258 +
  259 + //删除最大
  260 + if(-1 != maxAreaIndex)
  261 + {
  262 + contours.remove(maxAreaIndex);
  263 + }
  264 +
  265 + // 返回总面积
  266 + return allArea;
  267 + }
  268 +
  269 +
  270 + public static void main(String[] args) {
  271 + OpenCVConfig.loadOpenCv(args);
  272 + SrsService srsService = new SrsService();
  273 + FishRegionPanel fishRegionPanel = new FishRegionPanel();
  274 + int i=0;
  275 + while (i++<10)
  276 + {
  277 + VideoCapture videoCapture = OpenCVUtil.readVideoCaptureForVideo("");
  278 + Mat previousFrame = new Mat();
  279 + if (!videoCapture.read(previousFrame)) {
  280 + System.out.println("无法读取视频帧");
  281 + return;
  282 + }
  283 +
  284 + try {
  285 + if(null == srsService.recorder || !srsService.recorder.isInterleaved())
  286 + {
  287 + srsService.init(previousFrame.width(),previousFrame.height());
  288 + }
  289 + } catch (Exception e) {
  290 + throw new RuntimeException(e);
  291 + }
  292 +
  293 + Mat src = new Mat();
  294 + while (videoCapture.read(src))
  295 + {
  296 + Mat mat = srsService.fish(src);
  297 + fishRegionPanel.getLblImage().setIcon(new ImageIcon(convertMatToImage(mat)));
  298 + fishRegionPanel.getFrame().repaint();
  299 + OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();
  300 + Frame frame = converter.convert(mat);
  301 + srsService.push(frame);
  302 + }
  303 +
  304 + }
  305 + srsService.close();
  306 +
  307 + }
  308 +}
@@ -37,13 +37,6 @@ public class TerminalService { @@ -37,13 +37,6 @@ public class TerminalService {
37 @Value("${mqtt.clientId}") 37 @Value("${mqtt.clientId}")
38 private String clientId; 38 private String clientId;
39 39
40 - @Value("#{'${mqtt.topics}'.split(',')}")  
41 - private List<String> topics;  
42 -  
43 -  
44 - @Value("#{'${mqtt.mqtt_usernames}'.split(',')}")  
45 - private List<String> mqtt_usernames;  
46 -  
47 @Value("${mqtt.username}") 40 @Value("${mqtt.username}")
48 private String username; 41 private String username;
49 @Value("${mqtt.password}") 42 @Value("${mqtt.password}")
@@ -53,7 +46,6 @@ public class TerminalService { @@ -53,7 +46,6 @@ public class TerminalService {
53 log.info("-----------开始启动mqtt监听服务--------------------"); 46 log.info("-----------开始启动mqtt监听服务--------------------");
54 init(); 47 init();
55 connect(); 48 connect();
56 - subscribe();  
57 49
58 Map<String,Object> dmap = new HashMap<>(); 50 Map<String,Object> dmap = new HashMap<>();
59 Map<String,Object> map = new HashMap<>(); 51 Map<String,Object> map = new HashMap<>();
@@ -76,7 +68,7 @@ public class TerminalService { @@ -76,7 +68,7 @@ public class TerminalService {
76 options.setConnectionTimeout(15); 68 options.setConnectionTimeout(15);
77 //设置断开后重新连接 69 //设置断开后重新连接
78 options.setAutomaticReconnect(true); 70 options.setAutomaticReconnect(true);
79 - mqttclient.setCallback(mqttCallback); 71 + mqttclient.setCallback(mqttCallback.setMqttClient(mqttclient));
80 } 72 }
81 73
82 private void connect() throws MqttException { 74 private void connect() throws MqttException {
@@ -85,10 +77,6 @@ public class TerminalService { @@ -85,10 +77,6 @@ public class TerminalService {
85 mqttclient.connect(options); 77 mqttclient.connect(options);
86 } 78 }
87 79
88 - public void subscribe() throws MqttException {  
89 - mqttclient.subscribe(topics.toArray(new String[topics.size()]));  
90 - }  
91 -  
92 public void publish(String topic, MqttMessage message) throws MqttException { 80 public void publish(String topic, MqttMessage message) throws MqttException {
93 mqttclient.publish(topic,message); 81 mqttclient.publish(topic,message);
94 } 82 }
@@ -118,4 +106,5 @@ public class TerminalService { @@ -118,4 +106,5 @@ public class TerminalService {
118 log.error("关闭失败",e); 106 log.error("关闭失败",e);
119 } 107 }
120 } 108 }
  109 +
121 } 110 }
  1 +package com.zhonglai.luhui.smart.feeder.service.impl;
  2 +
  3 +import com.zhonglai.luhui.smart.feeder.dto.VeiwDto;
  4 +import com.zhonglai.luhui.smart.feeder.service.ConfigurationParameterService;
  5 +import com.zhonglai.luhui.smart.feeder.service.DisplayVeiwService;
  6 +
  7 +public class SrsVeiwServiceImpl implements DisplayVeiwService {
  8 + private ConfigurationParameterService configurationParameterService;
  9 +
  10 + public SrsVeiwServiceImpl(ConfigurationParameterService configurationParameterService) {
  11 + this.configurationParameterService = configurationParameterService;
  12 + }
  13 + @Override
  14 + public void veiw(VeiwDto veiwDto) {
  15 +
  16 + }
  17 +}
1 -# 开发环境配置 server: # 服务器的HTTP端口,默认为8080 port: 8064 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # 连接数满后的排队数,默认为100 accept-count: 1000 threads: # tomcat最大线程数,默认为200 max: 800 # Tomcat启动初始化的线程数,默认值10 min-spare: 100 # 日志配置 logging: level: com.ruoyi: debug org.springframework: warn # Swagger配置 swagger: # 是否开启swagger enabled: true # 请求前缀 pathMapping: /dev-api # 防止XSS攻击 xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* sys: staticPath: "file:/opt/lh-smart-feeder/lh-smart-feeder/html/" # MyBatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain,com.zhonglai.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml # 数据源配置 spring: # autoconfigure: # exclude: org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: org.sqlite.JDBC druid: # 主库数据源 master: url: jdbc:sqlite:db/my.db username: password: # 从库数据源 slave: # 从数据源开关/默认关闭 enabled: false url: username: password: # 初始连接数 initialSize: 5 # 最小连接池数量 minIdle: 10 # 最大连接池数量 maxActive: 20 # 配置获取连接等待超时的时间 maxWait: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 timeBetweenEvictionRunsMillis: 60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 minEvictableIdleTimeMillis: 300000 # 配置一个连接在池中最大生存的时间,单位是毫秒 maxEvictableIdleTimeMillis: 900000 # 配置检测连接是否有效 validationQuery: SELECT 1 testWhileIdle: true testOnBorrow: false testOnReturn: false webStatFilter: enabled: true statViewServlet: enabled: true # 设置白名单,不填则允许所有访问 allow: url-pattern: /druid/* # 控制台管理用户名和密码 login-username: ruoyi login-password: 123456 filter: stat: enabled: true # 慢SQL记录 log-slow-sql: true slow-sql-millis: 1000 merge-sql: true wall: config: multi-statement-allow: true ## 数据源配置 #spring: # datasource: # type: com.alibaba.druid.pool.DruidDataSource # driverClassName: com.mysql.cj.jdbc.Driver # druid: # # 主库数据源 # master: # url: jdbc:mysql://rm-wz9740un21f09iokuao.mysql.rds.aliyuncs.com:3306/mqtt_broker?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 # username: luhui # password: Luhui586 # # 从库数据源 # slave: # # 从数据源开关/默认关闭 # enabled: true # url: jdbc:mysql://119.23.218.181:3306/lh-server-ops?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 # username: luhui # password: Luhui586 # # 初始连接数 # initialSize: 5 # # 最小连接池数量 # minIdle: 10 # # 最大连接池数量 # maxActive: 20 # # 配置获取连接等待超时的时间 # maxWait: 60000 # # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 # timeBetweenEvictionRunsMillis: 60000 # # 配置一个连接在池中最小生存的时间,单位是毫秒 # minEvictableIdleTimeMillis: 300000 # # 配置一个连接在池中最大生存的时间,单位是毫秒 # maxEvictableIdleTimeMillis: 900000 # # 配置检测连接是否有效 # validationQuery: SELECT 1 FROM DUAL # testWhileIdle: true # testOnBorrow: false # testOnReturn: false # webStatFilter: # enabled: true # statViewServlet: # enabled: true # # 设置白名单,不填则允许所有访问 # allow: # url-pattern: /druid/* # # 控制台管理用户名和密码 # login-username: ruoyi # login-password: 123456 # filter: # stat: # enabled: true # # 慢SQL记录 # log-slow-sql: true # slow-sql-millis: 1000 # merge-sql: true # wall: # config: # multi-statement-allow: true mqtt: #链接地址 broker: tcp://175.24.61.68:1883 #唯一标识 clientId: 70094a59d1d991d #公司id roleid: 2 mqtt_usernames: 12_ZNZY #订阅的topic topics: PUT/+,GET_REQ/+, READ/+,POST_REQ/+ username: 12_ZNZY password: Luhui586 client: #客户端操作时间 operationTime: 10  
  1 +# 开发环境配置 server: # 服务器的HTTP端口,默认为8080 port: 8064 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # 连接数满后的排队数,默认为100 accept-count: 1000 threads: # tomcat最大线程数,默认为200 max: 800 # Tomcat启动初始化的线程数,默认值10 min-spare: 100 # 日志配置 logging: level: com.ruoyi: debug org.springframework: warn # Swagger配置 swagger: # 是否开启swagger enabled: true # 请求前缀 pathMapping: /dev-api # 防止XSS攻击 xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* sys: staticPath: "file:/opt/lh-smart-feeder/lh-smart-feeder/html/" srs_push_address: rtmp://119.23.218.181:21935/live/${mqtt.clientId} mp4_file_path: D:/lh-smart-feeder/2.mp4 # MyBatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain,com.zhonglai.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml # 数据源配置 spring: # autoconfigure: # exclude: org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: org.sqlite.JDBC druid: # 主库数据源 master: url: jdbc:sqlite:db/my.db username: password: # 从库数据源 slave: # 从数据源开关/默认关闭 enabled: false url: username: password: # 初始连接数 initialSize: 5 # 最小连接池数量 minIdle: 10 # 最大连接池数量 maxActive: 20 # 配置获取连接等待超时的时间 maxWait: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 timeBetweenEvictionRunsMillis: 60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 minEvictableIdleTimeMillis: 300000 # 配置一个连接在池中最大生存的时间,单位是毫秒 maxEvictableIdleTimeMillis: 900000 # 配置检测连接是否有效 validationQuery: SELECT 1 testWhileIdle: true testOnBorrow: false testOnReturn: false webStatFilter: enabled: true statViewServlet: enabled: true # 设置白名单,不填则允许所有访问 allow: url-pattern: /druid/* # 控制台管理用户名和密码 login-username: ruoyi login-password: 123456 filter: stat: enabled: true # 慢SQL记录 log-slow-sql: true slow-sql-millis: 1000 merge-sql: true wall: config: multi-statement-allow: true mqtt: #链接地址 broker: tcp://175.24.61.68:1883 #唯一标识 clientId: 70094a59d1d991d #订阅的topic topics: PUT/+,GET_REQ/+, READ/+,POST_REQ/+ username: 12_ZNZY password: Luhui586 client: #客户端操作时间 operationTime: 10