diff --git a/db/upgrade1210.sql b/db/upgrade1210.sql new file mode 100644 index 0000000..9c613ee --- /dev/null +++ b/db/upgrade1210.sql @@ -0,0 +1 @@ +ALTER TABLE `warn_rule` ADD COLUMN `notify_com` INT(11) NULL DEFAULT NULL COMMENT '0:不通知; 1:通知' AFTER `active`; diff --git a/src/main/java/com/xydl/cac/controller/IcdConfigController.java b/src/main/java/com/xydl/cac/controller/IcdConfigController.java index 5946c4b..9714c6f 100644 --- a/src/main/java/com/xydl/cac/controller/IcdConfigController.java +++ b/src/main/java/com/xydl/cac/controller/IcdConfigController.java @@ -10,6 +10,7 @@ import com.xydl.cac.iec.RealTimeDataService; import com.xydl.cac.model.ColumnModel; import com.xydl.cac.model.IcdAttUpdateModel; import com.xydl.cac.model.Response; +import com.xydl.cac.repository.IcdIedRepository; import com.xydl.cac.service.DataService; import com.xydl.cac.service.IcdFileConfigService; import io.swagger.annotations.Api; @@ -25,6 +26,7 @@ import javax.annotation.Resource; import javax.validation.constraints.NotNull; import java.nio.charset.Charset; import java.util.List; +import java.util.Optional; @RestController @Api(tags = {"IcdConfig相关接口"}) @@ -38,6 +40,8 @@ public class IcdConfigController extends BasicController { DataService dataService; @Resource RealTimeDataService realTimeDataService; + @Resource + IcdIedRepository iedRepository; @PostMapping("upload") @ApiOperation("上传客户端icd文件") @@ -161,8 +165,22 @@ public class IcdConfigController extends BasicController { if (RealTimeDataService.inDoing) { throw new BusinessException("请稍后再操作"); } - realTimeDataService.startCollect(iedId); - return Response.success("OK"); + Optional optional = iedRepository.findById(iedId); + if (!optional.isPresent()) { + throw new BusinessException("未找到该IED"); + } + IcdIed ied = optional.get(); + try { + realTimeDataService.startCollect(ied); + ied.setStart(Constants.TRUE); + iedRepository.save(ied); + return Response.success("OK"); + } catch (Exception ex) { + realTimeDataService.stopCollect(ied.getId()); + ied.setStart(Constants.FALSE); + iedRepository.save(ied); + return Response.fail(ex.getMessage()); + } } @PostMapping("stopCollect") @@ -174,7 +192,14 @@ public class IcdConfigController extends BasicController { if (RealTimeDataService.inDoing) { throw new BusinessException("请稍后再操作"); } - realTimeDataService.stopCollect(iedId); + Optional optional = iedRepository.findById(iedId); + if (!optional.isPresent()) { + throw new BusinessException("未找到该IED"); + } + IcdIed ied = optional.get(); + ied.setStart(Constants.FALSE); + iedRepository.save(ied); + realTimeDataService.stopCollect(ied.getId()); return Response.success("OK"); } diff --git a/src/main/java/com/xydl/cac/entity/IcdIed.java b/src/main/java/com/xydl/cac/entity/IcdIed.java index 818be12..405896e 100644 --- a/src/main/java/com/xydl/cac/entity/IcdIed.java +++ b/src/main/java/com/xydl/cac/entity/IcdIed.java @@ -46,4 +46,11 @@ public class IcdIed { @ApiModelProperty(name = "端口") @Column(name = "port") private Integer port; + + @Transient + private boolean connected; + @Transient + private int retry; + @Transient + private int seconds; } \ No newline at end of file diff --git a/src/main/java/com/xydl/cac/entity/WarnRule.java b/src/main/java/com/xydl/cac/entity/WarnRule.java index 9464296..9bfac57 100644 --- a/src/main/java/com/xydl/cac/entity/WarnRule.java +++ b/src/main/java/com/xydl/cac/entity/WarnRule.java @@ -77,6 +77,10 @@ public class WarnRule { @Column(name = "active") private Integer active; + @ApiModelProperty("状态 0:不通知 1:通知") + @Column(name = "notify_com") + private Integer notifyCom; + @ApiModelProperty("最后数据采集时间") @Column(name = "last_d_time") private Date lastDTime; diff --git a/src/main/java/com/xydl/cac/iec/IEDCollectService.java b/src/main/java/com/xydl/cac/iec/IEDCollectService.java index c8beed9..7f360f5 100644 --- a/src/main/java/com/xydl/cac/iec/IEDCollectService.java +++ b/src/main/java/com/xydl/cac/iec/IEDCollectService.java @@ -15,6 +15,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.util.CollectionUtils; +import java.net.SocketException; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -55,7 +56,8 @@ public class IEDCollectService { } public void connect() throws Exception { - iecClient.connect(ied, xml); + iecClient.init(ied, xml); + iecClient.connect(); } public void disconnect() { @@ -87,7 +89,11 @@ public class IEDCollectService { StaticVariable.doneWarnMap.put(key, "1"); _webSocketServer.sendMessage(err, null); } - RealTimeDataService.onErrorCheck(ied.getId()); + if (ex instanceof SocketException) { + NetErrorThread thread = new NetErrorThread(); + thread.iedId = ied.getId(); + thread.run(); + } } finally { iecClient.disconnect(); } diff --git a/src/main/java/com/xydl/cac/iec/IecClient.java b/src/main/java/com/xydl/cac/iec/IecClient.java index bb76c7a..d87fbb0 100644 --- a/src/main/java/com/xydl/cac/iec/IecClient.java +++ b/src/main/java/com/xydl/cac/iec/IecClient.java @@ -29,9 +29,12 @@ public class IecClient implements ClientEventListener { ServerModel serverModel; public boolean keep = false; + public boolean connected = false; private RealTimeDataService realTimeDataService; private WebSocketServer webSocketServer; - public int retry = 10; + public int retry = 0; + public int seconds = 0; + private boolean inRetry = false; public Date lastReportTime; public IecClient() { @@ -42,16 +45,20 @@ public class IecClient implements ClientEventListener { webSocketServer = _webSocketServer; } - public void connect(IcdIed _ied, String xml) throws Exception { + public void init(IcdIed _ied, String xml) throws Exception { InputStream in = IOUtils.toInputStream(xml, StandardCharsets.UTF_8); - this.connect(_ied, in); + this.init(_ied, in); } - public void connect(IcdIed _ied, InputStream in) throws Exception { + public void init(IcdIed _ied, InputStream in) throws Exception { ied = _ied; + serverModel = SclParser.parse(in).get(0); + } + + public void connect() throws Exception { title = new int[]{1, 3, 9999, 33}; - if (StringUtils.isNotBlank(_ied.getApTitle())) { - String[] strs = _ied.getApTitle().replaceAll(" ", ",").split(","); + if (StringUtils.isNotBlank(ied.getApTitle())) { + String[] strs = ied.getApTitle().replaceAll(" ", ",").split(","); if (strs.length == 4) { title[0] = Integer.parseInt(strs[0]); title[1] = Integer.parseInt(strs[1]); @@ -69,14 +76,15 @@ public class IecClient implements ClientEventListener { clientSap.setTSelRemote(new byte[]{0, 1}); clientSap.setTSelLocal(new byte[]{0, 0}); clientSap.setApTitleCalled(title); - serverModel = SclParser.parse(in).get(0); clientAssociation = clientSap.associate(InetAddress.getByName(ied.getIp()), ied.getPort(), null, this); clientAssociation.setServerModel(serverModel); + connected = true; } public void disconnect() { try { + connected = false; clientAssociation.disconnect(); clientAssociation = null; } catch (Exception ignore) { @@ -87,11 +95,13 @@ public class IecClient implements ClientEventListener { if (StaticVariable.shutdown == 1) { return; } + retry++; + seconds = 0; clientAssociation = clientSap.associate(InetAddress.getByName(ied.getIp()), ied.getPort(), null, this); clientAssociation.setServerModel(serverModel); log.info("61850订阅断线重连成功, ied=" + ied.getName() + ", ip=" + ied.getIp() + ", port=" + ied.getPort()); - retry = 10; - keep = true; + connected = true; + retry = 0; } public String getValue(String paramindex, String fc) throws Exception { @@ -126,7 +136,6 @@ public class IecClient implements ClientEventListener { } } log.info("61850订阅成功, ied=" + ied.getName() + ", ip=" + ied.getIp() + ", port=" + ied.getPort()); - keep = true; } public void disableReporting() { @@ -151,7 +160,6 @@ public class IecClient implements ClientEventListener { } else { log.info("61850停止订阅, ied=" + ied.getName() + ", ip=" + ied.getIp() + ", port=" + ied.getPort()); } - keep = false; } public List listFile(String path) throws Exception { @@ -177,36 +185,31 @@ public class IecClient implements ClientEventListener { @Override public void associationClosed(IOException e) { - if (keep) { + if (keep && !inRetry) { + inRetry = true; + retry = 0; + seconds = 0; this.disableReporting(); this.disconnect(); - while (retry > 0 && StaticVariable.shutdown == 0) { - retry--; + while (!connected && StaticVariable.shutdown == 0) { try { - if (retry >= 5) { - StaticVariable.wait(10); - this.reconnect(); - } else if (retry == 4) { - log.warn("61850订阅断线重连已失败5次, ied=" + ied.getName() + ", ip=" + ied.getIp() + ", port=" + ied.getPort()); - StaticVariable.wait(60); + Thread.sleep(1000); + seconds++; + if (retry < 10 && seconds > 60) { this.reconnect(); - } else if (retry >= 1) { - StaticVariable.wait(60); + } else if (seconds > 60 * 60) { this.reconnect(); - } else { - String err = "61850订阅断线重连已失败多次不再重连. ied=" + ied.getName() + ", ip=" + ied.getIp() + ", port=" + ied.getPort(); - log.warn(err); - if (realTimeDataService != null && ied != null) { - realTimeDataService.stopCollect(ied.getId()); - } - if (webSocketServer != null) { - webSocketServer.sendMessage(err, null); - } } - break; } catch (Exception ignore) { + String err = "61850订阅断线重连失败" + retry + "次, ied=" + + ied.getName() + ", ip=" + ied.getIp() + ", port=" + ied.getPort(); + log.warn(err); + if (webSocketServer != null && retry >= 10) { + webSocketServer.sendMessage(err, null); + } } } + inRetry = false; } } @@ -218,7 +221,8 @@ public class IecClient implements ClientEventListener { .port(102) .apTitle("1 3 9999 33") .build(); - iecClient.connect(ied, new FileInputStream("C:/资料/om.SCD")); + iecClient.init(ied, new FileInputStream("C:/资料/om.SCD")); + iecClient.connect(); String str = iecClient.getValue("OMDLMONT/SPDC1.MaxDsch.mag.f", "MX"); System.out.println(str); str = iecClient.getValue("OMDLMONT/SPDC1.MaxDsch.t", "MX"); diff --git a/src/main/java/com/xydl/cac/iec/IecServerService.java b/src/main/java/com/xydl/cac/iec/IecServerService.java index 9a38960..38cc22b 100644 --- a/src/main/java/com/xydl/cac/iec/IecServerService.java +++ b/src/main/java/com/xydl/cac/iec/IecServerService.java @@ -83,6 +83,7 @@ public class IecServerService { @PreDestroy private void stop() { + StaticVariable.shutdown = 1; Iterator it = StaticVariable.iecServerMap.keySet().iterator(); while (it.hasNext()) { Integer key = it.next(); diff --git a/src/main/java/com/xydl/cac/iec/NetErrorThread.java b/src/main/java/com/xydl/cac/iec/NetErrorThread.java new file mode 100644 index 0000000..de210c4 --- /dev/null +++ b/src/main/java/com/xydl/cac/iec/NetErrorThread.java @@ -0,0 +1,15 @@ +package com.xydl.cac.iec; + +import com.xydl.cac.model.StaticVariable; + +public class NetErrorThread extends Thread { + public int iedId; + + @Override + public void run() { + IecClient iecClient = StaticVariable.realTimeClientMap.get(iedId); + if (iecClient != null) { + iecClient.associationClosed(null); + } + } +} diff --git a/src/main/java/com/xydl/cac/iec/RealTimeDataService.java b/src/main/java/com/xydl/cac/iec/RealTimeDataService.java index f12f63c..8216e96 100644 --- a/src/main/java/com/xydl/cac/iec/RealTimeDataService.java +++ b/src/main/java/com/xydl/cac/iec/RealTimeDataService.java @@ -36,36 +36,30 @@ public class RealTimeDataService { if (!CollectionUtils.isEmpty(list)) { for (IcdIed ied : list) { try { - this.startCollect(ied.getId()); + this.startCollect(ied); } catch (Exception ignore) { } } } } - public void startCollect(Integer iedId) throws BusinessException { - Optional optional = iedRepository.findById(iedId); - if (!optional.isPresent()) { - throw new BusinessException("未找到该IED"); - } - IcdIed ied = optional.get(); + public void startCollect(IcdIed ied) throws BusinessException { Optional optionalFile = fileRepository.findById(ied.getIcdFileId()); if (!optionalFile.isPresent()) { throw new BusinessException("未找到该icd文件"); } inDoing = true; IcdFile icdFile = optionalFile.get(); + IecClient iecClient = new IecClient(this, webSocketServer); try { - IecClient iecClient = new IecClient(this, webSocketServer); - iecClient.connect(ied, icdFile.getXml()); - iecClient.enableReporting(); - ied.setStart(Constants.TRUE); - iedRepository.save(ied); + iecClient.init(ied, icdFile.getXml()); + iecClient.keep = true; StaticVariable.realTimeClientMap.put(ied.getId(), iecClient); + iecClient.connect(); + iecClient.enableReporting(); } catch (Exception ex) { String err = "61850订阅异常, ied=" + ied.getName() + ", ip=" + ied.getIp() + ", port=" + ied.getPort(); log.error(err, ex); - this.stopCollect(iedId); throw new BusinessException(err); } finally { inDoing = false; @@ -73,29 +67,12 @@ public class RealTimeDataService { } public void stopCollect(Integer iedId) { - this.onlyStop(iedId); - Optional optional = iedRepository.findById(iedId); - if (optional.isPresent()) { - IcdIed ied = optional.get(); - ied.setStart(Constants.FALSE); - iedRepository.save(ied); - } - } - - public static void onErrorCheck(Integer iedId) { - IecClient iecClient = StaticVariable.realTimeClientMap.get(iedId); - if (iecClient != null) { - iecClient.associationClosed(null); - } - } - - private void onlyStop(Integer iedId) { IecClient iecClient = StaticVariable.realTimeClientMap.get(iedId); if (iecClient != null) { + StaticVariable.realTimeClientMap.remove(iedId); iecClient.keep = false; iecClient.disableReporting(); iecClient.disconnect(); - StaticVariable.realTimeClientMap.remove(iedId); } } @@ -109,7 +86,7 @@ public class RealTimeDataService { idList.add(it.next()); } for (Integer iedId : idList) { - this.onlyStop(iedId); + this.stopCollect(iedId); } } diff --git a/src/main/java/com/xydl/cac/service/impl/IcdFileConfigServiceImpl.java b/src/main/java/com/xydl/cac/service/impl/IcdFileConfigServiceImpl.java index 1a02435..fd91fe4 100644 --- a/src/main/java/com/xydl/cac/service/impl/IcdFileConfigServiceImpl.java +++ b/src/main/java/com/xydl/cac/service/impl/IcdFileConfigServiceImpl.java @@ -3,7 +3,9 @@ package com.xydl.cac.service.impl; import com.xydl.cac.entity.*; import com.xydl.cac.entity.constants.Constants; import com.xydl.cac.exception.BusinessException; +import com.xydl.cac.iec.IecClient; import com.xydl.cac.model.IcdAttUpdateModel; +import com.xydl.cac.model.StaticVariable; import com.xydl.cac.repository.*; import com.xydl.cac.service.DataService; import com.xydl.cac.service.IcdFileConfigService; @@ -40,6 +42,8 @@ public class IcdFileConfigServiceImpl implements IcdFileConfigService { RptparamindexRepository rptparamindexRepository; @Resource DataService dataService; + @Resource + IedDlConfigRepository iedDlConfigRepository; @Override public void upload(String xml, String filename, int srv) throws Exception { @@ -108,6 +112,15 @@ public class IcdFileConfigServiceImpl implements IcdFileConfigService { List iedList = iedRepository.findByIcdFileId(icdFile.getId()); for (IcdIed ied : iedList) { if (StringUtils.isNotBlank(ied.getIp())) { + ied.setConnected(false); + ied.setRetry(0); + ied.setSeconds(0); + IecClient iecClient = StaticVariable.realTimeClientMap.get(ied.getId()); + if (iecClient != null) { + ied.setRetry(iecClient.retry); + ied.setConnected(iecClient.connected); + ied.setSeconds(iecClient.seconds); + } result.add(ied); } } @@ -220,6 +233,7 @@ public class IcdFileConfigServiceImpl implements IcdFileConfigService { configRepository.deleteAll(); fileRepository.deleteAll(); iedRepository.deleteAll(); + iedDlConfigRepository.deleteAll(); } @Override diff --git a/src/main/java/com/xydl/cac/service/impl/IedDlConfigServiceImpl.java b/src/main/java/com/xydl/cac/service/impl/IedDlConfigServiceImpl.java index 0a80e7e..4e4c367 100644 --- a/src/main/java/com/xydl/cac/service/impl/IedDlConfigServiceImpl.java +++ b/src/main/java/com/xydl/cac/service/impl/IedDlConfigServiceImpl.java @@ -100,7 +100,8 @@ public class IedDlConfigServiceImpl implements IedDlConfigService { IcdFile icdFile = optionalFile.get(); IecClient iecClient = new IecClient(); try { - iecClient.connect(ied, icdFile.getXml()); + iecClient.init(ied, icdFile.getXml()); + iecClient.connect(); return iecClient.listFile(path); } catch (Exception ex) { throw new BusinessException(ex.getMessage()); diff --git a/src/main/java/com/xydl/cac/service/impl/WarnRuleServiceImpl.java b/src/main/java/com/xydl/cac/service/impl/WarnRuleServiceImpl.java index dd00896..acdeec2 100644 --- a/src/main/java/com/xydl/cac/service/impl/WarnRuleServiceImpl.java +++ b/src/main/java/com/xydl/cac/service/impl/WarnRuleServiceImpl.java @@ -86,6 +86,7 @@ public class WarnRuleServiceImpl implements WarnRuleService { rule.setThreshold(item.getThreshold()); rule.setLevel(item.getLevel()); rule.setActive(item.getActive()); + rule.setNotifyCom(item.getNotifyCom()); repository.save(rule); StaticVariable.rule_Cache.remove(rule.getId()); } diff --git a/src/main/java/com/xydl/cac/task/RuleCheckTask.java b/src/main/java/com/xydl/cac/task/RuleCheckTask.java index d7a7b5d..c12159b 100644 --- a/src/main/java/com/xydl/cac/task/RuleCheckTask.java +++ b/src/main/java/com/xydl/cac/task/RuleCheckTask.java @@ -4,6 +4,7 @@ import com.xydl.cac.entity.ModevTypePoint; import com.xydl.cac.entity.NSensor; import com.xydl.cac.entity.WarnRule; import com.xydl.cac.entity.Warning; +import com.xydl.cac.entity.constants.Constants; import com.xydl.cac.model.StaticVariable; import com.xydl.cac.model.TriggerModel; import com.xydl.cac.repository.WarnRuleRepository; @@ -73,6 +74,10 @@ public class RuleCheckTask { for (TriggerModel model : warnList) { this.sendWarning(rule, model); } + if (rule.getNotifyCom() != null && rule.getNotifyCom().intValue() == Constants.TRUE) { + // 通知串口 + + } } } catch (Exception e) { log.error("RuleCheckTask.ruleCheck error.", e); diff --git a/src/main/java/com/xydl/cac/util/DateUtil.java b/src/main/java/com/xydl/cac/util/DateUtil.java index f5c5d44..9825e48 100644 --- a/src/main/java/com/xydl/cac/util/DateUtil.java +++ b/src/main/java/com/xydl/cac/util/DateUtil.java @@ -113,7 +113,6 @@ public class DateUtil { time = format(date); LocalDateTime localtime = LocalDateTime.parse(time, defaultFormatter); if (localtime.getYear() < 2000) { - log.warn("该时间小于2000年: " + str); return null; } ZonedDateTime zonedDateTime = localtime.atZone(ZoneOffset.UTC);