Sfoglia il codice sorgente

继电器掉线监控通知

linfutong 3 anni fa
parent
commit
0d304902e2

+ 27 - 0
zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/feign/RemoteLabHardwareService.java

@@ -0,0 +1,27 @@
+package com.zd.laboratory.api.feign;
+
+import com.zd.laboratory.api.feign.fallback.RemoteSubQueryFallbackFactory;
+import com.zd.model.constant.ApplicationConstants;
+import com.zd.model.domain.ResultData;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * <p>类注释说明</p>
+ *
+ * @author linft
+ * @version 1.0
+ * @date 1/10/2023
+ */
+@FeignClient(contextId = "remoteLabHardwareService", value = ApplicationConstants.LABORATORY_SERVICE, fallbackFactory = RemoteSubQueryFallbackFactory.class)
+public interface RemoteLabHardwareService {
+
+    @ApiOperation(value = "硬件信息状态统计")
+    @GetMapping("/remote/hardware/statistics")
+    ResultData statistics();
+
+    @ApiOperation(value = "离线设备列表")
+    @GetMapping("/remote/hardware/list")
+    ResultData list(@RequestParam("type") String type, @RequestParam("operate") String operate);
+}

+ 33 - 0
zd-api/zd-laboratory-api/src/main/java/com/zd/laboratory/api/feign/fallback/RemoteLabHardwareFallbackFactory.java

@@ -0,0 +1,33 @@
+package com.zd.laboratory.api.feign.fallback;
+
+import com.zd.laboratory.api.feign.RemoteLabHardwareService;
+import com.zd.model.domain.ResultData;
+import org.springframework.cloud.openfeign.FallbackFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * <p>类注释说明</p>
+ *
+ * @author linft
+ * @version 1.0
+ * @date 1/10/2023
+ */
+@Component
+public class RemoteLabHardwareFallbackFactory implements FallbackFactory<RemoteLabHardwareService> {
+
+    @Override
+    public RemoteLabHardwareService create(Throwable cause) {
+        return new RemoteLabHardwareService() {
+
+            @Override
+            public ResultData statistics() {
+                return ResultData.fail("请求失败!");
+            }
+
+            @Override
+            public ResultData list(String type, String operate) {
+                return ResultData.fail("请求失败!");
+            }
+        };
+    }
+}

+ 146 - 0
zd-common/common-core/src/main/java/com/zd/common/core/utils/HttpUtils.java

@@ -0,0 +1,146 @@
+package com.zd.common.core.utils;
+
+import org.apache.commons.codec.binary.Hex;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.MessageDigest;
+import java.util.Map;
+
+/**
+* <p>Http工具类</p>
+* 
+* @author lft  
+* @date 2018年8月28日
+* @since jdk1.8
+* @version 1.0
+ */
+public class HttpUtils {
+
+	private final static int CONNECT_TIMEOUT = 5000;
+    private final static String DEFAULT_ENCODING = "UTF-8";
+
+    /**
+     * 发送POST请求
+     * 
+     * @param urlStr
+     * @param data
+     * @param contentType
+     * @return
+     */
+    public static String sendPost(String urlStr, String data, String contentType, Map<String, String> headers){
+    	if(null == contentType || "".equals(contentType)){
+    		contentType = "application/x-www-form-urlencoded;charset=UTF-8";
+    	}
+        BufferedReader reader = null;
+        StringBuilder sbui = new StringBuilder();
+        try {
+            URL url = new URL(urlStr);
+            URLConnection conn = url.openConnection();
+            conn.setDoOutput(true);
+            conn.setConnectTimeout(CONNECT_TIMEOUT);
+            conn.setReadTimeout(CONNECT_TIMEOUT);
+            conn.setRequestProperty("User-Agent", "Linux; U");
+            conn.setRequestProperty("content-type", contentType);
+            conn.setRequestProperty("timestamp", String.valueOf(System.currentTimeMillis()));
+            //添加请求头
+            if (headers != null) {
+                for (Map.Entry<String, String> entry : headers.entrySet()) {
+                    conn.setRequestProperty(entry.getKey(),entry.getValue());
+                }
+            }
+            OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
+            if(data == null)
+                data = "";
+            writer.write(data);
+            writer.flush();
+            writer.close();
+            reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
+            String line = null;
+            while ((line = reader.readLine()) != null) {
+            	sbui.append(line);
+            	sbui.append("\r\n");
+            }
+        } catch (IOException e) {
+            //System.out.println("Error connecting to " + urlStr + ": " + e.getMessage());
+        } finally {
+            try {
+                if (reader != null)
+                    reader.close();
+            } catch (IOException e) {
+            }
+        }
+        return sbui.toString();
+    }
+    /**
+     * 发起Get请确认
+     * 
+     * @param url
+     * @return
+     */
+    public static String sendGet(String url){
+    	return sendGet(url, null);
+    }
+    
+    public static String sendGet(String url,Integer timeOut){
+ 		String result="";//访问返回结果
+ 		BufferedReader read=null;//读取访问结果
+ 		 try {
+ 		    //创建url
+ 		    URL realurl=new URL(url);
+ 		    //打开连接
+ 		    URLConnection connection=realurl.openConnection();
+ 		    if(timeOut != null) {
+ 		    	connection.setConnectTimeout(timeOut);
+ 		    	connection.setReadTimeout(timeOut);
+ 		    }
+ 		     // 设置通用的请求属性
+ 	         connection.setRequestProperty("accept", "*/*");
+ 	         connection.setRequestProperty("connection", "Keep-Alive");
+ 			connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+ 	         //建立连接
+ 	         connection.connect();
+ 	         // 获取所有响应头字段
+ 	         //Map<String, List<String>> map = connection.getHeaderFields();
+ 			read = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
+ 	         String line;//循环读取
+ 	         while ((line = read.readLine()) != null) {
+ 	             result += line;
+ 	         }
+ 		   } catch (Exception e) {
+ 		    e.printStackTrace();
+ 		   }finally{
+ 		    if(read!=null){//关闭流
+ 		     try {
+ 		      read.close();
+ 		     } catch (Exception e) {
+ 		      e.printStackTrace();
+ 		     }
+ 		    }
+ 		   }
+ 		   return result;
+ 	}
+    
+    /**
+	 * SHA1 哈希计算
+	 */
+	public static String hexSHA1(String value) {
+        try {
+            MessageDigest md = MessageDigest.getInstance("SHA-1");
+            md.update(value.getBytes("utf-8"));
+            byte[] digest = md.digest();
+            return byteToHexString(digest);
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+    
+    public static String byteToHexString(byte[] bytes) {
+        return String.valueOf(Hex.encodeHex(bytes));
+    }
+}

+ 1 - 1
zd-modules/zd-algorithm/src/main/java/com/zd/alg/forward/serivce/FireImageService.java

@@ -120,7 +120,7 @@ public class FireImageService {
         ImgPostResponse<DataPostAnalysisRespDto> send = HttpUtils.send(restTemplate, files, algorithmYml);
         if (send == null || send.getStatus_code() != SUCCESS_CODE) {
             assert send != null;
-            log.error(send.getMessage());
+            //log.error(send.getMessage());
             return;
         }
         DataPostAnalysisRespDto data = send.getData();

+ 16 - 7
zd-modules/zd-algorithm/src/main/java/com/zd/alg/forward/utils/HttpUtils.java

@@ -16,6 +16,8 @@ import org.springframework.web.multipart.MultipartFile;
 
 import java.io.File;
 import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
 
@@ -110,14 +112,21 @@ public class HttpUtils {
     public static ImgPostResponse<DataPostAnalysisRespDto> send(RestTemplate restTemplate, HttpEntity<MultiValueMap<String, Object>> files, AlgorithmYml algorithmYml) {
         ParameterizedTypeReference<ImgPostResponse<DataPostAnalysisRespDto>> reference = new ParameterizedTypeReference<ImgPostResponse<DataPostAnalysisRespDto>>() {
         };
-        ResponseEntity<ImgPostResponse<DataPostAnalysisRespDto>> response = restTemplate.exchange(algorithmYml.getImgPostUrl(), HttpMethod.POST, files, reference);
-        if (response.getStatusCode() != HttpStatus.OK) {
-            log.error("算法服务请求异常,请查看算服务器");
-        }
-        if (response.getBody() == null) {
-            log.error("算法服务接口返回异常");
+        String url = algorithmYml.getImgPostUrl();
+        try {
+            ResponseEntity<ImgPostResponse<DataPostAnalysisRespDto>> response = restTemplate.exchange(url, HttpMethod.POST, files, reference);
+            if (response.getStatusCode() != HttpStatus.OK) {
+                log.error("算法服务请求异常,请查看算服务器");
+            }
+            if (response.getBody() == null) {
+                log.error("算法服务接口返回异常");
+            }
+            return response.getBody();
+        } catch (Exception e) {
+            //e.printStackTrace();
+            log.error("forward算法服务接口请求异常:"+url+", 异常原因"+e.getMessage());
         }
-        return response.getBody();
+        return null;
     }
 
     public static ImgPostResponse<AnalysisReturnData> sendV5(RestTemplate restTemplate, HttpEntity<MultiValueMap<String, Object>> files, AlgorithmYml algorithmYml) {

+ 114 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/monitor/HardwareDeviceMonitor.java

@@ -0,0 +1,114 @@
+package com.zd.alg.monitor;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.zd.common.core.redis.RedisService;
+import com.zd.common.core.utils.HttpUtils;
+import com.zd.common.core.utils.StringUtils;
+import com.zd.laboratory.api.feign.RemoteLabHardwareService;
+import com.zd.model.constant.HttpStatus;
+import com.zd.model.domain.ResultData;
+import io.swagger.models.auth.In;
+import lombok.extern.slf4j.Slf4j;
+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 org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * <p>硬件设备监听</p>
+ *
+ * @author linft
+ * @version 1.0
+ * @date 1/10/2023
+ */
+@Component
+@Slf4j
+public class HardwareDeviceMonitor {
+
+    @Value("${monitor.alert.dingTalkNotice}")
+    private Boolean dingTalkNotice;
+
+    @Value("${monitor.alert.dingTalkSubject}")
+    private String dingTalkSubject;
+
+    @Value("${monitor.alert.dingTalkUrl}")
+    private String dingTalkUrl;
+
+    private String redisPrefix = "HARDWARE_DEVICE_MONITOR:";
+
+    private long expire = 30L;
+
+    @Autowired
+    private RedisService redisService;
+
+    @Autowired
+    private RemoteLabHardwareService remoteLabHardwareService;
+
+    @Scheduled(cron = "0 */9 * * * ?")
+    public void checkPowerUse() {
+        if (dingTalkNotice != null && dingTalkNotice && StringUtils.isNotEmpty(dingTalkUrl)) {
+            log.info("【设备监听提醒】 开始执行检查..............");
+            ResultData result = remoteLabHardwareService.statistics();
+            if (result != null && result.getCode() == HttpStatus.SUCCESS && result.getData() != null) {
+                String jsonStr = JSONObject.toJSONString(result.getData());
+                JSONObject json = JSONObject.parseObject(jsonStr);
+                Integer offline = json.getInteger("powerSupplyOffline");
+                log.info("【设备监听提醒】 异常设备掉线数量:" + offline);
+                if (offline != null && offline > 0) {
+                    //获取离线列表
+                    ResultData data = remoteLabHardwareService.list("SWITCH", "OFFLINE");
+                    //log.info("【设备监听提醒】 获取异常列表:"+JSONObject.toJSONString(data));
+                    if (data != null && data.getCode() == HttpStatus.SUCCESS && data.getData() != null) {
+                        //log.info("【设备监听提醒】 异常设备列表信息:" + data.getData());
+                        String listStr = JSONObject.toJSONString(data.getData());
+                        List<Map<String, Object>> list = JSONObject.parseObject(listStr, List.class);
+                        if (list != null && list.size() > 0) {
+                            Map<String, String> map = new HashMap<>();
+                            for (Map m : list) {
+                                String code = (String) m.get("relayCode");
+                                if (!map.containsKey(code)) {
+                                    map.put(code, "---信息[名称" + m.get("name") + ",所在学院:" + m.get("deptName") + ",所在实验室:" + m.get("subjectName") + "]\n");
+                                }
+                            }
+                            //封装消息
+                            if (!map.isEmpty()) {
+                                Set<String> code = map.keySet();
+                                StringBuffer buffer = new StringBuffer();
+                                buffer.append("【"+dingTalkSubject+"-设备掉线提醒】离线继电器信息:\n");
+                                boolean isSend = Boolean.FALSE;
+                                for (String key : code) {
+                                    Integer num = redisService.getCacheObject(redisPrefix+key);
+                                    if (num != null && num > 2) {
+                                        buffer.append("继电器[" + key + "] " + map.get(key));
+                                        redisService.deleteObject(redisPrefix+key);
+                                        isSend = Boolean.TRUE;
+                                    } else {
+                                        int value = num == null ? 1:num+1;
+                                        redisService.setCacheObject(redisPrefix+key, value, expire, TimeUnit.MINUTES);
+                                    }
+                                }
+                                //通知
+                                if (isSend) {
+                                    String msg = "{\"msgtype\": \"text\",\"text\": {\"content\":\"" + buffer.toString() + "\"}}";
+                                    String rs = HttpUtils.sendPost(dingTalkUrl, msg, "application/json", null);
+                                    //log.info("【设备监听提醒】 钉钉通知响应:" + rs);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 49 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/controller/device/HardwareRemoteController.java

@@ -0,0 +1,49 @@
+package com.zd.laboratory.controller.device;
+
+import com.zd.common.core.annotation.PreAuthorize;
+import com.zd.laboratory.domain.LabHardware;
+import com.zd.laboratory.domain.vo.LabHardwareVO;
+import com.zd.laboratory.service.ILabHardwareService;
+import com.zd.model.domain.AjaxResult;
+import com.zd.model.domain.R;
+import com.zd.model.domain.ResultData;
+import com.zd.model.domain.per.PerFun;
+import com.zd.model.domain.per.PerPrefix;
+import com.zd.model.page.TableDataInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>类注释说明</p>
+ *
+ * @author linft
+ * @version 1.0
+ * @date 1/10/2023
+ */
+@RestController
+@RequestMapping("/remote/hardware")
+public class HardwareRemoteController {
+
+    @Autowired
+    private ILabHardwareService labHardwareService;
+
+    @GetMapping("/statistics")
+    public ResultData statistics() {
+        Map<String, Object> map = labHardwareService.selectStatistics(new LabHardware());
+        return ResultData.success(map);
+    }
+
+    /**
+     * 查询设备列表
+     */
+    @GetMapping("/list")
+    public ResultData list(LabHardware labHardware) {
+        List<LabHardwareVO> list = labHardwareService.selectLabHardwareList(labHardware);
+        return ResultData.success(list);
+    }
+}