You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by jf...@apache.org on 2019/12/18 17:50:33 UTC
[plc4x] branch next-gen-core updated: Added Request Response
pattern with new API for S7 Driver
This is an automated email from the ASF dual-hosted git repository.
jfeinauer pushed a commit to branch next-gen-core
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/next-gen-core by this push:
new cfc21ba Added Request Response pattern with new API for S7 Driver
cfc21ba is described below
commit cfc21bafd29ce428a8e94bca2a57f2d96f5bb442
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Wed Dec 18 18:50:27 2019 +0100
Added Request Response pattern with new API for S7 Driver
---
.../s7/readwrite/protocol/Plc4xS7Protocol.java | 299 +++++++++++++--------
1 file changed, 182 insertions(+), 117 deletions(-)
diff --git a/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/Plc4xS7Protocol.java b/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/Plc4xS7Protocol.java
index 2a87fde..b6bd043 100644
--- a/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/Plc4xS7Protocol.java
+++ b/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/Plc4xS7Protocol.java
@@ -27,8 +27,48 @@ import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.apache.plc4x.java.api.messages.PlcResponse;
import org.apache.plc4x.java.api.model.PlcField;
import org.apache.plc4x.java.api.types.PlcResponseCode;
-import org.apache.plc4x.java.s7.readwrite.*;
-import org.apache.plc4x.java.s7.readwrite.types.*;
+import org.apache.plc4x.java.s7.readwrite.COTPPacket;
+import org.apache.plc4x.java.s7.readwrite.COTPPacketConnectionRequest;
+import org.apache.plc4x.java.s7.readwrite.COTPPacketConnectionResponse;
+import org.apache.plc4x.java.s7.readwrite.COTPPacketData;
+import org.apache.plc4x.java.s7.readwrite.COTPParameter;
+import org.apache.plc4x.java.s7.readwrite.COTPParameterCalledTsap;
+import org.apache.plc4x.java.s7.readwrite.COTPParameterCallingTsap;
+import org.apache.plc4x.java.s7.readwrite.COTPParameterTpduSize;
+import org.apache.plc4x.java.s7.readwrite.S7Address;
+import org.apache.plc4x.java.s7.readwrite.S7AddressAny;
+import org.apache.plc4x.java.s7.readwrite.S7Message;
+import org.apache.plc4x.java.s7.readwrite.S7MessageRequest;
+import org.apache.plc4x.java.s7.readwrite.S7MessageResponse;
+import org.apache.plc4x.java.s7.readwrite.S7MessageUserData;
+import org.apache.plc4x.java.s7.readwrite.S7Parameter;
+import org.apache.plc4x.java.s7.readwrite.S7ParameterReadVarRequest;
+import org.apache.plc4x.java.s7.readwrite.S7ParameterReadVarResponse;
+import org.apache.plc4x.java.s7.readwrite.S7ParameterSetupCommunication;
+import org.apache.plc4x.java.s7.readwrite.S7ParameterUserData;
+import org.apache.plc4x.java.s7.readwrite.S7ParameterUserDataItem;
+import org.apache.plc4x.java.s7.readwrite.S7ParameterUserDataItemCPUFunctions;
+import org.apache.plc4x.java.s7.readwrite.S7ParameterWriteVarResponse;
+import org.apache.plc4x.java.s7.readwrite.S7PayloadReadVarRequest;
+import org.apache.plc4x.java.s7.readwrite.S7PayloadReadVarResponse;
+import org.apache.plc4x.java.s7.readwrite.S7PayloadSetupCommunication;
+import org.apache.plc4x.java.s7.readwrite.S7PayloadUserData;
+import org.apache.plc4x.java.s7.readwrite.S7PayloadUserDataItem;
+import org.apache.plc4x.java.s7.readwrite.S7PayloadUserDataItemCpuFunctionReadSzlRequest;
+import org.apache.plc4x.java.s7.readwrite.S7PayloadUserDataItemCpuFunctionReadSzlResponse;
+import org.apache.plc4x.java.s7.readwrite.S7VarPayloadDataItem;
+import org.apache.plc4x.java.s7.readwrite.S7VarRequestParameterItem;
+import org.apache.plc4x.java.s7.readwrite.S7VarRequestParameterItemAddress;
+import org.apache.plc4x.java.s7.readwrite.SzlDataTreeItem;
+import org.apache.plc4x.java.s7.readwrite.SzlId;
+import org.apache.plc4x.java.s7.readwrite.TPKTPacket;
+import org.apache.plc4x.java.s7.readwrite.types.COTPProtocolClass;
+import org.apache.plc4x.java.s7.readwrite.types.COTPTpduSize;
+import org.apache.plc4x.java.s7.readwrite.types.DataTransportErrorCode;
+import org.apache.plc4x.java.s7.readwrite.types.DataTransportSize;
+import org.apache.plc4x.java.s7.readwrite.types.S7ControllerType;
+import org.apache.plc4x.java.s7.readwrite.types.SzlModuleTypeClass;
+import org.apache.plc4x.java.s7.readwrite.types.SzlSublist;
import org.apache.plc4x.java.s7.readwrite.utils.S7Field;
import org.apache.plc4x.java.spi.ConversationContext;
import org.apache.plc4x.java.spi.Plc4xProtocolBase;
@@ -56,12 +96,15 @@ import java.lang.reflect.Array;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
-import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -101,55 +144,122 @@ public class Plc4xS7Protocol extends Plc4xProtocolBase<TPKTPacket> {
public void onConnect(ConversationContext<TPKTPacket> context) {
logger.debug("ISO Transport Protocol Sending Connection Request");
// Open the session on ISO Transport Protocol first.
- COTPPacketConnectionRequest connectionRequest = new COTPPacketConnectionRequest(
- new COTPParameter[] {
- new COTPParameterCalledTsap(calledTsapId),
- new COTPParameterCallingTsap(callingTsapId),
- new COTPParameterTpduSize(cotpTpduSize)
- }, null, (short) 0x0000, (short) 0x000F, COTPProtocolClass.CLASS_0);
- TPKTPacket packet = new TPKTPacket(connectionRequest);
+ TPKTPacket packet = new TPKTPacket(createCOTPConnectionRequest(calledTsapId, callingTsapId, cotpTpduSize));
context.sendRequest(packet)
.expectResponse(TPKTPacket.class, Duration.ofMillis(100))
- .onTimeout(e -> {})
- .check(p -> {
- return p.getPayload() instanceof COTPPacketConnectionResponse;
- })
- .unwrap(p -> {
- return (COTPPacketConnectionResponse)p.getPayload();
+ .onTimeout(e -> {
})
+ .check(p -> p.getPayload() instanceof COTPPacketConnectionResponse)
+ .unwrap(p -> (COTPPacketConnectionResponse) p.getPayload())
.handle(cotpPacketConnectionResponse -> {
- // COTPPacketConnectionResponse cotpPacketConnectionResponse = (COTPPacketConnectionResponse) msg.getPayload();
- for (COTPParameter parameter : cotpPacketConnectionResponse.getParameters()) {
- if(parameter instanceof COTPParameterCalledTsap) {
- COTPParameterCalledTsap cotpParameterCalledTsap = (COTPParameterCalledTsap) parameter;
- calledTsapId = cotpParameterCalledTsap.getTsapId();
- } else if(parameter instanceof COTPParameterTpduSize) {
- COTPParameterTpduSize cotpParameterTpduSize = (COTPParameterTpduSize) parameter;
- cotpTpduSize = cotpParameterTpduSize.getTpduSize();
- } else if(parameter instanceof COTPParameterCallingTsap) {
- // Ignore this ...
- } else {
- logger.warn("Got unknown parameter type '" + parameter.getClass().getName() + "'");
+ context.sendRequest(createS7ConnectionRequest(cotpPacketConnectionResponse))
+ .expectResponse(TPKTPacket.class, Duration.ofMillis(100))
+ .onTimeout(e -> {
+ })
+ .check(p -> p.getPayload() instanceof COTPPacketData)
+ .unwrap(p -> ((COTPPacketData) p.getPayload()))
+ .check(p -> p.getPayload() instanceof S7MessageResponse)
+ .unwrap(p -> ((S7MessageResponse) p.getPayload()))
+ .check(p -> p.getParameter() instanceof S7ParameterSetupCommunication)
+ .unwrap(p -> ((S7ParameterSetupCommunication) p.getParameter()))
+ .handle(setupCommunication -> {
+ // Save some data from the response.
+ maxAmqCaller = setupCommunication.getMaxAmqCaller();
+ maxAmqCallee = setupCommunication.getMaxAmqCallee();
+ pduSize = setupCommunication.getPduLength();
+
+ // Only if the controller type is set to "ANY", then try to identify the PLC type.
+ if (controllerType != S7ControllerType.ANY) {
+ // Send an event that connection setup is complete.
+ context.fireConnected();
+ return;
+ }
+ // Prepare a message to request the remote to identify itself.
+ TPKTPacket tpktPacket = createIdentifyRemoteMessage();
+ context.sendRequest(tpktPacket)
+ .expectResponse(TPKTPacket.class, Duration.ofMillis(100))
+ .onTimeout(e -> {
+ })
+ .check(p -> p.getPayload() instanceof COTPPacketData)
+ .unwrap(p -> ((COTPPacketData) p.getPayload()))
+ .check(p -> p.getPayload() instanceof S7MessageUserData)
+ .unwrap(p -> ((S7MessageUserData) p.getPayload()))
+ .check(p -> p.getPayload() instanceof S7PayloadUserData)
+ .handle(messageUserData -> {
+ S7PayloadUserData payloadUserData = (S7PayloadUserData) messageUserData.getPayload();
+ extractControllerTypeAndFireConnected(context, payloadUserData);
+ });
+ });
+ });
+
+ // context.sendToWire(packet);
+ }
+
+ private void extractControllerTypeAndFireConnected(ConversationContext<TPKTPacket> context, S7PayloadUserData payloadUserData) {
+ for (S7PayloadUserDataItem item : payloadUserData.getItems()) {
+ if (item instanceof S7PayloadUserDataItemCpuFunctionReadSzlResponse) {
+ S7PayloadUserDataItemCpuFunctionReadSzlResponse readSzlResponseItem =
+ (S7PayloadUserDataItemCpuFunctionReadSzlResponse) item;
+ for (SzlDataTreeItem readSzlResponseItemItem : readSzlResponseItem.getItems()) {
+ if (readSzlResponseItemItem.getItemIndex() == 0x0001) {
+ final String articleNumber = new String(readSzlResponseItemItem.getMlfb());
+ controllerType = lookupControllerType(articleNumber);
+
+ // Send an event that connection setup is complete.
+ context.fireConnected();
}
}
+ }
+ }
+ }
- // Send an S7 login message.
- S7ParameterSetupCommunication s7ParameterSetupCommunication =
- new S7ParameterSetupCommunication(maxAmqCaller, maxAmqCallee, pduSize);
- S7Message s7Message = new S7MessageRequest(0, s7ParameterSetupCommunication,
- new S7PayloadSetupCommunication());
- COTPPacketData cotpPacketData = new COTPPacketData(null, s7Message, true, (short) 1);
- TPKTPacket tpktPacket = new TPKTPacket(cotpPacketData);
- context.sendToWire(tpktPacket);
- });
+ private static TPKTPacket createIdentifyRemoteMessage() {
+ S7MessageUserData identifyRemoteMessage = new S7MessageUserData(1, new S7ParameterUserData(new S7ParameterUserDataItem[]{
+ new S7ParameterUserDataItemCPUFunctions((short) 0x11, (byte) 0x4, (byte) 0x4, (short) 0x01, (short) 0x00, null, null, null)
+ }), new S7PayloadUserData(new S7PayloadUserDataItem[]{
+ new S7PayloadUserDataItemCpuFunctionReadSzlRequest(DataTransportErrorCode.OK, DataTransportSize.OCTET_STRING, new SzlId(SzlModuleTypeClass.CPU, (byte) 0x00, SzlSublist.MODULE_IDENTIFICATION), 0x0000)
+ }));
+ COTPPacketData cotpPacketData = new COTPPacketData(null, identifyRemoteMessage, true, (short) 2);
+ return new TPKTPacket(cotpPacketData);
+ }
+
+ private TPKTPacket createS7ConnectionRequest(COTPPacketConnectionResponse cotpPacketConnectionResponse) {
+ for (COTPParameter parameter : cotpPacketConnectionResponse.getParameters()) {
+ if (parameter instanceof COTPParameterCalledTsap) {
+ COTPParameterCalledTsap cotpParameterCalledTsap = (COTPParameterCalledTsap) parameter;
+ calledTsapId = cotpParameterCalledTsap.getTsapId();
+ } else if (parameter instanceof COTPParameterTpduSize) {
+ COTPParameterTpduSize cotpParameterTpduSize = (COTPParameterTpduSize) parameter;
+ cotpTpduSize = cotpParameterTpduSize.getTpduSize();
+ } else if (parameter instanceof COTPParameterCallingTsap) {
+ // Ignore this ...
+ } else {
+ logger.warn("Got unknown parameter type '" + parameter.getClass().getName() + "'");
+ }
+ }
- // context.sendToWire(packet);
+ // Send an S7 login message.
+ S7ParameterSetupCommunication s7ParameterSetupCommunication =
+ new S7ParameterSetupCommunication(maxAmqCaller, maxAmqCallee, pduSize);
+ S7Message s7Message = new S7MessageRequest(0, s7ParameterSetupCommunication,
+ new S7PayloadSetupCommunication());
+ COTPPacketData cotpPacketData = new COTPPacketData(null, s7Message, true, (short) 1);
+ return new TPKTPacket(cotpPacketData);
+ }
+
+ private static COTPPacketConnectionRequest createCOTPConnectionRequest(int calledTsapId, int callingTsapId, COTPTpduSize cotpTpduSize) {
+ return new COTPPacketConnectionRequest(
+ new COTPParameter[]{
+ new COTPParameterCalledTsap(calledTsapId),
+ new COTPParameterCallingTsap(callingTsapId),
+ new COTPParameterTpduSize(cotpTpduSize)
+ }, null, (short) 0x0000, (short) 0x000F, COTPProtocolClass.CLASS_0);
}
@Override
protected void encode(ConversationContext<TPKTPacket> context, PlcRequestContainer msg) throws Exception {
- if(msg.getRequest() instanceof DefaultPlcReadRequest) {
+ if (msg.getRequest() instanceof DefaultPlcReadRequest) {
DefaultPlcReadRequest request = (DefaultPlcReadRequest) msg.getRequest();
List<S7VarRequestParameterItem> requestItems = new ArrayList<>(request.getNumberOfFields());
for (PlcField field : request.getFields()) {
@@ -173,74 +283,31 @@ public class Plc4xS7Protocol extends Plc4xProtocolBase<TPKTPacket> {
// When getting a response to the connection request on COTP layer, extract some
// data and continue logging in on the S7 protocol.
- if(msg.getPayload() instanceof COTPPacketConnectionResponse) {
+ if (msg.getPayload() instanceof COTPPacketConnectionResponse) {
throw new IllegalStateException("You should not be here, fucker");
- }
-
- else if(msg.getPayload() instanceof COTPPacketData) {
- COTPPacketData packetData = (COTPPacketData) msg.getPayload();
- if(packetData.getPayload() instanceof S7MessageResponse) {
- S7MessageResponse s7MessageResponse = (S7MessageResponse) packetData.getPayload();
- final S7Parameter parameter = s7MessageResponse.getParameter();
- if(parameter instanceof S7ParameterSetupCommunication) {
- S7ParameterSetupCommunication setupCommunication = (S7ParameterSetupCommunication) parameter;
-
- // Save some data from the response.
- maxAmqCaller = setupCommunication.getMaxAmqCaller();
- maxAmqCallee = setupCommunication.getMaxAmqCallee();
- pduSize = setupCommunication.getPduLength();
-
- // Only if the controller type is set to "ANY", then try to identify the PLC type.
- if(controllerType == S7ControllerType.ANY) {
- // Prepare a message to request the remote to identify itself.
- S7MessageUserData identifyRemoteMessage = new S7MessageUserData(1, new S7ParameterUserData(new S7ParameterUserDataItem[] {
- new S7ParameterUserDataItemCPUFunctions((short) 0x11, (byte) 0x4, (byte) 0x4, (short) 0x01, (short) 0x00, null, null, null)
- }), new S7PayloadUserData( new S7PayloadUserDataItem[] {
- new S7PayloadUserDataItemCpuFunctionReadSzlRequest(DataTransportErrorCode.OK, DataTransportSize.OCTET_STRING, new SzlId(SzlModuleTypeClass.CPU, (byte) 0x00, SzlSublist.MODULE_IDENTIFICATION), 0x0000)
- }));
- COTPPacketData cotpPacketData = new COTPPacketData(null, identifyRemoteMessage, true, (short) 2);
- TPKTPacket tpktPacket = new TPKTPacket(cotpPacketData);
- context.sendToWire(tpktPacket);
- } else {
- // Send an event that connection setup is complete.
- context.fireConnected();
-
- }
- } else if (parameter instanceof S7ParameterReadVarResponse) {
- final PlcRequestContainer requestContainer = requests.remove(s7MessageResponse.getTpduReference());
- final PlcResponse response = decodeReadResponse(s7MessageResponse, requestContainer);
+ } else if (msg.getPayload() instanceof COTPPacketData) {
+ COTPPacket packageData = msg.getPayload();
+ if (!(packageData.getPayload() instanceof S7MessageResponse)) {
+ throw new IllegalStateException("You should not be here, fucker");
+ }
+ S7MessageResponse s7MessageResponse = (S7MessageResponse) packageData.getPayload();
+ final S7Parameter parameter = s7MessageResponse.getParameter();
+ if (parameter instanceof S7ParameterReadVarResponse) {
+ final PlcRequestContainer requestContainer = requests.remove(s7MessageResponse.getTpduReference());
+ final PlcResponse response;
+ try {
+ response = decodeReadResponse(s7MessageResponse, requestContainer);
requestContainer.getResponseFuture().complete(response);
- } else if (parameter instanceof S7ParameterWriteVarResponse) {
- S7ParameterWriteVarResponse writeResponseParameter = (S7ParameterWriteVarResponse) parameter;
-
- System.out.println(writeResponseParameter);
- }
- } else if(packetData.getPayload() instanceof S7MessageUserData) {
- S7MessageUserData messageUserData = (S7MessageUserData) packetData.getPayload();
- if(messageUserData.getPayload() instanceof S7PayloadUserData) {
- S7PayloadUserData payloadUserData = (S7PayloadUserData) messageUserData.getPayload();
- for (S7PayloadUserDataItem item : payloadUserData.getItems()) {
- if(item instanceof S7PayloadUserDataItemCpuFunctionReadSzlResponse) {
- S7PayloadUserDataItemCpuFunctionReadSzlResponse readSzlResponseItem =
- (S7PayloadUserDataItemCpuFunctionReadSzlResponse) item;
- for (SzlDataTreeItem readSzlResponseItemItem : readSzlResponseItem.getItems()) {
- if(readSzlResponseItemItem.getItemIndex() == 0x0001) {
- final String articleNumber = new String(readSzlResponseItemItem.getMlfb());
- controllerType = lookupControllerType(articleNumber);
-
- // Send an event that connection setup is complete.
- context.fireConnected();
- }
- }
- }
- }
+ } catch (PlcProtocolException e) {
+ e.printStackTrace();
}
- } else {
- System.out.println(packetData);
+ } else if (parameter instanceof S7ParameterWriteVarResponse) {
+ S7ParameterWriteVarResponse writeResponseParameter = (S7ParameterWriteVarResponse) parameter;
+
+ System.out.println(writeResponseParameter);
}
- }
- else {
+ } else {
System.out.println(msg);
}
}
@@ -362,9 +429,8 @@ public class Plc4xS7Protocol extends Plc4xProtocolBase<TPKTPacket> {
default:
throw new PlcProtocolException("Unsupported type " + field.getDataType());
}
- }
- catch (Exception e){
- logger.warn("Some other error occurred casting field {}, FieldInformation: {}",fieldName, field,e);
+ } catch (Exception e) {
+ logger.warn("Some other error occurred casting field {}, FieldInformation: {}", fieldName, field, e);
}
}
Pair<PlcResponseCode, BaseDefaultFieldItem> result = new ImmutablePair<>(responseCode, fieldItem);
@@ -539,24 +605,23 @@ public class Plc4xS7Protocol extends Plc4xProtocolBase<TPKTPacket> {
//per definition for Date_And_Time only the first 6 bytes are used
int year=convertByteToBcd(data.readByte());
- int month=convertByteToBcd(data.readByte());
- int day=convertByteToBcd(data.readByte());
- int hour=convertByteToBcd(data.readByte());
- int minute=convertByteToBcd(data.readByte());
- int second=convertByteToBcd(data.readByte());
+ int month = convertByteToBcd(data.readByte());
+ int day = convertByteToBcd(data.readByte());
+ int hour = convertByteToBcd(data.readByte());
+ int minute = convertByteToBcd(data.readByte());
+ int second = convertByteToBcd(data.readByte());
//skip the last 2 bytes no information present
data.readByte();
data.readByte();
//data-type ranges from 1990 up to 2089
- if(year>=90){
- year+=1900;
- }
- else{
- year+=2000;
+ if (year >= 90) {
+ year += 1900;
+ } else {
+ year += 2000;
}
- return LocalDateTime.of(year,month,day,hour,minute,second);
+ return LocalDateTime.of(year, month, day, hour, minute, second);
}
LocalTime readTimeOfDay(ByteBuf data) {