|
@@ -0,0 +1,149 @@
|
|
|
+package vip.xiaonuo.coldchain.core.event.alarm.service;
|
|
|
+
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.context.ApplicationEventPublisher;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import vip.xiaonuo.coldchain.core.bean.influxdb.SensorData;
|
|
|
+import vip.xiaonuo.coldchain.core.event.SensorAlarmEvent;
|
|
|
+import vip.xiaonuo.coldchain.core.event.alarm.bean.SensorThreshold;
|
|
|
+import vip.xiaonuo.coldchain.core.event.alarm.config.ColdChainAlarmMessageProperties;
|
|
|
+
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.Date;
|
|
|
+
|
|
|
+@Component
|
|
|
+@RequiredArgsConstructor
|
|
|
+@Slf4j
|
|
|
+public class DefaultSensorAlarmChecker implements SensorAlarmChecker {
|
|
|
+ private final SensorThresholdService thresholdService;
|
|
|
+ private final ColdChainAlarmMessageProperties alarmMessageProperties;
|
|
|
+ private final ApplicationEventPublisher applicationEventPublisher;
|
|
|
+
|
|
|
+ // 定义一个日期格式化器,用于将时间格式化成可读的字符串
|
|
|
+ private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean checkAlarm(SensorData sensorData) {
|
|
|
+ if (sensorData == null) {
|
|
|
+ throw new IllegalArgumentException("传感器数据不能为空!");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取传感器阈值配置
|
|
|
+ SensorThreshold threshold = thresholdService.getThresholdBySensorId(sensorData.getDeviceId(), sensorData.getRoads());
|
|
|
+ if (threshold == null) {
|
|
|
+ log.warn("没有找到设备 {} 的阈值配置", sensorData.getDeviceId());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 检查传感器数据并触发报警
|
|
|
+ boolean alarmTriggered = false;
|
|
|
+ if (sensorData.getTemperature() != null) {
|
|
|
+ alarmTriggered = checkThreshold(sensorData.getTemperature(), threshold.getTemperatureUp(), threshold.getTemperatureDown(), "温度", sensorData);
|
|
|
+ }
|
|
|
+ if (sensorData.getHumidity() != null) {
|
|
|
+ alarmTriggered |= checkThreshold(sensorData.getHumidity(), threshold.getHumidityUp(), threshold.getHumidityDown(), "湿度", sensorData);
|
|
|
+ }
|
|
|
+ if (sensorData.getCo2() != null) {
|
|
|
+ alarmTriggered |= checkThreshold(sensorData.getCo2(), threshold.getCo2Up(), threshold.getCo2Down(), "二氧化碳", sensorData);
|
|
|
+ }
|
|
|
+
|
|
|
+ return alarmTriggered;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查阈值并触发报警
|
|
|
+ *
|
|
|
+ * @param value 传感器数据的值
|
|
|
+ * @param upperThreshold 阈值上限
|
|
|
+ * @param lowerThreshold 阈值下限
|
|
|
+ * @param type 数据类型(温度、湿度、二氧化碳)
|
|
|
+ * @param sensorData 传感器数据
|
|
|
+ * @return 是否触发报警
|
|
|
+ */
|
|
|
+ private boolean checkThreshold(Float value, Float upperThreshold, Float lowerThreshold, String type, SensorData sensorData) {
|
|
|
+ boolean alarmTriggered = false;
|
|
|
+ String deviceName = "设备名称";
|
|
|
+ String time = DATE_FORMAT.format(new Date()); // 获取当前时间
|
|
|
+ String unit = getUnit(type);
|
|
|
+ if (value > upperThreshold) {
|
|
|
+ // 超过上限,触发超标报警
|
|
|
+ publishAlarm(type + "超标", value, unit, deviceName, time);
|
|
|
+ alarmTriggered = true;
|
|
|
+ } else if (value < lowerThreshold) {
|
|
|
+ // 低于下限,触发低于阈值报警
|
|
|
+ publishAlarm(type + "过低", value, unit, deviceName, time);
|
|
|
+ alarmTriggered = true;
|
|
|
+ }
|
|
|
+ return alarmTriggered;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发布报警事件
|
|
|
+ *
|
|
|
+ * @param alarmType 报警类型(例如 温度超标、湿度过低等)
|
|
|
+ * @param value 传感器数据值
|
|
|
+ * @param unit 传感器数据单位
|
|
|
+ * @param deviceName 设备名称
|
|
|
+ * @param time 时间戳
|
|
|
+ */
|
|
|
+ private void publishAlarm(String alarmType, Float value, String unit, String deviceName, String time) {
|
|
|
+ // 获取对应的报警消息模板
|
|
|
+ String alarmMessage = getAlarmMessage(alarmType, value, unit, deviceName, time);
|
|
|
+ // 发布报警事件(可以替换成实际的报警处理逻辑)
|
|
|
+ applicationEventPublisher.publishEvent(new SensorAlarmEvent(this, alarmMessage));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取报警消息模板并替换占位符
|
|
|
+ *
|
|
|
+ * @param alarmType 报警类型(例如 温度超标、湿度过低等)
|
|
|
+ * @param value 传感器数据值
|
|
|
+ * @param unit 传感器数据单位
|
|
|
+ * @param deviceName 设备名称
|
|
|
+ * @param time 时间戳
|
|
|
+ * @return 格式化后的报警消息
|
|
|
+ */
|
|
|
+ private String getAlarmMessage(String alarmType, Float value, String unit, String deviceName, String time) {
|
|
|
+ String messageTemplate = "";
|
|
|
+ // 根据报警类型获取对应的消息模板
|
|
|
+ switch (alarmType) {
|
|
|
+ case "温度超标":
|
|
|
+ messageTemplate = alarmMessageProperties.getTemperatureOverLimit();
|
|
|
+ break;
|
|
|
+ case "温度过低":
|
|
|
+ messageTemplate = alarmMessageProperties.getTemperatureBelowLimit();
|
|
|
+ break;
|
|
|
+ case "湿度超标":
|
|
|
+ messageTemplate = alarmMessageProperties.getHumidityOverLimit();
|
|
|
+ break;
|
|
|
+ case "湿度过低":
|
|
|
+ messageTemplate = alarmMessageProperties.getHumidityBelowLimit();
|
|
|
+ break;
|
|
|
+ case "二氧化碳超标":
|
|
|
+ messageTemplate = alarmMessageProperties.getCo2OverLimit();
|
|
|
+ break;
|
|
|
+ case "二氧化碳过低":
|
|
|
+ messageTemplate = alarmMessageProperties.getCo2BelowLimit();
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ messageTemplate = "{alarmType}: 当前值:{value} {unit}";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 替换模板中的占位符
|
|
|
+ return messageTemplate.replace("{value}", String.format("%.2f", value)).replace("{unit}", unit).replace("{alarmType}", alarmType).replace("{time}", time).replace("{deviceName}", deviceName);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getUnit(String sensorType) {
|
|
|
+ switch (sensorType) {
|
|
|
+ case "温度":
|
|
|
+ return "°C";
|
|
|
+ case "湿度":
|
|
|
+ return "%";
|
|
|
+ case "二氧化碳":
|
|
|
+ return "ppm";
|
|
|
+ default:
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|