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

git-site-role pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/plc4x-website.git


The following commit(s) were added to refs/heads/asf-site by this push:
     new 754df6014 Site checkin for project PLC4X: Jenkins Tools
754df6014 is described below

commit 754df6014e0a13422e7ef972a6365889d8156100
Author: jenkins <[email protected]>
AuthorDate: Mon Mar 4 05:26:42 2024 +0000

    Site checkin for project PLC4X: Jenkins Tools
---
 users/getting-started/plc4py.html | 251 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 251 insertions(+)

diff --git a/users/getting-started/plc4py.html 
b/users/getting-started/plc4py.html
index 50aeda708..938134b76 100644
--- a/users/getting-started/plc4py.html
+++ b/users/getting-started/plc4py.html
@@ -322,7 +322,258 @@
             <div class="sect1">
 <h2 id="getting_started_with_python">Getting Started with Python</h2>
 <div class="sectionbody">
+<div class="sect2">
+<h3 id="using_the_plc4py_api_directly">Using the PLC4PY API directly</h3>
+<div class="paragraph">
+<p>Currently, you need to install PLC4Py from the GitHub repository instead of 
pypi.
+Once we have decided that PLC4Py is in a position to release we will publish 
to pypi.</p>
+</div>
+<div class="paragraph">
+<p>Navigate to the sandbox/plc4py directory and run. This will install plc4py 
in your global repository.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>   pip install .</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>You now should be able to use PLC4Py in your application. A minimal example 
is shown below.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>from plc4py.PlcDriverManager import PlcDriverManager
+
+connection_string: = "modbus://192.168.1.174:502";
+
+driver_manager = PlcDriverManager()
+async with driver_manager.connection(connection_string) as connection:
+    with connection.read_request_builder() as builder:
+        builder.add_item("Random Tag", "4x00001[10]")
+        request = builder.build()
 
+    future = connection.execute(request)
+    await future
+    response = future.result()</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>PLC4X generally supports a very limited set of functions, which is not due 
to the fact, that we didn&#8217;t implement things, but that PLCs generally 
support a very limited set of functions.</p>
+</div>
+<div class="paragraph">
+<p>The basic functions supported by PLCs and therefore supported by PLC4X 
are:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>Discover Devices (Not yet available for PLC4Py)</p>
+</li>
+<li>
+<p>List resources in the PLC</p>
+</li>
+<li>
+<p>Read data</p>
+</li>
+<li>
+<p>Write data (Not yet available for PLC4Py)</p>
+</li>
+<li>
+<p>Subscribe for data (Not yet available for PLC4Py)</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>In general, we will try to offer as many features as possible.
+So if a protocol doesn&#8217;t support subscription based communication it is 
our goal to simulate this by polling in the background, so it is transparent 
for the users (This simulation feature hasn&#8217;t been implemented yet 
though, but it&#8217;s on our roadmap).</p>
+</div>
+<div class="paragraph">
+<p>But there are some cases in which we can&#8217;t simulate or features are 
simply disabled intentionally:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>If a PLC and/or protocol don&#8217;t support writing or browsing, we simply 
can&#8217;t provide this functionality.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Therefore, we use metadata to check programmatically, if a given feature is 
available.</p>
+</div>
+<div class="sect3">
+<h4 id="reading_data">Reading Data</h4>
+<div class="listingblock">
+<div class="content">
+<pre># Check if this connection support reading of data.
+if connection.is_read_supported():
+    logger.error("This connection doesn't support reading.")</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>As soon as you have ensured that a feature is available, you are ready to 
build a first request.
+This is done by getting a <code>ReadRequestBuilder</code>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre># Create a new read request:
+# - Give the single item requested an alias name
+with connection.read_request_builder() as builder:
+    builder.add_item("Random Tag 1", "4x00001[10]")
+    builder.add_item("Random Tag 2", "4x00011")
+    request = builder.build()</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>So, as you can see, you prepare a request, by adding tag addresses to the 
request and in the end by calling the <code>build</code> method.</p>
+</div>
+<div class="paragraph">
+<p>If you are using the <code>BrowseApi</code> you might also have been 
provided with <code>Tag</code> objects. In that case simply use 
<code>addTag</code> and pass in the <code>Tag</code> object instead of the 
address string.</p>
+</div>
+<div class="paragraph">
+<p>The request is sent to the PLC by issuing the <code>execute</code> method 
on the request object:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>try:
+    future = connection.execute(request)
+    await future
+    response = future.result()
+except TimeOutException:
+    # Handle timeout error
+except ...
+    # Handle all your other errors</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>In general, all requests are executed asynchronously.
+As soon as the request is fully processed, the callback gets called and will 
contain a <code>ReadResponse</code>, if everything went right or an excception  
if there were problems.</p>
+</div>
+<div class="paragraph">
+<p>The following example will demonstrate some of the options you have:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>for tag_name in response.tag_names:
+    if response.tags[tag_name].response_code == PlcResponseCode.OK:
+        num_values: int = len(response.tags[tag_name].value)
+        # If it's just one element, output just one single line.
+        if num_values == 1:
+            logger.info("Value[" + tag_name + "]: " + 
response.tags[tag_name].value)
+        else:
+            # If it's more than one element, output each in a single row.
+            logger.info("Value[" + tag_name + "]:")
+            for i in response.tags[tag_name].value.get_list():
+                logger.info(" - " + str(i))
+    else:
+        # Something went wrong, to output an error message instead.
+        logger.error("Error[" + tag_name + "]: " + 
response.tags[tag_name].name())</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>In the for-loop, we are demonstrating how the user can iterate over the tag 
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.</p>
+</div>
+<div class="paragraph">
+<p>Before accessing the data, it is advisable to check if an item was 
correctly returned.
+This is done by the <code>response_code</code> property for a given alias.
+If this is <code>PlcResponseCode.OK</code>, everything is ok, however it could 
be one of the following:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>NOT_FOUND</p>
+</li>
+<li>
+<p>ACCESS_DENIED</p>
+</li>
+<li>
+<p>INVALID_ADDRESS</p>
+</li>
+<li>
+<p>INVALID_DATATYPE</p>
+</li>
+<li>
+<p>INTERNAL_ERROR</p>
+</li>
+<li>
+<p>RESPONSE_PENDING</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Assuming the return code was <code>OK</code>, we can continue accessing the 
data.</p>
+</div>
+<div class="paragraph">
+<p>As all PlcValue items support the len property, the user can check how many 
items of a given type are returned by calling 
len(response.tags[tag_name].value)</p>
+</div>
+<div class="paragraph">
+<p>You can then treat the values in the PlcList as a list using 
response.tags[tag_name].value.get_list()</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="writing_data">Writing Data</h4>
+<div class="paragraph">
+<p>In general the structure of code for writing data is extremely similar to 
that of reading data.</p>
+</div>
+<div class="paragraph">
+<p>So first it is advisable to check if this connection is even able to write 
data:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>// Check if this connection support writing of data.
+if not plc_connection.is_write_supported():
+  logger.error("This connection doesn't support writing.")
+  return</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>As soon as we are sure that we can write, we create a new 
<code>PlcWriteRequest.Builder</code>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>// 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 a list of values)
+with connection.write_request_builder() as builder:
+    builder.add_item("Random Tag 1", "4x00001[2]", [1, 2])
+    builder.add_item("Random Tag 2", "4x00011", 1)
+    request = builder.build()</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The same way read requests are sent to the PLC by issuing the 
<code>execute</code> method on the request object:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>try:
+    future = connection.execute(request)
+    await future
+    response = future.result()
+except TimeOutException:
+    # Handle timeout error
+except ...
+    # Handle all your other errors</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>As we don&#8217;t have to process the data itself, for the write request, 
it&#8217;s enough to simply check the return code for each field.</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>for tag_name in response.tag_names:
+    if response.tags[tag_name].response_code == PlcResponseCode.OK:
+        logger.info("Value[" + tag_name + "]: updated");
+    else:
+        # Something went wrong, to output an error message instead.
+        logger.error("Error[" + tag_name + "]: " + 
response.tags[tag_name].name())</pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="subscribing_to_data">Subscribing to Data</h4>
+<div class="paragraph">
+<p>Coming Soon</p>
+</div>
+</div>
+</div>
 </div>
 </div>
         </main>

Reply via email to