You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cg...@apache.org on 2023/11/18 02:38:24 UTC
(plc4x) branch issue/s7h updated: Improved CYC example. Go to develop.
This is an automated email from the ASF dual-hosted git repository.
cgarcia pushed a commit to branch issue/s7h
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/issue/s7h by this push:
new 1e434e3859 Improved CYC example. Go to develop.
1e434e3859 is described below
commit 1e434e38592f2013c96f35e419bd102172905361
Author: Cesar Garcia <ce...@ceos.com.ve>
AuthorDate: Fri Nov 17 22:37:38 2023 -0400
Improved CYC example. Go to develop.
---
.../plc4j/s7event/PlcCycSubscriptionS7400H.java | 433 +++++++++++++--------
.../examples/plc4j/s7event/PlcReadDataS7400H.java | 4 +-
.../examples/plc4j/s7event/PlcReadS71200.java | 12 +-
3 files changed, 287 insertions(+), 162 deletions(-)
diff --git a/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/PlcCycSubscriptionS7400H.java b/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/PlcCycSubscriptionS7400H.java
index 19ab119627..aeb030534c 100644
--- a/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/PlcCycSubscriptionS7400H.java
+++ b/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/PlcCycSubscriptionS7400H.java
@@ -21,7 +21,6 @@ package org.apache.plc4x.examples.plc4j.s7event;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.apache.commons.codec.binary.Hex;
import org.apache.plc4x.java.DefaultPlcDriverManager;
-import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.messages.PlcSubscriptionRequest;
import org.apache.plc4x.java.api.messages.PlcUnsubscriptionRequest;
import org.apache.plc4x.java.api.messages.PlcSubscriptionResponse;
@@ -30,203 +29,323 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.commons.lang3.time.StopWatch;
import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
import org.apache.plc4x.java.api.listener.ConnectionStateListener;
-import org.apache.plc4x.java.api.messages.PlcUnsubscriptionResponse;
-import org.apache.plc4x.java.s7.readwrite.connection.S7HDefaultNettyPlcConnection;
import org.apache.plc4x.java.s7.readwrite.protocol.S7HPlcConnection;
/**
- * Example for capturing events generated from a Siemens S7-300, S7-400 or VIPA PLC.
- * Support for mode events ("MODE"), system events ("SYS"), user events ("USR")
- * and alarms ("ALM").
- * Each consumer shows the tags and associated values of the "map" containing
- * the event parameters.
- */
+ * Cyclic subscription allows the acquisition of data from
+ * the controller in push mode, the PLC is responsible for sending
+ * the data to the client application. The minimum time base is 100 msec.
+ * The data is sent as a stream of bytes so the client must
+ * maintain its consistency.This is the working mode of WinCC Scada.
+ * The connection is supervised.
+ * Plc: SIMATIC S7-400
+ * Model: CPU 417
+ * Part number: 6ES7 417-4XT05-0AB0
+ * Firmware version: 5.1.0
+ * CP1: 6GK7 443-1EX11-0XE0
+ * CP2: 6GK7 443-1EX20-0XB0
+*/
public class PlcCycSubscriptionS7400H implements ConnectionStateListener {
private static final Logger logger = LoggerFactory.getLogger(PlcCycSubscriptionS7400H.class);
- private S7HPlcConnection connection = null;
- private PlcSubscriptionResponse subresponse = null;
- private boolean shutdown = false;
- private boolean subscricted = false;
- private boolean unsubscricted = false;
+ private S7HPlcConnection connection = null;
+ private AtomicBoolean isConnected = new AtomicBoolean(false);
+ private AtomicBoolean ShutDown = new AtomicBoolean(false);
+ private final DefaultThreadFactory dtf = new DefaultThreadFactory("CYC", true);
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
- System.setProperty(org.slf4j.simple.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "Debug");
+ System.setProperty(org.slf4j.simple.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "Info");
- PlcCycSubscriptionS7400H myapp = new PlcCycSubscriptionS7400H();
- myapp.run(args);
-
-
+ PlcCycSubscriptionS7400H device = new PlcCycSubscriptionS7400H();
+ device.run(args);
}
- public void makeconnection() {
- try {
- connection =(S7HPlcConnection) new DefaultPlcDriverManager().getConnection("s7://10.10.1.80/10.10.1.81?remote-rack=0&remote-slot=3&remote-rack2=0&remote-slot=4&controller-type=S7_400&read-timeout=8&ping=true&ping-time=4&retry-time=5");
- connection.addEventListener(this);
- while(!connection.isConnected()){
- System.out.println("Conectando...");
- };
- } catch (PlcConnectionException ex) {
- System.out.println("RUNSCAN: " + ex.getMessage());
- }
- }
-
- public void makesubscription() throws Exception {
- final PlcSubscriptionRequest.Builder subscription = connection.subscriptionRequestBuilder();
- //subscription.addEventTagAddress("myCYC", "CYC(B01SEC:5):%DB9002.DBB0[1]");
- subscription.addEventTagAddress("myCYC_01", "CYC(B01SEC:5):%MB190:BYTE");
- subscription.addEventTagAddress("myCYC_02", "CYC(B01SEC:5):%MW190:INT");
-
- final PlcSubscriptionRequest sub = subscription.build();
- subresponse = sub.execute().get();
-
- //Si todo va bien con la subscripción puedo
-// subresponse
-// .getSubscriptionHandle("myMODE")
-// .register(msg -> {
-// System.out.println("******** S7ModeEvent ********");
-// Map<String, Object> map = ((S7ModeEvent) msg).getMap();
-// map.forEach((x, y) -> {
-// System.out.println(x + " : " + y);
-// });
-// System.out.println("****************************");
-// });
-//
-// subresponse
-// .getSubscriptionHandle("mySYS")
-// .register(msg -> {
-// System.out.println("******** S7SysEvent ********");
-// Map<String, Object> map = ((S7SysEvent) msg).getMap();
-// map.forEach((x, y) -> {
-// if ("INFO1".equals(x)) {
-// System.out.println(x + " : " + String.format("0x%04X", y));
-// } else if ("INFO2".equals(x)) {
-// System.out.println(x + " : " + String.format("0x%08X", y));
-// } else System.out.println(x + " : " + y);
-// });
-// System.out.println("****************************");
-// });
-//
-// subresponse
-// .getSubscriptionHandle("myUSR")
-// .register(msg -> {
-// System.out.println("******** S7UserEvent *******");
-// Map<String, Object> map = ((S7UserEvent) msg).getMap();
-// map.forEach((x, y) -> {
-// System.out.println(x + " : " + y);
-// });
-// System.out.println("****************************");
-// });
+ public void run (String[] args) throws Exception {
+
+ logger.info("*****************************************************");
+ logger.info("* Example of connection and read to a Simatic S7-400H");
+ logger.info("* Plc: SIMATIC S7-400");
+ logger.info("* Model: CPU 417");
+ logger.info("* Part number: 6ES7 417-4XT05-0AB0");
+ logger.info("* Firmware version: 5.1.0");
+ logger.info("* CP1: 6GK7 443-1EX11-0XE0");
+ logger.info("* CP2: 6GK7 443-1EX20-0XB0");
+ logger.info("*");
+ logger.info("* Note: . ");
+ logger.info("* . ");
+ logger.info("*****************************************************");
+
- subresponse.getSubscriptionHandles().forEach( a -> {
- System.out.println(a.toString());
- });
+
+ logger.info("*****************************************************");
+ logger.info("* 1. Once the connection is executed, it must ");
+ logger.info("* suscrict the data contained in the address.");
+ logger.info("* URL to:s7://10.10.1.80/10.10.1.81?remote-rack=0&");
+ logger.info(" remote-slot=3&remote-rack2=0&remote-slot=4&");
+ logger.info(" controller-type=S7_400&read-timeout=8&");
+ logger.info(" ping=true&ping-time=2&retry-time=3");
+ logger.info("* Press [ENTER]");
+ logger.info("*****************************************************");
+ System.in.read();
+
+ OpenConnection("s7://10.10.1.80/10.10.1.81?remote-rack=0&"
+ + "remote-slot=3&remote-rack2=0&remote-slot=4&"
+ + "controller-type=S7_400&read-timeout=8&"
+ + "ping=true&ping-time=2&retry-time=3"); //(01)
+
+ logger.info("*****************************************************");
+ logger.info("* 2. In this step subscriptions are launched.");
+ logger.info(" In the specific case of the S7-400,");
+ logger.info("* you can have up to 32 simultaneous subscriptions.");
+ logger.info("* You must be able to read the value from the PLC.");
+ logger.info("* Press [ENTER]");
+ logger.info("*****************************************************");
+ System.in.read();
- subresponse.getRequest().getTagNames().forEach(s -> {
- System.out.println("Tag " + s + " Tipo: " + subresponse.getRequest().getTag(s).getPlcValueType());
- });
+ MakeSubscription(); //(02)
+ logger.info("*****************************************************");
+ logger.info("* 3. Subscriptions are removed.");
+ logger.info("* Depending on how you handle your tasks, ");
+ logger.info("* you should ensure that they are all completed.");
+ logger.info("* Press [ENTER]");
+ logger.info("*****************************************************");
+ System.in.read();
+ MakeUnsubscription(); //(03)
+
+ logger.info("*****************************************************");
+ logger.info("* 4. We close the connection and release resources.");
+ logger.info("* Press [ENTER]");
+ logger.info("*****************************************************");
+ System.in.read();
+
+ CloseConnection(); //(04)
- subresponse
- .getSubscriptionHandle("myCYC_01")
- .register(msg -> {
- if (null == msg) return;
- System.out.println("******** CYC Event *********");
- Map<String, Object> map = ((S7CyclicEvent) msg).getMap();
- map.forEach((x, y) -> {
- if (x.startsWith("DATA_", 0)) {
- System.out.println("Longitud de datos: " + ((byte[]) y).length);
- System.out.println(x + ": " + Hex.encodeHexString((byte[]) y));
- } else
- System.out.println(x + " : " + y);
- });
- System.out.println("****************************");
- });
+ }
+
+ /***************************************************************************
+ * Under normal conditions, the driver expects you to have the PLC
+ * connected to the network to start operations.
+ * If a connection to the PLC cannot be established, an exception of type
+ * "PlcConnectionException" is generated, which must be handled by your
+ * application. In this example it waits for a connection to exist.
+ * When you disconnect the "connection", the S7 driver will take care of the
+ * connection and reconnection process if necessary.
+ * The internal wait time for the connection is one (01) second.
+ ***************************************************************************/
+ private void OpenConnection(String url) {
+ int retrys = 0;
+ StopWatch watch = new StopWatch();
+ watch.start();
+ while (null == connection) {
+ try {
+ connection =(S7HPlcConnection) new DefaultPlcDriverManager().
+ getConnection(url);
+ connection.addEventListener(this);
+ while (!connection.isConnected());
+ watch.stop();
+
+ isConnected.set( connection.isConnected());
+
+ logger.info("Time elapse for connection: {} in ms, with " +
+ "rettrys: {}",watch.getTime(), retrys);
+
+ } catch (PlcConnectionException ex) {
+ logger.info(ex.getMessage());
+ retrys++;
+ }
+ }
+ }
+
+ /***************************************************************************
+ * When the connection is closed, pending tasks and transactions are
+ * completed.
+ * The rest of the work should be sent to the GC.
+ ***************************************************************************/
+ private void CloseConnection() {
+ if (null == connection) return;
+ isConnected.set(false);
+ try {
+ connection.close();
+ connection = null; //GC do you job!.
+
+ } catch (PlcConnectionException ex) {
+ logger.info("CloseConnection: " + ex.getMessage());
+ }
+ }
+
+ /***************************************************************************
+ * This method is called when there is a physical disconnection of the driver
+ * Check the monitoring parameters given in the URL during connection.
+ ***************************************************************************/
+ public void MakeSubscription() throws Exception {
+ Thread th01 = null;
+
+ for (int i=1; i<=1; i++) {
+
+ th01 = dtf.newThread(new SubscriptionRunnable(connection, i));
+
+ th01.start();
+
+ }
+
}
+ /***************************************************************************
+ * Depending on your design, you must close all subscribers
+ * in an orderly manner.
+ ***************************************************************************/
+ public void MakeUnsubscription() throws Exception {
+ logger.info("Finish all subscriptions.");
+ ShutDown.set(true);
+ }
+
+ /***************************************************************************
+ * This method is called when the driver makes an internal TCP connection.
+ * The first connection of the driver does not generate this event.
+ * In the case of high availability systems, this signal should be used
+ * to restart subscriptions to events, alarms, etc.
+ ***************************************************************************/
@Override
public void connected() {
- System.out.println("*************** CONECTADO *****************");
+ logger.info("*****************************************************");
+ logger.info("*************** Plc is connected. *******************");
+ logger.info("*****************************************************");
+ isConnected.set(true);
}
+ /***************************************************************************
+ * This method is called when there is a physical disconnection of the driver
+ * Check the monitoring parameters given in the URL during connection.
+ ***************************************************************************/
@Override
public void disconnected() {
- System.out.println("*************** DESCONECTADO *****************");
- subscricted = false;
- }
-
+ logger.info("*****************************************************");
+ logger.info("*************** Plc is disconnected. ****************");
+ logger.info("*****************************************************");
+ isConnected.set(false);
+ }
- public void makeunsubscription() throws Exception {
- System.out.println("*************** ELIMINANDO SUSCRIPCION *****************");
- final PlcUnsubscriptionRequest.Builder unsubscription = connection.unsubscriptionRequestBuilder();
-
- unsubscription.addHandles(subresponse.getSubscriptionHandle("myCYC_01"));
-
- final PlcUnsubscriptionRequest res = unsubscription.build();
-
- res.execute().get();
+ /***************************************************************************
+ * This object encapsulates the three steps required for cyclic subscription.
+ * Try to handle all possible exceptions that are generated.
+ ***************************************************************************/
+ private class SubscriptionRunnable implements Runnable {
+ private final Logger logger = LoggerFactory.getLogger(SubscriptionRunnable.class);
- }
+ private final S7HPlcConnection myconnection;
+ private final int instance;
+ private PlcSubscriptionRequest.Builder subscription;
+ private PlcSubscriptionRequest sub;
+ private PlcSubscriptionResponse subresponse;
- public void run (String[] args) throws Exception {
- try {
-
- makeconnection();
-
- System.out.println("Waiting for events");
-
- DefaultThreadFactory tf = new
- DefaultThreadFactory("CYC", true);
+ public SubscriptionRunnable(S7HPlcConnection connection, int instance) {
+ this.myconnection = connection;
+ this.instance = instance;
+ }
- Thread th01 = tf.newThread(() -> {
-
- while(!shutdown){
- try {
-
- if ((connection.isConnected() == true) && (subscricted == false)) {
- System.out.println("REALIZO LA SUSCRIPCION..." + connection.isConnected() + " : " + subscricted);
- makesubscription();
- subscricted = true;
- } else if (connection.isConnected() == false) {
- subscricted = false;
- }
- Thread.sleep(1000);
- } catch (Exception ex){
- System.out.println("Algo fallo aqui..." + ex.getMessage());
- subscricted = false;
- }
- }
- }
- );
+ @Override
+ public void run() {
- th01.start();
+ MakeMySubscription();
- System.in.read();
- shutdown = true;
+ MakeMyRegister();
- System.out.println("Bye...");
+ while (!ShutDown.get()) {
+ try {
+ Thread.sleep(100);
+ } catch (Exception ex) {
+ logger.debug(ex.getMessage());
+ }
+ } ;
- makeunsubscription();
-
- Thread.sleep(2000);
+ MakeMyUnsubscription();
- connection.close();
+ logger.info("Bye!");
+ }
+
+ /***********************************************************************
+ * Registration of the different memory areas.
+ * Only the first request sets the time period for the entire group.
+ * The time bases are for the multiplier:
+ *
+ * . B01SEC: Time base 0.1 Sec. (100 mSec.).
+ * . B1SEC: Time base 1.0 Sec.
+ * . B10SEC: Time base 10 Sec.
+ ***********************************************************************/
+ private void MakeMySubscription() {
+ subscription = myconnection.subscriptionRequestBuilder();
+ subscription.addEventTagAddress(instance + "_myCYC_01", "CYC(B1SEC:5):%MB190:BYTE");
+ subscription.addEventTagAddress(instance + "_myCYC_02", "CYC(B1SEC:5):%MW190:INT");
-
- } catch (Exception ex) {
- System.out.println("Finaliza la ejecución...");
- ex.printStackTrace();
- };
- }
+ sub = subscription.build();
+
+ try {
+ subresponse = sub.execute().get();
+ } catch (InterruptedException ex) {
+ logger.info(ex.getMessage());
+ } catch (ExecutionException ex) {
+ logger.info(ex.getMessage());
+ }
+ }
+
+ /***********************************************************************
+ * This object encapsulates the three steps required for cyclic subscription.
+ * Try to handle all possible exceptions that are generated.
+ ***********************************************************************/
+ private void MakeMyRegister() {
+
+ subresponse
+ .getSubscriptionHandle(instance + "_myCYC_01")
+ .register(msg -> {
+ if (null == msg) return
+ ;
+ logger.info("******** {} CYC Event *********", instance);
+ Map<String, Object> map = ((S7CyclicEvent) msg).getMap();
+ map.forEach((x, y) -> {
+ if (x.startsWith("DATA_", 0)) {
+ logger.info("Longitud de datos: " + ((byte[]) y).length);
+ logger.info(x + ": " + Hex.encodeHexString((byte[]) y));
+ } else
+ logger.info(x + " : " + y);
+ });
+ logger.info("****************************");
+ });;
+ }
+
+ /***********************************************************************
+ * This object encapsulates the three steps required for cyclic subscription.
+ * Try to handle all possible exceptions that are generated.
+ ***********************************************************************/
+ private void MakeMyUnsubscription(){
+ final PlcUnsubscriptionRequest.Builder unsubscription = myconnection.unsubscriptionRequestBuilder();
+
+ unsubscription.addHandles(subresponse.getSubscriptionHandle(instance + "_myCYC_01"));
+
+ final PlcUnsubscriptionRequest res = unsubscription.build();
+
+ try {
+ res.execute().get();
+ } catch (InterruptedException ex) {
+ logger.info(ex.getMessage());
+ } catch (ExecutionException ex) {
+ logger.info(ex.getMessage());
+ }
+ }
+
+ }
+
-
}
diff --git a/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/PlcReadDataS7400H.java b/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/PlcReadDataS7400H.java
index fa7622c818..49cf838d0e 100644
--- a/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/PlcReadDataS7400H.java
+++ b/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/PlcReadDataS7400H.java
@@ -45,7 +45,7 @@ import org.slf4j.LoggerFactory;
*/
public class PlcReadDataS7400H implements ConnectionStateListener {
- private static final Logger logger = LoggerFactory.getLogger(PlcReadS71200.class);
+ private static final Logger logger = LoggerFactory.getLogger(PlcReadDataS7400H.class);
private S7HPlcConnection connection = null;
private AtomicBoolean isConnected = new AtomicBoolean(false);
@@ -54,6 +54,8 @@ public class PlcReadDataS7400H implements ConnectionStateListener {
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
+ System.setProperty(org.slf4j.simple.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "Debug");
+
PlcReadDataS7400H device = new PlcReadDataS7400H();
device.run();
}
diff --git a/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/PlcReadS71200.java b/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/PlcReadS71200.java
index b0ff943244..7a0ac295bf 100644
--- a/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/PlcReadS71200.java
+++ b/plc4j/examples/plc4j-s7event/src/main/java/org/apache/plc4x/examples/plc4j/s7event/PlcReadS71200.java
@@ -53,7 +53,8 @@ public class PlcReadS71200 implements ConnectionStateListener {
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception{
- // TODO code application logic here
+ System.setProperty(org.slf4j.simple.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "Debug");
+
PlcReadS71200 device = new PlcReadS71200();
device.run();
}
@@ -193,7 +194,6 @@ public class PlcReadS71200 implements ConnectionStateListener {
}
-
/***************************************************************************
* When the connection is closed, pending tasks and transactions are
* completed.
@@ -237,7 +237,10 @@ public class PlcReadS71200 implements ConnectionStateListener {
}
/***************************************************************************
- *
+ * This method is called when the driver makes an internal TCP connection.
+ * The first connection of the driver does not generate this event.
+ * In the case of high availability systems, this signal should be used
+ * to restart subscriptions to events, alarms, etc.
***************************************************************************/
@Override
public void connected() {
@@ -248,7 +251,8 @@ public class PlcReadS71200 implements ConnectionStateListener {
}
/***************************************************************************
- *
+ * This method is called when there is a physical disconnection of the driver
+ * Check the monitoring parameters given in the URL during connection.
***************************************************************************/
@Override
public void disconnected() {