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 2022/11/22 09:26:46 UTC

[plc4x] branch develop updated: docs(api): Started adding an alternate documentation for the SNAPSHOT version of the API

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/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new 2b687e933d docs(api): Started adding an alternate documentation for the SNAPSHOT version of the API
2b687e933d is described below

commit 2b687e933d69fbc0cdcf06d6e431ab0c850f376c
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Nov 22 10:26:36 2022 +0100

    docs(api): Started adding an alternate documentation for the SNAPSHOT version of the API
---
 .../users/getting-started/general-concepts.adoc    |  2 +-
 .../asciidoc/users/getting-started/plc4go.adoc     | 51 ++++++++++++-
 src/site/asciidoc/users/getting-started/plc4j.adoc | 85 +++++++++++++++++++++-
 .../users/getting-started/virtual-modbus.adoc      | 43 ++++++++---
 4 files changed, 164 insertions(+), 17 deletions(-)

diff --git a/src/site/asciidoc/users/getting-started/general-concepts.adoc b/src/site/asciidoc/users/getting-started/general-concepts.adoc
index 089b1fb4ab..cc81b77d88 100644
--- a/src/site/asciidoc/users/getting-started/general-concepts.adoc
+++ b/src/site/asciidoc/users/getting-started/general-concepts.adoc
@@ -100,7 +100,7 @@ Then this shorter version can be used. Please inspect the `Protocol Documentatio
 
 === Individual Resource Addresses
 
-Addresses for individual fields on a PLC are extremely dependent on the used protocol.
+Addresses for individual tags on a PLC are extremely dependent on the used protocol.
 As we usually decided to stick to the address formats that are used in those particular environments.
 
 Please check the `Protocol Documentation` on details about these address formats.
diff --git a/src/site/asciidoc/users/getting-started/plc4go.adoc b/src/site/asciidoc/users/getting-started/plc4go.adoc
index f820740279..13fc23da01 100644
--- a/src/site/asciidoc/users/getting-started/plc4go.adoc
+++ b/src/site/asciidoc/users/getting-started/plc4go.adoc
@@ -160,6 +160,7 @@ First off all, it's probably a good idea to check if this connection supports re
 
 In order to create and run such a `PlcReadRequest`, please add the following code:
 
+.Up to version 0.10.0
 ----
 	// Prepare a read-request
 	readRequest, err := connection.ReadRequestBuilder().
@@ -173,6 +174,20 @@ In order to create and run such a `PlcReadRequest`, please add the following cod
 	}
 ----
 
+.SNAPSHOT version
+----
+	// Prepare a read-request
+	readRequest, err := connection.ReadRequestBuilder().
+		AddTagAddress("tag1", "holding-register:1:REAL").
+		AddTagAddress("tag2", "holding-register:3:REAL").
+        Build()
+	if err != nil {
+		t.Errorf("error preparing read-request: %s", connectionResult.Err.Error())
+		t.Fail()
+		return
+	}
+----
+
 If you have any errors in the addresses or whatever, you will get an `err` instead of a `readRequest`.
 
 For now, let's assume you got all addresses correctly.
@@ -227,7 +242,7 @@ We first have to check if the connection supports this:
 
 Now we'll create the subscription request.
 
-The main difference is that while reading there is only one form how you could read, with subscriptions there are different forms of subscriptons:
+The main difference is that while reading there is only one form how you could read, with subscriptions there are different forms of subscriptions:
 
 - Change of state (Event is sent as soon as a value changes)
 - Cyclic (The Event is sent in regular cyclic intervals)
@@ -235,6 +250,7 @@ The main difference is that while reading there is only one form how you could r
 
 Therefore instead of using a normal `AddItem`, there are tree different functions as you can see in the following examples.
 
+.Up to version 0.10.0
 ----
 	// Prepare a subscription-request
     subscriptionRequest, err := connection.SubscriptionRequestBuilder().
@@ -249,8 +265,24 @@ Therefore instead of using a normal `AddItem`, there are tree different function
     }
 ----
 
+.SNAPSHOT version
+----
+	// Prepare a subscription-request
+    subscriptionRequest, err := connection.SubscriptionRequestBuilder().
+        AddChangeOfStateTagAddress("heating-actual-temperature", "*/*/10:DPT_Value_Temp").
+        AddChangeOfStateTagAddress("heating-target-temperature", "*/*/11:DPT_Value_Temp").
+        AddCyclicTagAddress("heating-valve-open", "*/*/12:DPT_OpenClose", 500 * time.Millisecond).
+        AddItemHandler(knxEventHandler).
+        Build()
+    if err != nil {
+	    fmt.Printf("Error preparing subscription-request: %s", connectionResult.Err.Error())
+        return
+    }
+----
+
 The `Event hadnler` for intercepting incoming events could look like this:
 
+.Up to version 0.10.0
 ----
 func knxEventHandler(event apiModel.PlcSubscriptionEvent) {
     for _, fieldName := range event.GetFieldNames() {
@@ -263,9 +295,22 @@ func knxEventHandler(event apiModel.PlcSubscriptionEvent) {
 }
 ----
 
-NOTE: The `AddCyclicField` method requires a third parameter `duration` which specifies the interval, in which a given value is sent (even if it has not changed).
+.SNAPSHOT version
+----
+func knxEventHandler(event apiModel.PlcSubscriptionEvent) {
+    for _, tagName := range event.GetTagNames() {
+        if event.GetResponseCode(tagName) == apiModel.PlcResponseCode_OK {
+            groupAddress := event.GetTag(tagName).GetAddressString()
+            fmt.Printf("Got update for tag %s with address %s. Value changed to: %s\n",
+                tagName, groupAddress, event.GetValue(tagName).GetString())
+        }
+    }
+}
+----
+
+NOTE: The `AddCyclicField`/`AddCyclicTagAddress` method requires a third parameter `duration` which specifies the interval, in which a given value is sent (even if it has not changed).
 
-NOTE: Here the API differs slightly form the Java version, as in the request-builder itself you specify the reference to the callback handler which should be notified on incoming data. Howerver, we will be alliging all API variants as much as possible in the near future.
+NOTE: Here the API differs slightly form the Java version, as in the request-builder itself you specify the reference to the callback handler which should be notified on incoming data. However, we will be aligning all API variants as much as possible in the near future.
 
 The request itself is executed exactly the same way the read and write operations are executed, using the `Execute` function.
 
diff --git a/src/site/asciidoc/users/getting-started/plc4j.adoc b/src/site/asciidoc/users/getting-started/plc4j.adoc
index 84d63fad58..6cc6d776f7 100644
--- a/src/site/asciidoc/users/getting-started/plc4j.adoc
+++ b/src/site/asciidoc/users/getting-started/plc4j.adoc
@@ -121,7 +121,7 @@ asyncResponse.whenComplete((response, throwable) -> {
 In general all requests are executed asynchronously.
 So as soon as the request is fully processed, the callback gets called and will contain a `readResponse`, if everything went right or a `throwable` if there were problems.
 
-However if you want to write your code in a more synchronous fashion, the following alternative will provide this:
+However, if you want to write your code in a more synchronous fashion, the following alternative will provide this:
 
 ----
 PlcReadResponse response = readRequest.execute().get(5000, TimeUnit.MILLISECONDS);
@@ -130,6 +130,7 @@ PlcReadResponse response = readRequest.execute().get(5000, TimeUnit.MILLISECONDS
 Processing of the responses is identical in both cases.
 The following example will demonstrate some of the options you have:
 
+.Up to version 0.10.0
 ----
 for (String fieldName : response.getFieldNames()) {
     if(response.getResponseCode(fieldName) == PlcResponseCode.OK) {
@@ -153,6 +154,30 @@ for (String fieldName : response.getFieldNames()) {
 }
 ----
 
+.SNAPSHOT version
+----
+for (String tagName : response.getTagNames()) {
+    if(response.getResponseCode(tagName) == PlcResponseCode.OK) {
+        int numValues = response.getNumberOfValues(tagName);
+        // If it's just one element, output just one single line.
+        if(numValues == 1) {
+            logger.info("Value[" + tagName + "]: " + response.getObject(tagName));
+        }
+        // If it's more than one element, output each in a single row.
+        else {
+            logger.info("Value[" + tagName + "]:");
+            for(int i = 0; i < numValues; i++) {
+                logger.info(" - " + response.getObject(tagName, i));
+            }
+        }
+    }
+    // Something went wrong, to output an error message instead.
+    else {
+        logger.error("Error[" + tagName + "]: " + response.getResponseCode(tagName).name());
+    }
+}
+----
+
 In the for loop, we are demonstrating how the user can iterate over the address aliases in the response.
 In case of an ordinary read request, this will be predefined by the items in the request, however in case of a subscription response, the response might only contain some of the items that were subscribed.
 
@@ -179,7 +204,7 @@ If you want to access a given element number, please use the two-argument versio
     response.getObject(fieldName, 42)
 
 PLC4X provides getters and setters for a wide variety of Java types and automatically handles the type conversion.
-However when for example trying to get a long-value as a byte and the long-value exceeds the range supported by the smaller type, a `RuntimeException` of type `PlcIncompatibleDatatypeException`.
+However, when for example trying to get a long-value as a byte and the long-value exceeds the range supported by the smaller type, a `RuntimeException` of type `PlcIncompatibleDatatypeException`.
 In order to avoid causing this exception to be thrown, however there are `isValid{TypeName}` methods that you can use to check if the value is compatible.
 
 ==== Writing Data
@@ -198,6 +223,7 @@ if (!plcConnection.getMetadata().canWrite()) {
 
 As soon as we are sure that we can write, we create a new `PlcWriteRequest.Builder`:
 
+.Up to version 0.10.0
 ----
 // Create a new write request:
 // - Give the single item requested an alias name
@@ -209,6 +235,18 @@ builder.addItem("value-4", "%DB.DB1.4:INT[3]", 7, 23, 42);
 PlcWriteRequest writeRequest = builder.build();
 ----
 
+.SNAPSHOT version
+----
+// Create a new write request:
+// - Give the single item requested an alias name
+// - Pass in the data you want to write (for arrays, pass in one value for every element)
+PlcWriteRequest.Builder builder = plcConnection.writeRequestBuilder();
+builder.addTagAddress("value-1", "%Q0.4:BOOL", true);
+builder.addTagAddress("value-2", "%Q0:BYTE", (byte) 0xFF);
+builder.addTagAddress("value-4", "%DB.DB1.4:INT[3]", 7, 23, 42);
+PlcWriteRequest writeRequest = builder.build();
+----
+
 The same way read requests are sent to the PLC by issuing the `execute` method on the request object:
 
 ----
@@ -226,6 +264,7 @@ PlcWriteResponse response = writeRequest.execute().get();
 
 As we don't have to process the data itself, for the write request, it's enough to simply check the return code for each field.
 
+.Up to version 0.10.0
 ----
 for (String fieldName : response.getFieldNames()) {
     if(response.getResponseCode(fieldName) == PlcResponseCode.OK) {
@@ -238,6 +277,19 @@ for (String fieldName : response.getFieldNames()) {
 }
 ----
 
+.SNAPSHOT version
+----
+for (String tagName : response.getTagNames()) {
+    if(response.getResponseCode(tagName) == PlcResponseCode.OK) {
+        logger.info("Value[" + tagName + "]: updated");
+    }
+    // Something went wrong, to output an error message instead.
+    else {
+        logger.error("Error[" + tagName + "]: " + response.getResponseCode(tagName).name());
+    }
+}
+----
+
 ==== Subscribing to Data
 
 Subscribing to data can be considered similar to reading data, at least the subscription itself if very similar to reading of data.
@@ -254,7 +306,7 @@ if (!plcConnection.getMetadata().canSubscribe()) {
 
 Now we'll create the subscription request.
 
-The main difference is that while reading there is only one form how you could read, with subscriptions there are different forms of subscriptons:
+The main difference is that while reading there is only one form how you could read, with subscriptions there are different forms of subscriptions:
 
 - Change of state (Event is sent as soon as a value changes)
 - Cyclic (The Event is sent in regular cyclic intervals)
@@ -262,6 +314,7 @@ The main difference is that while reading there is only one form how you could r
 
 Therefore instead of using a normal `addItem`, there are tree different methods as you can see in the following examples.
 
+.Up to version 0.10.0
 ----
 // Create a new subscription request:
 // - Give the single item requested an alias name
@@ -272,7 +325,18 @@ builder.addEventField("value-3", "{some alarm address}");
 PlcSubscriptionRequest subscriptionRequest = builder.build();
 ----
 
-NOTE: The `addCyclicField` method requires a third parameter `duration`.
+.SNAPSHOT version
+----
+// Create a new subscription request:
+// - Give the single tag requested an alias name
+PlcSubscriptionRequest.Builder builder = plcConnection.subscriptionRequestBuilder();
+builder.addChangeOfStateTagAddress("value-1", "{some address}");
+builder.addCyclicTagAddress("value-2", "{some address}", Duration.ofMillis(1000));
+builder.addEventTagAddress("value-3", "{some alarm address}");
+PlcSubscriptionRequest subscriptionRequest = builder.build();
+----
+
+NOTE: The `addCyclicField`/`addCyclicTagAddress` method requires a third parameter `duration`.
 
 The request itself is executed exactly the same way the read and write operations are executed, using the `execute` method, therefore just the short synchronous version here (The async version works just as good)
 
@@ -284,6 +348,7 @@ Now comes the little more tricky part, as subscriptions are always asynchronous,
 
 In general you can't say how many of your subscribed fields will be available in every callback so it is double important to check or iterate over the field names.
 
+.Up to version 0.10.0
 ----
 for (String subscriptionName : response.getFieldNames()) {
     final PlcSubscriptionHandle subscriptionHandle = response.getSubscriptionHandle(subscriptionName);
@@ -295,4 +360,16 @@ for (String subscriptionName : response.getFieldNames()) {
 }
 ----
 
+.SNAPSHOT version
+----
+for (String subscriptionName : response.getFieldNames()) {
+    final PlcSubscriptionHandle subscriptionHandle = response.getSubscriptionHandle(subscriptionName);
+    subscriptionHandle.register(plcSubscriptionEvent -> {
+        for (String tagName : plcSubscriptionEvent.getTagNames()) {
+            System.out.println(plcSubscriptionEvent.getPlcValue(tagName));
+        }
+    });
+}
+----
+
 NOTE: Here there currently is a double iteration over the field names, this will probably change soon.
\ No newline at end of file
diff --git a/src/site/asciidoc/users/getting-started/virtual-modbus.adoc b/src/site/asciidoc/users/getting-started/virtual-modbus.adoc
index a239b3c7aa..26ec3a88be 100644
--- a/src/site/asciidoc/users/getting-started/virtual-modbus.adoc
+++ b/src/site/asciidoc/users/getting-started/virtual-modbus.adoc
@@ -94,7 +94,7 @@ In general Modbus only knows two types of data: `Coils` and `Registers`.
 
 Coils are always simple `bits` or `boolean` values and Registers are always `16 bit short values`.
 
-However there are different types of these and they have different names:
+However, there are different types of these and they have different names:
 
 - `Discrete Inputs` (Boolean values) (read-only)
 - `Coils` (Boolean values) (read-write)
@@ -135,7 +135,7 @@ For Modbus the typical transports are:
 * tcp (transport-config is the ip or host-name of the slave and can be suffixed by a port separated from the ip/host with `:`)
 * serial (transport-config is the device name of the serial interface)
 
-If we have setup ModbusPal as described above and are running this on the same computer, the connection string to connect to this should be:
+If we have set up ModbusPal as described above and are running this on the same computer, the connection string to connect to this should be:
 
     modbus-tcp://localhost
 
@@ -160,7 +160,7 @@ When using Maven, all you need to do is add this dependency:
 ----
 
 This will allow you to write a valid application, that compiles fine.
-However in order to actually connect to a device using a given protocol, you need to add this protocol implementation to the classpath.
+However, in order to actually connect to a device using a given protocol, you need to add this protocol implementation to the classpath.
 
 For example in order to communicate using the `Modbus` protocol, you would need to add the following dependency:
 
@@ -199,15 +199,15 @@ The basic functions supported by PLCs and therefore supported by PLC4X are:
 * Execute functions in the PLC
 * List resources in the PLC
 
-In general we will try to offer as many features as possible.
-So if a protocol doesn't support subscription based communication it is our goal to simulate this by polling in the background so it is transparent for the users.
+In general, we will try to offer as many features as possible.
+So if a protocol doesn't support subscription based communication it is our goal to simulate this by polling in the background, so it is transparent for the users.
 
 But there are some cases in which we can't simulate or features are simply disabled intentionally:
 
 * If a PLC and/or protocol don't support executing of functions, we simply can't provide this functionality.
 * We will be providing stripped down versions of drivers, that for example intentionally don't support any writing of data and executing of functions.
 
-Therefore we use metadata to check programmatically, if a given feature is available:
+Therefore, we use metadata to check programmatically, if a given feature is available:
 
 === Reading Data
 
@@ -251,7 +251,7 @@ asyncResponse.whenComplete((response, throwable) -> {
 In general all requests are executed asynchronously.
 So as soon as the request is fully processed, the callback gets called and will contain a `readResponse`, if everything went right or a `throwable` if there were problems.
 
-However if you want to write your code in a more synchronous fashion, the following alternative will provide this:
+However, if you want to write your code in a more synchronous fashion, the following alternative will provide this:
 
 ----
 PlcReadResponse response = readRequest.execute().get();
@@ -260,6 +260,7 @@ PlcReadResponse response = readRequest.execute().get();
 Processing of the responses is identical in both cases.
 The following example will demonstrate some of the options you have:
 
+.Up to version 0.10.0
 ----
 for (String fieldName : response.getFieldNames()) {
     if(response.getResponseCode(fieldName) == PlcResponseCode.OK) {
@@ -283,6 +284,30 @@ for (String fieldName : response.getFieldNames()) {
 }
 ----
 
+.SNAPSHOT version
+----
+for (String tagName : response.getTagNames()) {
+    if(response.getResponseCode(tagName) == PlcResponseCode.OK) {
+        int numValues = response.getNumberOfValues(tagName);
+        // If it's just one element, output just one single line.
+        if(numValues == 1) {
+            logger.info("Value[" + tagName + "]: " + response.getObject(tagName));
+        }
+        // If it's more than one element, output each in a single row.
+        else {
+            logger.info("Value[" + tagName + "]:");
+            for(int i = 0; i < numValues; i++) {
+                logger.info(" - " + response.getObject(tagName, i));
+            }
+        }
+    }
+    // Something went wrong, to output an error message instead.
+    else {
+        logger.error("Error[" + tagName + "]: " + response.getResponseCode(tagName).name());
+    }
+}
+----
+
 In the for loop, we are demonstrating how the user can iterate over the address aliases in the response.
 In case of an ordinary read request, this will be predefined by the items in the request, however in case of a subscription response, the response might only contain some of the items that were subscribed.
 
@@ -309,14 +334,14 @@ If you want to access a given element number, please use the two-argument versio
     response.getObject(fieldName, 42)
 
 PLC4X provides getters and setters for a wide variety of Java types and automatically handles the type conversion.
-However when for example trying to get a long-value as a byte and the long-value exceeds the range supported by the smaller type, a `RuntimeException` of type `PlcIncompatibleDatatypeException`.
+However, when for example trying to get a long-value as a byte and the long-value exceeds the range supported by the smaller type, a `RuntimeException` of type `PlcIncompatibleDatatypeException`.
 In order to avoid causing this exception to be thrown, however there are `isValid{TypeName}` methods that you can use to check if the value is compatible.
 
 === Writing Data
 
 The code for writing is very similar to the code for reading, however when creating the write request, we have to pass in the data alongside the field definitions.
 
-While all of the 4 field types support reading from, only the `coil` and `holding-register` field types support writing to.
+While all 4 field types support reading from, only the `coil` and `holding-register` field types support writing to.
 If you attempt to write to these, this will result in errors.
 
 So again, we first check if this driver supports writing (Some drivers such as passive-mode drivers or read-only versions might generally not support writing):