node-red-contrib-opcua
Version:
A Node-RED node to communicate via OPC UA based on node-opcua library.
230 lines (218 loc) • 13 kB
HTML
<!--
Copyright 2015 Valmet Automation Inc.
Licensed 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.
-->
<script type="text/javascript">
RED.nodes.registerType('OpcUa-Server',{
category: 'opcua',
color:"#3FADB5",
defaults: {
port: {value: "53880", required: true},
name: {value:""},
endpoint: {value: ""},
users: {value: "users.json"},
nodeset: {value: ""},
autoAcceptUnknownCertificate: {value: true},
registerToDiscovery: {value: false},
constructDefaultAddressSpace: {value: true},
allowAnonymous: {value: true},
endpointNone: {value: true},
endpointSign: {value: true},
endpointSignEncrypt: {value: true},
endpointBasic128Rsa15: {value: true},
endpointBasic256: {value: true},
endpointBasic256Sha256: {value: true},
maxNodesPerBrowse: {value: 0, required: false},
maxNodesPerHistoryReadData: {value: 0, required: false},
maxNodesPerHistoryReadEvents: {value: 0, required: false},
maxNodesPerHistoryUpdateData: {value: 0, required: false},
maxNodesPerRead: {value: 0, required: false},
maxNodesPerWrite: {value: 0, required: false},
maxNodesPerMethodCall: {value: 0, required: false},
maxNodesPerRegisterNodes: {value: 0, required: false},
maxNodesPerNodeManagement: {value: 0, required: false},
maxMonitoredItemsPerCall: {value: 0, required: false},
maxNodesPerHistoryUpdateEvents: {value: 0, required: false},
maxNodesPerTranslateBrowsePathsToNodeIds: {value: 0, required: false}
},
inputs:1,
outputs:1,
align: "right",
icon: "opcuanodeLogo.png",
label: function() {
return this.name || "OPC UA server";
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>
<script type="text/x-red" data-template-name="OpcUa-Server">
<div class="form-row">
<label for="node-input-port"><i class="icon-tasks"></i> Port</label>
<!-- dynamic Ports from 49152 to 65535 (c000hex bis FFFFhex) -->
<input type="text" id="node-input-port" placeholder="Ports 49152 bis 65535 (c000hex bis FFFFhex)">
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tasks"></i> Name</label>
<input type="text" id="node-input-name" placeholder="">
</div>
<div class="form-row">
<label for="node-input-endpoint"><i class="icon-tasks"></i> ResourcePath</label>
<input type="text" id="node-input-endpoint" placeholder="UA/SimpleNodeRedServer">
</div>
<div class="form-row">
<label for="node-input-users"><i class="icon-tasks"></i> Users file</label>
<input type="text" id="node-input-users" placeholder="users.json">
</div>
<div class="form-row">
<label for="node-input-nodeset"><i class="icon-tasks"></i> Custom nodeset file</label>
<input type="text" id="node-input-nodeset" placeholder="">
</div>
<div class="form-row">
<label for="node-input-autoAcceptUnknownCertificate" style="width:72%;"><i class="icon-tasks"></i> Auto Accept Unknown Certificates</label>
<input type="checkbox" id="node-input-autoAcceptUnknownCertificate" style="max-width:20px">
</div>
<div class="form-row">
<label for="node-input-registerToDiscovery" style="width:72%;"><i class="icon-tasks"></i> Register to Local Discovery</label>
<input type="checkbox" id="node-input-registerToDiscovery" style="max-width:20px">
</div>
<div class="form-row">
<label for="node-input-constructDefaultAddressSpace" style="width:72%;"><i class="icon-tasks"></i> Build default AddressSpace</label>
<input type="checkbox" id="node-input-constructDefaultAddressSpace" style="max-width:20px">
</div>
<div class="form-row">
<label for="node-input-allowAnonymous" style="width:72%;"><i class="icon-tasks"></i> Allow anonymous user</label>
<input type="checkbox" id="node-input-allowAnonymous" style="max-width:20px">
</div>
<div class="form-row">
<label for="node-input-endpointNone" style="width:72%;"><i class="icon-tasks"></i> Security mode: None</label>
<input type="checkbox" id="node-input-endpointNone" style="max-width:20px">
</div>
<div class="form-row">
<label for="node-input-endpointSign" style="width:72%;"><i class="icon-tasks"></i> Security mode: Sign</label>
<input type="checkbox" id="node-input-endpointSign" style="max-width:20px">
</div>
<div class="form-row">
<label for="node-input-endpointSignEncrypt" style="width:72%;"><i class="icon-tasks"></i> Security mode: Sign & Encrypt</label>
<input type="checkbox" id="node-input-endpointSignEncrypt" style="max-width:20px">
</div>
<div class="form-row">
<label for="node-input-endpointBasic128Rsa15" style="width:72%;"><i class="icon-tasks"></i> Security policy: Basic128-Rsa15</label>
<input type="checkbox" id="node-input-endpointBasic128Rsa15" style="max-width:20px">
</div>
<div class="form-row">
<label for="node-input-endpointBasic256" style="width:72%;"><i class="icon-tasks"></i> Security policy: Basic256</label>
<input type="checkbox" id="node-input-endpointBasic256" style="max-width:20px">
</div>
<div class="form-row">
<label for="node-input-endpointBasic256Sha256" style="width:72%;"><i class="icon-tasks"></i> Security policy: Basic256-Sha256</label>
<input type="checkbox" id="node-input-endpointBasic256Sha256" style="max-width:20px">
</div>
<div class="form-row">
<label for="node-input-maxNodesPerBrowse" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerBrowse</label>
<input type="number" id="node-input-maxNodesPerBrowse" placeholder="number" style="max-width:100px">
</div>
<div class="form-row">
<label for="node-input-maxNodesPerHistoryReadData" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerHistoryReadData</label>
<input type="number" id="node-input-maxNodesPerHistoryReadData" placeholder="number" style="max-width:100px">
</div>
<div class="form-row">
<label for="node-input-maxNodesPerHistoryReadEvents" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerHistoryReadEvents</label>
<input type="number" id="node-input-maxNodesPerHistoryReadEvents" placeholder="number" style="max-width:100px">
</div>
<div class="form-row">
<label for="node-input-maxNodesPerHistoryUpdateData" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerHistoryUpdateData</label>
<input type="number" id="node-input-maxNodesPerHistoryUpdateData" placeholder="number" style="max-width:100px">
</div>
<div class="form-row">
<label for="node-input-maxNodesPerRead" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerRead</label>
<input type="number" id="node-input-maxNodesPerRead" placeholder="number" style="max-width:100px">
</div>
<div class="form-row">
<label for="node-input-maxNodesPerWrite" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerWrite</label>
<input type="number" id="node-input-maxNodesPerWrite" placeholder="number" style="max-width:100px">
</div>
<div class="form-row">
<label for="node-input-maxNodesPerMethodCall" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerMethodCall</label>
<input type="number" id="node-input-maxNodesPerMethodCall" placeholder="number" style="max-width:100px">
</div>
<div class="form-row">
<label for="node-input-maxNodesPerRegisterNodes" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerRegisterNodes</label>
<input type="number" id="node-input-maxNodesPerRegisterNodes" placeholder="number" style="max-width:100px">
</div>
<div class="form-row">
<label for="node-input-maxNodesPerNodeManagement" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerNodeManagement</label>
<input type="number" id="node-input-maxNodesPerNodeManagement" placeholder="number" style="max-width:100px">
</div>
<div class="form-row">
<label for="node-input-maxMonitoredItemsPerCall" style="width:72%;"><i class="icon-tasks"></i> maxMonitoredItemsPerCall</label>
<input type="number" id="node-input-maxMonitoredItemsPerCall" placeholder="number" style="max-width:100px">
</div>
<div class="form-row">
<label for="node-input-maxNodesPerHistoryUpdateEvents" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerHistoryUpdateEvents</label>
<input type="number" id="node-input-maxNodesPerHistoryUpdateEvents" placeholder="number" style="max-width:100px">
</div>
<div class="form-row">
<label for="node-input-maxNodesPerTranslateBrowsePathsToNodeIds" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerTranslateBrowsePathsToNodeIds</label>
<input type="number" id="node-input-maxNodesPerTranslateBrowsePathsToNodeIds" placeholder="number" style="max-width:100px">
</div>
</script>
<script type="text/x-red" data-help-name="OpcUa-Server">
<p>Creates OPC UA server with own variables, object structures and methods to endpoint: opc.tcp://localhost:PORT/ResourcePath/</p>
<p>Parameters PORT and ResourcePath can be given for the server.</p>
<p>File that contains username, password and role.</p>
<p>Register to local Discover Server, if true => OPC UA Server will register itself to opc.tcp://localhost:4840</p>
<p>ConstructDefaultAddressSpace, if false then Server AddressSpace will be empty (no VendorName and sub objects)<p>
<p>Server active endpoints from security mode and policy:</p>
<p>Security mode: None Sign SignAndEncrypt<p>
<p>Security policy: Basic128-Rsa15 | Basic256 | Basic128-Sha256<p>
<p>
OPC UA server commands:
<ul>
<li><b>restartOPCUAServer</b></li>
<li><b>addEquipment</b></li>
<li><b>addPhysicalAsset</b></li>
<li><b>setFolder</b> msg.topic = "folderName" // Example topic format ns=1;s=FolderName (note: uses this as parentFolder)</li>
<li><b>addFolder</b> msg.topic = "ns=1;s=NewFolder" // Note parent folder is objects if not set by setFolder</li>
<li><b>addVariable</b> msg.topic = "ns=1;s=VariableName;datatype=Double" // parent folder is set above</li>
<li><b>installHistorian</b> msg.topic = "ns=1;s=VariableName;datatype=Double</li>
<li><b>addExtensionObject</b> msg.topic = "ns=1;s=VariableName;datatype=ExtensionObject;TypeId=ns=3;i=1001</li>
<li><b>deleteNode</b> msg.payload = "ns=1;s=VariableName"</li>
<li><b>registerNamespace</b> msg.topic = "www.acme.com" output msg.payload = ns=index </li>
<li><b>getNamespaceIndex</b> msg.topic = "www.acme.com" output msg.payload = ns=index </li>
<li><b>setUsers</b> msg.topic = "" msg.users JSON structure of users (username, password role)</li>
</ul>
Examples JSON Injects: <br />
<pre>
msg.payload = { "opcuaCommand": "addEquipment", "nodeName": "Machine" }
</pre>
<pre>
{ "opcuaCommand": "restartOPCUAServer" }
{ "opcuaCommand": "addEquipment", "nodeName": "Machine" }
{ "opcuaCommand": "addPhysicalAsset", "nodeName": "PhysicalAsset" }
{ "opcuaCommand": "deleteNode", "nodeId": "ns=4;s=PhysicalAsset2" }
</pre>
</p>
<p>
OPC UA message type to set variable Counter by JSON Inject
<pre>
{ payload : { "messageType" : "Variable", "variableName": "Counter", "variableValue": msg.payload }};
</pre>
</p>
<p>
Server will send message as client will connect or disconnect.<br>
Topic: Client-connected or Client-disconnected, payload: session name (depends on client implementation)
</p>
<p>
Server operation limits can be set by node UI dialog.
</p>
</script>