You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2019/02/06 10:20:35 UTC
[incubator-plc4x] branch develop updated: - Fixed a bug in the
SCXML template making the S7 not respond correctly - Started implementing
the processing of responses in SCXML
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git
The following commit(s) were added to refs/heads/develop by this push:
new f0e7d31 - Fixed a bug in the SCXML template making the S7 not respond correctly - Started implementing the processing of responses in SCXML
f0e7d31 is described below
commit f0e7d31d8ed0ef14cebe557485337078795fb132
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Wed Feb 6 11:20:25 2019 +0100
- Fixed a bug in the SCXML template making the S7 not respond correctly
- Started implementing the processing of responses in SCXML
---
pom.xml | 5 +
.../apache/plc4x/protocols/s7/protocol.scxml.xml | 206 ++++++---------------
sandbox/dynamic-driver-s7/pom.xml | 4 +
.../java/org/apache/plc4x/sandbox/java/s7/Poc.java | 10 +-
.../sandbox/java/s7/actions/BasePlc4xAction.java | 76 ++++++++
.../sandbox/java/s7/actions/ConnectAction.java | 7 +-
.../sandbox/java/s7/actions/InitContextAction.java | 48 +++++
.../sandbox/java/s7/actions/ReceiveAction.java | 103 ++++++++++-
.../plc4x/sandbox/java/s7/actions/SendAction.java | 98 ++++------
9 files changed, 339 insertions(+), 218 deletions(-)
diff --git a/pom.xml b/pom.xml
index ac58c96..e83282c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -582,6 +582,11 @@
<version>${slf4j.version}</version>
</dependency>
<dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>${spock.version}</version>
diff --git a/protocols/s7/src/main/resources/org/apache/plc4x/protocols/s7/protocol.scxml.xml b/protocols/s7/src/main/resources/org/apache/plc4x/protocols/s7/protocol.scxml.xml
index 7f07b76..e272f77 100644
--- a/protocols/s7/src/main/resources/org/apache/plc4x/protocols/s7/protocol.scxml.xml
+++ b/protocols/s7/src/main/resources/org/apache/plc4x/protocols/s7/protocol.scxml.xml
@@ -27,7 +27,6 @@
<sc:datamodel>
<sc:data id="args"/>
- <sc:data id="connection"/>
</sc:datamodel>
<sc:state id="init">
@@ -50,15 +49,13 @@
<!-- Initialize the network connection to the remote host using the tcp adapter with a given host and port -->
<plc4x:connect type="tcp" host="10.10.64.20" port="102"/>
</sc:onentry>
- <sc:transition event="success" target="sendCotpConnectionRequest">
- <sc:assign location="connection" expr="_event.data"/>
- </sc:transition>
+ <sc:transition event="success" target="sendCotpConnectionRequest"/>
<sc:transition event="failure" target="error"/>
</sc:state>
<sc:state id="sendCotpConnectionRequest">
<sc:onentry>
- <plc4x:send socket="connection">
+ <plc4x:send socketParameterName="connection">
<s7:TpktMessage>
<magicByte>3</magicByte>
<reserved>0</reserved>
@@ -69,24 +66,24 @@
<s7:CotpTpduConnectionRequest>
<destinationReference>0</destinationReference>
<!-- Insert the value for "cotp-local-reference" as short here -->
- <sourceReference>16</sourceReference><!--plc4x:insert type="s7:short" name="cotp-local-reference"/-->
+ <sourceReference>15</sourceReference><!--plc4x:insert type="s7:short" name="cotp-local-reference"/-->
<protocolClass>0</protocolClass>
<s7:parameters>
<parameter>
- <type>193</type>
- <parameterLength>2</parameterLength>
- <s7:CotpParameterCallingTsap>
- <tsapId>256</tsapId><!--plc4x:insert type="s7:short" name="cotp-calling-tsap"/-->
- </s7:CotpParameterCallingTsap>
- </parameter>
- <parameter>
<type>194</type>
<parameterLength>2</parameterLength>
<s7:CotpParameterCalledTsap>
- <tsapId>258</tsapId><!--plc4x:insert type="s7:short" name="cotp-called-tsap"/-->
+ <tsapId>512</tsapId><!--plc4x:insert type="s7:short" name="cotp-called-tsap"/-->
</s7:CotpParameterCalledTsap>
</parameter>
<parameter>
+ <type>193</type>
+ <parameterLength>2</parameterLength>
+ <s7:CotpParameterCallingTsap>
+ <tsapId>273</tsapId><!--plc4x:insert type="s7:short" name="cotp-calling-tsap"/-->
+ </s7:CotpParameterCallingTsap>
+ </parameter>
+ <parameter>
<type>192</type>
<parameterLength>1</parameterLength>
<s7:CotpParameterTpduSize>
@@ -105,56 +102,12 @@
<sc:state id="receiveCotpConnectionResponse">
<sc:onentry>
- <plc4x:receive timeout="5000">
- <s7:tpktMessage>
- <magicByte>3</magicByte>
- <reserved>0</reserved>
- <!-- Just ignore the content of this field, we don't care about it as it's only required for parsing. -->
- <length><plc4x:ignore/></length>
- <userData>
- <!-- Just ignore the content of this field, we don't care about it as it's only required for parsing. -->
- <headerLength><plc4x:ignore/></headerLength>
- <type>208</type>
- <CotpTpduConnectionResponse>
- <!-- Make sure the reply uses the same reference as we used in the request. -->
- <destinationReference><plc4x:verify type="s7:short" name="cotp-local-reference"/></destinationReference>
- <!-- Extract the reference the remote would like us to use in this session. -->
- <sourceReference><plc4x:extract type="s7:short" name="cotp-remote-reference"/></sourceReference>
- <protocolClass>0</protocolClass>
- <parameters>
- <!--
- These elements might be transferred in alternate order, we just care about all of them being
- transferred.
- -->
- <plc4x:unordered>
- <parameter>
- <type>192</type>
- <parameterLength>1</parameterLength>
- <CotpParameterTpduSize>
- <tpduSize><plc4x:extract type="s7:byte" name="cotp-tpdu-size"/></tpduSize>
- </CotpParameterTpduSize>
- </parameter>
- <parameter>
- <type>193</type>
- <parameterLength>2</parameterLength>
- <CotpParameterCallingTsap>
- <tsapId><plc4x:extract type="s7:short" name="cotp-calling-tsap"/></tsapId>
- </CotpParameterCallingTsap>
- </parameter>
- <parameter>
- <type>194</type>
- <parameterLength>2</parameterLength>
- <CotpParameterCalledTsap>
- <tsapId><plc4x:extract type="s7:short" name="cotp-called-tsap"/></tsapId>
- </CotpParameterCalledTsap>
- </parameter>
- <!-- The remote might be passing other parameters, we'll just ignore them for now -->
- <plc4x:ignore/>
- </plc4x:unordered>
- </parameters>
- </CotpTpduConnectionResponse>
- </userData>
- </s7:tpktMessage>
+ <plc4x:receive socketParameterName="connection" timeout="5000">
+ <verification name="cotp-local-reference" xpath="s7:TpktMessage/userData/s7:CotpTpduConnectionResponse/destinationReference"/>
+ <extraction name="cotp-remote-reference" xpath="s7:TpktMessage/userData/s7:CotpTpduConnectionResponse/sourceReference"/>
+ <extraction name="cotp-tpdu-size" xpath="s7:TpktMessage/userData/s7:CotpTpduConnectionResponse/s7:parameters/parameter/s7:CotpParameterTpduSize/tpduSize"/>
+ <extraction name="cotp-calling-tsap" xpath="s7:TpktMessage/userData/s7:CotpTpduConnectionResponse/s7:parameters/parameter/s7:CotpParameterCallingTsap/tsapId"/>
+ <extraction name="cotp-called-tsap" xpath="s7:TpktMessage/userData/s7:CotpTpduConnectionResponse/s7:parameters/parameter/s7:CotpParameterCalledTsap/tsapId"/>
</plc4x:receive>
</sc:onentry>
<sc:transition event="success" target="sendS7SetupCommunicationRequest"/>
@@ -163,46 +116,46 @@
<sc:state id="sendS7SetupCommunicationRequest">
<sc:onentry>
- <plc4x:send>
- <s7:tpktMessage>
+ <plc4x:send socketParameterName="connection">
+ <s7:TpktMessage>
<magicByte>3</magicByte>
<reserved>0</reserved>
<length>25</length>
<userData>
<headerLength>2</headerLength>
<type>240</type>
- <CotpTpduData>
+ <s7:CotpTpduData>
<endOfTransmission>1</endOfTransmission>
<tpduRef>0</tpduRef>
- </CotpTpduData>
+ </s7:CotpTpduData>
<userData>
<magicByte>50</magicByte>
<type>1</type>
- <S7RequestMessage>
+ <s7:S7RequestMessage>
<reserved>0</reserved>
<tpduReference>0</tpduReference>
<parametersLength>8</parametersLength>
<payloadsLength>0</payloadsLength>
- <parameters>
+ <s7:parameters>
<parameter>
<type>240</type>
- <S7GeneralParameterSetupCommunication>
+ <s7:S7GeneralParameterSetupCommunication>
<reserved>0</reserved>
- <maxAmqCaller><plc4x:insert type="s7:short" name="s7-max-amq-caller"/></maxAmqCaller>
- <maxAmqCallee><plc4x:insert type="s7:short" name="s7-max-amq-callee"/></maxAmqCallee>
- <pduLength><plc4x:insert type="s7:short" name="s7-pdu-length"/></pduLength>
- </S7GeneralParameterSetupCommunication>
+ <maxAmqCaller>10</maxAmqCaller><!--plc4x:insert type="s7:short" name="s7-max-amq-caller"/-->
+ <maxAmqCallee>10</maxAmqCallee><!--plc4x:insert type="s7:short" name="s7-max-amq-callee"/-->
+ <pduLength>1024</pduLength><!--plc4x:insert type="s7:short" name="s7-pdu-length"/-->
+ </s7:S7GeneralParameterSetupCommunication>
</parameter>
- </parameters>
+ </s7:parameters>
<payloads>
<payload>
- <S7GeneralPayloadSetupCommunication/>
+ <s7:S7GeneralPayloadSetupCommunication/>
</payload>
</payloads>
- </S7RequestMessage>
+ </s7:S7RequestMessage>
</userData>
</userData>
- </s7:tpktMessage>
+ </s7:TpktMessage>
</plc4x:send>
</sc:onentry>
<sc:transition event="success" target="receiveS7SetupCommunicationResponse"/>
@@ -211,51 +164,12 @@
<sc:state id="receiveS7SetupCommunicationResponse">
<sc:onentry>
- <plc4x:receive timeout="5000">
- <s7:tpktMessage>
- <magicByte>3</magicByte>
- <reserved>0</reserved>
- <length><plc4x:ignore/></length>
- <userData>
- <headerLength>2</headerLength>
- <type>240</type>
- <CotpTpduData>
- <endOfTransmission>1</endOfTransmission>
- <tpduRef>0</tpduRef>
- </CotpTpduData>
- <userData>
- <magicByte>50</magicByte>
- <type>3</type>
- <S7ResponseMessage>
- <reserved>0</reserved>
- <tpduReference>0</tpduReference>
- <parametersLength><plc4x:ignore/></parametersLength>
- <payloadsLength>0</payloadsLength>
- <errorClass><plc4x:ignore/></errorClass>
- <errorCode><plc4x:extract/></errorCode>
- <parameters>
- <plc4x:unordered>
- <parameter>
- <type>240</type>
- <S7GeneralParameterSetupCommunication>
- <reserved>0</reserved>
- <maxAmqCaller><plc4x:extract type="s7:short" name="s7-max-amq-caller"/></maxAmqCaller>
- <maxAmqCallee><plc4x:extract type="s7:short" name="s7-max-amq-callee"/></maxAmqCallee>
- <pduLength><plc4x:extract type="s7:short" name="s7-pdu-length"/></pduLength>
- </S7GeneralParameterSetupCommunication>
- </parameter>
- <plc4x:ignore/>
- </plc4x:unordered>
- </parameters>
- <payloads>
- <payload>
- <S7GeneralPayloadSetupCommunication/>
- </payload>
- </payloads>
- </S7ResponseMessage>
- </userData>
- </userData>
- </s7:tpktMessage>
+ <plc4x:receive socketParameterName="connection" timeout="5000">
+ <verification name="cotp-local-reference" xpath="s7:TpktMessage/userData/s7:CotpTpduConnectionResponse/destinationReference"/>
+ <extraction name="returnCode" xpath="s7:TpktMessage/userData/userData/s7:S7ResponseMessage/errorCode"/>
+ <extraction name="s7-max-amq-caller" xpath="s7:TpktMessage/userData/userData/s7:S7ResponseMessage/parameters/s7:S7GeneralParameterSetupCommunication/maxAmqCaller"/>
+ <extraction name="s7-max-amq-callee" xpath="s7:TpktMessage/userData/userData/s7:S7ResponseMessage/parameters/s7:S7GeneralParameterSetupCommunication/maxAmqCallee"/>
+ <extraction name="s7-pdu-length" xpath="s7:TpktMessage/userData/userData/s7:S7ResponseMessage/parameters/s7:S7GeneralParameterSetupCommunication/pduLength"/>
</plc4x:receive>
</sc:onentry>
<sc:transition event="" target="sendS7IdentificationRequest"/>
@@ -265,30 +179,30 @@
<sc:state id="sendS7IdentificationRequest">
<sc:onentry>
- <plc4x:send>
- <s7:tpktMessage>
+ <plc4x:send socketParameterName="connection">
+ <s7:TpktMessage>
<magicByte>3</magicByte>
<reserved>0</reserved>
<length>33</length>
<userData>
<headerLength>2</headerLength>
<type>240</type>
- <CotpTpduData>
+ <s7:CotpTpduData>
<endOfTransmission>1</endOfTransmission>
<tpduRef>0</tpduRef>
- </CotpTpduData>
+ </s7:CotpTpduData>
<userData>
<magicByte>50</magicByte>
<type>7</type>
- <S7UserDataMessage>
+ <s7:S7UserDataMessage>
<reserved>0</reserved>
<tpduReference>256</tpduReference>
<parametersLength>8</parametersLength>
<payloadsLength>8</payloadsLength>
- <parameters>
+ <s7:parameters>
<parameter>
<type>0</type>
- <S7UserDataParameterCPUService>
+ <s7:S7UserDataParameterCPUService>
<header>274</header>
<paramLength>4</paramLength>
<typeCode>17</typeCode>
@@ -296,24 +210,24 @@
<functionGroup>4</functionGroup>
<subFunctionGroup>1</subFunctionGroup>
<sequenceNumber>0</sequenceNumber>
- </S7UserDataParameterCPUService>
+ </s7:S7UserDataParameterCPUService>
</parameter>
- </parameters>
+ </s7:parameters>
<payloads>
<payload>
- <S7UserDataPayloadCpuServices>
+ <s7:S7UserDataPayloadCpuServices>
<returnCode>255</returnCode>
<transportSize>9</transportSize>
<length>4</length>
<sslId>17</sslId>
<sslIndex>0</sslIndex>
- </S7UserDataPayloadCpuServices>
+ </s7:S7UserDataPayloadCpuServices>
</payload>
</payloads>
- </S7UserDataMessage>
+ </s7:S7UserDataMessage>
</userData>
</userData>
- </s7:tpktMessage>
+ </s7:TpktMessage>
</plc4x:send>
</sc:onentry>
<sc:transition event="success" target="receiveS7IdentificationRequest"/>
@@ -322,27 +236,27 @@
<sc:state id="receiveS7IdentificationRequest">
<sc:onentry>
- <plc4x:receive>
- <s7:tpktMessage>
+ <plc4x:receive socketParameterName="connection">
+ <s7:TpktMessage>
<magicByte>3</magicByte>
<reserved>0</reserved>
<length><plc4x:ignore/></length>
<userData>
<headerLength>2</headerLength>
<type>240</type>
- <CotpTpduData>
+ <s7:CotpTpduData>
<endOfTransmission>1</endOfTransmission>
<tpduRef>0</tpduRef>
- </CotpTpduData>
+ </s7:CotpTpduData>
<userData>
<magicByte>50</magicByte>
<type>7</type>
- <S7UserDataMessage>
+ <s7:S7UserDataMessage>
<reserved>0</reserved>
<tpduReference>256</tpduReference>
<parametersLength><plc4x:ignore/></parametersLength>
<payloadsLength><plc4x:ignore/></payloadsLength>
- <parameters>
+ <s7:parameters>
<plc4x:unordered>
<parameter>
<type>0</type>
@@ -361,7 +275,7 @@
</parameter>
<plc4x:ignore/>
</plc4x:unordered>
- </parameters>
+ </s7:parameters>
<payloads>
<plc4x:unordered>
<payload>
@@ -421,10 +335,10 @@
<plc4x:ignore/>
</plc4x:unordered>
</payloads>
- </S7UserDataMessage>
+ </s7:S7UserDataMessage>
</userData>
</userData>
- </s7:tpktMessage>
+ </s7:TpktMessage>
</plc4x:receive>
</sc:onentry>
<sc:transition event="success" target="connected"/>
diff --git a/sandbox/dynamic-driver-s7/pom.xml b/sandbox/dynamic-driver-s7/pom.xml
index 80e9432..5dd20dd 100644
--- a/sandbox/dynamic-driver-s7/pom.xml
+++ b/sandbox/dynamic-driver-s7/pom.xml
@@ -60,6 +60,10 @@
</dependency>
<dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.apache.plc4x</groupId>
<artifactId>plc4x-protocols-s7</artifactId>
<version>0.4.0-SNAPSHOT</version>
diff --git a/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/Poc.java b/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/Poc.java
index 08e6e8a..790f2ef 100644
--- a/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/Poc.java
+++ b/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/Poc.java
@@ -38,8 +38,8 @@ public class Poc {
private SCXMLExecutor executor;
- public Poc() throws Exception {
-
+ private Poc() throws Exception {
+ // Initialize our PLC4X specific actions.
List<CustomAction> customActions = new LinkedList<>();
customActions.add(
new CustomAction("https://plc4x.apache.org/scxml-extension", "initContext", InitContextAction.class));
@@ -50,15 +50,19 @@ public class Poc {
customActions.add(
new CustomAction("https://plc4x.apache.org/scxml-extension", "receive", ReceiveAction.class));
+ // Initialize the state-machine with the definition from the protocol module.
SCXML scxml = SCXMLReader.read(
Poc.class.getClassLoader().getResource("org/apache/plc4x/protocols/s7/protocol.scxml.xml"),
new SCXMLReader.Configuration(null, null, customActions));
+
+ // Create an executor for running the state-machine.
executor = new SCXMLExecutor(null, new SimpleDispatcher(), new SimpleErrorReporter());
executor.setStateMachine(scxml);
executor.registerInvokerClass("scxml", SimpleSCXMLInvoker.class);
}
- protected void run() throws Exception {
+ private void run() throws Exception {
+ // Run the state-machine.
executor.go();
}
diff --git a/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/BasePlc4xAction.java b/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/BasePlc4xAction.java
new file mode 100644
index 0000000..e7bb675
--- /dev/null
+++ b/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/BasePlc4xAction.java
@@ -0,0 +1,76 @@
+/*
+ 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
+
+ http://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.sandbox.java.s7.actions;
+
+import org.apache.commons.scxml2.ActionExecutionContext;
+import org.apache.commons.scxml2.model.Action;
+import org.apache.commons.scxml2.model.ParsedValue;
+import org.apache.commons.scxml2.model.ParsedValueContainer;
+import org.apache.daffodil.japi.DataProcessor;
+import org.apache.daffodil.japi.Diagnostic;
+import org.apache.daffodil.japi.WithDiagnostics;
+import org.slf4j.Logger;
+
+import java.net.Socket;
+import java.util.List;
+
+public abstract class BasePlc4xAction extends Action implements ParsedValueContainer {
+
+
+
+ private String socketParameterName;
+ private ParsedValue message;
+
+ public String getSocketParameterName() {
+ return socketParameterName;
+ }
+
+ public void setSocketParameterName(String socketParameterName) {
+ this.socketParameterName = socketParameterName;
+ }
+
+ @Override
+ public ParsedValue getParsedValue() {
+ return message;
+ }
+
+ @Override
+ public void setParsedValue(ParsedValue parsedValue) {
+ this.message = parsedValue;
+ }
+
+ protected abstract Logger getLogger();
+
+ protected Socket getSocket(ActionExecutionContext ctx) {
+ return (Socket) ctx.getGlobalContext().get(getSocketParameterName());
+ }
+
+ protected DataProcessor getDaffodilDataProcessor(ActionExecutionContext ctx) {
+ return (DataProcessor) ctx.getGlobalContext().get("dfdl");
+ }
+
+ protected void logDiagnosticInformation(WithDiagnostics withDiagnostics) {
+ List<Diagnostic> diags = withDiagnostics.getDiagnostics();
+ for (Diagnostic d : diags) {
+ getLogger().error(d.getSomeMessage());
+ }
+ }
+
+}
diff --git a/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/ConnectAction.java b/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/ConnectAction.java
index 490ad05..5a7a371 100644
--- a/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/ConnectAction.java
+++ b/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/ConnectAction.java
@@ -59,17 +59,18 @@ public class ConnectAction extends Action {
@Override
public void execute(ActionExecutionContext ctx) {
- ctx.getAppLog().info("Connecting.");
+ ctx.getAppLog().info("Connecting...");
try {
if ("TCP".equalsIgnoreCase(type)) {
Socket socket = new Socket(host, Integer.parseInt(port));
- TriggerEvent event = new EventBuilder("success", TriggerEvent.SIGNAL_EVENT).data(socket).build();
+ ctx.getGlobalContext().set("connection", socket);
+ TriggerEvent event = new EventBuilder("success", TriggerEvent.SIGNAL_EVENT).build();
ctx.getInternalIOProcessor().addEvent(event);
+ ctx.getAppLog().info("Connected.");
}
} catch (IOException e) {
e.printStackTrace();
}
- return;
}
}
diff --git a/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/InitContextAction.java b/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/InitContextAction.java
index 9285c64..6b6e5f4 100644
--- a/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/InitContextAction.java
+++ b/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/InitContextAction.java
@@ -23,14 +23,62 @@ import org.apache.commons.scxml2.ActionExecutionContext;
import org.apache.commons.scxml2.EventBuilder;
import org.apache.commons.scxml2.TriggerEvent;
import org.apache.commons.scxml2.model.Action;
+import org.apache.daffodil.japi.Compiler;
+import org.apache.daffodil.japi.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
public class InitContextAction extends Action {
+ private static final Logger logger = LoggerFactory.getLogger(InitContextAction.class);
+
@Override
public void execute(ActionExecutionContext ctx) {
ctx.getAppLog().info("Initializing Context.");
+
+ try {
+ Compiler c = Daffodil.compiler();
+ c.setValidateDFDLSchemas(true);
+ URL shemaUrl = SendAction.class.getClassLoader().getResource("org/apache/plc4x/protocols/s7/protocol.dfdl.xsd");
+ if (shemaUrl != null) {
+ URI schemaUri = shemaUrl.toURI();
+ ProcessorFactory pf = c.compileSource(schemaUri);
+ if (pf.isError()) {
+ logDiagnosticInformation(pf);
+ TriggerEvent event = new EventBuilder("failure", TriggerEvent.SIGNAL_EVENT).build();
+ ctx.getInternalIOProcessor().addEvent(event);
+ return;
+ }
+ DataProcessor dp = pf.onPath("/");
+ if (dp.isError()) {
+ logDiagnosticInformation(dp);
+ TriggerEvent event = new EventBuilder("failure", TriggerEvent.SIGNAL_EVENT).build();
+ ctx.getInternalIOProcessor().addEvent(event);
+ return;
+ }
+ ctx.getGlobalContext().set("dfdl", dp);
+ }
+ } catch (IOException | URISyntaxException e) {
+ TriggerEvent event = new EventBuilder("failure", TriggerEvent.SIGNAL_EVENT).data(e).build();
+ ctx.getInternalIOProcessor().addEvent(event);
+ return;
+ }
+
TriggerEvent event = new EventBuilder("success", TriggerEvent.SIGNAL_EVENT).build();
ctx.getInternalIOProcessor().addEvent(event);
}
+ private void logDiagnosticInformation(WithDiagnostics withDiagnostics) {
+ List<Diagnostic> diags = withDiagnostics.getDiagnostics();
+ for (Diagnostic d : diags) {
+ logger.error(d.getSomeMessage());
+ }
+ }
+
}
diff --git a/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/ReceiveAction.java b/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/ReceiveAction.java
index f6f62c0..d17d937 100644
--- a/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/ReceiveAction.java
+++ b/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/ReceiveAction.java
@@ -22,12 +22,46 @@ package org.apache.plc4x.sandbox.java.s7.actions;
import org.apache.commons.scxml2.ActionExecutionContext;
import org.apache.commons.scxml2.EventBuilder;
import org.apache.commons.scxml2.TriggerEvent;
-import org.apache.commons.scxml2.model.Action;
+import org.apache.commons.scxml2.model.NodeListValue;
+import org.apache.commons.scxml2.model.NodeValue;
+import org.apache.commons.scxml2.model.ParsedValue;
+import org.apache.daffodil.japi.DataProcessor;
+import org.apache.daffodil.japi.ParseResult;
+import org.apache.daffodil.japi.infoset.W3CDOMInfosetOutputter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
-public class ReceiveAction extends Action {
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.Socket;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ReceiveAction extends BasePlc4xAction {
private String timeout;
+ private final Map<String, String> verificationRules;
+ private final Map<String, String> extractionRules;
+
+ public ReceiveAction() {
+ verificationRules = new HashMap<>();
+ extractionRules = new HashMap<>();
+ }
+
+ @Override
+ protected Logger getLogger() {
+ return LoggerFactory.getLogger(ReceiveAction.class);
+ }
+
public String getTimeout() {
return timeout;
}
@@ -37,8 +71,73 @@ public class ReceiveAction extends Action {
}
@Override
+ @SuppressWarnings("unchecked")
+ public void setParsedValue(ParsedValue parsedValue) {
+ super.setParsedValue(parsedValue);
+
+ if(parsedValue != null) {
+ if(parsedValue instanceof NodeListValue) {
+ List<Node> ruleList = (List<Node>) parsedValue.getValue();
+ for (Node node : ruleList) {
+ if(node instanceof Element) {
+ parseElement((Element) node);
+ }
+ }
+ } else if(parsedValue instanceof NodeValue) {
+ parseElement((Element) parsedValue.getValue());
+ }
+ }
+ }
+
+ private void parseElement(Element ruleElement) {
+ String name = ruleElement.getAttribute("name");
+ String xpath = ruleElement.getAttribute("xpath");
+ if("verification".equals(ruleElement.getTagName())) {
+ verificationRules.put(name, xpath);
+ } else if("extraction".equals(ruleElement.getTagName())) {
+ extractionRules.put(name, xpath);
+ } else {
+ getLogger().error("unsupported rule type: " + ruleElement.getTagName());
+ }
+ }
+
+ @Override
public void execute(ActionExecutionContext ctx) {
ctx.getAppLog().info("Receiving.");
+ try {
+ DataProcessor dp = getDaffodilDataProcessor(ctx);
+ if(dp == null) {
+ TriggerEvent event = new EventBuilder("failure", TriggerEvent.SIGNAL_EVENT).
+ data("Couldn't initialize daffodil data processor.").build();
+ ctx.getInternalIOProcessor().addEvent(event);
+ return;
+ }
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ Socket connection = getSocket(ctx);
+ BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ System.out.println(in.readLine());
+
+ DataInputStream inputStream = new DataInputStream(connection.getInputStream());
+ ReadableByteChannel rbc = Channels.newChannel(inputStream);
+ W3CDOMInfosetOutputter outputter = new W3CDOMInfosetOutputter();
+ ParseResult byteMessage = dp.parse(rbc, outputter);
+ if (byteMessage.isError()) {
+ logDiagnosticInformation(byteMessage);
+ return;
+ }
+
+ Document message = outputter.getResult();
+ System.out.println(message);
+ ctx.getAppLog().info("Successfully sent message.");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
TriggerEvent event = new EventBuilder("success", TriggerEvent.SIGNAL_EVENT).build();
ctx.getInternalIOProcessor().addEvent(event);
}
diff --git a/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/SendAction.java b/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/SendAction.java
index 392d0c5..f761ac3 100644
--- a/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/SendAction.java
+++ b/sandbox/dynamic-driver-s7/src/main/java/org/apache/plc4x/sandbox/java/s7/actions/SendAction.java
@@ -22,13 +22,13 @@ package org.apache.plc4x.sandbox.java.s7.actions;
import org.apache.commons.scxml2.ActionExecutionContext;
import org.apache.commons.scxml2.EventBuilder;
import org.apache.commons.scxml2.TriggerEvent;
-import org.apache.commons.scxml2.model.Action;
import org.apache.commons.scxml2.model.ParsedValue;
-import org.apache.commons.scxml2.model.ParsedValueContainer;
-import org.apache.daffodil.japi.Compiler;
-import org.apache.daffodil.japi.*;
+import org.apache.daffodil.japi.DataProcessor;
+import org.apache.daffodil.japi.UnparseResult;
import org.apache.daffodil.japi.infoset.InfosetInputter;
import org.apache.daffodil.japi.infoset.W3CDOMInfosetInputter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
@@ -38,88 +38,58 @@ import javax.xml.parsers.ParserConfigurationException;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
-import java.util.List;
-public class SendAction extends Action implements ParsedValueContainer {
-
- private ParsedValue message;
-
- @Override
- public ParsedValue getParsedValue() {
- return message;
- }
+public class SendAction extends BasePlc4xAction {
@Override
- public void setParsedValue(ParsedValue parsedValue) {
- message = parsedValue;
+ protected Logger getLogger() {
+ return LoggerFactory.getLogger(SendAction.class);
}
@Override
public void execute(ActionExecutionContext ctx) {
- if(message != null) {
- if(message.getType() == ParsedValue.ValueType.NODE) {
+ ctx.getAppLog().info("Sending.");
+ if(getParsedValue() != null) {
+ if(getParsedValue().getType() == ParsedValue.ValueType.NODE) {
try {
- Node messageTemplate = (Node) message.getValue();
+ Node messageTemplate = (Node) getParsedValue().getValue();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.newDocument();
Node messageTemplateClone = doc.importNode(messageTemplate, true);
doc.appendChild(messageTemplateClone);
- Compiler c = Daffodil.compiler();
- c.setValidateDFDLSchemas(true);
- URL shemaUrl = SendAction.class.getClassLoader().getResource("org/apache/plc4x/protocols/s7/protocol.dfdl.xsd");
- if(shemaUrl != null) {
- URI schemaUri = shemaUrl.toURI();
- ProcessorFactory pf = c.compileSource(schemaUri);
- if(pf.isError()) {
- List<Diagnostic> diags = pf.getDiagnostics();
- for (Diagnostic d : diags) {
- System.err.println(d.getSomeMessage());
- }
- return;
- }
- DataProcessor dp = pf.onPath("/");
- if(dp.isError()) {
- List<Diagnostic> diags = dp.getDiagnostics();
- for (Diagnostic d : diags) {
- System.err.println(d.getSomeMessage());
- }
- return;
- }
- InfosetInputter inputter = new W3CDOMInfosetInputter(doc);
-
- Socket connection = (Socket) ctx.getGlobalContext().get("connection");
- DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
- WritableByteChannel wbc = Channels.newChannel(outputStream);
- UnparseResult byteMessage = dp.unparse(inputter, wbc);
- if(byteMessage.isError()) {
- List<Diagnostic> diags = byteMessage.getDiagnostics();
- for (Diagnostic d : diags) {
- System.err.println(d.getSomeMessage());
- }
- return;
- }
+ DataProcessor dp = getDaffodilDataProcessor(ctx);
+ if(dp == null) {
+ TriggerEvent event = new EventBuilder("failure", TriggerEvent.SIGNAL_EVENT).
+ data("Couldn't initialize daffodil data processor.").build();
+ ctx.getInternalIOProcessor().addEvent(event);
+ return;
+ }
+ InfosetInputter inputter = new W3CDOMInfosetInputter(doc);
- outputStream.flush();
+ Socket connection = getSocket(ctx);
+ DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
+ WritableByteChannel wbc = Channels.newChannel(outputStream);
+ UnparseResult byteMessage = dp.unparse(inputter, wbc);
+ if(byteMessage.isError()) {
+ logDiagnosticInformation(byteMessage);
+ return;
}
- } catch(URISyntaxException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (ParserConfigurationException e) {
+ outputStream.flush();
+ ctx.getAppLog().info("Successfully sent message.");
+ } catch(IOException | ParserConfigurationException e) {
e.printStackTrace();
}
- } else if(message.getType() == ParsedValue.ValueType.JSON) {
-
+ } else {
+ TriggerEvent event = new EventBuilder("failure", TriggerEvent.SIGNAL_EVENT).
+ data("type '" + getParsedValue().getType() + "' not supported").build();
+ ctx.getInternalIOProcessor().addEvent(event);
+ return;
}
}
- ctx.getAppLog().info("Sending.");
TriggerEvent event = new EventBuilder("success", TriggerEvent.SIGNAL_EVENT).build();
ctx.getInternalIOProcessor().addEvent(event);
}