This is an automated email from the ASF dual-hosted git repository. cdutz pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git
The following commit(s) were added to refs/heads/master by this push: new 24cdf38 - Removed the cyclic dependencies within the protocol layers. 24cdf38 is described below commit 24cdf38c03ebc788259ed67e85acd2872a2a3ff2 Author: Christofer Dutz <christofer.d...@c-ware.de> AuthorDate: Thu Apr 12 16:23:43 2018 +0200 - Removed the cyclic dependencies within the protocol layers. --- .../java/isoontcp/netty/IsoOnTcpProtocol.java | 8 + .../plc4x/java/isotp/netty/IsoTPProtocol.java | 92 ++++--- .../netty/model/params/CalledTsapParameter.java | 5 +- .../netty/model/params/CallingTsapParameter.java | 5 +- .../isotp/netty/model/params/TsapParameter.java | 30 +- .../plc4x/java/s7/connection/S7PlcConnection.java | 7 +- .../plc4x/java/s7/netty/Plc4XS7Protocol.java | 305 +++++++++++---------- .../org/apache/plc4x/java/s7/netty/S7Protocol.java | 103 ++++--- .../utils/S7TsapIdEncoder.java} | 30 +- .../plc4x/java/isotp/netty/IsoTPProtocolTest.java | 73 ++--- .../netty/model/params/TsapParameterTests.java | 17 +- 11 files changed, 358 insertions(+), 317 deletions(-) diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isoontcp/netty/IsoOnTcpProtocol.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isoontcp/netty/IsoOnTcpProtocol.java index 2a330e8..14ed866 100644 --- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isoontcp/netty/IsoOnTcpProtocol.java +++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isoontcp/netty/IsoOnTcpProtocol.java @@ -36,6 +36,10 @@ public class IsoOnTcpProtocol extends PlcMessageToMessageCodec<ByteBuf, IsoOnTcp private static final Logger logger = LoggerFactory.getLogger(IsoOnTcpProtocol.class); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Encoding + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override protected void encode(ChannelHandlerContext ctx, IsoOnTcpMessage in, List<Object> out) throws Exception { logger.debug("ISO on TCP RawMessage sent"); @@ -63,6 +67,10 @@ public class IsoOnTcpProtocol extends PlcMessageToMessageCodec<ByteBuf, IsoOnTcp out.add(buf); } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Decoding + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if(logger.isTraceEnabled()) { diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocol.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocol.java index b295db6..5ff5407 100644 --- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocol.java +++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocol.java @@ -44,19 +44,24 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd private static final Logger logger = LoggerFactory.getLogger(IsoTPProtocol.class); - private final byte rackNo; - private final byte slotNo; - private final TpduSize tpduSize; + private short callingTsapId; + private short calledTsapId; + private TpduSize tpduSize; - private CalledTsapParameter calledTsapParameter; - private TpduSizeParameter tpduSizeParameter; - - public IsoTPProtocol(byte rackNo, byte slotNo, TpduSize tpduSize) { - this.rackNo = rackNo; - this.slotNo = slotNo; + public IsoTPProtocol(short callingTsapId, short calledTsapId, TpduSize tpduSize) { + this.callingTsapId = callingTsapId; + this.calledTsapId = calledTsapId; this.tpduSize = tpduSize; } + /** + * If the IsoTP protocol is used on top of the ISO on TCP protocol, then as soon as the pipeline receives the + * request to connect, an IsoTP connection request TPDU must be sent in order to initialize the connection. + * + * @param ctx the current protocol layers context + * @param evt the event + * @throws Exception throws an exception if something goes wrong internally + */ @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { ChannelHandler prevHandler = getPrevChannelHandler(ctx); @@ -69,8 +74,8 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd ConnectionRequestTpdu connectionRequest = new ConnectionRequestTpdu( (short) 0x0000, (short) 0x000F, ProtocolClass.CLASS_0, Arrays.asList( - new CalledTsapParameter(DeviceGroup.PG_OR_PC, (byte) 0, (byte) 0), - new CallingTsapParameter(DeviceGroup.OTHERS, rackNo, slotNo), + new CalledTsapParameter(calledTsapId), + new CallingTsapParameter(callingTsapId), new TpduSizeParameter(tpduSize)), Unpooled.buffer()); ctx.channel().writeAndFlush(connectionRequest); @@ -80,6 +85,7 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Encoding //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @Override @@ -100,17 +106,17 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd switch (in.getTpduCode()) { case CONNECTION_REQUEST: case CONNECTION_CONFIRM: - encodeConnecton(in, buf); + encodeConnectionTpdu(in, buf); break; case DATA: - encodeData((DataTpdu) in, buf); + encodeDataTpdu((DataTpdu) in, buf); break; case DISCONNECT_REQUEST: case DISCONNECT_CONFIRM: - encodeDisconnect(in, buf); + encodeDisconnectTpdu(in, buf); break; case TPDU_ERROR: - encodeError(in, buf); + encodeErrorTpdu(in, buf); break; default: if (logger.isErrorEnabled()) { @@ -130,14 +136,14 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd } } - private void encodeError(Tpdu in, ByteBuf buf) { + private void encodeErrorTpdu(Tpdu in, ByteBuf buf) { ErrorTpdu errorTpdu = (ErrorTpdu) in; buf.writeShort(errorTpdu.getDestinationReference()); buf.writeByte(errorTpdu.getRejectCause().getCode()); encodeParameters(buf, in.getParameters()); } - private void encodeDisconnect(Tpdu in, ByteBuf buf) { + private void encodeDisconnectTpdu(Tpdu in, ByteBuf buf) { DisconnectTpdu disconnectTpdu = (DisconnectTpdu) in; buf.writeShort(disconnectTpdu.getDestinationReference()); buf.writeShort(disconnectTpdu.getSourceReference()); @@ -148,13 +154,13 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd encodeParameters(buf, in.getParameters()); } - private void encodeData(DataTpdu in, ByteBuf buf) { + private void encodeDataTpdu(DataTpdu in, ByteBuf buf) { // EOT (Bit 8 = 1) / TPDU (All other bits 0) buf.writeByte((byte) (in.getTpduRef() | (in.isEot() ? 0x80 : 0x00))); // Note: A Data TPDU in Class 0 doesn't have parameters } - private void encodeConnecton(Tpdu in, ByteBuf buf) { + private void encodeConnectionTpdu(Tpdu in, ByteBuf buf) { ConnectionTpdu connectionTpdu = (ConnectionTpdu) in; buf.writeShort(connectionTpdu.getDestinationReference()); buf.writeShort(connectionTpdu.getSourceReference()); @@ -174,8 +180,7 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd case CALLED_TSAP: case CALLING_TSAP: TsapParameter tsap = (TsapParameter) parameter; - out.writeByte(tsap.getDeviceGroup().getCode()); - out.writeByte((byte) ((tsap.getRackNumber() << 4) | (tsap.getSlotNumber() & 0x0F))); + out.writeShort(tsap.getTsapId()); break; case CHECKSUM: ChecksumParameter checksum = (ChecksumParameter) parameter; @@ -198,6 +203,10 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd } } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Decoding + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override protected void decode(ChannelHandlerContext ctx, IsoOnTcpMessage in, List<Object> out) { if (logger.isTraceEnabled()) { @@ -224,17 +233,17 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd switch (tpduCode) { case CONNECTION_REQUEST: case CONNECTION_CONFIRM: - tpdu = decodeConnection(ctx, userData, tpduCode, parameters); + tpdu = decodeConnectTpdu(ctx, userData, tpduCode, parameters); break; case DATA: - tpdu = decodeData(userData, parameters); + tpdu = decodeDataTpdu(userData, parameters); break; case DISCONNECT_REQUEST: case DISCONNECT_CONFIRM: - tpdu = decodeDisconnect(userData, tpduCode, parameters); + tpdu = decodeDisconnectTpdu(userData, tpduCode, parameters); break; case TPDU_ERROR: - tpdu = decodeError(userData, parameters); + tpdu = decodeErrorTpdu(userData, parameters); break; default: if (logger.isErrorEnabled()) { @@ -257,16 +266,16 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd // Save some of the information in the session and tell the next // layer to negotiate the connection parameters. if (tpdu instanceof ConnectionConfirmTpdu) { - // TODO: check if null is a valid value (fails test: org.apache.plc4x.java.isotp.netty.IsoTPProtocolTest.decodeConnectionConfirm) - calledTsapParameter = tpdu.getParameter(CalledTsapParameter.class).orElse(null); - // TODO: check if null is a valid value (fails test: org.apache.plc4x.java.isotp.netty.IsoTPProtocolTest.decodeConnectionConfirm) - tpduSizeParameter = tpdu.getParameter(TpduSizeParameter.class).orElse(null); + tpdu.getParameter(CalledTsapParameter.class).ifPresent( + calledTsapParameter -> calledTsapId = calledTsapParameter.getTsapId()); + tpdu.getParameter(TpduSizeParameter.class).ifPresent( + tpduSizeParameter -> tpduSize = tpduSizeParameter.getTpduSize()); } out.add(new IsoTPMessage(tpdu, userData)); } } - private Tpdu decodeError(ByteBuf userData, List<Parameter> parameters) { + private Tpdu decodeErrorTpdu(ByteBuf userData, List<Parameter> parameters) { Tpdu tpdu; short destinationReference = userData.readShort(); RejectCause rejectCause = RejectCause.valueOf(userData.readByte()); @@ -274,7 +283,7 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd return tpdu; } - private Tpdu decodeDisconnect(ByteBuf userData, TpduCode tpduCode, List<Parameter> parameters) { + private Tpdu decodeDisconnectTpdu(ByteBuf userData, TpduCode tpduCode, List<Parameter> parameters) { Tpdu tpdu; short destinationReference = userData.readShort(); short sourceReference = userData.readShort(); @@ -289,7 +298,7 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd return tpdu; } - private Tpdu decodeData(ByteBuf userData, List<Parameter> parameters) { + private Tpdu decodeDataTpdu(ByteBuf userData, List<Parameter> parameters) { Tpdu tpdu; byte tmp = userData.readByte(); boolean eot = (tmp & 0x80) == 0x80; @@ -298,7 +307,7 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd return tpdu; } - private Tpdu decodeConnection(ChannelHandlerContext ctx, ByteBuf userData, TpduCode tpduCode, List<Parameter> parameters) { + private Tpdu decodeConnectTpdu(ChannelHandlerContext ctx, ByteBuf userData, TpduCode tpduCode, List<Parameter> parameters) { Tpdu tpdu; short destinationReference = userData.readShort(); short sourceReference = userData.readShort(); @@ -324,7 +333,7 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd switch (parameterCode) { case CALLING_TSAP: case CALLED_TSAP: - return decodeCallParameter(out, parameterCode); + return decodeTsapParameter(out, parameterCode); case CHECKSUM: byte checksum = out.readByte(); return new ChecksumParameter(checksum); @@ -343,16 +352,13 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd } } - private Parameter decodeCallParameter(ByteBuf out, ParameterCode parameterCode) { - DeviceGroup deviceGroup = DeviceGroup.valueOf(out.readByte()); - byte rackAndSlot = out.readByte(); - byte rackId = (byte) ((rackAndSlot & 0xF0) >> 4); - byte slotId = (byte) (rackAndSlot & 0x0F); + private Parameter decodeTsapParameter(ByteBuf out, ParameterCode parameterCode) { + short tsapId = out.readShort(); switch (parameterCode) { case CALLING_TSAP: - return new CallingTsapParameter(deviceGroup, rackId, slotId); + return new CallingTsapParameter(tsapId); case CALLED_TSAP: - return new CalledTsapParameter(deviceGroup, rackId, slotId); + return new CalledTsapParameter(tsapId); default: if (logger.isErrorEnabled()) { logger.error("Parameter not implemented yet {}", parameterCode.name()); @@ -361,6 +367,10 @@ public class IsoTPProtocol extends PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd } } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Helpers + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** * Return the length of the entire header in bytes (including the size field itself) * This is a sum of the fixed size header defined for the given tpdu type and the diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CalledTsapParameter.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CalledTsapParameter.java index fbd8589..a9446f3 100644 --- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CalledTsapParameter.java +++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CalledTsapParameter.java @@ -18,13 +18,12 @@ under the License. */ package org.apache.plc4x.java.isotp.netty.model.params; -import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup; import org.apache.plc4x.java.isotp.netty.model.types.ParameterCode; public class CalledTsapParameter extends TsapParameter { - public CalledTsapParameter(DeviceGroup deviceGroup, byte rackNumber, byte slotNumber) { - super(deviceGroup, rackNumber, slotNumber); + public CalledTsapParameter(short tsapId) { + super(tsapId); } @Override diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CallingTsapParameter.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CallingTsapParameter.java index b3cb6e4..a4dd393 100644 --- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CallingTsapParameter.java +++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CallingTsapParameter.java @@ -18,13 +18,12 @@ under the License. */ package org.apache.plc4x.java.isotp.netty.model.params; -import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup; import org.apache.plc4x.java.isotp.netty.model.types.ParameterCode; public class CallingTsapParameter extends TsapParameter { - public CallingTsapParameter(DeviceGroup deviceGroup, byte rackNumber, byte slotNumber) { - super(deviceGroup, rackNumber, slotNumber); + public CallingTsapParameter(short tsapId) { + super(tsapId); } @Override diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java index 2d7f2d2..6439008 100644 --- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java +++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java @@ -18,31 +18,21 @@ under the License. */ package org.apache.plc4x.java.isotp.netty.model.params; - -import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup; - +/** + * Base class for calling and called TSAPs + * TODO: I find it strange to have these parameters directly relate to S7 specifics as they should not need to be known in the IsoTP protocol. + * Optionally it might be a good idea to have some mechanism + */ public abstract class TsapParameter implements Parameter { - private final DeviceGroup deviceGroup; - private final byte rackNumber; - private final byte slotNumber; - - public TsapParameter(DeviceGroup deviceGroup, byte rackNumber, byte slotNumber) { - this.deviceGroup = deviceGroup; - this.rackNumber = rackNumber; - this.slotNumber = slotNumber; - } - - public DeviceGroup getDeviceGroup() { - return deviceGroup; - } + private final short tsapId; - public byte getRackNumber() { - return rackNumber; + public TsapParameter(short tsapId) { + this.tsapId = tsapId; } - public byte getSlotNumber() { - return slotNumber; + public short getTsapId() { + return tsapId; } } diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/connection/S7PlcConnection.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/connection/S7PlcConnection.java index e224544..396b4c6 100644 --- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/connection/S7PlcConnection.java +++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/connection/S7PlcConnection.java @@ -34,6 +34,7 @@ import org.apache.plc4x.java.base.events.ConnectedEvent; import org.apache.plc4x.java.isoontcp.netty.IsoOnTcpProtocol; import org.apache.plc4x.java.isotp.netty.IsoTPProtocol; import org.apache.plc4x.java.isotp.netty.model.tpdus.DisconnectRequestTpdu; +import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup; import org.apache.plc4x.java.isotp.netty.model.types.DisconnectReason; import org.apache.plc4x.java.isotp.netty.model.types.TpduSize; import org.apache.plc4x.java.s7.model.S7Address; @@ -42,6 +43,7 @@ import org.apache.plc4x.java.s7.model.S7DataBlockAddress; import org.apache.plc4x.java.s7.netty.Plc4XS7Protocol; import org.apache.plc4x.java.s7.netty.S7Protocol; import org.apache.plc4x.java.s7.netty.model.types.MemoryArea; +import org.apache.plc4x.java.s7.utils.S7TsapIdEncoder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -121,6 +123,9 @@ public class S7PlcConnection extends AbstractPlcConnection implements PlcReader, @Override protected ChannelHandler getChannelHandler(CompletableFuture<Void> sessionSetupCompleteFuture) { + short calledTsapId = S7TsapIdEncoder.encodeS7TsapId(DeviceGroup.OTHERS, rack, slot); + short callingTsapId = S7TsapIdEncoder.encodeS7TsapId(DeviceGroup.PG_OR_PC, 0, 0); + return new ChannelInitializer() { @Override protected void initChannel(Channel channel) { @@ -137,7 +142,7 @@ public class S7PlcConnection extends AbstractPlcConnection implements PlcReader, } }); pipeline.addLast(new IsoOnTcpProtocol()); - pipeline.addLast(new IsoTPProtocol((byte) rack, (byte) slot, paramPduSize)); + pipeline.addLast(new IsoTPProtocol(callingTsapId, calledTsapId, paramPduSize)); pipeline.addLast(new S7Protocol(paramMaxAmqCaller, paramMaxAmqCallee, (short) paramPduSize.getValue())); pipeline.addLast(new Plc4XS7Protocol()); } diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java index f5c12f9..1d41aea 100644 --- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java +++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java @@ -65,6 +65,14 @@ public class Plc4XS7Protocol extends PlcMessageToMessageCodec<S7Message, PlcRequ this.requests = new HashMap<>(); } + /** + * If this protocol layer catches an {@link S7ConnectedEvent} from the protocol layer beneath, + * the connection establishment is finished. + * + * @param ctx the current protocol layers context + * @param evt the event + * @throws Exception throws an exception if something goes wrong internally + */ @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof S7ConnectedEvent) { @@ -74,6 +82,40 @@ public class Plc4XS7Protocol extends PlcMessageToMessageCodec<S7Message, PlcRequ } } + /** + * When receiving an error inside the pipeline, we have to find out which {@link PlcRequestContainer} + * correlates needs to be notified about the problem. If a container is found, we can relay the + * exception to that by calling completeExceptionally and passing in the exception. + * + * @param ctx the current protocol layers context + * @param cause the exception that was caught + * @throws Exception throws an exception if something goes wrong internally + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if(cause instanceof PlcProtocolPayloadTooBigException) { + PlcProtocolPayloadTooBigException pptbe = (PlcProtocolPayloadTooBigException) cause; + if(pptbe.getPayload() instanceof S7RequestMessage) { + S7RequestMessage request = (S7RequestMessage) pptbe.getPayload(); + if(request.getParent() instanceof PlcRequestContainer) { + PlcRequestContainer requestContainer = (PlcRequestContainer) request.getParent(); + + // Remove the current request from the unconfirmed requests list. + if(requests.containsKey(request.getTpduReference())) { + requests.remove(request.getTpduReference()); + } + + requestContainer.getResponseFuture().completeExceptionally(cause); + } + } + } + super.exceptionCaught(ctx, cause); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Encoding + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override protected void encode(ChannelHandlerContext ctx, PlcRequestContainer msg, List<Object> out) throws Exception { PlcRequest request = msg.getRequest(); @@ -84,6 +126,23 @@ public class Plc4XS7Protocol extends PlcMessageToMessageCodec<S7Message, PlcRequ } } + private void encodeReadRequest(PlcRequestContainer msg, List<Object> out) throws PlcException { + List<VarParameterItem> parameterItems = new LinkedList<>(); + + PlcReadRequest readRequest = (PlcReadRequest) msg.getRequest(); + encodeParameterItems(parameterItems, readRequest); + VarParameter readVarParameter = new VarParameter(ParameterType.READ_VAR, parameterItems); + + // Assemble the request. + S7RequestMessage s7ReadRequest = new S7RequestMessage(MessageType.JOB, + (short) tpduGenerator.getAndIncrement(), Collections.singletonList(readVarParameter), + Collections.emptyList(), msg); + + requests.put(s7ReadRequest.getTpduReference(), msg); + + out.add(s7ReadRequest); + } + private void encodeWriteRequest(PlcRequestContainer msg, List<Object> out) throws PlcException { List<VarParameterItem> parameterItems = new LinkedList<>(); List<VarPayloadItem> payloadItems = new LinkedList<>(); @@ -125,23 +184,6 @@ public class Plc4XS7Protocol extends PlcMessageToMessageCodec<S7Message, PlcRequ out.add(s7WriteRequest); } - private void encodeReadRequest(PlcRequestContainer msg, List<Object> out) throws PlcException { - List<VarParameterItem> parameterItems = new LinkedList<>(); - - PlcReadRequest readRequest = (PlcReadRequest) msg.getRequest(); - encodeParameterItems(parameterItems, readRequest); - VarParameter readVarParameter = new VarParameter(ParameterType.READ_VAR, parameterItems); - - // Assemble the request. - S7RequestMessage s7ReadRequest = new S7RequestMessage(MessageType.JOB, - (short) tpduGenerator.getAndIncrement(), Collections.singletonList(readVarParameter), - Collections.emptyList(), msg); - - requests.put(s7ReadRequest.getTpduReference(), msg); - - out.add(s7ReadRequest); - } - private void encodeParameterItems(List<VarParameterItem> parameterItems, PlcReadRequest readRequest) throws PlcException { for (ReadRequestItem requestItem : readRequest.getRequestItems()) { // Try to get the correct S7 transport size for the given data type. @@ -157,6 +199,75 @@ public class Plc4XS7Protocol extends PlcMessageToMessageCodec<S7Message, PlcRequ } } + private VarParameterItem encodeVarParameterItem(Address address, TransportSize transportSize, int size) throws PlcProtocolException { + // Depending on the address type, generate the corresponding type of request item. + if (!(address instanceof S7Address)) { + throw new PlcProtocolException("Can only use S7Address types on S7 connection"); + } + S7Address s7Address = (S7Address) address; + if (s7Address instanceof S7DataBlockAddress) { + S7DataBlockAddress s7DataBlockAddress = (S7DataBlockAddress) s7Address; + return new S7AnyVarParameterItem( + SpecificationType.VARIABLE_SPECIFICATION, s7Address.getMemoryArea(), + transportSize, (short) size, + s7DataBlockAddress.getDataBlockNumber(), s7DataBlockAddress.getByteOffset(), (byte) 0); + } else if (s7Address instanceof S7BitAddress) { + S7BitAddress s7BitAddress = (S7BitAddress) s7Address; + return new S7AnyVarParameterItem( + SpecificationType.VARIABLE_SPECIFICATION, s7Address.getMemoryArea(), + transportSize, (short) size, (short) 0, + s7Address.getByteOffset(), s7BitAddress.getBitOffset()); + } else { + return new S7AnyVarParameterItem( + SpecificationType.VARIABLE_SPECIFICATION, s7Address.getMemoryArea(), + transportSize, (short) size, (short) 0, + s7Address.getByteOffset(), (byte) 0); + } + } + + private TransportSize encodeTransportSize(Class<?> datatype) { + if (datatype == Boolean.class) { + return TransportSize.BIT; + } else if (datatype == Byte.class) { + return TransportSize.BYTE; + } else if (datatype == Short.class) { + return TransportSize.WORD; + } else if (datatype == Calendar.class) { + return TransportSize.DATE_AND_TIME; + } else if (datatype == Float.class) { + return TransportSize.REAL; + } else if (datatype == Integer.class) { + return TransportSize.DWORD; + } else if (datatype == String.class) { + return TransportSize.CHAR; + } + return null; + } + + private DataTransportSize encodeDataTransportSize(Class<?> datatype) { + if (datatype == Boolean.class) { + return DataTransportSize.BIT; + } else if (datatype == Byte.class) { + return DataTransportSize.BYTE_WORD_DWORD; + } else if (datatype == Short.class) { + return DataTransportSize.BYTE_WORD_DWORD; + } else if (datatype == Calendar.class) { + // TODO: Decide what to do here ... + return null; + } else if (datatype == Float.class) { + return DataTransportSize.REAL; + } else if (datatype == Integer.class) { + return DataTransportSize.BYTE_WORD_DWORD; + } else if (datatype == String.class) { + return DataTransportSize.OCTET_STRING; + } + return null; + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Decoding + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @SuppressWarnings("unchecked") @Override protected void decode(ChannelHandlerContext ctx, S7Message msg, List<Object> out) throws Exception { @@ -172,9 +283,9 @@ public class Plc4XS7Protocol extends PlcMessageToMessageCodec<S7Message, PlcRequ // Handle the response to a read request. if (request instanceof PlcReadRequest) { - response = decodeReadRequest(responseMessage, requestContainer); + response = decodeReadResponse(responseMessage, requestContainer); } else if (request instanceof PlcWriteRequest) { - response = decodeWriteRequest(responseMessage, requestContainer); + response = decodeWriteResponse(responseMessage, requestContainer); } // Confirm the response being handled. @@ -184,66 +295,8 @@ public class Plc4XS7Protocol extends PlcMessageToMessageCodec<S7Message, PlcRequ } } - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if(cause instanceof PlcProtocolPayloadTooBigException) { - PlcProtocolPayloadTooBigException pptbe = (PlcProtocolPayloadTooBigException) cause; - if(pptbe.getPayload() instanceof S7RequestMessage) { - S7RequestMessage request = (S7RequestMessage) pptbe.getPayload(); - if(request.getParent() instanceof PlcRequestContainer) { - PlcRequestContainer requestContainer = (PlcRequestContainer) request.getParent(); - - // Remove the current request from the unconfirmed requests list. - if(requests.containsKey(request.getTpduReference())) { - requests.remove(request.getTpduReference()); - } - - requestContainer.getResponseFuture().completeExceptionally(cause); - } - } - } - super.exceptionCaught(ctx, cause); - } - @SuppressWarnings("unchecked") - private PlcResponse decodeWriteRequest(S7ResponseMessage responseMessage, PlcRequestContainer requestContainer) throws PlcProtocolException { - PlcResponse response; - PlcWriteRequest plcWriteRequest = (PlcWriteRequest) requestContainer.getRequest(); - List<WriteResponseItem<?>> responseItems = new LinkedList<>(); - VarPayload payload = responseMessage.getPayload(VarPayload.class) - .orElseThrow(() -> new PlcProtocolException("No VarPayload supplied")); - // If the numbers of items don't match, we're in big trouble as the only - // way to know how to interpret the responses is by aligning them with the - // items from the request as this information is not returned by the PLC. - if (plcWriteRequest.getRequestItems().size() != payload.getPayloadItems().size()) { - throw new PlcProtocolException( - "The number of requested items doesn't match the number of returned items"); - } - List<VarPayloadItem> payloadItems = payload.getPayloadItems(); - final int noPayLoadItems = payloadItems.size(); - for (int i = 0; i < noPayLoadItems; i++) { - VarPayloadItem payloadItem = payloadItems.get(i); - - // Get the request item for this payload item - WriteRequestItem requestItem = plcWriteRequest.getRequestItems().get(i); - - // A write response contains only the return code for every item. - ResponseCode responseCode = decodeResponseCode(payloadItem.getReturnCode()); - - WriteResponseItem responseItem = new WriteResponseItem(requestItem, responseCode); - responseItems.add(responseItem); - } - - if (plcWriteRequest instanceof TypeSafePlcWriteRequest) { - response = new TypeSafePlcWriteResponse((TypeSafePlcWriteRequest) plcWriteRequest, responseItems); - } else { - response = new PlcWriteResponse(plcWriteRequest, responseItems); - } - return response; - } - - @SuppressWarnings("unchecked") - private PlcResponse decodeReadRequest(S7ResponseMessage responseMessage, PlcRequestContainer requestContainer) throws PlcProtocolException { + private PlcResponse decodeReadResponse(S7ResponseMessage responseMessage, PlcRequestContainer requestContainer) throws PlcProtocolException { PlcResponse response; PlcReadRequest plcReadRequest = (PlcReadRequest) requestContainer.getRequest(); @@ -289,79 +342,43 @@ public class Plc4XS7Protocol extends PlcMessageToMessageCodec<S7Message, PlcRequ return response; } - //////////////////////////////////////////////////////////////////////////////// - // Encoding helpers. - //////////////////////////////////////////////////////////////////////////////// - - private VarParameterItem encodeVarParameterItem(Address address, TransportSize transportSize, int size) throws PlcProtocolException { - // Depending on the address type, generate the corresponding type of request item. - if (!(address instanceof S7Address)) { - throw new PlcProtocolException("Can only use S7Address types on S7 connection"); - } - S7Address s7Address = (S7Address) address; - if (s7Address instanceof S7DataBlockAddress) { - S7DataBlockAddress s7DataBlockAddress = (S7DataBlockAddress) s7Address; - return new S7AnyVarParameterItem( - SpecificationType.VARIABLE_SPECIFICATION, s7Address.getMemoryArea(), - transportSize, (short) size, - s7DataBlockAddress.getDataBlockNumber(), s7DataBlockAddress.getByteOffset(), (byte) 0); - } else if (s7Address instanceof S7BitAddress) { - S7BitAddress s7BitAddress = (S7BitAddress) s7Address; - return new S7AnyVarParameterItem( - SpecificationType.VARIABLE_SPECIFICATION, s7Address.getMemoryArea(), - transportSize, (short) size, (short) 0, - s7Address.getByteOffset(), s7BitAddress.getBitOffset()); - } else { - return new S7AnyVarParameterItem( - SpecificationType.VARIABLE_SPECIFICATION, s7Address.getMemoryArea(), - transportSize, (short) size, (short) 0, - s7Address.getByteOffset(), (byte) 0); + @SuppressWarnings("unchecked") + private PlcResponse decodeWriteResponse(S7ResponseMessage responseMessage, PlcRequestContainer requestContainer) throws PlcProtocolException { + PlcResponse response; + PlcWriteRequest plcWriteRequest = (PlcWriteRequest) requestContainer.getRequest(); + List<WriteResponseItem<?>> responseItems = new LinkedList<>(); + VarPayload payload = responseMessage.getPayload(VarPayload.class) + .orElseThrow(() -> new PlcProtocolException("No VarPayload supplied")); + // If the numbers of items don't match, we're in big trouble as the only + // way to know how to interpret the responses is by aligning them with the + // items from the request as this information is not returned by the PLC. + if (plcWriteRequest.getRequestItems().size() != payload.getPayloadItems().size()) { + throw new PlcProtocolException( + "The number of requested items doesn't match the number of returned items"); } - } + List<VarPayloadItem> payloadItems = payload.getPayloadItems(); + final int noPayLoadItems = payloadItems.size(); + for (int i = 0; i < noPayLoadItems; i++) { + VarPayloadItem payloadItem = payloadItems.get(i); - private TransportSize encodeTransportSize(Class<?> datatype) { - if (datatype == Boolean.class) { - return TransportSize.BIT; - } else if (datatype == Byte.class) { - return TransportSize.BYTE; - } else if (datatype == Short.class) { - return TransportSize.WORD; - } else if (datatype == Calendar.class) { - return TransportSize.DATE_AND_TIME; - } else if (datatype == Float.class) { - return TransportSize.REAL; - } else if (datatype == Integer.class) { - return TransportSize.DWORD; - } else if (datatype == String.class) { - return TransportSize.CHAR; + // Get the request item for this payload item + WriteRequestItem requestItem = plcWriteRequest.getRequestItems().get(i); + + // A write response contains only the return code for every item. + ResponseCode responseCode = decodeResponseCode(payloadItem.getReturnCode()); + + WriteResponseItem responseItem = new WriteResponseItem(requestItem, responseCode); + responseItems.add(responseItem); } - return null; - } - private DataTransportSize encodeDataTransportSize(Class<?> datatype) { - if (datatype == Boolean.class) { - return DataTransportSize.BIT; - } else if (datatype == Byte.class) { - return DataTransportSize.BYTE_WORD_DWORD; - } else if (datatype == Short.class) { - return DataTransportSize.BYTE_WORD_DWORD; - } else if (datatype == Calendar.class) { - // TODO: Decide what to do here ... - return null; - } else if (datatype == Float.class) { - return DataTransportSize.REAL; - } else if (datatype == Integer.class) { - return DataTransportSize.BYTE_WORD_DWORD; - } else if (datatype == String.class) { - return DataTransportSize.OCTET_STRING; + if (plcWriteRequest instanceof TypeSafePlcWriteRequest) { + response = new TypeSafePlcWriteResponse((TypeSafePlcWriteRequest) plcWriteRequest, responseItems); + } else { + response = new PlcWriteResponse(plcWriteRequest, responseItems); } - return null; + return response; } - //////////////////////////////////////////////////////////////////////////////// - // Decoding helpers. - //////////////////////////////////////////////////////////////////////////////// - private ResponseCode decodeResponseCode(DataTransportErrorCode dataTransportErrorCode) { if (dataTransportErrorCode == null) { return ResponseCode.INTERNAL_ERROR; diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/S7Protocol.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/S7Protocol.java index 923b820..943603c 100644 --- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/S7Protocol.java +++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/S7Protocol.java @@ -64,6 +64,14 @@ public class S7Protocol extends PlcMessageToMessageCodec<IsoTPMessage, S7Message this.pduSize = requestedPduSize; } + /** + * If the S7 protocol layer is used over Iso TP, then after receiving a {@link IsoTPConnectedEvent} the + * corresponding S7 setup communication message has to be sent in order to negotiate the S7 protocol layer. + * + * @param ctx the current protocol layers context + * @param evt the event + * @throws Exception throws an exception if something goes wrong internally + */ @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { ChannelHandler prevHandler = getPrevChannelHandler(ctx); @@ -82,6 +90,10 @@ public class S7Protocol extends PlcMessageToMessageCodec<IsoTPMessage, S7Message } } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Encoding + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override protected void encode(ChannelHandlerContext ctx, S7Message in, List<Object> out) { logger.debug("S7 RawMessage sent"); @@ -104,41 +116,6 @@ public class S7Protocol extends PlcMessageToMessageCodec<IsoTPMessage, S7Message } } - /** - * While a SetupCommunication message is no problem, when reading or writing data, - * situations could arise that have to be handled. The following situations have to - * be handled: - * - The number of request items is so big, that the resulting PDU would exceed the - * agreed upon PDU size -> The request has to be split up into multiple requests. - * - If large blocks of data are requested by request items the result of a request - * could exceed the PDU size -> The requests has to be split up into multiple requests - * where each requests response doesn't exceed the PDU size. - * - * The following optimizations should be implemented: - * - If blocks are read which are in near proximity to each other it could be better - * to replace multiple requests by one that includes multiple blocks. - * - Rearranging the order of request items could reduce the number of needed PDUs. - * - * @param message incoming message - * @return List of outgoing messages - */ - private List<S7Message> optimizeMessage(S7Message message) { - // The following considerations have to be taken into account: - // - The size of all parameters and payloads of a message cannot exceed the negotiated PDU size - // - When reading data, the size of the returned data cannot exceed the negotiated PDU size - // - // Examples: - // - Size of the request exceeds the maximum - // When having a negotiated max PDU size of 256, the maximum size of individual addresses can be at most 18 - // If more are sent, the S7 will respond with a frame error. - // - Size of the response exceeds the maximum - // When reading two Strings of each 200 bytes length, the size of the request is ok, however the PLC would - // have to send back 400 bytes of String data, which would exceed the PDU size. In this case the first String - // is correctly returned, but for the second item the PLC will return a code of 0x03 = Access Denied - - return Collections.singletonList(message); - } - private void encodePayloads(S7Message in, ByteBuf buf) { for (S7Payload payload : in.getPayloads()) { ParameterType parameterType = payload.getType(); @@ -231,6 +208,10 @@ public class S7Protocol extends PlcMessageToMessageCodec<IsoTPMessage, S7Message | (s7AnyRequestItem.getBitOffset() & 0x07))); } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Decoding + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override protected void decode(ChannelHandlerContext ctx, IsoTPMessage in, List<Object> out) { if (logger.isTraceEnabled()) { @@ -269,7 +250,7 @@ public class S7Protocol extends PlcMessageToMessageCodec<IsoTPMessage, S7Message int i = 0; while (i < headerParametersLength) { - S7Parameter parameter = parseParameter(userData, isResponse, headerParametersLength - i); + S7Parameter parameter = decodeParameter(userData, isResponse, headerParametersLength - i); s7Parameters.add(parameter); if (parameter instanceof SetupCommunicationParameter) { setupCommunicationParameter = (SetupCommunicationParameter) parameter; @@ -283,7 +264,7 @@ public class S7Protocol extends PlcMessageToMessageCodec<IsoTPMessage, S7Message List<S7Payload> s7Payloads = decodePayloads(userData, isResponse, userDataLength, readWriteVarParameter); if (isResponse) { - setupCommunications(ctx, setupCommunicationParameter); + decodeSetupCommunications(ctx, setupCommunicationParameter); out.add(new S7ResponseMessage(messageType, tpduReference, s7Parameters, s7Payloads, errorClass, errorCode)); } else { // TODO: Find out if there is any situation in which a request is sent from the PLC @@ -291,7 +272,7 @@ public class S7Protocol extends PlcMessageToMessageCodec<IsoTPMessage, S7Message } } - private void setupCommunications(ChannelHandlerContext ctx, SetupCommunicationParameter setupCommunicationParameter) { + private void decodeSetupCommunications(ChannelHandlerContext ctx, SetupCommunicationParameter setupCommunicationParameter) { // If we got a SetupCommunicationParameter as part of the response // we are currently in the process of establishing a connection with // the PLC, so save some of the information in the session and tell @@ -353,7 +334,7 @@ public class S7Protocol extends PlcMessageToMessageCodec<IsoTPMessage, S7Message return s7Payloads; } - private S7Parameter parseParameter(ByteBuf in, boolean isResponse, int restLength) { + private S7Parameter decodeParameter(ByteBuf in, boolean isResponse, int restLength) { ParameterType parameterType = ParameterType.valueOf(in.readByte()); if (parameterType == null) { logger.error("Could not find parameter type"); @@ -372,7 +353,7 @@ public class S7Protocol extends PlcMessageToMessageCodec<IsoTPMessage, S7Message List<VarParameterItem> varParamameter; byte numItems = in.readByte(); if (!isResponse) { - varParamameter = parseReadWriteVarParameter(in, numItems); + varParamameter = decodeReadWriteVarParameter(in, numItems); } else { varParamameter = Collections.emptyList(); } @@ -392,7 +373,7 @@ public class S7Protocol extends PlcMessageToMessageCodec<IsoTPMessage, S7Message return null; } - private List<VarParameterItem> parseReadWriteVarParameter(ByteBuf in, byte numItems) { + private List<VarParameterItem> decodeReadWriteVarParameter(ByteBuf in, byte numItems) { List<VarParameterItem> items = new LinkedList<>(); for (int i = 0; i < numItems; i++) { SpecificationType specificationType = SpecificationType.valueOf(in.readByte()); @@ -427,6 +408,46 @@ public class S7Protocol extends PlcMessageToMessageCodec<IsoTPMessage, S7Message return items; } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Helpers + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + /** + * While a SetupCommunication message is no problem, when reading or writing data, + * situations could arise that have to be handled. The following situations have to + * be handled: + * - The number of request items is so big, that the resulting PDU would exceed the + * agreed upon PDU size -> The request has to be split up into multiple requests. + * - If large blocks of data are requested by request items the result of a request + * could exceed the PDU size -> The requests has to be split up into multiple requests + * where each requests response doesn't exceed the PDU size. + * + * The following optimizations should be implemented: + * - If blocks are read which are in near proximity to each other it could be better + * to replace multiple requests by one that includes multiple blocks. + * - Rearranging the order of request items could reduce the number of needed PDUs. + * + * @param message incoming message + * @return List of outgoing messages + */ + private List<S7Message> optimizeMessage(S7Message message) { + // The following considerations have to be taken into account: + // - The size of all parameters and payloads of a message cannot exceed the negotiated PDU size + // - When reading data, the size of the returned data cannot exceed the negotiated PDU size + // + // Examples: + // - Size of the request exceeds the maximum + // When having a negotiated max PDU size of 256, the maximum size of individual addresses can be at most 18 + // If more are sent, the S7 will respond with a frame error. + // - Size of the response exceeds the maximum + // When reading two Strings of each 200 bytes length, the size of the request is ok, however the PLC would + // have to send back 400 bytes of String data, which would exceed the PDU size. In this case the first String + // is correctly returned, but for the second item the PLC will return a code of 0x03 = Access Denied + + return Collections.singletonList(message); + } + private short getParametersLength(List<S7Parameter> parameters) { short l = 0; if (parameters != null) { diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/utils/S7TsapIdEncoder.java similarity index 55% copy from plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java copy to plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/utils/S7TsapIdEncoder.java index 2d7f2d2..3980c4c 100644 --- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java +++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/utils/S7TsapIdEncoder.java @@ -1,3 +1,4 @@ +package org.apache.plc4x.java.s7.utils; /* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file @@ -16,33 +17,28 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -package org.apache.plc4x.java.isotp.netty.model.params; - import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup; -public abstract class TsapParameter implements Parameter { - - private final DeviceGroup deviceGroup; - private final byte rackNumber; - private final byte slotNumber; +public class S7TsapIdEncoder { - public TsapParameter(DeviceGroup deviceGroup, byte rackNumber, byte slotNumber) { - this.deviceGroup = deviceGroup; - this.rackNumber = rackNumber; - this.slotNumber = slotNumber; + public static short encodeS7TsapId(DeviceGroup deviceGroup, int rack, int slot) { + short firstByte = ((short) (deviceGroup.getCode() << 8)); + short secondByte = ((short) ((rack << 4) | (slot & 0x0F))); + return (short) (firstByte | secondByte); } - public DeviceGroup getDeviceGroup() { - return deviceGroup; + public static DeviceGroup decodeDeviceGroup(short tsapId) { + byte deviceGroupCode = (byte) ((tsapId >> 8) & (0xFF)); + return DeviceGroup.valueOf(deviceGroupCode); } - public byte getRackNumber() { - return rackNumber; + public static int decodeRack(short tsapId) { + return ((tsapId >> 4) & 0xF); } - public byte getSlotNumber() { - return slotNumber; + public static int decodeSlot(short tsapId) { + return (tsapId & 0xF); } } diff --git a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocolTest.java b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocolTest.java index 886d63d..6f28908 100644 --- a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocolTest.java +++ b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocolTest.java @@ -26,6 +26,7 @@ import org.apache.plc4x.java.isotp.netty.model.IsoTPMessage; import org.apache.plc4x.java.isotp.netty.model.params.*; import org.apache.plc4x.java.isotp.netty.model.tpdus.*; import org.apache.plc4x.java.isotp.netty.model.types.*; +import org.apache.plc4x.java.s7.utils.S7TsapIdEncoder; import org.apache.plc4x.test.FastTests; import org.junit.After; import org.junit.Before; @@ -69,7 +70,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void encodeConnectionRequest() throws Exception { + public void encodeConnectionRequest() { ConnectionRequestTpdu tpdu = new ConnectionRequestTpdu((short) 0x1, (short) (0x2), ProtocolClass.CLASS_0, Collections.emptyList(), buf); isoTPProtocol.encode(ctx, tpdu, out); @@ -88,7 +89,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void decodeConnectionRequest() throws Exception { + public void decodeConnectionRequest() { buf.writeByte(0x6) // header length .writeByte(TpduCode.CONNECTION_REQUEST.getCode()) .writeShort(0x01) // destination reference @@ -111,7 +112,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void encodeDisconnectionRequest() throws Exception { + public void encodeDisconnectionRequest() { DisconnectRequestTpdu tpdu = new DisconnectRequestTpdu((short) 0x1, (short) (0x2), DisconnectReason.NORMAL, Collections.emptyList(), buf); isoTPProtocol.encode(ctx, tpdu, out); @@ -129,7 +130,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void decodeDisconnectionRequest() throws Exception { + public void decodeDisconnectionRequest() { buf.writeByte(0x6) // header length .writeByte(TpduCode.DISCONNECT_REQUEST.getCode()) .writeShort(0x01) // destination reference @@ -152,7 +153,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void encodeData() throws Exception { + public void encodeData() { DataTpdu tpdu = new DataTpdu(true, (byte) 0x7, Collections.emptyList(), buf); isoTPProtocol.encode(ctx, tpdu, out); @@ -169,7 +170,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void decodeDataEOT() throws Exception { + public void decodeDataEOT() { buf.writeByte(0x3) // header length .writeByte(TpduCode.DATA.getCode()) .writeByte((byte) 0x81); // Tpdu code + EOT @@ -189,7 +190,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void decodeData() throws Exception { + public void decodeData() { buf.writeByte(0x3) // header length .writeByte(TpduCode.DATA.getCode()) .writeByte((byte) 0x1); // Tpdu code @@ -209,7 +210,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void encodeConnectionConfirm() throws Exception { + public void encodeConnectionConfirm() { ConnectionConfirmTpdu tpdu = new ConnectionConfirmTpdu((short) 0x1, (short) (0x2), ProtocolClass.CLASS_1, Collections.emptyList(), buf); isoTPProtocol.encode(ctx, tpdu, out); @@ -228,7 +229,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void decodeConnectionConfirm() throws Exception { + public void decodeConnectionConfirm() { buf.writeByte(0x6) // header length .writeByte(TpduCode.CONNECTION_CONFIRM.getCode()) .writeShort(0x01) // destination reference @@ -251,7 +252,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void encodeDisconnectionConfirm() throws Exception { + public void encodeDisconnectionConfirm() { DisconnectConfirmTpdu tpdu = new DisconnectConfirmTpdu((short) 0x1, (short) (0x2), Collections.emptyList(), buf); isoTPProtocol.encode(ctx, tpdu, out); @@ -269,7 +270,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void decodeDisconnectionConfirm() throws Exception { + public void decodeDisconnectionConfirm() { buf.writeByte(0x5) // header length .writeByte(TpduCode.DISCONNECT_CONFIRM.getCode()) .writeShort(0x01) // destination reference @@ -291,7 +292,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void encodeError() throws Exception { + public void encodeError() { ErrorTpdu tpdu = new ErrorTpdu((short) 0x1, RejectCause.REASON_NOT_SPECIFIED, Collections.emptyList(), buf); isoTPProtocol.encode(ctx, tpdu, out); @@ -309,9 +310,11 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void encodeCallingParameter() throws Exception { + public void encodeCallingParameter() { ArrayList<Parameter> parmameters = new ArrayList<>(); - CallingTsapParameter callingParameter = new CallingTsapParameter(DeviceGroup.PG_OR_PC, (byte) 0x7, (byte) 0xe1); // slot number too big and overflows into rack + CallingTsapParameter callingParameter = new CallingTsapParameter( + // slot number too big and overflows into rack + S7TsapIdEncoder.encodeS7TsapId(DeviceGroup.PG_OR_PC, (byte) 0x7, (byte) 0xe1)); parmameters.add(callingParameter); ErrorTpdu tpdu = new ErrorTpdu((short) 0x1, RejectCause.REASON_NOT_SPECIFIED, parmameters, buf); @@ -336,7 +339,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void encodeChecksumParameter() throws Exception { + public void encodeChecksumParameter() { ArrayList<Parameter> parmameters = new ArrayList<>(); ChecksumParameter checksumParameter = new ChecksumParameter((byte) 0x77); parmameters.add(checksumParameter); @@ -360,7 +363,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void encodeAditionalInformationParameter() throws Exception { + public void encodeAditionalInformationParameter() { ArrayList<Parameter> parmameters = new ArrayList<>(); byte[] data = {'O', 'p', 'p', 's'}; DisconnectAdditionalInformationParameter informationParameter = new DisconnectAdditionalInformationParameter(data); @@ -388,7 +391,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void encodeSizeParameter() throws Exception { + public void encodeSizeParameter() { ArrayList<Parameter> parmameters = new ArrayList<>(); TpduSizeParameter sizeParameter = new TpduSizeParameter(TpduSize.SIZE_512); parmameters.add(sizeParameter); @@ -412,7 +415,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void decodeError() throws Exception { + public void decodeError() { buf.writeByte(0x4) // header length .writeByte(TpduCode.TPDU_ERROR.getCode()) .writeShort(0x01) // destination reference @@ -433,10 +436,8 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void encodeNullRequest() throws Exception { - ConnectionRequestTpdu tpdu = null; - - isoTPProtocol.encode(ctx, tpdu, out); + public void encodeNullRequest() { + isoTPProtocol.encode(ctx, null, out); assertThat("RawMessage not decoded", out, empty()); isoTPProtocol.encode(ctx, null, out); @@ -446,7 +447,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void decodeNull() throws Exception { + public void decodeNull() { IsoOnTcpMessage in = new IsoOnTcpMessage(buf); isoTPProtocol.decode(ctx, in, out); @@ -458,7 +459,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void encodeUnsupported() throws Exception { + public void encodeUnsupported() { ArrayList<Parameter> parmameters = new ArrayList<>(); CustomTpdu tpdu = new CustomTpdu((byte) 0x7F, parmameters, buf); @@ -469,7 +470,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void decodeUnsupported() throws Exception { + public void decodeUnsupported() { IsoOnTcpMessage in = new IsoOnTcpMessage(buf); buf.writeByte(0x3) // header length .writeByte(0x7F) @@ -480,7 +481,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void decodeCallingParameter() throws Exception { + public void decodeCallingParameter() { buf.writeByte(0x8) // header length .writeByte(TpduCode.TPDU_ERROR.getCode()) .writeShort(0x01) // destination reference @@ -503,14 +504,14 @@ public class IsoTPProtocolTest { assertThat(errorTpdu.getParameters(), hasSize(1)); CallingTsapParameter parameter = (CallingTsapParameter) errorTpdu.getParameters().get(0); assertThat(parameter.getType(), equalTo(ParameterCode.CALLING_TSAP)); - assertThat(parameter.getDeviceGroup(), equalTo(DeviceGroup.PG_OR_PC)); - assertThat(parameter.getRackNumber(), equalTo((byte) 0x1)); - assertThat(parameter.getSlotNumber(), equalTo((byte) 0x7)); + assertThat(S7TsapIdEncoder.decodeDeviceGroup(parameter.getTsapId()), equalTo(DeviceGroup.PG_OR_PC)); + assertThat(S7TsapIdEncoder.decodeRack(parameter.getTsapId()), equalTo(0x1)); + assertThat(S7TsapIdEncoder.decodeSlot(parameter.getTsapId()), equalTo(0x7)); } @Test @Category(FastTests.class) - public void decodeCalledParameter() throws Exception { + public void decodeCalledParameter() { buf.writeByte(0x8) // header length .writeByte(TpduCode.TPDU_ERROR.getCode()) .writeShort(0x01) // destination reference @@ -533,14 +534,14 @@ public class IsoTPProtocolTest { assertThat(errorTpdu.getParameters(), hasSize(1)); CalledTsapParameter parameter = (CalledTsapParameter) errorTpdu.getParameters().get(0); assertThat(parameter.getType(), equalTo(ParameterCode.CALLED_TSAP)); - assertThat(parameter.getDeviceGroup(), equalTo(DeviceGroup.PG_OR_PC)); - assertThat(parameter.getRackNumber(), equalTo((byte) 0x2)); - assertThat(parameter.getSlotNumber(), equalTo((byte) 0x3)); + assertThat(S7TsapIdEncoder.decodeDeviceGroup(parameter.getTsapId()), equalTo(DeviceGroup.PG_OR_PC)); + assertThat(S7TsapIdEncoder.decodeRack(parameter.getTsapId()), equalTo(0x2)); + assertThat(S7TsapIdEncoder.decodeSlot(parameter.getTsapId()), equalTo(0x3)); } @Test @Category(FastTests.class) - public void decodeChecksumParameter() throws Exception { + public void decodeChecksumParameter() { buf.writeByte(0x8) // header length .writeByte(TpduCode.TPDU_ERROR.getCode()) .writeShort(0x01) // destination reference @@ -567,7 +568,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void decodeSizeParameter() throws Exception { + public void decodeSizeParameter() { buf.writeByte(0x8) // header length .writeByte(TpduCode.TPDU_ERROR.getCode()) .writeShort(0x01) // destination reference @@ -594,7 +595,7 @@ public class IsoTPProtocolTest { @Test @Category(FastTests.class) - public void decodeAdditionalInformationParameter() throws Exception { + public void decodeAdditionalInformationParameter() { buf.writeByte(0x8) // header length .writeByte(TpduCode.TPDU_ERROR.getCode()) .writeShort(0x01) // destination reference diff --git a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameterTests.java b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameterTests.java index 0fb651c..705010c 100644 --- a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameterTests.java +++ b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameterTests.java @@ -19,7 +19,6 @@ under the License. package org.apache.plc4x.java.isotp.netty.model.params; -import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup; import org.apache.plc4x.java.isotp.netty.model.types.ParameterCode; import org.apache.plc4x.test.FastTests; import org.junit.After; @@ -41,24 +40,20 @@ public class TsapParameterTests { @Test @Category(FastTests.class) public void calledPartameter() { - DeviceGroup deviceGroup = DeviceGroup.valueOf((byte)0); - tsapParameter = new CalledTsapParameter(deviceGroup, (byte)1, (byte)4); + short calledTsapId = 0x1234; + tsapParameter = new CalledTsapParameter(calledTsapId); - assertThat("Device group incorrect", tsapParameter.getDeviceGroup(), equalTo(DeviceGroup.valueOf((byte)0))); - assertThat("Rack number not correct", tsapParameter.getRackNumber(), equalTo((byte)1)); - assertThat("Slot number not coorect", tsapParameter.getSlotNumber(), equalTo((byte)4)); + assertThat("TSAP Id incorrect", tsapParameter.getTsapId(), equalTo(calledTsapId)); assertThat(tsapParameter.getType(), equalTo(ParameterCode.CALLED_TSAP)); } @Test @Category(FastTests.class) public void callingPartameter() { - DeviceGroup deviceGroup = DeviceGroup.valueOf((byte)0); - tsapParameter = new CallingTsapParameter(deviceGroup, (byte)2, (byte)5); + short callingTsapId = 0x4321; + tsapParameter = new CallingTsapParameter(callingTsapId); - assertThat("Device group incorrect", tsapParameter.getDeviceGroup(), equalTo(DeviceGroup.valueOf((byte)0))); - assertThat("Rack number not correct", tsapParameter.getRackNumber(), equalTo((byte)2)); - assertThat("Slot number not coorect", tsapParameter.getSlotNumber(), equalTo((byte)5)); + assertThat("TSAP Id incorrect", tsapParameter.getTsapId(), equalTo(callingTsapId)); assertThat(tsapParameter.getType(), equalTo(ParameterCode.CALLING_TSAP)); } -- To stop receiving notification emails like this one, please contact cd...@apache.org.