8 Commits ecd8ab65a3 ... ea5c69bd58

Auteur SHA1 Message Date
  zlm ea5c69bd58 实现可燃气体设备发送短信预警功能 il y a 7 mois
  zlm 4f9631a991 实现消防设备发送短信预警功能 il y a 7 mois
  zlm 9cc932407b 将获取手机号的操作移到zksy-system里面 il y a 7 mois
  zlm b8f4e1cab7 将获取手机号的操作移到zksy-system里面 il y a 7 mois
  zlm 55fc55b0ef 从设备维护表和用户表中获取到真实手机号发送短信 il y a 7 mois
  zlm 1459552486 修改阿里云发送短信代码,用从数据库获取到的真实手机号码代替假数据 il y a 7 mois
  zlm c70dee3f57 将井盖服务做为子模块管理 il y a 7 mois
  zlm 9f5bebf932 修改RedisUtils相关注解 il y a 7 mois
20 fichiers modifiés avec 503 ajouts et 94 suppressions
  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);