1
0

8 Commits ecd8ab65a3 ... ea5c69bd58

Autor SHA1 Nachricht Datum
  zlm ea5c69bd58 实现可燃气体设备发送短信预警功能 vor 10 Monaten
  zlm 4f9631a991 实现消防设备发送短信预警功能 vor 10 Monaten
  zlm 9cc932407b 将获取手机号的操作移到zksy-system里面 vor 10 Monaten
  zlm b8f4e1cab7 将获取手机号的操作移到zksy-system里面 vor 10 Monaten
  zlm 55fc55b0ef 从设备维护表和用户表中获取到真实手机号发送短信 vor 10 Monaten
  zlm 1459552486 修改阿里云发送短信代码,用从数据库获取到的真实手机号码代替假数据 vor 10 Monaten
  zlm c70dee3f57 将井盖服务做为子模块管理 vor 10 Monaten
  zlm 9f5bebf932 修改RedisUtils相关注解 vor 10 Monaten
20 geänderte Dateien mit 503 neuen und 94 gelöschten Zeilen
  1. 5 0
      environment-service/pom.xml
  2. 13 2
      environment-service/src/main/java/com/zksy/environment/EnvironmentApplication.java
  3. 9 9
      environment-service/src/main/java/com/zksy/environment/config/RSServerService.java
  4. 5 1
      environment-service/src/main/resources/application-dev.yaml
  5. 16 0
      firefighting-pressure-service/pom.xml
  6. 15 2
      firefighting-pressure-service/src/main/java/com/zksy/pressure/PressureApplication.java
  7. 17 0
      firefighting-pressure-service/src/main/java/com/zksy/pressure/domain/Enum/FirefightingDeviceCodeEnum.java
  8. 18 0
      firefighting-pressure-service/src/main/java/com/zksy/pressure/domain/Enum/FirefightingWarningCodeEnum.java
  9. 85 0
      firefighting-pressure-service/src/main/java/com/zksy/pressure/utils/MessageHandler.java
  10. 4 1
      firefighting-pressure-service/src/main/resources/application-dev.yaml
  11. 10 0
      flammable-gas-service/pom.xml
  12. 15 2
      flammable-gas-service/src/main/java/com/zksy/gas/GasApplication.java
  13. 17 0
      flammable-gas-service/src/main/java/com/zksy/gas/domain/Enum/GasDeviceCodeEnum.java
  14. 20 0
      flammable-gas-service/src/main/java/com/zksy/gas/domain/Enum/GasWarningCodeEnum.java
  15. 129 0
      flammable-gas-service/src/main/java/com/zksy/gas/utils/MessageHandler.java
  16. 4 1
      flammable-gas-service/src/main/resources/application-dev.yaml
  17. 101 0
      pipe-network-service/zksy-system/src/main/java/com/zksy/utils/DevicePhoneFetchUtil.java
  18. 1 0
      pom.xml
  19. 15 75
      zk-api-service/src/main/java/com/zksy/api/utils/SmsUtil.java
  20. 4 1
      zk-common/src/main/java/com/zksy/common/utils/RedisUtils.java

+ 5 - 0
environment-service/pom.xml

@@ -28,6 +28,11 @@
             <artifactId>zk-api-service</artifactId>
             <version>1.0.0</version>
         </dependency>
+        <dependency>
+            <groupId>com.zksy</groupId>
+            <artifactId>zksy-system</artifactId>
+            <version>3.9.0</version>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>

+ 13 - 2
environment-service/src/main/java/com/zksy/environment/EnvironmentApplication.java

@@ -6,8 +6,19 @@ import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.scheduling.annotation.EnableAsync;
 
-@MapperScan(basePackages = "com.zksy.environment.mapper")
-@SpringBootApplication(scanBasePackages = {"com.zksy.environment","com.zksy.api"})
+@MapperScan({
+        "com.zksy.environment.mapper",
+        "com.zksy.base.mapper",
+        "com.zksy.system.mapper"
+})
+@SpringBootApplication(scanBasePackages = {
+        "com.zksy.environment", // 默认就会扫描,不写也行
+        "com.zksy.api",         // 需要跨模块时再加
+        "com.zksy.base.service",
+        "com.zksy.system.service",
+        "com.zksy.common",
+        "com.zksy.utils"
+})
 public class EnvironmentApplication {
     public static void main(String[] args) {
         SpringApplication.run(EnvironmentApplication.class, args);

+ 9 - 9
environment-service/src/main/java/com/zksy/environment/config/RSServerService.java

@@ -3,6 +3,7 @@ package com.zksy.environment.config;
 import com.zksy.api.utils.SmsUtil;
 import com.zksy.environment.domain.ERealTimeData;
 import com.zksy.environment.mapper.ERealTimeDataMapper;
+import com.zksy.utils.DevicePhoneFetchUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -12,7 +13,6 @@ import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
-import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -38,6 +38,8 @@ public class RSServerService {
 
     @Autowired
     private SmsUtil smsUtil;
+    @Autowired
+    private DevicePhoneFetchUtil devicePhoneFetchUtil;
 
     @PostConstruct
     public void init() {
@@ -107,12 +109,7 @@ public class RSServerService {
 
                 @Override
                 public void receiveRealtimeData(RealTimeData data) {
-                    // 1. 定义必须传入的报警手机号列表(可根据实际场景从配置/数据库获取)
-                    List<String> mandatoryAlarmPhones = Arrays.asList(
-                            "15773238205",
-                            "19892389826"
-                            // 可根据设备类型/节点ID动态调整
-                    );
+
                     for (NodeData nd : data.getNodeList()) {
                         try {
                             ERealTimeData realTimeData = new ERealTimeData();
@@ -128,8 +125,11 @@ public class RSServerService {
                             realTimeData.setCreateTime(LocalDateTime.now());
                             realTimeDataMapper.insert(realTimeData);
 
-                            // 2. 必须传入第三个参数(报警手机号列表)
-                            smsUtil.checkDeviceAlarmAndSend(data, nd, mandatoryAlarmPhones);
+                            //获取能够发送的手机号
+                            List<String> devicePhoneList = devicePhoneFetchUtil.getPhoneListByDeviceId(String.valueOf(data.getDeviceId()));
+
+                            //传入手机号参数
+                            smsUtil.checkDeviceAlarmAndSend(data, nd, devicePhoneList);
                         } catch (Exception e) {
                             log.error("实时数据入库失败:设备ID={}, 节点ID={}", data.getDeviceId(), nd.getNodeId(), e);
                         }

+ 5 - 1
environment-service/src/main/resources/application-dev.yaml

@@ -14,4 +14,8 @@ spring:
       discovery:
         server-addr: 192.168.110.30:8848
       config:
-        server-addr: 192.168.110.30:8848
+        server-addr: 192.168.110.30:8848
+
+mybatis-plus:
+  type-aliases-package: com.zksy.environment.domain, com.zksy.common.core.domain.entity,com.zksy.system.domain
+  mapper-locations: classpath*:mapper/**/*Mapper.xml

+ 16 - 0
firefighting-pressure-service/pom.xml

@@ -24,6 +24,22 @@
             <artifactId>zk-common</artifactId>
             <version>1.0.0</version>
         </dependency>
+        <dependency>
+            <groupId>com.zksy</groupId>
+            <artifactId>zk-api-service</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.zksy</groupId>
+            <artifactId>zksy-system</artifactId>
+            <version>3.9.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter-test</artifactId>
+            <version>3.0.5</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>

+ 15 - 2
firefighting-pressure-service/src/main/java/com/zksy/pressure/PressureApplication.java

@@ -6,8 +6,21 @@ import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.scheduling.annotation.EnableAsync;
 
-@MapperScan(basePackages = "com.zksy.pressure.mapper")
-@SpringBootApplication(scanBasePackages = {"com.zksy.pressure","com.zksy.api"})
+//@MapperScan(basePackages = "com.zksy.pressure.mapper")
+//@SpringBootApplication(scanBasePackages = {"com.zksy.pressure","com.zksy.api"})
+@MapperScan({
+        "com.zksy.pressure.mapper",
+        "com.zksy.base.mapper",
+        "com.zksy.system.mapper"
+})
+@SpringBootApplication(scanBasePackages = {
+        "com.zksy.pressure",
+        "com.zksy.api",
+        "com.zksy.base.service",
+        "com.zksy.system.service",
+        "com.zksy.common",
+        "com.zksy.utils"
+})
 public class PressureApplication {
     public static void main(String[] args) {
         SpringApplication.run(PressureApplication.class, args);

+ 17 - 0
firefighting-pressure-service/src/main/java/com/zksy/pressure/domain/Enum/FirefightingDeviceCodeEnum.java

@@ -0,0 +1,17 @@
+package com.zksy.pressure.domain.Enum;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 设备编码枚举(新增)
+ */
+@Getter
+@AllArgsConstructor
+public enum FirefightingDeviceCodeEnum {
+    //firefighting
+    FIREFIGHTING_DEVICE("1302100007", "消防设备"); // 对应数据库中的设备编码
+
+    private final String code;  // 设备编码
+    private final String name;  // 设备名称
+}

+ 18 - 0
firefighting-pressure-service/src/main/java/com/zksy/pressure/domain/Enum/FirefightingWarningCodeEnum.java

@@ -0,0 +1,18 @@
+package com.zksy.pressure.domain.Enum;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 预警编码枚举(替代原WarningTypeEnum)
+ */
+@Getter
+@AllArgsConstructor
+public enum FirefightingWarningCodeEnum {
+
+    PRESSURE("WARN-PRESSURE","消防压力过高预警",50.0);
+
+    private final String code;       // 预警编码(对应数据库)
+    private final String name;       // 预警名称
+    private final double defaultVal; // 默认阈值(数据库未配置时使用)
+}

+ 85 - 0
firefighting-pressure-service/src/main/java/com/zksy/pressure/utils/MessageHandler.java

@@ -1,9 +1,16 @@
 package com.zksy.pressure.utils;
 
 import cn.hutool.core.lang.UUID;
+import com.alibaba.fastjson.JSONObject;
+import com.zksy.api.domain.WarningThreshold;
+import com.zksy.api.service.WarningThresholdService;
+import com.zksy.api.utils.SmsUtil;
 import com.zksy.common.exception.InvalidMessageException;
+import com.zksy.pressure.domain.Enum.FirefightingDeviceCodeEnum;
+import com.zksy.pressure.domain.Enum.FirefightingWarningCodeEnum;
 import com.zksy.pressure.domain.FirefightingPressure;
 import com.zksy.pressure.service.FirefightingPressureService;
+import com.zksy.utils.DevicePhoneFetchUtil;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelHandler;
@@ -15,6 +22,11 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
 @ChannelHandler.Sharable
 @Slf4j
 @Component
@@ -22,6 +34,12 @@ public class MessageHandler extends ChannelInboundHandlerAdapter {
 	private static Logger logger = LoggerFactory.getLogger(MessageHandler.class);
 	private final FirefightingPressureService firefightingPressureService;
 	@Autowired
+	private WarningThresholdService service;
+	@Autowired
+	private SmsUtil smsUtil;
+	@Autowired
+	private DevicePhoneFetchUtil devicePhoneFetchUtil;
+	@Autowired
 	public MessageHandler(FirefightingPressureService firefightingPressureService) {
 		this.firefightingPressureService = firefightingPressureService;
 	}
@@ -59,6 +77,8 @@ public class MessageHandler extends ChannelInboundHandlerAdapter {
 				//String addressCode = resultData.getAddressCode();
 				//DeviceOfflineCheckTask.deviceLastReceiveTimeMap.put(addressCode, new Date());
 				firefightingPressureService.save(resultData);
+
+				checkIfSmsAlertNeeded(resultData);
 			}
 		} catch (InvalidMessageException e) {
 			logger.error("数据入库失败: {}", e.getMessage());
@@ -115,4 +135,69 @@ public class MessageHandler extends ChannelInboundHandlerAdapter {
 			logger.error("发送数据失败: {}", e.getMessage());
 		}
 	}
+	//检查是否会触发短信预警
+	public void checkIfSmsAlertNeeded(FirefightingPressure resultData){
+		try {
+			//用遥测站地址作为设备的设备编号
+			String deviceId = resultData.getTelemeteringStation();
+			//1、获取到压力阈值
+			Double warningValue = null;
+			//1.1获取到设备编码
+			String deviceWarningCode = FirefightingDeviceCodeEnum.FIREFIGHTING_DEVICE.getCode();
+			FirefightingWarningCodeEnum targetWarningType=FirefightingWarningCodeEnum.PRESSURE;
+
+			String warningCode = targetWarningType.getCode();
+			String warningMsg = targetWarningType.getName();
+			try {
+				//1.2根据设备编码获取压力阈值
+				WarningThreshold threshold = service.getWarningThresholdByDeviceAndCode(deviceWarningCode, warningCode);
+				warningValue = threshold.getWarningValue();
+			} catch (Exception e) {
+				log.error("查询预警阈值失败");
+			}
+			//1.2获取到实际压力值
+			Double pressureValue = resultData.getPressureValue();
+			boolean isOverThreshold = pressureValue > warningValue;
+			//1.3超出了阈值则发送短信,设备编号这里不是很清楚
+			if(isOverThreshold){
+				sendMessage(deviceId,warningMsg,resultData.getLongitude(),resultData.getLatitude());
+			}
+			if(resultData.getD14()==1){
+				sendMessage(deviceId,"压力变幅报警",resultData.getLongitude(),resultData.getLatitude());
+			}
+			if(resultData.getD13()==1){
+				sendMessage(deviceId,"压力下下限报警",resultData.getLongitude(),resultData.getLatitude());
+			}
+			if(resultData.getD12()==1){
+				sendMessage(deviceId,"压力上上限报警",resultData.getLongitude(),resultData.getLatitude());
+			}
+			if(resultData.getD11()==1){
+				sendMessage(deviceId,"压力下线报警",resultData.getLongitude(),resultData.getLatitude());
+			}
+			if(resultData.getD10()==1){
+				sendMessage(deviceId,"压力上限报警",resultData.getLongitude(),resultData.getLatitude());
+			}
+			if(resultData.getD9()==1){
+				sendMessage(deviceId,"传感器状态",resultData.getLongitude(),resultData.getLatitude());
+			}
+			if(resultData.getD1()==1){
+				sendMessage(deviceId,"倾斜报警1",resultData.getLongitude(),resultData.getLatitude());
+			}
+		} catch (Exception e) {
+			log.error("设备报警处理失败");
+		}
+
+	}
+	//构造发送短信参数&&发送短信
+	public void sendMessage(String deviceNo,String alarmType,BigDecimal lng,BigDecimal lat){
+		// 构造短信参数
+		JSONObject params = new JSONObject();
+		params.put("deviceNo", deviceNo);
+		params.put("alarmType", alarmType);
+		// 经纬度处理(为执行信息处理)
+		params.put("location", String.format("经纬度:%.6f,%.8f", lng, lat));
+		List<String> phoneListByDeviceId = devicePhoneFetchUtil.getPhoneListByDeviceId(deviceNo);
+		Map<String, Boolean> sendResults = smsUtil.sendBatchSms(phoneListByDeviceId, params.toJSONString());
+		log.info("发送信息完成");
+	}
 }

+ 4 - 1
firefighting-pressure-service/src/main/resources/application-dev.yaml

@@ -14,4 +14,7 @@ spring:
       discovery:
         server-addr: 192.168.110.30:8848
       config:
-        server-addr: 192.168.110.30:8848
+        server-addr: 192.168.110.30:8848
+mybatis-plus:
+  type-aliases-package: com.zksy.pressure.domain, com.zksy.common.core.domain.entity,com.zksy.system.domain
+  mapper-locations: classpath*:mapper/**/*Mapper.xml

+ 10 - 0
flammable-gas-service/pom.xml

@@ -24,6 +24,16 @@
             <artifactId>zk-common</artifactId>
             <version>1.0.0</version>
         </dependency>
+        <dependency>
+            <groupId>com.zksy</groupId>
+            <artifactId>zk-api-service</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.zksy</groupId>
+            <artifactId>zksy-system</artifactId>
+            <version>3.9.0</version>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>

+ 15 - 2
flammable-gas-service/src/main/java/com/zksy/gas/GasApplication.java

@@ -5,8 +5,21 @@ import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 
-@MapperScan(basePackages = "com.zksy.gas.mapper")
-@SpringBootApplication(scanBasePackages = {"com.zksy.gas","com.zksy.api"})
+//@MapperScan(basePackages = "com.zksy.gas.mapper")
+//@SpringBootApplication(scanBasePackages = {"com.zksy.gas","com.zksy.api"})
+@MapperScan({
+        "com.zksy.gas.mapper",
+        "com.zksy.base.mapper",
+        "com.zksy.system.mapper"
+})
+@SpringBootApplication(scanBasePackages = {
+        "com.zksy.gas",
+        "com.zksy.api",
+        "com.zksy.base.service",
+        "com.zksy.system.service",
+        "com.zksy.common",
+        "com.zksy.utils"
+})
 public class GasApplication {
     public static void main(String[] args) {
         SpringApplication.run(GasApplication.class, args);

+ 17 - 0
flammable-gas-service/src/main/java/com/zksy/gas/domain/Enum/GasDeviceCodeEnum.java

@@ -0,0 +1,17 @@
+package com.zksy.gas.domain.Enum;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 设备编码枚举(新增)
+ */
+@Getter
+@AllArgsConstructor
+public enum GasDeviceCodeEnum {
+    //firefighting
+    FIREFIGHTING_DEVICE("xxxxxxx", "可燃气体监测仪"); // 对应数据库中的设备编码
+
+    private final String code;  // 设备编码
+    private final String name;  // 设备名称
+}

+ 20 - 0
flammable-gas-service/src/main/java/com/zksy/gas/domain/Enum/GasWarningCodeEnum.java

@@ -0,0 +1,20 @@
+package com.zksy.gas.domain.Enum;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 预警编码枚举(替代原WarningTypeEnum)
+ */
+@Getter
+@AllArgsConstructor
+public enum GasWarningCodeEnum {
+
+    TEMPERATRUE("WARN-GAS-TEMPERATRUE","可燃气体温度预警",50.0),
+    HUMIDITY("WARN-GAS-HUMIDITY","可燃气体湿度预警",50.0),
+    GASCONCENTRATION("WARN-GAS-CONCENTRATION","可燃气体浓度预警",50.0);
+
+    private final String code;       // 预警编码(对应数据库)
+    private final String name;       // 预警名称
+    private final double defaultVal; // 默认阈值(数据库未配置时使用)
+}

+ 129 - 0
flammable-gas-service/src/main/java/com/zksy/gas/utils/MessageHandler.java

@@ -1,9 +1,16 @@
 package com.zksy.gas.utils;
 
 import cn.hutool.core.lang.UUID;
+import com.alibaba.fastjson.JSONObject;
+import com.zksy.api.domain.WarningThreshold;
+import com.zksy.api.service.WarningThresholdService;
+import com.zksy.api.utils.SmsUtil;
 import com.zksy.common.exception.InvalidMessageException;
+import com.zksy.gas.domain.Enum.GasDeviceCodeEnum;
+import com.zksy.gas.domain.Enum.GasWarningCodeEnum;
 import com.zksy.gas.domain.GasMonitorData;
 import com.zksy.gas.service.GasMonitorDataService;
+import com.zksy.utils.DevicePhoneFetchUtil;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelHandler;
@@ -11,13 +18,17 @@ import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
 import io.netty.handler.timeout.ReadTimeoutException;
 import io.netty.util.ReferenceCountUtil;
+import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import java.math.BigDecimal;
 import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
 
 @ChannelHandler.Sharable
 @Slf4j
@@ -25,6 +36,13 @@ import java.util.Arrays;
 public class MessageHandler extends ChannelInboundHandlerAdapter {
 	private static Logger logger = LoggerFactory.getLogger(MessageHandler.class);
 	private final GasMonitorDataService service;
+	@Autowired
+	private WarningThresholdService warningThresholdService;
+	@Autowired
+	private SmsUtil smsUtil;
+	@Autowired
+	private DevicePhoneFetchUtil devicePhoneFetchUtil;
+
 	@Autowired
 	public MessageHandler(GasMonitorDataService firefightingPressureService) {
 		this.service = firefightingPressureService;
@@ -92,7 +110,9 @@ public class MessageHandler extends ChannelInboundHandlerAdapter {
 			com.zksy.gas.domain.GasMonitorData resultData = DataParser.parseMessage(msgBytes);
 			resultData.setId(java.util.UUID.randomUUID().toString());
 			service.save(resultData);
+			checkIfSmsAlertNeeded(resultData);
 			logger.info("数据解析入库成功: {}", resultData);
+
 		} catch (InvalidMessageException e) {
 			logger.error("数据校验失败: {}", e.getMessage());
 			ctx.writeAndFlush(Unpooled.copiedBuffer("数据校验失败".getBytes()));
@@ -153,4 +173,113 @@ public class MessageHandler extends ChannelInboundHandlerAdapter {
 			logger.error("发送数据失败: {}", e.getMessage());
 		}
 	}
+	public void checkIfSmsAlertNeeded(GasMonitorData resultData){
+
+		//用MAC地址作为设备的设备编号
+		String deviceId = resultData.getMacAddress();
+
+		//获取温度阈值
+		String deviceWarningCode = GasDeviceCodeEnum.FIREFIGHTING_DEVICE.getCode();
+		GasWarningCodeEnum temTargetWarningType=GasWarningCodeEnum.TEMPERATRUE;
+		String temWarningCode = temTargetWarningType.getCode();
+		String temWarningMsg = temTargetWarningType.getName();
+		Double temWarningValue = checkTemAndHum(deviceWarningCode, temWarningCode);
+		//获取湿度阈值
+		GasWarningCodeEnum humTargetWarningType=GasWarningCodeEnum.HUMIDITY;
+		String humWarningCode = humTargetWarningType.getCode();
+		String humWarningMsg = humTargetWarningType.getName();
+		Double humWarningValue = checkTemAndHum(deviceWarningCode, humWarningCode);
+		//获取气体浓度阈值
+		GasWarningCodeEnum gasTargetWarningType=GasWarningCodeEnum.GASCONCENTRATION;
+		String gasWarningCode = gasTargetWarningType.getCode();
+		String gasWarningMsg = gasTargetWarningType.getName();
+		Double gasWarningValue = checkTemAndHum(deviceWarningCode, gasWarningCode);
+
+		//判断温度
+		float temperature = resultData.getTemperature();
+		boolean temperatureIsOverThreshold = temperature > temWarningValue;
+		if(temperatureIsOverThreshold){
+			sendMessage(deviceId,temWarningMsg,resultData.getLongitude(),resultData.getLatitude());
+		}
+		//判断湿度
+		float humidity = resultData.getHumidity();
+		boolean humidityIsOverThreshold=humidity>humWarningValue;
+		if(humidityIsOverThreshold){
+			sendMessage(deviceId,humWarningMsg,resultData.getLongitude(),resultData.getLatitude());
+		}
+		//判断气体浓度
+		BigDecimal gasConcentration = resultData.getGasConcentration();
+		float actualGasConcentration=gasConcentration.floatValue();
+		boolean concentrationIsOverThreshold=actualGasConcentration>gasWarningValue;
+		if(concentrationIsOverThreshold){
+			sendMessage(deviceId,gasWarningMsg,resultData.getLongitude(),resultData.getLatitude());
+		}
+		//获取到的数据逐一进行判断
+		Map<String, Boolean> alarmBits = resultData.parseAlarmBits();
+		if(alarmBits.get("unknownAlarm")){
+			sendMessage(deviceId,"未知报警",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("highAlarm")){
+			sendMessage(deviceId,"高报警",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("overRange")){
+			sendMessage(deviceId,"超量程",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("calibrationCycle")){
+			sendMessage(deviceId,"标定周期",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("overLife")){
+			sendMessage(deviceId,"超寿命",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("fallAlarm")){
+			sendMessage(deviceId,"跌倒报警",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("undervoltage")){
+			sendMessage(deviceId,"欠压报警",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("rangeAlarm")){
+			sendMessage(deviceId,"区间报警",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("keyAlarm")){
+			sendMessage(deviceId,"按键报警",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("vibrationAlarm")){
+			sendMessage(deviceId,"震动报警",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("waterLevelAlarm")){
+			sendMessage(deviceId,"水位报警",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("powerOffAlarm")){
+			sendMessage(deviceId,"断电报警",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("sensorFault")){
+			sendMessage(deviceId,"传感器故障",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("overHumidity")){
+			sendMessage(deviceId,"超湿报警",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("overTemperature")){
+			sendMessage(deviceId,"超温报警",resultData.getLongitude(),resultData.getLatitude());
+		}
+		if(alarmBits.get("systemFault")){
+			sendMessage(deviceId,"系统故障",resultData.getLongitude(),resultData.getLatitude());
+		}
+	}
+	public Double checkTemAndHum(String deviceWarningCode,String warningCode){
+		//获取数据库中的阈值
+		WarningThreshold threshold = warningThresholdService.getWarningThresholdByDeviceAndCode(deviceWarningCode, warningCode);
+		return threshold.getWarningValue();
+	}
+	//构造发送短信参数&&发送短信
+	public void sendMessage(String deviceNo, String alarmType, BigDecimal lng, BigDecimal lat){
+		// 构造短信参数
+		JSONObject params = new JSONObject();
+		params.put("deviceNo", deviceNo);
+		params.put("alarmType", alarmType);
+		// 经纬度处理(位置)
+		params.put("location", String.format("经纬度:%.6f,%.8f", lng, lat));
+		List<String> phoneListByDeviceId = devicePhoneFetchUtil.getPhoneListByDeviceId(deviceNo);
+		Map<String, Boolean> sendResults = smsUtil.sendBatchSms(phoneListByDeviceId, params.toJSONString());
+		log.info("发送信息完成");
+	}
 }

+ 4 - 1
flammable-gas-service/src/main/resources/application-dev.yaml

@@ -14,4 +14,7 @@ spring:
       discovery:
         server-addr: 192.168.110.30:8848
       config:
-        server-addr: 192.168.110.30:8848
+        server-addr: 192.168.110.30:8848
+mybatis-plus:
+  type-aliases-package: com.zksy.gas.domain, com.zksy.common.core.domain.entity,com.zksy.system.domain
+  mapper-locations: classpath*:mapper/**/*Mapper.xml

+ 101 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/utils/DevicePhoneFetchUtil.java

@@ -0,0 +1,101 @@
+package com.zksy.utils;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zksy.base.domain.EquipmentMaintain;
+import com.zksy.base.domain.EquipmentStatus;
+import com.zksy.base.service.EquipmentMaintainService;
+import com.zksy.base.service.EquipmentStatusService;
+import com.zksy.common.core.domain.entity.SysUser;
+import com.zksy.system.service.ISysUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+//
+@Component
+public class DevicePhoneFetchUtil {
+
+    //换了一种方式注入,待测试
+    @Autowired
+    private  EquipmentMaintainService equipmentMaintainService;
+    @Autowired
+    private  EquipmentStatusService equipmentStatusService;
+    @Autowired
+    private  ISysUserService sysUserService;
+
+//    private final EquipmentMaintainService equipmentMaintainService;
+//    private final EquipmentStatusService equipmentStatusService;
+//    private final ISysUserService sysUserService;
+//
+//    public DevicePhoneFetchUtil(EquipmentMaintainService equipmentMaintainService,
+//                                EquipmentStatusService equipmentStatusService,
+//                                ISysUserService sysUserService) {
+//        this.equipmentMaintainService = equipmentMaintainService;
+//        this.equipmentStatusService = equipmentStatusService;
+//        this.sysUserService = sysUserService;
+//    }
+
+    /**
+     * 根据设备ID获取所有关联手机号
+     * @param deviceId 设备ID
+     * @return 去重后的有效手机号列表
+     */
+    public List<String> getPhoneListByDeviceId(String deviceId) {
+        Set<String> phoneSet = new HashSet<>();
+
+        //获取维护表中的手机号
+        addAllMaintainPersonPhones(phoneSet, deviceId);
+        //获取用户表的手机号
+        addUserPhoneByStatus(phoneSet, deviceId);
+        return phoneSet.stream()
+                .filter(this::isValidPhone)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 收集该设备所有维护记录中的维护人手机号
+     */
+    private void addAllMaintainPersonPhones(Set<String> phoneSet, String deviceId) {
+        LambdaQueryWrapper<EquipmentMaintain> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(EquipmentMaintain::getEquipmentId, deviceId);
+
+        List<EquipmentMaintain> maintainList = equipmentMaintainService.list(queryWrapper);
+        if (maintainList.isEmpty()) {
+            return;
+        }
+        maintainList.forEach(maintain -> {
+            String phone = String.valueOf(maintain.getMaintainPersonPhone());
+            phoneSet.add(phone);
+        });
+    }
+
+    /**
+     * 从设备状态表关联用户表获取负责人手机号
+     */
+    private void addUserPhoneByStatus(Set<String> phoneSet, String deviceId) {
+
+        LambdaQueryWrapper<EquipmentStatus> statusWrapper = new LambdaQueryWrapper<>();
+        statusWrapper.eq(EquipmentStatus::getEquipmentId, deviceId);
+        EquipmentStatus equipmentStatus = equipmentStatusService.getOne(statusWrapper);
+
+        if (equipmentStatus == null || equipmentStatus.getUserId() == null) {
+            return;
+        }
+        SysUser sysUser = sysUserService.selectUserById(equipmentStatus.getUserId());
+
+        //0代表存在的用户
+        if (sysUser != null && sysUser.getPhonenumber() != null && sysUser.getDelFlag().equals("0")) {
+            phoneSet.add(sysUser.getPhonenumber());
+        }
+    }
+
+    /**
+     * 校验手机号格式(11位数字)
+     */
+    private boolean isValidPhone(String phone) {
+        return phone != null && phone.matches("^1[3-9]\\d{9}$");
+    }
+}

+ 1 - 0
pom.xml

@@ -14,6 +14,7 @@
         <module>zk-gateway</module>
         <module>zk-common</module>
         <module>zk-api-service</module>
+        <module>manhole-service</module>
         <module>firefighting-pressure-service</module>
         <module>flammable-gas-service</module>
     </modules>

+ 15 - 75
zk-api-service/src/main/java/com/zksy/api/utils/SmsUtil.java

@@ -4,7 +4,8 @@ import com.alibaba.fastjson.JSONObject;
 import com.aliyun.auth.credentials.Credential;
 import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
 import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
-import com.aliyun.sdk.service.dysmsapi20170525.models.*;
+import com.aliyun.sdk.service.dysmsapi20170525.models.SendBatchSmsRequest;
+import com.aliyun.sdk.service.dysmsapi20170525.models.SendBatchSmsResponse;
 import com.google.gson.Gson;
 import com.zksy.api.config.AliyunSmsConfig;
 import com.zksy.api.domain.Enum.DeviceCodeEnum;
@@ -19,7 +20,9 @@ import rk.netDevice.sdk.p2.NodeData;
 import rk.netDevice.sdk.p2.RealTimeData;
 
 import java.time.Duration;
-import java.util.*;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
@@ -35,13 +38,9 @@ public class SmsUtil {
     // 报警缓存和冷却时间
 //    private static final Map<String, Long> ALARM_CACHE = new ConcurrentHashMap<>();
 //    private static final long ALARM_COOLDOWN_MS = 5 * 60 * 1000;
-    //TODO 假数据
-    private static final List<String> DEFAULT_ALARM_PHONES = Arrays.asList(
-            "15773238205", "19892389826"
-    );
 
     @Autowired
-    public SmsUtil(AliyunSmsConfig aliyunSmsConfig,WarningThresholdService service) {
+    public SmsUtil(AliyunSmsConfig aliyunSmsConfig, WarningThresholdService service) {
         this.aliyunSmsConfig = aliyunSmsConfig;
         this.service=service;
 
@@ -65,39 +64,6 @@ public class SmsUtil {
             throw new RuntimeException("短信服务初始化异常", e); // 初始化失败应快速失败
         }
     }
-
-    /**
-     * 发送单条短信
-     * @param phoneNumber 接收短信的手机号
-     * @param templateParam 短信模板参数,JSON格式字符串
-     * @return 是否发送成功
-     */
-    public boolean sendSms(String phoneNumber, String templateParam) {
-        try {
-            // 构建发送短信请求
-            SendSmsRequest sendSmsRequest = SendSmsRequest.builder()
-                    .phoneNumbers(phoneNumber)
-                    .signName(aliyunSmsConfig.getSignName())
-                    .templateCode(aliyunSmsConfig.getTemplateCode())
-                    .templateParam(templateParam)
-                    .build();
-
-            // 发送短信
-            CompletableFuture<SendSmsResponse> response = client.sendSms(sendSmsRequest);
-            SendSmsResponse resp = response.get();
-
-            // 处理响应结果
-            SendSmsResponseBody body = resp.getBody();
-            System.out.println("短信发送响应: " + new Gson().toJson(body));
-
-            // 返回发送结果,"OK"表示成功
-            return "OK".equals(body.getCode());
-        } catch (Exception e) {
-            System.err.println("发送短信失败: " + e.getMessage());
-            e.printStackTrace();
-            return false;
-        }
-    }
     /**
      * 批量发送相同内容的短信给多个手机号
      * @param phoneNumbers 接收短信的手机号列表
@@ -105,21 +71,18 @@ public class SmsUtil {
      * @return 发送结果,key为手机号,value为是否成功
      */
     public Map<String, Boolean> sendBatchSms(List<String> phoneNumbers, String templateParam) {
-        // 入参校验
         if (phoneNumbers == null || phoneNumbers.isEmpty()) {
             log.warn("批量发送短信失败:手机号列表为空");
             return Collections.emptyMap();
         }
 
         try {
-            //生成与手机号数量相同的签名列表
             List<String> signNames = phoneNumbers.stream()
-                    .map(phone -> aliyunSmsConfig.getSignName()) // 复制签名,与手机号数量一致
+                    .map(phone -> aliyunSmsConfig.getSignName())
                     .collect(Collectors.toList());
 
-            //生成与手机号数量相同的模板参数列表
             List<String> templateParams = phoneNumbers.stream()
-                    .map(phone -> templateParam) // 复制参数,与手机号数量一致
+                    .map(phone -> templateParam)
                     .collect(Collectors.toList());
 
             //构建批量发送请求
@@ -134,7 +97,6 @@ public class SmsUtil {
             CompletableFuture<SendBatchSmsResponse> response = client.sendBatchSms(request);
             SendBatchSmsResponse resp = response.get();
 
-            //System.out.println("批量短信发送响应: " + new Gson().toJson(resp.getBody()));
             log.info("批量短信发送响应: {}",new Gson().toJson(resp.getBody()));
             return phoneNumbers.stream()
                     .collect(Collectors.toMap(
@@ -142,7 +104,6 @@ public class SmsUtil {
                             phone -> "OK".equals(resp.getBody().getCode())
                     ));
         } catch (Exception e) {
-            //System.err.println("批量发送短信失败: " + e.getMessage());
             log.error("批量短信发送响应: {}",e.getMessage());
             e.printStackTrace();
             return phoneNumbers.stream()
@@ -154,10 +115,9 @@ public class SmsUtil {
     }
     /**
      * 检查设备数据是否触发报警并发送短信
-     * 优化点:根据node_id确定唯一warningCode,直接查询单个阈值
      */
     public boolean checkDeviceAlarmAndSend(RealTimeData realTimeData, NodeData nodeData, List<String> alarmPhones) {
-        // 入参校验
+
         if (realTimeData == null || nodeData == null) {
             log.error("预警参数异常:设备数据或节点数据为空");
             return false;
@@ -174,10 +134,6 @@ public class SmsUtil {
         }
 
         try {
-            // 确定报警接收人
-            List<String> targetAlarmPhones = alarmPhones != null && !alarmPhones.isEmpty()
-                    ? alarmPhones
-                    : DEFAULT_ALARM_PHONES;
 
             //TODO 冷处理待定
 //            String cacheKey = realTimeData.getDeviceId() + "_" + nodeId;
@@ -196,11 +152,10 @@ public class SmsUtil {
             String warningCode = targetWarningType.getCode();
             String warningMsg = targetWarningType.getName();
 
-            // 直接查询该预警类型的阈值(无需查所有再筛选)
+            // 直接查询该预警类型的阈值
             double actualThreshold;
             try {
                 String deviceCode = DeviceCodeEnum.ENVIRONMENT_DEVICE.getCode();
-                // 调用新的Service方法:根据设备编码+单个预警编码查询
                 WarningThreshold threshold = service.getWarningThresholdByDeviceAndCode(deviceCode, warningCode);
 
                 // 优先使用数据库配置,无配置则用枚举默认值
@@ -215,41 +170,26 @@ public class SmsUtil {
             // 获取当前节点的指标数值
             double currentValue = getCurrentValueByNodeId(nodeData, nodeId);
 
-            // 判断是否超限(统一逻辑)
             boolean isOverThreshold = currentValue > actualThreshold;
 
-            // 调试日志
             log.debug("设备{}节点{} - 预警类型:{},当前值:{},阈值:{},是否超限:{}",
                     realTimeData.getDeviceId(), nodeId, warningMsg, currentValue, actualThreshold, isOverThreshold);
 
-            // 触发报警
+            // 超过期限,触发报警
             if (isOverThreshold) {
-//                Map<String, Object> alarmInfo = new HashMap<>();
-//                alarmInfo.put("alarmType", warningMsg);
-//                alarmInfo.put("currentValue", currentValue);
-//                alarmInfo.put("threshold", actualThreshold);
-//                alarmInfo.put("nodeId", nodeId);
-
                 log.warn("设备{}节点{}触发预警:{}(当前值:{} > 阈值:{})",
                         realTimeData.getDeviceId(), nodeId, warningMsg, currentValue, actualThreshold);
 
                 // 构造短信参数
                 JSONObject params = new JSONObject();
-//                params.put("name", "系统管理员");
                 params.put("deviceNo", realTimeData.getDeviceId());
-//                params.put("alarmTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                 params.put("alarmType", warningMsg);
-                // 经纬度处理
+                // 经纬度处理(为执行信息处理)
                 double lng = nodeData.getLng();
                 double lat = nodeData.getLat();
                 params.put("location", String.format("经纬度:%.6f,%.8f", lng, lat));
 
-//                params.put("alarmDetails", new Gson().toJson(alarmInfo));
-//                params.put("contactPerson", "设备维护组");
-//                params.put("contactPhone", "13888888888");
-
-                // 发送短信
-                Map<String, Boolean> sendResults = this.sendBatchSms(targetAlarmPhones, params.toJSONString());
+                Map<String, Boolean> sendResults = this.sendBatchSms(alarmPhones, params.toJSONString());
                 long successCount = sendResults.values().stream().filter(Boolean::booleanValue).count();
                 log.info("设备{}报警短信发送完成,成功{}条,失败{}条",
                         realTimeData.getDeviceId(), successCount, sendResults.size() - successCount);
@@ -284,10 +224,10 @@ public class SmsUtil {
      */
     private double getCurrentValueByNodeId(NodeData nodeData, int nodeId) {
         if (nodeId == 1) {
-            // 节点1:悬浮物(floatValue字段)
+            // 节点1需要特殊处理,取悬浮物字段(floatValue字段)
             return nodeData.getFloatValue();
         } else {
-            // 节点2-5:使用hum字段
+            // 其他节点取hum字段
             return nodeData.getHum();
         }
     }

+ 4 - 1
zk-common/src/main/java/com/zksy/common/utils/RedisUtils.java

@@ -4,9 +4,12 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 
+import javax.annotation.Resource;
+
 @Component
 public class RedisUtils {
-    @Autowired
+//    @Autowired
+    @Resource
     private RedisTemplate<String, Object> redisTemplate;
     public void set(String key, Object value) {
         redisTemplate.opsForValue().set(key, value);