Skip to content

Commit

Permalink
Feature/iec 60870 5 104 (#1088)
Browse files Browse the repository at this point in the history
* feat(plc4j/iec-60870): Finished implementing the decoding of most of the datatypes as well as the timestamp handling

* feat(plc4j/iec-60870): Finished a first rough version of the code to publish incoming IEC 60870-5-104 events to PLC4X Subscription Handlers (Still query expressions and filtering isn't implemented)

* feat(plc4j/iec-60870): Slightly changed the API for the new MetaData in PlcValues

* feat(plc4j/plc-values): Improved the PlcNull implementation of the Metadata methods.

* feat(plc4j/plc-values): Removed an odd character from the file.

* feat(plc4j/iec-60870): Made the Tag-informaiton available in subscription events.
  • Loading branch information
chrisdutz authored Sep 4, 2023
1 parent 9ef986d commit a05857e
Show file tree
Hide file tree
Showing 90 changed files with 7,991 additions and 5,959 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,10 @@ public interface PlcValue {

Map<String, ? extends PlcValue> getStruct();

Set<String> getMetaDataNames();

boolean hasMetaData(String key);

PlcValue getMetaData(String key);

}
4 changes: 4 additions & 0 deletions plc4j/drivers/iec-60870/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>

<dependency>
<groupId>org.apache.plc4x</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,9 @@ public static ASDU staticParse(ReadBuffer readBuffer) throws ParseException {
new DataReaderComplexDefault<>(
() ->
InformationObject.staticParse(
readBuffer, (TypeIdentification) (typeIdentification)),
readBuffer,
(TypeIdentification) (typeIdentification),
(byte) (typeIdentification.getNumTimeBytes())),
readBuffer),
numberOfObjects,
WithOption.WithByteOrder(ByteOrder.LITTLE_ENDIAN));
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.plc4x.java.iec608705104.readwrite;

import static org.apache.plc4x.java.spi.codegen.fields.FieldReaderFactory.*;
import static org.apache.plc4x.java.spi.codegen.fields.FieldWriterFactory.*;
import static org.apache.plc4x.java.spi.codegen.io.DataReaderFactory.*;
import static org.apache.plc4x.java.spi.codegen.io.DataWriterFactory.*;
import static org.apache.plc4x.java.spi.generation.StaticHelper.*;

import java.time.*;
import java.util.*;
import org.apache.plc4x.java.api.exceptions.*;
import org.apache.plc4x.java.api.value.*;
import org.apache.plc4x.java.spi.codegen.*;
import org.apache.plc4x.java.spi.codegen.fields.*;
import org.apache.plc4x.java.spi.codegen.io.*;
import org.apache.plc4x.java.spi.generation.*;

// Code generated by code-generation. DO NOT EDIT.

public abstract class InformationObjectWithSevenByteTime extends InformationObject
implements Message {

// Accessors for discriminator values.
public Byte getNumTimeByte() {
return (byte) 7;
}

// Abstract accessors for discriminator values.
public abstract TypeIdentification getTypeIdentification();

public InformationObjectWithSevenByteTime(int address) {
super(address);
}

public abstract SevenOctetBinaryTime getCp56Time2a();

protected abstract void serializeInformationObjectWithSevenByteTimeChild(WriteBuffer writeBuffer)
throws SerializationException;

@Override
protected void serializeInformationObjectChild(WriteBuffer writeBuffer)
throws SerializationException {
PositionAware positionAware = writeBuffer;
boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
writeBuffer.pushContext("InformationObjectWithSevenByteTime");

// Switch field (Serialize the sub-type)
serializeInformationObjectWithSevenByteTimeChild(writeBuffer);

writeBuffer.popContext("InformationObjectWithSevenByteTime");
}

@Override
public int getLengthInBytes() {
return (int) Math.ceil((float) getLengthInBits() / 8.0);
}

@Override
public int getLengthInBits() {
int lengthInBits = super.getLengthInBits();
InformationObjectWithSevenByteTime _value = this;
boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();

// Length of sub-type elements will be added by sub-type...

return lengthInBits;
}

public static InformationObjectBuilder staticParseInformationObjectBuilder(
ReadBuffer readBuffer, TypeIdentification typeIdentification, Byte numTimeByte)
throws ParseException {
readBuffer.pullContext("InformationObjectWithSevenByteTime");
PositionAware positionAware = readBuffer;
boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();

// Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
InformationObjectWithSevenByteTimeBuilder builder = null;
if (EvaluationHelper.equals(
typeIdentification, TypeIdentification.SINGLE_POINT_INFORMATION_WITH_TIME_TAG_CP56TIME2A)) {
builder =
InformationObjectWithSevenByteTime_SINGLE_POINT_INFORMATION
.staticParseInformationObjectWithSevenByteTimeBuilder(
readBuffer, typeIdentification, numTimeByte);
} else if (EvaluationHelper.equals(
typeIdentification, TypeIdentification.DOUBLE_POINT_INFORMATION_WITH_TIME_TAG_CP56TIME2A)) {
builder =
InformationObjectWithSevenByteTime_DOUBLE_POINT_INFORMATION
.staticParseInformationObjectWithSevenByteTimeBuilder(
readBuffer, typeIdentification, numTimeByte);
} else if (EvaluationHelper.equals(
typeIdentification,
TypeIdentification.STEP_POSITION_INFORMATION_WITH_TIME_TAG_CP56TIME2A)) {
builder =
InformationObjectWithSevenByteTime_STEP_POSITION_INFORMATION
.staticParseInformationObjectWithSevenByteTimeBuilder(
readBuffer, typeIdentification, numTimeByte);
} else if (EvaluationHelper.equals(
typeIdentification, TypeIdentification.BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A)) {
builder =
InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT
.staticParseInformationObjectWithSevenByteTimeBuilder(
readBuffer, typeIdentification, numTimeByte);
} else if (EvaluationHelper.equals(
typeIdentification,
TypeIdentification.MEASURED_VALUE_NORMALISED_VALUE_WITH_TIME_TAG_CP56TIME2A)) {
builder =
InformationObjectWithSevenByteTime_MEASURED_VALUE_NORMALISED_VALUE
.staticParseInformationObjectWithSevenByteTimeBuilder(
readBuffer, typeIdentification, numTimeByte);
} else if (EvaluationHelper.equals(
typeIdentification,
TypeIdentification.MEASURED_VALUE_SCALED_VALUE_WITH_TIME_TAG_CP56TIME2A)) {
builder =
InformationObjectWithSevenByteTime_MEASURED_VALUE_SCALED_VALUE
.staticParseInformationObjectWithSevenByteTimeBuilder(
readBuffer, typeIdentification, numTimeByte);
} else if (EvaluationHelper.equals(
typeIdentification,
TypeIdentification.MEASURED_VALUE_SHORT_FLOATING_POINT_NUMBER_WITH_TIME_TAG_CP56TIME2A)) {
builder =
InformationObjectWithSevenByteTime_MEASURED_VALUE_SHORT_FLOATING_POINT_NUMBER
.staticParseInformationObjectWithSevenByteTimeBuilder(
readBuffer, typeIdentification, numTimeByte);
} else if (EvaluationHelper.equals(
typeIdentification, TypeIdentification.INTEGRATED_TOTALS_WITH_TIME_TAG_CP56TIME2A)) {
builder =
InformationObjectWithSevenByteTime_INTEGRATED_TOTALS
.staticParseInformationObjectWithSevenByteTimeBuilder(
readBuffer, typeIdentification, numTimeByte);
} else if (EvaluationHelper.equals(
typeIdentification,
TypeIdentification.EVENT_OF_PROTECTION_EQUIPMENT_WITH_TIME_TAG_CP56TIME2A)) {
builder =
InformationObjectWithSevenByteTime_EVENT_OF_PROTECTION_EQUIPMENT
.staticParseInformationObjectWithSevenByteTimeBuilder(
readBuffer, typeIdentification, numTimeByte);
} else if (EvaluationHelper.equals(
typeIdentification,
TypeIdentification.PACKED_START_EVENTS_OF_PROTECTION_EQUIPMENT_WITH_TIME_TAG_CP56TIME2A)) {
builder =
InformationObjectWithSevenByteTime_PACKED_START_EVENTS_OF_PROTECTION_EQUIPMENT
.staticParseInformationObjectWithSevenByteTimeBuilder(
readBuffer, typeIdentification, numTimeByte);
} else if (EvaluationHelper.equals(
typeIdentification,
TypeIdentification
.PACKED_OUTPUT_CIRCUIT_INFORMATION_OF_PROTECTION_EQUIPMENT_WITH_TIME_TAG_CP56TIME2A)) {
builder =
InformationObjectWithSevenByteTime_PACKED_OUTPUT_CIRCUIT_INFORMATION_OF_PROTECTION_EQUIPMENT
.staticParseInformationObjectWithSevenByteTimeBuilder(
readBuffer, typeIdentification, numTimeByte);
}
if (builder == null) {
throw new ParseException(
"Unsupported case for discriminated type"
+ " parameters ["
+ "typeIdentification="
+ typeIdentification
+ "]");
}

readBuffer.closeContext("InformationObjectWithSevenByteTime");
// Create the instance
return new InformationObjectWithSevenByteTimeBuilderImpl(builder);
}

public interface InformationObjectWithSevenByteTimeBuilder {
InformationObjectWithSevenByteTime build(int address);
}

public static class InformationObjectWithSevenByteTimeBuilderImpl
implements InformationObject.InformationObjectBuilder {
private final InformationObjectWithSevenByteTimeBuilder builder;

public InformationObjectWithSevenByteTimeBuilderImpl(
InformationObjectWithSevenByteTimeBuilder builder) {
this.builder = builder;
}

public InformationObjectWithSevenByteTime build(int address) {
return builder.build(address);
}
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof InformationObjectWithSevenByteTime)) {
return false;
}
InformationObjectWithSevenByteTime that = (InformationObjectWithSevenByteTime) o;
return super.equals(that) && true;
}

@Override
public int hashCode() {
return Objects.hash(super.hashCode());
}

@Override
public String toString() {
WriteBufferBoxBased writeBufferBoxBased = new WriteBufferBoxBased(true, true);
try {
writeBufferBoxBased.writeSerializable(this);
} catch (SerializationException e) {
throw new RuntimeException(e);
}
return "\n" + writeBufferBoxBased.getBox().toString() + "\n";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@

// Code generated by code-generation. DO NOT EDIT.

public class InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A
extends InformationObject implements Message {
public class InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT
extends InformationObjectWithSevenByteTime implements Message {

// Accessors for discriminator values.
public TypeIdentification getTypeIdentification() {
Expand All @@ -48,7 +48,7 @@ public TypeIdentification getTypeIdentification() {
protected final QualityDescriptor qds;
protected final SevenOctetBinaryTime cp56Time2a;

public InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A(
public InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT(
int address,
BinaryStateInformation bsi,
QualityDescriptor qds,
Expand All @@ -72,11 +72,11 @@ public SevenOctetBinaryTime getCp56Time2a() {
}

@Override
protected void serializeInformationObjectChild(WriteBuffer writeBuffer)
protected void serializeInformationObjectWithSevenByteTimeChild(WriteBuffer writeBuffer)
throws SerializationException {
PositionAware positionAware = writeBuffer;
boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
writeBuffer.pushContext("InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A");
writeBuffer.pushContext("InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT");

// Simple Field (bsi)
writeSimpleField(
Expand All @@ -99,7 +99,7 @@ protected void serializeInformationObjectChild(WriteBuffer writeBuffer)
new DataWriterComplexDefault<>(writeBuffer),
WithOption.WithByteOrder(ByteOrder.LITTLE_ENDIAN));

writeBuffer.popContext("InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A");
writeBuffer.popContext("InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT");
}

@Override
Expand All @@ -110,7 +110,7 @@ public int getLengthInBytes() {
@Override
public int getLengthInBits() {
int lengthInBits = super.getLengthInBits();
InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A _value = this;
InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT _value = this;
boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();

// Simple field (bsi)
Expand All @@ -125,9 +125,11 @@ public int getLengthInBits() {
return lengthInBits;
}

public static InformationObjectBuilder staticParseInformationObjectBuilder(
ReadBuffer readBuffer, TypeIdentification typeIdentification) throws ParseException {
readBuffer.pullContext("InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A");
public static InformationObjectWithSevenByteTimeBuilder
staticParseInformationObjectWithSevenByteTimeBuilder(
ReadBuffer readBuffer, TypeIdentification typeIdentification, Byte numTimeByte)
throws ParseException {
readBuffer.pullContext("InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT");
PositionAware positionAware = readBuffer;
boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();

Expand All @@ -152,31 +154,31 @@ public static InformationObjectBuilder staticParseInformationObjectBuilder(
() -> SevenOctetBinaryTime.staticParse(readBuffer), readBuffer),
WithOption.WithByteOrder(ByteOrder.LITTLE_ENDIAN));

readBuffer.closeContext("InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A");
readBuffer.closeContext("InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT");
// Create the instance
return new InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2ABuilderImpl(
return new InformationObjectWithSevenByteTime_BITSTRING_OF_32_BITBuilderImpl(
bsi, qds, cp56Time2a);
}

public static class InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2ABuilderImpl
implements InformationObject.InformationObjectBuilder {
public static class InformationObjectWithSevenByteTime_BITSTRING_OF_32_BITBuilderImpl
implements InformationObjectWithSevenByteTime.InformationObjectWithSevenByteTimeBuilder {
private final BinaryStateInformation bsi;
private final QualityDescriptor qds;
private final SevenOctetBinaryTime cp56Time2a;

public InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2ABuilderImpl(
public InformationObjectWithSevenByteTime_BITSTRING_OF_32_BITBuilderImpl(
BinaryStateInformation bsi, QualityDescriptor qds, SevenOctetBinaryTime cp56Time2a) {
this.bsi = bsi;
this.qds = qds;
this.cp56Time2a = cp56Time2a;
}

public InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A build(int address) {
InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A
informationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A =
new InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A(
public InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT build(int address) {
InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT
informationObjectWithSevenByteTime_BITSTRING_OF_32_BIT =
new InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT(
address, bsi, qds, cp56Time2a);
return informationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A;
return informationObjectWithSevenByteTime_BITSTRING_OF_32_BIT;
}
}

Expand All @@ -185,11 +187,11 @@ public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A)) {
if (!(o instanceof InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT)) {
return false;
}
InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A that =
(InformationObject_BITSTRING_OF_32_BIT_WITH_TIME_TAG_CP56TIME2A) o;
InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT that =
(InformationObjectWithSevenByteTime_BITSTRING_OF_32_BIT) o;
return (getBsi() == that.getBsi())
&& (getQds() == that.getQds())
&& (getCp56Time2a() == that.getCp56Time2a())
Expand Down
Loading

0 comments on commit a05857e

Please sign in to comment.