You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
backend/src/main/java/com/xydl/cac/iec/IecClient.java

204 lines
7.7 KiB
Java

package com.xydl.cac.iec;
import com.beanit.iec61850bean.*;
import com.xydl.cac.entity.IcdIed;
import com.xydl.cac.entity.constants.Constants;
import com.xydl.cac.socket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.util.List;
@Slf4j
public class IecClient implements ClientEventListener {
IcdIed ied;
int[] title;
ClientSap clientSap = new ClientSap();
ClientAssociation clientAssociation = null;
ServerModel serverModel;
public boolean keep = false;
public RealTimeDataService realTimeDataService;
public WebSocketServer webSocketServer;
int retry = 10;
public void connect(IcdIed _ied, String xml) throws Exception {
InputStream in = IOUtils.toInputStream(xml, StandardCharsets.UTF_8);
this.connect(_ied, in);
}
public void connect(IcdIed _ied, InputStream in) throws Exception {
ied = _ied;
title = new int[]{1, 3, 9999, 33};
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]);
title[2] = Integer.parseInt(strs[2]);
title[3] = Integer.parseInt(strs[3]);
} else if (strs.length == 5) {
title = new int[]{1, 3, 9999, 33, 1};
title[0] = Integer.parseInt(strs[0]);
title[1] = Integer.parseInt(strs[1]);
title[2] = Integer.parseInt(strs[2]);
title[3] = Integer.parseInt(strs[3]);
title[4] = Integer.parseInt(strs[4]);
}
}
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);
}
public void disconnect() {
try {
clientAssociation.disconnect();
clientAssociation = null;
} catch (Exception ignore) {
}
}
private void reconnect() throws Exception {
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;
}
public String getValue(String paramindex, String fc) throws Exception {
FcModelNode node = (FcModelNode) serverModel.findModelNode(paramindex, Fc.valueOf(fc));
clientAssociation.getDataValues(node);
if (node instanceof BasicDataAttribute) {
String value = ((BasicDataAttribute) node).getValueString();
return value;
}
return null;
}
public void enableReporting() throws Exception {
if (!CollectionUtils.isEmpty(serverModel.getUrcbs())) {
for (Urcb urcb : serverModel.getUrcbs()) {
clientAssociation.enableReporting(urcb);
}
}
if (!CollectionUtils.isEmpty(serverModel.getBrcbs())) {
for (Brcb brcb : serverModel.getBrcbs()) {
clientAssociation.enableReporting(brcb);
}
}
log.info("61850订阅成功, ied=" + ied.getName() + ", ip=" + ied.getIp() + ", port=" + ied.getPort());
}
public void disableReporting() {
if (!CollectionUtils.isEmpty(serverModel.getUrcbs())) {
try {
for (Urcb urcb : serverModel.getUrcbs()) {
clientAssociation.disableReporting(urcb);
}
} catch (Exception ignore) {
}
}
if (!CollectionUtils.isEmpty(serverModel.getBrcbs())) {
try {
for (Brcb brcb : serverModel.getBrcbs()) {
clientAssociation.disableReporting(brcb);
}
} catch (Exception ignore) {
}
}
log.info("61850停止订阅, ied=" + ied.getName() + ", ip=" + ied.getIp() + ", port=" + ied.getPort());
}
public List<FileInformation> listFile(String path) throws Exception {
List<FileInformation> list = clientAssociation.getFileDirectory(path);
return list;
}
public void getFile(String remotePath, String filename, String localPath, Integer todel) throws Exception {
GetFileAction gfa = new GetFileAction(localPath);
clientAssociation.getFile(remotePath + filename, gfa);
if (todel != null && todel == Constants.TRUE) {
clientAssociation.deleteFile(remotePath + filename);
}
}
@Override
public void newReport(Report report) {
if (report != null) {
RealTimeDataService.processReport(report);
}
}
@Override
public void associationClosed(IOException e) {
if (keep) {
this.disableReporting();
this.disconnect();
log.warn("61850订阅已断开, ied=" + ied.getName() + ", ip=" + ied.getIp() + ", port=" + ied.getPort());
while (retry > 0) {
retry--;
try {
if (retry >= 5) {
Thread.sleep(10 * 1000);
this.reconnect();
} else if (retry == 4) {
log.warn("61850订阅断线重连已失败5次, ied=" + ied.getName() + ", ip=" + ied.getIp() + ", port=" + ied.getPort());
Thread.sleep(60 * 1000);
this.reconnect();
} else if (retry >= 1) {
Thread.sleep(60 * 1000);
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) {
}
}
}
}
public static void main(String[] args) {
IecClient iecClient = new IecClient();
try {
IcdIed ied = IcdIed.builder()
.ip("192.168.1.17")
.port(102)
.apTitle("1 3 9999 33")
.build();
iecClient.connect(ied, new FileInputStream("C:/资料/om.SCD"));
String str = iecClient.getValue("OMDLMONT/SPDC1.MaxDsch.mag.f", "MX");
System.out.println(str);
str = iecClient.getValue("OMDLMONT/SPDC1.MaxDsch.t", "MX");
System.out.println(str);
List<FileInformation> list = iecClient.listFile("/fdata");
iecClient.getFile("/fdata/web/comtrade/1/18/6/", "20241021_113736_703_0_0.dat", "/eqmid/20241021_113736_703_0_0.dat", 1);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
iecClient.disconnect();
}
}
}