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 2018/05/22 15:59:38 UTC

[incubator-plc4x] branch master updated (3b6460b -> 851838e)

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git.


    from 3b6460b  use java8 streams api for closing of handles
     new e437de7  Updated the examples to the real ip adresses used in the iot lab.
     new 0949946  Updated the Kafka Bridge example to a more advanced version currently running at a customers site.
     new 1e70443  Added a new example using the iot-labs virtual factory.
     new 86ebdc2  Added some documentation on setting up AMS routes for Beckhoff
     new 851838e  Updated the iot-factory example to use Elasticsearch to save data which can then be displayed with Kibana (for example)

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 examples/iot-factory/README.adoc                   |  66 ++++++
 examples/{plclogger => iot-factory}/pom.xml        |  31 ++-
 .../iotfactory/IotElasticsearchFactory.java        | 224 +++++++++++++++++++++
 .../iot-factory/src/main/resources/log4j2.xml      |  25 ++-
 .../src/main/resources/logback.xml                 |   4 +
 examples/kafka-bridge/pom.xml                      |   4 +
 .../java/examples/kafkabridge/KafkaBridge.java     |  67 ++++--
 .../examples/kafkabridge/model/Configuration.java  |   9 +
 .../model/{Address.java => PlcAddress.java}        |  11 +-
 .../java/examples/kafkabridge/model/PlcConfig.java |  23 ++-
 .../model/{Address.java => PlcMemoryBlock.java}    |  21 +-
 examples/pom.xml                                   |  18 ++
 .../org/apache/plc4x/java/s7/S7PlcScanner.java     |   2 +-
 .../org/apache/plc4x/java/s7/S7PlcTestConsole.java |   2 +-
 src/site/asciidoc/developers/vpn.adoc              |  33 +++
 .../resources/img/plc4x-vpn-beckhoff-route-1.png   | Bin 0 -> 99036 bytes
 .../resources/img/plc4x-vpn-beckhoff-route-2.png   | Bin 0 -> 87524 bytes
 .../resources/img/plc4x-vpn-beckhoff-route-3.png   | Bin 0 -> 185843 bytes
 18 files changed, 480 insertions(+), 60 deletions(-)
 create mode 100644 examples/iot-factory/README.adoc
 copy examples/{plclogger => iot-factory}/pom.xml (73%)
 create mode 100644 examples/iot-factory/src/main/java/org/apache/plc4x/java/examples/iotfactory/IotElasticsearchFactory.java
 copy .mvn/extensions.xml => examples/iot-factory/src/main/resources/log4j2.xml (61%)
 copy examples/{kafka-bridge => iot-factory}/src/main/resources/logback.xml (92%)
 copy examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/{Address.java => PlcAddress.java} (86%)
 rename examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/{Address.java => PlcMemoryBlock.java} (77%)
 create mode 100644 src/site/resources/img/plc4x-vpn-beckhoff-route-1.png
 create mode 100644 src/site/resources/img/plc4x-vpn-beckhoff-route-2.png
 create mode 100644 src/site/resources/img/plc4x-vpn-beckhoff-route-3.png

-- 
To stop receiving notification emails like this one, please contact
cdutz@apache.org.

[incubator-plc4x] 01/05: Updated the examples to the real ip adresses used in the iot lab.

Posted by cd...@apache.org.
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

commit e437de75d31b1ee370766c86c62c3cc6a9cd664d
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Fri May 18 16:43:18 2018 +0200

    Updated the examples to the real ip adresses used in the iot lab.
    
    (cherry picked from commit 3070d64)
---
 .../s7/src/test/java/org/apache/plc4x/java/s7/S7PlcScanner.java         | 2 +-
 .../s7/src/test/java/org/apache/plc4x/java/s7/S7PlcTestConsole.java     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/S7PlcScanner.java b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/S7PlcScanner.java
index 53bbb37..2650274 100644
--- a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/S7PlcScanner.java
+++ b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/S7PlcScanner.java
@@ -43,7 +43,7 @@ public class S7PlcScanner {
     public static void main(String[] args) throws Exception {
         // Create a connection to the S7 PLC (s7://{hostname/ip}/{racknumber}/{slotnumber})
         logger.info("Connecting");
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection("s7://192.168.0.1/0/0")) {
+        try (PlcConnection plcConnection = new PlcDriverManager().getConnection("s7://10.10.64.20/1/1")) {
             logger.info("Connected");
 
             Optional<PlcReader> reader = plcConnection.getReader();
diff --git a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/S7PlcTestConsole.java b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/S7PlcTestConsole.java
index 06f14b3..5ca77b6 100644
--- a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/S7PlcTestConsole.java
+++ b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/S7PlcTestConsole.java
@@ -44,7 +44,7 @@ public class S7PlcTestConsole {
     public static void main(String[] args) throws Exception {
         // Create a connection to the S7 PLC (s7://{hostname/ip}/{racknumber}/{slotnumber})
         logger.info("Connecting");
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection("s7://192.168.0.1/0/0")) {
+        try (PlcConnection plcConnection = new PlcDriverManager().getConnection("s7://10.10.64.20/1/1")) {
             logger.info("Connected");
 
             Optional<PlcReader> reader = plcConnection.getReader();

-- 
To stop receiving notification emails like this one, please contact
cdutz@apache.org.

[incubator-plc4x] 02/05: Updated the Kafka Bridge example to a more advanced version currently running at a customers site.

Posted by cd...@apache.org.
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

commit 094994616645bf7be56c092d41148105a035c19f
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Fri May 18 16:44:07 2018 +0200

    Updated the Kafka Bridge example to a more advanced version currently running at a customers site.
    
    (cherry picked from commit 1873276)
---
 examples/kafka-bridge/pom.xml                      |  4 ++
 .../java/examples/kafkabridge/KafkaBridge.java     | 67 ++++++++++++++++------
 .../examples/kafkabridge/model/Configuration.java  |  9 +++
 .../model/{Address.java => PlcAddress.java}        | 11 +++-
 .../java/examples/kafkabridge/model/PlcConfig.java | 23 ++++++--
 .../model/{Address.java => PlcMemoryBlock.java}    | 21 +------
 6 files changed, 90 insertions(+), 45 deletions(-)

diff --git a/examples/kafka-bridge/pom.xml b/examples/kafka-bridge/pom.xml
index b922d8b..b637af5 100644
--- a/examples/kafka-bridge/pom.xml
+++ b/examples/kafka-bridge/pom.xml
@@ -84,6 +84,10 @@
       <artifactId>jackson-annotations</artifactId>
       <version>2.9.0</version>
     </dependency>
+    <dependency>
+      <groupId>com.google.code.gson</groupId>
+      <artifactId>gson</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.commons</groupId>
diff --git a/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/KafkaBridge.java b/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/KafkaBridge.java
index 0a223ce..6f2e88c 100644
--- a/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/KafkaBridge.java
+++ b/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/KafkaBridge.java
@@ -20,12 +20,12 @@ package org.apache.plc4x.java.examples.kafkabridge;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import com.google.gson.JsonObject;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.edgent.connectors.kafka.KafkaProducer;
 import org.apache.edgent.function.Supplier;
@@ -34,10 +34,16 @@ import org.apache.edgent.topology.TStream;
 import org.apache.edgent.topology.Topology;
 import org.apache.plc4x.edgent.PlcConnectionAdapter;
 import org.apache.plc4x.edgent.PlcFunctions;
+import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcException;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
 import org.apache.plc4x.java.api.messages.items.ReadRequestItem;
-import org.apache.plc4x.java.examples.kafkabridge.model.Address;
+import org.apache.plc4x.java.api.messages.items.ReadResponseItem;
+import org.apache.plc4x.java.api.model.Address;
+import org.apache.plc4x.java.examples.kafkabridge.model.PlcAddress;
 import org.apache.plc4x.java.examples.kafkabridge.model.Configuration;
+import org.apache.plc4x.java.examples.kafkabridge.model.PlcMemoryBlock;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -71,31 +77,54 @@ public class KafkaBridge {
         DirectProvider dp = new DirectProvider();
         Topology top = dp.newTopology("kafka-bridge");
 
-        Map<String, ReadRequestItem> readRequestItems = new HashMap<>();
-        for(Address address : config.getPlcConfig().getAddresses()) {
-            try {
-                org.apache.plc4x.java.api.model.Address plcAddress = plcAdapter.parseAddress(address.getAddress());
-                ReadRequestItem readItem = new ReadRequestItem<>(address.getType(), plcAddress, address.getSize());
-                readRequestItems.put(address.getName(), readItem);
-            } catch (PlcException e) {
-                logger.error("Error parsing address {}", address.getAddress(), e);
+        // Build the entire request.
+        Map<ReadRequestItem, String> names = new HashMap<>();
+        PlcReadRequest readRequest = new PlcReadRequest();
+        for(PlcMemoryBlock plcMemoryBlock : config.getPlcConfig().getPlcMemoryBlocks()) {
+            for (PlcAddress address : config.getPlcConfig().getPlcAddresses()) {
+                try {
+                    Address plcAddress = plcAdapter.parseAddress(
+                            "DATA_BLOCKS/" + plcMemoryBlock.getAddress() + "/" + address.getAddress());
+                    ReadRequestItem readItem = new ReadRequestItem<>(address.getType(), plcAddress,
+                            +address.getSize());
+                    readRequest.addItem(readItem);
+                    names.put(readItem, plcMemoryBlock.getName() + "/" + address.getName());
+                } catch (PlcConnectionException e) {
+                    logger.error("Error connecting to remote", e);
+                    System.exit(1);
+                } catch (PlcException e) {
+                    logger.error("Error parsing address {}", address.getAddress(), e);
+                    System.exit(1);
+                }
             }
         }
-        // TODO: Here we somehow have to create an Edgent supplier, that can cope with batch reads ...
-        // WARN: This example doesn't work at the moment ...
-        Supplier<Byte> plcSupplier = PlcFunctions.byteSupplier(plcAdapter, "INPUTS/0");
+
+        // Create a supplier that is able to read the batch we just created.
+        Supplier<PlcReadResponse> plcSupplier = PlcFunctions.batchSupplier(plcAdapter, readRequest);
 
         // Start polling our plc source in the given interval.
-        TStream<Byte> source = top.poll(plcSupplier, config.getPollingInterval(), TimeUnit.MILLISECONDS);
+        TStream<PlcReadResponse> source = top.poll(plcSupplier, config.getPollingInterval(), TimeUnit.MILLISECONDS);
 
         // Convert the byte into a string.
-        TStream<String> stringSource = source.map(value -> Byte.toString(value));
+        TStream<String> jsonSource = source.map(value -> {
+            JsonObject jsonObject = new JsonObject();
+            for (ReadResponseItem<?> readResponseItem : value.getResponseItems()) {
+                String name = names.get(readResponseItem.getRequestItem());
+                if(readResponseItem.getValues().size() == 1) {
+                    jsonObject.addProperty(name, Byte.toString((Byte) readResponseItem.getValues().get(0)));
+                } else if (readResponseItem.getValues().size() > 1) {
+                    // TODO: Implement this ...
+                    //jsonObject.addProperty(name, readResponseItem.getValues());
+                }
+            }
+            return jsonObject.toString();
+        });
 
-        // Publish the stream to the topic.  The String tuple is the message value.
+        // Publish the stream to the topic. The String tuple is the message value.
         // Create the Kafka Producer broker connector
         Map<String,Object> kafkaConfig = createKafkaConfig();
         KafkaProducer kafka = new KafkaProducer(top, () -> kafkaConfig);
-        kafka.publish(stringSource, config.getKafkaConfig().getTopicName());
+        kafka.publish(jsonSource, config.getKafkaConfig().getTopicName());
 
         dp.submit(top);
     }
@@ -111,7 +140,7 @@ public class KafkaBridge {
 
     public static void main(String[] args) {
         if(args.length != 1) {
-            System.out.println("Usage: KafkaBridge {path-to-kafkabridge-yml}");
+            System.out.println("Usage: KafkaBridge {path-to-kafka-bridge.yml}");
         }
         KafkaBridge kafkaBridge = new KafkaBridge(args[0]);
         kafkaBridge.run();
diff --git a/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/Configuration.java b/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/Configuration.java
index 8e2ce42..6de279d 100644
--- a/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/Configuration.java
+++ b/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/Configuration.java
@@ -28,6 +28,8 @@ public class Configuration {
     private PlcConfig plcConfig;
     @JsonProperty("polling-interval")
     private int pollingInterval;
+    @JsonProperty("commission-id")
+    private String commissionId;
 
     public KafkaConfig getKafkaConfig() {
         return kafkaConfig;
@@ -53,4 +55,11 @@ public class Configuration {
         this.pollingInterval = pollingInterval;
     }
 
+    public String getCommissionId() {
+        return commissionId;
+    }
+
+    public void setCommissionId(String commissionId) {
+        this.commissionId = commissionId;
+    }
 }
diff --git a/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/Address.java b/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/PlcAddress.java
similarity index 86%
copy from examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/Address.java
copy to examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/PlcAddress.java
index 686a49d..90d63de 100644
--- a/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/Address.java
+++ b/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/PlcAddress.java
@@ -18,9 +18,10 @@ under the License.
 */
 package org.apache.plc4x.java.examples.kafkabridge.model;
 
-public class Address {
+public class PlcAddress {
 
     private String name;
+    private String description;
     private String address;
     private int size;
     private Class<?> type;
@@ -33,6 +34,14 @@ public class Address {
         this.name = name;
     }
 
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
     public String getAddress() {
         return address;
     }
diff --git a/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/PlcConfig.java b/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/PlcConfig.java
index 76c76b9..aabc9c6 100644
--- a/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/PlcConfig.java
+++ b/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/PlcConfig.java
@@ -18,12 +18,17 @@ under the License.
 */
 package org.apache.plc4x.java.examples.kafkabridge.model;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+
 import java.util.List;
 
 public class PlcConfig {
 
     private String connection;
-    private List<Address> addresses;
+    @JsonProperty("memory-blocks")
+    private List<PlcMemoryBlock> plcMemoryBlocks;
+    @JsonProperty("addresses")
+    private List<PlcAddress> plcAddresses;
 
     public String getConnection() {
         return connection;
@@ -33,12 +38,20 @@ public class PlcConfig {
         this.connection = connection;
     }
 
-    public List<Address> getAddresses() {
-        return addresses;
+    public List<PlcMemoryBlock> getPlcMemoryBlocks() {
+        return plcMemoryBlocks;
+    }
+
+    public void setPlcMemoryBlocks(List<PlcMemoryBlock> plcMemoryBlocks) {
+        this.plcMemoryBlocks = plcMemoryBlocks;
+    }
+
+    public List<PlcAddress> getPlcAddresses() {
+        return plcAddresses;
     }
 
-    public void setAddresses(List<Address> addresses) {
-        this.addresses = addresses;
+    public void setPlcAddresses(List<PlcAddress> plcAddresses) {
+        this.plcAddresses = plcAddresses;
     }
 
 }
diff --git a/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/Address.java b/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/PlcMemoryBlock.java
similarity index 77%
rename from examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/Address.java
rename to examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/PlcMemoryBlock.java
index 686a49d..bfd99c8 100644
--- a/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/Address.java
+++ b/examples/kafka-bridge/src/main/java/org/apache/plc4x/java/examples/kafkabridge/model/PlcMemoryBlock.java
@@ -18,12 +18,10 @@ under the License.
 */
 package org.apache.plc4x.java.examples.kafkabridge.model;
 
-public class Address {
+public class PlcMemoryBlock {
 
     private String name;
     private String address;
-    private int size;
-    private Class<?> type;
 
     public String getName() {
         return name;
@@ -40,21 +38,4 @@ public class Address {
     public void setAddress(String address) {
         this.address = address;
     }
-
-    public int getSize() {
-        return size;
-    }
-
-    public void setSize(int size) {
-        this.size = size;
-    }
-
-    public Class<?> getType() {
-        return type;
-    }
-
-    public void setType(Class<?> type) {
-        this.type = type;
-    }
-
 }

-- 
To stop receiving notification emails like this one, please contact
cdutz@apache.org.

[incubator-plc4x] 05/05: Updated the iot-factory example to use Elasticsearch to save data which can then be displayed with Kibana (for example)

Posted by cd...@apache.org.
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

commit 851838e455cfe2fc59eae2e490428596a836a48e
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue May 22 17:40:49 2018 +0200

    Updated the iot-factory example to use Elasticsearch to save data which can then be displayed with Kibana (for example)
    
    (cherry picked from commit 93ae433)
---
 examples/iot-factory/README.adoc                   |  66 ++++++
 examples/iot-factory/pom.xml                       |  14 +-
 .../iotfactory/IotElasticsearchFactory.java        | 224 +++++++++++++++++++++
 .../plc4x/java/examples/iotfactory/IotFactory.java |  86 --------
 examples/iot-factory/src/main/resources/log4j2.xml |  35 ++++
 5 files changed, 338 insertions(+), 87 deletions(-)

diff --git a/examples/iot-factory/README.adoc b/examples/iot-factory/README.adoc
new file mode 100644
index 0000000..869730f
--- /dev/null
+++ b/examples/iot-factory/README.adoc
@@ -0,0 +1,66 @@
+//
+//  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.
+//
+
+== IoT Factory example
+
+In this example we will be running the full stack of tools for a rudimentary factory dashboard.
+
+This example however is everything but production ready.
+First of all we use create an Elasticsearch single node cluster embedded within the applications VM.
+Secondly we communicate with the `cluster` using the NodeClient, which is super-easy to use, but shouldn't be used in production type environments.
+
+We decided to go this path because this way it's super-easy to setup everything and running the example is nothing but starting a Java application.
+
+=== What else do I need?
+
+In General:
+- A PLC
+- A Factory
+
+Even if you might be able to get your hands on a PLC I doubt you have a spare factory available.
+
+This example is built to visualize a virtual factory simulated with https://factoryio.com/[Factory I/O].
+
+We have decided to stick with one of the on-board examples, to make it as easy as possible for you to reproduce.
+The example we used is: "Sorting by Height".
+
+Here's a video demonstrating this:
+https://www.youtube.com/watch?v=B0n8gT1vto4
+
+You can run this with a real PLC or use a PLC simulator.
+In our IoT lab we are currently running this with the real S7-1200.
+
+=== What happens in detail?
+
+When the application is started it first starts up an Elasticsearch node.
+
+After that is up and running, it checks if the indexes we are going to write to exist.
+
+If they don't and we would just have ES create them on the fly, we wouldn't be able to use the time-data in the time fields as they would be treated as numbers.
+
+Any non-existent indexes are created.
+
+After that an `Apache Edgent` instance is created and one stream is created to fetch the state of all 8 outputs of the PLC every 100ms.
+
+This stream is then split up.
+
+One branch simply dumps the data into the `factory-data` index.
+
+The second branch is a little more complex as it monitors the state of the left and right conveyors to extrapolate if a new `big` or `small box is being transported.
+
+Only when a new box is detected an entry is written into the `product-data` index.
+
diff --git a/examples/iot-factory/pom.xml b/examples/iot-factory/pom.xml
index 900c83d..fcda208 100644
--- a/examples/iot-factory/pom.xml
+++ b/examples/iot-factory/pom.xml
@@ -33,7 +33,7 @@
   <description>Client application demonstrating PLC4X in our virtual IoT Factory.</description>
 
   <properties>
-    <app.main.class>org.apache.plc4x.java.examples.iotfactory.IotFactory</app.main.class>
+    <app.main.class>org.apache.plc4x.java.examples.iotfactory.IotElasticsearchFactory</app.main.class>
   </properties>
 
   <dependencies>
@@ -59,6 +59,18 @@
       <version>1.2.0</version>
     </dependency>
 
+    <!-- Elasticsearch dependencies -->
+    <dependency>
+      <groupId>org.elasticsearch</groupId>
+      <artifactId>elasticsearch</artifactId>
+      <version>6.2.4</version>
+    </dependency>
+    <dependency>
+      <groupId>org.elasticsearch.plugin</groupId>
+      <artifactId>transport-netty4-client</artifactId>
+      <version>6.2.4</version>
+    </dependency>
+
     <!-- Required driver implementation -->
     <dependency>
       <groupId>org.apache.plc4x</groupId>
diff --git a/examples/iot-factory/src/main/java/org/apache/plc4x/java/examples/iotfactory/IotElasticsearchFactory.java b/examples/iot-factory/src/main/java/org/apache/plc4x/java/examples/iotfactory/IotElasticsearchFactory.java
new file mode 100644
index 0000000..1a0c225
--- /dev/null
+++ b/examples/iot-factory/src/main/java/org/apache/plc4x/java/examples/iotfactory/IotElasticsearchFactory.java
@@ -0,0 +1,224 @@
+package org.apache.plc4x.java.examples.iotfactory;
+/*
+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.
+*/
+
+import org.apache.edgent.function.Supplier;
+import org.apache.edgent.providers.direct.DirectProvider;
+import org.apache.edgent.topology.TStream;
+import org.apache.edgent.topology.Topology;
+import org.apache.plc4x.edgent.PlcConnectionAdapter;
+import org.apache.plc4x.edgent.PlcFunctions;
+import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
+import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
+import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
+import org.elasticsearch.action.index.IndexResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.client.IndicesAdminClient;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.node.InternalSettingsPreparer;
+import org.elasticsearch.node.Node;
+import org.elasticsearch.node.NodeValidationException;
+import org.elasticsearch.plugins.Plugin;
+import org.elasticsearch.transport.Netty4Plugin;
+
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+
+public class IotElasticsearchFactory {
+
+    public enum ConveyorState {
+        STOPPED,
+        RUNNING_LEFT,
+        RUNNING_RIGHT
+    }
+
+    private ConveyorState conveyorState = ConveyorState.STOPPED;
+
+    private Node startElasticsearchNode() throws NodeValidationException {
+        Node node = new MyNode(Settings.builder()
+            .put("transport.type", "netty4")
+            .put("http.type", "netty4")
+            .put("http.enabled", "true")
+            .put("path.home", "elasticsearch-data")
+            .build(), Collections.singletonList(Netty4Plugin.class));
+        node.start();
+        return node;
+    }
+
+    private void prepareIndexes(Client esClient) throws Exception {
+        IndicesAdminClient indicesAdminClient = esClient.admin().indices();
+
+        // Check if the factory-data index exists and create it, if it doesn't.
+        IndicesExistsRequest factoryDataIndexExistsRequest =
+            indicesAdminClient.prepareExists("product-data").request();
+        if(!indicesAdminClient.exists(factoryDataIndexExistsRequest).actionGet().isExists()) {
+            CreateIndexRequest createIndexRequest = new CreateIndexRequest("factory-data");
+            createIndexRequest.mapping("FactoryData",
+                "{\n" +
+                    "            \"properties\": {\n" +
+                    "                \"time\": {\n" +
+                    "                    \"type\": \"date\"\n" +
+                    "                }\n" +
+                    "            }\n" +
+                    "        }", XContentType.JSON);
+            CreateIndexResponse createIndexResponse = indicesAdminClient.create(createIndexRequest).actionGet();
+            if(!createIndexResponse.isAcknowledged()) {
+                throw new Exception("Could not create index 'product-data'");
+            }
+        }
+
+        // Check if the product-data index exists and create it, if it doesn't.
+        IndicesExistsRequest productDataIndexExistsRequest =
+            indicesAdminClient.prepareExists("product-data").request();
+        if(!indicesAdminClient.exists(productDataIndexExistsRequest).actionGet().isExists()) {
+            CreateIndexRequest createIndexRequest = new CreateIndexRequest("product-data");
+            createIndexRequest.mapping("ProductData",
+                "{\n" +
+                    "            \"properties\": {\n" +
+                    "                \"time\": {\n" +
+                    "                    \"type\": \"date\"\n" +
+                    "                },\n" +
+                    "                \"type\": {\n" +
+                    "                    \"type\": \"keyword\"\n" +
+                    "                }\n" +
+                    "            }\n" +
+                    "        }", XContentType.JSON);
+            CreateIndexResponse createIndexResponse = indicesAdminClient.create(createIndexRequest).actionGet();
+            if(!createIndexResponse.isAcknowledged()) {
+                throw new Exception("Could not create index 'product-data'");
+            }
+        }
+    }
+
+    private void runFactory() throws Exception {
+        // Start an Elasticsearch node.
+        Node esNode = startElasticsearchNode();
+        Client esClient = esNode.client();
+        System.out.println("Started Elasticsearch node on port 9200");
+
+        // Make sure the indexes exist prior to writing to them.
+        prepareIndexes(esClient);
+
+        // Get a plc connection.
+        try (PlcConnectionAdapter plcAdapter = new PlcConnectionAdapter("s7://10.10.64.20/1/1")) {
+            // Initialize the Edgent core.
+            DirectProvider dp = new DirectProvider();
+            Topology top = dp.newTopology();
+
+            // Define the event stream.
+            // 1) PLC4X source generating a stream of bytes.
+            Supplier<Byte> plcSupplier = PlcFunctions.byteSupplier(plcAdapter, "OUTPUTS/0");
+            // 2) Use polling to get an item from the byte-stream in regular intervals.
+            TStream<Byte> plcOutputStates = top.poll(plcSupplier, 100, TimeUnit.MILLISECONDS);
+
+            // 3a) Create a stream that pumps all data into a 'factory-data' index.
+            TStream<XContentBuilder> factoryData = plcOutputStates.map(value -> {
+                boolean conveyorEntry = (value & 1) != 0;
+                boolean load = (value & 2) != 0;
+                boolean unload = (value & 4) != 0;
+                boolean transferLeft = (value & 8) != 0;
+                boolean transferRight = (value & 16) != 0;
+                boolean conveyorLeft = (value & 32) != 0;
+                boolean conveyorRight = (value & 64) != 0;
+
+                try {
+                    return XContentFactory.jsonBuilder()
+                        .startObject()
+                        .field("time", Calendar.getInstance().getTimeInMillis())
+                        .field("conveyorEntry", conveyorEntry)
+                        .field("load", load)
+                        .field( "unload", unload)
+                        .field( "transferLeft", transferLeft)
+                        .field( "transferRight", transferRight)
+                        .field( "conveyorLeft", conveyorLeft)
+                        .field( "conveyorRight", conveyorRight)
+                        .endObject();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+                return null;
+            });
+            TStream<IndexResponse> factoryDataResponses = factoryData.map(
+                value -> esClient.prepareIndex("factory-data", "FactoryData").setSource(value).get());
+            factoryDataResponses.print();
+
+            // 3b) Create a stream that does some local analysis to detect big and small boxes and to only output
+            //     something to the 'product-data' index, if a new item is detected.
+            TStream<XContentBuilder> productData = plcOutputStates.map(value -> {
+                    boolean transferLeft = (value & 8) != 0;
+                    boolean transferRight = (value & 16) != 0;
+
+                    if (conveyorState == ConveyorState.STOPPED) {
+                        if (transferLeft | transferRight) {
+                            if (transferLeft) {
+                                conveyorState = ConveyorState.RUNNING_LEFT;
+                                try {
+                                    return XContentFactory.jsonBuilder()
+                                        .startObject()
+                                        .field("time", Calendar.getInstance().getTimeInMillis())
+                                        .field("type", "small")
+                                        .endObject();
+                                } catch (IOException e) {
+                                    e.printStackTrace();
+                                }
+                            } else {
+                                conveyorState = ConveyorState.RUNNING_RIGHT;
+                                try {
+                                    return XContentFactory.jsonBuilder()
+                                        .startObject()
+                                        .field("time", Calendar.getInstance().getTimeInMillis())
+                                        .field("type", "large")
+                                        .endObject();
+                                } catch (IOException e) {
+                                    e.printStackTrace();
+                                }
+                            }
+                        }
+                    } else if (!(transferLeft | transferRight)) {
+                        conveyorState = ConveyorState.STOPPED;
+                    }
+                    return null;
+                });
+            TStream<IndexResponse> productDataResponses = productData.map(
+                value -> esClient.prepareIndex("product-data", "ProductData").setSource(value).get());
+            productDataResponses.print();
+
+            // Submit the topology and hereby start the event streams.
+            dp.submit(top);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        IotElasticsearchFactory factory = new IotElasticsearchFactory();
+        factory.runFactory();
+    }
+
+    private static class MyNode extends Node {
+        private MyNode(Settings preparedSettings, Collection<Class<? extends Plugin>> classpathPlugins) {
+            super(InternalSettingsPreparer.prepareEnvironment(preparedSettings, null), classpathPlugins);
+        }
+    }
+
+}
diff --git a/examples/iot-factory/src/main/java/org/apache/plc4x/java/examples/iotfactory/IotFactory.java b/examples/iot-factory/src/main/java/org/apache/plc4x/java/examples/iotfactory/IotFactory.java
deleted file mode 100644
index 91f6d26..0000000
--- a/examples/iot-factory/src/main/java/org/apache/plc4x/java/examples/iotfactory/IotFactory.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.apache.plc4x.java.examples.iotfactory;/*
-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.
-*/
-
-import org.apache.edgent.function.Supplier;
-import org.apache.edgent.providers.direct.DirectProvider;
-import org.apache.edgent.topology.TStream;
-import org.apache.edgent.topology.Topology;
-import org.apache.plc4x.edgent.PlcConnectionAdapter;
-import org.apache.plc4x.edgent.PlcFunctions;
-
-import java.util.concurrent.TimeUnit;
-
-public class IotFactory {
-
-    public enum ConveyorState {
-        STOPPED,
-        RUNNING_LEFT,
-        RUNNING_RIGHT
-    };
-
-    private static int smallBoxes = 0;
-    private static int largeBoxes = 0;
-    private static ConveyorState conveyorState = ConveyorState.STOPPED;
-
-
-    public static void main(String[] args) throws Exception {
-        // Get a plc connection.
-        try (PlcConnectionAdapter plcAdapter = new PlcConnectionAdapter("s7://10.10.64.20/1/1")) {
-            // Initialize the Edgent core.
-            DirectProvider dp = new DirectProvider();
-            Topology top = dp.newTopology();
-
-            // Define the event stream.
-            // 1) PLC4X source generating a stream of bytes.
-            Supplier<Byte> plcSupplier = PlcFunctions.byteSupplier(plcAdapter, "OUTPUTS/0");
-            // 2) Use polling to get an item from the byte-stream in regular intervals.
-            TStream<Byte> source = top.poll(plcSupplier, 100, TimeUnit.MILLISECONDS);
-            // 3) Output the events in the stream on the console.
-
-            source.sink(value -> {
-                boolean runningLeft = (value & 8) != 0;
-                boolean runningRight = (value & 16) != 0;
-
-                if(conveyorState == ConveyorState.STOPPED) {
-                    if(runningLeft | runningRight) {
-                        if (runningLeft) {
-                            smallBoxes++;
-                            conveyorState = ConveyorState.RUNNING_LEFT;
-                            updateOutput();
-                        } else {
-                            largeBoxes++;
-                            conveyorState = ConveyorState.RUNNING_RIGHT;
-                            updateOutput();
-                        }
-                    }
-                } else if (!(runningLeft | runningRight)){
-                    conveyorState = ConveyorState.STOPPED;
-                }
-            });
-
-            // Submit the topology and hereby start the event streams.
-            dp.submit(top);
-        }
-    }
-
-    private static void updateOutput() {
-        System.out.println(String.format("Small Boxes: %3d, Large Boxes %3d", smallBoxes, largeBoxes));
-    }
-
-}
diff --git a/examples/iot-factory/src/main/resources/log4j2.xml b/examples/iot-factory/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..d82c7c3
--- /dev/null
+++ b/examples/iot-factory/src/main/resources/log4j2.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  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.
+
+-->
+<Configuration package="log4j.test"
+               status="WARN">
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
+    </Console>
+  </Appenders>
+  <Loggers>
+    <Logger name="io.netty.util.ResourceLeakDetector" level="fatal">
+      <AppenderRef ref="Console"/>
+    </Logger>
+    <Root level="info">
+      <AppenderRef ref="Console"/>
+    </Root>
+  </Loggers>
+</Configuration>
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
cdutz@apache.org.

[incubator-plc4x] 03/05: Added a new example using the iot-labs virtual factory.

Posted by cd...@apache.org.
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

commit 1e70443c001168eb8f65eadc9691b834fb88509b
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Fri May 18 16:44:43 2018 +0200

    Added a new example using the iot-labs virtual factory.
    
    (cherry picked from commit df9536a)
---
 examples/iot-factory/pom.xml                       | 100 +++++++++++++++++++++
 .../plc4x/java/examples/iotfactory/IotFactory.java |  86 ++++++++++++++++++
 .../iot-factory/src/main/resources/logback.xml     |  40 +++++++++
 examples/pom.xml                                   |  18 ++++
 4 files changed, 244 insertions(+)

diff --git a/examples/iot-factory/pom.xml b/examples/iot-factory/pom.xml
new file mode 100644
index 0000000..900c83d
--- /dev/null
+++ b/examples/iot-factory/pom.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.plc4x.examples</groupId>
+    <artifactId>examples</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>iot-factory</artifactId>
+  <name>Examples: IoT Factory</name>
+  <description>Client application demonstrating PLC4X in our virtual IoT Factory.</description>
+
+  <properties>
+    <app.main.class>org.apache.plc4x.java.examples.iotfactory.IotFactory</app.main.class>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>apache-edgent</artifactId>
+      <version>0.0.1-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.edgent</groupId>
+      <artifactId>edgent-api-function</artifactId>
+      <version>1.2.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.edgent</groupId>
+      <artifactId>edgent-api-topology</artifactId>
+      <version>1.2.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.edgent</groupId>
+      <artifactId>edgent-providers-direct</artifactId>
+      <version>1.2.0</version>
+    </dependency>
+
+    <!-- Required driver implementation -->
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-protocol-s7</artifactId>
+      <version>0.0.1-SNAPSHOT</version>
+      <scope>runtime</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>log4j-over-slf4j</artifactId>
+      <version>1.7.25</version>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <configuration>
+          <usedDependencies>
+            <usedDependency>org.apache.plc4x:plc4j-protocol-s7</usedDependency>
+            <usedDependency>org.slf4j:log4j-over-slf4j</usedDependency>
+          </usedDependencies>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
\ No newline at end of file
diff --git a/examples/iot-factory/src/main/java/org/apache/plc4x/java/examples/iotfactory/IotFactory.java b/examples/iot-factory/src/main/java/org/apache/plc4x/java/examples/iotfactory/IotFactory.java
new file mode 100644
index 0000000..91f6d26
--- /dev/null
+++ b/examples/iot-factory/src/main/java/org/apache/plc4x/java/examples/iotfactory/IotFactory.java
@@ -0,0 +1,86 @@
+package org.apache.plc4x.java.examples.iotfactory;/*
+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.
+*/
+
+import org.apache.edgent.function.Supplier;
+import org.apache.edgent.providers.direct.DirectProvider;
+import org.apache.edgent.topology.TStream;
+import org.apache.edgent.topology.Topology;
+import org.apache.plc4x.edgent.PlcConnectionAdapter;
+import org.apache.plc4x.edgent.PlcFunctions;
+
+import java.util.concurrent.TimeUnit;
+
+public class IotFactory {
+
+    public enum ConveyorState {
+        STOPPED,
+        RUNNING_LEFT,
+        RUNNING_RIGHT
+    };
+
+    private static int smallBoxes = 0;
+    private static int largeBoxes = 0;
+    private static ConveyorState conveyorState = ConveyorState.STOPPED;
+
+
+    public static void main(String[] args) throws Exception {
+        // Get a plc connection.
+        try (PlcConnectionAdapter plcAdapter = new PlcConnectionAdapter("s7://10.10.64.20/1/1")) {
+            // Initialize the Edgent core.
+            DirectProvider dp = new DirectProvider();
+            Topology top = dp.newTopology();
+
+            // Define the event stream.
+            // 1) PLC4X source generating a stream of bytes.
+            Supplier<Byte> plcSupplier = PlcFunctions.byteSupplier(plcAdapter, "OUTPUTS/0");
+            // 2) Use polling to get an item from the byte-stream in regular intervals.
+            TStream<Byte> source = top.poll(plcSupplier, 100, TimeUnit.MILLISECONDS);
+            // 3) Output the events in the stream on the console.
+
+            source.sink(value -> {
+                boolean runningLeft = (value & 8) != 0;
+                boolean runningRight = (value & 16) != 0;
+
+                if(conveyorState == ConveyorState.STOPPED) {
+                    if(runningLeft | runningRight) {
+                        if (runningLeft) {
+                            smallBoxes++;
+                            conveyorState = ConveyorState.RUNNING_LEFT;
+                            updateOutput();
+                        } else {
+                            largeBoxes++;
+                            conveyorState = ConveyorState.RUNNING_RIGHT;
+                            updateOutput();
+                        }
+                    }
+                } else if (!(runningLeft | runningRight)){
+                    conveyorState = ConveyorState.STOPPED;
+                }
+            });
+
+            // Submit the topology and hereby start the event streams.
+            dp.submit(top);
+        }
+    }
+
+    private static void updateOutput() {
+        System.out.println(String.format("Small Boxes: %3d, Large Boxes %3d", smallBoxes, largeBoxes));
+    }
+
+}
diff --git a/examples/iot-factory/src/main/resources/logback.xml b/examples/iot-factory/src/main/resources/logback.xml
new file mode 100644
index 0000000..71652b3
--- /dev/null
+++ b/examples/iot-factory/src/main/resources/logback.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  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.
+
+-->
+<configuration xmlns="http://ch.qos.logback/xml/ns/logback"
+               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xsi:schemaLocation="http://ch.qos.logback/xml/ns/logback https://raw.githubusercontent.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <!-- encoders are assigned the type
+         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <logger level="OFF" name="io.netty.util" additivity="false">
+    <appender-ref ref="STDOUT" />
+  </logger>
+
+  <root level="warn">
+    <appender-ref ref="STDOUT" />
+  </root>
+
+</configuration>
\ No newline at end of file
diff --git a/examples/pom.xml b/examples/pom.xml
index 88e92bd..574edcd 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -37,11 +37,29 @@
 
   <modules>
     <module>dummy-driver</module>
+    <module>iot-factory</module>
     <module>iotree</module>
     <module>kafka-bridge</module>
     <module>plclogger</module>
   </modules>
 
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>ch.qos.logback</groupId>
+        <artifactId>logback-core</artifactId>
+        <version>${logback.version}</version>
+        <scope>compile</scope>
+      </dependency>
+      <dependency>
+        <groupId>ch.qos.logback</groupId>
+        <artifactId>logback-classic</artifactId>
+        <version>${logback.version}</version>
+        <scope>compile</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
   <profiles>
     <profile>
       <id>build-executable-jars</id>

-- 
To stop receiving notification emails like this one, please contact
cdutz@apache.org.

[incubator-plc4x] 04/05: Added some documentation on setting up AMS routes for Beckhoff

Posted by cd...@apache.org.
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

commit 86ebdc2502f59db24bad4bbc5aa55dda24e4ee26
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue May 22 11:48:25 2018 +0200

    Added some documentation on setting up AMS routes for Beckhoff
    
    (cherry picked from commit 6a0bebe)
---
 src/site/asciidoc/developers/vpn.adoc              |  33 +++++++++++++++++++++
 .../resources/img/plc4x-vpn-beckhoff-route-1.png   | Bin 0 -> 99036 bytes
 .../resources/img/plc4x-vpn-beckhoff-route-2.png   | Bin 0 -> 87524 bytes
 .../resources/img/plc4x-vpn-beckhoff-route-3.png   | Bin 0 -> 185843 bytes
 4 files changed, 33 insertions(+)

diff --git a/src/site/asciidoc/developers/vpn.adoc b/src/site/asciidoc/developers/vpn.adoc
index c3e19e1..1014f88 100644
--- a/src/site/asciidoc/developers/vpn.adoc
+++ b/src/site/asciidoc/developers/vpn.adoc
@@ -122,6 +122,39 @@ This device is able to use the following protocols:
 
 It is configured to use the IP: `10.10.64.40`
 
+Beckhoff PLCs are processes running on a host operating system.
+
+In this case, this host OS is `Windows 7 Professional`.
+
+These processes seem to communicate with an internal network, which isn't connected to the physical network of the host.
+
+In order to be able to communicate with the PLC from the outside world, a so-called `AMS Route` needs to be added.
+Unfortunately it seems that this route needs to be added individually for every clients ip.
+As the VPN gateway is automatically assigning IPs to the clients, this step eventually has to be done every time you log in.
+Right now we hope that as soon as routes have been added for quite some ips, eventually we won't have to do this anymore, but right now it looks as if we do.
+
+Adding a route is done by opening the ADS Route Editor on the Beckhoff machine:
+
+image::plc4x-vpn-beckhoff-route-1.png[]
+
+Here you click on add:
+
+image::plc4x-vpn-beckhoff-route-2.png[]
+
+And enter the details of the new route:
+
+image::plc4x-vpn-beckhoff-route-3.png[]
+
+Here it is important to give the route a name.
+The `AmsNetId` is sort of like a 6-segment ipv4-address. It could be chosen independently from the real ip address, however the default is to use the ip address for the first 4 segments and to append `.1.1` after this.
+So from an ip address: `10.10.57.104` the corresponding `AmsNetId` would be: `10.10.57.104.1.1`.
+`Transport Type` should be set to: `TCP_IP`.
+`Address Info` is where the clients ip address is added.
+Be sure to select the `IP Address` radio button below.
+Next thing, you should ensure, is that the type of `Remote Route` is set to `None`.
+
+When clicking on `Add Route`, don't be surprised that the window doesn't close, you have to click on `Close` after that and then you should see your new route in the route list screen.
+
 === Requesting an account
 
 The PLC hardware in the `PLC4X IoT Lab` is hosted in the codecentric Frankfurt office.
diff --git a/src/site/resources/img/plc4x-vpn-beckhoff-route-1.png b/src/site/resources/img/plc4x-vpn-beckhoff-route-1.png
new file mode 100644
index 0000000..ae4d50c
Binary files /dev/null and b/src/site/resources/img/plc4x-vpn-beckhoff-route-1.png differ
diff --git a/src/site/resources/img/plc4x-vpn-beckhoff-route-2.png b/src/site/resources/img/plc4x-vpn-beckhoff-route-2.png
new file mode 100644
index 0000000..1c37c3d
Binary files /dev/null and b/src/site/resources/img/plc4x-vpn-beckhoff-route-2.png differ
diff --git a/src/site/resources/img/plc4x-vpn-beckhoff-route-3.png b/src/site/resources/img/plc4x-vpn-beckhoff-route-3.png
new file mode 100644
index 0000000..c826d43
Binary files /dev/null and b/src/site/resources/img/plc4x-vpn-beckhoff-route-3.png differ

-- 
To stop receiving notification emails like this one, please contact
cdutz@apache.org.