Ver código fonte

新增控返不一致报警类型(永州万达)

zhangqiankun 3 anos atrás
pai
commit
6461df03a7

+ 1 - 0
docker/Dockerfile

@@ -8,6 +8,7 @@ COPY *.jar $WORKER_HOME/
 COPY entrypoint.sh $WORKER_HOME/
 COPY *.yml $WORKER_HOME/config/
 COPY *.jks $WORKER_HOME/config/
+COPY *.json $WORKER_HOME/config/
 #EXPOSE 9931
 WORKDIR $WORKER_HOME
 RUN ls

+ 1 - 1
src/main/java/com/persagy/cache/CurrentDataCache.java

@@ -31,7 +31,7 @@ public class CurrentDataCache {
         return latestIOTDataMap.get(getKey(meterId, funcId));
     }
 
-    private String getKey(String meterId, String funcId) {
+    public static String getKey(String meterId, String funcId) {
         return meterId + "-" + funcId;
     }
 

+ 2 - 22
src/main/java/com/persagy/cache/TemperatureWarningCache.java

@@ -1,24 +1,5 @@
 package com.persagy.cache;
 
-
-import cn.hutool.core.collection.CollectionUtil;
-import com.alibaba.fastjson.JSONObject;
-import com.googlecode.aviator.AviatorEvaluator;
-import com.googlecode.aviator.Expression;
-import com.persagy.entity.AlarmDefine;
-import com.persagy.entity.AlarmState;
-import com.persagy.entity.Condition;
-import com.persagy.entity.TemperatureWarningState;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-import org.springframework.util.CollectionUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
-
 /**
  * @Description 温度预警事项
  * @ClassName TemperatureWarningCache.java
@@ -27,13 +8,12 @@ import java.util.stream.Collectors;
  * @createTime  2021/05/07 9:43
  * @Since
  */
-@Component
-@Slf4j
+//@Component
 public class TemperatureWarningCache {
     /**
      * 报警定义  <报警定义标识,温度预警事项状态>
      */
-    private final ConcurrentHashMap<String, TemperatureWarningState> temperatureWarningStateMap = new ConcurrentHashMap<>();
+    //private final ConcurrentHashMap<String, TemperatureWarningState> temperatureWarningStateMap = new ConcurrentHashMap<>();
 
 
 }

+ 34 - 55
src/main/java/com/persagy/client/WebSocketClientFactory.java

@@ -1,21 +1,5 @@
 package com.persagy.client;
 
-import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.date.TimeInterval;
-import cn.hutool.core.thread.ExecutorBuilder;
-import com.persagy.service.AlarmHandleService;
-import com.persagy.utils.GZIPCompressUtil;
-import com.persagy.utils.LockUtil;
-import com.persagy.utils.StringUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.java_websocket.WebSocket;
-import org.java_websocket.client.WebSocketClient;
-import org.java_websocket.handshake.ServerHandshake;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
@@ -24,6 +8,25 @@ import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.java_websocket.WebSocket;
+import org.java_websocket.client.WebSocketClient;
+import org.java_websocket.handshake.ServerHandshake;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import com.persagy.constant.CommonConst;
+import com.persagy.init.InitReturnAlarmConfig;
+import com.persagy.netty.collect.ReturnDifferentAlarm;
+import com.persagy.service.AlarmHandleService;
+import com.persagy.utils.GZIPCompressUtil;
+import com.persagy.utils.LockUtil;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.date.TimeInterval;
+import cn.hutool.core.thread.ExecutorBuilder;
+import lombok.extern.slf4j.Slf4j;
+
 /**
  * @description: WebSocketClient连接,接受IOT采集数据
  * @author:LuoGuangyi
@@ -47,34 +50,15 @@ public class WebSocketClientFactory {
             .setWorkQueue(new LinkedBlockingQueue<>(102400))
             .setHandler(new ThreadPoolExecutor.AbortPolicy())
             .build();
+    
+    @Autowired
+    private AlarmHandleService alarmHandleService;
+    
     @Autowired
-    AlarmHandleService alarmHandleService;
+    private ReturnDifferentAlarm returnDifferentAlarm;
+    
     AtomicInteger total = new AtomicInteger(0);
-    /**
-     * IP
-     */
-    @Value("${terminal.alarm.host:127.0.0.1}")
-    private String host;
-    /**
-     * 端口
-     */
-    @Value("${terminal.alarm.port}")
-    private int port;
-    /**
-     * 后缀
-     */
-    @Value("${terminal.alarm.suffix}")
-    private String suffix;
-    /**
-     * 是否启用压缩
-     */
-    @Value("${terminal.alarm.compress}")
-    private boolean compress;
-    /**
-     * 项目名称
-     */
-    @Value("${project.iotid}")
-    private String iotProjectId;
+    
     private WebSocketClient outCallWebSocketClientHolder;
 
     public WebSocketClient getOutCallWebSocketClientHolder() {
@@ -92,20 +76,17 @@ public class WebSocketClientFactory {
      * @throws URISyntaxException
      */
     private WebSocketClient createNewWebSocketClient() throws URISyntaxException {
-        String outCallWebSockertUrl = "ws://" + host + ":" + port;
-        outCallWebSockertUrl += StringUtil.isEmpty(suffix) ? "" : "/" + suffix;
-        log.info("连接地址为:[{}]", outCallWebSockertUrl);
-        WebSocketClient webSocketClient = new WebSocketClient(new URI(outCallWebSockertUrl)) {
+        log.info("iot-project连接地址为:[{}]", CommonConst.websocket);
+        WebSocketClient webSocketClient = new WebSocketClient(new URI(CommonConst.websocket)) {
             @Override
             public void onOpen(ServerHandshake serverHandshake) {
-                String msg = iotProjectId;
-                sendMsg(getOutCallWebSocketClientHolder(), msg);
+                //sendMsg(getOutCallWebSocketClientHolder(), CommonConst.building);
             }
 
             @Override
             public void onMessage(String msg) {
                 String message = msg;
-                if (compress) {
+                if (CommonConst.compress) {
                     try {
                         byte[] byteArrayMsg = GZIPCompressUtil.uncompress(msg.getBytes(StandardCharsets.ISO_8859_1));
                         message = new String(byteArrayMsg);
@@ -120,12 +101,6 @@ public class WebSocketClientFactory {
                             log.warn("等待获取锁....");
                             LockUtil.getInstance().lock.lockInterruptibly();
                             log.warn("已经获取锁....");
-//                            try {
-//                                LockUtil.getInstance().condition.await();
-//                            } catch (InterruptedException e) {
-//                                e.printStackTrace();
-//                            }
-//                            log.warn("等待结束....");
                         } catch (Exception e) {
                             log.error("数据加锁处理发生异常", e);
                         } finally {
@@ -140,6 +115,10 @@ public class WebSocketClientFactory {
                             log.error("数据处理失败", e);
                         }
                     });
+                    // 控返不一致报警处理
+                    if (CommonConst.collectEnable && InitReturnAlarmConfig.alarmEnable) {
+                    	executor.execute(() -> returnDifferentAlarm.putMsg(finalMessage));
+					}
                 } catch (Exception e) {
                     log.error("数据处理失败", e);
                 }

+ 107 - 26
src/main/java/com/persagy/constant/CommonConst.java

@@ -1,35 +1,116 @@
 package com.persagy.constant;
 
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
 /**
- * @description: 通用常量
- * @author:LuoGuangyi
- * @company:PersagyTechnologyCo.,Ltd
- * @since:2021/04/13 16:52
- * @version:V1.0
- **/
+ * 获取此服务的所有配置
+ * 
+ * @version 1.0.0
+ * @company persagy 
+ * @author zhangqiankun
+ * @date 2021年12月8日 下午8:02:36
+ */
+@Component
 public class CommonConst {
-    /**
-     * 项目id
-     */
-    public static String projectId;
-    /**
-     * 集团编码
-     */
+	
+	/** 项目根路径*/
+	public static final String SERVER_ROOT_PATH = System.getProperty("user.dir");
+
+    /** 系统标识,用于创建人 */
+    public static String systemId;
+    
+    /** 是否启用kafka推送 */
+    public static boolean kafkaEnable;
+    
+    /** 集团编码 */
     public static String groupCode;
 
+    /** 项目ID */
+    public static String projectId;
 
-    /**
-     * 云端nettyhost
-     */
-    public static String inetHost;
-    /**
-     * 云端netty端口
-     */
-    public static int inetPort;
-    /**
-     * 系统标识,用于创建人
-     */
-    public static String systemId;
+    /** iot中所使用的项目ID,切记不带Pj */
+    public static String building;
+
+    /** 报警服务地址 */
+    public static String alarmHost;
+    
+    /** 报警服务netty端口 */
+    public static int alarmPort;
+
+    /** 是否开启压缩 */
+    public static boolean compress;
+
+    /** iot-collect服务,是否启用 */
+    public static boolean collectEnable;
+    
+    /** iot-collect服务的IP地址 */
+    public static String collectHost;
 
+    /** iot-collect服务的收数端口 */
+    public static int collectPort;
+    
+    /** iot-project服务的webSocket地址 */
+    public static String websocket;
 
-}
+    @Value("${system.id}")
+    public void setSystemId(String value) {
+        CommonConst.systemId = value;
+    }
+    
+    @Value("${spring.kafka.enable:false}")
+    public void setKafkaEnable(Boolean value) {
+        CommonConst.kafkaEnable = value;
+    }
+    
+    @Value("${config.group-code}")
+    public void setGroupCode(String value) {
+        CommonConst.groupCode = value;
+    }
+    
+    @Value("${config.project-id}")
+    public void setProjectId(String value) {
+        CommonConst.projectId = value;
+    }
+    
+    @Value("${config.building}")
+    public void setBuilding(String value) {
+        CommonConst.building = value;
+    }
+    
+    @Value("${ibms-alarm.host}")
+    public void setAlarmHost(String value) {
+        CommonConst.alarmHost = value;
+    }
+    
+    @Value("${ibms-alarm.port}")
+    public void setAlarmPort(int value) {
+        CommonConst.alarmPort = value;
+    }
+    
+    @Value("${ibms-alarm.compress}")
+    public void setCompress(Boolean value) {
+        CommonConst.compress = value;
+    }
+    
+    @Value("${iot.collect.enable}")
+    public void setCollectEnable(Boolean value) {
+        CommonConst.collectEnable = value;
+    }
+    
+    @Value("${iot.collect.host}")
+    public void setCollectHost(String value) {
+        CommonConst.collectHost = value;
+    }
+    
+    @Value("${iot.collect.port}")
+    public void setCollectPort(int value) {
+        CommonConst.collectPort = value;
+    }
+    
+    @Value("${iot.project.websocket}")
+    public void setWebsocket(String value) {
+        CommonConst.websocket = value;
+    }
+    
+}

+ 31 - 0
src/main/java/com/persagy/entity/PonitData.java

@@ -0,0 +1,31 @@
+package com.persagy.entity;
+
+import java.math.BigDecimal;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+/**
+ * 
+ * @version 1.0.0
+ * @company persagy 
+ * @author zhangqiankun
+ * @date 2021年12月9日 下午4:38:19
+ */
+@Getter
+@Setter
+@ToString
+public class PonitData {
+
+	private String infoCode;
+	
+    private String meter;
+	
+    private Integer funcid;
+    
+    private String dataTime;
+    
+    private BigDecimal dataValue;
+	
+}

+ 41 - 0
src/main/java/com/persagy/entity/ReturnAlarmDefine.java

@@ -0,0 +1,41 @@
+package com.persagy.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+/**
+ * 控返不一致报警定义
+ * 
+ * @version 1.0.0
+ * @company persagy 
+ * @author zhangqiankun
+ * @date 2021年12月9日 下午3:07:15
+ */
+@Getter
+@Setter
+@ToString
+public class ReturnAlarmDefine {
+	
+	/** 集团编码 */
+    private String groupCode;
+	
+    /** 项目ID */
+    private String projectId;
+    
+    /** 项目ID,不带Pj */
+    private String building;
+    
+	/** 需要判断的信息点 */
+	private PonitData setInfo;
+	
+	/** 实际iot数据点位*/
+	private PonitData returnInfo;
+	
+	/** 报警信息点 */
+	private PonitData alarmInfo;
+	
+	/** 报警条件 */
+	private String alarmCondition;
+
+}

+ 160 - 0
src/main/java/com/persagy/init/InitReturnAlarmConfig.java

@@ -0,0 +1,160 @@
+package com.persagy.init;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ResourceUtils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.parser.Feature;
+import com.persagy.cache.CurrentDataCache;
+import com.persagy.constant.CommonConst;
+import com.persagy.entity.PonitData;
+import com.persagy.entity.ReturnAlarmDefine;
+
+import cn.hutool.core.util.BooleanUtil;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 项目启动后,加载控返不一致报警所需数据
+ * 
+ * @version 1.0.0
+ * @company persagy 
+ * @author zhangqiankun
+ * @date 2021年10月14日 下午5:09:18
+ */
+@Slf4j
+@Component
+public class InitReturnAlarmConfig implements CommandLineRunner {
+	
+	public static volatile boolean alarmEnable = false;
+	
+	/** 信息点到报警定义 */
+	public static Map<String, ReturnAlarmDefine> infoCode2Alarm = new HashMap<String, ReturnAlarmDefine>();
+	/** 信息点到报警定义 */
+	public static Map<String, ReturnAlarmDefine> returnCode2Alarm = new HashMap<String, ReturnAlarmDefine>();
+	/** 信息点到报警定义 */
+	public static Map<String, ReturnAlarmDefine> alarmCode2Alarm = new HashMap<String, ReturnAlarmDefine>();
+	
+	/** 表号-功能号, 信息点 */
+	public static Map<String, String> meterFunid2Code = new HashMap<String, String>();
+	
+	/** 报警信息点, 1-报警,0-正常,-1-不作任何处理 */
+	public static Map<String, Integer> alarmCode2IsAlarm = new ConcurrentHashMap<String, Integer>();
+	
+	@Override
+	public void run(String... args) throws Exception {
+		if (!CommonConst.collectEnable) {
+			return;
+		}
+		// 获取控返不一致报警配置文件
+		File file = this.getFile();
+		if (file == null || !file.exists()) {
+			return;
+		}
+		// 解析文件
+		this.parseAlarmConfig(file);
+	}
+	
+	/**
+	 * 文件加载,并放入本地缓存
+	 * 
+	 * @param alarmFile
+	 * @throws IOException 
+	 * @date 2021年10月14日 下午5:35:03
+	 */
+	private void parseAlarmConfig(File alarmFile) throws IOException {
+		JSONObject fileJSON = this.readFileInfo(alarmFile);
+		alarmEnable = fileJSON.getBoolean("alarm-enable");
+		if (!BooleanUtil.isTrue(alarmEnable)) {
+			return;
+		}
+		
+		JSONArray alarmDefines = fileJSON.getJSONArray("alarm-define");
+		for (int i = 0; i < alarmDefines.size(); i++) {
+			JSONObject alarmDefine = alarmDefines.getJSONObject(i);
+			
+			ReturnAlarmDefine define = new ReturnAlarmDefine();
+			define.setGroupCode(CommonConst.groupCode);
+			define.setProjectId(CommonConst.projectId);
+			define.setBuilding(CommonConst.building);
+			
+			// 需要判断的信息点
+			JSONObject setInfo = alarmDefine.getJSONObject("setInfo");
+			PonitData setPonitData = new PonitData();
+			setPonitData.setInfoCode(setInfo.getString("code"));
+			setPonitData.setMeter(setInfo.getString("meter"));
+			setPonitData.setFuncid(Integer.valueOf(setInfo.getString("funcid")));
+			define.setSetInfo(setPonitData);
+			infoCode2Alarm.put(setInfo.getString("code"), define);
+			meterFunid2Code.put(CurrentDataCache.getKey(setInfo.getString("meter"), setInfo.getString("funcid")), setInfo.getString("code"));
+			
+			// 需要验证的实际信息点
+			JSONObject returnInfo = alarmDefine.getJSONObject("returnInfo");
+			PonitData returnPonitData = new PonitData();
+			returnPonitData.setInfoCode(returnInfo.getString("code"));
+			returnPonitData.setMeter(returnInfo.getString("meter"));
+			returnPonitData.setFuncid(Integer.valueOf(returnInfo.getString("funcid")));
+			define.setReturnInfo(returnPonitData);
+			returnCode2Alarm.put(returnInfo.getString("code"), define);
+			meterFunid2Code.put(CurrentDataCache.getKey(returnInfo.getString("meter"), returnInfo.getString("funcid")), returnInfo.getString("code"));
+			
+			// 需要产生报警的信息点
+			JSONObject alarmInfo = alarmDefine.getJSONObject("alarmInfo");
+			PonitData alarmPonitData = new PonitData();
+			alarmPonitData.setInfoCode(alarmInfo.getString("code"));
+			alarmPonitData.setMeter(alarmInfo.getString("meter"));
+			alarmPonitData.setFuncid(Integer.valueOf(alarmInfo.getString("funcid")));
+			define.setAlarmInfo(alarmPonitData);
+			alarmCode2Alarm.put(alarmInfo.getString("code"), define);
+			alarmCode2IsAlarm.put(alarmInfo.getString("code"), -1);		// 默认不做任何处理
+			meterFunid2Code.put(CurrentDataCache.getKey(alarmInfo.getString("meter"), alarmInfo.getString("funcid")), alarmInfo.getString("code"));
+			
+			define.setAlarmCondition(alarmDefine.getString("alarmCondition"));
+		}
+	}
+	
+	/**
+	 * 读取文件内容,返回文件信息
+	 * 
+	 * @return
+	 * @throws IOException 
+	 * @date 2021年10月14日 下午5:37:29
+	 */
+	private JSONObject readFileInfo(File file) throws IOException {
+		return JSON.parseObject(new FileInputStream(file), StandardCharsets.UTF_8, JSONObject.class,
+                // 自动关闭流
+                Feature.AutoCloseSource,
+                // 允许注释
+                Feature.AllowComment,
+                // 允许单引号
+                Feature.AllowSingleQuotes);
+		
+	}
+	
+	
+	private File getFile() throws FileNotFoundException {
+		File file = null;
+		try {
+			// 先获取config目录下的文件,获取不到,再获取classpath下的
+			file = ResourceUtils.getFile(CommonConst.SERVER_ROOT_PATH + "/config/return-alarm.json");
+			if (!file.exists()) {
+				log.warn("config目录下不存在控返不一致的报警配置,获取classpath下的默认配置");
+				file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "return-alarm.json");
+			}
+		} catch (Exception e) {
+		}
+		return file;
+	}
+	
+}

+ 20 - 45
src/main/java/com/persagy/init/InitRunner.java

@@ -1,83 +1,58 @@
 package com.persagy.init;
 
 
-import cn.hutool.core.thread.ThreadUtil;
+import javax.servlet.ServletContextAttributeListener;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Service;
+
 import com.googlecode.aviator.AviatorEvaluator;
 import com.persagy.client.WebSocketClientFactory;
 import com.persagy.constant.CommonConst;
 import com.persagy.job.AlarmMessageThread;
 import com.persagy.netty.client.NettyClient;
+import com.persagy.netty.collect.IotCollectNettyClient;
 import com.persagy.service.AlarmQuartzService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.CommandLineRunner;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Service;
 
-import javax.servlet.ServletContextAttributeListener;
+import cn.hutool.core.thread.ThreadUtil;
 
 
 @Service
 @Order(1)
-@Slf4j
 public class InitRunner implements ServletContextAttributeListener, CommandLineRunner {
 
     @Autowired
     AlarmQuartzService alarmQuartzService;
+    
     @Autowired
     private WebSocketClientFactory webSocketClientFactory;
+    
+    @Autowired
+    private IotCollectNettyClient iotCollectNettyClient;
+    
     @Autowired
     private NettyClient nettyClient;
-    @Value("${spring.kafka.enable:false}")
-    private Boolean kafkaEnable;
 
     @Override
     public void run(String... args) throws Exception {
 
         //5.0 开始引入了 LRU 缓存,可指定缓存的表达式个数,比如设置为最大 1 万个缓存结果:
         AviatorEvaluator.getInstance().useLRUExpressionCache(10000);
-        if(!kafkaEnable) {
+        if(!CommonConst.kafkaEnable) {
             //启动netty客户端,接受云端数据
             nettyClient.connect();
         }
+        // 启动collect服务连接
+        if (CommonConst.collectEnable) {
+        	iotCollectNettyClient.connect();
+		}
+        
         //启动websocket,接受IOT采集庶数据
         webSocketClientFactory.retryOutCallWebSocketClient();
         //异步消费消息
         ThreadUtil.execAsync(new AlarmMessageThread(alarmQuartzService), true);
     }
 
-    /**
-     * 项目名称
-     */
-    @Value("${project.id}")
-    public void setProjectId(String value) {
-        CommonConst.projectId = value;
-    }
-
-    /**
-     * 集团编码
-     */
-    @Value("${group.code}")
-    public void setGroupCode(String value) {
-        CommonConst.groupCode = value;
-    }
-
-
-    @Value("${group.alarm.host:127.0.0.1}")
-    public void setInetHost(String value) {
-        CommonConst.inetHost = value;
-    }
-
-
-    @Value("${group.alarm.port}")
-    public void setInetPort(int value) {
-        CommonConst.inetPort = value;
-    }
-
-    @Value("${system.id}")
-    public void setSystemId(String value) {
-        CommonConst.systemId = value;
-    }
-
 }

+ 1 - 3
src/main/java/com/persagy/netty/client/CenterChannelInitializer.java

@@ -4,11 +4,9 @@ import com.persagy.netty.codec.ObjDecoder;
 import com.persagy.netty.codec.ObjEncoder;
 import com.persagy.repository.AlarmRecordRepository;
 import com.persagy.service.AlarmDefineService;
+
 import io.netty.channel.ChannelInitializer;
 import io.netty.channel.socket.SocketChannel;
-import io.netty.handler.timeout.IdleStateHandler;
-
-import java.util.concurrent.TimeUnit;
 
 
 public class CenterChannelInitializer extends ChannelInitializer<SocketChannel> {

+ 10 - 9
src/main/java/com/persagy/netty/client/CenterClientHandler.java

@@ -1,8 +1,9 @@
 package com.persagy.netty.client;
 
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.date.TimeInterval;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.TypeReference;
 import com.persagy.cache.AlarmInfoCache;
@@ -14,20 +15,20 @@ import com.persagy.job.NettyMessageQueue;
 import com.persagy.repository.AlarmRecordRepository;
 import com.persagy.service.AlarmDefineService;
 import com.persagy.utils.LockUtil;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.date.TimeInterval;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.SimpleChannelInboundHandler;
 import lombok.extern.slf4j.Slf4j;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
 @Slf4j
 public class CenterClientHandler extends SimpleChannelInboundHandler<NettyMessage<JSONObject>> {
     // Sleep 5 seconds before a reconnection attempt.
     static final int RECONNECT_DELAY = Integer.parseInt(System.getProperty("reconnectDelay", "5"));
     // Reconnect when the server sends nothing for 10 seconds.
-    private static final int READ_TIMEOUT = Integer.parseInt(System.getProperty("readTimeout", "10"));
+    // private static final int READ_TIMEOUT = Integer.parseInt(System.getProperty("readTimeout", "10"));
 
     private final AlarmDefineService alarmDefineService;
     private final NettyClient nettyClient;
@@ -187,7 +188,7 @@ public class CenterClientHandler extends SimpleChannelInboundHandler<NettyMessag
 
     @Override
     public void channelUnregistered(final ChannelHandlerContext ctx) throws Exception {
-        log.info("channelUnregistered and reconnecting to: {}:{} ", RECONNECT_DELAY, CommonConst.inetHost, CommonConst.inetPort);
+        log.info("channelUnregistered and reconnecting to: {}:{} ", RECONNECT_DELAY, CommonConst.alarmHost, CommonConst.alarmPort);
         ctx.channel().eventLoop().schedule(new Runnable() {
             @Override
             public void run() {

+ 7 - 6
src/main/java/com/persagy/netty/client/NettyClient.java

@@ -22,17 +22,18 @@ import org.springframework.stereotype.Component;
 public class NettyClient {
 
     public static Channel channel;
+    
     public Bootstrap bootstrap = new Bootstrap();
+    
     @Autowired
     AlarmDefineService alarmDefineService;
+    
     @Autowired
     AlarmRecordRepository alarmRecordRepository;
+    
     @Autowired(required = false)
     private KafkaProducer kafkaProducer;
 
-    @Value("${spring.kafka.enable:false}")
-    private Boolean kafkaEnable;
-
     public void connect() {
         EventLoopGroup workerGroup = new NioEventLoopGroup();
         try {
@@ -40,7 +41,7 @@ public class NettyClient {
             bootstrap.channel(NioSocketChannel.class);
             bootstrap.option(ChannelOption.AUTO_READ, true);
             bootstrap.handler(new CenterChannelInitializer(alarmDefineService, this, alarmRecordRepository));
-            ChannelFuture f = bootstrap.connect(CommonConst.inetHost, CommonConst.inetPort).sync();
+            ChannelFuture f = bootstrap.connect(CommonConst.alarmHost, CommonConst.alarmPort).sync();
             channel = f.channel();
             // f.channel().closeFuture().sync();
         } catch (Exception e) {
@@ -53,7 +54,7 @@ public class NettyClient {
 
     public void reConnect() {
         // 加入断线后自动重连监听器
-        channel = bootstrap.connect(CommonConst.inetHost, CommonConst.inetPort).addListener(new ChannelFutureListener() {
+        channel = bootstrap.connect(CommonConst.alarmHost, CommonConst.alarmPort).addListener(new ChannelFutureListener() {
             @Override
             public void operationComplete(ChannelFuture future) throws Exception {
                 if (future.cause() != null) {
@@ -65,7 +66,7 @@ public class NettyClient {
 
 
     public void sendMessage(NettyMessage msg) throws InterruptedException {
-        if(kafkaEnable){
+        if(CommonConst.kafkaEnable){
             kafkaProducer.send(msg);
         }else {
             log.info("给云端发送数据:[{}]", msg);

+ 97 - 0
src/main/java/com/persagy/netty/collect/IotCollectNettyClient.java

@@ -0,0 +1,97 @@
+package com.persagy.netty.collect;
+
+import org.springframework.stereotype.Component;
+
+import com.persagy.constant.CommonConst;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.codec.string.StringDecoder;
+import io.netty.handler.codec.string.StringEncoder;
+import io.netty.util.CharsetUtil;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * iot-collect 服务netty
+ * 
+ * @version 1.0.0
+ * @company persagy 
+ * @author zhangqiankun
+ * @date 2021年12月9日 上午10:09:00
+ */
+@Slf4j
+@Component
+public class IotCollectNettyClient {
+
+    public static Channel channel;
+    
+    public Bootstrap bootstrap = new Bootstrap();
+    
+    public void connect() {
+        EventLoopGroup workerGroup = new NioEventLoopGroup();
+        try {
+            bootstrap.group(workerGroup);
+            bootstrap.channel(NioSocketChannel.class);
+            bootstrap.option(ChannelOption.AUTO_READ, true);
+            bootstrap.handler(new ChannelInitializer<SocketChannel>() { // 绑定连接初始化器
+				@Override
+				protected void initChannel(SocketChannel ch) throws Exception {
+					log.info("正在连接中...");
+					ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
+					ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
+				}
+			});
+            ChannelFuture f = bootstrap.connect(CommonConst.collectHost, CommonConst.collectPort).sync();
+            channel = f.channel();
+        } catch (Exception e) {
+            log.info("连接异常", e);
+        } 
+    }
+
+
+    public void reConnect() {
+        // 加入断线后自动重连监听器
+        channel = bootstrap.connect(CommonConst.collectHost, CommonConst.collectPort).addListener(new ChannelFutureListener() {
+            @Override
+            public void operationComplete(ChannelFuture future) throws Exception {
+                if (future.cause() != null) {
+                    log.error("Failed to connect: {}", future.cause());
+                }
+            }
+        }).channel();
+    }
+
+
+    public void sendMessage(String command) throws InterruptedException {
+    	int count = 0;
+    	while ((!channel.isActive() || !channel.isWritable()) && count < 5) {
+    		channel.close();
+        	this.reConnect();
+        	count++;
+        	// 不能太快,稍微等一会在执行
+        	Thread.yield();
+    	}
+    	if (count >= 5) {
+    		log.error("Failed to connect iot-collect服务");
+    		return;
+		}
+    	
+    	log.info("上报数据至iot-collect服务,报文:{}", command);
+        try {
+            channel.writeAndFlush(command);
+        } catch (Exception e) {
+        	e.printStackTrace();
+            log.error("上报数据至iot-collect服务失败", e);
+            channel.close();
+        }
+    }
+
+}

+ 197 - 0
src/main/java/com/persagy/netty/collect/ReturnDifferentAlarm.java

@@ -0,0 +1,197 @@
+package com.persagy.netty.collect;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import com.alibaba.fastjson.JSONObject;
+import com.googlecode.aviator.AviatorEvaluator;
+import com.googlecode.aviator.Expression;
+import com.persagy.cache.CurrentDataCache;
+import com.persagy.entity.ReturnAlarmDefine;
+import com.persagy.init.InitReturnAlarmConfig;
+
+import cn.hutool.core.date.DateUnit;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.BooleanUtil;
+import cn.hutool.core.util.StrUtil;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 控返不一致报警
+ * 
+ * @version 1.0.0
+ * @company persagy 
+ * @author zhangqiankun
+ * @date 2021年12月9日 上午10:09:00
+ */
+@Slf4j
+@Component
+public class ReturnDifferentAlarm {
+	
+	/** 从左到右:项目,时间,表号,功能号,值 */
+	public static final String COMMAND = "({};1;report;{};123;{};1;{};{})";
+	
+	@Autowired
+	private IotCollectNettyClient iotCollectNettyClient;
+	
+	/**
+	 * 启动后 延时 10s触发,以5s的间隔时间触发控返不一致的信息点实时数据写入
+	 * 
+	 * 每5s的间隔,代表着人为抑制了5s的持续性报警
+	 * 
+	 * @throws Exception
+	 * @date 2021年12月9日 下午8:11:36
+	 */
+    @Scheduled(initialDelay = 10 * 1000, fixedRate = 5 * 1000)
+    public void returnDifferentAlarm() throws Exception {
+    	if (InitReturnAlarmConfig.alarmCode2Alarm.size() == 0) {
+			return;
+		}
+    	String now = DateUtil.date().toString("yyyyMMddHHmmss");
+    	
+    	// 根据数据,拼接出指令信息,发送入库
+    	StringBuilder sb = new StringBuilder();
+    	Set<String> alarmCodes = InitReturnAlarmConfig.alarmCode2IsAlarm.keySet();
+    	for (String alarmCode : alarmCodes) {
+    		Integer isAlarm = InitReturnAlarmConfig.alarmCode2IsAlarm.get(alarmCode);
+    		if (isAlarm != null && isAlarm != -1) {
+    			ReturnAlarmDefine alarmDefine = InitReturnAlarmConfig.alarmCode2Alarm.get(alarmCode);
+    			// 0-正常,1-报警
+    			BigDecimal dataValue = isAlarm == 1 ? new BigDecimal("1") : new BigDecimal("0");
+    			String command = StrUtil.format(COMMAND, alarmDefine.getBuilding(), now, alarmDefine.getAlarmInfo().getMeter(), alarmDefine.getAlarmInfo().getFuncid(), dataValue.toPlainString());
+    			sb.append(command).append("&");
+			}
+		}
+    	
+    	String command = sb.toString();
+    	if (command != null && command.endsWith("&")) {
+    		command = command.substring(0, command.length() - 1);
+		}
+    	
+    	// 数据上报
+    	if (StrUtil.isNotBlank(command)) {
+    		this.iotCollectNettyClient.sendMessage(command);
+		}
+    }
+    
+    /**
+     * {"data":"20211209150133;10346;903;1.0","type":"pointset"}
+     * {"data":"20211209155421;CW20379;902;0.0","type":"iot"}
+     * 
+     * @param message
+     * @date 2021年12月9日 下午3:54:35
+     */
+    public void putMsg(String message) {
+    	if (InitReturnAlarmConfig.infoCode2Alarm.size() == 0) {
+			return;
+		}
+    	
+    	Set<String> infoCodes = InitReturnAlarmConfig.infoCode2Alarm.keySet();
+    	Set<String> returnCodes = InitReturnAlarmConfig.returnCode2Alarm.keySet();
+    	try {
+    		// 解析此条iot数据详情
+			JSONObject messageObj = JSONObject.parseObject(message);
+			String data = messageObj.getString("data");
+			String[] split = data.split(";");
+			String dataTime = split[0];
+			String meter = split[1];
+			String funcid = split[2];
+			BigDecimal dataValue = new BigDecimal(split[3]);
+			
+			// 根据表号和功能号判断是否需要进行控返不一致的报警验证
+			ReturnAlarmDefine returnAlarmDefine = null;
+			String code = InitReturnAlarmConfig.meterFunid2Code.get(CurrentDataCache.getKey(meter, funcid));
+			if (infoCodes.contains(code)) {
+				returnAlarmDefine = InitReturnAlarmConfig.infoCode2Alarm.get(code);
+				// 防止频繁的控制,导致无法进入2分钟后的逻辑判断,这里如果值相同的话,取上一次的上报时间使用
+				BigDecimal oldValue = returnAlarmDefine.getSetInfo().getDataValue();
+				if (oldValue == null || dataValue.compareTo(oldValue) != 0) {
+					returnAlarmDefine.getSetInfo().setDataTime(dataTime);
+					returnAlarmDefine.getSetInfo().setDataValue(dataValue);
+				}
+			} else if (returnCodes.contains(code)) {
+				returnAlarmDefine = InitReturnAlarmConfig.returnCode2Alarm.get(code);
+				returnAlarmDefine.getReturnInfo().setDataTime(dataTime);
+				returnAlarmDefine.getReturnInfo().setDataValue(dataValue);
+			}
+			
+			if (returnAlarmDefine == null) {
+				return;
+			}
+			
+			// 正常数据下,判断此条数据,是否会影响控返不一致的报警信息点
+			this.returnAlarmHandler(returnAlarmDefine);
+		} catch (Exception e) {
+			e.printStackTrace();
+			log.error("控返不一致的报警,逻辑处理异常", e);
+		}
+    }
+
+    /**
+     * 判断此条数据,是否会影响控返不一致的报警信息点的值
+     * 
+     * 因为在服务启动的时候,iot-project会推送一次全量数据,所以在数据正常的情况下,一定有值
+     * 
+	 * 是否报警说明:
+	 * 1.新的指令和旧的iot数据,无论是否满足报警定义都不做任何处理,等待最新的iot数据上传后在做判断
+     * 
+     * 2.旧的指令和新的iot数据
+     * 	不是2分钟后上传上来的iot数据,这里不做任何处理
+     * 	满足报警条件,产生报警,不满足,恢复
+     * 
+     * @param returnAlarmDefine
+     * @date 2021年12月9日 下午5:29:37
+     */
+	private void returnAlarmHandler(ReturnAlarmDefine returnAlarmDefine) {
+		String setTimeStr = returnAlarmDefine.getSetInfo().getDataTime();
+		String returnTimeStr = returnAlarmDefine.getReturnInfo().getDataTime();
+		if (!StrUtil.isAllNotBlank(setTimeStr, returnTimeStr)) {
+			InitReturnAlarmConfig.alarmCode2IsAlarm.put(returnAlarmDefine.getAlarmInfo().getInfoCode(), -1);
+			return;
+		}
+		long setTime = Long.valueOf(setTimeStr);
+		long returnTime = Long.valueOf(returnTimeStr);
+		if (setTime > returnTime) {
+        	// 新的指令和旧的iot数据,无论是否满足报警定义都不做任何处理,等待最新的iot数据上传后在做判断
+        	InitReturnAlarmConfig.alarmCode2IsAlarm.put(returnAlarmDefine.getAlarmInfo().getInfoCode(), -1);
+        	return;
+        }
+		
+		// 先判断一下这两条数据之间是否时差超过2分钟
+		long minute = DateUtil.between(DateUtil.parse(setTimeStr, "yyyyMMddHHmmss"), DateUtil.parse(returnTimeStr, "yyyyMMddHHmmss"), DateUnit.MINUTE, true);
+		boolean newest = minute > 1;
+		
+		// 报警条件初次验证
+		String alarmCondition = returnAlarmDefine.getAlarmCondition();
+		Expression triggerExp = AviatorEvaluator.compile(alarmCondition, true);
+		
+		// 判断实际是否应该产生报警
+		String infoCode = returnAlarmDefine.getSetInfo().getInfoCode();
+		String returnCode = returnAlarmDefine.getReturnInfo().getInfoCode();
+		Map<String, Object> paramMap = new HashMap<String, Object>();
+		paramMap.put(infoCode, returnAlarmDefine.getSetInfo().getDataValue());
+		paramMap.put(returnCode, returnAlarmDefine.getReturnInfo().getDataValue());
+        Boolean triggerResult = (Boolean) triggerExp.execute(paramMap);
+        
+    	// 旧的指令和新的iot数据
+    	if (!newest) {
+    		// 不是2分钟后上传上来的iot数据,这里不做任何处理
+			InitReturnAlarmConfig.alarmCode2IsAlarm.put(returnAlarmDefine.getAlarmInfo().getInfoCode(), -1);
+		} else if (BooleanUtil.isTrue(triggerResult)) {
+			// 满足报警条件,产生报警
+        	InitReturnAlarmConfig.alarmCode2IsAlarm.put(returnAlarmDefine.getAlarmInfo().getInfoCode(), 1);
+		} else if (BooleanUtil.isFalse(triggerResult)) {
+			// 不满足报警条件,如果已报警,则需恢复
+        	InitReturnAlarmConfig.alarmCode2IsAlarm.put(returnAlarmDefine.getAlarmInfo().getInfoCode(), 0);
+		} else {
+			InitReturnAlarmConfig.alarmCode2IsAlarm.put(returnAlarmDefine.getAlarmInfo().getInfoCode(), -1);
+		}
+	}
+	
+}

+ 31 - 16
src/main/java/com/persagy/service/impl/AlarmHandleServiceImpl.java

@@ -1,14 +1,37 @@
 package com.persagy.service.impl;
 
-import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.util.ObjectUtil;
+import static org.apache.commons.lang3.math.NumberUtils.INTEGER_ONE;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.apache.commons.lang3.StringUtils;
+import org.quartz.JobDataMap;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
 import com.alibaba.fastjson.JSONObject;
 import com.googlecode.aviator.AviatorEvaluator;
 import com.googlecode.aviator.Expression;
 import com.persagy.cache.AlarmInfoCache;
 import com.persagy.cache.CurrentDataCache;
 import com.persagy.constant.CommonConst;
-import com.persagy.entity.*;
+import com.persagy.entity.AlarmDefine;
+import com.persagy.entity.AlarmRecord;
+import com.persagy.entity.AlarmState;
+import com.persagy.entity.Condition;
+import com.persagy.entity.ExpireAlarmMessage;
+import com.persagy.entity.NettyMessage;
+import com.persagy.entity.ZktAlarmRecordDO;
 import com.persagy.job.ExpireAlarmQueue;
 import com.persagy.netty.client.NettyClient;
 import com.persagy.repository.AlarmRecordRepository;
@@ -16,20 +39,10 @@ import com.persagy.service.AlarmHandleService;
 import com.persagy.service.AlarmQuartzService;
 import com.persagy.utils.DateUtils;
 import com.persagy.utils.StringUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.quartz.JobDataMap;
-import org.quartz.SchedulerException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.format.DateTimeFormatter;
-import java.util.*;
-
-import static org.apache.commons.lang3.math.NumberUtils.INTEGER_ONE;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjectUtil;
+import lombok.extern.slf4j.Slf4j;
 
 /**
  * @description:报警处理实现类:包含报警产生和报警恢复
@@ -65,6 +78,8 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
      */
     @Override
     public void handleIOTData(String msg) throws SchedulerException, InterruptedException {
+		JSONObject parseObject = JSONObject.parseObject(msg);
+		msg = parseObject.getString("data");
         String[] split = msg.split(";");
         if (split.length % 4 != 0) {
             return;

+ 31 - 24
src/main/resources/application-16Pj3201110003.yml

@@ -1,24 +1,31 @@
-group:
-  #需要更改
-  code: HY   #标识哪个接团 南京弘扬
-  alarm:
-    #需要更改
-    host: 39.102.43.179 #netty IP39.102.43.179
-    #需要更改
-    port: 9986          #netty 端口8826
-    #需要更改
-terminal: #边缘端IOT采集程序地址
-  alarm: # 拼接后的地址为ws://host:port/suffix
-    #需要更改
-    compress: false    #采用的是压缩方式还是不压缩方式  true-压缩 false-不压缩
-    #需要更改
-    host: 39.96.55.242  # 172.17.233.176
-    #需要更改
-    port: 9984 #9984
-    #需要更改
-    suffix: websocket   #websocker后缀
-project:
-  #需要更改
-  iotid: 3201110003 #iot使用项目ID,不包含PJ
-  #需要更改
-  id: Pj3201110003 #南京弘扬项目ID
+config:
+  # 标识哪个接团 比如万达使用WD,需修改
+  group-code: HY
+  # 项目ID,需修改
+  project-id: Pj3201110003
+  # iot数据汇总所使用的项目ID,切记不包含Pj,需修改
+  building: 3201110003
+
+# 报警服务
+ibms-alarm:
+  # 推送消息时,是否会开启压缩,true-压缩 false-不压缩
+  compress: false
+  # 需要更改
+  host: 39.102.43.179
+  # 需要更改
+  port: 9998
+
+# IOT程序
+iot:
+  # iot-collect 服务
+  collect:
+    # 是否启用collect服务的netty客户端,true-启用
+    enable: true
+    # iot-collect 服务的ip
+    host: 39.96.55.242
+    # iot-collect 服务的收数端口,切记不是服务端口
+    port: 9995
+  # iot-project服务
+  project:
+    # 需要更改,修改其中的项目ID和ip、port,其中port为websocket的端口,切记不是服务端口
+    websocket: ws://39.96.55.242:9980/websocket?projectId=3201110003&type=pointset,iot

+ 34 - 26
src/main/resources/application-ZSPj4403050019.yml

@@ -1,28 +1,36 @@
-group:
-  #需要更改
-  code: ZS   #标识哪个接团 比如万达使用WD
-  alarm:
-    #需要更改
-    host: 39.102.43.179 #netty IP39.102.43.179
-    #需要更改
-    port: 9971          #netty 端口8826
-    #需要更改
-terminal: #边缘端IOT采集程序地址
-  alarm: # 拼接后的地址为ws://host:port/suffix
-    #需要更改
-    compress: false    #采用的是压缩方式还是不压缩方式  true-压缩 false-不压缩
-    #需要更改
-    host: 39.102.43.179  #172.17.233.176
-    #需要更改
-    port: 9994 #9984
-    #需要更改
-    suffix: websocket   #websocker后缀
-project:
-  #需要更改
-  iotid: 4403050019 #iot使用项目ID,不包含PJ
-  #需要更改
-  id: Pj4403050019 #项目ID
+config:
+  # 标识哪个接团 比如万达使用WD,需修改
+  group-code: ZS
+  # 项目ID,需修改
+  project-id: Pj4403050019
+  # iot数据汇总所使用的项目ID,切记不包含Pj,需修改
+  building: 4403050019
+
+# 报警服务
+ibms-alarm:
+  # 推送消息时,是否会开启压缩,true-压缩 false-不压缩
+  compress: false
+  # 需要更改
+  host: 39.102.43.179
+  # 需要更改
+  port: 9998
+
+# IOT程序
+iot:
+  # iot-collect 服务
+  collect:
+    # 是否启用collect服务的netty客户端,true-启用
+    enable: true
+    # iot-collect 服务的ip
+    host: 39.96.55.242
+    # iot-collect 服务的收数端口,切记不是服务端口
+    port: 9995
+  # iot-project服务
+  project:
+    # 需要更改,修改其中的项目ID和ip、port,其中port为websocket的端口,切记不是服务端口
+    websocket: ws://39.96.55.242:9980/websocket?projectId=4403050019&type=pointset,iot
+
 spring:
   datasource:
-    #需要更改
-    url: jdbc:mysql://39.102.43.179:9934/alarm-quartz-zs-hg?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false
+    # 需要更改
+    url: jdbc:mysql://39.102.43.179:9934/alarm-quartz-pj4403050019?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false

+ 23 - 0
src/main/resources/return-alarm.json

@@ -0,0 +1,23 @@
+{
+	"alarm-enable": true,
+    "alarm-define": [
+        {
+            "setInfo": {
+                "code": "equipSwitchSet",
+                "meter": "10462",
+                "funcid": 903
+            },
+            "returnInfo": {
+                "code": "runStatus",
+                "meter": "10457",
+                "funcid": 903
+            },
+            "alarmInfo": {
+                "code": "orderFailAlarm",
+                "meter": "QK120901",
+                "funcid": 903
+            },
+            "alarmCondition": "equipSwitchSet != runStatus"
+        }
+    ]
+}

BIN
src/main/resources/uat.client.keystore.jks


BIN
src/main/resources/uat.client.truststore.jks