[Project] Added initial PLC documentation
This commit is contained in:
parent
ce8402117c
commit
049d68fd37
|
@ -44,5 +44,6 @@ blockquote {
|
||||||
.image {
|
.image {
|
||||||
display: block;
|
display: block;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto
|
margin-right: auto;
|
||||||
|
margin-bottom: 10px;
|
||||||
}
|
}
|
|
@ -83,13 +83,13 @@ mvn clean install -DskipTests</pre>
|
||||||
<p>The following shows the maven command to create the new maven project. Note that you should replace the
|
<p>The following shows the maven command to create the new maven project. Note that you should replace the
|
||||||
placeholders in the brackets:</p>
|
placeholders in the brackets:</p>
|
||||||
<pre>
|
<pre>
|
||||||
mvn archetype:generate
|
mvn archetype:generate \
|
||||||
-DarchetypeGroupId=li.strolch
|
-DarchetypeGroupId=li.strolch \
|
||||||
-DarchetypeArtifactId=li.strolch.mvn.archetype.main
|
-DarchetypeArtifactId=li.strolch.mvn.archetype.main \
|
||||||
-DarchetypeVersion=1.6.0-SNAPSHOT
|
-DarchetypeVersion=1.6.0-SNAPSHOT \
|
||||||
-DgroupId=<my.groupid>
|
-DgroupId=<my.groupid> \
|
||||||
-DartifactId=<my-artifactId>
|
-DartifactId=<my-artifactId> \
|
||||||
-Dversion=<my.version>
|
-Dversion=<my.version> \
|
||||||
-DappName="<my app name>"</pre>
|
-DappName="<my app name>"</pre>
|
||||||
|
|
||||||
<p>You change into the directory of the new project and then build the project by calling:</p>
|
<p>You change into the directory of the new project and then build the project by calling:</p>
|
||||||
|
@ -107,13 +107,13 @@ mvn exec:java</pre>
|
||||||
<p>The following shows the maven command to create the new maven project. Note that you should replace the
|
<p>The following shows the maven command to create the new maven project. Note that you should replace the
|
||||||
placeholders in the brackets:</p>
|
placeholders in the brackets:</p>
|
||||||
<pre>
|
<pre>
|
||||||
mvn archetype:generate
|
mvn archetype:generate \
|
||||||
-DarchetypeGroupId=li.strolch
|
-DarchetypeGroupId=li.strolch \
|
||||||
-DarchetypeArtifactId=li.strolch.mvn.archetype.webapp
|
-DarchetypeArtifactId=li.strolch.mvn.archetype.webapp \
|
||||||
-DarchetypeVersion=1.6.0-SNAPSHOT
|
-DarchetypeVersion=1.6.0-SNAPSHOT \
|
||||||
-DgroupId=<my.groupid>
|
-DgroupId=<my.groupid> \
|
||||||
-DartifactId=<my-artifactId>
|
-DartifactId=<my-artifactId> \
|
||||||
-Dversion=<my.version>
|
-Dversion=<my.version> \
|
||||||
-DappName="<my app name>"</pre>
|
-DappName="<my app name>"</pre>
|
||||||
|
|
||||||
<h4>Install the web dependencies</h4>
|
<h4>Install the web dependencies</h4>
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 39 KiB |
|
@ -68,9 +68,26 @@
|
||||||
are satisfied with the result. What follows is a description in how to set up your own Strolch based PLC.</p>
|
are satisfied with the result. What follows is a description in how to set up your own Strolch based PLC.</p>
|
||||||
|
|
||||||
<h2>Architecture</h2>
|
<h2>Architecture</h2>
|
||||||
|
<h3>Overview</h3>
|
||||||
|
<img class="image" src="images/Strolch-PLC-Architecture-Overview.png" alt="Strolch PLC Architecture Overview">
|
||||||
<p>The Strolch PLC architecture sees the Strolch Agent as the server, managing logical devices, i.e. multiple
|
<p>The Strolch PLC architecture sees the Strolch Agent as the server, managing logical devices, i.e. multiple
|
||||||
sensors and actors together and thus deciding </p>
|
sensors and actors together and thus deciding on further steps. With this architecture multiple PLCs can be
|
||||||
|
combined together in one agent for flow control.</p>
|
||||||
|
|
||||||
|
<h3>PLC Architecture</h3>
|
||||||
<img class="image" src="images/Strolch-PLC-Architecture.png" alt="Strolch PLC Architecture">
|
<img class="image" src="images/Strolch-PLC-Architecture.png" alt="Strolch PLC Architecture">
|
||||||
|
<p>On the agent side the two main classes are the <code>PlcGwServerHandler</code> and the
|
||||||
|
<code>PlcGwService</code></p>
|
||||||
|
<p>The <code>PlcGwServerHandler</code> handles connections from remote PLCs over WebSockets and sends the
|
||||||
|
requests to these PLCs. A <code>PlcGwService</code> instance will be notified and can then decide on an
|
||||||
|
action. In an execution model with <code>Activities</code>, the <code>PlcNotificationListener</code>
|
||||||
|
interface can be implemented, or the <code>PlcExecutionPolicy</code> can be directly extended.</p>
|
||||||
|
|
||||||
|
<p>On the PLC side, the <code>PlcGwClientHandler</code> is optional if no agent is required. The <code>PlcHandler</code>
|
||||||
|
initializes the model and connections. The <code>Plc</code> class is Strolch agnostic and manages the
|
||||||
|
connections and notifies <code>PlcListener</code> instances on changes coming from the underlying
|
||||||
|
connections. The <code>PlcService</code> implementations implement business logic, and can also be notified
|
||||||
|
on updates from connections.</p>
|
||||||
|
|
||||||
<h2>Example set up</h2>
|
<h2>Example set up</h2>
|
||||||
<p>This example setup describes the movement of containers over conveyors. The conveyors have motors which can
|
<p>This example setup describes the movement of containers over conveyors. The conveyors have motors which can
|
||||||
|
@ -82,6 +99,453 @@
|
||||||
|
|
||||||
<img class="image" src="images/Strolch-Plc-Example.png" alt="Strolch PLC Conveyor Example" />
|
<img class="image" src="images/Strolch-Plc-Example.png" alt="Strolch PLC Conveyor Example" />
|
||||||
|
|
||||||
|
<h2>New Project</h2>
|
||||||
|
<ol>
|
||||||
|
<li>First create a new Strolch Web project using the <a href="development.html">Strolch Maven archetype</a>
|
||||||
|
</li>
|
||||||
|
<li>Now add the following Maven dependencies:
|
||||||
|
<pre>
|
||||||
|
<properties>
|
||||||
|
<strolch.version>1.6.0-SNAPSHOT</strolch.version>
|
||||||
|
<strolch.plc.version>0.1.0-SNAPSHOT</strolch.plc.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependency>
|
||||||
|
<groupId>li.strolch</groupId>
|
||||||
|
<artifactId>li.strolch.bom</artifactId>
|
||||||
|
<type>pom</type>
|
||||||
|
<version>${strolch.version}</version>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>li.strolch</groupId>
|
||||||
|
<artifactId>strolch-plc-bom</artifactId>
|
||||||
|
<type>pom</type>
|
||||||
|
<version>${strolch.plc.version}</version>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- PLC -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>li.strolch</groupId>
|
||||||
|
<artifactId>strolch-plc-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>li.strolch</groupId>
|
||||||
|
<artifactId>strolch-plc-rest</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>li.strolch</groupId>
|
||||||
|
<artifactId>strolch-plc-gw-client</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies></pre>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p>Add a bower dependency: <code>"strolch-wc-plc": "4treesCH/strolch-wc-plc#^0.3.4"</code> to <code>src/main/webapp/bower.json</code>
|
||||||
|
</p>
|
||||||
|
<p>After adding the dependeny, run <code>gulp</code> in the webapp directory. Gulp should have been
|
||||||
|
installed through the instructions from the <a href="development.html">development page</a>.</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p>Now we need to add the PLC web views to our new project. This is added in the <code>src/main/webapp/app/src/c-app.html</code>
|
||||||
|
file. Add the following:</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<!-- HTML Imports -->
|
||||||
|
<link rel="import" href="../bower_components/strolch-wc-plc/strolch-wc-plc-connections.html">
|
||||||
|
<link rel="import" href="../bower_components/strolch-wc-plc/strolch-wc-plc-logical-devices.html">
|
||||||
|
|
||||||
|
<!-- Change default-page to plcLogicalDevices -->
|
||||||
|
<c-app-routing id="appRouting"
|
||||||
|
login-page="login"
|
||||||
|
default-page="plcLogicalDevices"
|
||||||
|
auth-valid="[[authTokenValid]]"
|
||||||
|
page="{{page}}"
|
||||||
|
route-tail="{{routeTail}}"
|
||||||
|
use-hash-as-path></c-app-routing>
|
||||||
|
|
||||||
|
<!-- Add the new pages in the iron-pages element: -->
|
||||||
|
<template is="dom-if" if="[[equal(page, 'plcConnections')]]" restamp>
|
||||||
|
<strolch-wc-plc-connections id="plcConnections"
|
||||||
|
base-path="../"
|
||||||
|
base-rest-path="[[baseRestPath]]"
|
||||||
|
route="{{subroute}}"></strolch-wc-plc-connections>
|
||||||
|
</template>
|
||||||
|
<template is="dom-if" if="[[equal(page, 'plcLogicalDevices')]]" restamp>
|
||||||
|
<strolch-wc-plc-logical-devices id="plcLogicalDevices"
|
||||||
|
base-path="../"
|
||||||
|
base-rest-path="[[baseRestPath]]"
|
||||||
|
base-ws-path="[[baseWsPath]]"
|
||||||
|
route="{{subroute}}"></strolch-wc-plc-logical-devices>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
// add a new property to the WebSocket path for observing changes on the PLC
|
||||||
|
wsObserverPath: {
|
||||||
|
type: String,
|
||||||
|
value: function () {
|
||||||
|
return CustomWeb.baseWsPath + "/plc/observer";
|
||||||
|
}
|
||||||
|
}</pre>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p>Now we need to configure the PLC's runtime by modifying <code>runtime/StrolchConfiguration.xml</code>
|
||||||
|
and adding the following:</p>
|
||||||
|
<pre>
|
||||||
|
<!--
|
||||||
|
This component configures the PlcHandler by
|
||||||
|
loading the PlcConnections, PlcAddresses and PlcTelegrams
|
||||||
|
-->
|
||||||
|
<Component>
|
||||||
|
<name>PlcHandler</name>
|
||||||
|
<api>li.strolch.plc.core.PlcHandler</api>
|
||||||
|
<impl>li.strolch.plc.core.DefaultPlcHandler</impl>
|
||||||
|
<depends>RealmHandler</depends>
|
||||||
|
<Properties>
|
||||||
|
<!-- The component handling the low level connections -->
|
||||||
|
<plcClass>li.strolch.plc.core.hw.DefaultPlc</plcClass>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This component handles registrations of the PlcServices, i.e. your PLC business logic
|
||||||
|
-->
|
||||||
|
<Component>
|
||||||
|
<name>PlcServiceInitializer</name>
|
||||||
|
<api>li.strolch.plc.core.PlcServiceInitializer</api>
|
||||||
|
<impl>li.strolch.plc.example.CustomPlcServiceInitializer</impl>
|
||||||
|
<depends>PlcHandler</depends>
|
||||||
|
<Properties>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This component notifies a Strolch agent of changes on the PLC
|
||||||
|
only if you have a Strolch server with a configured
|
||||||
|
li.strolch.plc.gw.server.PlcServerWebSocketEndpoint ready to accept connections
|
||||||
|
-->
|
||||||
|
<Component>
|
||||||
|
<name>PlcGwClientHandler</name>
|
||||||
|
<api>li.strolch.plc.gw.client.PlcGwClientHandler</api>
|
||||||
|
<impl>li.strolch.plc.gw.client.PlcGwClientHandler</impl>
|
||||||
|
<depends>PlcHandler</depends>
|
||||||
|
<depends>PlcServiceInitializer</depends>
|
||||||
|
<Properties>
|
||||||
|
<plcId>plc-01</plcId>
|
||||||
|
<gwUsername>plc-01</gwUsername>
|
||||||
|
<gwPassword>plc-01</gwPassword>
|
||||||
|
<gwServerUrl>ws://localhost:8080/agent/websocket/strolch/plc</gwServerUrl>
|
||||||
|
</Properties>
|
||||||
|
</Component></pre>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p>Now we add the custom classes we just declared.</p>
|
||||||
|
|
||||||
|
<p><b>PlcServiceInitializer</b></p>
|
||||||
|
<pre>
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import li.strolch.plc.example.services.*;
|
||||||
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
|
import li.strolch.plc.core.PlcHandler;
|
||||||
|
import li.strolch.plc.core.PlcService;
|
||||||
|
import li.strolch.plc.core.PlcServiceInitializer;
|
||||||
|
|
||||||
|
public class CustomPlcServiceInitializer extends PlcServiceInitializer {
|
||||||
|
|
||||||
|
public CustomPlcServiceInitializer(ComponentContainer container, String componentName) {
|
||||||
|
super(container, componentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<PlcService> getPlcServices(PlcHandler plcHandler) {
|
||||||
|
ArrayList<PlcService> plcServices = new ArrayList<>();
|
||||||
|
|
||||||
|
StartupPlcService startupPlcService = new StartupPlcService(plcHandler);
|
||||||
|
ConveyorPlcService conveyorPlcService = new ConveyorPlcService(plcHandler);
|
||||||
|
|
||||||
|
plcServices.add(conveyorPlcService);
|
||||||
|
plcServices.add(startupPlcService);
|
||||||
|
|
||||||
|
return plcServices;
|
||||||
|
}
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<p><b>PlcPostInitializer</b></p>
|
||||||
|
<pre>
|
||||||
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
|
import li.strolch.plc.core.PlcPostInitializer;
|
||||||
|
|
||||||
|
public class CustomPostInitializer extends PlcPostInitializer {
|
||||||
|
public CustomPostInitializer(ComponentContainer container, String componentName) {
|
||||||
|
super(container, componentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// override the initialize(), start(), stop() and destroy() methods as needed
|
||||||
|
}</pre>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p>In the <code>CustomPlcServiceInitializer</code> we added two PlcServices, for which the code is
|
||||||
|
missing. The following are simple examples:</p>
|
||||||
|
|
||||||
|
<p><b>StartupPlcService</b></p>
|
||||||
|
<pre>
|
||||||
|
import li.strolch.persistence.api.StrolchTransaction;
|
||||||
|
import li.strolch.plc.core.PlcHandler;
|
||||||
|
import li.strolch.plc.core.PlcService;
|
||||||
|
|
||||||
|
public class StartupPlcService extends PlcService {
|
||||||
|
|
||||||
|
public static final String PLC = "PLC";
|
||||||
|
public static final String STARTED = "Started";
|
||||||
|
public static final String STOPPED = "Stopped";
|
||||||
|
|
||||||
|
public StartupPlcService(PlcHandler plcHandler) {
|
||||||
|
super(plcHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(StrolchTransaction tx) {
|
||||||
|
send(PLC, STARTED);
|
||||||
|
super.start(tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
send(PLC, STOPPED);
|
||||||
|
super.stop();
|
||||||
|
}
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<p><b>ConveyorPlcService</b></p>
|
||||||
|
<pre>
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import li.strolch.plc.core.PlcHandler;
|
||||||
|
import li.strolch.plc.core.PlcService;
|
||||||
|
import li.strolch.plc.model.PlcAddress;
|
||||||
|
|
||||||
|
public class ConveyorPlcService extends PlcService {
|
||||||
|
|
||||||
|
public static final int BOX_TRANSFER_DURATION = 30;
|
||||||
|
|
||||||
|
private static final String R_CONVEYOR_01 = "Conveyor01";
|
||||||
|
private static final String A_START_BUTTON = "StartButton";
|
||||||
|
private static final String T_MOTOR_ON = "MotorOn";
|
||||||
|
private static final String T_MOTOR_OFF = "MotorOff";
|
||||||
|
private static final String A_BOX_DETECTED = "BoxDetected";
|
||||||
|
|
||||||
|
private boolean motorOn;
|
||||||
|
private ScheduledFuture<?> motorStopTask;
|
||||||
|
|
||||||
|
public ConveyorPlcService(PlcHandler plcHandler) {
|
||||||
|
super(plcHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleNotification(PlcAddress address, Object value) {
|
||||||
|
String resource = address.resource;
|
||||||
|
String action = address.action;
|
||||||
|
|
||||||
|
if (!resource.equals("Conveyor01"))
|
||||||
|
throw new IllegalStateException("Unexpected resource " + resource);
|
||||||
|
|
||||||
|
boolean active = (boolean) value;
|
||||||
|
|
||||||
|
if (action.equals(A_START_BUTTON)) {
|
||||||
|
|
||||||
|
if (active) {
|
||||||
|
logger.info("Start button pressed. Starting motors...");
|
||||||
|
send(R_CONVEYOR_01, T_MOTOR_ON);
|
||||||
|
this.motorOn = true;
|
||||||
|
scheduleStopTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (action.equals(A_BOX_DETECTED)) {
|
||||||
|
|
||||||
|
if (active && this.motorOn) {
|
||||||
|
logger.info("Container detected, refreshing stop task...");
|
||||||
|
scheduleStopTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
logger.info("Unhandled notification " + address.toKeyAddress());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleStopTask() {
|
||||||
|
if (this.motorStopTask != null)
|
||||||
|
this.motorStopTask.cancel(false);
|
||||||
|
this.motorStopTask = schedule(this::stopMotor, BOX_TRANSFER_DURATION, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopMotor() {
|
||||||
|
send(R_CONVEYOR_01, T_MOTOR_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register() {
|
||||||
|
this.plcHandler.register(R_CONVEYOR_01, A_START_BUTTON, this);
|
||||||
|
this.plcHandler.register(R_CONVEYOR_01, A_BOX_DETECTED, this);
|
||||||
|
super.register();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregister() {
|
||||||
|
this.plcHandler.unregister(R_CONVEYOR_01, A_START_BUTTON, this);
|
||||||
|
this.plcHandler.unregister(R_CONVEYOR_01, A_BOX_DETECTED, this);
|
||||||
|
super.unregister();
|
||||||
|
}
|
||||||
|
}</pre>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p>Now the last part is to add the model, i.e. PlcConnections, PlcAddresses and PlcTelegrams. To have
|
||||||
|
less configuration files and make it easier to reconfigure at runtime, this data is stored in normal
|
||||||
|
Strolch <code>Resources</code></p>
|
||||||
|
<p>In this example we will use simple Raspberry Pi GPIOs. For convenience, and also when sharing I/O
|
||||||
|
definitions with external partners, it is easier to use a CSV file to define the I/Os and then use
|
||||||
|
the <code>PlcAddressGenerator</code> to generate and validate the model.</p>
|
||||||
|
<p>For this purpose in this example, we will use one conveyor with 2 inputs and 1 output. The CSV file
|
||||||
|
should have the following content:</p>
|
||||||
|
<pre>
|
||||||
|
Description,Type,SubType,Device,Pin,Resource,Action1,Action2,Connection,DeviceId
|
||||||
|
Material Flow,Group,,,,,,,,MaterialFlow
|
||||||
|
Conveyor 1,Input,GPIO,,4,Conveyor,Occupied,,raspiBcmGpioInput
|
||||||
|
Conveyor 1,Input,GPIO,,17,Conveyor,BoxDetected,,raspiBcmGpioInput
|
||||||
|
Conveyor 1,Output,GPIO,,18,Conveyor,MotorOn,MotorOff,raspiBcmGpioOutput</pre>
|
||||||
|
|
||||||
|
<p>The CSV headers are as follows:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Description → a simple description for this PlcAddress</li>
|
||||||
|
<li>Type →
|
||||||
|
<ul>
|
||||||
|
<li>Group → Must be the first line and generates a PlcLogicalDevice, all succeeding
|
||||||
|
lines are grouped to this device. Add additional to group further devices
|
||||||
|
</li>
|
||||||
|
<li>Input → defines a boolean input</li>
|
||||||
|
<li>Output → defines a boolean output</li>
|
||||||
|
<li>Virtual → defines a virtual address which has no corresponding hardware connection.
|
||||||
|
Used for internal communication.
|
||||||
|
</li>
|
||||||
|
<li>DataLogicScanner → defines an address to read barcodes from a DataLogic Scanner.
|
||||||
|
The actions must be left empty as the keys Barcode (address), On and Off (telegrams)
|
||||||
|
will be generated.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>SubType →
|
||||||
|
<ul>
|
||||||
|
<li>For Input and Output types →
|
||||||
|
<ul>
|
||||||
|
<li>PCF8574 → For PCF8574 the Device and Pin values must be defined and will be
|
||||||
|
appended to the Connection. Define the device and pin values starting with 1,
|
||||||
|
the values will be decremented, to fit the hardware index
|
||||||
|
</li>
|
||||||
|
<li>GPIO → For GPIO the Pin will be appended to the Connection</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>For Virtual types →
|
||||||
|
<ul>
|
||||||
|
<li>Boolean</li>
|
||||||
|
<li>String</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Device → Device number</li>
|
||||||
|
<li>Pin → The pin number on the device</li>
|
||||||
|
<li>Resource → The resource ID with which to notify the agent</li>
|
||||||
|
<li>Action1 → The action ID</li>
|
||||||
|
<li>Action2 → The second action ID if required</li>
|
||||||
|
<li>Connection → The ID of the PlcConnection with which this I/O is attached</li>
|
||||||
|
<li>DeviceId → For type Group: Set the ID of this PlcLogicalDevice being generated</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>When you use this file as input for the <code>PlcAddressGenerator</code>, then it will generate
|
||||||
|
PlcLogicalDevice, PlcAddress and PlcTelegram elements:</p>
|
||||||
|
<pre>
|
||||||
|
<Resource Id="D_MaterialFlow" Name="MaterialFlow" Type="PlcLogicalDevice">
|
||||||
|
<ParameterBag Id="parameters" Name="Parameters" Type="Parameters">
|
||||||
|
<Parameter Id="description" Name="Description" Type="String" Value="Material Flow"/>
|
||||||
|
<Parameter Id="group" Name="Group" Type="String" Value="01 Material Flow"/>
|
||||||
|
<Parameter Id="index" Name="Index" Type="Integer" Value="10"/>
|
||||||
|
</ParameterBag>
|
||||||
|
<ParameterBag Id="relations" Name="Relations" Type="Relations">
|
||||||
|
<Parameter Id="addresses" Name="Addresses" Type="StringList" Interpretation="Resource-Ref" Uom="PlcAddress" Value="A_Conveyor-Occupied, A_Conveyor-BoxDetected, A_Conveyor-MotorOn"/>
|
||||||
|
<Parameter Id="telegrams" Name="Telegrams" Type="StringList" Interpretation="Resource-Ref" Uom="PlcTelegram" Value="T_Conveyor-MotorOn, T_Conveyor-MotorOff"/>
|
||||||
|
</ParameterBag>
|
||||||
|
</Resource>
|
||||||
|
|
||||||
|
<Resource Id="A_Conveyor-Occupied" Name="Conveyor - Occupied" Type="PlcAddress">
|
||||||
|
<ParameterBag Id="parameters" Name="Parameters" Type="Parameters">
|
||||||
|
<Parameter Id="description" Name="Description" Type="String" Index="5" Value="Conveyor 1"/>
|
||||||
|
<Parameter Id="address" Name="HW Address" Type="String" Interpretation="PlcConnection" Index="10" Value="raspiBcmGpioInput.4"/>
|
||||||
|
<Parameter Id="resource" Name="Resource ID for PlcAddress" Type="String" Index="20" Value="Conveyor"/>
|
||||||
|
<Parameter Id="action" Name="Action ID for PlcAddress" Type="String" Index="30" Value="Occupied"/>
|
||||||
|
<Parameter Id="index" Name="Index" Type="Integer" Index="40" Value="10"/>
|
||||||
|
<Parameter Id="value" Name="Value" Type="Boolean" Index="100" Value="false"/>
|
||||||
|
</ParameterBag>
|
||||||
|
</Resource>
|
||||||
|
|
||||||
|
<Resource Id="T_Conveyor-MotorOn" Name="Conveyor - MotorOn" Type="PlcTelegram">
|
||||||
|
<ParameterBag Id="parameters" Name="Parameters" Type="Parameters">
|
||||||
|
<Parameter Id="description" Name="Description" Type="String" Index="5" Value="Conveyor 1"/>
|
||||||
|
<Parameter Id="address" Name="HW Address" Type="String" Interpretation="PlcConnection" Index="10" Value="raspiBcmGpioOutput.18"/>
|
||||||
|
<Parameter Id="resource" Name="Resource ID for PlcAddress" Type="String" Index="20" Value="Conveyor"/>
|
||||||
|
<Parameter Id="action" Name="Action ID for PlcAddress" Type="String" Index="30" Value="MotorOn"/>
|
||||||
|
<Parameter Id="index" Name="Index" Type="Integer" Index="40" Value="10"/>
|
||||||
|
<Parameter Id="value" Name="Value" Type="Boolean" Index="100" Value="true"/>
|
||||||
|
</ParameterBag>
|
||||||
|
</Resource></pre>
|
||||||
|
|
||||||
|
<p>The PlcLogicalDevice references the PlcAddress and PlcTelegram objects, and is then used in the UI
|
||||||
|
for grouping.</p>
|
||||||
|
<p>The PlcAddress is used to store the current value and defines the keys with which the agent will be
|
||||||
|
notified</p>
|
||||||
|
<p>The PlcTelegram is used to store default values to send, for specific keys. E.g. The action
|
||||||
|
<code>On</code> would send true, and <code>Off</code> would send false. This is semantics, and is
|
||||||
|
defined in each project depending on the hardware.</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>Now that we have a model, the PlcConnections are to be defined. In the previous example we used a
|
||||||
|
Raspberry Pi's GPIOs. This needs to be defined as a PlcConnection:
|
||||||
|
<pre>
|
||||||
|
<Resource Id="raspiBcmGpioOutput" Name="Raspi BCM GPIO Output" Type="PlcConnection">
|
||||||
|
<ParameterBag Id="parameters" Name="Parameters" Type="Parameters">
|
||||||
|
<Parameter Id="className" Name="Connection Class" Type="String" Value="li.strolch.plc.core.hw.gpio.RaspiBcmGpioOutputConnection"/>
|
||||||
|
<Parameter Id="state" Name="Connection State" Type="String" Interpretation="Enumeration" Uom="ConnectionState" Value="Disconnected"/>
|
||||||
|
<Parameter Id="stateMsg" Name="Connection State Msg" Type="String" Interpretation="Enumeration" Uom="ConnectionState"
|
||||||
|
Value=""/>
|
||||||
|
<Parameter Id="inverted" Name="Inverted" Type="Boolean" Value="false"/>
|
||||||
|
<Parameter Id="bcmOutputPins" Name="BCM Output Pins" Type="IntegerList" Value="27"/>
|
||||||
|
</ParameterBag>
|
||||||
|
</Resource>
|
||||||
|
<Resource Id="raspiBcmGpioInput" Name="Raspi BCM GPIO Input" Type="PlcConnection">
|
||||||
|
<ParameterBag Id="parameters" Name="Parameters" Type="Parameters">
|
||||||
|
<Parameter Id="className" Name="Connection Class" Type="String" Value="li.strolch.plc.core.hw.gpio.RaspiBcmGpioInputConnection"/>
|
||||||
|
<Parameter Id="state" Name="Connection State" Type="String" Interpretation="Enumeration" Uom="ConnectionState" Value="Disconnected"/>
|
||||||
|
<Parameter Id="stateMsg" Name="Connection State Msg" Type="String" Interpretation="Enumeration" Uom="ConnectionState"
|
||||||
|
Value=""/>
|
||||||
|
<Parameter Id="inverted" Name="Inverted" Type="Boolean" Value="true"/>
|
||||||
|
<Parameter Id="bcmInputPins" Name="BCM Input Pins" Type="IntegerList" Value="4"/>
|
||||||
|
</ParameterBag>
|
||||||
|
</Resource></pre>
|
||||||
|
<p>See
|
||||||
|
<a href="https://github.com/4treesCH/strolch-plc/blob/develop/example/strolch-plc-example-connections.xml">strolch-plc-example-connections.xml</a>
|
||||||
|
for further examples. </p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /.content -->
|
<!-- /.content -->
|
||||||
|
|
Loading…
Reference in New Issue