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