Browse Source

环境项目第一次提交

邵洋 1 year ago
parent
commit
5c09e8b323
26 changed files with 1398 additions and 4 deletions
  1. 84 0
      environment-data-service/pom.xml
  2. 21 0
      environment-data-service/src/main/java/com/zksy/environment/EnvironmentApplication.java
  3. 127 0
      environment-data-service/src/main/java/com/zksy/environment/config/NtServer.java
  4. 65 0
      environment-data-service/src/main/java/com/zksy/environment/domain/po/PictureMessage.java
  5. 95 0
      environment-data-service/src/main/java/com/zksy/environment/domain/po/StationHour.java
  6. 13 0
      environment-data-service/src/main/java/com/zksy/environment/enums/DataSourceEnum.java
  7. 16 0
      environment-data-service/src/main/java/com/zksy/environment/mapper/PictureMessageMapper.java
  8. 17 0
      environment-data-service/src/main/java/com/zksy/environment/mapper/StationHourMapper.java
  9. 26 0
      environment-data-service/src/main/java/com/zksy/environment/service/PictureMessageService.java
  10. 26 0
      environment-data-service/src/main/java/com/zksy/environment/service/StationHourService.java
  11. 154 0
      environment-data-service/src/main/java/com/zksy/environment/service/impl/PictureMessageServiceImpl.java
  12. 123 0
      environment-data-service/src/main/java/com/zksy/environment/service/impl/StationHourServiceImpl.java
  13. 151 0
      environment-data-service/src/main/java/com/zksy/environment/utils/DataCheckUtil.java
  14. 27 0
      environment-data-service/src/main/java/com/zksy/environment/utils/DateTimeUtil.java
  15. 50 0
      environment-data-service/src/main/java/com/zksy/environment/utils/HexToImageConverter.java
  16. 161 0
      environment-data-service/src/main/java/com/zksy/environment/utils/MonitorDatasynch.java
  17. 14 0
      environment-data-service/src/main/java/com/zksy/environment/utils/NettyConfig.java
  18. 26 0
      environment-data-service/src/main/java/com/zksy/environment/utils/ResponseEncoder.java
  19. 90 0
      environment-data-service/src/main/java/com/zksy/environment/utils/ServerHandler.java
  20. 19 0
      environment-data-service/src/main/resources/application-dev.yaml
  21. 17 0
      environment-data-service/src/main/resources/application-prod.yaml
  22. 31 0
      environment-data-service/src/main/resources/bootstrap.yaml
  23. 16 0
      environment-data-service/src/main/resources/mapper/PictureMessageMapper.xml
  24. 22 0
      environment-data-service/src/main/resources/mapper/StationHourMapper.xml
  25. 7 0
      pom.xml
  26. 0 4
      zksy-gateway/src/main/java/com/zksy/gateway/filter/AuthGlobalFilter.java

+ 84 - 0
environment-data-service/pom.xml

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.zksy</groupId>
+        <artifactId>dh-server-micro</artifactId>
+        <version>1.0.0</version>
+    </parent>
+    <artifactId>environment-data-service</artifactId>
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <!--common-->
+        <dependency>
+            <groupId>com.zksy</groupId>
+            <artifactId>zksy-common</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <!--web-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <!--数据库-->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <!--mybatis-->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+        </dependency>
+        <!--nacos 服务注册发现-->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <!--负载均衡-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
+        </dependency>
+        <!--统一配置管理-->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+        <!--加载bootstrap-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-bootstrap</artifactId>
+        </dependency>
+        <!--redis-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <!--sentinel-->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.zksy</groupId>
+            <artifactId>minioutil</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 21 - 0
environment-data-service/src/main/java/com/zksy/environment/EnvironmentApplication.java

@@ -0,0 +1,21 @@
+package com.zksy.environment;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @author Administrator
+ * @version 1.0
+ * @project dh-server-micro
+ * @description
+ * @date 2024/8/14 10:59:19
+ */
+@MapperScan("com.zksy.environment.mapper")
+@SpringBootApplication
+public class EnvironmentApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(EnvironmentApplication.class,args);
+        System.out.println("启动成功");
+    }
+}

+ 127 - 0
environment-data-service/src/main/java/com/zksy/environment/config/NtServer.java

@@ -0,0 +1,127 @@
+package com.zksy.environment.config;
+
+import com.zksy.environment.utils.ServerHandler;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.ServerSocketChannel;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.ByteToMessageDecoder;
+import io.netty.handler.timeout.IdleStateHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@Configuration
+public class NtServer {
+
+    @Value("${netty.port:8084}")
+    private int port;
+
+    private ServerSocketChannel serverSocketChannel;
+
+    private EventLoopGroup boss;
+
+    private EventLoopGroup worker;
+
+    @PostConstruct
+    private void startServer() {
+        log.info("进入程序....");
+        Thread thread = new Thread(() -> {
+            //服务端要建立两个group,一个负责接收客户端的连接,一个负责处理数据传输
+            //连接处理group
+            boss = new NioEventLoopGroup(1);
+            //事件处理group
+            worker = new NioEventLoopGroup();
+
+            ServerBootstrap bootstrap = new ServerBootstrap();
+            // 绑定处理group
+            bootstrap.group(boss, worker).channel(NioServerSocketChannel.class)
+                    //保持连接数
+                    .option(ChannelOption.SO_BACKLOG, 300)
+                    //有数据立即发送
+                    .option(ChannelOption.TCP_NODELAY, true)
+                    //保持连接
+                    .childOption(ChannelOption.SO_KEEPALIVE, true)
+                    // 设置心跳检测
+                    .childHandler(new ChannelInitializer<SocketChannel>() {
+                        @Override
+                        protected void initChannel(SocketChannel sc) throws Exception {
+                            ChannelPipeline p = sc.pipeline();
+                            // 添加心跳检测处理器
+                            p.addLast(new IdleStateHandler(0, 0, 180, TimeUnit.SECONDS)); // 每3分钟检查一次空闲状态
+                            // 添加解码器将字节数据解码成16进制字符串
+                            p.addLast(new HexDecoder());
+                            p.addLast(new ServerHandler());
+                        }
+                    });
+
+            //绑定端口,同步等待成功
+            ChannelFuture future;
+            try {
+                future = bootstrap.bind(port).sync();
+                if (future.isSuccess()) {
+                    serverSocketChannel = (ServerSocketChannel) future.channel();
+                    log.info("服务端启动成功,端口:" + port);
+                } else {
+                    log.info("服务端启动失败!");
+                }
+
+                //等待服务监听端口关闭
+                future.channel().closeFuture().sync();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            } finally {
+                //退出,释放线程池资源
+                boss.shutdownGracefully();
+                worker.shutdownGracefully();
+            }
+        });
+        thread.start();
+    }
+
+    /**
+     * 释放资源
+     */
+    @PreDestroy
+    public void destroy() {
+        if (boss != null) {
+            boss.shutdownGracefully();
+        }
+        if (worker != null) {
+            worker.shutdownGracefully();
+        }
+    }
+
+    static class HexDecoder extends ByteToMessageDecoder {
+
+        @Override
+        protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+            // 读取2个字节数据
+            byte[] hexBytes = new byte[in.readableBytes()];
+            in.readBytes(hexBytes);
+
+            // 将字节数据转换为16进制字符串
+            String hexData = bytesToHex(hexBytes);
+            // 将16进制字符串添加到输出列表
+            out.add(hexData);
+        }
+
+        // 将字节数组转换为16进制字符串
+        private String bytesToHex(byte[] bytes) {
+            StringBuilder hexBuilder = new StringBuilder();
+            for (byte b : bytes) {
+                hexBuilder.append(String.format("%02X", b));
+            }
+            return hexBuilder.toString();
+        }
+    }
+}

+ 65 - 0
environment-data-service/src/main/java/com/zksy/environment/domain/po/PictureMessage.java

@@ -0,0 +1,65 @@
+package com.zksy.environment.domain.po;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 遥测站图片报或中心站查询遥测站图片采集信息
+ * </p>
+ *
+ * @author Yang
+ * @since 2024-08-09
+ */
+@Data
+@TableName("picture_message")
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value = "遥测站图片报或中心站查询遥测站图片采集信息(报送 JPG 图片信息)")
+public class PictureMessage extends Model<PictureMessage> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id", type = IdType.ASSIGN_UUID)
+    private String id;
+
+    /**
+     * 发报时间
+     */
+    private LocalDateTime sendingMessageTime;
+
+    /**
+     * 测站地址
+     */
+    private String measuringStationAddress;
+
+    /**
+     * 测站类型
+     */
+    private String measuringStationType;
+
+    /**
+     * 观测时间
+     */
+    private LocalDateTime observeTime;
+
+    /**
+     * 报文图片
+     */
+    private String message;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+}

+ 95 - 0
environment-data-service/src/main/java/com/zksy/environment/domain/po/StationHour.java

@@ -0,0 +1,95 @@
+package com.zksy.environment.domain.po;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 遥测站小时报-报送以小时为基本单位的历史数据和实时数据
+ * </p>
+ *
+ * @author Yang
+ * @since 2023-12-19
+ */
+@Data
+@TableName("station_hour")
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value = "遥测站小时报-报送以小时为基本单位的历史数据和实时数据")
+public class StationHour extends Model<StationHour> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id", type = IdType.ASSIGN_UUID)
+    private String id;
+
+    /**
+     *功能码
+     */
+    private String functionCode;
+
+    /**
+     * 发报时间
+     */
+    private LocalDateTime sendingMessageTime;
+
+    /**
+     * 测站地址
+     */
+    private String measuringStationAddress;
+
+    /**
+     * 测站类型
+     */
+    private String measuringStationType;
+
+    /**
+     * 观测时间
+     */
+    private LocalDateTime observeTime;
+
+    /**
+     * 水温
+     */
+    private Double waterTemperature;
+
+    /**
+     * 浊度
+     */
+    private Integer turbidity;
+
+    /**
+     * 电压
+     */
+    private Double voltage;
+
+    /**
+     * 信号强度
+     */
+    private Integer signalStrength;
+
+    /**
+     * 设备温度
+     */
+    private Double deviceTemperature;
+
+    /**
+     * 报文
+     */
+    private String message;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+}

+ 13 - 0
environment-data-service/src/main/java/com/zksy/environment/enums/DataSourceEnum.java

@@ -0,0 +1,13 @@
+package com.zksy.environment.enums;
+
+public enum DataSourceEnum {
+    DB1("db1");
+    private String value;
+    DataSourceEnum(String value){
+        this.value = value;
+    }
+    public String getValue(){
+        return this.value;
+    }
+
+}

+ 16 - 0
environment-data-service/src/main/java/com/zksy/environment/mapper/PictureMessageMapper.java

@@ -0,0 +1,16 @@
+package com.zksy.environment.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zksy.environment.domain.po.PictureMessage;
+
+/**
+ * <p>
+ * 遥测站图片报或中心站查询遥测站图片采集信息 Mapper 接口
+ * </p>
+ *
+ * @author Yang
+ * @since 2024-08-09
+ */
+public interface PictureMessageMapper extends BaseMapper<PictureMessage> {
+
+}

+ 17 - 0
environment-data-service/src/main/java/com/zksy/environment/mapper/StationHourMapper.java

@@ -0,0 +1,17 @@
+package com.zksy.environment.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zksy.environment.domain.po.StationHour;
+
+/**
+ * <p>
+ * 遥测站小时报-报送以小时为基本单位的历史数据和实时数据 Mapper 接口
+ * </p>
+ *
+ * @author Yang
+ * @since 2023-12-19
+ */
+public interface StationHourMapper extends BaseMapper<StationHour> {
+
+
+}

+ 26 - 0
environment-data-service/src/main/java/com/zksy/environment/service/PictureMessageService.java

@@ -0,0 +1,26 @@
+package com.zksy.environment.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zksy.environment.domain.po.PictureMessage;
+
+/**
+ * <p>
+ * 遥测站图片报或中心站查询遥测站图片采集信息 服务类
+ * </p>
+ *
+ * @author Yang
+ * @since 2024-08-09
+ */
+public interface PictureMessageService extends IService<PictureMessage> {
+
+    /**
+     * TODO 添加报送 JPG 图片信息
+      * @param dataStr 主体正文
+     * @return boolean
+     * @author Administrator
+     * @date 2024/08/09 09:50:24
+     */
+    boolean savePictureMessage(String oldDataStr,String dataStr);
+
+}

+ 26 - 0
environment-data-service/src/main/java/com/zksy/environment/service/StationHourService.java

@@ -0,0 +1,26 @@
+package com.zksy.environment.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zksy.environment.domain.po.StationHour;
+
+/**
+ * <p>
+ * 遥测站小时报-报送以小时为基本单位的历史数据和实时数据 服务类
+ * </p>
+ *
+ * @author Yang
+ * @since 2023-12-19
+ */
+public interface StationHourService extends IService<StationHour> {
+
+    /**
+     * TODO 添加报送以小时为基本单位的历史数据和实时数据
+      * @param dataStr 主体正文
+     * @return boolean
+     * @author Administrator
+     * @date 2023/12/19 09:50:24
+     */
+    boolean saveStationHour(String oldDataStr,String dataStr);
+
+}

+ 154 - 0
environment-data-service/src/main/java/com/zksy/environment/service/impl/PictureMessageServiceImpl.java

@@ -0,0 +1,154 @@
+package com.zksy.environment.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zksy.environment.domain.po.PictureMessage;
+import com.zksy.environment.mapper.PictureMessageMapper;
+import com.zksy.environment.service.PictureMessageService;
+import com.zksy.environment.utils.DataCheckUtil;
+import com.zksy.environment.utils.DateTimeUtil;
+import com.zksy.environment.utils.HexToImageConverter;
+import com.zksy.service.MinioFileStorageService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.nio.file.Paths;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * <p>
+ * 遥测站图片报或中心站查询遥测站图片采集信息 服务实现类
+ * </p>
+ *
+ * @author Yang
+ * @since 2024-08-09
+ */
+@Slf4j
+@Service
+public class PictureMessageServiceImpl extends ServiceImpl<PictureMessageMapper, PictureMessage> implements PictureMessageService {
+    private final List<String> allDataSegments = new ArrayList<>();
+    private final Object lock = new Object();
+    private HashMap<String,String> map = new HashMap<>();
+    @Autowired
+    private MinioFileStorageService minioFileStorageService;
+    @Override
+    public boolean savePictureMessage(String oldDataStr, String dataStr) {
+        boolean flag = false;
+        try {
+            PictureMessage pictureMessage = new PictureMessage();
+            // 解析数据包
+            String SYN = dataStr.substring(0, 2);
+            String totalHex = dataStr.substring(2, 5);
+            String total = DataCheckUtil.hexToDecimalExample(totalHex);
+            String packageNumberHex = dataStr.substring(5, 8);
+            String packageNumber = DataCheckUtil.hexToDecimalExample(packageNumberHex);
+
+            // 处理数据包
+            String segment;
+            if ("01".equals(packageNumber)) {
+                // 解析初始数据包
+                String serialNumber = dataStr.substring(8, 12);
+                String dataTime = dataStr.substring(12, 24);
+                String sendingMessageTime = "20" + dataTime;
+                map.put("sendingMessageTime", DateTimeUtil.parseDateTime(sendingMessageTime).toString());
+
+                // 测站地址
+                int stationAddressIndex = dataStr.indexOf("f1f1");
+                if (stationAddressIndex != -1 && stationAddressIndex + 10 < dataStr.length()) {
+                    String result = dataStr.substring(stationAddressIndex + 4, stationAddressIndex + 14);
+                    map.put("measuringStationAddress",result);
+                }
+
+                // 测站类型
+                Pattern pattern = Pattern.compile("F0F0", Pattern.CASE_INSENSITIVE);
+                String[] f0F0s = pattern.split(dataStr);
+                String f0F0 = f0F0s[0];
+                if (f0F0.length() >= 2) {
+                    String prefix = f0F0.substring(f0F0.length() - 2);
+                    map.put("measuringStationType",prefix);
+                }
+
+                // 观测时间
+                String f0F01 = f0F0s[1];
+                if (f0F01.length() >= 10) {
+                    String digits = f0F01.substring(0, 10);
+                    String observeTime = "20" + digits + "00";
+                    map.put("observeTime",DateTimeUtil.parseDateTime(observeTime).toString());
+                }
+
+                // 初始化数据段列表
+                synchronized (lock) {
+                    ((ArrayList<String>) allDataSegments).ensureCapacity(Integer.parseInt(total));
+                }
+
+                // 对于首个包,直接获取数据段
+                List<String> dataSegments = new ArrayList<>();
+                int startIndex = dataStr.indexOf("f3f3");
+                if (startIndex != -1) {
+                    segment = dataStr.substring(startIndex + "f3f3".length());
+                    dataSegments.add(segment);
+                }
+                segment = String.join("", dataSegments);
+            } else {
+                // 对于非首个包,直接获取数据段
+                segment = dataStr.substring(8);
+            }
+
+            // 保存数据段
+            synchronized (lock) {
+                int index = Integer.parseInt(packageNumber) - 1;
+                if (index >= allDataSegments.size()) {
+                    // 如果索引超出范围,扩展列表大小
+                    while (allDataSegments.size() <= index) {
+                        allDataSegments.add(null);
+                    }
+                }
+                allDataSegments.set(index, segment);
+
+                System.out.println("packageNumber====="+packageNumber+"total====="+total);
+                // 检查是否所有数据包都已经收到
+                if (Integer.parseInt(packageNumber) == Integer.parseInt(total)) {
+                    // 重新组合所有的数据包
+                    StringBuilder completeImageDataBuilder = new StringBuilder();
+                    for (String segment1 : allDataSegments) {
+                        // 确保 segment 不为 null
+                        if (segment1 != null) {
+                            completeImageDataBuilder.append(segment1);
+                        }
+                    }
+                    String completeImageData = completeImageDataBuilder.toString();
+                    System.out.println("图片集合:" + completeImageData);
+                    File image = HexToImageConverter.hexStringToImage(completeImageData, "output.png");
+
+                    if(ObjectUtils.isNotEmpty(image)){
+                        String filePath = minioFileStorageService.uploadFileByFile(image, "environment-image");
+                        // 设置完整的消息
+                        pictureMessage.setMessage(filePath);
+                        System.out.println("pictureMessage=====" + pictureMessage);
+                        // 设置 ID 和创建时间
+                        pictureMessage.setId(UUID.randomUUID().toString().replace("-", ""));
+                        pictureMessage.setCreateTime(LocalDateTime.now());
+                        pictureMessage.setSendingMessageTime(LocalDateTime.parse(map.get("sendingMessageTime")));
+                        pictureMessage.setMeasuringStationAddress(map.get("measuringStationAddress"));
+                        pictureMessage.setMeasuringStationType(map.get("measuringStationType"));
+                        pictureMessage.setObserveTime(LocalDateTime.parse(map.get("observeTime")));
+                        // 执行保存操作
+                        flag = super.save(pictureMessage);
+                    }
+                    allDataSegments.clear(); // 清空列表以便下次使用
+                }
+            }
+            return flag;
+        } catch (Exception e) {
+            log.info("==========数据解析错误==========", oldDataStr);
+            e.printStackTrace();
+            allDataSegments.clear(); // 清空列表以便下次使用
+        }
+        return flag;
+    }
+}

+ 123 - 0
environment-data-service/src/main/java/com/zksy/environment/service/impl/StationHourServiceImpl.java

@@ -0,0 +1,123 @@
+package com.zksy.environment.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zksy.environment.domain.po.StationHour;
+import com.zksy.environment.mapper.StationHourMapper;
+import com.zksy.environment.service.StationHourService;
+import com.zksy.environment.utils.DateTimeUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+import java.util.regex.Pattern;
+
+/**
+ * <p>
+ * 遥测站小时报-报送以小时为基本单位的历史数据和实时数据 服务实现类
+ * </p>
+ *
+ * @author Yang
+ * @since 2023-12-19
+ */
+@Slf4j
+@Service
+public class StationHourServiceImpl extends ServiceImpl<StationHourMapper, StationHour> implements StationHourService {
+    @Override
+    public boolean saveStationHour(String oldDataStr,String dataStr) {
+        boolean flag = false;
+        try {
+            StationHour stationHour = new StationHour();
+            stationHour.setId(UUID.randomUUID().toString().replace("-", ""));
+            stationHour.setMessage(oldDataStr);
+            stationHour.setCreateTime(LocalDateTime.now());
+
+            //功能码
+            String functionCode = oldDataStr.substring(20, 22);
+            stationHour.setFunctionCode(functionCode);
+            //发报时间
+            String dataTime = dataStr.substring(0, 12);
+            //拼接年份
+            String sendingMessageTime = "20"+dataTime;
+            stationHour.setSendingMessageTime(DateTimeUtil.parseDateTime(sendingMessageTime));
+            //测站地址
+            int stationAddressIndex = dataStr.indexOf("F1F1");
+            // 如果找到了并且后面有10个字符
+            if (stationAddressIndex != -1 && stationAddressIndex + 14 <= dataStr.length()) {
+                // 提取后面的10个字符
+                String result = dataStr.substring(stationAddressIndex + 4, stationAddressIndex + 14);
+                stationHour.setMeasuringStationAddress(result);
+            }
+            //测站类型
+            Pattern pattern = Pattern.compile("F0F0", Pattern.CASE_INSENSITIVE);
+            String[] f0F0s = pattern.split(dataStr);
+            String f0F0 = f0F0s[0];
+            if (f0F0.length() >= 2) {
+                // 取出前两位数字
+                String prefix = f0F0.substring(f0F0.length() - 2);
+                stationHour.setMeasuringStationType(prefix);
+            }
+            //观测时间(到分钟)
+            String f0F01 = f0F0s[1];
+            if (f0F01.length() >= 10) {
+                // 取出前面10位数字
+                String digits = f0F01.substring(0, 10);
+                //拼接年份和秒
+                String observeTime = "20"+digits+"00";
+                stationHour.setObserveTime(DateTimeUtil.parseDateTime(observeTime));
+            }
+            //水温
+            int waterTemperatureIndex = dataStr.indexOf("0311");
+            // 如果找到了并且后面有4个字符
+            if (waterTemperatureIndex != -1 && waterTemperatureIndex + 4 < dataStr.length()) {
+                // 提取后面的4个字符
+                String result = dataStr.substring(waterTemperatureIndex + 4, waterTemperatureIndex + 8);
+                int parseInt = Integer.parseInt(result);
+                double numberDouble = (double) parseInt / 10;
+                stationHour.setWaterTemperature(numberDouble);
+            }
+            //浊度
+            int turbidityIndex = dataStr.indexOf("4919");
+            // 如果找到了并且后面有6个字符
+            if (turbidityIndex != -1 && turbidityIndex + 6 < dataStr.length()) {
+                // 提取后面的6个字符1
+                String result = dataStr.substring(turbidityIndex + 4, turbidityIndex + 10);
+                stationHour.setTurbidity(Integer.parseInt(result));
+            }
+            //电压
+            int voltageIndex = dataStr.indexOf("3812");
+            // 如果找到了并且后面有4个字符
+            if (voltageIndex != -1 && voltageIndex + 4 < dataStr.length()) {
+                // 提取后面的4个字符
+                String result = dataStr.substring(voltageIndex + 4, voltageIndex + 8);
+                int parseInt = Integer.parseInt(result);
+                double numberDouble = (double) parseInt / 100;
+                stationHour.setVoltage(numberDouble);
+            }
+            //信号强度
+            int signalIndex = dataStr.indexOf("7A08");
+            // 如果找到了并且后面有2个字符
+            if (signalIndex != -1 && signalIndex + 2 < dataStr.length()) {
+                // 提取后面的2个字符
+                String result = dataStr.substring(signalIndex + 4, signalIndex + 6);
+                stationHour.setSignalStrength(Integer.parseInt(result));
+            }
+            //设备温度
+            int deviceTemperatureIndex = dataStr.indexOf("FFA011");
+            // 如果找到了并且后面有4个字符
+            if (deviceTemperatureIndex != -1 && deviceTemperatureIndex + 4 < dataStr.length()) {
+                // 提取后面的4个字符
+                String result = dataStr.substring(deviceTemperatureIndex + 6, deviceTemperatureIndex + 10);
+                int parseInt = Integer.parseInt(result);
+                double numberDouble = (double) parseInt / 10;
+                stationHour.setDeviceTemperature(numberDouble);
+            }
+            System.out.println("stationHour====="+stationHour);
+             flag = super.save(stationHour);
+        } catch (Exception e) {
+            log.info("==========数据解析错误==========", dataStr);
+            e.printStackTrace();
+        }
+        return flag;
+    }
+}

+ 151 - 0
environment-data-service/src/main/java/com/zksy/environment/utils/DataCheckUtil.java

@@ -0,0 +1,151 @@
+package com.zksy.environment.utils;
+
+import cn.hutool.core.util.StrUtil;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.util.internal.StringUtil;
+
+/**
+ * @Description
+ * @Date 2021- 06-04-上午 9:02
+ * @auther Javen
+ */
+public class DataCheckUtil {
+    /**
+     * 进行CRC16数据传输协议校验
+     * @param puchMsg
+     * @param usDataLen
+     * @return
+     */
+    public static String crc16_Checkout(String puchMsg, int usDataLen){
+        int i,j,crc_reg,check;
+
+        crc_reg=0xFFFF;
+        char[] chars = puchMsg.toCharArray();
+        for(i=0;i<usDataLen;i++){
+            crc_reg=(crc_reg>>8)^chars[i];
+            for(j=0;j<8;j++) {
+                check = crc_reg&0x0001;
+                crc_reg>>=1;
+                if(check==0x0001) {
+                    crc_reg^=0xA001;
+                }
+            }
+        }
+
+        String code = as10to16(crc_reg);
+        return code;
+    }
+
+    /**
+     * 将10进制转16进制
+     * @param number
+     * @return
+     */
+    public static String as10to16(int number) {
+        int i = 0;
+        StringBuffer dataCode = new StringBuffer();
+        char[] crc16Char = new char[100];
+        if(number == 0){
+            System.out.print(0);
+        } else {
+            while(number!=0) {
+                int t=number%16;
+                if(t >=0 && t<10) {
+                    crc16Char[i] = (char)(t+'0');
+                    i++;
+                } else {
+                    crc16Char[i] = (char)(t+'A'-10);
+                    i++;
+                }
+                number=number/16;
+            }
+
+            for (int j=i-1;j>=0;j--) {
+                dataCode.append(crc16Char[j]);
+            }
+        }
+        //长度补齐4位
+        String paddedString = StrUtil.fillBefore(String.valueOf(dataCode), '0', 4);
+        return paddedString;
+    }
+
+    /**
+     * TODO CRC16/MODBUS校验
+     * @param str 16进制数据
+     * @return java.lang.String
+     * @author Administrator
+     * @date 2023/12/19 13:18:37
+     */
+    public static String getCRC16Result(String str) {
+        String paddedString = "";
+        try {
+            String strReplace = str.replace(" ", "");
+            int CRC = 0x0000FFFF;
+            for (int i = 0; i < strReplace.length(); i += 2) { // 改为 i += 2
+                if (i + 2 > strReplace.length()) { // 添加条件检查
+                    break; // 如果超出范围,则跳出循环
+                }
+                int CRCL = CRC & 0x000000FF; // 低八位
+                int CRCH = CRC & 0x0000FF00; // 高八位
+                String CRCIn = strReplace.substring(i, i + 2);
+                int a = Integer.parseInt(CRCIn, 16); // 待处理数据转16进制
+                CRC = CRCH + CRCL ^ a;
+                for (int j = 0; j < 8; j++) {
+                    if ((CRC & 0x0001) == 0) {
+                        CRC = CRC >> 1;
+                    } else {
+                        CRC >>= 1;
+                        CRC = CRC ^ 0xA001;
+                    }
+                }
+            }
+            String dataCode = Integer.toHexString(CRC);
+            // 小写转大写
+            String upperCaseStr = dataCode.toUpperCase();
+            // 长度补齐4位
+            paddedString = StrUtil.fillBefore(upperCaseStr, '0', 4);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return paddedString;
+    }
+    /**
+     * TODO 16进制转10进制
+     * @param hex
+     * @return String
+     * @author Administrator
+     * @date 2023/11/13 15:31:52
+     */
+    public static String hexToDecimalExample(String hex){
+        String str = "";
+        int decimal=Integer.parseInt(hex,16);
+        if(String.valueOf(decimal).length() < 2){
+            str = "0"+decimal;
+        }else{
+            str = String.valueOf(decimal);
+        }
+        int num = Integer.parseInt(str);
+        if(num > 127){
+            str = String.valueOf(hexToDecimal(num));
+        }
+        return str;
+    }
+
+    /**
+     * TODO 十进制大于127为负值
+     * @param hexString
+     * @return int
+     * @author Administrator
+     * @date 2024/8/6 10:10:04
+     */
+    public static int hexToDecimal(int hexString) {
+        int decimal = 256 - hexString;
+        return -decimal;
+    }
+    public static ByteBuf hexStringToByteBuf(String hexString) {
+        byte[] bytes = StringUtil.decodeHexDump(hexString);
+        return Unpooled.wrappedBuffer(bytes);
+    }
+
+}

+ 27 - 0
environment-data-service/src/main/java/com/zksy/environment/utils/DateTimeUtil.java

@@ -0,0 +1,27 @@
+package com.zksy.environment.utils;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * @Description
+ * @Date 2021- 06-08-下午 16:38
+ * @auther Javen
+ */
+public class DateTimeUtil {
+    /**
+     * 获取现在时间
+     *
+     * @return返回时间格式
+     */
+    public static LocalDateTime parseDateTime(String str) {
+        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
+        LocalDateTime ldt = null;
+        try {
+            ldt = LocalDateTime.parse(str, format);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return ldt;
+    }
+}

+ 50 - 0
environment-data-service/src/main/java/com/zksy/environment/utils/HexToImageConverter.java

@@ -0,0 +1,50 @@
+package com.zksy.environment.utils;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+
+public class HexToImageConverter {
+    /**
+     * 将字节数组保存为图片文件。
+     *
+     * @param hexString  16进制字符串
+     * @param outputFilePath 输出文件路径
+     * @throws IOException 如果写入文件时发生异常
+     */
+    public static File hexStringToImage(String hexString, String outputFilePath) throws IOException {
+        // 将16进制字符串转换为字节数组
+        byte[] imageBytes = hexStringToByteArray(hexString);
+
+        // 使用ImageIO的read方法从字节输入流中读取图片(注意:这里直接读取可能不工作,因为ImageIO.read期望的是图片格式的文件流)
+        // 对于直接从字节数组创建图片,我们通常需要知道图片的具体格式,或者使用 ByteArrayInputStream 包装字节数组
+        BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));
+        File file;
+        if(image != null) {
+            file = new File(outputFilePath);
+            // 保存图片到文件
+            ImageIO.write(image, "PNG", file);
+        }else{
+            file = null;
+        }
+        return file;
+    }
+
+    /**
+     * 将16进制字符串转换成字节数组。
+     *
+     * @param hexString 16进制字符串
+     * @return 字节数组
+     */
+    public static byte[] hexStringToByteArray(String hexString) {
+        int len = hexString.length();
+        byte[] data = new byte[len / 2];
+        for (int i = 0; i < len; i += 2) {
+            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+                    + Character.digit(hexString.charAt(i+1), 16));
+        }
+        return data;
+    }
+}

+ 161 - 0
environment-data-service/src/main/java/com/zksy/environment/utils/MonitorDatasynch.java

@@ -0,0 +1,161 @@
+package com.zksy.environment.utils;
+
+import com.zksy.environment.service.PictureMessageService;
+import com.zksy.environment.service.StationHourService;
+import io.netty.buffer.ByteBuf;
+import io.netty.util.internal.StringUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
+
+/**
+ * @Description
+ * @Date 2021- 06-01-下午 14:37
+ * @auther Javen
+ */
+@Service
+@Slf4j
+@Scope(SCOPE_PROTOTYPE)
+public class MonitorDatasynch {
+    @Autowired
+    private StationHourService stationHourService;
+    @Autowired
+    private PictureMessageService pictureMessageService;
+
+    private final List<String> data1List = new ArrayList<>();
+    private final Object lock = new Object();
+
+    /**
+     * 获取水质同步数据,数据有效性校验,解析
+     */
+    public String pushMonitorData(ByteBuf dataBuf) {
+        String response = null;
+    try {
+        if (dataBuf.isReadable()) {
+            // 读取并转换 ByteBuf 中的数据为16进制字符串
+            String oldDataStr = StringUtil.toHexString(dataBuf.array(), dataBuf.readerIndex(), dataBuf.readableBytes());
+
+            log.info("==========接收到数据:" + oldDataStr + "==========");
+
+            // 获取检验码数据
+            String codeStr = oldDataStr.substring(0, oldDataStr.length() - 4);
+            // 获取数据CRC16检验码
+            String code = "";
+            code = oldDataStr.substring(oldDataStr.length() - 4);
+
+            // 通过数据生成CRC16校验码
+            String nowCode = "";
+            nowCode = DataCheckUtil.getCRC16Result(codeStr);
+
+            //先将两个字符串转换为相同的大小写形式(默认是小写)
+            if (code.equalsIgnoreCase(nowCode)) {
+                boolean flag = false;
+                // dataType == "32" 遥测站定时报,"33" 遥测站加时报,"34" 遥测站小时报,"36" 查询/报送 JPG 图片信息
+                // 获取报文特征
+                String dataType = oldDataStr.substring(20, 22);
+
+                if (!"2F".equalsIgnoreCase(dataType)) {
+                    if ("36".equals(dataType)) {
+                        // 获取数据正文
+                        String dataStr = oldDataStr.substring(26, oldDataStr.length() - 6);
+                        log.info("数据主体正文:" + dataStr);
+                        flag = pictureMessageService.savePictureMessage(oldDataStr, dataStr);
+                        //清除data1List
+                        data1List.clear();
+                    } else {
+                        // 获取数据正文
+                        String dataStr = oldDataStr.substring(32, oldDataStr.length() - 6);
+                        log.info("数据主体正文:" + dataStr);
+                        flag = stationHourService.saveStationHour(oldDataStr, dataStr);
+                    }
+
+                    if (flag) {
+                        log.info("新增成功", oldDataStr);
+                    } else {
+                        log.info("新增失败", oldDataStr);
+                    }
+                } else {
+                    log.info("收到数据========", oldDataStr);
+                }
+            } else {
+                /**
+                 * 图片数据第一条分段接收的问题进行合并
+                 */
+                //开始符
+                String startCharacter = oldDataStr.substring(0, 4);
+                //结束符
+                // 获取字符串的长度
+                int length = oldDataStr.length();
+
+                // 计算倒数第5位和第6位的位置
+                int pos5 = length - 5;
+                int pos6 = length - 6;
+
+                // 截取倒数第5位到倒数第6位的子字符串
+                String subStr = oldDataStr.substring(pos6, pos5 + 1);
+                if(!"7E7E".equalsIgnoreCase(startCharacter) || !"17".equals(subStr)) {
+                    // 将不完整数据存入data1List
+                    synchronized (lock) {
+                        data1List.add(oldDataStr);
+                    }
+                    StringBuilder dataBuilder = new StringBuilder();
+                    if (data1List.size() >= 2) {
+                        for (String data : data1List) {
+                            dataBuilder.append(data);
+                        }
+                    }
+                    if (dataBuilder != null && dataBuilder.length() > 6) {
+                        //开始符
+                        String dataBuilderStartCharacter = dataBuilder.substring(0, 4);
+                        // 获取字符串的长度
+                        int dataLength = dataBuilder.length();
+                        // 计算倒数第5位和第6位的位置
+                        int dataPos5 = dataLength - 5;
+                        int dataPos6 = dataLength - 6;
+                        // 截取倒数第5位到倒数第6位的子字符串
+                        String dataSubStr = dataBuilder.substring(dataPos6, dataPos5 + 1);
+                        if (!"7E7E".equalsIgnoreCase(dataBuilderStartCharacter) && !"17".equals(dataSubStr)) {
+                            return response;
+                        } else {
+                            oldDataStr = dataBuilder.toString();
+                            System.out.println("组合不完整数据dataBuilder======" + dataBuilder);
+                        }
+                    }
+                }
+                // 获取报文特征
+                String dataType = oldDataStr.substring(20, 22);
+
+                // 获取检验码数据
+                String codeStrBuilder = oldDataStr.substring(0, oldDataStr.length() - 4);
+                // 获取数据CRC16检验码
+                String codeBuilder = oldDataStr.substring(oldDataStr.length() - 4);
+
+                // 通过数据生成CRC16校验码
+                String nowCodeBuilder = DataCheckUtil.getCRC16Result(codeStrBuilder);
+                if(codeBuilder.equalsIgnoreCase(nowCodeBuilder)) {
+                    if ("36".equals(dataType)) {
+                        // 获取数据正文
+                        String dataStr = oldDataStr.substring(26, oldDataStr.length() - 6);
+                        log.info("数据主体正文:" + dataStr);
+                        pictureMessageService.savePictureMessage(oldDataStr, dataStr);
+                    }
+                }else{
+                    log.info("==========数据解包校验不正确==========");
+                }
+            }
+        } else {
+            log.info("==========数据长度格式不正确==========");
+        }
+    }finally {
+        // 确保在方法结束前释放 ByteBuf
+        dataBuf.release();
+    }
+        return response;
+    }
+}

+ 14 - 0
environment-data-service/src/main/java/com/zksy/environment/utils/NettyConfig.java

@@ -0,0 +1,14 @@
+package com.zksy.environment.utils;
+
+import io.netty.channel.group.ChannelGroup;
+import io.netty.channel.group.DefaultChannelGroup;
+import io.netty.util.concurrent.GlobalEventExecutor;
+
+public class NettyConfig {
+
+    /**
+     * 存储每一个客户端接入进来时的channel对象
+     */
+    public static ChannelGroup group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
+
+}

+ 26 - 0
environment-data-service/src/main/java/com/zksy/environment/utils/ResponseEncoder.java

@@ -0,0 +1,26 @@
+package com.zksy.environment.utils;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToByteEncoder;
+
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @author Administrator
+ * @version 1.0
+ * @project datasynch
+ * @description 数据编码器
+ * @date 2023/11/16 14:02:56
+ */
+public class ResponseEncoder extends MessageToByteEncoder<String> {
+
+    @Override
+    protected void encode(ChannelHandlerContext ctx, String msg, ByteBuf out) throws Exception {
+        byte[] content = msg.getBytes(StandardCharsets.UTF_8); // 将字符串转换为字节数组
+        int length = content.length;
+
+        out.writeInt(length); // 写入响应消息的长度
+        out.writeBytes(content); // 写入响应消息的内容
+    }
+}

+ 90 - 0
environment-data-service/src/main/java/com/zksy/environment/utils/ServerHandler.java

@@ -0,0 +1,90 @@
+package com.zksy.environment.utils;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+@Slf4j
+@Component
+public class ServerHandler extends ChannelInboundHandlerAdapter {
+    private static ServerHandler serverHandler;
+
+    @Autowired
+    private MonitorDatasynch monitorDatasynch;
+
+    @PostConstruct
+    public void init() {
+        log.info("init()方法");
+        serverHandler = this;
+        serverHandler.monitorDatasynch = this.monitorDatasynch;
+    }
+
+    /**
+     * 客户端与服务端创建连接的时候调用
+     */
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        log.info("客户端与服务端连接开始...");
+        //获取到当前与服务器连接成功的channel
+        NettyConfig.group.add(ctx.channel());
+        System.out.println(ctx.channel().remoteAddress()+" 上线,"+"在线数量:"+NettyConfig.group.size());
+        /**
+         * 往客户端发送消息
+         */
+        /*String helo = "##0128QN=20231030111800029;ST=22;CN=2041;PW=123456;MN=010000A8900016F007;Flag=5;CP=&&BeginTime=20231029000000,EndTime=20231029000000&&";
+        ByteBuf byteBuf = Unpooled.wrappedBuffer(helo.getBytes());
+        ctx.channel().writeAndFlush(byteBuf);
+        System.out.println("首次连接完成!"+byteBuf);*/
+    }
+
+    /**
+     * 客户端与服务端断开连接时调用
+     */
+    @Override
+    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+        log.info("客户端与服务端连接关闭...");
+        //获取当前要断连接的channel
+        NettyConfig.group.remove(ctx.channel());
+        System.out.println(ctx.channel().remoteAddress()+" 下线,"+"在线数量:"+NettyConfig.group.size());
+    }
+
+    /**
+     * 服务端接收客户端发送过来的数据结束之后调用
+     */
+    @Override
+    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
+        ctx.flush();
+        log.info("信息接收完毕...");
+    }
+
+    /**
+     * 工程出现异常的时候调用
+     */
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+        cause.printStackTrace();
+        ctx.close();
+    }
+
+    /**
+     * 服务端处理客户端websocket请求的核心方法,这里接收了客户端发来的信息
+     */
+    @Override
+    public void channelRead(ChannelHandlerContext channelHandlerContext, Object msg) throws Exception {
+        try {
+            String hexString = (String) msg; // 接收16进制字符串
+            ByteBuf buf = DataCheckUtil.hexStringToByteBuf(hexString); // 将16进制字符串转换为 ByteBuf
+            //System.err.println("strArr==="+strArr);
+            //log.info("==========数据已接收,接收时间:==========" + LocalDateTime.now());
+            String pushMonitorDataStr = serverHandler.monitorDatasynch.pushMonitorData(buf);
+        } catch (Exception e) {
+            log.info("==========数据入库失败==========");
+            e.printStackTrace();
+        }
+    }
+}

+ 19 - 0
environment-data-service/src/main/resources/application-dev.yaml

@@ -0,0 +1,19 @@
+zksy:
+  db:
+    host: 192.168.110.30
+    un: root
+    pw: 123
+    port: 3307
+    database: environment_data
+spring:
+  redis:
+    host: 192.168.110.30
+    port: 6379
+minio:
+  endpoint: http://192.168.110.30:9000
+  accessKey: minio
+  secretKey: minio123
+  bucket: zksy-file
+  readPath: http://192.168.110.30:9000
+
+

+ 17 - 0
environment-data-service/src/main/resources/application-prod.yaml

@@ -0,0 +1,17 @@
+zksy:
+  db:
+    host: 192.168.110.30
+    un: root
+    pw: 123
+    port: 3307
+    database: environment_data
+spring:
+  redis:
+    host: 192.168.110.30
+    port: 6379
+minio:
+  endpoint: http://192.168.110.30:9000
+  accessKey: minio
+  secretKey: minio123
+  bucket: test
+  readPath: http://192.168.110.30:9000

+ 31 - 0
environment-data-service/src/main/resources/bootstrap.yaml

@@ -0,0 +1,31 @@
+spring:
+  application:
+    name: environment-data-service
+  profiles:
+    active: dev
+  main:
+    allow-bean-definition-overriding: true
+  cloud:
+    sentinel:
+      transport:
+        dashboard: 192.168.110.30:8090
+      http-method-specify: true
+    nacos:
+      discovery:
+        server-addr: 192.168.110.30:8848
+      config:
+        server-addr: 192.168.110.30:8848
+        file-extension: yaml
+        shared-configs:
+          - dataId: environment-data-service.yaml
+          - dataId: zksy-shared-jdbc.yaml
+          - dataId: zksy-shared-log.yaml
+  redis:
+    host: 192.168.110.30
+    port: 6379
+netty:
+  # 端口号
+  port: 8085
+
+
+

+ 16 - 0
environment-data-service/src/main/resources/mapper/PictureMessageMapper.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zksy.environment.mapper.PictureMessageMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.zksy.environment.domain.po.PictureMessage">
+        <id column="id" property="id" />
+        <result column="sending_message_time" property="sendingMessageTime" />
+        <result column="measuring_station_address" property="measuringStationAddress" />
+        <result column="measuring_station_type" property="measuringStationType" />
+        <result column="observe_time" property="observeTime" />
+        <result column="message" property="message" />
+        <result column="create_time" property="createTime" />
+    </resultMap>
+
+</mapper>

+ 22 - 0
environment-data-service/src/main/resources/mapper/StationHourMapper.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zksy.environment.mapper.StationHourMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.zksy.environment.domain.po.StationHour">
+        <id column="id" property="id" />
+        <result column="function_code" property="functionCode" />
+        <result column="sending_message_time" property="sendingMessageTime" />
+        <result column="measuring_station_address" property="measuringStationAddress" />
+        <result column="measuring_station_type" property="measuringStationType" />
+        <result column="observe_time" property="observeTime" />
+        <result column="water_temperature" property="waterTemperature" />
+        <result column="turbidity" property="turbidity" />
+        <result column="voltage" property="voltage" />
+        <result column="signal_strength" property="signalStrength" />
+        <result column="device_temperature" property="deviceTemperature" />
+        <result column="message" property="message" />
+        <result column="create_time" property="createTime" />
+    </resultMap>
+
+</mapper>

+ 7 - 0
pom.xml

@@ -13,6 +13,7 @@
         <module>zksy-gateway</module>
         <module>zksy-common</module>
         <module>visualization-service</module>
+        <module>environment-data-service</module>
     </modules>
 
     <parent>
@@ -37,6 +38,7 @@
         <okhttp.version>4.9.3</okhttp.version>
         <redis.version>3.0.5</redis.version>
         <sentinel.version>2021.0.4.0</sentinel.version>
+        <minioutil.version>1.0.0</minioutil.version>
     </properties>
 
     <dependencyManagement>
@@ -93,6 +95,11 @@
                 <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
                 <version>${sentinel.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.zksy</groupId>
+                <artifactId>minioutil</artifactId>
+                <version>${minioutil.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 

+ 0 - 4
zksy-gateway/src/main/java/com/zksy/gateway/filter/AuthGlobalFilter.java

@@ -1,15 +1,11 @@
 package com.zksy.gateway.filter;
 
-import com.zksy.common.exception.UnauthorizedException;
 import com.zksy.gateway.config.AuthProperties;
 import com.zksy.gateway.utils.JwtTool;
 import lombok.RequiredArgsConstructor;
 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
 import org.springframework.cloud.gateway.filter.GlobalFilter;
 import org.springframework.core.Ordered;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.http.server.reactive.ServerHttpResponse;
 import org.springframework.stereotype.Component;
 import org.springframework.util.AntPathMatcher;
 import org.springframework.web.server.ServerWebExchange;