diff --git a/src/main/java/com/beanit/iec61850bean/BdaTimestamp.java b/src/main/java/com/beanit/iec61850bean/BdaTimestamp.java
index 3e328e9..6ec5d0b 100644
--- a/src/main/java/com/beanit/iec61850bean/BdaTimestamp.java
+++ b/src/main/java/com/beanit/iec61850bean/BdaTimestamp.java
@@ -17,226 +17,266 @@
import com.beanit.iec61850bean.internal.mms.asn1.Data;
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
import com.beanit.iec61850bean.internal.mms.asn1.UtcTime;
+
import java.time.Instant;
import java.util.Date;
public final class BdaTimestamp extends BasicDataAttribute {
- private volatile byte[] value;
-
- public BdaTimestamp(
- ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
- super(objectReference, fc, sAddr, dchg, dupd);
- basicType = BdaType.TIMESTAMP;
- setDefault();
- }
-
- /**
- * The SecondSinceEpoch shall be the interval in seconds continuously counted from the epoch
- * 1970-01-01 00:00:00 UTC
- */
-
- /**
- * Returns the value as the number of seconds since epoch 1970-01-01 00:00:00 UTC
- *
- * @return the number of seconds since epoch 1970-01-01 00:00:00 UTC
- */
- private long getSecondsSinceEpoch() {
- return ((0xffL & value[0]) << 24
- | (0xffL & value[1]) << 16
- | (0xffL & value[2]) << 8
- | (0xffL & value[3]));
- }
-
- /**
- * The attribute FractionOfSecond shall be the fraction of the current second when the value of
- * the TimeStamp has been determined. The fraction of second shall be calculated as
- * (SUM from I = 0 to 23 of bi*2**–(I+1) s).
NOTE 1 The resolution is the smallest unit by
- * which the time stamp is updated. The 24 bits of the integer provides 1 out of 16777216 counts
- * as the smallest unit; calculated by 1/2**24 which equals approximately 60 ns.
- *
- *
NOTE 2 The resolution of a time stamp may be 1/2**1 (= 0,5 s) if only the first bit is used;
- * or may be 1/2**2 (= 0,25 s) if the first two bits are used; or may be approximately 60 ns if
- * all 24 bits are used. The resolution provided by an IED is outside the scope of this standard.
- *
- * @return the fraction of seconds
- */
- private int getFractionOfSecond() {
- return ((0xff & value[4]) << 16 | (0xff & value[5]) << 8 | (0xff & value[6]));
- }
-
- @Override
- public void setValueFrom(BasicDataAttribute bda) {
- byte[] srcValue = ((BdaTimestamp) bda).getValue();
- if (value.length != srcValue.length) {
- value = new byte[srcValue.length];
- }
- System.arraycopy(srcValue, 0, value, 0, srcValue.length);
- }
-
- public Instant getInstant() {
- if (value == null || value.length == 0) {
- return null;
- }
- long time =
- getSecondsSinceEpoch() * 1000L
- + (long) (((float) getFractionOfSecond()) / (1 << 24) * 1000 + 0.5);
- return Instant.ofEpochMilli(time);
- }
-
- public void setInstant(Instant instant) {
- setInstant(instant, true, false, false, 10);
- }
-
- public void setInstant(
- Instant instant,
- boolean leapSecondsKnown,
- boolean clockFailure,
- boolean clockNotSynchronized,
- int timeAccuracy) {
- if (value == null) {
- value = new byte[8];
- }
-
- int secondsSinceEpoch = (int) (instant.toEpochMilli() / 1000L);
- int fractionOfSecond = (int) ((instant.toEpochMilli() % 1000L) / 1000.0 * (1 << 24));
-
- int timeQuality = timeAccuracy & 0x1f;
- if (leapSecondsKnown) {
- timeQuality = timeQuality | 0x80;
- }
- if (clockFailure) {
- timeQuality = timeQuality | 0x40;
- }
- if (clockNotSynchronized) {
- timeQuality = timeQuality | 0x20;
- }
-
- value =
- new byte[] {
- (byte) ((secondsSinceEpoch >> 24) & 0xff),
- (byte) ((secondsSinceEpoch >> 16) & 0xff),
- (byte) ((secondsSinceEpoch >> 8) & 0xff),
- (byte) (secondsSinceEpoch & 0xff),
- (byte) ((fractionOfSecond >> 16) & 0xff),
- (byte) ((fractionOfSecond >> 8) & 0xff),
- (byte) (fractionOfSecond & 0xff),
- (byte) timeQuality
- };
- }
-
- public byte[] getValue() {
- return value;
- }
-
- public void setValue(byte[] value) {
- if (value == null) {
- this.value = new byte[8];
- }
- this.value = value;
- }
-
- /**
- * The value TRUE of the attribute LeapSecondsKnown shall indicate that the value for
- * SecondSinceEpoch takes into account all leap seconds occurred. If it is FALSE then the value
- * does not take into account the leap seconds that occurred before the initialization of the time
- * source of the device.
- *
- * @return TRUE of the attribute LeapSecondsKnown shall indicate that the value for
- * SecondSinceEpoch takes into account all leap seconds occurred
- */
- public boolean getLeapSecondsKnown() {
- return ((value[7] & 0x80) != 0);
- }
-
- /**
- * The attribute clockFailure shall indicate that the time source of the sending device is
- * unreliable. The value of the TimeStamp shall be ignored.
- *
- * @return true if the time source of the sending device is unreliable
- */
- public boolean getClockFailure() {
- return ((value[7] & 0x40) != 0);
- }
-
- /**
- * The attribute clockNotSynchronized shall indicate that the time source of the sending device is
- * not synchronized with the external UTC time.
- *
- * @return true if the time source of the sending device is not synchronized
- */
- public boolean getClockNotSynchronized() {
- return ((value[7] & 0x20) != 0);
- }
-
- /**
- * The attribute TimeAccuracy shall represent the time accuracy class of the time source of the
- * sending device relative to the external UTC time. The timeAccuracy classes shall represent the
- * number of significant bits in the FractionOfSecond
- *
- *
If the time is set via Java {@link Date} objects, the accuracy is 1 ms, that is a
- * timeAccuracy value of 10.
- *
- * @return the time accuracy
- */
- public int getTimeAccuracy() {
- return ((value[7] & 0x1f));
- }
-
- /** Sets Timestamp the empty byte array (indicating an invalid Timestamp) */
- @Override
- public void setDefault() {
- value = new byte[8];
- }
-
- /** Sets Timestamp to current time */
- public void setCurrentTime() {
- setInstant(Instant.now());
- }
-
- @Override
- public BdaTimestamp copy() {
- BdaTimestamp copy = new BdaTimestamp(objectReference, fc, sAddr, dchg, dupd);
- byte[] valueCopy = new byte[value.length];
- System.arraycopy(value, 0, valueCopy, 0, value.length);
- copy.setValue(valueCopy);
- if (mirror == null) {
- copy.mirror = this;
- } else {
- copy.mirror = mirror;
- }
- return copy;
- }
-
- @Override
- Data getMmsDataObj() {
- Data data = new Data();
- data.setUtcTime(new UtcTime(value));
- return data;
- }
-
- @Override
- void setValueFromMmsDataObj(Data data) throws ServiceError {
- if (data.getUtcTime() == null) {
- throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: utc_time/timestamp");
- }
- value = data.getUtcTime().value;
- }
-
- @Override
- TypeDescription getMmsTypeSpec() {
- TypeDescription typeDescription = new TypeDescription();
- typeDescription.setUtcTime(new BerNull());
- return typeDescription;
- }
-
- @Override
- public String toString() {
- return getReference().toString() + ": " + getInstant();
- }
-
- @Override
- public String getValueString() {
- return getInstant().toString();
- }
+ private volatile byte[] value;
+
+ public BdaTimestamp(
+ ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
+ super(objectReference, fc, sAddr, dchg, dupd);
+ basicType = BdaType.TIMESTAMP;
+ setDefault();
+ }
+
+ /**
+ * The SecondSinceEpoch shall be the interval in seconds continuously counted from the epoch
+ * 1970-01-01 00:00:00 UTC
+ */
+
+ /**
+ * Returns the value as the number of seconds since epoch 1970-01-01 00:00:00 UTC
+ *
+ * @return the number of seconds since epoch 1970-01-01 00:00:00 UTC
+ */
+ private long getSecondsSinceEpoch() {
+ return ((0xffL & value[0]) << 24
+ | (0xffL & value[1]) << 16
+ | (0xffL & value[2]) << 8
+ | (0xffL & value[3]));
+ }
+
+ /**
+ * The attribute FractionOfSecond shall be the fraction of the current second when the value of
+ * the TimeStamp has been determined. The fraction of second shall be calculated as
+ * (SUM from I = 0 to 23 of bi*2**–(I+1) s).
NOTE 1 The resolution is the smallest unit by
+ * which the time stamp is updated. The 24 bits of the integer provides 1 out of 16777216 counts
+ * as the smallest unit; calculated by 1/2**24 which equals approximately 60 ns.
+ *
+ *
NOTE 2 The resolution of a time stamp may be 1/2**1 (= 0,5 s) if only the first bit is used;
+ * or may be 1/2**2 (= 0,25 s) if the first two bits are used; or may be approximately 60 ns if
+ * all 24 bits are used. The resolution provided by an IED is outside the scope of this standard.
+ *
+ * @return the fraction of seconds
+ */
+ private int getFractionOfSecond() {
+ return ((0xff & value[4]) << 16 | (0xff & value[5]) << 8 | (0xff & value[6]));
+ }
+
+ public Date getDate() {
+ if (value == null || value.length == 0) {
+ return null;
+ }
+ long time =
+ getSecondsSinceEpoch() * 1000L
+ + (long) (((float) getFractionOfSecond()) / (1 << 24) * 1000 + 0.5);
+ return new Date(time);
+ }
+
+ public void setDate(Date date) {
+ if (value == null) {
+ value = new byte[8];
+ }
+
+ int secondsSinceEpoch = (int) (date.getTime() / 1000L);
+ int fractionOfSecond = (int) ((date.getTime() % 1000L) / 1000.0 * (1 << 24));
+
+ // 0x8a = time accuracy of 10 and LeapSecondsKnown = true, ClockFailure
+ // = false, ClockNotSynchronized = false
+ value =
+ new byte[] {
+ (byte) ((secondsSinceEpoch >> 24) & 0xff),
+ (byte) ((secondsSinceEpoch >> 16) & 0xff),
+ (byte) ((secondsSinceEpoch >> 8) & 0xff),
+ (byte) (secondsSinceEpoch & 0xff),
+ (byte) ((fractionOfSecond >> 16) & 0xff),
+ (byte) ((fractionOfSecond >> 8) & 0xff),
+ (byte) (fractionOfSecond & 0xff),
+ (byte) 0x8a
+ };
+ }
+
+
+
+ @Override
+ public void setValueFrom(BasicDataAttribute bda) {
+ byte[] srcValue = ((BdaTimestamp) bda).getValue();
+ if (value.length != srcValue.length) {
+ value = new byte[srcValue.length];
+ }
+ System.arraycopy(srcValue, 0, value, 0, srcValue.length);
+ }
+
+ public Instant getInstant() {
+ if (value == null || value.length == 0) {
+ return null;
+ }
+ long time =
+ getSecondsSinceEpoch() * 1000L
+ + (long) (((float) getFractionOfSecond()) / (1 << 24) * 1000 + 0.5);
+ return Instant.ofEpochMilli(time);
+ }
+
+ public void setInstant(Instant instant) {
+ setInstant(instant, true, false, false, 10);
+ }
+
+ public void setInstant(
+ Instant instant,
+ boolean leapSecondsKnown,
+ boolean clockFailure,
+ boolean clockNotSynchronized,
+ int timeAccuracy) {
+ if (value == null) {
+ value = new byte[8];
+ }
+
+ int secondsSinceEpoch = (int) (instant.toEpochMilli() / 1000L);
+ int fractionOfSecond = (int) ((instant.toEpochMilli() % 1000L) / 1000.0 * (1 << 24));
+
+ int timeQuality = timeAccuracy & 0x1f;
+ if (leapSecondsKnown) {
+ timeQuality = timeQuality | 0x80;
+ }
+ if (clockFailure) {
+ timeQuality = timeQuality | 0x40;
+ }
+ if (clockNotSynchronized) {
+ timeQuality = timeQuality | 0x20;
+ }
+
+ value =
+ new byte[]{
+ (byte) ((secondsSinceEpoch >> 24) & 0xff),
+ (byte) ((secondsSinceEpoch >> 16) & 0xff),
+ (byte) ((secondsSinceEpoch >> 8) & 0xff),
+ (byte) (secondsSinceEpoch & 0xff),
+ (byte) ((fractionOfSecond >> 16) & 0xff),
+ (byte) ((fractionOfSecond >> 8) & 0xff),
+ (byte) (fractionOfSecond & 0xff),
+ (byte) timeQuality
+ };
+ }
+
+ public byte[] getValue() {
+ return value;
+ }
+
+ public void setValue(byte[] value) {
+ if (value == null) {
+ this.value = new byte[8];
+ }
+ this.value = value;
+ }
+
+ /**
+ * The value TRUE of the attribute LeapSecondsKnown shall indicate that the value for
+ * SecondSinceEpoch takes into account all leap seconds occurred. If it is FALSE then the value
+ * does not take into account the leap seconds that occurred before the initialization of the time
+ * source of the device.
+ *
+ * @return TRUE of the attribute LeapSecondsKnown shall indicate that the value for
+ * SecondSinceEpoch takes into account all leap seconds occurred
+ */
+ public boolean getLeapSecondsKnown() {
+ return ((value[7] & 0x80) != 0);
+ }
+
+ /**
+ * The attribute clockFailure shall indicate that the time source of the sending device is
+ * unreliable. The value of the TimeStamp shall be ignored.
+ *
+ * @return true if the time source of the sending device is unreliable
+ */
+ public boolean getClockFailure() {
+ return ((value[7] & 0x40) != 0);
+ }
+
+ /**
+ * The attribute clockNotSynchronized shall indicate that the time source of the sending device is
+ * not synchronized with the external UTC time.
+ *
+ * @return true if the time source of the sending device is not synchronized
+ */
+ public boolean getClockNotSynchronized() {
+ return ((value[7] & 0x20) != 0);
+ }
+
+ /**
+ * The attribute TimeAccuracy shall represent the time accuracy class of the time source of the
+ * sending device relative to the external UTC time. The timeAccuracy classes shall represent the
+ * number of significant bits in the FractionOfSecond
+ *
+ *
If the time is set via Java {@link Date} objects, the accuracy is 1 ms, that is a
+ * timeAccuracy value of 10.
+ *
+ * @return the time accuracy
+ */
+ public int getTimeAccuracy() {
+ return ((value[7] & 0x1f));
+ }
+
+ /**
+ * Sets Timestamp the empty byte array (indicating an invalid Timestamp)
+ */
+ @Override
+ public void setDefault() {
+ value = new byte[8];
+ }
+
+ /**
+ * Sets Timestamp to current time
+ */
+ public void setCurrentTime() {
+ setInstant(Instant.now());
+ }
+
+ @Override
+ public BdaTimestamp copy() {
+ BdaTimestamp copy = new BdaTimestamp(objectReference, fc, sAddr, dchg, dupd);
+ byte[] valueCopy = new byte[value.length];
+ System.arraycopy(value, 0, valueCopy, 0, value.length);
+ copy.setValue(valueCopy);
+ if (mirror == null) {
+ copy.mirror = this;
+ } else {
+ copy.mirror = mirror;
+ }
+ return copy;
+ }
+
+ @Override
+ Data getMmsDataObj() {
+ Data data = new Data();
+ data.setUtcTime(new UtcTime(value));
+ return data;
+ }
+
+ @Override
+ void setValueFromMmsDataObj(Data data) throws ServiceError {
+ if (data.getUtcTime() == null) {
+ throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: utc_time/timestamp");
+ }
+ value = data.getUtcTime().value;
+ }
+
+ @Override
+ TypeDescription getMmsTypeSpec() {
+ TypeDescription typeDescription = new TypeDescription();
+ typeDescription.setUtcTime(new BerNull());
+ return typeDescription;
+ }
+
+ @Override
+ public String toString() {
+ return getReference().toString() + ": " + getInstant();
+ }
+
+ @Override
+ public String getValueString() {
+ return getInstant().toString();
+ }
}
diff --git a/src/main/java/com/beanit/iec61850bean/ConnectionParam.java b/src/main/java/com/beanit/iec61850bean/ConnectionParam.java
new file mode 100644
index 0000000..0e25626
--- /dev/null
+++ b/src/main/java/com/beanit/iec61850bean/ConnectionParam.java
@@ -0,0 +1,148 @@
+package com.beanit.iec61850bean;
+
+import java.util.Objects;
+
+public class ConnectionParam {
+ private String iedName;
+
+ private String IP;
+ private String IP_SUBNET;
+ private String OSI_AP_Title;
+ private String OSI_AE_Qualifier;
+ private String OSI_PSEL;
+ private String OSI_SSEL;
+ private String OSI_TSEL;
+ private String IP_GATEWAY;
+ private String S_Profile;
+ private String MAC_Address;
+
+
+ public String getIedName() {
+ return iedName;
+ }
+
+ public void setIedName(String iedName) {
+ this.iedName = iedName;
+ }
+
+ public String getIP() {
+ return IP;
+ }
+
+ public void setIP(String IP) {
+ this.IP = IP;
+ }
+
+ public String getIP_SUBNET() {
+ return IP_SUBNET;
+ }
+
+ public void setIP_SUBNET(String IP_SUBNET) {
+ this.IP_SUBNET = IP_SUBNET;
+ }
+
+ public String getOSI_AP_Title() {
+ return OSI_AP_Title;
+ }
+
+ public void setOSI_AP_Title(String OSI_AP_Title) {
+ this.OSI_AP_Title = OSI_AP_Title;
+ }
+
+ public String getOSI_AE_Qualifier() {
+ return OSI_AE_Qualifier;
+ }
+
+ public void setOSI_AE_Qualifier(String OSI_AE_Qualifier) {
+ this.OSI_AE_Qualifier = OSI_AE_Qualifier;
+ }
+
+ public String getOSI_PSEL() {
+ return OSI_PSEL;
+ }
+
+ public void setOSI_PSEL(String OSI_PSEL) {
+ this.OSI_PSEL = OSI_PSEL;
+ }
+
+ public String getOSI_SSEL() {
+ return OSI_SSEL;
+ }
+
+ public void setOSI_SSEL(String OSI_SSEL) {
+ this.OSI_SSEL = OSI_SSEL;
+ }
+
+ public String getOSI_TSEL() {
+ return OSI_TSEL;
+ }
+
+ public void setOSI_TSEL(String OSI_TSEL) {
+ this.OSI_TSEL = OSI_TSEL;
+ }
+
+ public String getIP_GATEWAY() {
+ return IP_GATEWAY;
+ }
+
+ public void setIP_GATEWAY(String IP_GATEWAY) {
+ this.IP_GATEWAY = IP_GATEWAY;
+ }
+
+ public String getS_Profile() {
+ return S_Profile;
+ }
+
+ public void setS_Profile(String s_Profile) {
+ S_Profile = s_Profile;
+ }
+
+ public String getMAC_Address() {
+ return MAC_Address;
+ }
+
+ public void setMAC_Address(String MAC_Address) {
+ this.MAC_Address = MAC_Address;
+ }
+
+
+ @Override
+ public String toString() {
+ return "iedName = " + iedName + '\n' +
+ "IP = " + IP + '\n' +
+ "IP_SUBNET = " + IP_SUBNET + '\n' +
+ "OSI_AP_Title = " + OSI_AP_Title + '\n' +
+ "OSI_AE_Qualifier = " + OSI_AE_Qualifier + '\n' +
+ "OSI_PSEL = " + OSI_PSEL + '\n' +
+ "OSI_SSEL = " + OSI_SSEL + '\n' +
+ "OSI_TSEL = " + OSI_TSEL + '\n' +
+ "IP_GATEWAY = " + IP_GATEWAY + '\n' +
+ "S_Profile = " + S_Profile + '\n' +
+ "MAC-Address = " + MAC_Address
+ ;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ConnectionParam that = (ConnectionParam) o;
+ return iedName.equals(that.iedName) &&
+ IP.equals(that.IP) &&
+ Objects.equals(IP_SUBNET, that.IP_SUBNET) &&
+ Objects.equals(OSI_AP_Title, that.OSI_AP_Title) &&
+ Objects.equals(OSI_AE_Qualifier, that.OSI_AE_Qualifier) &&
+ Objects.equals(OSI_PSEL, that.OSI_PSEL) &&
+ Objects.equals(OSI_SSEL, that.OSI_SSEL) &&
+ Objects.equals(OSI_TSEL, that.OSI_TSEL) &&
+ Objects.equals(IP_GATEWAY, that.IP_GATEWAY) &&
+ Objects.equals(S_Profile, that.S_Profile) &&
+ Objects.equals(MAC_Address, that.MAC_Address);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(iedName, IP, IP_SUBNET, OSI_AP_Title, OSI_AE_Qualifier, OSI_PSEL, OSI_SSEL,
+ OSI_TSEL, IP_GATEWAY, S_Profile, MAC_Address);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/beanit/iec61850bean/FcDataObject.java b/src/main/java/com/beanit/iec61850bean/FcDataObject.java
index 8b0cf5a..4f6b2e3 100644
--- a/src/main/java/com/beanit/iec61850bean/FcDataObject.java
+++ b/src/main/java/com/beanit/iec61850bean/FcDataObject.java
@@ -14,6 +14,7 @@
package com.beanit.iec61850bean;
import com.beanit.iec61850bean.internal.mms.asn1.Data;
+
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -30,66 +31,89 @@
*/
public class FcDataObject extends FcModelNode {
- public FcDataObject(ObjectReference objectReference, Fc fc, List children) {
+ private final List fcModelNodes;
+ private String doType;
+ private String cdc;
- this.children = new LinkedHashMap<>((int) ((children.size() / 0.75) + 1));
- this.objectReference = objectReference;
- for (ModelNode child : children) {
- this.children.put(child.getReference().getName(), child);
- child.setParent(this);
- }
- this.fc = fc;
- }
-
- @Override
- public FcDataObject copy() {
- List childCopies = new ArrayList<>(children.size());
- for (ModelNode childNode : children.values()) {
- childCopies.add((FcModelNode) childNode.copy());
+
+ public FcDataObject(ObjectReference objectReference, Fc fc, List children) {
+ this.fcModelNodes = children;
+ super.setDataAttributes(children);
+ this.children = new LinkedHashMap<>((int) ((children.size() / 0.75) + 1));
+ this.objectReference = objectReference;
+
+ for (ModelNode child : children) {
+ this.children.put(child.getReference().getName(), child);
+ child.setParent(this);
+ }
+ this.fc = fc;
}
- return new FcDataObject(objectReference, fc, childCopies);
- }
-
- @Override
- Data getMmsDataObj() {
- Data.Structure dataStructure = new Data.Structure();
- List seq = dataStructure.getData();
-
- for (ModelNode modelNode : getChildren()) {
- Data child = modelNode.getMmsDataObj();
- if (child == null) {
- throw new IllegalArgumentException(
- "Unable to convert Child: " + modelNode.objectReference + " to MMS Data Object.");
- }
- seq.add(child);
+
+ @Override
+ public FcDataObject copy() {
+ List childCopies = new ArrayList<>(children.size());
+ for (ModelNode childNode : children.values()) {
+ childCopies.add((FcModelNode) childNode.copy());
+ }
+ return new FcDataObject(objectReference, fc, childCopies);
}
- if (seq.size() == 0) {
- throw new IllegalArgumentException(
- "Converting ModelNode: "
- + objectReference
- + " to MMS Data Object resulted in Sequence of size zero.");
+
+ @Override
+ Data getMmsDataObj() {
+ Data.Structure dataStructure = new Data.Structure();
+ List seq = dataStructure.getData();
+
+ for (ModelNode modelNode : getChildren()) {
+ Data child = modelNode.getMmsDataObj();
+ if (child == null) {
+ throw new IllegalArgumentException(
+ "Unable to convert Child: " + modelNode.objectReference + " to MMS Data Object.");
+ }
+ seq.add(child);
+ }
+ if (seq.size() == 0) {
+ throw new IllegalArgumentException(
+ "Converting ModelNode: "
+ + objectReference
+ + " to MMS Data Object resulted in Sequence of size zero.");
+ }
+
+ Data data = new Data();
+ data.setStructure(dataStructure);
+
+ return data;
}
- Data data = new Data();
- data.setStructure(dataStructure);
+ @Override
+ void setValueFromMmsDataObj(Data data) throws ServiceError {
+ if (data.getStructure() == null) {
+ throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: structure");
+ }
+ if (data.getStructure().getData().size() != children.size()) {
+ throw new ServiceError(
+ ServiceError.TYPE_CONFLICT,
+ "expected type: structure with " + children.size() + " elements");
+ }
+
+ Iterator iterator = data.getStructure().getData().iterator();
+ for (ModelNode child : children.values()) {
+ child.setValueFromMmsDataObj(iterator.next());
+ }
+ }
- return data;
- }
+ public String getDoType() {
+ return doType;
+ }
- @Override
- void setValueFromMmsDataObj(Data data) throws ServiceError {
- if (data.getStructure() == null) {
- throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: structure");
+ public void setDoType(String doType) {
+ this.doType = doType;
}
- if (data.getStructure().getData().size() != children.size()) {
- throw new ServiceError(
- ServiceError.TYPE_CONFLICT,
- "expected type: structure with " + children.size() + " elements");
+
+ public String getCdc() {
+ return cdc;
}
- Iterator iterator = data.getStructure().getData().iterator();
- for (ModelNode child : children.values()) {
- child.setValueFromMmsDataObj(iterator.next());
+ public void setCdc(String cdc) {
+ this.cdc = cdc;
}
- }
}
diff --git a/src/main/java/com/beanit/iec61850bean/FcModelNode.java b/src/main/java/com/beanit/iec61850bean/FcModelNode.java
index e414979..1447f4d 100644
--- a/src/main/java/com/beanit/iec61850bean/FcModelNode.java
+++ b/src/main/java/com/beanit/iec61850bean/FcModelNode.java
@@ -13,240 +13,373 @@
*/
package com.beanit.iec61850bean;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.beanit.iec61850bean.internal.mms.asn1.AlternateAccess;
-import com.beanit.iec61850bean.internal.mms.asn1.AlternateAccessSelection;
+import com.beanit.iec61850bean.internal.mms.asn1.*;
import com.beanit.iec61850bean.internal.mms.asn1.AlternateAccessSelection.SelectAccess;
import com.beanit.iec61850bean.internal.mms.asn1.AlternateAccessSelection.SelectAccess.Component;
-import com.beanit.iec61850bean.internal.mms.asn1.BasicIdentifier;
-import com.beanit.iec61850bean.internal.mms.asn1.Identifier;
-import com.beanit.iec61850bean.internal.mms.asn1.ObjectName;
-import com.beanit.iec61850bean.internal.mms.asn1.Unsigned32;
-import com.beanit.iec61850bean.internal.mms.asn1.VariableDefs;
-import com.beanit.iec61850bean.internal.mms.asn1.VariableSpecification;
+
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
public abstract class FcModelNode extends ModelNode {
- Fc fc;
- private VariableDefs.SEQUENCE variableDef = null;
- private ServerAssociation selected = null;
- private TimerTask task = null;
+ Fc fc;
+ private VariableDefs.SEQUENCE variableDef = null;
+ private ServerAssociation selected = null;
+ private TimerTask task = null;
+
+ private String daType;
+ private BdaType basicType = null;
+ private String sAddr;
+ private String daiVal;
+ private boolean dchg;
+ private boolean dupd;
+ private boolean qchg;
+
+ private String bType;
+ private List bdas;
+
+ private short valueShort;
+ private byte[] valueBytes;
+ private byte valueByte;
+ private boolean valueBoolean;
+ private int valueInt;
+ private long valueLong;
+
+ public Fc getFc() {
+ return fc;
+ }
- public Fc getFc() {
- return fc;
- }
+ boolean select(ServerAssociation association, Timer timer) {
+ if (selected != null) {
+ if (selected != association) {
+ return false;
+ }
+ } else {
+ selected = association;
+ association.selects.add(this);
+ }
- boolean select(ServerAssociation association, Timer timer) {
- if (selected != null) {
- if (selected != association) {
- return false;
- }
- } else {
- selected = association;
- association.selects.add(this);
- }
+ ModelNode sboTimeoutNode =
+ association.serverModel.findModelNode(objectReference, Fc.CF).getChild("sboTimeout");
- ModelNode sboTimeoutNode =
- association.serverModel.findModelNode(objectReference, Fc.CF).getChild("sboTimeout");
+ if (sboTimeoutNode == null) {
+ return true;
+ }
- if (sboTimeoutNode == null) {
- return true;
- }
+ long sboTimeout = ((BdaInt32U) sboTimeoutNode).getValue();
- long sboTimeout = ((BdaInt32U) sboTimeoutNode).getValue();
+ if (sboTimeout == 0) {
+ return true;
+ }
- if (sboTimeout == 0) {
- return true;
- }
+ class SelectResetTask extends TimerTask {
+ final ServerAssociation association;
+
+ SelectResetTask(ServerAssociation association) {
+ this.association = association;
+ }
+
+ @Override
+ public void run() {
+ synchronized (association.serverModel) {
+ if (task == this) {
+ task = null;
+ deselectAndRemove(association);
+ }
+ }
+ }
+ }
- class SelectResetTask extends TimerTask {
- ServerAssociation association;
+ if (task != null) {
+ task.cancel();
+ }
- SelectResetTask(ServerAssociation association) {
- this.association = association;
- }
+ task = new SelectResetTask(association);
+ timer.schedule(task, sboTimeout);
+
+ return true;
+ }
- @Override
- public void run() {
- synchronized (association.serverModel) {
- if (task == this) {
+ void deselectAndRemove(ServerAssociation association) {
+ selected = null;
+ if (task != null) {
+ task.cancel();
task = null;
- deselectAndRemove(association);
- }
}
- }
+ association.selects.remove(this);
}
- if (task != null) {
- task.cancel();
+ void deselect() {
+ selected = null;
+ if (task != null) {
+ task.cancel();
+ task = null;
+ }
}
- task = new SelectResetTask(association);
- timer.schedule(task, sboTimeout);
-
- return true;
- }
-
- void deselectAndRemove(ServerAssociation association) {
- selected = null;
- if (task != null) {
- task.cancel();
- task = null;
+ boolean isSelected() {
+ return selected != null;
}
- association.selects.remove(this);
- }
- void deselect() {
- selected = null;
- if (task != null) {
- task.cancel();
- task = null;
+ boolean isSelectedBy(ServerAssociation association) {
+ return selected == association;
}
- }
- boolean isSelected() {
- return selected != null;
- }
+ VariableDefs.SEQUENCE getMmsVariableDef() {
+
+ if (variableDef != null) {
+ return variableDef;
+ }
- boolean isSelectedBy(ServerAssociation association) {
- return selected == association;
- }
+ AlternateAccess alternateAccess = null;
- VariableDefs.SEQUENCE getMmsVariableDef() {
+ StringBuilder preArrayIndexItemId = new StringBuilder(objectReference.get(1));
+ preArrayIndexItemId.append("$");
+ preArrayIndexItemId.append(fc);
- if (variableDef != null) {
- return variableDef;
- }
+ int arrayIndexPosition = objectReference.getArrayIndexPosition();
+ if (arrayIndexPosition != -1) {
- AlternateAccess alternateAccess = null;
+ for (int i = 2; i < arrayIndexPosition; i++) {
+ preArrayIndexItemId.append("$");
+ preArrayIndexItemId.append(objectReference.get(i));
+ }
- StringBuilder preArrayIndexItemId = new StringBuilder(objectReference.get(1));
- preArrayIndexItemId.append("$");
- preArrayIndexItemId.append(fc);
+ alternateAccess = new AlternateAccess();
+ List subSeqOfAlternateAccess = alternateAccess.getCHOICE();
+ Unsigned32 indexBerInteger =
+ new Unsigned32(Integer.parseInt(objectReference.get(arrayIndexPosition)));
- int arrayIndexPosition = objectReference.getArrayIndexPosition();
- if (arrayIndexPosition != -1) {
+ if (arrayIndexPosition < (objectReference.size() - 1)) {
+ // this reference points to a sub-node of an array element
- for (int i = 2; i < arrayIndexPosition; i++) {
- preArrayIndexItemId.append("$");
- preArrayIndexItemId.append(objectReference.get(i));
- }
+ StringBuilder postArrayIndexItemId =
+ new StringBuilder(objectReference.get(arrayIndexPosition + 1));
+
+ for (int i = (arrayIndexPosition + 2); i < objectReference.size(); i++) {
+ postArrayIndexItemId.append("$");
+ postArrayIndexItemId.append(objectReference.get(i));
+ }
+
+ BasicIdentifier subIndexReference =
+ new BasicIdentifier(postArrayIndexItemId.toString().getBytes(UTF_8));
+
+ AlternateAccessSelection.SelectAccess subIndexReferenceSelectAccess =
+ new AlternateAccessSelection.SelectAccess();
+ Component component = new Component();
+ component.setBasic(subIndexReference);
+ subIndexReferenceSelectAccess.setComponent(component);
+
+ AlternateAccessSelection subIndexReferenceAlternateAccessSelection =
+ new AlternateAccessSelection();
+ subIndexReferenceAlternateAccessSelection.setSelectAccess(subIndexReferenceSelectAccess);
+
+ AlternateAccess.CHOICE subIndexReferenceAlternateAccessSubChoice =
+ new AlternateAccess.CHOICE();
+ subIndexReferenceAlternateAccessSubChoice.setUnnamed(
+ subIndexReferenceAlternateAccessSelection);
+
+ AlternateAccess subIndexReferenceAlternateAccess = new AlternateAccess();
+
+ List subIndexReferenceAlternateAccessSubSeqOf =
+ subIndexReferenceAlternateAccess.getCHOICE();
+ subIndexReferenceAlternateAccessSubSeqOf.add(subIndexReferenceAlternateAccessSubChoice);
+
+ // set array index:
+
+ AlternateAccessSelection.SelectAlternateAccess.AccessSelection indexAccessSelectionChoice =
+ new AlternateAccessSelection.SelectAlternateAccess.AccessSelection();
+ indexAccessSelectionChoice.setIndex(indexBerInteger);
+
+ AlternateAccessSelection.SelectAlternateAccess indexAndLowerReferenceSelectAlternateAccess =
+ new AlternateAccessSelection.SelectAlternateAccess();
+ indexAndLowerReferenceSelectAlternateAccess.setAccessSelection(indexAccessSelectionChoice);
+ indexAndLowerReferenceSelectAlternateAccess.setAlternateAccess(
+ subIndexReferenceAlternateAccess);
+
+ AlternateAccessSelection indexAndLowerReferenceAlternateAccessSelection =
+ new AlternateAccessSelection();
+ indexAndLowerReferenceAlternateAccessSelection.setSelectAlternateAccess(
+ indexAndLowerReferenceSelectAlternateAccess);
+
+ AlternateAccess.CHOICE indexAndLowerReferenceAlternateAccessChoice =
+ new AlternateAccess.CHOICE();
+ indexAndLowerReferenceAlternateAccessChoice.setUnnamed(
+ indexAndLowerReferenceAlternateAccessSelection);
+
+ subSeqOfAlternateAccess.add(indexAndLowerReferenceAlternateAccessChoice);
+
+ } else {
+ SelectAccess selectAccess = new SelectAccess();
+ selectAccess.setIndex(indexBerInteger);
+
+ AlternateAccessSelection alternateAccessSelection = new AlternateAccessSelection();
+ alternateAccessSelection.setSelectAccess(selectAccess);
+
+ AlternateAccess.CHOICE alternateAccessChoice = new AlternateAccess.CHOICE();
+ alternateAccessChoice.setUnnamed(alternateAccessSelection);
+
+ subSeqOfAlternateAccess.add(alternateAccessChoice);
+ }
- alternateAccess = new AlternateAccess();
- List subSeqOfAlternateAccess = alternateAccess.getCHOICE();
- Unsigned32 indexBerInteger =
- new Unsigned32(Integer.parseInt(objectReference.get(arrayIndexPosition)));
+ } else {
- if (arrayIndexPosition < (objectReference.size() - 1)) {
- // this reference points to a sub-node of an array element
+ for (int i = 2; i < objectReference.size(); i++) {
+ preArrayIndexItemId.append("$");
+ preArrayIndexItemId.append(objectReference.get(i));
+ }
+ }
+
+ ObjectName.DomainSpecific domainSpecificObjectName = new ObjectName.DomainSpecific();
+ domainSpecificObjectName.setDomainID(new Identifier(objectReference.get(0).getBytes(UTF_8)));
+ domainSpecificObjectName.setItemID(
+ new Identifier(preArrayIndexItemId.toString().getBytes(UTF_8)));
+
+ ObjectName objectName = new ObjectName();
+ objectName.setDomainSpecific(domainSpecificObjectName);
- StringBuilder postArrayIndexItemId =
- new StringBuilder(objectReference.get(arrayIndexPosition + 1));
+ VariableSpecification varSpec = new VariableSpecification();
+ varSpec.setName(objectName);
+
+ variableDef = new VariableDefs.SEQUENCE();
+ variableDef.setAlternateAccess(alternateAccess);
+ variableDef.setVariableSpecification(varSpec);
+
+ return variableDef;
+ }
- for (int i = (arrayIndexPosition + 2); i < objectReference.size(); i++) {
- postArrayIndexItemId.append("$");
- postArrayIndexItemId.append(objectReference.get(i));
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getReference().toString()).append(" [").append(fc).append("]");
+ for (ModelNode childNode : children.values()) {
+ sb.append("\n");
+ sb.append(childNode.toString());
}
+ return sb.toString();
+ }
- BasicIdentifier subIndexReference =
- new BasicIdentifier(postArrayIndexItemId.toString().getBytes(UTF_8));
+ public String getDaType() {
+ return daType;
+ }
- AlternateAccessSelection.SelectAccess subIndexReferenceSelectAccess =
- new AlternateAccessSelection.SelectAccess();
- Component component = new Component();
- component.setBasic(subIndexReference);
- subIndexReferenceSelectAccess.setComponent(component);
+ public void setDaType(String daType) {
+ this.daType = daType;
+ }
+
+ public BdaType getBasicType() {
+ return basicType;
+ }
+
+ public void setBasicType(BdaType basicType) {
+ this.basicType = basicType;
+ }
+
+ public String getsAddr() {
+ return sAddr;
+ }
+
+ public void setsAddr(String sAddr) {
+ this.sAddr = sAddr;
+ }
+
+ public String getDaiVal() {
+ return daiVal;
+ }
+
+ public void setDaiVal(String daiVal) {
+ this.daiVal = daiVal;
+ }
- AlternateAccessSelection subIndexReferenceAlternateAccessSelection =
- new AlternateAccessSelection();
- subIndexReferenceAlternateAccessSelection.setSelectAccess(subIndexReferenceSelectAccess);
+ public boolean isDchg() {
+ return dchg;
+ }
- AlternateAccess.CHOICE subIndexReferenceAlternateAccessSubChoice =
- new AlternateAccess.CHOICE();
- subIndexReferenceAlternateAccessSubChoice.setUnnamed(
- subIndexReferenceAlternateAccessSelection);
+ public void setDchg(boolean dchg) {
+ this.dchg = dchg;
+ }
- AlternateAccess subIndexReferenceAlternateAccess = new AlternateAccess();
+ public boolean isDupd() {
+ return dupd;
+ }
- List subIndexReferenceAlternateAccessSubSeqOf =
- subIndexReferenceAlternateAccess.getCHOICE();
- subIndexReferenceAlternateAccessSubSeqOf.add(subIndexReferenceAlternateAccessSubChoice);
+ public void setDupd(boolean dupd) {
+ this.dupd = dupd;
+ }
- // set array index:
+ public boolean isQchg() {
+ return qchg;
+ }
- AlternateAccessSelection.SelectAlternateAccess.AccessSelection indexAccessSelectionChoice =
- new AlternateAccessSelection.SelectAlternateAccess.AccessSelection();
- indexAccessSelectionChoice.setIndex(indexBerInteger);
+ public void setQchg(boolean qchg) {
+ this.qchg = qchg;
+ }
- AlternateAccessSelection.SelectAlternateAccess indexAndLowerReferenceSelectAlternateAccess =
- new AlternateAccessSelection.SelectAlternateAccess();
- indexAndLowerReferenceSelectAlternateAccess.setAccessSelection(indexAccessSelectionChoice);
- indexAndLowerReferenceSelectAlternateAccess.setAlternateAccess(
- subIndexReferenceAlternateAccess);
+ public String getbType() {
+ return bType;
+ }
- AlternateAccessSelection indexAndLowerReferenceAlternateAccessSelection =
- new AlternateAccessSelection();
- indexAndLowerReferenceAlternateAccessSelection.setSelectAlternateAccess(
- indexAndLowerReferenceSelectAlternateAccess);
+ public void setbType(String bType) {
+ this.bType = bType;
+ }
- AlternateAccess.CHOICE indexAndLowerReferenceAlternateAccessChoice =
- new AlternateAccess.CHOICE();
- indexAndLowerReferenceAlternateAccessChoice.setUnnamed(
- indexAndLowerReferenceAlternateAccessSelection);
+ public List getDataAttributes() {
+ return bdas;
+ }
- subSeqOfAlternateAccess.add(indexAndLowerReferenceAlternateAccessChoice);
+ public FcModelNode setDataAttributes(List bdas) {
+ this.bdas = bdas;
+ return this;
+ }
- } else {
- SelectAccess selectAccess = new SelectAccess();
- selectAccess.setIndex(indexBerInteger);
+ public short getValueShort() {
+ return valueShort;
+ }
- AlternateAccessSelection alternateAccessSelection = new AlternateAccessSelection();
- alternateAccessSelection.setSelectAccess(selectAccess);
+ public void setValueShort(short valueShort) {
+ this.valueShort = valueShort;
+ }
- AlternateAccess.CHOICE alternateAccessChoice = new AlternateAccess.CHOICE();
- alternateAccessChoice.setUnnamed(alternateAccessSelection);
+ public byte[] getValueBytes() {
+ return valueBytes;
+ }
- subSeqOfAlternateAccess.add(alternateAccessChoice);
- }
+ public void setValueBytes(byte[] valueBytes) {
+ this.valueBytes = valueBytes;
+ }
- } else {
+ public byte getValueByte() {
+ return valueByte;
+ }
- for (int i = 2; i < objectReference.size(); i++) {
- preArrayIndexItemId.append("$");
- preArrayIndexItemId.append(objectReference.get(i));
- }
+ public void setValueByte(byte valueByte) {
+ this.valueByte = valueByte;
}
- ObjectName.DomainSpecific domainSpecificObjectName = new ObjectName.DomainSpecific();
- domainSpecificObjectName.setDomainID(new Identifier(objectReference.get(0).getBytes(UTF_8)));
- domainSpecificObjectName.setItemID(
- new Identifier(preArrayIndexItemId.toString().getBytes(UTF_8)));
+ public boolean isValueBoolean() {
+ return valueBoolean;
+ }
- ObjectName objectName = new ObjectName();
- objectName.setDomainSpecific(domainSpecificObjectName);
+ public void setValueBoolean(boolean valueBoolean) {
+ this.valueBoolean = valueBoolean;
+ }
- VariableSpecification varSpec = new VariableSpecification();
- varSpec.setName(objectName);
+ public int getValueInt() {
+ return valueInt;
+ }
- variableDef = new VariableDefs.SEQUENCE();
- variableDef.setAlternateAccess(alternateAccess);
- variableDef.setVariableSpecification(varSpec);
+ public void setValueInt(int valueInt) {
+ this.valueInt = valueInt;
+ }
- return variableDef;
- }
+ public long getValueLong() {
+ return valueLong;
+ }
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append(getReference().toString()).append(" [").append(fc).append("]");
- for (ModelNode childNode : children.values()) {
- sb.append("\n");
- sb.append(childNode.toString());
+ public void setValueLong(long valueLong) {
+ this.valueLong = valueLong;
}
- return sb.toString();
- }
}
diff --git a/src/main/java/com/beanit/iec61850bean/LogicalDevice.java b/src/main/java/com/beanit/iec61850bean/LogicalDevice.java
index c67bfe6..d46d6e6 100644
--- a/src/main/java/com/beanit/iec61850bean/LogicalDevice.java
+++ b/src/main/java/com/beanit/iec61850bean/LogicalDevice.java
@@ -19,7 +19,11 @@
public final class LogicalDevice extends ModelNode {
+ private final List logicalNodes;
+ private String ldInst;
+
public LogicalDevice(ObjectReference objectReference, List logicalNodes) {
+ this.logicalNodes = logicalNodes;
children = new LinkedHashMap<>((int) ((logicalNodes.size() / 0.75) + 1));
this.objectReference = objectReference;
for (LogicalNode logicalNode : logicalNodes) {
@@ -36,4 +40,16 @@ public LogicalDevice copy() {
}
return new LogicalDevice(objectReference, childCopies);
}
+
+ public List getLogicalNodes() {
+ return logicalNodes;
+ }
+
+ public String getLdInst() {
+ return ldInst;
+ }
+
+ public void setLdInst(String ldInst) {
+ this.ldInst = ldInst;
+ }
}
diff --git a/src/main/java/com/beanit/iec61850bean/LogicalNode.java b/src/main/java/com/beanit/iec61850bean/LogicalNode.java
index c5f9e2a..38393f7 100644
--- a/src/main/java/com/beanit/iec61850bean/LogicalNode.java
+++ b/src/main/java/com/beanit/iec61850bean/LogicalNode.java
@@ -28,7 +28,14 @@ public final class LogicalNode extends ModelNode {
private final Map urcbs = new HashMap<>();
private final Map brcbs = new HashMap<>();
+ private final List dataObjects;
+ private String prefix;
+ private String lnClass;
+ private String lnInst;
+ private String lnType;
+
public LogicalNode(ObjectReference objectReference, List fcDataObjects) {
+ this.dataObjects = fcDataObjects;
children = new LinkedHashMap<>();
for (Fc fc : Fc.values()) {
this.fcDataObjects.put(fc, new LinkedHashMap());
@@ -59,8 +66,7 @@ public LogicalNode copy() {
dataObjectsCopy.add((FcDataObject) obj.copy());
}
- LogicalNode copy = new LogicalNode(objectReference, dataObjectsCopy);
- return copy;
+ return new LogicalNode(objectReference, dataObjectsCopy);
}
public List getChildren(Fc fc) {
@@ -134,4 +140,36 @@ public String toString() {
}
return sb.toString();
}
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public String getLnClass() {
+ return lnClass;
+ }
+
+ public void setLnClass(String lnClass) {
+ this.lnClass = lnClass;
+ }
+
+ public String getLnInst() {
+ return lnInst;
+ }
+
+ public void setLnInst(String lnInst) {
+ this.lnInst = lnInst;
+ }
+
+ public String getLnType() {
+ return lnType;
+ }
+
+ public void setLnType(String lnType) {
+ this.lnType = lnType;
+ }
}
diff --git a/src/main/java/com/beanit/iec61850bean/Report.java b/src/main/java/com/beanit/iec61850bean/Report.java
index 80f1c42..038cf29 100644
--- a/src/main/java/com/beanit/iec61850bean/Report.java
+++ b/src/main/java/com/beanit/iec61850bean/Report.java
@@ -14,6 +14,7 @@
package com.beanit.iec61850bean;
import com.beanit.iec61850bean.internal.HexString;
+
import java.util.List;
public class Report {
@@ -172,7 +173,7 @@ public String toString() {
sb.append("\nEntry ID: ").append(HexString.fromBytes(entryId.getValue()));
}
if (confRev != null) {
- sb.append("\nConfiguration revision: ").append(confRev.toString());
+ sb.append("\nConfiguration revision: ").append(confRev);
}
sb.append("\nReported data set members:");
int index = 0;
diff --git a/src/main/java/com/beanit/iec61850bean/SclParser.java b/src/main/java/com/beanit/iec61850bean/SclParser.java
index adc5a10..e5b94da 100644
--- a/src/main/java/com/beanit/iec61850bean/SclParser.java
+++ b/src/main/java/com/beanit/iec61850bean/SclParser.java
@@ -1,3 +1,4 @@
+
/*
* Copyright 2011 The IEC61850bean Authors
*
@@ -13,1098 +14,1267 @@
*/
package com.beanit.iec61850bean;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.beanit.iec61850bean.internal.scl.AbstractDataAttribute;
-import com.beanit.iec61850bean.internal.scl.Bda;
-import com.beanit.iec61850bean.internal.scl.Da;
-import com.beanit.iec61850bean.internal.scl.DaType;
-import com.beanit.iec61850bean.internal.scl.Do;
-import com.beanit.iec61850bean.internal.scl.DoType;
-import com.beanit.iec61850bean.internal.scl.EnumType;
-import com.beanit.iec61850bean.internal.scl.EnumVal;
-import com.beanit.iec61850bean.internal.scl.LnSubDef;
-import com.beanit.iec61850bean.internal.scl.LnType;
-import com.beanit.iec61850bean.internal.scl.Sdo;
-import com.beanit.iec61850bean.internal.scl.TypeDefinitions;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import javax.xml.parsers.DocumentBuilderFactory;
+import com.beanit.iec61850bean.internal.scl.*;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-public class SclParser {
-
- private final Map dataSetsMap = new HashMap<>();
- private final List dataSetDefs = new ArrayList<>();
- private TypeDefinitions typeDefinitions;
- private Document doc;
- private String iedName;
- private List serverModels = new ArrayList<>();
- private boolean useResvTmsAttributes = false;
-
- private SclParser() {}
-
- public static List parse(InputStream is) throws SclParseException {
- SclParser sclParser = new SclParser();
- sclParser.parseStream(is);
- return sclParser.serverModels;
- }
-
- public static List parse(String sclFilePath) throws SclParseException {
- try {
- return parse(new FileInputStream(sclFilePath));
- } catch (FileNotFoundException e) {
- throw new SclParseException(e);
- }
- }
-
- private void parseStream(InputStream icdFileStream) throws SclParseException {
-
- typeDefinitions = new TypeDefinitions();
-
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setIgnoringComments(true);
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.*;
- try {
- doc = factory.newDocumentBuilder().parse(icdFileStream);
- } catch (Exception e) {
- throw new SclParseException(e);
- }
+import static java.nio.charset.StandardCharsets.UTF_8;
- Node rootNode = doc.getDocumentElement();
+public class SclParser {
- if (!"SCL".equals(rootNode.getNodeName())) {
- throw new SclParseException("Root node in SCL file is not of type \"SCL\"");
+ private final Map dataSetsMap = new HashMap<>();
+ private final List dataSetDefs = new ArrayList<>();
+ private TypeDefinitions typeDefinitions;
+ private Document doc;
+ private String iedName;
+ private final List serverModels = new ArrayList<>();
+ private boolean useResvTmsAttributes = false;
+
+ private String iedConnectedAP;
+ ConnectionParam connectionParm;
+ private final Map iedConnectionMap = new HashMap<>();
+ private String iedManufacturer;
+ Map descMap;
+
+ private List ldsInsts;
+ private List ldsRefs;
+ private Set lnSet;
+ private Map> lns;
+ private final HashSet lnS = new HashSet<>();
+ private final Map cdcDOMap = new HashMap<>();
+ private Map daiDescMap;
+ private List logicalDevices;
+
+ private SclParser() {
}
- readTypeDefinitions();
-
- NodeList iedList = doc.getElementsByTagName("IED");
- if (iedList.getLength() == 0) {
- throw new SclParseException("No IED section found!");
+ public static List parse(InputStream is) throws SclParseException {
+ SclParser sclParser = new SclParser();
+ sclParser.parseStream(is);
+ return sclParser.serverModels;
}
- for (int z = 0; z < iedList.getLength(); z++) {
- Node iedNode = iedList.item(z);
-
- useResvTmsAttributes = false;
-
- Node nameAttribute = iedNode.getAttributes().getNamedItem("name");
-
- iedName = nameAttribute.getNodeValue();
- if ((iedName == null) || (iedName.length() == 0)) {
- throw new SclParseException("IED must have a name!");
- }
-
- NodeList iedElements = iedNode.getChildNodes();
-
- for (int i = 0; i < iedElements.getLength(); i++) {
- Node element = iedElements.item(i);
- String nodeName = element.getNodeName();
- if ("AccessPoint".equals(nodeName)) {
- ServerSap serverSap = createAccessPoint(element);
- if (serverSap != null) {
- serverModels.add(serverSap.serverModel);
- }
- } else if ("Services".equals(nodeName)) {
- NodeList servicesElements = element.getChildNodes();
- for (int j = 0; j < servicesElements.getLength(); j++) {
- if ("ReportSettings".equals(servicesElements.item(j).getNodeName())) {
- Node resvTmsAttribute =
- servicesElements.item(j).getAttributes().getNamedItem("resvTms");
- if (resvTmsAttribute != null) {
- useResvTmsAttributes = resvTmsAttribute.getNodeValue().equalsIgnoreCase("true");
- }
- }
- }
+ public static List parse(String sclFilePath) throws SclParseException {
+ try {
+ return parse(new FileInputStream(sclFilePath));
+ } catch (FileNotFoundException e) {
+ throw new SclParseException(e);
}
- }
}
- }
- private void readTypeDefinitions() throws SclParseException {
+ private void parseStream(InputStream icdFileStream) throws SclParseException {
- NodeList dttSections = doc.getElementsByTagName("DataTypeTemplates");
+ typeDefinitions = new TypeDefinitions();
- if (dttSections.getLength() != 1) {
- throw new SclParseException("Only one DataTypeSection allowed");
- }
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setIgnoringComments(true);
- Node dtt = dttSections.item(0);
+ try {
+ doc = factory.newDocumentBuilder().parse(icdFileStream);
+ } catch (Exception e) {
+ throw new SclParseException(e);
+ }
+
+ Node rootNode = doc.getDocumentElement();
- NodeList dataTypes = dtt.getChildNodes();
+ if (!"SCL".equals(rootNode.getNodeName())) {
+ throw new SclParseException("Root node in SCL file is not of type \"SCL\"");
+ }
- for (int i = 0; i < dataTypes.getLength(); i++) {
- Node element = dataTypes.item(i);
+ readTypeDefinitions();
- String nodeName = element.getNodeName();
+ NodeList connectedAPs = doc.getElementsByTagName("ConnectedAP");
- if (nodeName.equals("LNodeType")) {
- typeDefinitions.putLNodeType(new LnType(element));
- } else if (nodeName.equals("DOType")) {
- typeDefinitions.putDOType(new DoType(element));
- } else if (nodeName.equals("DAType")) {
- typeDefinitions.putDAType(new DaType(element));
- } else if (nodeName.equals("EnumType")) {
- typeDefinitions.putEnumType(new EnumType(element));
- }
- }
- }
+ for (int zz = 0; zz < connectedAPs.getLength(); zz++) {
+ Node connectedAP = connectedAPs.item(zz);
+ Node attributeName = connectedAP.getAttributes().getNamedItem("iedName");
+ iedConnectedAP = attributeName.getNodeValue();
+ connectionParm = new ConnectionParam();
+ if ((iedConnectedAP == null) || (iedConnectedAP.length() == 0)) {
+ throw new SclParseException("ConnectedAP must has a name");
+ }
+ NodeList elementsConnectedAP = connectedAP.getChildNodes();
+
+ for (int yy = 0; yy < elementsConnectedAP.getLength(); yy++) {
+ Node elementConnectedAP = elementsConnectedAP.item(yy);
+ String nodeAddress = elementConnectedAP.getNodeName();
+ if (nodeAddress.equals("Address")) {
+
+ NodeList address = elementConnectedAP.getChildNodes();
+ for (int ii = 0; ii < address.getLength(); ii++) {
+
+ Node elementAddress = address.item(ii);
+
+ String nodeCheck = elementAddress.getNodeName();
+ if ("P".equals(nodeCheck)) {
+ setConnectionParm(elementAddress);
+ }
+ }
+ connectionParm.setIedName(iedConnectedAP);
+ iedConnectionMap.put(iedConnectedAP, connectionParm);
+ }
+ }
+ }
+
+ NodeList iedList = doc.getElementsByTagName("IED");
+ if (iedList.getLength() == 0) {
+ throw new SclParseException("No IED section found!");
+ }
- private ServerSap createAccessPoint(Node iedServer) throws SclParseException {
- ServerSap serverSap = null;
+ for (int z = 0; z < iedList.getLength(); z++) {
+ Node iedNode = iedList.item(z);
- NodeList elements = iedServer.getChildNodes();
+ useResvTmsAttributes = false;
- for (int i = 0; i < elements.getLength(); i++) {
- Node element = elements.item(i);
+ Node nameAttribute = iedNode.getAttributes().getNamedItem("name");
- if (element.getNodeName().equals("Server")) {
+ Node manufacturerAttr = iedNode.getAttributes().getNamedItem("manufacturer");
+ iedManufacturer = manufacturerAttr.getNodeValue();
- ServerModel server = createServerModel(element);
+ iedName = nameAttribute.getNodeValue();
+ if ((iedName == null) || (iedName.length() == 0)) {
+ throw new SclParseException("IED must have a name!");
+ }
- Node namedItem = iedServer.getAttributes().getNamedItem("name");
- if (namedItem == null) {
- throw new SclParseException("AccessPoint has no name attribute!");
+ NodeList iedElements = iedNode.getChildNodes();
+
+ for (int i = 0; i < iedElements.getLength(); i++) {
+ Node element = iedElements.item(i);
+ String nodeName = element.getNodeName();
+ if ("AccessPoint".equals(nodeName)) {
+ ServerSap serverSap = createAccessPoint(element);
+ if (serverSap != null) {
+ serverModels.add(serverSap.serverModel);
+ }
+ } else if ("Services".equals(nodeName)) {
+ NodeList servicesElements = element.getChildNodes();
+ for (int j = 0; j < servicesElements.getLength(); j++) {
+ if ("ReportSettings".equals(servicesElements.item(j).getNodeName())) {
+ Node resvTmsAttribute =
+ servicesElements.item(j).getAttributes().getNamedItem("resvTms");
+ if (resvTmsAttribute != null) {
+ useResvTmsAttributes = resvTmsAttribute.getNodeValue().equalsIgnoreCase("true");
+ }
+ }
+ }
+ }
+ }
}
- // TODO save this name?
- serverSap = new ServerSap(102, 0, null, server, null);
+ }
- break;
- }
+ public void setConnectionParm(Node P) {
+ String nodeValue;
+
+ P.getAttributes().getNamedItem("type");
+ String typeValue = P.getAttributes().getNamedItem("type").getNodeValue();
+
+ nodeValue = P.getTextContent();
+
+ switch (typeValue) {
+ case "IP":
+ connectionParm.setIP(nodeValue);
+ break;
+ case "IP-SUBNET":
+ connectionParm.setIP_SUBNET(nodeValue);
+ break;
+ case "OSI-AP-Title":
+ connectionParm.setOSI_AP_Title(nodeValue);
+ break;
+ case "OSI-AE-Qualifier":
+ connectionParm.setOSI_AE_Qualifier(nodeValue);
+ break;
+ case "OSI-PSEL":
+ connectionParm.setOSI_PSEL(nodeValue);
+ break;
+ case "OSI-SSEL":
+ connectionParm.setOSI_SSEL(nodeValue);
+ break;
+ case "OSI-TSEL":
+ connectionParm.setOSI_TSEL(nodeValue);
+ break;
+ case "IP-GATEWAY":
+ connectionParm.setIP_GATEWAY(nodeValue);
+ break;
+ case "S-Profile":
+ connectionParm.setS_Profile(nodeValue);
+ break;
+ case "MAC-Address":
+ connectionParm.setMAC_Address(nodeValue);
+ break;
+ }
}
- return serverSap;
- }
+ private void readTypeDefinitions() throws SclParseException {
- private ServerModel createServerModel(Node serverXMLNode) throws SclParseException {
+ NodeList dttSections = doc.getElementsByTagName("DataTypeTemplates");
- NodeList elements = serverXMLNode.getChildNodes();
- List logicalDevices = new ArrayList<>(elements.getLength());
+ if (dttSections.getLength() != 1) {
+ throw new SclParseException("Only one DataTypeSection allowed");
+ }
- for (int i = 0; i < elements.getLength(); i++) {
- Node element = elements.item(i);
+ Node dtt = dttSections.item(0);
- if (element.getNodeName().equals("LDevice")) {
- logicalDevices.add(createNewLDevice(element));
- }
- }
+ NodeList dataTypes = dtt.getChildNodes();
- ServerModel serverModel = new ServerModel(logicalDevices, null);
+ for (int i = 0; i < dataTypes.getLength(); i++) {
+ Node element = dataTypes.item(i);
- dataSetsMap.clear();
+ String nodeName = element.getNodeName();
- for (LnSubDef dataSetDef : dataSetDefs) {
- DataSet dataSet = createDataSet(serverModel, dataSetDef.logicalNode, dataSetDef.defXmlNode);
- dataSetsMap.put(dataSet.getReferenceStr(), dataSet);
+ switch (nodeName) {
+ case "LNodeType":
+ typeDefinitions.putLNodeType(new LnType(element));
+ break;
+ case "DOType":
+ typeDefinitions.putDOType(new DoType(element));
+ break;
+ case "DAType":
+ typeDefinitions.putDAType(new DaType(element));
+ break;
+ case "EnumType":
+ typeDefinitions.putEnumType(new EnumType(element));
+ break;
+ }
+ }
}
- serverModel.addDataSets(dataSetsMap.values());
+ private ServerSap createAccessPoint(Node iedServer) throws SclParseException {
+ ServerSap serverSap = null;
- dataSetDefs.clear();
+ NodeList elements = iedServer.getChildNodes();
- return serverModel;
- }
+ for (int i = 0; i < elements.getLength(); i++) {
+ Node element = elements.item(i);
- private LogicalDevice createNewLDevice(Node ldXmlNode) throws SclParseException {
+ if (element.getNodeName().equals("Server")) {
- String inst = null;
- String ldName = null;
+ ldsInsts = new ArrayList<>();
+ ldsRefs = new ArrayList<>();
+ descMap = new HashMap<>();
+ daiDescMap = new HashMap<>();
+ logicalDevices = new ArrayList<>();
- NamedNodeMap attributes = ldXmlNode.getAttributes();
+ ServerModel server = createServerModel(element);
- for (int i = 0; i < attributes.getLength(); i++) {
- Node node = attributes.item(i);
- String nodeName = node.getNodeName();
+ Node namedItem = iedServer.getAttributes().getNamedItem("name");
+ if (namedItem == null) {
+ throw new SclParseException("AccessPoint has no name attribute!");
+ }
+ // TODO save this name?
+ serverSap = new ServerSap(102, 0, null, server, null);
- if (nodeName.equals("inst")) {
- inst = node.getNodeValue();
- } else if (nodeName.equals("ldName")) {
- ldName = node.getNodeValue();
- }
- }
+ break;
+ }
+ }
- if (inst == null) {
- throw new SclParseException("Required attribute \"inst\" in logical device not found!");
+ return serverSap;
}
- NodeList elements = ldXmlNode.getChildNodes();
- List logicalNodes = new ArrayList<>();
+ private ServerModel createServerModel(Node serverXMLNode) throws SclParseException {
- String ref;
- if ((ldName != null) && (ldName.length() != 0)) {
- ref = ldName;
- } else {
- ref = iedName + inst;
- }
+ NodeList elements = serverXMLNode.getChildNodes();
+ List logicalDevices = new ArrayList<>(elements.getLength());
- for (int i = 0; i < elements.getLength(); i++) {
- Node element = elements.item(i);
+ for (int i = 0; i < elements.getLength(); i++) {
+ Node element = elements.item(i);
- if (element.getNodeName().equals("LN") || element.getNodeName().equals("LN0")) {
- logicalNodes.add(createNewLogicalNode(element, ref));
- }
- }
+ if (element.getNodeName().equals("LDevice")) {
+ lns = new HashMap<>();
+ logicalDevices.add(createNewLDevice(element));
+ this.logicalDevices.add(createNewLDevice(element));
+ }
+ }
- LogicalDevice lDevice = new LogicalDevice(new ObjectReference(ref), logicalNodes);
+ ServerModel serverModel = new ServerModel(logicalDevices, null);
- return lDevice;
- }
+ dataSetsMap.clear();
- private LogicalNode createNewLogicalNode(Node lnXmlNode, String parentRef)
- throws SclParseException {
+ for (LnSubDef dataSetDef : dataSetDefs) {
+ DataSet dataSet = createDataSet(serverModel, dataSetDef.logicalNode, dataSetDef.defXmlNode);
+ dataSetsMap.put(dataSet.getReferenceStr(), dataSet);
+ }
- // attributes not needed: desc
+ serverModel.addDataSets(dataSetsMap.values());
- String inst = null;
- String lnClass = null;
- String lnType = null;
- String prefix = "";
+ dataSetDefs.clear();
- NamedNodeMap attributes = lnXmlNode.getAttributes();
+ serverModel.setConnectionParam(iedConnectionMap.get(iedName));
+ serverModel.setIedName(iedName);
+ serverModel.setIedManufacturer(iedManufacturer);
+ serverModel.setLns(lns);
+ serverModel.setLnS(lnS);
+ serverModel.setDos(cdcDOMap);
- for (int i = 0; i < attributes.getLength(); i++) {
- Node node = attributes.item(i);
- String nodeName = node.getNodeName();
+ serverModel.setLdsInsts(ldsInsts);
+ serverModel.setLdsRefs(ldsRefs);
+ serverModel.setDescriptions(descMap);
+ serverModel.setdAIDescriptions(daiDescMap);
+ serverModel.setLogicalDevices(logicalDevices);
- if (nodeName.equals("inst")) {
- inst = node.getNodeValue();
- } else if (nodeName.equals("lnType")) {
- lnType = node.getNodeValue();
- } else if (nodeName.equals("lnClass")) {
- lnClass = node.getNodeValue();
- } else if (nodeName.equals("prefix")) {
- prefix = node.getNodeValue();
- }
+ return serverModel;
}
- if (inst == null) {
- throw new SclParseException("Required attribute \"inst\" not found!");
- }
- if (lnType == null) {
- throw new SclParseException("Required attribute \"lnType\" not found!");
- }
- if (lnClass == null) {
- throw new SclParseException("Required attribute \"lnClass\" not found!");
- }
+ private LogicalDevice createNewLDevice(Node ldXmlNode) throws SclParseException {
- String ref = parentRef + '/' + prefix + lnClass + inst;
+ String inst = null;
+ String ldName = null;
- LnType lnTypeDef = typeDefinitions.getLNodeType(lnType);
+ NamedNodeMap attributes = ldXmlNode.getAttributes();
- List dataObjects = new ArrayList<>();
+ for (int i = 0; i < attributes.getLength(); i++) {
+ Node node = attributes.item(i);
+ String nodeName = node.getNodeName();
- if (lnTypeDef == null) {
- throw new SclParseException("LNType " + lnType + " not defined!");
- }
- for (Do dobject : lnTypeDef.dos) {
-
- // look for DOI node with the name of the DO
- Node doiNodeFound = null;
- for (int i = 0; i < lnXmlNode.getChildNodes().getLength(); i++) {
- Node childNode = lnXmlNode.getChildNodes().item(i);
- if ("DOI".equals(childNode.getNodeName())) {
-
- NamedNodeMap doiAttributes = childNode.getAttributes();
- Node nameAttribute = doiAttributes.getNamedItem("name");
- if (nameAttribute != null && nameAttribute.getNodeValue().equals(dobject.getName())) {
- doiNodeFound = childNode;
- }
+ if (nodeName.equals("inst")) {
+ inst = node.getNodeValue();
+ } else if (nodeName.equals("ldName")) {
+ ldName = node.getNodeValue();
+ }
}
- }
- dataObjects.addAll(
- createFcDataObjects(dobject.getName(), ref, dobject.getType(), doiNodeFound));
- }
+ if (inst == null) {
+ throw new SclParseException("Required attribute \"inst\" in logical device not found!");
+ }
- // look for ReportControl
- for (int i = 0; i < lnXmlNode.getChildNodes().getLength(); i++) {
- Node childNode = lnXmlNode.getChildNodes().item(i);
- if ("ReportControl".equals(childNode.getNodeName())) {
- dataObjects.addAll(createReportControlBlocks(childNode, ref));
- }
- }
+ ldsInsts.add(inst);
- LogicalNode lNode = new LogicalNode(new ObjectReference(ref), dataObjects);
+ NodeList elements = ldXmlNode.getChildNodes();
+ List logicalNodes = new ArrayList<>();
- // look for DataSet definitions
- for (int i = 0; i < lnXmlNode.getChildNodes().getLength(); i++) {
- Node childNode = lnXmlNode.getChildNodes().item(i);
- if ("DataSet".equals(childNode.getNodeName())) {
- dataSetDefs.add(new LnSubDef(childNode, lNode));
- }
- }
- return lNode;
- }
+ String ref;
+ if ((ldName != null) && (ldName.length() != 0)) {
+ ref = ldName;
+ ldsRefs.add(ref);
+ } else {
+ ref = iedName + inst;
+ ldsRefs.add(ref);
+ }
+ lnSet = new HashSet<>();
- private DataSet createDataSet(ServerModel serverModel, LogicalNode lNode, Node dsXmlNode)
- throws SclParseException {
+ for (int i = 0; i < elements.getLength(); i++) {
+ Node element = elements.item(i);
- Node nameAttribute = dsXmlNode.getAttributes().getNamedItem("name");
- if (nameAttribute == null) {
- throw new SclParseException("DataSet must have a name");
- }
+ if (element.getNodeName().equals("LN") || element.getNodeName().equals("LN0")) {
+ logicalNodes.add(createNewLogicalNode(element, ref));
+ }
+ }
+ lns.put(ref, lnSet);
- String name = nameAttribute.getNodeValue();
+ LogicalDevice lDevice = new LogicalDevice(new ObjectReference(ref), logicalNodes);
+ lDevice.setLdInst(inst);
- List dsMembers = new ArrayList<>();
+ return lDevice;
+ }
- for (int i = 0; i < dsXmlNode.getChildNodes().getLength(); i++) {
- Node fcdaXmlNode = dsXmlNode.getChildNodes().item(i);
- if ("FCDA".equals(fcdaXmlNode.getNodeName())) {
+ private LogicalNode createNewLogicalNode(Node lnXmlNode, String parentRef)
+ throws SclParseException {
- // For the definition of FCDA see Table 22 part6 ed2
+ // attributes not needed: desc
- String ldInst = null;
- String prefix = "";
+ String inst = null;
String lnClass = null;
- String lnInst = "";
- String doName = "";
- String daName = "";
- Fc fc = null;
-
- NamedNodeMap attributes = fcdaXmlNode.getAttributes();
-
- for (int j = 0; j < attributes.getLength(); j++) {
- Node node = attributes.item(j);
- String nodeName = node.getNodeName();
-
- if (nodeName.equals("ldInst")) {
- ldInst = node.getNodeValue();
- } else if (nodeName.equals("lnInst")) {
- lnInst = node.getNodeValue();
- } else if (nodeName.equals("lnClass")) {
- lnClass = node.getNodeValue();
- } else if (nodeName.equals("prefix")) {
- prefix = node.getNodeValue();
- } else if (nodeName.equals("doName")) {
- doName = node.getNodeValue();
- } else if (nodeName.equals("daName")) {
- if (!node.getNodeValue().isEmpty()) {
- daName = "." + node.getNodeValue();
- }
- } else if (nodeName.equals("fc")) {
- fc = Fc.fromString(node.getNodeValue());
- if (fc == null) {
- throw new SclParseException("FCDA contains invalid FC: " + node.getNodeValue());
+ String lnType = null;
+ String prefix = "";
+
+ NamedNodeMap attributes = lnXmlNode.getAttributes();
+
+ for (int i = 0; i < attributes.getLength(); i++) {
+ Node node = attributes.item(i);
+ String nodeName = node.getNodeName();
+
+ switch (nodeName) {
+ case "inst":
+ inst = node.getNodeValue();
+ break;
+ case "lnType":
+ lnType = node.getNodeValue();
+ break;
+ case "lnClass":
+ lnClass = node.getNodeValue();
+ break;
+ case "prefix":
+ prefix = node.getNodeValue();
+ break;
}
- }
}
- if (ldInst == null) {
- throw new SclParseException(
- "Required attribute \"ldInst\" not found in FCDA: " + nameAttribute + "!");
- }
+ lnSet.add(prefix + lnClass + inst);
- if (lnClass == null) {
- throw new SclParseException("Required attribute \"lnClass\" not found in FCDA!");
+ if (inst == null) {
+ throw new SclParseException("Required attribute \"inst\" not found!");
}
- if (fc == null) {
- throw new SclParseException("Required attribute \"fc\" not found in FCDA!");
+ if (lnType == null) {
+ throw new SclParseException("Required attribute \"lnType\" not found!");
}
- if (!doName.isEmpty()) {
-
- String objectReference =
- iedName + ldInst + "/" + prefix + lnClass + lnInst + "." + doName + daName;
-
- ModelNode fcdaNode = serverModel.findModelNode(objectReference, fc);
-
- if (fcdaNode == null) {
- throw new SclParseException(
- "Specified FCDA: "
- + objectReference
- + " in DataSet: "
- + nameAttribute
- + " not found in Model.");
- }
- dsMembers.add((FcModelNode) fcdaNode);
- } else {
- String objectReference = iedName + ldInst + "/" + prefix + lnClass + lnInst;
- ModelNode logicalNode = serverModel.findModelNode(objectReference, null);
- if (logicalNode == null) {
- throw new SclParseException(
- "Specified FCDA: "
- + objectReference
- + " in DataSet: "
- + nameAttribute
- + " not found in Model.");
- }
- List fcDataObjects = ((LogicalNode) logicalNode).getChildren(fc);
- for (FcDataObject dataObj : fcDataObjects) {
- dsMembers.add(dataObj);
- }
+ if (lnClass == null) {
+ throw new SclParseException("Required attribute \"lnClass\" not found!");
}
- }
- }
- DataSet dataSet = new DataSet(lNode.getReference().toString() + '.' + name, dsMembers, false);
- return dataSet;
- }
+ String ref = parentRef + '/' + prefix + lnClass + inst;
+ lnS.add(ref);
- private List createReportControlBlocks(Node xmlNode, String parentRef)
- throws SclParseException {
+ LnType lnTypeDef = typeDefinitions.getLNodeType(lnType);
- Fc fc = Fc.RP;
- NamedNodeMap rcbNodeAttributes = xmlNode.getAttributes();
- Node attribute = rcbNodeAttributes.getNamedItem("buffered");
- if (attribute != null && "true".equalsIgnoreCase(attribute.getNodeValue())) {
- fc = Fc.BR;
- }
+ List dataObjects = new ArrayList<>();
- Node nameAttribute = rcbNodeAttributes.getNamedItem("name");
- if (nameAttribute == null) {
- throw new SclParseException("Report Control Block has no name attribute.");
- }
+ if (lnTypeDef == null) {
+ throw new SclParseException("LNType " + lnType + " not defined!");
+ }
+ for (Do dobject : lnTypeDef.dos) {
+
+ // look for DOI node with the name of the DO
+ Node doiNodeFound = null;
+ for (int i = 0; i < lnXmlNode.getChildNodes().getLength(); i++) {
+ Node childNode = lnXmlNode.getChildNodes().item(i);
+ if ("DOI".equals(childNode.getNodeName())) {
+
+ NamedNodeMap doiAttributes = childNode.getAttributes();
+ Node nameAttribute = doiAttributes.getNamedItem("name");
+ Node cdcAttribute = doiAttributes.getNamedItem("desc");
+
+ if (cdcAttribute != null) {
+ descMap.put(ref + "." + nameAttribute.getNodeValue(), cdcAttribute.getNodeValue());
+ }
+
+ if (nameAttribute != null && nameAttribute.getNodeValue().equals(dobject.getName())) {
+ doiNodeFound = childNode;
+ }
+ }
+ }
- int maxInstances = 1;
- for (int i = 0; i < xmlNode.getChildNodes().getLength(); i++) {
- Node childNode = xmlNode.getChildNodes().item(i);
-
- if ("RptEnabled".equals(childNode.getNodeName())) {
- Node rptEnabledMaxAttr = childNode.getAttributes().getNamedItem("max");
- if (rptEnabledMaxAttr != null) {
- maxInstances = Integer.parseInt(rptEnabledMaxAttr.getNodeValue());
- if (maxInstances < 1 || maxInstances > 99) {
- throw new SclParseException(
- "Report Control Block max instances should be between 1 and 99 but is: "
- + maxInstances);
- }
+ dataObjects.addAll(
+ createFcDataObjects(dobject.getName(), ref, dobject.getType(), doiNodeFound, dobject.getType()));
}
- }
- }
- List rcbInstances = new ArrayList<>(maxInstances);
+ // look for ReportControl
+ for (int i = 0; i < lnXmlNode.getChildNodes().getLength(); i++) {
+ Node childNode = lnXmlNode.getChildNodes().item(i);
+ if ("ReportControl".equals(childNode.getNodeName())) {
+ dataObjects.addAll(createReportControlBlocks(childNode, ref));
+ }
+ }
- for (int z = 1; z <= maxInstances; z++) {
+ LogicalNode lNode = new LogicalNode(new ObjectReference(ref), dataObjects);
- ObjectReference reportObjRef;
+ // look for DataSet definitions
+ for (int i = 0; i < lnXmlNode.getChildNodes().getLength(); i++) {
+ Node childNode = lnXmlNode.getChildNodes().item(i);
+ if ("DataSet".equals(childNode.getNodeName())) {
+ dataSetDefs.add(new LnSubDef(childNode, lNode));
+ }
+ }
- if (maxInstances == 1) {
+ lNode.setPrefix(prefix);
+ lNode.setLnClass(lnClass);
+ lNode.setLnInst(inst);
+ lNode.setLnType(lnType);
- reportObjRef = new ObjectReference(parentRef + "." + nameAttribute.getNodeValue());
- } else {
- reportObjRef =
- new ObjectReference(
- parentRef + "." + nameAttribute.getNodeValue() + String.format("%02d", z));
- }
+ return lNode;
+ }
- BdaTriggerConditions trigOps =
- new BdaTriggerConditions(new ObjectReference(reportObjRef + ".TrgOps"), fc);
- BdaOptFlds optFields = new BdaOptFlds(new ObjectReference(reportObjRef + ".OptFlds"), fc);
- for (int i = 0; i < xmlNode.getChildNodes().getLength(); i++) {
- Node childNode = xmlNode.getChildNodes().item(i);
- if (childNode.getNodeName().equals("TrgOps")) {
+ private DataSet createDataSet(ServerModel serverModel, LogicalNode lNode, Node dsXmlNode)
+ throws SclParseException {
- NamedNodeMap attributes = childNode.getAttributes();
+ Node nameAttribute = dsXmlNode.getAttributes().getNamedItem("name");
+ if (nameAttribute == null) {
+ throw new SclParseException("DataSet must have a name");
+ }
- if (attributes != null) {
- for (int j = 0; j < attributes.getLength(); j++) {
- Node node = attributes.item(j);
- String nodeName = node.getNodeName();
+ String name = nameAttribute.getNodeValue();
+
+ List dsMembers = new ArrayList<>();
+
+ for (int i = 0; i < dsXmlNode.getChildNodes().getLength(); i++) {
+ Node fcdaXmlNode = dsXmlNode.getChildNodes().item(i);
+ if ("FCDA".equals(fcdaXmlNode.getNodeName())) {
+
+ // For the definition of FCDA see Table 22 part6 ed2
+
+ String ldInst = null;
+ String prefix = "";
+ String lnClass = null;
+ String lnInst = "";
+ String doName = "";
+ String daName = "";
+ Fc fc = null;
+
+ NamedNodeMap attributes = fcdaXmlNode.getAttributes();
+
+ for (int j = 0; j < attributes.getLength(); j++) {
+ Node node = attributes.item(j);
+ String nodeName = node.getNodeName();
+
+ switch (nodeName) {
+ case "ldInst":
+ ldInst = node.getNodeValue();
+ break;
+ case "lnInst":
+ lnInst = node.getNodeValue();
+ break;
+ case "lnClass":
+ lnClass = node.getNodeValue();
+ break;
+ case "prefix":
+ prefix = node.getNodeValue();
+ break;
+ case "doName":
+ doName = node.getNodeValue();
+ break;
+ case "daName":
+ if (!node.getNodeValue().isEmpty()) {
+ daName = "." + node.getNodeValue();
+ }
+ break;
+ case "fc":
+ fc = Fc.fromString(node.getNodeValue());
+ if (fc == null) {
+ throw new SclParseException("FCDA contains invalid FC: " + node.getNodeValue());
+ }
+ break;
+ }
+ }
+
+ if (ldInst == null) {
+ throw new SclParseException(
+ "Required attribute \"ldInst\" not found in FCDA: " + nameAttribute + "!");
+ }
+
+ if (lnClass == null) {
+ throw new SclParseException("Required attribute \"lnClass\" not found in FCDA!");
+ }
+ if (fc == null) {
+ throw new SclParseException("Required attribute \"fc\" not found in FCDA!");
+ }
+ if (!doName.isEmpty()) {
+
+ String objectReference =
+ iedName + ldInst + "/" + prefix + lnClass + lnInst + "." + doName + daName;
+
+ ModelNode fcdaNode = serverModel.findModelNode(objectReference, fc);
+
+ if (fcdaNode == null) {
+ throw new SclParseException(
+ "Specified FCDA: "
+ + objectReference
+ + " in DataSet: "
+ + nameAttribute
+ + " not found in Model.");
+ }
+ dsMembers.add((FcModelNode) fcdaNode);
+ } else {
+ String objectReference = iedName + ldInst + "/" + prefix + lnClass + lnInst;
+ ModelNode logicalNode = serverModel.findModelNode(objectReference, null);
+ if (logicalNode == null) {
+ throw new SclParseException(
+ "Specified FCDA: "
+ + objectReference
+ + " in DataSet: "
+ + nameAttribute
+ + " not found in Model.");
+ }
+ List fcDataObjects = ((LogicalNode) logicalNode).getChildren(fc);
+ for (FcDataObject dataObj : fcDataObjects) {
+ dsMembers.add(dataObj);
+ }
+ }
+ }
+ }
- if ("dchg".equals(nodeName)) {
- trigOps.setDataChange(node.getNodeValue().equalsIgnoreCase("true"));
- } else if ("qchg".equals(nodeName)) {
- trigOps.setQualityChange(node.getNodeValue().equalsIgnoreCase("true"));
+ return new DataSet(lNode.getReference().toString() + '.' + name, dsMembers, false);
+ }
- } else if ("dupd".equals(nodeName)) {
- trigOps.setDataUpdate(node.getNodeValue().equalsIgnoreCase("true"));
+ private List createReportControlBlocks(Node xmlNode, String parentRef)
+ throws SclParseException {
- } else if ("period".equals(nodeName)) {
- trigOps.setIntegrity(node.getNodeValue().equalsIgnoreCase("true"));
+ Fc fc = Fc.RP;
+ NamedNodeMap rcbNodeAttributes = xmlNode.getAttributes();
+ Node attribute = rcbNodeAttributes.getNamedItem("buffered");
+ if (attribute != null && "true".equalsIgnoreCase(attribute.getNodeValue())) {
+ fc = Fc.BR;
+ }
- } else if ("gi".equals(nodeName)) {
- trigOps.setGeneralInterrogation(node.getNodeValue().equalsIgnoreCase("true"));
- }
- }
- }
- } else if ("OptFields".equals(childNode.getNodeName())) {
-
- NamedNodeMap attributes = childNode.getAttributes();
-
- if (attributes != null) {
- for (int j = 0; j < attributes.getLength(); j++) {
-
- Node node = attributes.item(j);
- String nodeName = node.getNodeName();
-
- if ("seqNum".equals(nodeName)) {
- optFields.setSequenceNumber(node.getNodeValue().equalsIgnoreCase("true"));
- } else if ("timeStamp".equals(nodeName)) {
- optFields.setReportTimestamp(node.getNodeValue().equalsIgnoreCase("true"));
-
- } else if ("reasonCode".equals(nodeName)) {
- optFields.setReasonForInclusion(node.getNodeValue().equalsIgnoreCase("true"));
-
- } else if ("dataSet".equals(nodeName)) {
- optFields.setDataSetName(node.getNodeValue().equalsIgnoreCase("true"));
-
- }
- // not supported for now
- // else if (nodeName.equals("dataRef")) {
- // optFields.setDataReference(node.getNodeValue().equals("true"));
- //
- // }
- else if (nodeName.equals("bufOvfl")) {
- optFields.setBufferOverflow(node.getNodeValue().equalsIgnoreCase("true"));
-
- } else if (nodeName.equals("entryID")) {
- optFields.setEntryId(node.getNodeValue().equalsIgnoreCase("true"));
- }
- // not supported for now:
- // else if (nodeName.equals("configRef")) {
- // optFields.setConfigRevision(node.getNodeValue().equals("true"));
- // }
- }
- }
- } else if ("RptEnabled".equals(childNode.getNodeName())) {
- Node rptEnabledMaxAttr = childNode.getAttributes().getNamedItem("max");
- if (rptEnabledMaxAttr != null) {
- maxInstances = Integer.parseInt(rptEnabledMaxAttr.getNodeValue());
- if (maxInstances < 1 || maxInstances > 99) {
- throw new SclParseException(
- "Report Control Block max instances should be between 1 and 99 but is: "
- + maxInstances);
- }
- }
+ Node nameAttribute = rcbNodeAttributes.getNamedItem("name");
+ if (nameAttribute == null) {
+ throw new SclParseException("Report Control Block has no name attribute.");
}
- }
-
- if (fc == Fc.RP) {
- optFields.setEntryId(false);
- optFields.setBufferOverflow(false);
- }
-
- List children = new ArrayList<>();
-
- BdaVisibleString rptId =
- new BdaVisibleString(
- new ObjectReference(reportObjRef.toString() + ".RptID"), fc, "", 129, false, false);
- attribute = rcbNodeAttributes.getNamedItem("rptID");
- if (attribute != null) {
- rptId.setValue(attribute.getNodeValue().getBytes(UTF_8));
- } else {
- rptId.setValue(reportObjRef.toString());
- }
-
- children.add(rptId);
-
- children.add(
- new BdaBoolean(
- new ObjectReference(reportObjRef.toString() + ".RptEna"), fc, "", false, false));
-
- if (fc == Fc.RP) {
- children.add(
- new BdaBoolean(
- new ObjectReference(reportObjRef.toString() + ".Resv"), fc, "", false, false));
- }
-
- BdaVisibleString datSet =
- new BdaVisibleString(
- new ObjectReference(reportObjRef.toString() + ".DatSet"), fc, "", 129, false, false);
-
- attribute = xmlNode.getAttributes().getNamedItem("datSet");
- if (attribute != null) {
- String nodeValue = attribute.getNodeValue();
- String dataSetName = parentRef + "$" + nodeValue;
- datSet.setValue(dataSetName.getBytes(UTF_8));
- }
- children.add(datSet);
-
- BdaInt32U confRef =
- new BdaInt32U(
- new ObjectReference(reportObjRef.toString() + ".ConfRev"), fc, "", false, false);
- attribute = xmlNode.getAttributes().getNamedItem("confRev");
- if (attribute == null) {
- throw new SclParseException(
- "Report Control Block does not contain mandatory attribute confRev");
- }
- confRef.setValue(Long.parseLong(attribute.getNodeValue()));
- children.add(confRef);
-
- children.add(optFields);
-
- BdaInt32U bufTm =
- new BdaInt32U(
- new ObjectReference(reportObjRef.toString() + ".BufTm"), fc, "", false, false);
- attribute = xmlNode.getAttributes().getNamedItem("bufTime");
- if (attribute != null) {
- bufTm.setValue(Long.parseLong(attribute.getNodeValue()));
- }
- children.add(bufTm);
-
- children.add(
- new BdaInt8U(
- new ObjectReference(reportObjRef.toString() + ".SqNum"), fc, "", false, false));
-
- children.add(trigOps);
-
- BdaInt32U intgPd =
- new BdaInt32U(
- new ObjectReference(reportObjRef.toString() + ".IntgPd"), fc, "", false, false);
- attribute = xmlNode.getAttributes().getNamedItem("intgPd");
- if (attribute != null) {
- intgPd.setValue(Long.parseLong(attribute.getNodeValue()));
- }
- children.add(intgPd);
-
- children.add(
- new BdaBoolean(
- new ObjectReference(reportObjRef.toString() + ".GI"), fc, "", false, false));
-
- Rcb rcb = null;
-
- if (fc == Fc.BR) {
-
- children.add(
- new BdaBoolean(
- new ObjectReference(reportObjRef.toString() + ".PurgeBuf"), fc, "", false, false));
-
- children.add(
- new BdaOctetString(
- new ObjectReference(reportObjRef.toString() + ".EntryID"),
- fc,
- "",
- 8,
- false,
- false));
-
- children.add(
- new BdaEntryTime(
- new ObjectReference(reportObjRef.toString() + ".TimeOfEntry"),
- fc,
- "",
- false,
- false));
-
- if (useResvTmsAttributes) {
- children.add(
- new BdaInt16(
- new ObjectReference(reportObjRef.toString() + ".ResvTms"), fc, "", false, false));
+
+ int maxInstances = 1;
+ for (int i = 0; i < xmlNode.getChildNodes().getLength(); i++) {
+ Node childNode = xmlNode.getChildNodes().item(i);
+
+ if ("RptEnabled".equals(childNode.getNodeName())) {
+ Node rptEnabledMaxAttr = childNode.getAttributes().getNamedItem("max");
+ if (rptEnabledMaxAttr != null) {
+ maxInstances = Integer.parseInt(rptEnabledMaxAttr.getNodeValue());
+ if (maxInstances < 1 || maxInstances > 99) {
+ throw new SclParseException(
+ "Report Control Block max instances should be between 1 and 99 but is: "
+ + maxInstances);
+ }
+ }
+ }
}
- children.add(
- new BdaOctetString(
- new ObjectReference(reportObjRef.toString() + ".Owner"), fc, "", 64, false, false));
+ List rcbInstances = new ArrayList<>(maxInstances);
- rcb = new Brcb(reportObjRef, children);
+ for (int z = 1; z <= maxInstances; z++) {
- } else {
- children.add(
- new BdaOctetString(
- new ObjectReference(reportObjRef.toString() + ".Owner"), fc, "", 64, false, false));
+ ObjectReference reportObjRef;
- rcb = new Urcb(reportObjRef, children);
- }
+ if (maxInstances == 1) {
- rcbInstances.add(rcb);
- }
+ reportObjRef = new ObjectReference(parentRef + "." + nameAttribute.getNodeValue());
+ } else {
+ reportObjRef =
+ new ObjectReference(
+ parentRef + "." + nameAttribute.getNodeValue() + String.format("%02d", z));
+ }
- return rcbInstances;
- }
+ BdaTriggerConditions trigOps =
+ new BdaTriggerConditions(new ObjectReference(reportObjRef + ".TrgOps"), fc);
+ BdaOptFlds optFields = new BdaOptFlds(new ObjectReference(reportObjRef + ".OptFlds"), fc);
+ for (int i = 0; i < xmlNode.getChildNodes().getLength(); i++) {
+ Node childNode = xmlNode.getChildNodes().item(i);
+ if (childNode.getNodeName().equals("TrgOps")) {
+
+ NamedNodeMap attributes = childNode.getAttributes();
+
+ if (attributes != null) {
+ for (int j = 0; j < attributes.getLength(); j++) {
+ Node node = attributes.item(j);
+ String nodeName = node.getNodeName();
+
+ if ("dchg".equals(nodeName)) {
+ trigOps.setDataChange(node.getNodeValue().equalsIgnoreCase("true"));
+ } else if ("qchg".equals(nodeName)) {
+ trigOps.setQualityChange(node.getNodeValue().equalsIgnoreCase("true"));
+
+ } else if ("dupd".equals(nodeName)) {
+ trigOps.setDataUpdate(node.getNodeValue().equalsIgnoreCase("true"));
+
+ } else if ("period".equals(nodeName)) {
+ trigOps.setIntegrity(node.getNodeValue().equalsIgnoreCase("true"));
+
+ } else if ("gi".equals(nodeName)) {
+ trigOps.setGeneralInterrogation(node.getNodeValue().equalsIgnoreCase("true"));
+ }
+ }
+ }
+ } else if ("OptFields".equals(childNode.getNodeName())) {
+
+ NamedNodeMap attributes = childNode.getAttributes();
+
+ if (attributes != null) {
+ for (int j = 0; j < attributes.getLength(); j++) {
+
+ Node node = attributes.item(j);
+ String nodeName = node.getNodeName();
+
+ if ("seqNum".equals(nodeName)) {
+ optFields.setSequenceNumber(node.getNodeValue().equalsIgnoreCase("true"));
+ } else if ("timeStamp".equals(nodeName)) {
+ optFields.setReportTimestamp(node.getNodeValue().equalsIgnoreCase("true"));
+
+ } else if ("reasonCode".equals(nodeName)) {
+ optFields.setReasonForInclusion(node.getNodeValue().equalsIgnoreCase("true"));
+
+ } else if ("dataSet".equals(nodeName)) {
+ optFields.setDataSetName(node.getNodeValue().equalsIgnoreCase("true"));
+
+ }
+ // not supported for now
+ // else if (nodeName.equals("dataRef")) {
+ // optFields.setDataReference(node.getNodeValue().equals("true"));
+ //
+ // }
+ else if (nodeName.equals("bufOvfl")) {
+ optFields.setBufferOverflow(node.getNodeValue().equalsIgnoreCase("true"));
+
+ } else if (nodeName.equals("entryID")) {
+ optFields.setEntryId(node.getNodeValue().equalsIgnoreCase("true"));
+ }
+ // not supported for now:
+ // else if (nodeName.equals("configRef")) {
+ // optFields.setConfigRevision(node.getNodeValue().equals("true"));
+ // }
+ }
+ }
+ } else if ("RptEnabled".equals(childNode.getNodeName())) {
+ Node rptEnabledMaxAttr = childNode.getAttributes().getNamedItem("max");
+ if (rptEnabledMaxAttr != null) {
+ maxInstances = Integer.parseInt(rptEnabledMaxAttr.getNodeValue());
+ if (maxInstances < 1 || maxInstances > 99) {
+ throw new SclParseException(
+ "Report Control Block max instances should be between 1 and 99 but is: "
+ + maxInstances);
+ }
+ }
+ }
+ }
- private List createFcDataObjects(
- String name, String parentRef, String doTypeID, Node doiNode) throws SclParseException {
+ if (fc == Fc.RP) {
+ optFields.setEntryId(false);
+ optFields.setBufferOverflow(false);
+ }
- DoType doType = typeDefinitions.getDOType(doTypeID);
+ List children = new ArrayList<>();
- if (doType == null) {
- throw new SclParseException("DO type " + doTypeID + " not defined!");
- }
+ BdaVisibleString rptId =
+ new BdaVisibleString(
+ new ObjectReference(reportObjRef + ".RptID"), fc, "", 129, false, false);
+ attribute = rcbNodeAttributes.getNamedItem("rptID");
+ if (attribute != null) {
+ rptId.setValue(attribute.getNodeValue().getBytes(UTF_8));
+ } else {
+ rptId.setValue(reportObjRef.toString());
+ }
- String ref = parentRef + '.' + name;
+ children.add(rptId);
- List childNodes = new ArrayList<>();
+ children.add(
+ new BdaBoolean(
+ new ObjectReference(reportObjRef + ".RptEna"), fc, "", false, false));
- for (Da dattr : doType.das) {
+ if (fc == Fc.RP) {
+ children.add(
+ new BdaBoolean(
+ new ObjectReference(reportObjRef + ".Resv"), fc, "", false, false));
+ }
- // look for DAI node with the name of the DA
- Node iNodeFound = findINode(doiNode, dattr.getName());
+ BdaVisibleString datSet =
+ new BdaVisibleString(
+ new ObjectReference(reportObjRef + ".DatSet"), fc, "", 129, false, false);
- if (dattr.getCount() >= 1) {
- childNodes.add(createArrayOfDataAttributes(ref + '.' + dattr.getName(), dattr, iNodeFound));
- } else {
- childNodes.add(
- createDataAttribute(
- ref + '.' + dattr.getName(),
- dattr.getFc(),
- dattr,
- iNodeFound,
- false,
- false,
- false));
- }
- }
+ attribute = xmlNode.getAttributes().getNamedItem("datSet");
+ if (attribute != null) {
+ String nodeValue = attribute.getNodeValue();
+ String dataSetName = parentRef + "$" + nodeValue;
+ datSet.setValue(dataSetName.getBytes(UTF_8));
+ }
+ children.add(datSet);
+
+ BdaInt32U confRef =
+ new BdaInt32U(
+ new ObjectReference(reportObjRef + ".ConfRev"), fc, "", false, false);
+ attribute = xmlNode.getAttributes().getNamedItem("confRev");
+ if (attribute == null) {
+ throw new SclParseException(
+ "Report Control Block does not contain mandatory attribute confRev");
+ }
+ confRef.setValue(Long.parseLong(attribute.getNodeValue()));
+ children.add(confRef);
- for (Sdo sdo : doType.sdos) {
+ children.add(optFields);
- // parsing Arrays of SubDataObjects is ignored for now because no SCL file was found to test
- // against. The
- // only DO that contains an Array of SDOs is Harmonic Value (HMV). The Kalkitech SCL Manager
- // handles the
- // array of SDOs in HMV as an array of DAs.
+ BdaInt32U bufTm =
+ new BdaInt32U(
+ new ObjectReference(reportObjRef + ".BufTm"), fc, "", false, false);
+ attribute = xmlNode.getAttributes().getNamedItem("bufTime");
+ if (attribute != null) {
+ bufTm.setValue(Long.parseLong(attribute.getNodeValue()));
+ }
+ children.add(bufTm);
- Node iNodeFound = findINode(doiNode, sdo.getName());
+ children.add(
+ new BdaInt8U(
+ new ObjectReference(reportObjRef + ".SqNum"), fc, "", false, false));
- childNodes.addAll(createFcDataObjects(sdo.getName(), ref, sdo.getType(), iNodeFound));
- }
+ children.add(trigOps);
- Map> subFCDataMap = new LinkedHashMap<>();
+ BdaInt32U intgPd =
+ new BdaInt32U(
+ new ObjectReference(reportObjRef + ".IntgPd"), fc, "", false, false);
+ attribute = xmlNode.getAttributes().getNamedItem("intgPd");
+ if (attribute != null) {
+ intgPd.setValue(Long.parseLong(attribute.getNodeValue()));
+ }
+ children.add(intgPd);
+
+ children.add(
+ new BdaBoolean(
+ new ObjectReference(reportObjRef + ".GI"), fc, "", false, false));
+
+ Rcb rcb;
+
+ if (fc == Fc.BR) {
+
+ children.add(
+ new BdaBoolean(
+ new ObjectReference(reportObjRef + ".PurgeBuf"), fc, "", false, false));
+
+ children.add(
+ new BdaOctetString(
+ new ObjectReference(reportObjRef + ".EntryID"),
+ fc,
+ "",
+ 8,
+ false,
+ false));
+
+ children.add(
+ new BdaEntryTime(
+ new ObjectReference(reportObjRef + ".TimeOfEntry"),
+ fc,
+ "",
+ false,
+ false));
+
+ if (useResvTmsAttributes) {
+ children.add(
+ new BdaInt16(
+ new ObjectReference(reportObjRef + ".ResvTms"), fc, "", false, false));
+ }
+
+ children.add(
+ new BdaOctetString(
+ new ObjectReference(reportObjRef + ".Owner"), fc, "", 64, false, false));
+
+ rcb = new Brcb(reportObjRef, children);
+
+ } else {
+ children.add(
+ new BdaOctetString(
+ new ObjectReference(reportObjRef + ".Owner"), fc, "", 64, false, false));
+
+ rcb = new Urcb(reportObjRef, children);
+ }
- for (Fc fc : Fc.values()) {
- subFCDataMap.put(fc, new ArrayList<>());
- }
+ rcbInstances.add(rcb);
+ }
- for (ModelNode childNode : childNodes) {
- subFCDataMap.get(((FcModelNode) childNode).getFc()).add((FcModelNode) childNode);
+ return rcbInstances;
}
- List fcDataObjects = new ArrayList<>();
- ObjectReference objectReference = new ObjectReference(ref);
+ private List createFcDataObjects(
+ String name, String parentRef, String doTypeID, Node doiNode, String type) throws SclParseException {
- for (Fc fc : Fc.values()) {
- if (subFCDataMap.get(fc).size() > 0) {
- fcDataObjects.add(new FcDataObject(objectReference, fc, subFCDataMap.get(fc)));
- }
- }
+ DoType doType = typeDefinitions.getDOType(doTypeID);
- return fcDataObjects;
- }
+ if (doType == null) {
+ throw new SclParseException("DO type " + doTypeID + " not defined!");
+ }
- private Node findINode(Node iNode, String dattrName) {
+ String ref = parentRef + '.' + name;
- if (iNode == null) {
- return null;
- }
+ String cdc = doType.getCdc();
- for (int i = 0; i < iNode.getChildNodes().getLength(); i++) {
- Node childNode = iNode.getChildNodes().item(i);
- if (childNode.getAttributes() != null) {
- Node nameAttribute = childNode.getAttributes().getNamedItem("name");
- if (nameAttribute != null && nameAttribute.getNodeValue().equals(dattrName)) {
- return childNode;
- }
- }
- }
- return null;
- }
-
- private Array createArrayOfDataAttributes(String ref, Da dataAttribute, Node iXmlNode)
- throws SclParseException {
-
- Fc fc = dataAttribute.getFc();
- int size = dataAttribute.getCount();
-
- List arrayItems = new ArrayList<>();
- for (int i = 0; i < size; i++) {
- // TODO go down the iXmlNode using the ix attribute?
- arrayItems.add(
- createDataAttribute(
- ref + '(' + i + ')',
- fc,
- dataAttribute,
- iXmlNode,
- dataAttribute.isDchg(),
- dataAttribute.isDupd(),
- dataAttribute.isQchg()));
- }
+ cdcDOMap.put(ref, cdc);
- return new Array(new ObjectReference(ref), fc, arrayItems);
- }
-
- /** returns a ConstructedDataAttribute or BasicDataAttribute */
- private FcModelNode createDataAttribute(
- String ref,
- Fc fc,
- AbstractDataAttribute dattr,
- Node iXmlNode,
- boolean dchg,
- boolean dupd,
- boolean qchg)
- throws SclParseException {
-
- if (dattr instanceof Da) {
- Da dataAttribute = (Da) dattr;
- dchg = dataAttribute.isDchg();
- dupd = dataAttribute.isDupd();
- qchg = dataAttribute.isQchg();
- }
+ List childNodes = new ArrayList<>();
- String bType = dattr.getbType();
+ for (Da dattr : doType.das) {
- if (bType.equals("Struct")) {
- DaType datype = typeDefinitions.getDaType(dattr.getType());
+ // look for DAI node with the name of the DA
+ Node iNodeFound = findINode(doiNode, dattr.getName());
- if (datype == null) {
- throw new SclParseException("DAType " + dattr.getbType() + " not declared!");
- }
+ if (iNodeFound != null) {
+ NamedNodeMap daiAttributes = iNodeFound.getAttributes();
+ if (daiAttributes != null) {
+ Node nameAttribute = daiAttributes.getNamedItem("name");
+ Node cdcAttribute = daiAttributes.getNamedItem("desc");
- List subDataAttributes = new ArrayList<>();
- for (Bda bda : datype.bdas) {
+ if (cdcAttribute != null) {
+ daiDescMap.put(ref + "." + nameAttribute.getNodeValue(), cdcAttribute.getNodeValue());
+ }
+ }
+ }
- Node iNodeFound = findINode(iXmlNode, bda.getName());
+ if (dattr.getCount() >= 1) {
+ childNodes.add(createArrayOfDataAttributes(ref + '.' + dattr.getName(), dattr, iNodeFound));
+ } else {
+ FcModelNode fcModelNode =
+ createDataAttribute(
+ ref + '.' + dattr.getName(),
+ dattr.getFc(),
+ dattr,
+ iNodeFound,
+ false,
+ false,
+ false
+ );
+
+ fcModelNode.setbType(dattr.getbType());
+ fcModelNode.setDaType(dattr.getType());
+ childNodes.add(fcModelNode);
+ }
+ }
- subDataAttributes.add(
- createDataAttribute(ref + '.' + bda.getName(), fc, bda, iNodeFound, dchg, dupd, qchg));
- }
- return new ConstructedDataAttribute(new ObjectReference(ref), fc, subDataAttributes);
- }
+ for (Sdo sdo : doType.sdos) {
- String val = null;
- String sAddr = null;
- if (iXmlNode != null) {
- NamedNodeMap attributeMap = iXmlNode.getAttributes();
- Node sAddrAttribute = attributeMap.getNamedItem("sAddr");
- if (sAddrAttribute != null) {
- sAddr = sAddrAttribute.getNodeValue();
- }
-
- NodeList elements = iXmlNode.getChildNodes();
- for (int i = 0; i < elements.getLength(); i++) {
- Node node = elements.item(i);
- if (node.getNodeName().equals("Val")) {
- val = node.getTextContent();
- }
- }
- if (val == null) {
- // insert value from DA element
- val = dattr.value;
- }
- }
+ // parsing Arrays of SubDataObjects is ignored for now because no SCL file was found to test
+ // against. The
+ // only DO that contains an Array of SDOs is Harmonic Value (HMV). The Kalkitech SCL Manager
+ // handles the
+ // array of SDOs in HMV as an array of DAs.
- if (bType.equals("BOOLEAN")) {
- BdaBoolean bda = new BdaBoolean(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- if (val.equalsIgnoreCase("true") || val.equals("1")) {
- bda.setValue(true);
- } else if (val.equalsIgnoreCase("false") || val.equals("0")) {
- bda.setValue(false);
- } else {
- throw new SclParseException("invalid boolean configured value: " + val);
- }
- }
- return bda;
- } else if (bType.equals("INT8")) {
- BdaInt8 bda = new BdaInt8(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- try {
- bda.setValue(Byte.parseByte(val));
- } catch (NumberFormatException e) {
- throw new SclParseException("invalid INT8 configured value: " + val);
- }
- }
- return bda;
- } else if (bType.equals("INT16")) {
- BdaInt16 bda = new BdaInt16(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- try {
- bda.setValue(Short.parseShort(val));
- } catch (NumberFormatException e) {
- throw new SclParseException("invalid INT16 configured value: " + val);
+ Node iNodeFound = findINode(doiNode, sdo.getName());
+
+ childNodes.addAll(createFcDataObjects(sdo.getName(), ref, sdo.getType(), iNodeFound, type));
}
- }
- return bda;
- } else if (bType.equals("INT32")) {
- BdaInt32 bda = new BdaInt32(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- try {
- bda.setValue(Integer.parseInt(val));
- } catch (NumberFormatException e) {
- throw new SclParseException("invalid INT32 configured value: " + val);
+
+ Map> subFCDataMap = new LinkedHashMap<>();
+
+ for (Fc fc : Fc.values()) {
+ subFCDataMap.put(fc, new ArrayList<>());
}
- }
- return bda;
- } else if (bType.equals("INT64")) {
- BdaInt64 bda = new BdaInt64(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- try {
- bda.setValue(Long.parseLong(val));
- } catch (NumberFormatException e) {
- throw new SclParseException("invalid INT64 configured value: " + val);
+
+ for (ModelNode childNode : childNodes) {
+ subFCDataMap.get(((FcModelNode) childNode).getFc()).add((FcModelNode) childNode);
}
- }
- return bda;
- } else if (bType.equals("INT128")) {
- BdaInt128 bda = new BdaInt128(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- try {
- bda.setValue(Long.parseLong(val));
- } catch (NumberFormatException e) {
- throw new SclParseException("invalid INT128 configured value: " + val);
+
+ List fcDataObjects = new ArrayList<>();
+ ObjectReference objectReference = new ObjectReference(ref);
+
+ for (Fc fc : Fc.values()) {
+ if (subFCDataMap.get(fc).size() > 0) {
+ FcDataObject fcDataObject = new FcDataObject(objectReference, fc, subFCDataMap.get(fc));
+ fcDataObject.setDoType(type);
+ fcDataObject.setCdc(cdc);
+ fcDataObjects.add(fcDataObject);
+ }
}
- }
- return bda;
- } else if (bType.equals("INT8U")) {
- BdaInt8U bda = new BdaInt8U(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- try {
- bda.setValue(Short.parseShort(val));
- } catch (NumberFormatException e) {
- throw new SclParseException("invalid INT8U configured value: " + val);
+
+ return fcDataObjects;
+ }
+
+ private Node findINode(Node iNode, String dattrName) {
+
+ if (iNode == null) {
+ return null;
}
- }
- return bda;
- } else if (bType.equals("INT16U")) {
- BdaInt16U bda = new BdaInt16U(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- try {
- bda.setValue(Integer.parseInt(val));
- } catch (NumberFormatException e) {
- throw new SclParseException("invalid INT16U configured value: " + val);
+
+ for (int i = 0; i < iNode.getChildNodes().getLength(); i++) {
+ Node childNode = iNode.getChildNodes().item(i);
+ if (childNode.getAttributes() != null) {
+ Node nameAttribute = childNode.getAttributes().getNamedItem("name");
+ if (nameAttribute != null && nameAttribute.getNodeValue().equals(dattrName)) {
+ return childNode;
+ }
+ }
}
- }
- return bda;
- } else if (bType.equals("INT32U")) {
- BdaInt32U bda = new BdaInt32U(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- try {
- bda.setValue(Long.parseLong(val));
- } catch (NumberFormatException e) {
- throw new SclParseException("invalid INT32U configured value: " + val);
+ return null;
+ }
+
+ private Array createArrayOfDataAttributes(String ref, Da dataAttribute, Node iXmlNode)
+ throws SclParseException {
+
+ Fc fc = dataAttribute.getFc();
+ int size = dataAttribute.getCount();
+
+ List arrayItems = new ArrayList<>();
+ for (int i = 0; i < size; i++) {
+ // TODO go down the iXmlNode using the ix attribute?
+ arrayItems.add(
+ createDataAttribute(
+ ref + '(' + i + ')',
+ fc,
+ dataAttribute,
+ iXmlNode,
+ dataAttribute.isDchg(),
+ dataAttribute.isDupd(),
+ dataAttribute.isQchg()));
}
- }
- return bda;
- } else if (bType.equals("FLOAT32")) {
- BdaFloat32 bda = new BdaFloat32(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- try {
- bda.setFloat(Float.parseFloat(val));
- } catch (NumberFormatException e) {
- throw new SclParseException("invalid FLOAT32 configured value: " + val);
+
+ return new Array(new ObjectReference(ref), fc, arrayItems);
+ }
+
+ /**
+ * returns a ConstructedDataAttribute or BasicDataAttribute
+ */
+ private FcModelNode createDataAttribute(
+ String ref,
+ Fc fc,
+ AbstractDataAttribute dattr,
+ Node iXmlNode,
+ boolean dchg,
+ boolean dupd,
+ boolean qchg)
+ throws SclParseException {
+
+ if (dattr instanceof Da) {
+ Da dataAttribute = (Da) dattr;
+ dchg = dataAttribute.isDchg();
+ dupd = dataAttribute.isDupd();
+ qchg = dataAttribute.isQchg();
}
- }
- return bda;
- } else if (bType.equals("FLOAT64")) {
- BdaFloat64 bda = new BdaFloat64(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- try {
- bda.setDouble(Double.parseDouble(val));
- } catch (NumberFormatException e) {
- throw new SclParseException("invalid FLOAT64 configured value: " + val);
+
+ String bType = dattr.getbType();
+
+ if (bType.equals("Struct")) {
+ DaType datype = typeDefinitions.getDaType(dattr.getType());
+
+ if (datype == null) {
+ throw new SclParseException("DAType " + dattr.getbType() + " not declared!");
+ }
+
+ List subDataAttributes = new ArrayList<>();
+ for (Bda bda : datype.bdas) {
+
+ Node iNodeFound = findINode(iXmlNode, bda.getName());
+
+ FcModelNode fcModelNode = createDataAttribute(ref + '.' + bda.getName(), fc, bda, iNodeFound, dchg, dupd, qchg);
+ fcModelNode.setDaType(bda.getType());
+ fcModelNode.setbType(bda.getbType());
+
+ subDataAttributes.add(fcModelNode);
+ }
+ return new ConstructedDataAttribute(new ObjectReference(ref), fc, subDataAttributes);
}
- }
- return bda;
- } else if (bType.startsWith("VisString")) {
- BdaVisibleString bda =
- new BdaVisibleString(
- new ObjectReference(ref),
- fc,
- sAddr,
- Integer.parseInt(dattr.getbType().substring(9)),
- dchg,
- dupd);
- if (val != null) {
- bda.setValue(val.getBytes(UTF_8));
- }
- return bda;
- } else if (bType.startsWith("Unicode")) {
- BdaUnicodeString bda =
- new BdaUnicodeString(
- new ObjectReference(ref),
- fc,
- sAddr,
- Integer.parseInt(dattr.getbType().substring(7)),
- dchg,
- dupd);
- if (val != null) {
- bda.setValue(val.getBytes(UTF_8));
- }
- return bda;
- } else if (bType.startsWith("Octet")) {
- BdaOctetString bda =
- new BdaOctetString(
- new ObjectReference(ref),
- fc,
- sAddr,
- Integer.parseInt(dattr.getbType().substring(5)),
- dchg,
- dupd);
- if (val != null) {
- // TODO
- // throw new SclParseException("parsing configured value for octet string is not supported
- // yet.");
- }
- return bda;
- } else if (bType.equals("Quality")) {
- return new BdaQuality(new ObjectReference(ref), fc, sAddr, qchg);
- } else if (bType.equals("Check")) {
- return new BdaCheck(new ObjectReference(ref));
- } else if (bType.equals("Dbpos")) {
- return new BdaDoubleBitPos(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- } else if (bType.equals("Tcmd")) {
- return new BdaTapCommand(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- } else if (bType.equals("OptFlds")) {
- return new BdaOptFlds(new ObjectReference(ref), fc);
- } else if (bType.equals("TrgOps")) {
- return new BdaTriggerConditions(new ObjectReference(ref), fc);
- } else if (bType.equals("EntryID")) {
- return new BdaOctetString(new ObjectReference(ref), fc, sAddr, 8, dchg, dupd);
- } else if (bType.equals("EntryTime")) {
- return new BdaEntryTime(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- } else if (bType.equals("PhyComAddr")) {
- // TODO not correct!
- return new BdaOctetString(new ObjectReference(ref), fc, sAddr, 6, dchg, dupd);
- } else if (bType.equals("Timestamp")) {
- BdaTimestamp bda = new BdaTimestamp(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- // TODO
- throw new SclParseException("parsing configured value for TIMESTAMP is not supported yet.");
- }
- return bda;
- } else if (bType.equals("Enum")) {
- String type = dattr.getType();
- if (type == null) {
- throw new SclParseException("The exact type of the enumeration is not set.");
- }
- EnumType enumType = typeDefinitions.getEnumType(type);
-
- if (enumType == null) {
- throw new SclParseException("Definition of enum type: " + type + " not found.");
- }
-
- if (enumType.max > 127 || enumType.min < -128) {
- BdaInt16 bda = new BdaInt16(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- for (EnumVal enumVal : enumType.getValues()) {
- if (val.equals(enumVal.getId())) {
- bda.setValue((short) enumVal.getOrd());
- return bda;
+
+ String val = null;
+ String sAddr = null;
+ if (iXmlNode != null) {
+ NamedNodeMap attributeMap = iXmlNode.getAttributes();
+ Node sAddrAttribute = attributeMap.getNamedItem("sAddr");
+ if (sAddrAttribute != null) {
+ sAddr = sAddrAttribute.getNodeValue();
+ }
+
+ NodeList elements = iXmlNode.getChildNodes();
+ for (int i = 0; i < elements.getLength(); i++) {
+ Node node = elements.item(i);
+ if (node.getNodeName().equals("Val")) {
+ val = node.getTextContent();
+ }
+ }
+ if (val == null) {
+ // insert value from DA element
+ val = dattr.value;
}
- }
- throw new SclParseException("unknown enum value: " + val);
}
- return bda;
- } else {
- BdaInt8 bda = new BdaInt8(new ObjectReference(ref), fc, sAddr, dchg, dupd);
- if (val != null) {
- for (EnumVal enumVal : enumType.getValues()) {
- if (val.equals(enumVal.getId())) {
- bda.setValue((byte) enumVal.getOrd());
- return bda;
+
+ if (bType.equals("BOOLEAN")) {
+ BdaBoolean bda = new BdaBoolean(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ if (val.equalsIgnoreCase("true") || val.equals("1")) {
+ bda.setValue(true);
+ } else if (val.equalsIgnoreCase("false") || val.equals("0")) {
+ bda.setValue(false);
+ } else {
+ throw new SclParseException("invalid boolean configured value: " + val);
+ }
+ }
+ return bda;
+ } else if (bType.equals("INT8")) {
+ BdaInt8 bda = new BdaInt8(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ try {
+ bda.setValue(Byte.parseByte(val));
+ } catch (NumberFormatException e) {
+ throw new SclParseException("invalid INT8 configured value: " + val);
+ }
+ }
+ return bda;
+ } else if (bType.equals("INT16")) {
+ BdaInt16 bda = new BdaInt16(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ try {
+ bda.setValue(Short.parseShort(val));
+ } catch (NumberFormatException e) {
+ throw new SclParseException("invalid INT16 configured value: " + val);
+ }
+ }
+ return bda;
+ } else if (bType.equals("INT32")) {
+ BdaInt32 bda = new BdaInt32(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ try {
+ bda.setValue(Integer.parseInt(val));
+ } catch (NumberFormatException e) {
+ throw new SclParseException("invalid INT32 configured value: " + val);
+ }
+ }
+ return bda;
+ } else if (bType.equals("INT64")) {
+ BdaInt64 bda = new BdaInt64(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ try {
+ bda.setValue(Long.parseLong(val));
+ } catch (NumberFormatException e) {
+ throw new SclParseException("invalid INT64 configured value: " + val);
+ }
+ }
+ return bda;
+ } else if (bType.equals("INT128")) {
+ BdaInt128 bda = new BdaInt128(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ try {
+ bda.setValue(Long.parseLong(val));
+ } catch (NumberFormatException e) {
+ throw new SclParseException("invalid INT128 configured value: " + val);
+ }
+ }
+ return bda;
+ } else if (bType.equals("INT8U")) {
+ BdaInt8U bda = new BdaInt8U(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ try {
+ bda.setValue(Short.parseShort(val));
+ } catch (NumberFormatException e) {
+ throw new SclParseException("invalid INT8U configured value: " + val);
+ }
+ }
+ return bda;
+ } else if (bType.equals("INT16U")) {
+ BdaInt16U bda = new BdaInt16U(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ try {
+ bda.setValue(Integer.parseInt(val));
+ } catch (NumberFormatException e) {
+ throw new SclParseException("invalid INT16U configured value: " + val);
+ }
+ }
+ return bda;
+ } else if (bType.equals("INT32U")) {
+ BdaInt32U bda = new BdaInt32U(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ try {
+ bda.setValue(Long.parseLong(val));
+ } catch (NumberFormatException e) {
+ throw new SclParseException("invalid INT32U configured value: " + val);
+ }
+ }
+ return bda;
+ } else if (bType.equals("FLOAT32")) {
+ BdaFloat32 bda = new BdaFloat32(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ try {
+ bda.setFloat(Float.parseFloat(val));
+ } catch (NumberFormatException e) {
+ throw new SclParseException("invalid FLOAT32 configured value: " + val);
+ }
+ }
+ return bda;
+ } else if (bType.equals("FLOAT64")) {
+ BdaFloat64 bda = new BdaFloat64(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ try {
+ bda.setDouble(Double.parseDouble(val));
+ } catch (NumberFormatException e) {
+ throw new SclParseException("invalid FLOAT64 configured value: " + val);
+ }
}
- }
- throw new SclParseException("unknown enum value: " + val);
+ return bda;
+ } else if (bType.startsWith("VisString")) {
+ BdaVisibleString bda =
+ new BdaVisibleString(
+ new ObjectReference(ref),
+ fc,
+ sAddr,
+ Integer.parseInt(dattr.getbType().substring(9)),
+ dchg,
+ dupd);
+ if (val != null) {
+ bda.setValue(val.getBytes(UTF_8));
+ }
+ return bda;
+ } else if (bType.startsWith("Unicode")) {
+ BdaUnicodeString bda =
+ new BdaUnicodeString(
+ new ObjectReference(ref),
+ fc,
+ sAddr,
+ Integer.parseInt(dattr.getbType().substring(7)),
+ dchg,
+ dupd);
+ if (val != null) {
+ bda.setValue(val.getBytes(UTF_8));
+ }
+ return bda;
+ } else if (bType.startsWith("Octet")) {
+ BdaOctetString bda =
+ new BdaOctetString(
+ new ObjectReference(ref),
+ fc,
+ sAddr,
+ Integer.parseInt(dattr.getbType().substring(5)),
+ dchg,
+ dupd);
+ if (val != null) {
+ // TODO
+ // throw new SclParseException("parsing configured value for octet string is not supported
+ // yet.");
+ }
+ return bda;
+ } else if (bType.equals("Quality")) {
+ return new BdaQuality(new ObjectReference(ref), fc, sAddr, qchg);
+ } else if (bType.equals("Check")) {
+ return new BdaCheck(new ObjectReference(ref));
+ } else if (bType.equals("Dbpos")) {
+ return new BdaDoubleBitPos(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ } else if (bType.equals("Tcmd")) {
+ return new BdaTapCommand(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ } else if (bType.equals("OptFlds")) {
+ return new BdaOptFlds(new ObjectReference(ref), fc);
+ } else if (bType.equals("TrgOps")) {
+ return new BdaTriggerConditions(new ObjectReference(ref), fc);
+ } else if (bType.equals("EntryID")) {
+ return new BdaOctetString(new ObjectReference(ref), fc, sAddr, 8, dchg, dupd);
+ } else if (bType.equals("EntryTime")) {
+ return new BdaEntryTime(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ } else if (bType.equals("PhyComAddr")) {
+ // TODO not correct!
+ return new BdaOctetString(new ObjectReference(ref), fc, sAddr, 6, dchg, dupd);
+ } else if (bType.equals("Timestamp")) {
+ BdaTimestamp bda = new BdaTimestamp(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ // TODO
+ bda.setDate(new Date(System.currentTimeMillis()));
+ }
+ return bda;
+ } else if (bType.equals("Enum")) {
+ String type = dattr.getType();
+ if (type == null) {
+ throw new SclParseException("The exact type of the enumeration is not set.");
+ }
+ EnumType enumType = typeDefinitions.getEnumType(type);
+
+ if (enumType == null) {
+ throw new SclParseException("Definition of enum type: " + type + " not found.");
+ }
+
+ if (enumType.max > 127 || enumType.min < -128) {
+ BdaInt16 bda = new BdaInt16(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ for (EnumVal enumVal : enumType.getValues()) {
+ if (val.equals(enumVal.getId())) {
+ bda.setValue((short) enumVal.getOrd());
+ return bda;
+ }
+ }
+ throw new SclParseException("unknown enum value: " + val);
+ }
+ return bda;
+ } else {
+ BdaInt8 bda = new BdaInt8(new ObjectReference(ref), fc, sAddr, dchg, dupd);
+ if (val != null) {
+ for (EnumVal enumVal : enumType.getValues()) {
+ if (val.equals(enumVal.getId())) {
+ bda.setValue((byte) enumVal.getOrd());
+ return bda;
+ }
+ }
+ throw new SclParseException("unknown enum value: " + val);
+ }
+ return bda;
+ }
+ } else if (bType.equals("ObjRef")) {
+ BdaVisibleString bda =
+ new BdaVisibleString(new ObjectReference(ref), fc, sAddr, 129, dchg, dupd);
+ if (val != null) {
+ bda.setValue(val.getBytes(UTF_8));
+ }
+ return bda;
+ } else {
+ throw new SclParseException("Invalid bType: " + bType);
}
- return bda;
- }
- } else if (bType.equals("ObjRef")) {
- BdaVisibleString bda =
- new BdaVisibleString(new ObjectReference(ref), fc, sAddr, 129, dchg, dupd);
- if (val != null) {
- bda.setValue(val.getBytes(UTF_8));
- }
- return bda;
- } else {
- throw new SclParseException("Invalid bType: " + bType);
}
- }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/beanit/iec61850bean/ServerAssociation.java b/src/main/java/com/beanit/iec61850bean/ServerAssociation.java
index dde88d3..e10e5a3 100644
--- a/src/main/java/com/beanit/iec61850bean/ServerAssociation.java
+++ b/src/main/java/com/beanit/iec61850bean/ServerAssociation.java
@@ -13,84 +13,45 @@
*/
package com.beanit.iec61850bean;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream;
import com.beanit.asn1bean.ber.types.BerInteger;
import com.beanit.asn1bean.ber.types.BerNull;
import com.beanit.asn1bean.ber.types.string.BerVisibleString;
import com.beanit.iec61850bean.internal.BerBoolean;
import com.beanit.iec61850bean.internal.NamedThreadFactory;
-import com.beanit.iec61850bean.internal.mms.asn1.AccessResult;
-import com.beanit.iec61850bean.internal.mms.asn1.ConfirmedErrorPDU;
-import com.beanit.iec61850bean.internal.mms.asn1.ConfirmedRequestPDU;
-import com.beanit.iec61850bean.internal.mms.asn1.ConfirmedResponsePDU;
-import com.beanit.iec61850bean.internal.mms.asn1.ConfirmedServiceRequest;
-import com.beanit.iec61850bean.internal.mms.asn1.ConfirmedServiceResponse;
-import com.beanit.iec61850bean.internal.mms.asn1.Data;
-import com.beanit.iec61850bean.internal.mms.asn1.DataAccessError;
-import com.beanit.iec61850bean.internal.mms.asn1.DefineNamedVariableListRequest;
-import com.beanit.iec61850bean.internal.mms.asn1.DefineNamedVariableListResponse;
-import com.beanit.iec61850bean.internal.mms.asn1.DeleteNamedVariableListRequest;
-import com.beanit.iec61850bean.internal.mms.asn1.DeleteNamedVariableListResponse;
-import com.beanit.iec61850bean.internal.mms.asn1.GetNameListRequest;
-import com.beanit.iec61850bean.internal.mms.asn1.GetNameListResponse;
+import com.beanit.iec61850bean.internal.mms.asn1.*;
import com.beanit.iec61850bean.internal.mms.asn1.GetNameListResponse.ListOfIdentifier;
-import com.beanit.iec61850bean.internal.mms.asn1.GetNamedVariableListAttributesResponse;
-import com.beanit.iec61850bean.internal.mms.asn1.GetVariableAccessAttributesRequest;
-import com.beanit.iec61850bean.internal.mms.asn1.GetVariableAccessAttributesResponse;
-import com.beanit.iec61850bean.internal.mms.asn1.Identifier;
-import com.beanit.iec61850bean.internal.mms.asn1.InitiateRequestPDU;
-import com.beanit.iec61850bean.internal.mms.asn1.InitiateResponsePDU;
-import com.beanit.iec61850bean.internal.mms.asn1.Integer16;
-import com.beanit.iec61850bean.internal.mms.asn1.Integer32;
-import com.beanit.iec61850bean.internal.mms.asn1.Integer8;
-import com.beanit.iec61850bean.internal.mms.asn1.MMSpdu;
-import com.beanit.iec61850bean.internal.mms.asn1.ObjectName;
import com.beanit.iec61850bean.internal.mms.asn1.ObjectName.DomainSpecific;
-import com.beanit.iec61850bean.internal.mms.asn1.ParameterSupportOptions;
-import com.beanit.iec61850bean.internal.mms.asn1.ReadRequest;
-import com.beanit.iec61850bean.internal.mms.asn1.ReadResponse;
import com.beanit.iec61850bean.internal.mms.asn1.ReadResponse.ListOfAccessResult;
import com.beanit.iec61850bean.internal.mms.asn1.ServiceError.ErrorClass;
-import com.beanit.iec61850bean.internal.mms.asn1.ServiceSupportOptions;
-import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription.Structure;
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription.Structure.Components;
-import com.beanit.iec61850bean.internal.mms.asn1.TypeSpecification;
-import com.beanit.iec61850bean.internal.mms.asn1.Unsigned32;
-import com.beanit.iec61850bean.internal.mms.asn1.VariableAccessSpecification;
-import com.beanit.iec61850bean.internal.mms.asn1.VariableDefs;
-import com.beanit.iec61850bean.internal.mms.asn1.WriteRequest;
-import com.beanit.iec61850bean.internal.mms.asn1.WriteResponse;
import com.beanit.josistack.AcseAssociation;
import com.beanit.josistack.ByteBufferInputStream;
import com.beanit.josistack.DecodingException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
+import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeoutException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
final class ServerAssociation {
private static final Logger logger = LoggerFactory.getLogger(ServerAssociation.class);
private static final WriteResponse.CHOICE writeSuccess = new WriteResponse.CHOICE();
- private static String[] mmsFcs = {
- "MX", "ST", "CO", "CF", "DC", "SP", "SG", "RP", "LG", "BR", "GO", "GS", "SV", "SE", "EX", "SR",
- "OR", "BL"
+ private static final String[] mmsFcs = {
+ "MX", "ST", "CO", "CF", "DC", "SP", "SG", "RP", "LG", "BR", "GO", "GS", "SV", "SE", "EX", "SR",
+ "OR", "BL"
};
static {
diff --git a/src/main/java/com/beanit/iec61850bean/ServerModel.java b/src/main/java/com/beanit/iec61850bean/ServerModel.java
index 9a4f59f..a13f073 100644
--- a/src/main/java/com/beanit/iec61850bean/ServerModel.java
+++ b/src/main/java/com/beanit/iec61850bean/ServerModel.java
@@ -17,384 +17,488 @@
import com.beanit.iec61850bean.internal.mms.asn1.ObjectName;
import com.beanit.iec61850bean.internal.mms.asn1.ObjectName.DomainSpecific;
import com.beanit.iec61850bean.internal.mms.asn1.VariableDefs;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+
+import java.util.*;
public final class ServerModel extends ModelNode {
- private final Map dataSets = new LinkedHashMap<>();
+ private final Map dataSets = new LinkedHashMap<>();
+
+ private final Map urcbs = new HashMap<>();
+ private final Map brcbs = new HashMap<>();
+
+ private ConnectionParam connectionParam;
+ private String iedName;
+ private String iedManufacturer;
+ private List ldsInsts;
+ private List ldsRefs;
+ private List lnsRefs;
+ private Map> lns;
+ private HashSet lnS;
+ private Map descriptions;
+ private Map dAIDescriptions;
+ private Map dos;
+ private List logicalDevices;
+
+ public ServerModel(List logicalDevices, Collection dataSets) {
+ children = new LinkedHashMap<>();
+ objectReference = null;
+ for (LogicalDevice logicalDevice : logicalDevices) {
+ children.put(logicalDevice.getReference().getName(), logicalDevice);
+ logicalDevice.setParent(this);
+ }
+
+ if (dataSets != null) {
+ addDataSets(dataSets);
+ }
+
+ for (LogicalDevice ld : logicalDevices) {
+ for (ModelNode ln : ld.getChildren()) {
+ for (Urcb urcb : ((LogicalNode) ln).getUrcbs()) {
+ urcbs.put(urcb.getReference().toString(), urcb);
+ urcb.dataSet = getDataSet(urcb.getDatSet().getStringValue().replace('$', '.'));
+ }
+ for (Brcb brcb : ((LogicalNode) ln).getBrcbs()) {
+ brcbs.put(brcb.getReference().toString(), brcb);
+ brcb.dataSet = getDataSet(brcb.getDatSet().getStringValue().replace('$', '.'));
+ }
+ }
+ }
+ }
- private final Map urcbs = new HashMap<>();
- private final Map brcbs = new HashMap<>();
+ @Override
+ public ServerModel copy() {
+ List childCopies = new ArrayList<>(children.size());
+ for (ModelNode childNode : children.values()) {
+ childCopies.add((LogicalDevice) childNode.copy());
+ }
+
+ List dataSetCopies = new ArrayList<>(dataSets.size());
+ for (DataSet dataSet : dataSets.values()) {
+ dataSetCopies.add(dataSet);
+ }
+
+ return new ServerModel(childCopies, dataSetCopies);
+ }
+
+ /**
+ * Get the data set with the given reference. Return null if none is found.
+ *
+ * @param reference the reference of the requested data set.
+ * @return the data set with the given reference.
+ */
+ public DataSet getDataSet(String reference) {
+ return dataSets.get(reference);
+ }
+
+ void addDataSet(DataSet dataSet) {
+ dataSets.put(dataSet.getReferenceStr().replace('$', '.'), dataSet);
+ for (ModelNode ld : children.values()) {
+ for (ModelNode ln : ld.getChildren()) {
+ for (Urcb urcb : ((LogicalNode) ln).getUrcbs()) {
+ urcb.dataSet = getDataSet(urcb.getDatSet().getStringValue().replace('$', '.'));
+ }
+ for (Brcb brcb : ((LogicalNode) ln).getBrcbs()) {
+ brcb.dataSet = getDataSet(brcb.getDatSet().getStringValue().replace('$', '.'));
+ }
+ }
+ }
+ }
+
+ void addDataSets(Collection dataSets) {
+ for (DataSet dataSet : dataSets) {
+ addDataSet(dataSet);
+ }
+ for (ModelNode ld : children.values()) {
+ for (ModelNode ln : ld.getChildren()) {
+ for (Urcb urcb : ((LogicalNode) ln).getUrcbs()) {
+ urcb.dataSet = getDataSet(urcb.getDatSet().getStringValue().replace('$', '.'));
+ }
+ for (Brcb brcb : ((LogicalNode) ln).getBrcbs()) {
+ brcb.dataSet = getDataSet(brcb.getDatSet().getStringValue().replace('$', '.'));
+ }
+ }
+ }
+ }
- public ServerModel(List logicalDevices, Collection dataSets) {
- children = new LinkedHashMap<>();
- objectReference = null;
- for (LogicalDevice logicalDevice : logicalDevices) {
- children.put(logicalDevice.getReference().getName(), logicalDevice);
- logicalDevice.setParent(this);
+ List getDataSetNames(String ldName) {
+ // TODO make thread save
+ List dataSetNames = new ArrayList<>();
+ for (String dataSetRef : dataSets.keySet()) {
+ if (dataSetRef.startsWith(ldName)) {
+ dataSetNames.add(dataSetRef.substring(dataSetRef.indexOf('/') + 1).replace('.', '$'));
+ }
+ }
+ return dataSetNames;
}
- if (dataSets != null) {
- addDataSets(dataSets);
+ /**
+ * Get a collection of all data sets that exist in this model.
+ *
+ * @return a collection of all data sets
+ */
+ public Collection getDataSets() {
+ return dataSets.values();
}
- for (LogicalDevice ld : logicalDevices) {
- for (ModelNode ln : ld.getChildren()) {
- for (Urcb urcb : ((LogicalNode) ln).getUrcbs()) {
- urcbs.put(urcb.getReference().toString(), urcb);
- urcb.dataSet = getDataSet(urcb.getDatSet().getStringValue().replace('$', '.'));
+ /**
+ * @param dataSetReference the data set reference
+ * @return returns the DataSet that was removed, null if no DataSet with the given reference was
+ * found or the data set is not deletable.
+ */
+ DataSet removeDataSet(String dataSetReference) {
+ DataSet dataSet = dataSets.get(dataSetReference);
+ if (dataSet == null || !dataSet.isDeletable()) {
+ return null;
}
- for (Brcb brcb : ((LogicalNode) ln).getBrcbs()) {
- brcbs.put(brcb.getReference().toString(), brcb);
- brcb.dataSet = getDataSet(brcb.getDatSet().getStringValue().replace('$', '.'));
+ DataSet removedDataSet = dataSets.remove(dataSetReference);
+ for (ModelNode ld : children.values()) {
+ for (ModelNode ln : ld.getChildren()) {
+ for (Urcb urcb : ((LogicalNode) ln).getUrcbs()) {
+ urcb.dataSet = getDataSet(urcb.getDatSet().getStringValue().replace('$', '.'));
+ }
+ for (Brcb brcb : ((LogicalNode) ln).getBrcbs()) {
+ brcb.dataSet = getDataSet(brcb.getDatSet().getStringValue().replace('$', '.'));
+ }
+ }
}
- }
+ return removedDataSet;
+ }
+
+ void addUrcb(Urcb urcb) {
+ urcbs.put(urcb.getReference().getName(), urcb);
}
- }
- @Override
- public ServerModel copy() {
- List childCopies = new ArrayList<>(children.size());
- for (ModelNode childNode : children.values()) {
- childCopies.add((LogicalDevice) childNode.copy());
+ /**
+ * Get the unbuffered report control block (URCB) with the given reference.
+ *
+ * @param reference the reference of the requested URCB.
+ * @return the reference to the requested URCB or null if none with the given reference is found.
+ */
+ public Urcb getUrcb(String reference) {
+ return urcbs.get(reference);
}
- List dataSetCopies = new ArrayList<>(dataSets.size());
- for (DataSet dataSet : dataSets.values()) {
- dataSetCopies.add(dataSet);
+ /**
+ * Get a collection of all unbuffered report control blocks (URCB) that exist in this model.
+ *
+ * @return a collection of all unbuffered report control blocks (URCB)
+ */
+ public Collection getUrcbs() {
+ return urcbs.values();
}
- return new ServerModel(childCopies, dataSetCopies);
- }
+ /**
+ * Get the buffered report control block (BRCB) with the given reference.
+ *
+ * @param reference the reference of the requested BRCB.
+ * @return the reference to the requested BRCB or null if none with the given reference is found.
+ */
+ public Brcb getBrcb(String reference) {
+ return brcbs.get(reference);
+ }
- /**
- * Get the data set with the given reference. Return null if none is found.
- *
- * @param reference the reference of the requested data set.
- * @return the data set with the given reference.
- */
- public DataSet getDataSet(String reference) {
- return dataSets.get(reference);
- }
+ /**
+ * Get a collection of all buffered report control blocks (BRCB) that exist in this model.
+ *
+ * @return a collection of all buffered report control blocks (BRCB)
+ */
+ public Collection getBrcbs() {
+ return brcbs.values();
+ }
- void addDataSet(DataSet dataSet) {
- dataSets.put(dataSet.getReferenceStr().replace('$', '.'), dataSet);
- for (ModelNode ld : children.values()) {
- for (ModelNode ln : ld.getChildren()) {
- for (Urcb urcb : ((LogicalNode) ln).getUrcbs()) {
- urcb.dataSet = getDataSet(urcb.getDatSet().getStringValue().replace('$', '.'));
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ for (ModelNode logicalDevice : children.values()) {
+ sb.append(logicalDevice.toString());
}
- for (Brcb brcb : ((LogicalNode) ln).getBrcbs()) {
- brcb.dataSet = getDataSet(brcb.getDatSet().getStringValue().replace('$', '.'));
+ sb.append("\n\n\n---------------------\nURCBs:");
+ for (Urcb urcb : getUrcbs()) {
+ sb.append("\n\n").append(urcb);
}
- }
+
+ sb.append("\n\n\n---------------------\nBRCBs:");
+ for (Brcb brcb : getBrcbs()) {
+ sb.append("\n\n").append(brcb);
+ }
+
+ sb.append("\n\n\n---------------------\nData sets:");
+ for (DataSet dataSet : getDataSets()) {
+ sb.append("\n\n").append(dataSet);
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Searches and returns the model node with the given object reference and FC. If searching for
+ * Logical Devices and Logical Nodes the given fc parameter may be null
.
+ *
+ * @param objectReference the object reference of the node that is being searched for. It has a
+ * syntax like "ldname/ln.do....".
+ * @param fc the functional constraint of the requested model node. May be null for Logical Device
+ * and Logical Node references.
+ * @return the model node if it was found or null otherwise
+ */
+ public ModelNode findModelNode(ObjectReference objectReference, Fc fc) {
+
+ ModelNode currentNode = this;
+ Iterator searchedNodeReferenceIterator = objectReference.iterator();
+
+ while (searchedNodeReferenceIterator.hasNext()) {
+ currentNode = currentNode.getChild(searchedNodeReferenceIterator.next(), fc);
+ if (currentNode == null) {
+ return null;
+ }
+ }
+ return currentNode;
}
- }
- void addDataSets(Collection dataSets) {
- for (DataSet dataSet : dataSets) {
- addDataSet(dataSet);
+ /**
+ * Searches and returns the model node with the given object reference and FC. If searching for
+ * Logical Devices and Logical Nodes the given fc parameter may be null
.
+ *
+ * @param objectReference the object reference of the node that is being searched for. It has a
+ * syntax like "ldname/ln.do....".
+ * @param fc the functional constraint of the requested model node. May be null for Logical Device
+ * and Logical Node references.
+ * @return the model node if it was found or null otherwise
+ */
+ public ModelNode findModelNode(String objectReference, Fc fc) {
+ return findModelNode(new ObjectReference(objectReference), fc);
}
- for (ModelNode ld : children.values()) {
- for (ModelNode ln : ld.getChildren()) {
- for (Urcb urcb : ((LogicalNode) ln).getUrcbs()) {
- urcb.dataSet = getDataSet(urcb.getDatSet().getStringValue().replace('$', '.'));
+
+ /**
+ * Returns the subModelNode that is referenced by the given VariableDef. Return null in case the
+ * referenced ModelNode is not found.
+ *
+ * @param variableDef the variableDef
+ * @return the subModelNode that is referenced by the given VariableDef
+ * @throws ServiceError if an error occurs
+ */
+ FcModelNode getNodeFromVariableDef(VariableDefs.SEQUENCE variableDef) throws ServiceError {
+
+ ObjectName objectName = variableDef.getVariableSpecification().getName();
+
+ if (objectName == null) {
+ throw new ServiceError(
+ ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
+ "name in objectName is not selected");
+ }
+
+ DomainSpecific domainSpecific = objectName.getDomainSpecific();
+
+ if (domainSpecific == null) {
+ throw new ServiceError(
+ ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
+ "domain_specific in name is not selected");
}
- for (Brcb brcb : ((LogicalNode) ln).getBrcbs()) {
- brcb.dataSet = getDataSet(brcb.getDatSet().getStringValue().replace('$', '.'));
+
+ ModelNode modelNode = getChild(domainSpecific.getDomainID().toString());
+
+ if (modelNode == null) {
+ return null;
+ }
+
+ String mmsItemId = domainSpecific.getItemID().toString();
+ int index1 = mmsItemId.indexOf('$');
+
+ if (index1 == -1) {
+ throw new ServiceError(
+ ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
+ "invalid mms item id: " + domainSpecific.getItemID());
}
- }
- }
- }
-
- List getDataSetNames(String ldName) {
- // TODO make thread save
- List dataSetNames = new ArrayList<>();
- for (String dataSetRef : dataSets.keySet()) {
- if (dataSetRef.startsWith(ldName)) {
- dataSetNames.add(dataSetRef.substring(dataSetRef.indexOf('/') + 1).replace('.', '$'));
- }
- }
- return dataSetNames;
- }
-
- /**
- * Get a collection of all data sets that exist in this model.
- *
- * @return a collection of all data sets
- */
- public Collection getDataSets() {
- return dataSets.values();
- }
-
- /**
- * @param dataSetReference the data set reference
- * @return returns the DataSet that was removed, null if no DataSet with the given reference was
- * found or the data set is not deletable.
- */
- DataSet removeDataSet(String dataSetReference) {
- DataSet dataSet = dataSets.get(dataSetReference);
- if (dataSet == null || !dataSet.isDeletable()) {
- return null;
- }
- DataSet removedDataSet = dataSets.remove(dataSetReference);
- for (ModelNode ld : children.values()) {
- for (ModelNode ln : ld.getChildren()) {
- for (Urcb urcb : ((LogicalNode) ln).getUrcbs()) {
- urcb.dataSet = getDataSet(urcb.getDatSet().getStringValue().replace('$', '.'));
+
+ LogicalNode ln = (LogicalNode) modelNode.getChild(mmsItemId.substring(0, index1));
+
+ if (ln == null) {
+ return null;
}
- for (Brcb brcb : ((LogicalNode) ln).getBrcbs()) {
- brcb.dataSet = getDataSet(brcb.getDatSet().getStringValue().replace('$', '.'));
+
+ int index2 = mmsItemId.indexOf('$', index1 + 1);
+
+ if (index2 == -1) {
+ throw new ServiceError(
+ ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT, "invalid mms item id");
}
- }
- }
- return removedDataSet;
- }
-
- void addUrcb(Urcb urcb) {
- urcbs.put(urcb.getReference().getName(), urcb);
- }
-
- /**
- * Get the unbuffered report control block (URCB) with the given reference.
- *
- * @param reference the reference of the requested URCB.
- * @return the reference to the requested URCB or null if none with the given reference is found.
- */
- public Urcb getUrcb(String reference) {
- return urcbs.get(reference);
- }
-
- /**
- * Get a collection of all unbuffered report control blocks (URCB) that exist in this model.
- *
- * @return a collection of all unbuffered report control blocks (URCB)
- */
- public Collection getUrcbs() {
- return urcbs.values();
- }
-
- /**
- * Get the buffered report control block (BRCB) with the given reference.
- *
- * @param reference the reference of the requested BRCB.
- * @return the reference to the requested BRCB or null if none with the given reference is found.
- */
- public Brcb getBrcb(String reference) {
- return brcbs.get(reference);
- }
-
- /**
- * Get a collection of all buffered report control blocks (BRCB) that exist in this model.
- *
- * @return a collection of all buffered report control blocks (BRCB)
- */
- public Collection getBrcbs() {
- return brcbs.values();
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- for (ModelNode logicalDevice : children.values()) {
- sb.append(logicalDevice.toString());
- }
- sb.append("\n\n\n---------------------\nURCBs:");
- for (Urcb urcb : getUrcbs()) {
- sb.append("\n\n").append(urcb);
- }
-
- sb.append("\n\n\n---------------------\nBRCBs:");
- for (Brcb brcb : getBrcbs()) {
- sb.append("\n\n").append(brcb);
- }
-
- sb.append("\n\n\n---------------------\nData sets:");
- for (DataSet dataSet : getDataSets()) {
- sb.append("\n\n").append(dataSet);
- }
-
- return sb.toString();
- }
- /**
- * Searches and returns the model node with the given object reference and FC. If searching for
- * Logical Devices and Logical Nodes the given fc parameter may be null
.
- *
- * @param objectReference the object reference of the node that is being searched for. It has a
- * syntax like "ldname/ln.do....".
- * @param fc the functional constraint of the requested model node. May be null for Logical Device
- * and Logical Node references.
- * @return the model node if it was found or null otherwise
- */
- public ModelNode findModelNode(ObjectReference objectReference, Fc fc) {
-
- ModelNode currentNode = this;
- Iterator searchedNodeReferenceIterator = objectReference.iterator();
+ Fc fc = Fc.fromString(mmsItemId.substring(index1 + 1, index2));
- while (searchedNodeReferenceIterator.hasNext()) {
- currentNode = currentNode.getChild(searchedNodeReferenceIterator.next(), fc);
- if (currentNode == null) {
- return null;
- }
- }
- return currentNode;
- }
+ if (fc == null) {
+ throw new ServiceError(
+ ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
+ "unknown functional constraint: " + mmsItemId.substring(index1 + 1, index2));
+ }
- /**
- * Searches and returns the model node with the given object reference and FC. If searching for
- * Logical Devices and Logical Nodes the given fc parameter may be null
.
- *
- * @param objectReference the object reference of the node that is being searched for. It has a
- * syntax like "ldname/ln.do....".
- * @param fc the functional constraint of the requested model node. May be null for Logical Device
- * and Logical Node references.
- * @return the model node if it was found or null otherwise
- */
- public ModelNode findModelNode(String objectReference, Fc fc) {
- return findModelNode(new ObjectReference(objectReference), fc);
- }
+ index1 = index2;
+
+ index2 = mmsItemId.indexOf('$', index1 + 1);
+
+ if (index2 == -1) {
+ if (fc == Fc.RP) {
+ return ln.getUrcb(mmsItemId.substring(index1 + 1));
+ }
+ if (fc == Fc.BR) {
+ return ln.getBrcb(mmsItemId.substring(index1 + 1));
+ }
+ return (FcModelNode) ln.getChild(mmsItemId.substring(index1 + 1), fc);
+ }
+
+ if (fc == Fc.RP) {
+ modelNode = ln.getUrcb(mmsItemId.substring(index1 + 1, index2));
+ } else if (fc == Fc.BR) {
+ modelNode = ln.getBrcb(mmsItemId.substring(index1 + 1, index2));
+ } else {
+ modelNode = ln.getChild(mmsItemId.substring(index1 + 1, index2), fc);
+ }
+
+ index1 = index2;
+ index2 = mmsItemId.indexOf('$', index1 + 1);
+ while (index2 != -1) {
+ modelNode = modelNode.getChild(mmsItemId.substring(index1 + 1, index2));
+ index1 = index2;
+ index2 = mmsItemId.indexOf('$', index1 + 1);
+ }
- /**
- * Returns the subModelNode that is referenced by the given VariableDef. Return null in case the
- * referenced ModelNode is not found.
- *
- * @param variableDef the variableDef
- * @return the subModelNode that is referenced by the given VariableDef
- * @throws ServiceError if an error occurs
- */
- FcModelNode getNodeFromVariableDef(VariableDefs.SEQUENCE variableDef) throws ServiceError {
+ modelNode = modelNode.getChild(mmsItemId.substring(index1 + 1));
- ObjectName objectName = variableDef.getVariableSpecification().getName();
+ if (variableDef.getAlternateAccess() == null) {
+ // no array is in this node path
+ return (FcModelNode) modelNode;
+ }
- if (objectName == null) {
- throw new ServiceError(
- ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
- "name in objectName is not selected");
+ AlternateAccessSelection altAccIt =
+ variableDef.getAlternateAccess().getCHOICE().get(0).getUnnamed();
+
+ if (altAccIt.getSelectAlternateAccess() != null) {
+ // path to node below an array element
+ modelNode =
+ ((Array) modelNode)
+ .getChild(
+ altAccIt.getSelectAlternateAccess().getAccessSelection().getIndex().intValue());
+
+ String mmsSubArrayItemId =
+ altAccIt
+ .getSelectAlternateAccess()
+ .getAlternateAccess()
+ .getCHOICE()
+ .get(0)
+ .getUnnamed()
+ .getSelectAccess()
+ .getComponent()
+ .getBasic()
+ .toString();
+
+ index1 = -1;
+ index2 = mmsSubArrayItemId.indexOf('$');
+ while (index2 != -1) {
+ modelNode = modelNode.getChild(mmsSubArrayItemId.substring(index1 + 1, index2));
+ index1 = index2;
+ index2 = mmsItemId.indexOf('$', index1 + 1);
+ }
+
+ return (FcModelNode) modelNode.getChild(mmsSubArrayItemId.substring(index1 + 1));
+ } else {
+ // path to an array element
+ return (FcModelNode)
+ ((Array) modelNode).getChild(altAccIt.getSelectAccess().getIndex().intValue());
+ }
}
- DomainSpecific domainSpecific = objectName.getDomainSpecific();
+ public ConnectionParam getConnectionParam() {
+ return connectionParam;
+ }
- if (domainSpecific == null) {
- throw new ServiceError(
- ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
- "domain_specific in name is not selected");
+ public void setConnectionParam(ConnectionParam connectionParam) {
+ this.connectionParam = connectionParam;
}
- ModelNode modelNode = getChild(domainSpecific.getDomainID().toString());
+ public String getIedName() {
+ return iedName;
+ }
- if (modelNode == null) {
- return null;
+ public void setIedName(String iedName) {
+ this.iedName = iedName;
}
- String mmsItemId = domainSpecific.getItemID().toString();
- int index1 = mmsItemId.indexOf('$');
+ public String getIedManufacturer() {
+ return iedManufacturer;
+ }
- if (index1 == -1) {
- throw new ServiceError(
- ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
- "invalid mms item id: " + domainSpecific.getItemID());
+ public void setIedManufacturer(String iedManufacturer) {
+ this.iedManufacturer = iedManufacturer;
}
- LogicalNode ln = (LogicalNode) modelNode.getChild(mmsItemId.substring(0, index1));
+ public List getLdsInsts() {
+ return ldsInsts;
+ }
- if (ln == null) {
- return null;
+ public void setLdsInsts(List ldsInsts) {
+ this.ldsInsts = ldsInsts;
}
- int index2 = mmsItemId.indexOf('$', index1 + 1);
+ public List getLdsRefs() {
+ return ldsRefs;
+ }
- if (index2 == -1) {
- throw new ServiceError(
- ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT, "invalid mms item id");
+ public void setLdsRefs(List ldsRefs) {
+ this.ldsRefs = ldsRefs;
}
- Fc fc = Fc.fromString(mmsItemId.substring(index1 + 1, index2));
+ public List getLnsRefs() {
+ return lnsRefs;
+ }
- if (fc == null) {
- throw new ServiceError(
- ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
- "unknown functional constraint: " + mmsItemId.substring(index1 + 1, index2));
+ public void setLnsRefs(List lnsRefs) {
+ this.lnsRefs = lnsRefs;
}
- index1 = index2;
+ public Map> getLns() {
+ return lns;
+ }
- index2 = mmsItemId.indexOf('$', index1 + 1);
+ public void setLns(Map> lns) {
+ this.lns = lns;
+ }
- if (index2 == -1) {
- if (fc == Fc.RP) {
- return ln.getUrcb(mmsItemId.substring(index1 + 1));
- }
- if (fc == Fc.BR) {
- return ln.getBrcb(mmsItemId.substring(index1 + 1));
- }
- return (FcModelNode) ln.getChild(mmsItemId.substring(index1 + 1), fc);
+ public HashSet getLnS() {
+ return lnS;
}
- if (fc == Fc.RP) {
- modelNode = ln.getUrcb(mmsItemId.substring(index1 + 1, index2));
- } else if (fc == Fc.BR) {
- modelNode = ln.getBrcb(mmsItemId.substring(index1 + 1, index2));
- } else {
- modelNode = ln.getChild(mmsItemId.substring(index1 + 1, index2), fc);
+ public void setLnS(HashSet lnS) {
+ this.lnS = lnS;
}
- index1 = index2;
- index2 = mmsItemId.indexOf('$', index1 + 1);
- while (index2 != -1) {
- modelNode = modelNode.getChild(mmsItemId.substring(index1 + 1, index2));
- index1 = index2;
- index2 = mmsItemId.indexOf('$', index1 + 1);
+ public Map getDescriptions() {
+ return descriptions;
}
- modelNode = modelNode.getChild(mmsItemId.substring(index1 + 1));
+ public void setDescriptions(Map descriptions) {
+ this.descriptions = descriptions;
+ }
- if (variableDef.getAlternateAccess() == null) {
- // no array is in this node path
- return (FcModelNode) modelNode;
+ public Map getdAIDescriptions() {
+ return dAIDescriptions;
}
- AlternateAccessSelection altAccIt =
- variableDef.getAlternateAccess().getCHOICE().get(0).getUnnamed();
+ public void setdAIDescriptions(Map dAIDescriptions) {
+ this.dAIDescriptions = dAIDescriptions;
+ }
- if (altAccIt.getSelectAlternateAccess() != null) {
- // path to node below an array element
- modelNode =
- ((Array) modelNode)
- .getChild(
- altAccIt.getSelectAlternateAccess().getAccessSelection().getIndex().intValue());
+ public Map getDos() {
+ return dos;
+ }
- String mmsSubArrayItemId =
- altAccIt
- .getSelectAlternateAccess()
- .getAlternateAccess()
- .getCHOICE()
- .get(0)
- .getUnnamed()
- .getSelectAccess()
- .getComponent()
- .getBasic()
- .toString();
+ public void setDos(Map dos) {
+ this.dos = dos;
+ }
- index1 = -1;
- index2 = mmsSubArrayItemId.indexOf('$');
- while (index2 != -1) {
- modelNode = modelNode.getChild(mmsSubArrayItemId.substring(index1 + 1, index2));
- index1 = index2;
- index2 = mmsItemId.indexOf('$', index1 + 1);
- }
+ public List getLogicalDevices() {
+ return logicalDevices;
+ }
- return (FcModelNode) modelNode.getChild(mmsSubArrayItemId.substring(index1 + 1));
- } else {
- // path to an array element
- return (FcModelNode)
- ((Array) modelNode).getChild(altAccIt.getSelectAccess().getIndex().intValue());
+ public void setLogicalDevices(List logicalDevices) {
+ this.logicalDevices = logicalDevices;
}
- }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/beanit/iec61850bean/ServerSap.java b/src/main/java/com/beanit/iec61850bean/ServerSap.java
index 722de00..e1aa9a2 100644
--- a/src/main/java/com/beanit/iec61850bean/ServerSap.java
+++ b/src/main/java/com/beanit/iec61850bean/ServerSap.java
@@ -15,13 +15,14 @@
import com.beanit.josistack.AcseAssociation;
import com.beanit.josistack.ServerAcseSap;
+
+import javax.net.ServerSocketFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
-import javax.net.ServerSocketFactory;
/**
* The ServerSap
class represents the IEC 61850 service access point for server
@@ -340,11 +341,7 @@ public void setValues(List bdas) {
bdaMirror.setValueFrom(bda);
synchronized (bdaMirror.chgRcbs) {
for (Urcb urcb : bdaMirror.chgRcbs) {
- if (bdaMirror.dupd && urcb.getTrgOps().isDataUpdate()) {
- urcb.report(bdaMirror, true, false, true);
- } else {
- urcb.report(bdaMirror, true, false, false);
- }
+ urcb.report(bdaMirror, true, false, bdaMirror.dupd && urcb.getTrgOps().isDataUpdate());
}
}
} else if (bdaMirror.dupd && bdaMirror.dupdRcbs.size() != 0) {
diff --git a/src/main/java/com/beanit/iec61850bean/clientgui/ClientGui.java b/src/main/java/com/beanit/iec61850bean/clientgui/ClientGui.java
index a981eca..dc21245 100644
--- a/src/main/java/com/beanit/iec61850bean/clientgui/ClientGui.java
+++ b/src/main/java/com/beanit/iec61850bean/clientgui/ClientGui.java
@@ -18,11 +18,13 @@
import com.beanit.iec61850bean.ServerModel;
import com.beanit.iec61850bean.ServiceError;
import com.beanit.iec61850bean.clientgui.util.Counter;
-import java.awt.Component;
-import java.awt.Dimension;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
+
+import javax.swing.*;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
@@ -32,23 +34,6 @@
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Properties;
-import javax.swing.Box;
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JSeparator;
-import javax.swing.JTextField;
-import javax.swing.JTree;
-import javax.swing.ToolTipManager;
-import javax.swing.UIManager;
-import javax.swing.UnsupportedLookAndFeelException;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.DefaultTreeModel;
public class ClientGui extends JFrame implements ActionListener, TreeSelectionListener {
@@ -416,7 +401,7 @@ private void showDataDetails(DataTreeNode node, String pre, Counter y) {
for (int i = 0; i < node.getChildCount(); i++) {
y.increment();
DataObjectTreeNode childNode = (DataObjectTreeNode) node.getChildAt(i);
- showDataDetails(childNode, pre + "." + childNode.toString(), y);
+ showDataDetails(childNode, pre + "." + childNode, y);
detailsPanel.add(new JSeparator());
addDetailsComponent(new JSeparator(), 0, y.getValue(), 3, 1, 1, 0);
}
diff --git a/src/main/java/com/beanit/iec61850bean/internal/scl/DoType.java b/src/main/java/com/beanit/iec61850bean/internal/scl/DoType.java
index 67bfce6..0a0a567 100644
--- a/src/main/java/com/beanit/iec61850bean/internal/scl/DoType.java
+++ b/src/main/java/com/beanit/iec61850bean/internal/scl/DoType.java
@@ -14,36 +14,45 @@
package com.beanit.iec61850bean.internal.scl;
import com.beanit.iec61850bean.SclParseException;
-import java.util.ArrayList;
-import java.util.List;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import java.util.ArrayList;
+import java.util.List;
+
public final class DoType extends AbstractType {
- // attributes not needed: cdc, iedType
+ // attributes not needed: cdc, iedType
- public List das = new ArrayList<>();
- public List sdos = new ArrayList<>();
+ public List das = new ArrayList<>();
+ public List sdos = new ArrayList<>();
- public DoType(Node xmlNode) throws SclParseException {
+ private final String cdc;
- super(xmlNode);
+ public DoType(Node xmlNode) throws SclParseException {
- if (xmlNode.getAttributes().getNamedItem("cdc") == null) {
- throw new SclParseException("Required attribute \"cdc\" not found in DOType!");
- }
+ super(xmlNode);
+
+ if (xmlNode.getAttributes().getNamedItem("cdc") == null) {
+ throw new SclParseException("Required attribute \"cdc\" not found in DOType!");
+ } else {
+ cdc = xmlNode.getAttributes().getNamedItem("cdc").getNodeValue();
+ }
- NodeList elements = xmlNode.getChildNodes();
+ NodeList elements = xmlNode.getChildNodes();
+
+ for (int i = 0; i < elements.getLength(); i++) {
+ Node node = elements.item(i);
+ if (node.getNodeName().equals("SDO")) {
+ sdos.add(new Sdo(node));
+ }
+ if (node.getNodeName().equals("DA")) {
+ das.add(new Da(node));
+ }
+ }
+ }
- for (int i = 0; i < elements.getLength(); i++) {
- Node node = elements.item(i);
- if (node.getNodeName().equals("SDO")) {
- sdos.add(new Sdo(node));
- }
- if (node.getNodeName().equals("DA")) {
- das.add(new Da(node));
- }
+ public String getCdc() {
+ return cdc;
}
- }
}
diff --git a/src/main/java/com/beanit/iec61850bean/internal/scl/LnType.java b/src/main/java/com/beanit/iec61850bean/internal/scl/LnType.java
index 7947ec3..34e898e 100644
--- a/src/main/java/com/beanit/iec61850bean/internal/scl/LnType.java
+++ b/src/main/java/com/beanit/iec61850bean/internal/scl/LnType.java
@@ -14,32 +14,44 @@
package com.beanit.iec61850bean.internal.scl;
import com.beanit.iec61850bean.SclParseException;
-import java.util.ArrayList;
-import java.util.List;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import java.util.ArrayList;
+import java.util.List;
+
public final class LnType extends AbstractType {
- // attributes not needed: lnClass, iedType
+ // attributes not needed: lnClass, iedType
+
+ public List dos = new ArrayList<>();
+ private String lnClass;
- public List dos = new ArrayList<>();
+ public LnType(Node xmlNode) throws SclParseException {
- public LnType(Node xmlNode) throws SclParseException {
+ super(xmlNode);
- super(xmlNode);
+ if (xmlNode.getAttributes().getNamedItem("lnClass") == null) {
+ throw new SclParseException("Required attribute \"lnClass\" not found in LNType!");
+ } else {
+ lnClass = xmlNode.getAttributes().getNamedItem("lnClass").getNodeValue();
+ }
- if (xmlNode.getAttributes().getNamedItem("lnClass") == null) {
- throw new SclParseException("Required attribute \"lnClass\" not found in LNType!");
+ NodeList elements = xmlNode.getChildNodes();
+
+ for (int i = 0; i < elements.getLength(); i++) {
+ Node node = elements.item(i);
+ if (node.getNodeName().equals("DO")) {
+ dos.add(new Do(node));
+ }
+ }
}
- NodeList elements = xmlNode.getChildNodes();
+ public String getLnClass() {
+ return lnClass;
+ }
- for (int i = 0; i < elements.getLength(); i++) {
- Node node = elements.item(i);
- if (node.getNodeName().equals("DO")) {
- dos.add(new Do(node));
- }
+ public void setLnClass(String lnClass) {
+ this.lnClass = lnClass;
}
- }
}
diff --git a/src/main/java/com/beanit/jositransport/TConnection.java b/src/main/java/com/beanit/jositransport/TConnection.java
index 8cd6e71..7576e2c 100644
--- a/src/main/java/com/beanit/jositransport/TConnection.java
+++ b/src/main/java/com/beanit/jositransport/TConnection.java
@@ -14,12 +14,8 @@
package com.beanit.jositransport;
import com.beanit.iec61850bean.internal.util.SequenceNumber;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.EOFException;
-import java.io.IOException;
+
+import java.io.*;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;