作者 钟来

模块整理

正在显示 58 个修改的文件 包含 1683 行增加2623 行删除

要显示太多修改。

为保证性能只显示 58 of 58+ 个文件。

... ... @@ -20,26 +20,7 @@
<dependency>
<groupId>com.zhonglai.luhui</groupId>
<artifactId>ruoyi-framework</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>com.zhonglai.luhui</groupId>
<artifactId>lh-common-swagger</artifactId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bytedeco/opencv -->
... ... @@ -63,29 +44,10 @@
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- sqlite -->
<dependency>
<groupId>com.zhonglai.luhui</groupId>
<artifactId>ruoyi-framework</artifactId>
</dependency>
<dependency>
<groupId>com.zhonglai.luhui</groupId>
<artifactId>lh-common-datasource</artifactId>
</dependency>
<dependency>
<groupId>com.zhonglai.luhui</groupId>
<artifactId>lh-public-dao</artifactId>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.21.0.1</version>
</dependency>
<!-- mqtt -->
<!-- nio -->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
... ... @@ -99,6 +61,10 @@
<artifactId>jSerialComm</artifactId>
<version>2.10.3</version>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
</dependencies>
<build>
... ...
package com.zhonglai.luhui.smart.feeder;
import com.ruoyi.framework.config.ResourcesConfig;
import com.zhonglai.luhui.smart.feeder.config.OpenCVConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.zhonglai.luhui.smart.feeder.service.InitService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.scheduling.annotation.EnableScheduling;
@ComponentScan(basePackages = {
"com.ruoyi.common",
"com.ruoyi.framework",
"com.zhonglai.luhui.datasource",
"com.zhonglai.luhui.dao",
"com.zhonglai.luhui.smart.feeder",
}
,excludeFilters = {@ComponentScan.Filter(type= FilterType.ASSIGNABLE_TYPE,classes = {ResourcesConfig.class})}
)
@EnableScheduling
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class})
public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
logger.info("开始启动服务器");
OpenCVConfig.loadOpenCv(args);
SpringApplication.run(Main.class,args);
//配置参数
logger.info("配置参数");
InitService.initConfig();
logger.info("启动服务");
InitService.startService();
logger.info("启动服务器结束");
}
}
\ No newline at end of file
... ...
package com.zhonglai.luhui.smart.feeder.config;
public interface IfOperatingDataValueIsNotNull {
public void exeValue(String fieldname,Object fieldObject);
}
... ...
package com.zhonglai.luhui.smart.feeder.config;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.smart.feeder.dto.*;
import com.zhonglai.luhui.smart.feeder.dto.commd.FeederBackstateTtpe;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.DevicedatRequest;
import com.zhonglai.luhui.smart.feeder.service.InitService;
import com.zhonglai.luhui.smart.feeder.util.FeederCommd06ResponseType;
import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil;
import com.zhonglai.luhui.smart.feeder.util.MessageUtil;
import java.lang.reflect.Field;
/**
* 运行数据
... ... @@ -9,6 +18,48 @@ public class OperatingData {
public static SysConfig sysConfig = new SysConfig(); //系统配置
public static CameraData cameraData = new CameraData(); //摄像头数据
public static CameraConfig cameraConfig = new CameraConfig() ; //摄像头配置
public static FeederData feederData = new FeederData() ; //投料机数据
public static DevicedatRequest devicedat = new DevicedatRequest() ; //投料机数据
public static FeederConfig feederConfig = new FeederConfig() ; //投料机配置
public static RegisterConfig registerConfig = new RegisterConfig(); //数据解析字典
public static void setClassObjecValue(Object value,IfOperatingDataValueIsNotNull ifOperatingDataValueIsNotNull) throws IllegalAccessException {
if(null != value)
{
OperatingDataType operatingDataType = getOperatingDataType(value);
Class cls = value.getClass();
Field[] fields = cls.getDeclaredFields();
for(Field field:fields)
{
field.setAccessible(true);
Object object = field.get(value);
if(null != object)
{
operatingDataType.setValue(field,object);
ifOperatingDataValueIsNotNull.exeValue(field.getName(),object);
}
}
}
}
public static OperatingDataType getOperatingDataType(Object value)
{
if(value instanceof SysConfig)
{
return sysConfig;
}else
if(value instanceof CameraConfig)
{
return cameraConfig;
}else
if(value instanceof FeederConfig)
{
return feederConfig;
}else
if(value instanceof RegisterConfig)
{
return registerConfig;
}
return null;
}
}
... ...
package com.zhonglai.luhui.smart.feeder.config;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 通用配置
*
* @author ruoyi
*/
@Configuration
public class ResourcesConfig implements WebMvcConfigurer
{
@Value("${sys.staticPath}")
private String staticPath;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
/** 本地文件上传路径 */
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
.addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
registry.addResourceHandler( "/camera/**")
.addResourceLocations(staticPath);
/** swagger配置 */
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
}
/**
* 跨域配置
*/
@Bean
public CorsFilter corsFilter()
{
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// 设置访问源地址
config.addAllowedOriginPattern("*");
// 设置访问源请求头
config.addAllowedHeader("*");
// 设置访问源请求方法
config.addAllowedMethod("*");
// 有效期 1800秒
config.setMaxAge(1800L);
// 添加映射路径,拦截一切请求
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
// 返回新的CorsFilter
return new CorsFilter(source);
}
}
\ No newline at end of file
package com.zhonglai.luhui.smart.feeder.config;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
public class ScheduledConfig {
public final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5);
}
... ...
package com.zhonglai.luhui.smart.feeder.config;
import com.ruoyi.common.config.RuoYiConfig;
import com.zhonglai.luhui.smart.feeder.config.v2apibug.ResponseFilter;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
/** 系统基础配置 */
@Autowired
private RuoYiConfig ruoyiConfig;
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}
/**
* 添加摘要信息
*/
private ApiInfo apiInfo()
{
// 用ApiInfoBuilder进行定制
return new ApiInfoBuilder()
// 设置标题
.title("标题:智能投料机")
// 描述
.description("描述:智能投料机")
// 作者信息
.contact(new Contact(ruoyiConfig.getName(), null, null))
// 版本
.version("版本号:" + ruoyiConfig.getVersion())
.build();
}
/**
// * 解决/v2/api-docs返回多了一层value的问题
// * @return
// */
// @Bean
// public FilterRegistrationBean someFilterRegistration() {
// FilterRegistrationBean registration = new FilterRegistrationBean();
// registration.setFilter(new ResponseFilter());
// // 过滤的地址
// registration.addUrlPatterns("/v2/api-docs");
// return registration;
// }
}
\ No newline at end of file
package com.zhonglai.luhui.smart.feeder.config;
import com.zhonglai.luhui.smart.feeder.service.WebSocketSever;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.websocket.Session;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
public class WebSocketClien {
private static final Logger log = LoggerFactory.getLogger(WebSocketSever.class);
// session集合,存放对应的session
public static ConcurrentHashMap<Integer, Session> sessionPool = new ConcurrentHashMap<>();
// concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。
public static CopyOnWriteArraySet<WebSocketSever> webSocketSet = new CopyOnWriteArraySet<>();
public static boolean login(Integer userId)
{
try {
Session historySession = sessionPool.get(userId);
// historySession不为空,说明已经有人登陆账号,应该删除登陆的WebSocket对象
if (historySession != null) {
webSocketSet.remove(historySession);
historySession.close();
}
return true;
} catch (IOException e) {
log.error("重复登录异常,错误信息:" + e.getMessage(), e);
return false;
}
}
public static void close(Integer userId)
{
try {
Session historySession = sessionPool.get(userId);
// historySession不为空,说明已经有人登陆账号,应该删除登陆的WebSocket对象
if (historySession != null) {
webSocketSet.remove(historySession);
historySession.close();
}
} catch (IOException e) {
log.error("关闭连接,错误信息:" + e.getMessage(), e);
}
}
}
package com.zhonglai.luhui.smart.feeder.config;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
@Configuration
public class WebSocketConfig implements ServletContextInitializer {
/**
* 这个bean的注册,用于扫描带有@ServerEndpoint的注解成为websocket,如果你使用外置的tomcat就不需要该配置文件
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
}
}
package com.zhonglai.luhui.smart.feeder.config.manager;
import com.ruoyi.common.utils.Threads;
import com.ruoyi.common.utils.spring.SpringUtils;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 异步任务管理器
*
* @author ruoyi
*/
public class AsyncManager
{
/**
* 异步操作任务调度线程池
*/
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
/**
* 单例模式
*/
private AsyncManager(){}
private static AsyncManager me = new AsyncManager();
public static AsyncManager me()
{
return me;
}
/**
* 停止任务线程池
*/
public void shutdown()
{
Threads.shutdownAndAwaitTermination(executor);
}
}
package com.zhonglai.luhui.smart.feeder.config.manager;
import com.zhonglai.luhui.smart.feeder.service.SrsService;
import com.zhonglai.luhui.smart.feeder.service.EhCacheService;
import com.zhonglai.luhui.smart.feeder.service.device.SerialPortService;
import com.zhonglai.luhui.smart.feeder.service.TerminalService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
/**
* 确保应用退出时能关闭后台线程
*
* @author ruoyi
*/
@Component
public class ShutdownManager
{
private static final Logger logger = LoggerFactory.getLogger(ShutdownManager.class);
@Autowired
private EhCacheService ehCacheService;
@Autowired
private SerialPortService serialPortService;
@Autowired
private TerminalService terminalService;
@Autowired
private SrsService srsService;
@PreDestroy
public void destroy()
{
terminalService.close();
serialPortService.close();
ehCacheService.shutdown();
srsService.stop();
shutdownAsyncManager();
}
/**
* 停止异步执行任务
*/
private void shutdownAsyncManager()
{
try
{
logger.info("====关闭后台任务任务线程池111====");
AsyncManager.me().shutdown();
}
catch (Exception e)
{
logger.error(e.getMessage(), e);
}
}
}
package com.zhonglai.luhui.smart.feeder.config.v2apibug;
import com.google.gson.Gson;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class ResponseFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 这里需要重写ResponseWrapper,因为原方法是没有获取返回值的功能
ResponseWrapper wrapperResponse = new ResponseWrapper((HttpServletResponse) response);
// 这里只拦截返回,直接让请求过去,如果在请求前有处理,可以在这里处理
chain.doFilter(request, wrapperResponse);
byte[] content = wrapperResponse.getContent();//获取返回值
// 判断是否有值
if (content.length > 0) {
// 这里是返回的内容
String str = new String(content, "UTF-8");
System.out.println("拦截的返回值:" + str);
try {
if(str.startsWith("{\"value\""))
{
Gson gson = new Gson();
Map<String,Object> map = gson.fromJson(str, HashMap.class);
response.getWriter().println(map.get("value"));
}else{
response.getWriter().write(str);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
response.getWriter().flush();
}
}
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
package com.zhonglai.luhui.smart.feeder.config.v2apibug;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class ResponseWrapper extends HttpServletResponseWrapper {
private ByteArrayOutputStream buffer;
private ServletOutputStream out;
public ResponseWrapper(HttpServletResponse httpServletResponse) {
super(httpServletResponse);
buffer = new ByteArrayOutputStream();
out = new WrapperOutputStream(buffer);
}
@Override
public ServletOutputStream getOutputStream()
throws IOException {
return out;
}
@Override
public void flushBuffer()
throws IOException {
if (out != null) {
out.flush();
}
}
public byte[] getContent()
throws IOException {
flushBuffer();
return buffer.toByteArray();
}
class WrapperOutputStream extends ServletOutputStream {
private ByteArrayOutputStream bos;
public WrapperOutputStream(ByteArrayOutputStream bos) {
this.bos = bos;
}
@Override
public void write(int b)
throws IOException {
bos.write(b);
}
@Override
public boolean isReady() {
// TODO Auto-generated method stub
return false;
}
@Override
public void setWriteListener(WriteListener arg0) {
// TODO Auto-generated method stub
}
}
}
package com.zhonglai.luhui.smart.feeder.controller;
import com.ruoyi.common.core.domain.AjaxResult;
import com.zhonglai.luhui.smart.feeder.config.WebSocketClien;
import com.zhonglai.luhui.smart.feeder.dto.ModbusDto;
import com.zhonglai.luhui.smart.feeder.service.DeviceService;
import com.zhonglai.luhui.smart.feeder.util.FeederCommd06ResponseType;
import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
@Api(tags = "摄像头功能")
@RestController
@RequestMapping("/camera")
public class CameraController {
@Autowired
private DeviceService deviceService;
@ApiOperation("关闭连接")
@GetMapping("/discon/{userId}")
public AjaxResult discon( @PathVariable(value = "userId") Integer userId)
{
WebSocketClien.close(userId);
return AjaxResult.success();
}
}
package com.zhonglai.luhui.smart.feeder.controller;
import com.ruoyi.common.core.domain.AjaxResult;
import com.zhonglai.luhui.dao.service.PublicService;
import com.zhonglai.luhui.smart.feeder.dto.ConfigDto;
import com.zhonglai.luhui.smart.feeder.service.ConfigurationParameterService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@Api(tags = "配置")
@RestController
@RequestMapping("/config")
public class ConfigController {
@Autowired
private PublicService publicService;
@Autowired
private ConfigurationParameterService configurationParameterService;
@ApiOperation("获取配置所有参数")
@GetMapping("/all")
public AjaxResult all()
{
AjaxResult ajaxResult = AjaxResult.success();
Map<String, Object> cache = configurationParameterService.getAll();
for (String key:cache.keySet()) {
// Process the key and value as needed.
ajaxResult.put(key,cache.get(key));
}
return ajaxResult;
}
@ApiOperation("参数配置")
@PostMapping("/set")
public AjaxResult set(@RequestBody ConfigDto configDto)
{
configurationParameterService.setConfig(configDto.getConfigurationParameter(),configDto.getValue());
return AjaxResult.success();
}
@ApiOperation("执行sqlite")
@PostMapping("/extsql")
public AjaxResult extsql(String sql)
{
List<Map<String,Object>> list = publicService.getObjectListBySQL(sql);
return AjaxResult.success(list);
}
}
package com.zhonglai.luhui.smart.feeder.controller;
import com.ruoyi.common.core.domain.AjaxResult;
import com.zhonglai.luhui.smart.feeder.dto.commd.*;
import com.zhonglai.luhui.smart.feeder.service.device.SerialPortService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@Api(tags = "串口管理")
@RestController
@RequestMapping("/serialPort")
public class SerialPortController {
@Autowired
private SerialPortService serialPortService;
@ApiOperation("打开")
@PostMapping("/open")
public AjaxResult open(Integer baudrate)
{
return AjaxResult.success(serialPortService.open());
}
@ApiOperation("发送16进制")
@GetMapping("/sendHexData")
public AjaxResult sendHexData(String hexStr)
{
return AjaxResult.success(serialPortService.sendHexData(hexStr));
}
@ApiOperation("发送字符串")
@GetMapping("/sendStrData")
public AjaxResult sendStrData(String str)
{
return AjaxResult.success(serialPortService.sendStrData(str));
}
@ApiOperation("读取")
@GetMapping("/read")
public AjaxResult read(Integer start_char,Integer char_lenth)
{
return AjaxResult.success(serialPortService.sendHexData(new FeederCommdDto(new FeederCommd03Response(start_char,char_lenth)).getHstr()));
}
@ApiOperation("单独写入")
@GetMapping("/write")
public AjaxResult write(Integer register_address,Integer value)
{
return AjaxResult.success(serialPortService.sendHexData(new FeederCommdDto(new FeederCommd06Response(register_address,value)).getHstr()));
}
}
... ... @@ -13,4 +13,18 @@ public class Register {
public Integer char_lenth;
public String field_name;
public String clas;
public Register()
{
}
public Register(Integer address, String name, Integer start_char, Integer char_lenth, String field_name, String clas) {
this.address = address;
this.name = name;
this.start_char = start_char;
this.char_lenth = char_lenth;
this.field_name = field_name;
this.clas = clas;
}
}
... ...
... ... @@ -3,15 +3,12 @@ package com.zhonglai.luhui.smart.feeder.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.lang.reflect.Field;
import java.util.ArrayList;
@Data
@Accessors(chain = true) //链式写法
public class CameraConfig {
/**
* 摄像头编号
*/
private Integer captureNumber;
public class CameraConfig implements OperatingDataType{
/**
* 摄像头接口类型
... ... @@ -21,25 +18,77 @@ public class CameraConfig {
private String cameraInterfaceType;
/**
* 反光阈值
* 动态像素的最小值
* 阈值,函数根据这个阈值将输入图像的像素分为两类。所有强度大于或等于该阈值的像素都设置为最大值(在本例中为255),所有其他像素都设置为0。
*/
private Integer reflectionThreshold;
private Integer trendsPixelMin;
/**
* 去噪调整内核大小,用来消除小的物体或噪声
* 动态像素的最大值
* 用于阈值化的最大值。当阈值类型为THRESH_BINARY或THRESH_BINARY_INV时,这个值对应于超过阈值的强度。
*/
private Integer kernelSize;
private Integer trendsPixelMax;
/**
* 标注框的最小宽度
*/
private Integer calloutBoxWidthMin;
/**
* 过滤反光的最小值
*/
private Integer reflectionMin;
/**
* 过滤反光的最大值
*/
private Integer reflectionMax;
/**
* 过滤亮度的最小值
*/
private Integer brightnessMin;
/**
* 过滤亮度的最大值
*/
private Integer brightnessMax;
/**
* 最大反光阈
* 过滤透明度的最小
*/
private Integer maxValue;
private Integer transparencyMeasureMin;
/**
* 过滤透明度的最大值
*/
private Integer transparencyMeasureMax;
/**
* 过滤面积的最小值
*/
private Integer areaMin;
/**
* 过滤面积的最大值
*/
private Integer areaMax;
/**
* 去噪调整内核大小,用来消除小的物体或噪声
*/
private Integer kernelSize;
/**
* 斜率范围对应的档位
*/
private ArrayList<FishCurveControlCondition> absValue_command;
/**
* 是否显示原图
*/
private Boolean veiwDto_isFrame;
/**
* 是否显示临时图
*/
... ... @@ -67,4 +116,41 @@ public class CameraConfig {
* 鱼群图像识别投料控制是否开启
*/
private Boolean feedingControl;
public CameraConfig creteDefault()
{
this.cameraInterfaceType = "RTSP";
this.trendsPixelMin = 150;
this.trendsPixelMax = 200;
this.calloutBoxWidthMin = 5;
this.reflectionMin = 150;
this.reflectionMax = 200;
this.brightnessMin = 100;
this.brightnessMax = 150;
this.transparencyMeasureMin = 100;
this.transparencyMeasureMax = 150;
this.areaMin = 25;
this.areaMax = 100;
this.kernelSize = 3;
absValue_command = new ArrayList<>();
absValue_command.add(new FishCurveControlCondition(8590,1));
absValue_command.add(new FishCurveControlCondition(9590,2));
absValue_command.add(new FishCurveControlCondition(10590,3));
absValue_command.add(new FishCurveControlCondition(11590,4));
this.veiwDto_isFrame = false;
this.veiwDto_isBinaryImage = false;
this.veiwDto_isSize = false;
this.veiwDto_isAbsValue = false;
this.identificationFrequency = 1000l;
this.fishGroupImageRecognition = true;
this.feedingControl = true;
return this;
}
@Override
public void setValue(Field field, Object value) throws IllegalAccessException {
field.set(this,value);
}
}
... ...
... ... @@ -3,22 +3,75 @@ package com.zhonglai.luhui.smart.feeder.dto;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 摄像头数据
*/
@Data
@Accessors(chain = true) //链式写法
public class CameraData {
/**
* 当前画面的亮度
*/
private Double brightness;
/**
* 当前画面的反光
*/
private Double reflection;
/**
* 当前画面的透明度
*/
private Double transparencyMeasure;
/**
* 当前画面的面积
*/
private Double area;
/**
* 斜率
* 当前的斜率
*/
private Double absValue;
private Double slope;
/**
* 面积大小
* 当前斜率的差值
*/
private Integer size;
private Double slopeDifference;
/**
* 斜率差值的绝对值
*/
private Double absValue;
/**
* 当前档位
*/
private Integer nowGear;
/**
* 视频是否打开
*/
private boolean videoIsOpen;
/**
* 是否摄像头推流
*/
private boolean is_push_camera;
/**
* 是否显示数字
*/
private Boolean isText;
private Boolean displaySrc;
/**
* 鱼群图像识别运行状态
*/
private Boolean fishGroupImageRecognIsRun = false;
}
... ...
package com.zhonglai.luhui.smart.feeder.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class ConfigDto implements Serializable {
private static final long serialVersionUID = 4437689065039524585L;
private ConfigurationParameter configurationParameter;
private Object value;
}
package com.zhonglai.luhui.smart.feeder.dto;
import com.alibaba.fastjson.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
public enum ConfigurationParameter {
ifUpLoadData(false, Boolean.class,"sys_config","是否上报数据",true),//是否上报数据
ifVeiw(false, Boolean.class,"sys_config","是否显示",true),//是否显示
captureNumber(0, Integer.class,"sys_config","摄像头编号",true),//摄像头编号
reflectionThreshold(100, Integer.class,"sys_config","反光阈值",true),//反光阈值
kernelSize(3, Integer.class,"sys_config","去噪调整内核大小,用来消除小的物体或噪声",true),//去噪调整内核大小,用来消除小的物体或噪声
maxValue(255, Integer.class,"sys_config","最大反光阈值",true), //最大反光阈值
absValue_command (new ArrayList<FishCurveControlCondition>(),ArrayList.class,"absValue_command","斜率范围对应的档位",true), //斜率范围对应的档位
VeiwDto_isFrame(false, Boolean.class,"sys_config","是否显示原图",true), //是否显示原图
VeiwDto_isBinaryImage(false, Boolean.class,"sys_config","是否显示临时图",true), //是否显示临时图
VeiwDto_isSize(false, Boolean.class,"sys_config","是否显示面积",true), //是否显示面积
VeiwDto_isAbsValue(false, Boolean.class,"sys_config","是否显示斜率",true), //是否显示斜率
absValue(0.0, Double.class,"sys_config","显示斜率",false), //斜率
IdentificationFrequency(1000l, Long.class,"sys_config","鱼群图像识别的频率(单位秒)",true), //鱼群图像识别的频率
FishGroupImageRecognition(true, Boolean.class,"sys_config","鱼群图像识别是否开启",true), //鱼群图像识别是否开启
FeedingControl(true, Boolean.class,"sys_config","鱼群图像识别控制投料控制是否开启",true), //鱼群图像识别投料控制是否开启
SerialPortConfig(new SerialPortConfig().defaultSerialPortConfig(),com.zhonglai.luhui.smart.feeder.dto.SerialPortConfig.class,"sys_config","串口配置",true),//串口配置
;
private Object value; //值
private Class<?> valuType; //数据类型
private String tableName; //表名
private String describe; //描述
private Boolean persistence; //是否需要持久化
ConfigurationParameter(Object value,Class valuType,String tableName,String describe,Boolean persistence) {
this.value = value;
this.valuType = valuType;
this.tableName = tableName;
this.describe = describe;
this.persistence = persistence;
}
public Object getValue()
{
return value;
}
public Class<?> getValuType() {
return valuType;
}
public String getTableName() {
return tableName;
}
public String getDescribe() {
return describe;
}
public Boolean getPersistence() {
return persistence;
}
public String valueToString(Object o)
{
switch (getValuType().getName()) {
case "java.lang.Boolean":
return ((Boolean)o).toString();
case "java.lang.Integer":
return o+"";
case "java.lang.Double":
return o+"";
case "com.zhonglai.luhui.smart.feeder.dto.SerialPortConfig":
if(o instanceof String)
{
return (String) o;
}
return JSONObject.toJSONString(o);
default:
throw new RuntimeException("配置参数类型不正确" + name() + o);
}
}
}
... ... @@ -3,8 +3,21 @@ package com.zhonglai.luhui.smart.feeder.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.lang.reflect.Field;
@Data
@Accessors(chain = true) //链式写法
public class FeederConfig {
public class FeederConfig implements OperatingDataType{
private SerialPortConfig serialPortConfig;
public FeederConfig creteDefault()
{
serialPortConfig = new SerialPortConfig().defaultSerialPortConfig();
return this;
}
@Override
public void setValue(Field field, Object value) throws IllegalAccessException {
field.set(this,value);
}
}
... ...
... ... @@ -6,4 +6,5 @@ import lombok.experimental.Accessors;
@Data
@Accessors(chain = true) //链式写法
public class FeederData {
}
... ...
... ... @@ -10,6 +10,15 @@ public class FishCurveControlCondition implements Serializable {
private Integer sartAbsValue; //开始斜率
private Integer gear; //档位
public FishCurveControlCondition()
{
}
public FishCurveControlCondition(Integer sartAbsValue,Integer gear)
{
this.sartAbsValue = sartAbsValue;
this.gear = gear;
}
public Integer getGear() {
return gear;
}
... ...
package com.zhonglai.luhui.smart.feeder.dto;
import lombok.Data;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="xml")
@Data
public class HCCameraRepose {
private String Uuid;
private String Types;
private String DeviceType;
private String DeviceDescription;
private String DeviceSN;
private String CommandPort;
private String HttpPort;
private String MAC;
private String IPv4Address;
private String IPv4SubnetMask;
private String IPv4Gateway;
private String DHCP;
private String AnalogChannelNum;
private String DigitalChannelNum;
private String SoftwareVersion;
private String DSPVersion;
private String BootTime;
private String OEMInfo;
private String EZVIZCode;
private String manufacturer;
private String Activated;
private String ResetAbility;
private String PasswordResetAbility;
private String PasswordResetModeSecond;
}
... ...
package com.zhonglai.luhui.smart.feeder.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true) //链式写法
public class NettyConfig {
private String host = "127.0.0.1";
private Integer port = 4722;
private String clientId = "202310271543";
}
... ...
package com.zhonglai.luhui.smart.feeder.dto;
import java.lang.reflect.Field;
public interface OperatingDataType {
public void setValue(Field field,Object value) throws IllegalAccessException;
}
... ...
package com.zhonglai.luhui.smart.feeder.controller;
package com.zhonglai.luhui.smart.feeder.dto;
import com.ruoyi.common.core.domain.AjaxResult;
import com.zhonglai.luhui.dao.service.PublicService;
import com.zhonglai.luhui.smart.feeder.domain.Register;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import lombok.Data;
import lombok.experimental.Accessors;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
@Api(tags = "寄存器管理")
@RestController
@RequestMapping("/register")
public class RegisterConreoller {
@Autowired
private PublicService publicService;
@Data
@Accessors(chain = true) //链式写法
public class RegisterConfig implements OperatingDataType{
private List<Register> registerList;
@ApiOperation("初始化定时器解析规则")
@GetMapping("/iniTimer")
public AjaxResult iniTimer()
public RegisterConfig creteDefault()
{
List<Register> list = new ArrayList<>();
registerList = new ArrayList<>();
registerList.add(new Register(0,"机器状态",0,16,"machstate","java.lang.Integer"));
registerList.add(new Register(1,"电池电量",0,16,"battlevel","java.lang.Integer"));
registerList.add(new Register(3,"厂家码",0,2,"mfrs","java.lang.Integer"));
registerList.add(new Register(3,"设备类型",2,2,"equitype","java.lang.Integer"));
registerList.add(new Register(3,"设备模式",4,1,"equimode","java.lang.Integer"));
registerList.add(new Register(4,"故障代码",0,16,"faultcode","java.lang.Integer"));
registerList.add(new Register(5,"饲料状态",0,16,"fodderstate","java.lang.Boolean"));
registerList.add(new Register(6,"饲料重量",0,16,"fodderweight","java.lang.Float"));
registerList.add(new Register(7,"投料次数",0,16,"feednum","java.lang.Integer"));
registerList.add(new Register(8,"本次投料量",0,16,"feedweight","java.lang.Float"));
registerList.add(new Register(13,"运行模式",0,16,"runmode","java.lang.Boolean"));
registerList.add(new Register(14,"投料量",0,16,"runspeed","java.lang.Integer"));
registerList.add(new Register(15,"投料时间",0,16,"worktime","java.lang.Integer"));
registerList.add(new Register(16,"间隔时间",0,16,"interval","java.lang.Integer"));
registerList.add(new Register(17,"开/关",0,16,"runstate","java.lang.Integer"));
registerList.add(new Register(18,"停投料倒计时",0,16,"stopfeedcnt","java.lang.Integer"));
int startaddress = 23;
for(int i=0;i<48;i+=2)
{
... ... @@ -93,16 +100,21 @@ public class RegisterConreoller {
register7.setChar_lenth(1);
register7.setField_name("timer"+timerNumber+"_is_close");
list.add(register);
list.add(register1);
list.add(register2);
list.add(register3);
list.add(register4);
list.add(register5);
list.add(register6);
list.add(register7);
registerList.add(register);
registerList.add(register1);
registerList.add(register2);
registerList.add(register3);
registerList.add(register4);
registerList.add(register5);
registerList.add(register6);
registerList.add(register7);
}
return AjaxResult.success(publicService.insertAll(list));
return this;
}
@Override
public void setValue(Field field, Object value) throws IllegalAccessException {
field.set(this,value);
}
}
... ...
... ... @@ -3,17 +3,38 @@ package com.zhonglai.luhui.smart.feeder.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.lang.reflect.Field;
/**
* 系统配置
*/
@Data
@Accessors(chain = true) //链式写法
public class SysConfig {
public class SysConfig implements OperatingDataType{
/**
* 是否上报数据
*/
private Boolean ifUpLoadData;
private Boolean ifUpLoadData = true;
/**
* 是否显示
*/
private Boolean ifVeiw;
private Boolean ifVeiw = false;
private NettyConfig nettyConfig;
private Boolean ifRegisterConfig = false;
public SysConfig creteDefault()
{
ifUpLoadData = false;
ifVeiw = false;
nettyConfig = new NettyConfig();
return this;
}
@Override
public void setValue(Field field, Object value) throws IllegalAccessException {
field.set(this,value);
}
}
... ...
package com.zhonglai.luhui.smart.feeder.dto.commd;
public class FeederBackstateTtpe {
/**
* 成功
*/
public static int success = 0x37;
/**
* 串口没有找到
*/
public static int serialPortErr = 0x90;
/**
* 程序运行时错误
*/
public static int runErr = 0x91;
/**
* 串口没有找到
*/
public static int serialPortCommandSendErr = 0x92;
/**
* 摄像头没有找到
*/
public static int cameraErr = 0x93;
}
... ...
package com.zhonglai.luhui.smart.feeder.dto.mqtt;
import com.zhonglai.luhui.smart.feeder.dto.CameraConfig;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true) //链式写法
public class CameracontrolRequest {
private String cmd; //操作指令 devicedata
private String type; //设备网络型号 字符串("4G.hs")
private CameraConfig cameraConfig;
}
... ...
package com.zhonglai.luhui.smart.feeder.dto.mqtt;
import io.swagger.models.auth.In;
import lombok.Data;
import lombok.experimental.Accessors;
... ...
package com.zhonglai.luhui.smart.feeder.dto.mqtt;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.ruoyi.common.utils.ByteUtil;
import com.ruoyi.common.utils.GsonConstructor;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.UnsupportedEncodingException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Data
@Accessors(chain = true) //链式写法
public class CmdDto {
private String start = "^";
private String imei;
private JsonObject jsonObject;
private String lrc;
private String end = "~";
public CmdDto()
{
}
public CmdDto(String data)
{
String regEx = "(?:\\^)\\d+";
Matcher matcher = Pattern.compile(regEx).matcher(data);
if(matcher.find())
{
imei = matcher.group().replace("^","");
}
regEx = "\\w+(?:~)";
matcher = Pattern.compile(regEx).matcher(data);
if(matcher.find())
{
lrc = matcher.group().replace("~","");
}
jsonObject = GsonConstructor.get().fromJson(getJsonData(data),JsonObject.class);
}
public boolean checkLRC()
{
return lrc.toUpperCase().equals(generateLRC().toUpperCase());
}
public String generateCmd()
{
return start+imei+new GsonBuilder().setVersion(1.0D).disableInnerClassSerialization().setFieldNamingPolicy(FieldNamingPolicy.IDENTITY).create().toJson(jsonObject)+generateLRC()+end;
}
public String generateLRC()
{
String str = imei+new GsonBuilder().setVersion(1.0D).disableInnerClassSerialization().setFieldNamingPolicy(FieldNamingPolicy.IDENTITY).create().toJson(jsonObject);
try {
return ByteUtil.toHexString(ByteUtil.intToBytesASC(getLRC(str.getBytes("gb2312")),1));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
private static String getJsonData(String data)
{
String regEx = "(?:\\{).*(?:})";
Matcher matcher = Pattern.compile(regEx).matcher(data);
if(matcher.find())
{
return matcher.group();
}
return null;
}
/*
* 输入byte[] data , 返回LRC校验byte
*/
private byte getLRC(byte[] data) {
int tmp = 0;
for (int i = 0; i < data.length; i++) {
tmp = tmp + (byte) data[i];
}
tmp = ~tmp;
tmp = (tmp & (0xff));
tmp += 1;
return (byte) tmp;
}
public static void main(String[] args) {
String str = "5e 38 36 35 30 36 31 30 35 33 32 35 32 38 36 38 7b 22 63 6d 64 22 3a 22 6d 61 6e 75 61 6c 63 6f 6e 74 72 6f 6c 22 2c 22 74 79 70 65 22 3a 22 34 47 2e 68 73 22 2c 22 63 6f 6e 64 61 74 61 22 3a 7b 22 6f 6e 6f 66 66 22 3a 31 7d 7d 62 7e";
byte[] ss = ByteUtil.hexStringToByte(str.replace(" ","").toUpperCase());
CmdDto cmdDto = new CmdDto("^865061053252868{\"cmd\":\"manualcontrol\",\"type\":\"4G.hs\",\"condata\":{\"onoff\":1}}b~");
System.out.println(cmdDto.generateLRC());
System.out.println(cmdDto.generateCmd());
// CmdDto cmdDto = new CmdDto("^869537052982171{\"cmd\":\"devicedata\",\"type\":\"4G.hs\",\"signal\":3,\"machstate\":1,\"battlevel\":4,\"condata\":{\"runmode\":0,\"runspeed\":9,\"worktime\":6,\"interval\":4,\"runstate\":3,\"stopfeedcnt\":0},\"info\":{\"mfrs\":\"中渔科技\",\"equitype\":0,\"equimode\":0,\"faultcode\":0,\"fodderstate\":1,\"fodderweight\":65535,\"feednum\":65535,\"feedweight\":65535},\"timer\":[]}1F~");
// System.out.println(cmdDto.getLrc());
// System.out.println(cmdDto.generateLRC());
}
}
... ...
package com.zhonglai.luhui.smart.feeder.dto.mqtt;
import com.zhonglai.luhui.smart.feeder.dto.*;
import lombok.Data;
import lombok.experimental.Accessors;
... ... @@ -10,10 +11,16 @@ import java.util.List;
public class DevicedatRequest {
private String cmd; //操作指令 devicedata
private String type; //设备网络型号 字符串("4G.hs")
private String signal; //信号量
private String machstate; //机器状态
private String battlevel; //电池电量
private Integer signal; //信号量
private Integer machstate; //机器状态
private Integer battlevel; //电池电量
private Condata condata;
private Info info;
private List<Integer[]> timer; //开启、关闭、使能 8:00开启-9:00关闭,状态:启用
private SysConfig sysConfig;
private CameraData cameraData;
private CameraConfig cameraConfig;
private FeederConfig feederConfig;
private RegisterConfig registerConfig;
}
... ...
package com.zhonglai.luhui.smart.feeder.dto.mqtt;
import lombok.Data;
@Data
public class HeadDto
{
private String cmd;
private String type;
private String errorcode;
}
... ...
package com.zhonglai.luhui.smart.feeder.dto.mqtt;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true) //链式写法
public class ReturnOkDto {
private String cmd; //操作指令
private String type; //设备网络型号
private Integer backstate; //返回状态 正确返回0x36,其余错误
private Integer errorcode; //错误代码 0xE0:IMEI错误,0xE1:LRC错误,0xE2:指令错误,0xE4无效数据,0xE5不支持的指令
}
... ...
package com.zhonglai.luhui.smart.feeder.mapper;
import com.zhonglai.luhui.dao.dto.PublicSQL;
import com.zhonglai.luhui.smart.feeder.dto.FishCurveControlCondition;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.SelectProvider;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.common.BaseMapper;
import java.util.List;
@Component(value = "AbsValueCommandMapper")
public interface AbsValueCommandMapper extends BaseMapper<FishCurveControlCondition> {
@SelectProvider(type = PublicSQL.class, method = "getObjectListBySQL")
List<FishCurveControlCondition> getFishCurveControlConditionList(@Param("sql") String sql);
}
package com.zhonglai.luhui.smart.feeder.service;
import cn.hutool.core.bean.BeanUtil;
import com.google.gson.JsonObject;
import com.ruoyi.common.utils.ByteUtil;
import com.zhonglai.luhui.smart.feeder.Main;
import com.zhonglai.luhui.smart.feeder.domain.Register;
import com.zhonglai.luhui.smart.feeder.dto.ModbusDto;
import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommd;
... ... @@ -22,13 +19,9 @@ import java.util.Map;
/**
* 数据解析服务
*/
@Service
public class AnalysisDataService {
private static final Logger logger = LoggerFactory.getLogger(AnalysisDataService.class);
@Autowired
private ConfigurationParameterService configurationParameterService;
public Map<String,Object> analysis(ModbusDto modbusDto)
{
if(modbusDto instanceof FeederCommdDto)
... ... @@ -38,7 +31,7 @@ public class AnalysisDataService {
FeederCommd feederCommd = feederCommdDto.getFeederCommd();
if (feederCommd instanceof FeederCommd03Request)
{
Map<Integer, List<Register>> configMap = configurationParameterService.getRegisterMap();
Map<Integer, List<Register>> configMap = ConfigurationParameterService.registerMap;
Map<String,Object> valueMap = new HashMap<>();
... ...
package com.zhonglai.luhui.smart.feeder.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.smart.feeder.config.OperatingData;
import com.zhonglai.luhui.smart.feeder.domain.Register;
import com.zhonglai.luhui.smart.feeder.dto.ConfigurationParameter;
import com.zhonglai.luhui.smart.feeder.dto.FishCurveControlCondition;
import com.zhonglai.luhui.smart.feeder.dto.StateData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zhonglai.luhui.smart.feeder.dto.*;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
... ... @@ -17,49 +18,76 @@ import java.util.Map;
/**
* 配置参数
*/
@Service
public class ConfigurationParameterService {
private Map<Integer,List<Register>> registerMap = new HashMap<>(); //解析的数据字典
public static Map<Integer,List<Register>> registerMap = new HashMap<>(); //解析的数据字典
private Map<String,Register> controlMap = new HashMap<>(); //控制的数据字典
public static Map<String,Register> controlMap = new HashMap<>(); //控制的数据字典
@Autowired
private EhCacheService ehCacheService;
public static void initConfigurationParameter()
{
try {
File sysConfigFile = new File("sysConfig");
if(!sysConfigFile.exists())
{
sysConfigFile.createNewFile();
SysConfig sysConfig = new SysConfig().creteDefault();
FileUtil.writeString(GsonConstructor.get().toJson(sysConfig),sysConfigFile,"UTF-8");
BeanUtil.copyProperties(sysConfig,OperatingData.sysConfig);
}else{
String str = FileUtil.readUtf8String(sysConfigFile);
SysConfig sysConfig = GsonConstructor.get().fromJson(str,SysConfig.class);
BeanUtil.copyProperties(sysConfig,OperatingData.sysConfig);
}
@Autowired
private SqliteService sqliteService;
File cameraConfigFile = new File("cameraConfig");
if(!cameraConfigFile.exists())
{
cameraConfigFile.createNewFile();
CameraConfig cameraConfig = new CameraConfig().creteDefault();
FileUtil.writeString(GsonConstructor.get().toJson(cameraConfig),cameraConfigFile,"UTF-8");
BeanUtil.copyProperties(cameraConfig,OperatingData.cameraConfig);
}else{
CameraConfig cameraConfig = GsonConstructor.get().fromJson(FileUtil.readUtf8String(cameraConfigFile),CameraConfig.class);
BeanUtil.copyProperties(cameraConfig,OperatingData.cameraConfig);
}
private StateData stateData;
File feederConfigFile = new File("feederConfig");
if(!feederConfigFile.exists())
{
feederConfigFile.createNewFile();
FeederConfig feederConfig = new FeederConfig().creteDefault();
FileUtil.writeString(GsonConstructor.get().toJson(feederConfig),feederConfigFile,"UTF-8");
BeanUtil.copyProperties(feederConfig,OperatingData.feederConfig);
}else{
FeederConfig feederConfig = GsonConstructor.get().fromJson(FileUtil.readUtf8String(feederConfigFile),FeederConfig.class);
BeanUtil.copyProperties(feederConfig,OperatingData.feederConfig);
}
public void initConfigurationParameter()
{
//系统配置
List<Map<String,Object>> sysConfigList = sqliteService.getAllSysConfig();
if(null != sysConfigList && sysConfigList.size() != 0)
{
for(Map<String,Object> map:sysConfigList)
File registerFile = new File("register");
if(!registerFile.exists())
{
ConfigurationParameter configurationParameter = ConfigurationParameter.valueOf((String) map.get("parameter_name"));
ehCacheService.writeToCache(configurationParameter,map.get("parameter_value"));
registerFile.createNewFile();
RegisterConfig registerConfig = new RegisterConfig().creteDefault();
FileUtil.writeString(GsonConstructor.get().toJson(registerConfig),registerFile,"UTF-8");
BeanUtil.copyProperties(registerConfig,OperatingData.registerConfig);
}else{
RegisterConfig registerConfig = GsonConstructor.get().fromJson(FileUtil.readUtf8String(registerFile),RegisterConfig.class);
BeanUtil.copyProperties(registerConfig,OperatingData.registerConfig);
}
}
//斜率对应的档位
List<FishCurveControlCondition> absValueCommandList = sqliteService.getAllAbsValueCommand();
ehCacheService.writeToCache(ConfigurationParameter.absValue_command,new ArrayList<>());
if(null != absValueCommandList && absValueCommandList.size() != 0)
{
ehCacheService.writeToCache(ConfigurationParameter.absValue_command,absValueCommandList);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
//数据解析字典
List<Map<String,Object>> registerList = sqliteService.getAllRegister();
List<Register> registerList = OperatingData.registerConfig.getRegisterList();
if(null != registerList && registerList.size() != 0)
{
for (Map<String,Object> map:registerList)
for (Register register:registerList)
{
Register register = BeanUtil.mapToBean(map,Register.class,false,null);
List<Register> list = registerMap.get(register.getAddress());
if(null == list)
{
... ... @@ -69,121 +97,11 @@ public class ConfigurationParameterService {
list.add(register);
}
for (Map<String,Object> map:registerList)
for (Register register:registerList)
{
Register register = BeanUtil.mapToBean(map,Register.class,false,null);
controlMap.put(register.getField_name(),register);
}
}
}
public Map<String, Object> getAll()
{
return ehCacheService.getMyCache();
}
public synchronized void setConfig(ConfigurationParameter configurationParameter,Object value)
{
switch (configurationParameter)
{
case absValue_command:
if(value instanceof ArrayList)
{
List<FishCurveControlCondition> slist = new ArrayList<>();
for(Object object:(List) value)
{
if(object instanceof FishCurveControlCondition)
{
slist = (List) value;
break;
}else if (object instanceof HashMap)
{
FishCurveControlCondition fishCurveControlCondition = BeanUtil.mapToBean((HashMap)object,FishCurveControlCondition.class,false,null);
slist.add(fishCurveControlCondition);
}
}
setabsValueCommandList(slist);
}else if(value instanceof FishCurveControlCondition)
{
setabsValueCommand((FishCurveControlCondition) value);
}else {
throw new RuntimeException("配置参数类型不正确");
}
break;
default:
if(configurationParameter.getPersistence())
{
setDefaultCommandMap(configurationParameter,value);
}else{
setNotPersistenceCommandMap(configurationParameter,value);
}
}
}
public Object getConfig(ConfigurationParameter configurationParameter)
{
return ehCacheService.readFromCache(configurationParameter);
}
private void setNotPersistenceCommandMap(ConfigurationParameter configurationParameter,Object value)
{
ehCacheService.writeToCache(configurationParameter,value);
}
private void setDefaultCommandMap(ConfigurationParameter configurationParameter,Object value)
{
ehCacheService.writeToCache(configurationParameter,value);
sqliteService.updateConfigurationParameter(configurationParameter,value);
}
private void setabsValueCommandList(List<FishCurveControlCondition> absValueCommandList)
{
sqliteService.deleteabsValueCommandAll();
ehCacheService.readFromCache(ConfigurationParameter.absValue_command);
for (FishCurveControlCondition fishCurveControlCondition:absValueCommandList)
{
sqliteService.updateabsValueCommand(fishCurveControlCondition.getGear(),fishCurveControlCondition.getSartAbsValue());
}
ehCacheService.writeToCache(ConfigurationParameter.absValue_command,absValueCommandList);
}
private void setabsValueCommand(FishCurveControlCondition absValueCommand)
{
List<FishCurveControlCondition> old = (List<FishCurveControlCondition>) ehCacheService.readFromCache(ConfigurationParameter.absValue_command);
if(null == old)
{
old = new ArrayList<>();
}
old.removeIf(condition -> condition.getGear().equals(absValueCommand.getGear()));
ehCacheService.writeToCache(ConfigurationParameter.absValue_command,old);
sqliteService.updateabsValueCommand(absValueCommand.getGear(),absValueCommand.getSartAbsValue());
}
public Map<Integer, List<Register>> getRegisterMap() {
return registerMap;
}
public Map<String, Register> getControlMap() {
return controlMap;
}
public StateData getStateData() {
return stateData;
}
public void setStateData(StateData stateData) {
this.stateData = stateData;
}
}
... ...
... ... @@ -2,126 +2,180 @@ package com.zhonglai.luhui.smart.feeder.service;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.zhonglai.luhui.smart.feeder.dto.ConfigurationParameter;
import com.zhonglai.luhui.smart.feeder.dto.ModbusDto;
import com.zhonglai.luhui.smart.feeder.dto.StateData;
import com.zhonglai.luhui.smart.feeder.dto.VeiwDto;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.smart.feeder.config.OperatingData;
import com.zhonglai.luhui.smart.feeder.config.ScheduledConfig;
import com.zhonglai.luhui.smart.feeder.dto.*;
import com.zhonglai.luhui.smart.feeder.dto.commd.FeederTimer;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.CmdDto;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.Condata;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.DevicedatRequest;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.Info;
import com.zhonglai.luhui.smart.feeder.service.device.SerialPortService;
import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil;
import org.eclipse.paho.client.mqttv3.MqttException;
import com.zhonglai.luhui.smart.feeder.util.MessageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 数据监听服务
*/
@Service
public class DateListenService {
private static final Logger logger = LoggerFactory.getLogger(DateListenService.class);
@Autowired
private ScheduledExecutorService scheduledExecutorService;
@Autowired
private SerialPortService serialPortService;
@Autowired
private AnalysisDataService analysisDataService;
@Autowired
private TerminalService terminalService;
private AnalysisDataService analysisDataService = new AnalysisDataService();
@Autowired
private ConfigurationParameterService configurationParameterService;
private SerialPortService serialPortService;
@Autowired
private FishGroupImageRecognitionService fishGroupImageRecognitionService;
public DateListenService(SerialPortService serialPortService)
{
this.serialPortService = serialPortService;
}
public void run()
{
scheduledExecutorService.scheduleAtFixedRate(() -> {
try {
gatherDevice0();
Thread.sleep(1000);
} catch (MqttException e) {
logger.error("采集主机信息失败",e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
//更新投料机数据
ScheduledConfig.scheduler.scheduleAtFixedRate(() -> {
ModbusDto modbusDto = serialPortService.sendHexData(FeederCommdUtil.readAll());
Map<String,Object> data = analysisDataService.analysis(modbusDto);
if(null != data && data.size() != 0)
{
Condata condata = BeanUtil.mapToBean(data, Condata.class,false,null);
Info info = BeanUtil.mapToBean(data, Info.class,false,null);
OperatingData.devicedat.setCondata(condata);
OperatingData.devicedat.setInfo(info);
List<Integer[]> timerList = new ArrayList<>();
for(String key:data.keySet())
{
if(key.startsWith("timer"))
{
FeederTimer feederTimer = (FeederTimer) data.get(key);
timerList.add(new Integer[]{feederTimer.getTimer_start_h(),feederTimer.getTimer_start_m(),feederTimer.getTimer_close_h(),feederTimer.getTimer_start_m(),feederTimer.getTimer_if_start()});
}
}
if(null != timerList && timerList.size() != 0)
{
OperatingData.devicedat.setTimer(timerList);
}
}
try {
gatherDevice1();
Thread.sleep(1000);
} catch (MqttException e) {
logger.error("采集投料机数据失败",e);
}catch (InterruptedException e) {
throw new RuntimeException(e);
},1,10, TimeUnit.SECONDS);
//上报数据
ScheduledConfig.scheduler.scheduleAtFixedRate(() -> {
if(OperatingData.sysConfig.getIfUpLoadData())
{
try {
if(InitService.nettyClient.getCtx().channel().isOpen())
{
DevicedatRequest devicedatRequest = new DevicedatRequest();
devicedatRequest.setCmd("devicedata");
devicedatRequest.setType("4G.hs");
devicedatRequest.setSignal(4);
devicedatRequest.setMachstate(1);
devicedatRequest.setBattlevel(4);
devicedatRequest.setCondata(OperatingData.devicedat.getCondata());
devicedatRequest.setInfo(OperatingData.devicedat.getInfo());
devicedatRequest.setTimer(OperatingData.devicedat.getTimer());
String str = GsonConstructor.get().toJson(devicedatRequest);
System.out.println(str);
if(str.length()>=1024)
{
System.out.println("超标了");
}
CmdDto cmdDto = new CmdDto().setImei(OperatingData.sysConfig.getNettyConfig().getClientId()).setJsonObject( GsonConstructor.get().fromJson( str, JsonObject.class));
MessageUtil.sendMessage(InitService.nettyClient.getCtx(), cmdDto.generateCmd(),true);
Thread.sleep(10000);
devicedatRequest = new DevicedatRequest();
devicedatRequest.setCmd("devicedata");
devicedatRequest.setType("4G.hs");
devicedatRequest.setSignal(4);
devicedatRequest.setMachstate(1);
devicedatRequest.setBattlevel(4);
devicedatRequest.setSysConfig(OperatingData.sysConfig);
devicedatRequest.setFeederConfig(OperatingData.feederConfig);
str = GsonConstructor.get().toJson(devicedatRequest);
System.out.println(str);
if(str.length()>=1024)
{
System.out.println("超标了");
}
cmdDto = new CmdDto().setImei(OperatingData.sysConfig.getNettyConfig().getClientId()).setJsonObject( GsonConstructor.get().fromJson( str, JsonObject.class));
MessageUtil.sendMessage(InitService.nettyClient.getCtx(), cmdDto.generateCmd(),true);
Thread.sleep(10000);
devicedatRequest = new DevicedatRequest();
devicedatRequest.setCmd("devicedata");
devicedatRequest.setType("4G.hs");
devicedatRequest.setSignal(4);
devicedatRequest.setMachstate(1);
devicedatRequest.setBattlevel(4);
devicedatRequest.setCameraData(OperatingData.cameraData);
devicedatRequest.setCameraConfig(OperatingData.cameraConfig);
str = GsonConstructor.get().toJson(devicedatRequest);
System.out.println(str);
if(str.length()>=1024)
{
System.out.println("超标了");
}
cmdDto = new CmdDto().setImei(OperatingData.sysConfig.getNettyConfig().getClientId()).setJsonObject( GsonConstructor.get().fromJson( str, JsonObject.class));
MessageUtil.sendMessage(InitService.nettyClient.getCtx(), cmdDto.generateCmd(),true);
if(OperatingData.sysConfig.getIfRegisterConfig())
{
Thread.sleep(10000);
devicedatRequest = new DevicedatRequest();
devicedatRequest.setCmd("devicedata");
devicedatRequest.setType("4G.hs");
devicedatRequest.setSignal(4);
devicedatRequest.setMachstate(1);
devicedatRequest.setBattlevel(4);
devicedatRequest.setRegisterConfig(OperatingData.registerConfig);
str = GsonConstructor.get().toJson(devicedatRequest);
cmdDto = new CmdDto().setImei(OperatingData.sysConfig.getNettyConfig().getClientId()).setJsonObject( GsonConstructor.get().fromJson( str, JsonObject.class));
MessageUtil.sendMessage(InitService.nettyClient.getCtx(), cmdDto.generateCmd(),true);
}
}
}catch (Exception e)
{
logger.error("上传数据异常",e);
}
}
try {
gatherDevice2();
} catch (MqttException e) {
logger.error("采集摄像头信息失败",e);
}
},1,60, TimeUnit.SECONDS);
}
/**
* 采集投料机数据
*/
private void gatherDevice1() throws MqttException {
if(null == configurationParameterService.getConfig(ConfigurationParameter.ifUpLoadData) || !(Boolean) configurationParameterService.getConfig(ConfigurationParameter.ifUpLoadData))
{
return;
}
ModbusDto modbusDto = serialPortService.sendHexData(FeederCommdUtil.readAll());
Map<String,Object> data = analysisDataService.analysis(modbusDto);
if(null != data && data.size() != 0)
{
StateData stateData = BeanUtil.mapToBean(data, StateData.class,false,null);
configurationParameterService.setStateData(stateData);
JSONObject jsonObject = new JSONObject();
jsonObject.put("10_1",data);
String topic = "ALL_POST";
terminalService.publish(topic,jsonObject.toJSONString());
}
},1,10, TimeUnit.SECONDS);
}
/**
* 采集主机信息
*/
private void gatherDevice0() throws MqttException {
Map<String, Object> map = configurationParameterService.getAll();
if(null != map && map.size() !=0)
{
JSONObject jsonObject = new JSONObject();
jsonObject.put("0",map);
String topic = "ADD_POST";
terminalService.publish(topic,jsonObject.toJSONString());
}
public static void main(String[] args) {
ConfigurationParameterService.initConfigurationParameter();
DevicedatRequest devicedatRequest = new DevicedatRequest();
devicedatRequest.setCmd("devicedata");
devicedatRequest.setType("4G.hs");
devicedatRequest.setSignal(4);
devicedatRequest.setMachstate(1);
devicedatRequest.setBattlevel(4);
devicedatRequest.setCondata(OperatingData.devicedat.getCondata());
devicedatRequest.setInfo(OperatingData.devicedat.getInfo());
devicedatRequest.setTimer(OperatingData.devicedat.getTimer());
devicedatRequest.setSysConfig(OperatingData.sysConfig);
devicedatRequest.setCameraData(OperatingData.cameraData);
devicedatRequest.setCameraConfig(OperatingData.cameraConfig);
devicedatRequest.setFeederConfig(OperatingData.feederConfig);
System.out.println(GsonConstructor.get().toJson(devicedatRequest));
}
/**
* 采集摄像头信息
*/
private void gatherDevice2() throws MqttException {
VeiwDto veiwDto = fishGroupImageRecognitionService.getVeiwDto();
if(null != veiwDto && BeanUtil.isNotEmpty(veiwDto,"size","absValue"))
{
veiwDto = BeanUtil.copyProperties(veiwDto,VeiwDto.class,"frame","binaryImage");
JSONObject jsonObject = new JSONObject();
jsonObject.put("1_1",veiwDto);
String topic = "ALL_POST";
terminalService.publish(topic,jsonObject.toJSONString());
}
}
}
... ...
package com.zhonglai.luhui.smart.feeder.service;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.smart.feeder.config.OperatingData;
import com.zhonglai.luhui.smart.feeder.config.ScheduledConfig;
import com.zhonglai.luhui.smart.feeder.dto.*;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.Condata;
import com.zhonglai.luhui.smart.feeder.service.device.SerialPortService;
import com.zhonglai.luhui.smart.feeder.util.FeederCommd06ResponseType;
import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 设备管理
*/
@Service
public class DeviceService {
private static Logger logger = LoggerFactory.getLogger(DeviceService.class);
private Double backArea; //上一个大小
private Double slope; //斜率
private Double backSlope; //斜率
private Double slopeDifference; //斜率差值
private Double absValue; //斜率差值的绝对值
private Integer nowGear; //当前档位
private Integer oldGear; //老的档位
private Double area; //面积
@Autowired
private ConfigurationParameterService configurationParameterService;
@Autowired
private ScheduledExecutorService scheduledExecutorService;
@Autowired
private EhCacheService ehCacheService;
@Autowired
private SerialPortService serialPortService;
public DeviceService(SerialPortService serialPortService)
{
this.serialPortService = serialPortService;
}
public void run()
{
//投料控制
scheduledExecutorService.scheduleWithFixedDelay(() -> {
if (((Boolean)ehCacheService.readFromCache(ConfigurationParameter.FeedingControl))) {
logger.info("当前档位{},以前的档位{},斜率{},斜率差值{},面积{},开关是否打开{}",nowGear,oldGear,slope,absValue,area,null == configurationParameterService.getStateData()?"未知":configurationParameterService.getStateData().getSwitch_status());
ScheduledConfig.scheduler.scheduleWithFixedDelay(() -> {
if (OperatingData.cameraConfig.getFeedingControl()) {
Condata condata = OperatingData.devicedat.getCondata();
CameraData cameraData = OperatingData.cameraData;
logger.info("摄像头识别档位{},投料机的档位{},斜率{},斜率差值{},面积{},开关是否打开{}",cameraData.getNowGear(),condata.getRunspeed(),cameraData.getSlope(),cameraData.getAbsValue(),cameraData.getArea(),null == condata.getRunstate()?"未知":condata.getRunstate());
getGearFromAbsValue();
if(null != nowGear && oldGear != nowGear)
if(null !=condata && 1==condata.getRunstate()) //数据状态出来了,并且设备已经启动
{
if(nowGear>0 ) //如果档位有值
if(1==condata.getRunmode()) //只有手动模式才能控制
{
if(null !=configurationParameterService.getStateData() && 1==configurationParameterService.getStateData().getRunmode())
{
serialPortService.sendHexData(FeederCommdUtil.controlData(FeederCommd06ResponseType.runmode,0)); //,运行模式改成手动
}
if(null !=configurationParameterService.getStateData() && 0==configurationParameterService.getStateData().getSwitch_status())
ModbusDto modbusDto = serialPortService.sendHexData(FeederCommdUtil.controlData(FeederCommd06ResponseType.runmode,0)); //,运行模式改成手动
if(null!=modbusDto)
{
serialPortService.sendHexData(FeederCommdUtil.controlData(FeederCommd06ResponseType.OnOroff,1)); //,开关是关的就先打开开关
condata.setRunmode(1);
}
serialPortService.sendHexData(FeederCommdUtil.controlData(FeederCommd06ResponseType.runspeed,nowGear));
oldGear = nowGear;
}else{
if(null !=configurationParameterService.getStateData() && 0==configurationParameterService.getStateData().getRunmode())
{
serialPortService.sendHexData(FeederCommdUtil.controlData(FeederCommd06ResponseType.runmode,1)); //,运行模式改成自动
}
if(null !=configurationParameterService.getStateData() && 1==configurationParameterService.getStateData().getSwitch_status())
}
if( cameraData.getNowGear() != condata.getRunspeed())
{
ModbusDto modbusDto = serialPortService.sendHexData(FeederCommdUtil.controlData(FeederCommd06ResponseType.runspeed,cameraData.getNowGear())); //较准档位
if(null!=modbusDto)
{
serialPortService.sendHexData(FeederCommdUtil.controlData(FeederCommd06ResponseType.OnOroff,0)); //,开关是关的就先打开开关
condata.setRunspeed(cameraData.getNowGear());
}
}
}
}
},1,1, TimeUnit.SECONDS);
}
public String getState()
{
Map<String,Object> map = new HashMap<>();
map.put("backArea",backArea);
map.put("slope",slope);
map.put("backSlope",backSlope);
map.put("slopeDifference",slopeDifference);
map.put("absValue",absValue);
map.put("nowGear",nowGear);
return GsonConstructor.get().toJson(map);
}
/**
* 根据面积计算斜率
* @param area
* @return
*/
public double controlDevice(double area)
{
this.area = area;
if(null == backArea )
{
backArea = area;
return 0;
}
slope = area-backArea;
if(null == backSlope)
{
backSlope = slope;
}
slopeDifference = slope-backSlope;
absValue = Math.abs(slopeDifference);
nowGear = getGearFromAbsValue();
return absValue;
}
/**
* 根据斜率计算档位
* @return
*/
private Integer getGearFromAbsValue()
{
Double absValue = OperatingData.cameraData.getAbsValue();
Integer gear = null;
List<FishCurveControlCondition> list = (List<FishCurveControlCondition>) ehCacheService.readFromCache(ConfigurationParameter.absValue_command);
List<FishCurveControlCondition> list = OperatingData.cameraConfig.getAbsValue_command();
if(null != list && list.size() != 0)
{
list.sort(Comparator.comparing(FishCurveControlCondition::getSartAbsValue));//以 sartAbsValue 升序排序
... ... @@ -145,6 +82,7 @@ public class DeviceService {
}
}
}
OperatingData.cameraData.setNowGear(gear);
return gear;
}
... ...
package com.zhonglai.luhui.smart.feeder.service;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.smart.feeder.dto.ConfigurationParameter;
import com.zhonglai.luhui.smart.feeder.dto.SerialPortConfig;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/**
* 缓存
*/
@Service
public class EhCacheService {
private static Map<String,Object> cacheMap = new HashMap<>();
public void writeToCache(ConfigurationParameter key, Object value) {
Class cls = key.getValuType();
if(cls.isInstance(value))
{
cacheMap.put(key.name(), cls.cast(value));
}else if(value instanceof String)
{
switch (cls.getName())
{
case "java.lang.Boolean":
cacheMap.put(key.name(), Boolean.valueOf((String) value));
return;
case "java.lang.Integer":
cacheMap.put(key.name(), Integer.valueOf((String) value));
return;
case "java.lang.Double":
cacheMap.put(key.name(), Double.valueOf((String) value));
return;
case "java.lang.Long":
cacheMap.put(key.name(), Long.valueOf((String) value));
return;
case "com.zhonglai.luhui.smart.feeder.dto.SerialPortConfig":
SerialPortConfig serialPortConfig = GsonConstructor.get().fromJson((String) value,SerialPortConfig.class);
cacheMap.put(key.name(), serialPortConfig);
return;
default:
throw new RuntimeException("配置参数类型不正确"+key+value);
}
}else{
throw new RuntimeException("配置参数类型不正确");
}
}
public Object readFromCache(ConfigurationParameter key) {
return cacheMap.get(key.name());
}
public Map<String, Object> getMyCache() {
return cacheMap;
}
public void shutdown() {
if (cacheMap != null) {
cacheMap.clear();
}
}
}
package com.zhonglai.luhui.smart.feeder.service;
import cn.hutool.core.util.ArrayUtil;
import com.ruoyi.common.utils.StringUtils;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;
import org.bytedeco.javacv.Frame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@Service
public class FFmCameraService {
private static final Logger logger = LoggerFactory.getLogger(FFmCameraService.class);
private FFmpegFrameGrabber grabber;
private OpenCVFrameConverter.ToOrgOpenCvCoreMat converter2 = new OpenCVFrameConverter.ToOrgOpenCvCoreMat();
@Autowired
private ScheduledExecutorService scheduledExecutorService;
@Autowired
private SrsService srsService;
private static String MAC = "78-a6-a0-d2-bd-e1";
public boolean getVideoIsOpen()
{
return !grabber.isDeinterlace();
}
public void start()
{
loadCamera();
}
public static void main(String[] args) {
pushCamera();
}
public static void pushCamera()
{
String ip = "192.168.0.198";
String inputUrl = "rtsp://admin:Luhui586@" + ip + ":554/h264/ch1/main/av_stream";
String outputUrl = "rtmp://119.23.218.181:21935/live/70094a59d1d991d";
try {
FFmpegFrameGrabber.tryLoad();
} catch (Exception e) {
throw new RuntimeException("Failed to load FFmpeg", e);
}
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputUrl);
grabber.setVideoOption("fflags", "nobuffer");
grabber.setVideoOption("rtsp_transport", "tcp");
grabber.setOption("stimeout", "2000000");
avutil.av_log_set_level(avutil.AV_LOG_ERROR);
try {
grabber.start();
Frame frame = grabber.grabImage();
while (0 == frame.imageWidth)
{
Thread.sleep(1000);
}
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputUrl, frame.imageWidth, frame.imageHeight);
recorder.setFormat("flv");
recorder.setFrameRate(30);
recorder.setVideoBitrate(2000000);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
recorder.start();
Frame capturedFrame;
while ((capturedFrame = grabber.grabImage()) != null) {
recorder.record(capturedFrame);
}
grabber.stop();
recorder.stop();
System.out.println("摄像头流推送完成");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 加载摄像头
*/
public void loadCamera()
{
String ip = "192.168.0.198";
if(StringUtils.isEmpty(ip))
{
System.out.println("没有找到摄像头:"+MAC);
return;
}
String rtspUrl = "rtsp://admin:Luhui586@"+ip+":554/h264/ch1/main/av_stream";
try {
FFmpegFrameGrabber.tryLoad();
} catch (Exception e) {
throw new RuntimeException("Failed to load FFmpeg", e);
}
grabber = new FFmpegFrameGrabber(rtspUrl);
grabber.setVideoOption("fflags", "nobuffer"); // 禁用缓冲
grabber.setVideoOption("rtsp_transport", "tcp"); // 使用TCP传输
grabber.setOption("stimeout", "2000000");
avutil.av_log_set_level(avutil.AV_LOG_ERROR); // 设置日志级别
try {
grabber.start();
} catch (Exception e) {
close();
e.printStackTrace();
}
// scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
// @Override
// public void run() {
// if()
// {
// srsService.push(getFrame());
// }
//
// }
// },0,0, TimeUnit.MILLISECONDS);
}
public Boolean isOk()
{
try {
return null!=grabber && grabber.grab() != null;
} catch (FrameGrabber.Exception e) {
return false;
}
}
public void close()
{
if(null != grabber)
{
try {
grabber.stop();
grabber.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void display(Frame frame) throws FrameGrabber.Exception {
CanvasFrame canvasFrame = new CanvasFrame("Key Frame Capture", CanvasFrame.getDefaultGamma() / grabber.getGamma());
canvasFrame.dispose();
while (true) {
canvasFrame.showImage(dream(getFrame()));
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
String formattedDateTime = now.format(formatter);
System.out.println("当前时间: " + formattedDateTime);
}
}
public org.opencv.core.Mat getMat()
{
Frame frame = getFrame();
if(null == frame)
{
return null;
}
return converter2.convert(frame);
}
public Frame getFrame() {
Frame frame = null;
try {
frame = grabber.grabImage();
if (frame == null || frame.imageHeight==0) {
//TODO:连续n次为null,进行重连
logger.info("读取不到画面,当前grabber状态:hasAudio {},hasVideo {},isCloseInputStream {},isDeinterlace {},isTriggerMode {}",grabber.hasAudio(),grabber.hasVideo(),grabber.isCloseInputStream(),grabber.isDeinterlace(),grabber.isTriggerMode());
return null;
}
else{
return frame;
}
} catch (FrameGrabber.Exception e) {
return null;
}
}
private int maxX = 200;
private int POINT_RADIUS = 3;
private int quHeight = 200;
private java.util.List<Double> points = new ArrayList<>();
private BufferedImage dream(Frame frame)
{
BufferedImage image = Java2DFrameUtils.toBufferedImage(frame);
double point = Math.random();
points.add(point);
if (points.size() > maxX) {
points.remove(0);
}
BufferedImage curveImage = new BufferedImage(image.getWidth(), image.getHeight()+quHeight,image.getType());
Graphics2D g2d = curveImage.createGraphics();
// 在图像上绘制曲线
g2d.setColor(Color.RED);
g2d.setStroke(new BasicStroke(POINT_RADIUS));
Double maxY = ArrayUtil.max(points.toArray(new Double[0]));
int vx = image.getWidth()/maxX;
Double vy = quHeight/maxY;
// 绘制动态曲线
for(int i=0;i<points.size()-1;i++)
{
int x = i*vx;
int y = new Double(points.get(i)*vy).intValue();
g2d.drawLine(x, y+image.getHeight(), x+vx, new Double(points.get(i+1)*vy).intValue()+image.getHeight());
}
// 将第一个帧绘制到合并图像的上方
curveImage.createGraphics().drawImage(image, 0, 0, null);
g2d.dispose();
return curveImage;
}
}
package com.zhonglai.luhui.smart.feeder.service;
import com.zhonglai.luhui.smart.feeder.config.WebSocketClien;
import com.zhonglai.luhui.smart.feeder.dto.ConfigurationParameter;
import com.zhonglai.luhui.smart.feeder.dto.VeiwDto;
import com.zhonglai.luhui.smart.feeder.config.OpenCVConfig;
import com.zhonglai.luhui.smart.feeder.config.OperatingData;
import com.zhonglai.luhui.smart.feeder.config.ScheduledConfig;
import com.zhonglai.luhui.smart.feeder.dto.CameraConfig;
import com.zhonglai.luhui.smart.feeder.opencv.OpenCVUtil;
import com.zhonglai.luhui.smart.feeder.service.impl.HtmllVeiwServiceImpl;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import com.zhonglai.luhui.smart.feeder.service.device.CameraHandle;
import com.zhonglai.luhui.smart.feeder.service.device.handle.CameraRtspHandle;
import org.bytedeco.opencv.opencv_core.Point2f;
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.video.BackgroundSubtractorMOG2;
import org.opencv.video.Video;
import org.opencv.videoio.VideoCapture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import static com.zhonglai.luhui.smart.feeder.service.InitService.*;
/**
* 鱼群图像识别
*/
@Service
public class FishGroupImageRecognitionService {
private static final Logger logger = LoggerFactory.getLogger(FishGroupImageRecognitionService.class);
@Autowired
private FFmCameraService fFmCameraService;
@Autowired
private ScheduledExecutorService scheduledExecutorService;
@Autowired
private ConfigurationParameterService configurationParameterService;
private static BackgroundSubtractorMOG2 backgroundSubtractor;
@Autowired
private DeviceService deviceService;
private static Mat frame = new Mat(); //原图
private static Mat diff = new Mat(); //移动的图片
private static Boolean isRun = false;
private static Mat thresh = new Mat(); //二值化图片
private VeiwDto veiwDto;
private Boolean isText = false;
private MatOfPoint largestContour;
public FishGroupImageRecognitionService()
{
backgroundSubtractor = Video.createBackgroundSubtractorMOG2();
}
public void run()
{
scheduledExecutorService.scheduleWithFixedDelay(() -> {
if (!isRun)
ScheduledConfig.scheduler.scheduleWithFixedDelay(() -> {
if (!OperatingData.cameraData.getFishGroupImageRecognIsRun())
{
start();
OperatingData.cameraData.setFishGroupImageRecognIsRun(false);
}
},1,1,TimeUnit.SECONDS);
}
// 创建FrameConverter对象
public void start()
{
if(fFmCameraService.getVideoIsOpen()) //摄像头打开才能识别
{
isRun = true;
configurationParameterService.setConfig(ConfigurationParameter.FishGroupImageRecognition,true);
brightnessIdentifyFishRegion();
}
}
public void stop()
private void start()
{
configurationParameterService.setConfig(ConfigurationParameter.FishGroupImageRecognition,false);
fFmCameraService.close();
isRun = false;
}
CameraHandle cameraHandle = InitService.cameraHandle;
/**
* 获取标准水域轮廓
* @param previousFrame
* @return
*/
private MatOfPoint getDefaultMatOfPoint(Mat previousFrame)
{
Mat firstBinaryImage = waterBybinary(previousFrame,(Integer) configurationParameterService.getConfig(ConfigurationParameter.reflectionThreshold));
// 绘制白色区域的轮廓
List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchy = new Mat();
Imgproc.findContours(firstBinaryImage, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
// 找到最大区域
double maxArea = 0;
int maxAreaIndex = -1;
for (int i = 0; i < contours.size(); i++) {
MatOfPoint matOfPoint = contours.get(i);
double area = Imgproc.contourArea(matOfPoint);
if (area > maxArea) {
maxArea = area;
maxAreaIndex = i;
}
}
// 获取最大区域的轮廓
MatOfPoint largestContour = contours.get(maxAreaIndex);
contours.remove(maxAreaIndex);
for(MatOfPoint matOfPoint:contours)
if(!cameraHandle.isOpen())
{
matOfPoint.release();
cameraHandle.init();
}
firstBinaryImage.release();
hierarchy.release();
return largestContour;
OperatingData.cameraData.setFishGroupImageRecognIsRun(true);
brightnessIdentifyFishRegion();
}
/**
* 亮度查找水面,透明度过滤鱼群
*/
private void brightnessIdentifyFishRegion()
{
logger.info("启动鱼群识别");
// 读取第一帧并获取视频大小
org.opencv.core.Mat previousFrame = fFmCameraService.getMat();
if (null == previousFrame) {
System.out.println("无法读取视频帧");
return;
}
logger.info("鱼群识别时检测摄像头");
// 获取水域轮廓
if(null != largestContour)
Long time =1000l;
if(null != OperatingData.cameraConfig.getIdentificationFrequency())
{
largestContour.release();
time = OperatingData.cameraConfig.getIdentificationFrequency();
}
largestContour = getDefaultMatOfPoint(previousFrame);
Long time =66l;
if(null != configurationParameterService.getConfig(ConfigurationParameter.IdentificationFrequency))
while (cameraHandle.isOpen())
{
time = (Long) configurationParameterService.getConfig(ConfigurationParameter.IdentificationFrequency);
}
// 逐帧处理视频
scheduledExecutorService.scheduleWithFixedDelay(() -> {
try {
Boolean fishGroupImageRecognition = ((Boolean)configurationParameterService.getConfig(ConfigurationParameter.FishGroupImageRecognition));
Mat frame = fFmCameraService.getMat();
Boolean fishGroupImageRecognition = OperatingData.cameraConfig.getFishGroupImageRecognition();
frame = CameraRtspHandle.mat.clone();
Boolean isread = false;
if(null != frame)
{
... ... @@ -158,140 +106,133 @@ public class FishGroupImageRecognitionService {
return;
}
if (fishGroupImageRecognition && isread) {
identify(frame);
yidong(frame);
}
frame.release();
}catch (Exception e)
{
logger.error("识别错误",e);
}finally {
if(null != frame)
{
frame.release();
}
try {
Thread.sleep(time);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
},0,time, TimeUnit.MILLISECONDS);
previousFrame.release();
}
public void setText(Boolean text) {
isText = text;
}
}
/**
* 识别
* 检测移动
* @return
*/
private void identify(Mat frame)
private void yidong(Mat image)
{
//抠图
Mat shuiyu = OpenCVUtil.matting(frame,largestContour);
// 2. 转换为灰度图像
Mat gray = new Mat();
Imgproc.cvtColor(shuiyu, gray, Imgproc.COLOR_BGR2GRAY);
// 3. 进行阈值分割以得到二值图像
Mat binaryImage = new Mat();
Imgproc.threshold(gray, binaryImage, 100, 255, Imgproc.THRESH_BINARY);
List<MatOfPoint> contours = new ArrayList<>(); // 用于存储找到的轮廓
Mat hierarchy = new Mat(); // 轮廓的层次结构
// 在水域二值图像中找所有轮廓
Imgproc.findContours(binaryImage, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
if(null != isText && isText)
if(!image.empty())
{
//标注识别对象
Imgproc.drawContours(frame, contours, -1, new Scalar(0, 0, 255), 2);
Imgproc.drawContours(frame, Arrays.asList(new MatOfPoint[]{largestContour}), 0, new Scalar(0, 255, 0), 2);
}
backgroundSubtractor.apply(image, diff); // 应用背景减法获取运动部件
//计算大小
double area = getArea(contours);
// 执行阈值和形态学操作
Imgproc.threshold(diff, thresh, OperatingData.cameraConfig.getTrendsPixelMin(), OperatingData.cameraConfig.getTrendsPixelMax(), Imgproc.THRESH_BINARY);
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(OperatingData.cameraConfig.getKernelSize(), OperatingData.cameraConfig.getKernelSize()));
Imgproc.dilate(thresh, thresh, kernel, new Point(-1, -1), 2);
//计算斜率
double absValue = deviceService.controlDevice(area);
configurationParameterService.setConfig(ConfigurationParameter.absValue,absValue);
//找到动作的轮廓
List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchy = new Mat();
Imgproc.findContours(thresh, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
veiwDto = new VeiwDto(new Double(area).intValue(),absValue);
double[] dsTotal = new double[5];
// 显示图像
logger.info("是否显示{},客户端数量{}",configurationParameterService.getConfig(ConfigurationParameter.ifVeiw),WebSocketClien.webSocketSet.size());
// 在图像上显示结果
logger.info("socket数量{}",WebSocketClien.webSocketSet.size());
if((Boolean)configurationParameterService.getConfig(ConfigurationParameter.ifVeiw) && WebSocketClien.webSocketSet.size()>0)
{
new HtmllVeiwServiceImpl(configurationParameterService).veiw(veiwDto);
}
shuiyu.release();
gray.release();
hierarchy.release();
binaryImage.release();
}
contours.removeIf(matOfPoint -> {
Rect rect = Imgproc.boundingRect(matOfPoint);
matOfPoint.release();
if(rect.width!=image.width() && rect.width>OperatingData.cameraConfig.getCalloutBoxWidthMin())
{
double[] ds = count(image,rect);
if(filterate(ds))
{
dsTotal[0]+=ds[0];
dsTotal[1]+=ds[1];
dsTotal[2]+=ds[2];
dsTotal[3]+=ds[3];
dsTotal[4]++;
Imgproc.rectangle(image, rect.tl(), rect.br(), new Scalar(0, 255, 0), 2);
return false;
}
}
return true;
});
/**
* 计算鱼群面积
* @param contours
* @return
*/
private double getArea(List<MatOfPoint> contours) {
// 找到最大区域
double maxArea = 0;
int maxAreaIndex = -1;
double allArea = 0;
for (int i = 0; i < contours.size(); i++) {
MatOfPoint matOfPoint = contours.get(i);
double area = Imgproc.contourArea(matOfPoint);
if (area > maxArea) {
maxArea = area;
maxAreaIndex = i;
if(0!=dsTotal[4])
{
double brightness = dsTotal[0]/dsTotal[4];
double reflection= dsTotal[1]/dsTotal[4];
double transparencyMeasure= dsTotal[2]/dsTotal[4];
double area= dsTotal[3]/dsTotal[4];
//计算斜率
double slope = area - (null==OperatingData.cameraData.getArea()?area:OperatingData.cameraData.getArea());
//当前斜率的差值
double slopeDifference = slope-(null==OperatingData.cameraData.getSlope()?slope:OperatingData.cameraData.getSlope());
//计算斜率差值的绝对值
double absValue = Math.abs(slopeDifference);
OperatingData.cameraData.setBrightness(brightness);
OperatingData.cameraData.setReflection(reflection);
OperatingData.cameraData.setTransparencyMeasure(transparencyMeasure);
OperatingData.cameraData.setArea(area);
OperatingData.cameraData.setSlope(slope);
OperatingData.cameraData.setSlopeDifference(slopeDifference);
OperatingData.cameraData.setAbsValue(absValue);
}
allArea += area;
matOfPoint.release();
}
//删除最大
if(-1 != maxAreaIndex)
{
contours.remove(maxAreaIndex);
}
// 返回总面积
return allArea;
}
private static Mat hsvImage = new Mat();
private static Mat grayImage = new Mat();
private static Scalar meanGray = Core.mean(grayImage);
/**
* 根据反光查找水面
* @param frame
* @return
* 运算
* @param image
* @param rect
*/
public Mat waterBybinary(Mat frame,int reflectionThreshold) {
// 将加载的图像转换为灰度图像,以便进行亮度或反光的分析
Mat grayImage = new Mat();
Imgproc.cvtColor(frame, grayImage, Imgproc.COLOR_BGR2GRAY);
// 检测反光
Mat binaryImage = new Mat();
Imgproc.threshold(grayImage, binaryImage, reflectionThreshold, (Integer) configurationParameterService.getConfig(ConfigurationParameter.maxValue), Imgproc.THRESH_BINARY);
// 进行形态学操作,去除噪点
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size((Integer) configurationParameterService.getConfig(ConfigurationParameter.kernelSize),(Integer) configurationParameterService.getConfig(ConfigurationParameter.kernelSize)));
Imgproc.morphologyEx(binaryImage, binaryImage, Imgproc.MORPH_OPEN, kernel);
grayImage.release();
kernel.release();
return binaryImage;
}
public VeiwDto getVeiwDto() {
return veiwDto;
private double[] count(Mat image,Rect rect)
{
// 计算轮廓区域内的反光、亮度和透明度值
Mat roi = new Mat(image, rect);
// 计算亮度
Imgproc.cvtColor(roi, hsvImage, Imgproc.COLOR_BGR2HSV);
Scalar mean = Core.mean(hsvImage);
double brightness = mean.val[2];
// 计算反光
Imgproc.cvtColor(roi, grayImage, Imgproc.COLOR_BGR2GRAY);
Core.MinMaxLocResult minMaxLocResult = Core.minMaxLoc(grayImage);
double reflection = minMaxLocResult.maxVal;
// 计算灰度均值
double meanGrayValue = meanGray.val[0];
// 将灰度均值映射到0到255范围内作为透明度度量(较低的灰度值表示较高的透明度,反之亦然)
double transparencyMeasure = 255 - meanGrayValue;
//计算面积
Size roiSize = roi.size();
double area = roiSize.width * roiSize.height;
roi.release();
return new double[]{brightness,reflection,transparencyMeasure,area};
}
public void setVeiwDto(VeiwDto veiwDto) {
this.veiwDto = veiwDto;
private boolean filterate(double[] ds)
{
return OperatingData.cameraConfig.getReflectionMax()>ds[1] && ds[1]>OperatingData.cameraConfig.getReflectionMin()
&& OperatingData.cameraConfig.getBrightnessMax()>ds[0] && ds[0]>OperatingData.cameraConfig.getBrightnessMin()
&& ds[2]>OperatingData.cameraConfig.getTransparencyMeasureMin() && ds[2]<OperatingData.cameraConfig.getTransparencyMeasureMax()
&& ds[3]>OperatingData.cameraConfig.getAreaMin() && ds[3]<OperatingData.cameraConfig.getAreaMax();
}
}
... ...
package com.zhonglai.luhui.smart.feeder.service;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.util.concurrent.ScheduledExecutorService;
import com.zhonglai.luhui.smart.feeder.service.device.CameraHandle;
import com.zhonglai.luhui.smart.feeder.service.device.SerialPortService;
import com.zhonglai.luhui.smart.feeder.service.device.handle.CameraRtspHandle;
import com.zhonglai.luhui.smart.feeder.service.netty.NettyClient;
@Configuration
public class InitService {
@Autowired
private FFmCameraService fFmCameraService;
public static SerialPortService serialPortService;
@Autowired
private ConfigurationParameterService configurationParameterService;
public static CameraHandle cameraHandle;
@Autowired
private DateListenService dateListenService;
@Autowired
private DeviceService deviceService;
@Autowired
private FishGroupImageRecognitionService fishGroupImageRecognitionService;
@Autowired
private SqliteService sqliteService;
@Autowired
private TerminalService terminalService;
public static NettyClient nettyClient;
public static DeviceService deviceService;
/**
* 守护摄像头
* 加载配置
*/
@PostConstruct
private void run() throws MqttException {
//持久化初始
sqliteService.init();
public static void initConfig() {
//配置参数
configurationParameterService.initConfigurationParameter();
//摄像头监听
fFmCameraService.start();
//鱼群识别
fishGroupImageRecognitionService.run();
ConfigurationParameterService.initConfigurationParameter();
}
public static void startService()
{
/**
* 串口服务器启动
*/
serialPortService = new SerialPortService();
/**
* mq远程登录
*/
nettyClient = new NettyClient();
nettyClient.start();
/**
* 初始化海康的摄像头
*/
cameraHandle = new CameraRtspHandle();
/**
* 图像识别
*/
new FishGroupImageRecognitionService().run();
//鱼群图像识别控制投料控制
deviceService = new DeviceService(serialPortService);
deviceService.run();
//连接上报终端
terminalService.startMqttListenerService();
//串口数据上报
dateListenService.run();
//数据上报
new DateListenService(serialPortService).run();
}
}
... ...
package com.zhonglai.luhui.smart.feeder.service;
import com.google.gson.JsonObject;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.smart.feeder.domain.Register;
import com.zhonglai.luhui.smart.feeder.dto.ConfigDto;
import com.zhonglai.luhui.smart.feeder.dto.VeiwDto;
import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommd06Response;
import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommdDto;
import com.zhonglai.luhui.smart.feeder.dto.commd.FeederTimer;
import com.zhonglai.luhui.smart.feeder.service.device.SerialPortService;
import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil;
import org.eclipse.paho.client.mqttv3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class MqttCallback implements MqttCallbackExtended {
private static final Logger log = LoggerFactory.getLogger(MqttCallback.class);
@Autowired
private ConfigurationParameterService configurationParameterService;
@Autowired
private SerialPortService serialPortService;
@Autowired
private SrsService srsService;
@Autowired
private FishGroupImageRecognitionService fishGroupImageRecognitionService;
private MqttClient mqttclient;
@Value("#{'${mqtt.topics}'.split(',')}")
private List<String> topics;
@Override
public void connectComplete(boolean b, String s) {
log.info("连接成功");
try {
subscribe();
} catch (MqttException e) {
throw new RuntimeException(e);
}
}
@Override
public void connectionLost(Throwable cause) {
log.error("连接丢失",cause);
}
public MqttCallback setMqttClient(MqttClient mqttclient)
{
this.mqttclient = mqttclient;
return this;
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
log.info("收到消息 {}",message);
if(topic.indexOf("PUT")>=0)
{
Map<String, Register> map = configurationParameterService.getControlMap();
byte[] bs = message.getPayload();
if(null != bs && bs.length!=0)
{
String str = new String(bs);
JsonObject jsonObject = GsonConstructor.get().fromJson(str, JsonObject.class);
if(jsonObject.has("10_1")) //投料机控制
{
JsonObject controlData = jsonObject.get("10_1").getAsJsonObject();
Map<Integer, FeederTimer> timerMap = new HashMap<>();
for (String key:controlData.keySet())
{
if(key.startsWith("timer"))
{
Integer timerNumber = Integer.parseInt(key.split("_")[0].replace("timer",""));
FeederTimer feederTimer = timerMap.get(timerNumber);
if(null == feederTimer)
{
feederTimer = new FeederTimer();
timerMap.put(timerNumber,feederTimer);
}
feederTimer.setObjectValue(key.replace(""+timerNumber+"",""),Long.valueOf(controlData.get(key).getAsString()));
}else {
Register register = map.get(key);
serialPortService.sendHexData(new FeederCommdDto(new FeederCommd06Response(register.getAddress(),controlData.get(key).getAsInt())).getHstr());
}
}
if(null != timerMap && timerMap.size() != 0)
{
for (Integer timerNumber:timerMap.keySet())
{
serialPortService.sendHexData(FeederCommdUtil.controlTimer(timerNumber,timerMap.get(timerNumber)));
}
}
}
else if(jsonObject.has("0")) //主机
{
ConfigDto configDto = GsonConstructor.get().fromJson(jsonObject.get("0").toString(),ConfigDto.class);
configurationParameterService.setConfig(configDto.getConfigurationParameter(),configDto.getValue());
}
else if(jsonObject.has("1_1")) //探头
{
VeiwDto veiwDto = GsonConstructor.get().fromJson(jsonObject.get("1_1").toString(),VeiwDto.class);
if(null != veiwDto.getPush_camera())
{
switch (veiwDto.getPush_camera())
{
case 0:
srsService.stop();
break;
case 1:
srsService.run(300);
fishGroupImageRecognitionService.setText(veiwDto.getText());
srsService.setDisplaySrc(veiwDto.getDisplaySrc());
break;
}
}
}
}
}
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
// 成功发出消息
log.info("成功发出消息 messageid{}",token);
}
private void subscribe() throws MqttException {
mqttclient.subscribe(topics.toArray(new String[topics.size()]));
}
}
package com.zhonglai.luhui.smart.feeder.service;
import org.bytedeco.javacv.Frame;
public interface PushVideo {
void display(Frame filteredFrame);
}
... ...
package com.zhonglai.luhui.smart.feeder.service;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.dao.service.PublicService;
import com.zhonglai.luhui.smart.feeder.domain.Register;
import com.zhonglai.luhui.smart.feeder.dto.ConfigurationParameter;
import com.zhonglai.luhui.smart.feeder.dto.FishCurveControlCondition;
import com.zhonglai.luhui.smart.feeder.dto.SerialPortConfig;
import com.zhonglai.luhui.smart.feeder.mapper.AbsValueCommandMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class SqliteService {
private static Logger logger = LoggerFactory.getLogger(SqliteService.class);
@Autowired
private PublicService publicService;
@Autowired
private AbsValueCommandMapper absValueCommandMapper;
@Value("${spring.datasource.druid.master.url}")
private String masterUrl;
public void init()
{
initDb();
initSysConfig();
initAbsValueCommand();
}
/**
* 数据库
*/
private void initDb()
{
logger.info("检查数据库文件");
File dbFile = new File(masterUrl.replace("jdbc:sqlite:",""));
if (!dbFile.exists()) {
logger.info("数据库文件不存在自动创建");
try {
// 创建新的数据库文件
boolean created = dbFile.createNewFile();
if (created) {
System.out.println("成功创建数据库文件my.db");
// 进行其他初始化操作,如创建表格等
} else {
System.out.println("创建数据库文件my.db失败");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 配置表
*/
private void initSysConfig()
{
logger.info("检查配置表");
Long ct = publicService.selectCountBySql("SELECT count(*) ct FROM sqlite_master WHERE type='table' AND `name`='sys_config'");
if (0==ct)
{
logger.info("配置表不存在自动创建");
publicService.updateBySql("CREATE TABLE \"sys_config\" (\n" +
" \"parameter_name\" TEXT NOT NULL,\n" +
" \"parameter_value\" TEXT NOT NULL,\n" +
" \"describe\" TEXT,\n" +
" PRIMARY KEY (\"parameter_name\"),\n" +
" CONSTRAINT \"名称唯一\" UNIQUE (\"parameter_name\" ASC)\n" +
")");
logger.info("初始化置表数据");
publicService.updateBySql("INSERT INTO \"sys_config\" VALUES ('ifVeiw', 'false', '是否显示');\n" +
"INSERT INTO \"sys_config\" VALUES ('captureNumber', '0', '摄像头编号');\n" +
"INSERT INTO \"sys_config\" VALUES ('reflectionThreshold', '100', '反光阈值');\n" +
"INSERT INTO \"sys_config\" VALUES ('kernelSize', '3', '去噪调整内核大小,用来消除小的物体或噪声');\n" +
"INSERT INTO \"sys_config\" VALUES ('maxValue', '255.0', '最大反光阈值');\n" +
"INSERT INTO \"sys_config\" VALUES ('VeiwDto_isFrame', 'false', '是否显示原图');\n" +
"INSERT INTO \"sys_config\" VALUES ('VeiwDto_isBinaryImage', 'false', '是否显示临时图');\n" +
"INSERT INTO \"sys_config\" VALUES ('VeiwDto_isSize', 'false', '是否显示面积');\n" +
"INSERT INTO \"sys_config\" VALUES ('VeiwDto_isAbsValue', 'false', '是否显示斜率');\n" +
"INSERT INTO \"sys_config\" VALUES ('absValue', '0', '是否显示斜率');\n" +
"INSERT INTO \"sys_config\" VALUES ('FishGroupImageRecognition', 'true', '鱼群图像识别是否开启');\n" +
"INSERT INTO \"sys_config\" VALUES ('FeedingControl', 'true', '鱼群图像识别投料控制是否开启');\n" +
"INSERT INTO \"sys_config\" VALUES ('SerialPortConfig', '{\"portName\": \"COM6\",\"baudrate\": 9600,\"dataBits\": 8,\"stopBits\": 0,\"parity\": 0}', '串口配置');\n" +
"\n" );
}
}
private void initAbsValueCommand() {
logger.info("检查斜率范围对应的档位表");
Long ct = publicService.selectCountBySql("SELECT count(*) ct FROM sqlite_master WHERE type='table' AND name='absValue_command'");
if (0 == ct)
{
logger.info("斜率范围对应的档位不存在自动创建");
publicService.updateBySql("CREATE TABLE \"absValue_command\" (\n" +
" \"sartAbsValue\" integer,\n" +
" \"gear\" integer NOT NULL,\n" +
" PRIMARY KEY (\"gear\"),\n" +
" CONSTRAINT \"档位唯一\" UNIQUE (\"gear\" ASC)\n" +
")");
}
}
public List<Map<String,Object>> getAllSysConfig()
{
return publicService.getObjectListBySQL("SELECT * FROM sys_config");
}
public List<FishCurveControlCondition> getAllAbsValueCommand()
{
return absValueCommandMapper.getFishCurveControlConditionList("SELECT * FROM absValue_command");
}
public List<Map<String,Object>> getAllRegister()
{
return publicService.getObjectListBySQL("SELECT * FROM register");
}
public void updateConfigurationParameter(ConfigurationParameter key,Object value)
{
switch (key)
{
case absValue_command:
List<FishCurveControlCondition> list = (List<FishCurveControlCondition>) value;
for(FishCurveControlCondition fishCurveControlCondition:list)
{
updateabsValueCommand(fishCurveControlCondition.getGear(),fishCurveControlCondition.getSartAbsValue());
}
break;
default:
updateSysConfig(key, key.valueToString(value));
break;
}
}
public void updateSysConfig(ConfigurationParameter key,String value)
{
publicService.updateBySql("delete from sys_config where parameter_name='"+key.name()+"'");
publicService.updateBySql("insert into sys_config(`parameter_name`,`parameter_value`,`describe`) values ('"+key.name()+"','"+value+"','"+key.getDescribe()+"')");
}
public void updateabsValueCommand(Integer gear,Integer sartAbsValue)
{
publicService.updateBySql("delete from absValue_command where sartAbsValue="+sartAbsValue+"");
publicService.updateBySql("insert into absValue_command(`gear`,`sartAbsValue`) values ("+gear+",'"+sartAbsValue+"')");
}
public void deleteabsValueCommandAll()
{
publicService.updateBySql("delete from absValue_command ");
}
}
package com.zhonglai.luhui.smart.feeder.service;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.ip.IpUtils;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 终端服务
*/
@Service
public class TerminalService {
private static final Logger log = LoggerFactory.getLogger(TerminalService.class);
private MqttClient mqttclient;
private MqttConnectOptions options;
@Autowired
private MqttCallback mqttCallback;
@Value("${mqtt.broker}")
private String broker;
@Value("${mqtt.clientId}")
private String clientId;
@Value("${mqtt.username}")
private String username;
@Value("${mqtt.password}")
private String password;
public void startMqttListenerService() throws MqttException{
log.info("-----------开始启动mqtt监听服务--------------------");
init();
connect();
Map<String,Object> dmap = new HashMap<>();
Map<String,Object> map = new HashMap<>();
dmap.put("summary",map);
map.put("localhostIp",IpUtils.getLocalHost());
JSONObject jsonObject = new JSONObject();
jsonObject.put("0",dmap);
String topic = "ADD_POST";
publish(topic,jsonObject.toJSONString());
}
public void init() throws MqttException {
if(null == mqttclient)
{
mqttclient = new MqttClient(broker, clientId, new MemoryPersistence());
}
options = new MqttConnectOptions();
options.setCleanSession(true);
options.setConnectionTimeout(15);
//设置断开后重新连接
options.setAutomaticReconnect(true);
mqttclient.setCallback(mqttCallback.setMqttClient(mqttclient));
}
private void connect() throws MqttException {
options.setUserName(username);
options.setPassword(password.toCharArray());
mqttclient.connect(options);
}
public void publish(String topic, MqttMessage message) throws MqttException {
mqttclient.publish(topic,message);
}
public void publish(String topic, String messageStr) throws MqttException {
MqttMessage message = new MqttMessage();
message.setPayload(messageStr.getBytes());
mqttclient.publish(topic,message);
}
public void scheduledSubmissionData(String messageStr) throws MqttException {
String topic = "ALL_POST";
publish(topic,messageStr);
}
public void close()
{
try {
options.setAutomaticReconnect(false);
if(null != mqttclient && mqttclient.isConnected())
{
mqttclient.disconnect();
mqttclient.close();
}
} catch (MqttException e) {
log.error("关闭失败",e);
}
}
}
package com.zhonglai.luhui.smart.feeder.service;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.GsonConstructor;
import com.ruoyi.common.utils.StringUtils;
import com.zhonglai.luhui.smart.feeder.config.WebSocketClien;
import com.zhonglai.luhui.smart.feeder.dto.WebSocketVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* 会话连接
*/
@ServerEndpoint("/websocket/{userId}")
@Component
public class WebSocketSever {
private static final Logger log = LoggerFactory.getLogger(WebSocketSever.class);
@Autowired
private DeviceService deviceService;
// 与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
private Boolean runState = false;
/**
* 建立WebSocket连接
*
* @param session
* @param userId 用户ID
*/
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") Integer userId) {
log.info("WebSocket建立连接中,连接用户ID:{}", userId);
WebSocketClien.login(userId);
// 建立连接
this.session = session;
WebSocketClien.webSocketSet.add(this);
WebSocketClien.sessionPool.put(userId, session);
log.info("建立连接完成,当前在线人数为:{}", WebSocketClien.webSocketSet.size());
sendMessageByUser(userId,AjaxResult.success("链接成功").toString());
}
/**
* 发生错误
*
* @param throwable e
*/
@OnError
public void onError(Throwable throwable) {
throwable.printStackTrace();
}
/**
* 连接关闭
*/
@OnClose
public void onClose() {
WebSocketClien.webSocketSet.remove(this);
log.info("连接断开,当前在线人数为:{}", WebSocketClien.webSocketSet.size());
}
/**
* 接收客户端消息
*
* @param message 接收的消息
*/
@OnMessage
public void onMessage(String message) {
log.info("收到客户端发来的消息:{}", message);
if(StringUtils.isNotEmpty(message))
{
switch (message)
{
case "openRunState":
runState = true;
case "closeRunState":
runState = false;
}
}
}
/**
* 推送消息到指定用户
*
* @param userId 用户ID
* @param message 发送的消息
*/
public void sendMessageByUser(Integer userId, String message) {
log.info("用户ID:" + userId + ",推送内容:" + message);
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
log.error("推送消息到指定用户发生错误:" + e.getMessage(), e);
}
}
/**
* 推送消息到指定用户
*
* @param webSocketVO 用户ID
*/
public void sendWebSocketVO(WebSocketVO webSocketVO) {
try {
if(runState)
{
webSocketVO.setStateData(deviceService.getState());
}
session.getBasicRemote().sendText(JSONObject.toJSONString(webSocketVO));
} catch (IOException e) {
log.error("推送消息到指定用户发生错误:" + e.getMessage(), e);
}
}
/**
* 群发消息
*
* @param message 发送的消息
*/
public void sendAllMessage(String message) {
log.info("发送消息:{}", message);
for (WebSocketSever webSocket : WebSocketClien.webSocketSet) {
try {
webSocket.session.getBasicRemote().sendText(message);
} catch (IOException e) {
log.error("群发消息发生错误:" + e.getMessage(), e);
}
}
}
}
package com.zhonglai.luhui.smart.feeder.service.device;
import org.bytedeco.javacv.Frame;
import com.zhonglai.luhui.smart.feeder.service.PushVideo;
public interface CameraHandle {
public void init();
public boolean init();
public org.opencv.core.Mat getMat();
public boolean isOpen();
public void pushVideo(PushVideo pushVideo);
}
... ...
package com.zhonglai.luhui.smart.feeder.service.device;
import com.ruoyi.common.utils.StringUtils;
import com.zhonglai.luhui.smart.feeder.config.OperatingData;
import com.zhonglai.luhui.smart.feeder.dto.ConfigurationParameter;
import org.opencv.videoio.VideoCapture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
* 摄像头
*/
@Service
public class CameraService {
private static final Logger logger = LoggerFactory.getLogger(CameraService.class);
@Value("${sys.network_camera_ip}")
private String ip;
@Value("${sys.mp4_file_path}")
private String MP4_FILE_PATH;
private VideoCapture videoCapture;
private ScheduledFuture scheduledFuture;
@Autowired
private ScheduledExecutorService scheduledExecutorService;
/**
* 初始化摄像头
*/
private void openCapture()
{
switch (OperatingData.cameraConfig.getCameraInterfaceType().toUpperCase())
{
case "USB":
videoCapture = readVideoCaptureForUSB();
break;
case "RTSP":
videoCapture = readVideoCaptureForRtsp();
break;
default:
videoCapture = readVideoCaptureForFile();
}
if(null == videoCapture)
{
return;
}
monitorCapture();
}
/**
* 检测摄像头是否打开
*/
private void monitorCapture()
{
// 检查视频是否成功打开
if (null !=videoCapture && videoCapture.isOpened()) {
OperatingData.cameraData.setVideoIsOpen(true);
return;
}
OperatingData.cameraData.setVideoIsOpen(false);
}
/**
* 开启
*/
public void start()
{
if(null == scheduledFuture || scheduledFuture.isDone())
{
scheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(() -> {
logger.info("摄像头状态{}",OperatingData.cameraData.isVideoIsOpen());
if(!OperatingData.cameraData.isVideoIsOpen())
{
openCapture();
}
},0,1, TimeUnit.SECONDS);
}
logger.info("启动摄像头{}");
}
/**
* 关闭
*/
public void close()
{
if(scheduledFuture.isDone())
{
scheduledFuture.cancel(true);
}
if(OperatingData.cameraData.isVideoIsOpen())
{
OperatingData.cameraData.setVideoIsOpen(false);
// 释放资源
videoCapture.release();
}
logger.info("关闭摄像头");
}
/**
* 释放资源
*/
public void clean()
{
if(OperatingData.cameraData.isVideoIsOpen())
{
OperatingData.cameraData.setVideoIsOpen(false);
// 释放资源
videoCapture.release();
}
}
public VideoCapture getVideoCapture() {
return videoCapture;
}
/**
* 读取网络摄像头
* @return
*/
public VideoCapture readVideoCaptureForRtsp()
{
String rtspUrl = "rtsp://admin:Luhui586@"+ip+":554/h264/ch1/main/av_stream";
VideoCapture videoCapture = new VideoCapture(rtspUrl);
while (!videoCapture.isOpened())
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return videoCapture;
}
/**
* 读取USB口的摄像头
* @return
*/
public VideoCapture readVideoCaptureForUSB()
{
for(int i=0;i<10;i++)
{
logger.info("初始化摄像头");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
VideoCapture videoCapture = new VideoCapture();
boolean isopen = videoCapture.open(i);
if(isopen)
{
logger.info("打开化摄像头"+i+"成功");
return videoCapture;
}else {
logger.info("打开化摄像头"+i+"失败");
}
if(null != videoCapture)
{
return videoCapture; //拿到的第一个摄像头返回
}
}
logger.info("未检测到USB摄像头!!!");
return null;
}
/**
* 读取本地视频文件
* @return
*/
private VideoCapture readVideoCaptureForFile()
{
logger.info("未检测到摄像头{},尝试打开本地视频",MP4_FILE_PATH);
//如果找不到摄像头就找本地视频文件
File file = new File(MP4_FILE_PATH);
if(file.exists() && file.isFile())
{
VideoCapture videoCapture = new VideoCapture();
boolean isopen = videoCapture.open(MP4_FILE_PATH);
System.out.println(isopen);
return videoCapture;
}
return null;
}
}
... ... @@ -5,7 +5,7 @@ import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;
import com.ruoyi.common.utils.ByteUtil;
import com.zhonglai.luhui.smart.feeder.dto.ConfigurationParameter;
import com.zhonglai.luhui.smart.feeder.config.OperatingData;
import com.zhonglai.luhui.smart.feeder.dto.ModbusDto;
import com.zhonglai.luhui.smart.feeder.dto.SerialPortConfig;
import com.zhonglai.luhui.smart.feeder.dto.commd.FeederCommdDto;
... ... @@ -22,7 +22,6 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@Service
public class SerialPortService {
private static final Logger logger = LoggerFactory.getLogger(SerialPortService.class);
private SerialPort serialPort;
... ... @@ -31,10 +30,8 @@ public class SerialPortService {
private final Object lock = new Object();
// 用于存储串口返回的数据,使用线程安全的队列
private BlockingQueue<ModbusDto> dataQueue = new LinkedBlockingQueue<>();
@Autowired
private ConfigurationParameterService configurationParameterService;
public void init()
public SerialPortService()
{
open();
}
... ... @@ -60,7 +57,8 @@ public class SerialPortService {
private void setComPortParameters()
{
SerialPortConfig serialPortConfig = (SerialPortConfig)configurationParameterService.getConfig(ConfigurationParameter.SerialPortConfig);
SerialPortConfig serialPortConfig = OperatingData.feederConfig.getSerialPortConfig();
serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 1000, 1000);//设置超时
serialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);//设置串口的控制流,可以设置为disabled,或者CTS, RTS/CTS, DSR, DTR/DSR, Xon, Xoff, Xon/Xoff等
... ... @@ -72,7 +70,10 @@ public class SerialPortService {
if(null == serialPort || !serialPort.isOpen())
{
serialPort = findSerialPort();
setComPortParameters();
if(null != serialPort)
{
setComPortParameters();
}
}
if(null == serialPort)
{
... ...
package com.zhonglai.luhui.smart.feeder.service.device.handle;
import com.ruoyi.common.utils.ByteUtil;
import com.sun.jna.Pointer;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.utils.StringUtils;
import com.zhonglai.luhui.smart.feeder.config.OperatingData;
import com.zhonglai.luhui.smart.feeder.dto.HCCameraRepose;
import com.zhonglai.luhui.smart.feeder.service.ConfigurationParameterService;
import com.zhonglai.luhui.smart.feeder.service.PushVideo;
import com.zhonglai.luhui.smart.feeder.service.device.CameraHandle;
import com.zhonglai.luhui.smart.feeder.service.device.CameraService;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.opencv_core.IplImage;
import org.opencv.core.Mat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import javax.swing.*;
import java.io.File;
import java.net.*;
import java.util.Enumeration;
import java.util.Random;
import java.util.UUID;
public class CameraRtspHandle implements CameraHandle {
private static final Logger logger = LoggerFactory.getLogger(CameraRtspHandle.class);
private FFmpegFrameGrabber grabber;
private String ip = "192.168.0.198";
private OpenCVFrameConverter.ToOrgOpenCvCoreMat converter2;
private FFmpegFrameFilter filter;
public static Mat mat;
public CameraRtspHandle()
{
init();
}
@Override
public void init() {
public boolean init() {
if(isOpen())
{
return true;
}
try {
FFmpegFrameGrabber.tryLoad();
String rtspUrl = "rtsp://admin:Luhui586@"+ip+":554/h264/ch1/main/av_stream";
grabber = new FFmpegFrameGrabber(rtspUrl);
// grabber.setOption("framerate", "30"); // 设置帧率为30帧/秒
grabber.setVideoOption("fflags", "nobuffer");
grabber.setVideoOption("rtsp_transport", "tcp");
grabber.setOption("stimeout", "2000000");
avutil.av_log_set_level(avutil.AV_LOG_ERROR);
grabber.start();
switch (OperatingData.cameraConfig.getCameraInterfaceType().toLowerCase())
{
case "rtsp":
if(!initRtsp())
{
return false;
}
break;
case "local":
if(!iniLocal())
{
return false;
}
break;
default:
return false;
}
// 创建一个FFmpegFrameFilter对象,用于图像压缩
filter = new FFmpegFrameFilter("scale=640:-1", grabber.getImageWidth(), grabber.getImageHeight());
try {
filter.start();
} catch (FFmpegFrameFilter.Exception e) {
throw new RuntimeException(e);
}
converter2 = new OpenCVFrameConverter.ToOrgOpenCvCoreMat();
Thread.sleep(3000);
Thread thread = new Thread(() -> {
while (isOpen()) {
try {
mat = getMat();
} catch (Exception e) {
logger.error("抓取摄像头帧失败",e);
}
}
});
thread.start();
return true;
} catch (Exception e) {
logger.error("摄像头初始化失败",e);
return false;
}
}
private boolean iniLocal() throws FFmpegFrameGrabber.Exception, InterruptedException {
File file = new File("2.pm4");
if(!file.exists())
{
return false;
}
grabber = new FFmpegFrameGrabber(file);
avutil.av_log_set_level(avutil.AV_LOG_ERROR);
grabber.start();
while (!grabber.hasAudio() || !grabber.hasVideo())
{
Thread.sleep(1000);
}
return true;
}
private boolean initRtsp() throws FFmpegFrameGrabber.Exception, InterruptedException {
String ip = findCameraIp();
if(StringUtils.isEmpty(ip))
{
logger.error("未找到摄像头");
return false;
}
String rtspUrl = "rtsp://admin:Luhui586@"+ip+":554/h264/ch1/main/av_stream";
grabber = new FFmpegFrameGrabber(rtspUrl);
// grabber.setOption("framerate", "30"); // 设置帧率为30帧/秒
// grabber.setOption("skip_frame", "nokey"); // 只抓取关键帧
// grabber.setOption("skip_initial_bytes", "1"); // 跳过初始字节直到第一个关键帧
grabber.setVideoOption("fflags", "nobuffer");
grabber.setVideoOption("-vf", "nobuffer");
// grabber.setOption("buffer_size", "4096"); // 设置缓冲区大小为1024字节
grabber.setVideoOption("rtsp_transport", "tcp");
grabber.setOption("stimeout", "2000000");
avutil.av_log_set_level(avutil.AV_LOG_ERROR);
grabber.start();
while (!grabber.hasAudio() || !grabber.hasVideo())
{
Thread.sleep(1000);
}
return true;
}
public boolean isOpen()
{
if(null == grabber)
{
return false;
}
if(grabber.isDeinterlace())
{
close();
return false;
}
if(grabber.isCloseInputStream())
{
close();
return false;
}
if(grabber.isTriggerMode())
{
close();
return false;
}
if(!grabber.hasAudio())
{
close();
return false;
}
if(!grabber.hasVideo())
{
close();
return false;
}
return true;
}
@Override
public Mat getMat() {
return null;
Frame frame = getFrame();
if(null == frame)
{
return null;
}
return converter2.convert(frame);
}
public static void main(String[] args) {
// CameraRtspHandle cameraRtspHandle = new CameraRtspHandle();
// cameraRtspHandle.init();
// FFmpegFrameGrabber grabber = cameraRtspHandle.grabber;
//
// CanvasFrame previewCanvas = new CanvasFrame("摄像头预览", CanvasFrame.getDefaultGamma() / grabber.getGamma());
// previewCanvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// previewCanvas.setAlwaysOnTop(true);
//
// // 创建一个FFmpegFrameFilter对象,用于图像压缩
// FFmpegFrameFilter filter = new FFmpegFrameFilter("scale=640:-1", grabber.getImageWidth(), grabber.getImageHeight());
// try {
// filter.start();
// } catch (FFmpegFrameFilter.Exception e) {
// throw new RuntimeException(e);
// }
//
//
// while (true)
// {
// logger.info("当前grabber状态:hasAudio {},hasVideo {},isCloseInputStream {},isDeinterlace {},isTriggerMode {}",grabber.hasAudio(),grabber.hasVideo(),grabber.isCloseInputStream(),grabber.isDeinterlace(),grabber.isTriggerMode());
// try {
// filter.push(grabber.grabImage());
// Frame filteredFrame = filter.pull();
// if(null != filteredFrame)
// {
// previewCanvas.showImage(filteredFrame);
// }
// } catch (FFmpegFrameGrabber.Exception e) {
// logger.info("无法显示");
// } catch (FFmpegFrameFilter.Exception e) {
// throw new RuntimeException(e);
// }
// }
// 创建UDP Socket
MulticastSocket socket = null;
try {
socket = new MulticastSocket (37020);
socket.setTimeToLive(1);
// socket.setSoTimeout(10000);
socket.joinGroup( InetAddress.getByName("239.255.255.250"));
} catch (SocketException e) {
throw new RuntimeException(e);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
public Frame toFram(Mat mat) {
if(null == mat)
{
return null;
}
return converter2.convert(mat);
}
private Frame getFrame() {
Frame frame = null;
try {
frame = grabber.grabImage();
if (frame == null || frame.imageHeight==0) {
//TODO:连续n次为null,进行重连
logger.info("读取不到画面,当前grabber状态:hasAudio {},hasVideo {},isCloseInputStream {},isDeinterlace {},isTriggerMode {}",grabber.hasAudio(),grabber.hasVideo(),grabber.isCloseInputStream(),grabber.isDeinterlace(),grabber.isTriggerMode());
return null;
}
else{
return frame;
}
} catch (Exception e) {
logger.error("抓取摄像头帧失败",e);
return null;
}
for (int i=0;i<3;i++)
{
UUID uuid = UUID.randomUUID();
String uuidString = uuid.toString().toUpperCase();
// 构造sadp请求数据包
String str = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Probe><Uuid>"+uuidString+"</Uuid><Types>inquiry</Types></Probe>";
}
byte[] requestData = str.getBytes();
DatagramPacket requestPacket = new DatagramPacket(requestData, requestData.length, InetAddress.getByName("239.255.255.250"), 37020);
public Frame compress(Frame frame)
{
try {
filter.push(frame);
Frame filteredFrame = filter.pull();
return filteredFrame;
} catch (FFmpegFrameFilter.Exception e) {
logger.error("压缩失败",e);
}
return frame;
}
Thread.sleep(1000);
// 发送请求数据包
socket.send(requestPacket);
public void pushVideo(PushVideo pushVideo)
{
logger.info("当前grabber状态:hasAudio {},hasVideo {},isCloseInputStream {},isDeinterlace {},isTriggerMode {}",grabber.hasAudio(),grabber.hasVideo(),grabber.isCloseInputStream(),grabber.isDeinterlace(),grabber.isTriggerMode());
if(grabber.hasAudio() && grabber.hasVideo())
{
try {
Frame filteredFrame = compress(grabber.grabImage());
if(null != filteredFrame)
{
pushVideo.display(filteredFrame);
}
} catch (FFmpegFrameGrabber.Exception e) {
logger.info("无法显示");
}
}
}
public static void main(String[] args) {
ConfigurationParameterService.initConfigurationParameter();
CameraRtspHandle cameraRtspHandle = new CameraRtspHandle();
if(cameraRtspHandle.isOpen())
{
CanvasFrame previewCanvas = new CanvasFrame("摄像头预览", CanvasFrame.getDefaultGamma() / cameraRtspHandle.grabber.getGamma());
previewCanvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
previewCanvas.setAlwaysOnTop(true);
while (true)
{
// 接收响应数据包
byte[] responseData = new byte[4096];
DatagramPacket responsePacket = new DatagramPacket(responseData, responseData.length);
socket.receive(responsePacket);
// 解析响应数据包
String response = new String(responsePacket.getData(), 0, responsePacket.getLength());
System.out.println("Response: " + response);
cameraRtspHandle.pushVideo(filteredFrame -> previewCanvas.showImage(filteredFrame));
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
socket.leaveGroup( InetAddress.getByName("239.255.255.250"));
} catch (IOException e) {
throw new RuntimeException(e);
}
private static String getLocalIp()
{
Enumeration<NetworkInterface> interfaces = null;
try {
interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
continue;
}
Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress addr = addresses.nextElement();
if (addr.isSiteLocalAddress()) { // Checks if this address is a "site local" address.
if(addr.getHostAddress().contains("192.168"))
{
return addr.getHostAddress();
}
}
}
}
// 关闭Socket
socket.close();
} catch (SocketException e) {
}
return null;
}
public static String formatUuid(String uuid) {
return uuid.substring(0, 8) + "-" +
uuid.substring(8, 12) + "-" +
uuid.substring(12, 16) + "-" +
uuid.substring(16, 20) + "-" +
uuid.substring(20);
public static String findCameraIp() {
String localIP = getLocalIp();
if(null == localIP)
{
return null;
}
try {
final String[] ip = new String[1];
final Object lock = new Object();
Thread thread1 = new Thread(() -> {
try {
synchronized (lock) {
ip[0] = getCameraIp(localIP);
lock.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
});
Thread thread2 = new Thread(() -> {
try {
while (StringUtils.isEmpty(ip[0]))
{
findCamera(localIP);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread1.start();
thread2.start();
synchronized (lock) {
lock.wait(5000);
}
return ip[0];
} catch (InterruptedException e) {
}
return null;
}
public static void sendudp()
private static void findCamera(String ip)
{
try {
// 创建组播Socket
InetAddress group = InetAddress.getByName("239.255.255.250");
MulticastSocket socket = new MulticastSocket(37020);
InetAddress group = InetAddress.getByName("239.255.255.250"); // 组播地址
int port = 37020; // 组播端口
// 加入组播组
socket.joinGroup(group);
MulticastSocket multicastSocket = new MulticastSocket(new InetSocketAddress(InetAddress.getByName(ip), 37020));
while (socket.isConnected())
{
// 接收消息
byte[] buffer = new byte[4096];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
// 解析消息并处理
String message = new String(packet.getData(), 0, packet.getLength());
System.out.println("Received message: " + message);
}
// 退出组播组
socket.leaveGroup(group);
// 发送消息
String uuid = UUID.randomUUID().toString().toUpperCase();
String message = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<Probe>" +
" <Uuid>" + uuid + "</Uuid>" +
" <Types>inquiry</Types>" +
"</Probe>";
byte[] buffer = message.getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, port);
multicastSocket.send(packet);
// 关闭Socket
socket.close();
multicastSocket.close();
} catch (Exception e) {
e.printStackTrace();
}finally {
}
}
/**
* 生成UUID的方法
* @return 返回 UUID 字符串
*/
public static String generateUUID() {
// 获取当前时间戳
long timeMillis = 1697789348000l;
// 获取机器MAC地址
String macAddress = "G24198441";
// 生成随机数
int randomInt = new Random().nextInt();
// 获取个人或组织的标识码(这里设为 001)
int nodeId = 001;
// 组合 UUID 字符串
String uuid = String.format("%016x", timeMillis) //
+ String.format("%016x", randomInt) //
+ String.format("%016x", nodeId) //
+ macAddress;
// 返回 UUID 字符串
return uuid;
}
}
private static String getCameraIp(String ip) throws Exception {
// 1.创建组播socket,加入指定的组播地址和端口
InetAddress group = InetAddress.getByName("239.255.255.250");
MulticastSocket multicastSocket = new MulticastSocket(37020);
multicastSocket.joinGroup(new InetSocketAddress(group,37020),NetworkInterface.getByInetAddress(InetAddress.getByName(ip)));
multicastSocket.setSoTimeout(100000);
// 2.创建接收的数据包
byte[] buf = new byte[1024];
// 4.解析数据包,并打印出来
HCCameraRepose probe = null;
while (ObjectUtil.isEmpty(probe))
{
DatagramPacket dpReceive = new DatagramPacket(buf, buf.length);
// 3.调用socket对象的接收方法接收数据包
multicastSocket.receive(dpReceive);
String receivedXml = new String(dpReceive.getData(), 0, dpReceive.getLength());
String startTag = "<IPv4Address>";
String endTag = "</IPv4Address>";
int start = receivedXml.indexOf(startTag);
int end = receivedXml.indexOf(endTag);
if(start<0)
{
continue;
}
// 检查是否找到标签
if (start == -1 || end == -1) {
return "No IPv4Address tag found.";
}
// 计算开始位置(包含开始标签的长度,因为我们想要从标签后面开始截取)
start = start + startTag.length();
// 截取并返回结果
return receivedXml.substring(start, end);
}
return probe.getIPv4Address();
}
public void close()
{
if(null != grabber)
{
try {
grabber.release();
grabber.close();
grabber = null;
} catch (FrameGrabber.Exception e) {
logger.info("摄像头关闭失败",e);
}
}
if(null !=converter2)
{
converter2.close();
}
}
}
... ...
package com.zhonglai.luhui.smart.feeder.service.feeder;
import com.google.gson.JsonObject;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.smart.feeder.config.OperatingData;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.CmdDto;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.HeadDto;
import com.zhonglai.luhui.smart.feeder.service.netty.NettyClient;
import com.zhonglai.luhui.smart.feeder.util.MessageUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 协议解析
*/
public class AgreementHandler extends MessageToMessageDecoder<String> {
private CfgdataService cfgdataService = new CfgdataService();
private ManualcontrolService manualcontrolService = new ManualcontrolService();
private CameracontrolService cameracontrolService = new CameracontrolService();
private NettyClient nettyClient;
public AgreementHandler(NettyClient nettyClient)
{
this.nettyClient = nettyClient;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
nettyClient.setCtx(ctx);
// 连接建立时的处理,发送请求注册消息给服务器
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("cmd","manualcontrol");
jsonObject.addProperty("type","4G.hs");
MessageUtil.sendMessage(ctx, new CmdDto().setImei(OperatingData.sysConfig.getNettyConfig().getClientId()).setJsonObject(jsonObject).generateCmd(),true);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
Thread.sleep(3000);
nettyClient.close();
Thread.sleep(3000);
nettyClient.start();
}
private static boolean checkAgreement(String data)
{
String regEx = "(?:\\^)\\d+\\{.*}\\w+(?:~)";
// 编译正则表达式
Pattern pattern = Pattern.compile(regEx);
// 忽略大小写的写法
// Pattern pat = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(data);
// 字符串是否与正则表达式相匹配
boolean rs = matcher.matches();
return rs;
}
@Override
protected void decode(ChannelHandlerContext ctx, String msg, List<Object> out) throws Exception {
try {
System.out.println("读取到数据:"+msg);
if(StringUtils.isNotBlank(msg) && checkAgreement(msg))
{
CmdDto cmdDto = new CmdDto(msg);
if(cmdDto.checkLRC())
{
HeadDto headDto = GsonConstructor.get().fromJson(cmdDto.getJsonObject(), HeadDto.class);
switch (headDto.getCmd())
{
case "devicedataOK":
break;
case "cfgdata":
cfgdataService.noticeFeeder(ctx,cmdDto);
break;
case "manualcontrol":
manualcontrolService.noticeFeeder(ctx,cmdDto);
break;
case "cameracontrol":
cameracontrolService.noticeFeeder(ctx,cmdDto);
break;
default:
break;
}
}
}
}catch (Exception e)
{
}
}
}
... ...
package com.zhonglai.luhui.smart.feeder.service.feeder;
import com.google.gson.JsonObject;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.smart.feeder.config.OperatingData;
import com.zhonglai.luhui.smart.feeder.dto.CameraConfig;
import com.zhonglai.luhui.smart.feeder.dto.commd.FeederBackstateTtpe;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.CameracontrolRequest;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.CmdDto;
import com.zhonglai.luhui.smart.feeder.service.InitService;
import com.zhonglai.luhui.smart.feeder.service.device.handle.CameraRtspHandle;
import com.zhonglai.luhui.smart.feeder.util.FeederCommd06ResponseType;
import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil;
import com.zhonglai.luhui.smart.feeder.util.MessageUtil;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CameracontrolService {
private static final Logger logger = LoggerFactory.getLogger(CameracontrolService.class);
public void noticeFeeder(ChannelHandlerContext ctx,CmdDto cmdDto)
{
if(!InitService.cameraHandle.isOpen())
{
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.cameraErr,0);
return;
}
JsonObject data = cmdDto.getJsonObject();
if (null == data || data.size()==0)
{
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.success,0xE2);
return;
}
try {
CameracontrolRequest cameracontrolRequest = GsonConstructor.get().fromJson(data.toString(), CameracontrolRequest.class);
OperatingData.setClassObjecValue(cameracontrolRequest.getCameraConfig(), (fieldname, fieldObject) -> {
switch (fieldname)
{
case "cameraInterfaceType":
((CameraRtspHandle)InitService.cameraHandle).close();
InitService.cameraHandle.init();
break;
}
});
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.success,0);
}catch (Exception e)
{
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.runErr,0);
}
}
}
... ...
package com.zhonglai.luhui.smart.feeder.service.feeder;
import com.google.gson.JsonObject;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.smart.feeder.Main;
import com.zhonglai.luhui.smart.feeder.config.OperatingData;
import com.zhonglai.luhui.smart.feeder.domain.Register;
import com.zhonglai.luhui.smart.feeder.dto.CameraConfig;
import com.zhonglai.luhui.smart.feeder.dto.commd.FeederBackstateTtpe;
import com.zhonglai.luhui.smart.feeder.dto.commd.FeederTimer;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.CameracontrolRequest;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.CfgdataRequest;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.CmdDto;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.Condata;
import com.zhonglai.luhui.smart.feeder.service.ConfigurationParameterService;
import com.zhonglai.luhui.smart.feeder.service.InitService;
import com.zhonglai.luhui.smart.feeder.util.FeederCommd06ResponseType;
import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil;
import com.zhonglai.luhui.smart.feeder.util.MessageUtil;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
public class CfgdataService {
private static final Logger logger = LoggerFactory.getLogger(CfgdataService.class);
public void noticeFeeder(ChannelHandlerContext ctx,CmdDto cmdDto)
{
if(!InitService.serialPortService.open())
{
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.serialPortErr,0);
return;
}
JsonObject data = cmdDto.getJsonObject();
if (null == data || data.size()==0)
{
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.success,0xE2);
return;
}
try {
CfgdataRequest cfgdataRequest = GsonConstructor.get().fromJson(data.toString(), CfgdataRequest.class);
OperatingData.setClassObjecValue(cfgdataRequest.getCondata(), (fieldname, fieldObject) -> {
try {
String commd = FeederCommdUtil.controlData( FeederCommd06ResponseType.valueOf(fieldname),(Integer) fieldObject);
logger.info("远程发送指令{}",commd);
InitService.serialPortService.sendStrData(commd);
}catch (Exception e)
{
logger.error("发送指令失败:"+GsonConstructor.get().toJson(fieldname),e);
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.serialPortCommandSendErr,0);
throw new RuntimeException(e);
}
});
List<Integer[]> timerList = cfgdataRequest.getTimer();
if(null != timerList && timerList.size() != 0 )
{
for (int i=0;i<timerList.size();i++)
{
Integer[] timerNumber = timerList.get(i);
FeederTimer feederTimer = new FeederTimer();
feederTimer.setTimer_start_m(timerNumber[1]);
feederTimer.setTimer_start_h(timerNumber[0]);
feederTimer.setTimer_if_start(timerNumber[4]);
feederTimer.setTimer_is_start(1);
feederTimer.setTimer_close_m(timerNumber[3]);
feederTimer.setTimer_close_h(timerNumber[2]);
feederTimer.setTimer_if_close(timerNumber[4]);
feederTimer.setTimer_is_close(1);
InitService.serialPortService.sendHexData(FeederCommdUtil.controlTimer((i/2)+1,feederTimer));
}
}
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.success,0);
}catch (Exception e)
{
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.runErr,0);
}
}
}
... ...
package com.zhonglai.luhui.smart.feeder.service.feeder;
import com.google.gson.JsonObject;
import com.ruoyi.common.utils.GsonConstructor;
import com.zhonglai.luhui.smart.feeder.config.OperatingData;
import com.zhonglai.luhui.smart.feeder.dto.commd.FeederBackstateTtpe;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.CfgdataRequest;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.CmdDto;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.Condata;
import com.zhonglai.luhui.smart.feeder.dto.mqtt.ManualcontrolRequest;
import com.zhonglai.luhui.smart.feeder.service.InitService;
import com.zhonglai.luhui.smart.feeder.util.FeederCommd06ResponseType;
import com.zhonglai.luhui.smart.feeder.util.FeederCommdUtil;
import com.zhonglai.luhui.smart.feeder.util.MessageUtil;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
public class ManualcontrolService {
private static final Logger logger = LoggerFactory.getLogger(CfgdataService.class);
public void noticeFeeder(ChannelHandlerContext ctx,CmdDto cmdDto)
{
if(!InitService.serialPortService.open())
{
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.serialPortErr,0);
return;
}
JsonObject data = cmdDto.getJsonObject();
if (null == data || data.size()==0)
{
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.success,0xE2);
return;
}
try {
ManualcontrolRequest manualcontrolRequest = GsonConstructor.get().fromJson(data.toString(), ManualcontrolRequest.class);
OperatingData.setClassObjecValue(manualcontrolRequest.getCondata(), (fieldname, fieldObject) -> {
try {
String commd = FeederCommdUtil.controlData( FeederCommd06ResponseType.valueOf(fieldname),(Integer) fieldObject);
logger.info("远程发送指令{}",commd);
InitService.serialPortService.sendStrData(commd);
}catch (Exception e)
{
logger.error("发送指令失败:"+GsonConstructor.get().toJson(fieldname),e);
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.serialPortCommandSendErr,0);
throw new RuntimeException(e);
}
});
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.success,0);
}catch (Exception e)
{
MessageUtil.sendFeederResponseMessage(ctx,"cfgdataOK", FeederBackstateTtpe.runErr,0);
}
}
}
... ...