@t0a5tbr0t/node-red-contrib-opcua 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE +20 -0
  3. package/Readme.md +239 -0
  4. package/images/PROSYS-OPC-UA-EXAMPLE2.png +0 -0
  5. package/images/nodeopcua64.png +0 -0
  6. package/images/opcuanode.png +0 -0
  7. package/images/opcuanodeLogo64.png +0 -0
  8. package/opcua/101-opcuaitem.html +106 -0
  9. package/opcua/101-opcuaitem.js +82 -0
  10. package/opcua/102-opcuaclient.html +274 -0
  11. package/opcua/102-opcuaclient.js +2741 -0
  12. package/opcua/103-opcuabrowser.html +71 -0
  13. package/opcua/103-opcuabrowser.js +230 -0
  14. package/opcua/104-opcuaserver.html +261 -0
  15. package/opcua/104-opcuaserver.js +1844 -0
  16. package/opcua/105-opcuaendpoint.html +224 -0
  17. package/opcua/105-opcuaendpoint.js +64 -0
  18. package/opcua/106-opcuaevent.html +110 -0
  19. package/opcua/106-opcuaevent.js +50 -0
  20. package/opcua/107-opcuamethod.html +244 -0
  21. package/opcua/107-opcuamethod.js +521 -0
  22. package/opcua/108-opcuarights.html +223 -0
  23. package/opcua/108-opcuarights.js +156 -0
  24. package/opcua/109-opcuadiscovery.html +51 -0
  25. package/opcua/109-opcuadiscovery.js +180 -0
  26. package/opcua/dump_certificates.js +55 -0
  27. package/opcua/icons/opcuanode.png +0 -0
  28. package/opcua/icons/opcuanodeLogo.png +0 -0
  29. package/opcua/opcua-basics.js +1061 -0
  30. package/opcua/public/vendor/opc-foundation/binary/OPC.ISA95.Types.bsd.xml +141 -0
  31. package/opcua/public/vendor/opc-foundation/binary/Opc.Ua.Adi.Types.bsd.xml +76 -0
  32. package/opcua/public/vendor/opc-foundation/binary/Opc.Ua.Di.Types.bsd.xml +11 -0
  33. package/opcua/public/vendor/opc-foundation/binary/Opc.Ua.Gds.Types.bsd.xml +25 -0
  34. package/opcua/public/vendor/opc-foundation/binary/Opc.Ua.Types.bsd.xml +2391 -0
  35. package/opcua/public/vendor/opc-foundation/csv/AttributeIds.csv +22 -0
  36. package/opcua/public/vendor/opc-foundation/csv/NodeIds.csv +5746 -0
  37. package/opcua/public/vendor/opc-foundation/csv/Opc.Ua.StatusCodes.csv +227 -0
  38. package/opcua/public/vendor/opc-foundation/csv/OpcUaDiModel.csv +1523 -0
  39. package/opcua/public/vendor/opc-foundation/csv/OpcUaGdsModel.csv +400 -0
  40. package/opcua/public/vendor/opc-foundation/csv/ServerCapabilities.csv +13 -0
  41. package/opcua/public/vendor/opc-foundation/csv/ServerCapabilityIdentifiers.csv +13 -0
  42. package/opcua/public/vendor/opc-foundation/csv/StatusCode.csv +227 -0
  43. package/opcua/public/vendor/opc-foundation/csv/StatusCodes.csv +227 -0
  44. package/opcua/public/vendor/opc-foundation/schema/OPC.ISA95.Types.xsd +163 -0
  45. package/opcua/public/vendor/opc-foundation/schema/OPCBinarySchema.xsd +119 -0
  46. package/opcua/public/vendor/opc-foundation/schema/Opc.Ua.Types.xsd +3938 -0
  47. package/opcua/public/vendor/opc-foundation/schema/SecuredApplication.xsd +106 -0
  48. package/opcua/public/vendor/opc-foundation/schema/UANodeSet.xsd +420 -0
  49. package/opcua/public/vendor/opc-foundation/xml/OPC.ISA95.NodeSet2.Nov52013.xml +3293 -0
  50. package/opcua/public/vendor/opc-foundation/xml/Opc.ISA95.NodeSet2.xml +3589 -0
  51. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.Adi.NodeSet2.xml +8301 -0
  52. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.Adi.Types.bsd.xml +76 -0
  53. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.Adi.Types.xsd +157 -0
  54. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.AutoID.NodeSet2.xml +6062 -0
  55. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.Di.NodeSet2.xml +5066 -0
  56. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.Di.PredefinedNodes.xml +11495 -0
  57. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.Di.Types.bsd +86 -0
  58. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.Di.Types.bsd.xml +11 -0
  59. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.Di.Types.xsd +155 -0
  60. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.Gds.NodeSet.xml +15226 -0
  61. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.Gds.NodeSet2.xml +6214 -0
  62. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.Gds.Types.bsd.xml +25 -0
  63. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.Gds.Types.xsd +30 -0
  64. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet-2.xml +134881 -0
  65. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet-3.xml +134881 -0
  66. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet.xml +134881 -0
  67. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet2.Part10.xml +832 -0
  68. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet2.Part11.xml +793 -0
  69. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet2.Part12.xml +3877 -0
  70. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet2.Part13.xml +344 -0
  71. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet2.Part3.xml +1103 -0
  72. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet2.Part4.xml +3091 -0
  73. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet2.Part5.xml +17092 -0
  74. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet2.Part8.xml +525 -0
  75. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet2.Part9.xml +2049 -0
  76. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet2.Part999.xml +134 -0
  77. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.NodeSet2.xml +67169 -0
  78. package/opcua/public/vendor/opc-foundation/xml/Opc.Ua.PredefinedNodes.xml +64500 -0
  79. package/opcua/public/vendor/opc-foundation/xml/OpcUaDiModel.xml +1239 -0
  80. package/opcua/utils.js +55 -0
  81. package/package.json +68 -0
  82. package/users.json +22 -0
@@ -0,0 +1,71 @@
1
+ <!--
2
+
3
+ Copyright 2015 Valmet Automation Inc.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+
17
+ -->
18
+
19
+ <script type="text/javascript">
20
+
21
+ RED.nodes.registerType('OpcUa-Browser', {
22
+ category: 'opcua',
23
+ color: "#3FADB5",
24
+ defaults: {
25
+ endpoint: {value: "", required: true, type: "OpcUa-Endpoint"},
26
+ item: {value: ""},
27
+ datatype: {value: ""},
28
+ topic: {value: ""},
29
+ items: {value: []},
30
+ name: {value: ""}
31
+ },
32
+ inputs: 1,
33
+ outputs: 1,
34
+ align: "right",
35
+ icon: "opcuanodeLogo.png",
36
+ label: function () {
37
+ return this.item || "OPC UA Browser";
38
+ },
39
+ labelStyle: function () {
40
+ return this.item ? "node_label_italic" : "";
41
+ }
42
+ });
43
+ </script>
44
+
45
+ <script type="text/x-red" data-template-name="OpcUa-Browser">
46
+ <div class="form-row" style="min-width:640px">
47
+ <label for="node-input-endpoint"><i class="icon-bookmark"></i> Endpoint</label>
48
+ <input type="text" id="node-input-endpoint">
49
+ </div>
50
+ <div class="form-row">
51
+ <label for="node-input-topic"><i class="icon-search"></i> Topic</label>
52
+ <input type="text" id="node-input-topic" placeholder="ns=0;i=85">
53
+ </div>
54
+ <div class="form-row">
55
+ <label for="node-input-name"><i class="icon-search"></i> Name</label>
56
+ <input type="text" id="node-input-name" placeholder="OPC UA Browser">
57
+ </div>
58
+ </script>
59
+
60
+
61
+
62
+ <script type="text/x-red" data-help-name="OpcUa-Browser">
63
+
64
+ <p>Connect to an endpoint: opc.tcp://host:port/UA/EndpointName</p>
65
+
66
+ <p><strong>Inject</strong> a Timestamp or fill <strong>topic</strong> of <strong>msg</strong> object to browse.</p>
67
+
68
+ <p>Browsers <strong>Topic</strong> field is to define one browsable OPC UA Item address like ns=0;i=85</p>
69
+
70
+ <p><strong>Payload</strong> contains just references of the give OPC UA address.</p>
71
+ </script>
@@ -0,0 +1,230 @@
1
+ /**
2
+
3
+ Copyright 2015 Valmet Automation Inc.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+
17
+ **/
18
+
19
+ module.exports = function (RED) {
20
+ "use strict";
21
+ var opcua = require('node-opcua');
22
+ var uaclient = require('node-opcua-client');
23
+ var path = require("path");
24
+ var chalk = require("chalk");
25
+ const { createClientCertificateManager } = require("./utils");
26
+ function OpcUaBrowserNode(config) {
27
+
28
+ RED.nodes.createNode(this, config);
29
+
30
+ this.item = config.item; // OPC UA address: ns=2;i=4 OR ns=3;s=MyVariable
31
+ this.datatype = config.datatype; // String;
32
+ this.topic = config.topic;
33
+ this.items = config.items;
34
+ this.name = config.name;
35
+
36
+ const objectsFolderNodeId = "ns=0;i=85"; // Default root, server Objects
37
+
38
+ var node = this;
39
+ // node.name = "OPC UA Browser";
40
+
41
+ var opcuaEndpoint = RED.nodes.getNode(config.endpoint);
42
+
43
+ var connectionOption = {};
44
+ var userIdentity = {};
45
+
46
+ if (opcuaEndpoint.securityPolicy) {
47
+ connectionOption.securityPolicy = opcua.SecurityPolicy[opcuaEndpoint.securityPolicy];
48
+ }
49
+ else {
50
+ connectionOption.securityPolicy = opcua.SecurityPolicy.None;
51
+ }
52
+ if (opcuaEndpoint.securityMode) {
53
+ connectionOption.securityMode = opcua.MessageSecurityMode[opcuaEndpoint.securityMode];
54
+ }
55
+ else {
56
+ connectionOption.securityPolicy = opcua.MessageSecurityMode.None;
57
+ }
58
+ connectionOption.endpointMustExist = false;
59
+
60
+ if (opcuaEndpoint.login) {
61
+ userIdentity.userName = opcuaEndpoint.credentials.user;
62
+ userIdentity.password = opcuaEndpoint.credentials.password;
63
+ userIdentity.type = uaclient.UserTokenType.UserName; // New TypeScript API parameter
64
+ }
65
+
66
+ connectionOption.clientCertificateManager = createClientCertificateManager();
67
+
68
+ node.status({
69
+ fill: "gray",
70
+ shape: "dot",
71
+ text: "no Items",
72
+ source: { id: node.id, type: node.type, name: "OPC UA Browser"}
73
+ });
74
+
75
+ node.add_item = function (item) {
76
+ if (item) {
77
+ if (!node.items) {
78
+ node.items = new Array();
79
+ }
80
+ node.items.push({
81
+ 'item': item
82
+ });
83
+ }
84
+ };
85
+
86
+ function node_error(err) {
87
+ node.error("Browse node error!", err);
88
+ }
89
+
90
+ async function setupClient(url, nodeIdToBrowse, callback) {
91
+
92
+ if(!nodeIdToBrowse) return;
93
+
94
+ // new OPC UA Client and browse from Objects ns=0;s=Objects
95
+ const client = opcua.OPCUAClient.create(connectionOption);
96
+ client.clientCertificateManager = connectionOption.clientCertificateManager; // FIX connection issue
97
+ try
98
+ {
99
+ // step 0 : init clientCertificateManager
100
+ try {
101
+ await client.clientCertificateManager.initialize();
102
+ }
103
+ catch (error1) {
104
+ set_node_status_to("invalid certificate");
105
+ let msg = {};
106
+ msg.error = {};
107
+ msg.error.message = "Certificate error: " + error1.message;
108
+ msg.error.source = this;
109
+ node.error("Certificate error", msg);
110
+ }
111
+ node.debug(chalk.yellow("Trusted folder: ") + chalk.cyan(client?.clientCertificateManager?.trustedFolder));
112
+ node.debug(chalk.yellow("Rejected folder: ") + chalk.cyan(client?.clientCertificateManager?.rejectedFolder));
113
+ node.debug(chalk.yellow("Crl folder: ") + chalk.cyan(client?.clientCertificateManager?.crlFolder));
114
+ node.debug(chalk.yellow("Issuers Cert folder: ") + chalk.cyan(client?.clientCertificateManager?.issuersCertFolder));
115
+ node.debug(chalk.yellow("Issuers Crl folder: ") + chalk.cyan(client?.clientCertificateManager?.issuersCrlFolder));
116
+
117
+ // step 1 : connect to
118
+ await client.connect(url);
119
+ node.debug("start browse client on " + opcuaEndpoint.endpoint);
120
+
121
+ // step 2 : createSession
122
+ const session = await client.createSession(userIdentity);
123
+ node.debug("start browse session on " + opcuaEndpoint.endpoint);
124
+
125
+ // step 3 : browse
126
+ node.debug("nodeIdBrowse:" + nodeIdToBrowse);
127
+ try {
128
+ const browseResult = await session.browse(nodeIdToBrowse);
129
+
130
+
131
+ // step 4 : Read Value and Datatypes
132
+ for(const reference of browseResult.references)
133
+ {
134
+ var ref_obj = Object.assign({}, reference);
135
+ const dataValue = await session.read({nodeId: ref_obj.nodeId, attributeId: opcua.AttributeIds.Value});
136
+ ref_obj["value"] = dataValue.value.value;
137
+ ref_obj["dataType"] = opcua.DataType[dataValue.value.dataType];
138
+ node.add_item(ref_obj);
139
+ }
140
+ node.status({
141
+ fill: "green",
142
+ shape: "dot",
143
+ text: "Items: " + node.items.length,
144
+ source: { id: node.id, type: node.type, name: "OPC UA Browser"}
145
+ });
146
+ } catch (err) {
147
+ node_error(err);
148
+ node.status({
149
+ fill: "yellow",
150
+ shape: "ring",
151
+ text: "browse error",
152
+ source: { id: node.id, type: node.type, name: "OPC UA Browser" }
153
+ });
154
+ }
155
+
156
+ //step 5 close session
157
+ node.debug("close browse session");
158
+ await session.close();
159
+
160
+ // Set status notification browse done
161
+ node.status({
162
+ fill: "green",
163
+ shape: "dot",
164
+ text: "Done",
165
+ source: { id: node.id, type: node.type, name: "OPC UA Browser"}
166
+ });
167
+
168
+ return node.items;
169
+ }
170
+ catch(err)
171
+ {
172
+ callback(err);
173
+ }
174
+ finally {
175
+ if (client) {
176
+ client.disconnect();
177
+ }
178
+ }
179
+ }
180
+
181
+ setupClient(opcuaEndpoint.endpoint, null, function (err) {
182
+ if (err) {
183
+ node_error(err);
184
+ node.status({
185
+ fill: "red",
186
+ shape: "dot",
187
+ text: "Error Items: " + node.items.length,
188
+ source: { id: node.id, type: node.type, name: "OPC UA Browser"}
189
+ });
190
+ }
191
+ else {
192
+ node.debug("Browse loading Items done...");
193
+ }
194
+ });
195
+
196
+ node.on("input", function (msg) {
197
+ node.debug("input browser");
198
+
199
+ node.items = [];
200
+
201
+ let nodeToBrowse = msg.topic ? msg.topic : node.topic;
202
+ if(!nodeToBrowse) nodeToBrowse = objectsFolderNodeId;
203
+
204
+ var validNodeId = opcua.isValidNodeId(opcua.resolveNodeId(nodeToBrowse));
205
+ if(!validNodeId) return;
206
+
207
+ setupClient(opcuaEndpoint.endpoint, nodeToBrowse, function (err) {
208
+ if (err) {
209
+ node_error(err);
210
+ node.status({
211
+ fill: "red",
212
+ shape: "dot",
213
+ text: "Error Items: " + (node.items?.length || 0),
214
+ source: { id: node.id, type: node.type, name: "OPC UA Browser"}
215
+ });
216
+ }
217
+ else {
218
+ node.debug("Browse loading Items done ...");
219
+ }
220
+ }).then((items) =>{
221
+ node.items = items;
222
+ msg.endpoint = opcuaEndpoint.endpoint;
223
+ msg.payload = items;
224
+ node.send(msg);
225
+ });
226
+ });
227
+ }
228
+
229
+ RED.nodes.registerType("OpcUa-Browser", OpcUaBrowserNode);
230
+ };
@@ -0,0 +1,261 @@
1
+ <!--
2
+
3
+ Copyright 2015 Valmet Automation Inc.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+
17
+ -->
18
+
19
+ <script type="text/javascript">
20
+ RED.nodes.registerType('OpcUa-Server',{
21
+ category: 'opcua',
22
+ color:"#3FADB5",
23
+ defaults: {
24
+ port: {value: "53880", required: true},
25
+ name: {value:""},
26
+ endpoint: {value: ""},
27
+ usersFile: {value: "users.json"},
28
+ nodesetDir: {value: ""},
29
+ autoAcceptUnknownCertificate: {value: true},
30
+ registerToDiscovery: {value: false},
31
+ constructDefaultAddressSpace: {value: true},
32
+ allowAnonymous: {value: true, required: true},
33
+ endpointNone: {value: true},
34
+ endpointSign: {value: true},
35
+ endpointSignEncrypt: {value: true},
36
+ endpointBasic128Rsa15: {value: true},
37
+ endpointBasic256: {value: true},
38
+ endpointBasic256Sha256: {value: true},
39
+ maxNodesPerBrowse: {value: 0, required: false},
40
+ maxNodesPerHistoryReadData: {value: 0, required: false},
41
+ maxNodesPerHistoryReadEvents: {value: 0, required: false},
42
+ maxNodesPerHistoryUpdateData: {value: 0, required: false},
43
+ maxNodesPerRead: {value: 0, required: false},
44
+ maxNodesPerWrite: {value: 0, required: false},
45
+ maxNodesPerMethodCall: {value: 0, required: false},
46
+ maxNodesPerRegisterNodes: {value: 0, required: false},
47
+ maxNodesPerNodeManagement: {value: 0, required: false},
48
+ maxMonitoredItemsPerCall: {value: 0, required: false},
49
+ maxNodesPerHistoryUpdateEvents: {value: 0, required: false},
50
+ maxNodesPerTranslateBrowsePathsToNodeIds: {value: 0, required: false},
51
+ maxConnectionsPerEndpoint: {value: 20, required: false},
52
+ maxMessageSize: {value: 4096, required: false},
53
+ maxBufferSize: {value: 4096, required: false},
54
+ maxSessions: {value: 20 , required: false}
55
+ },
56
+ inputs:1,
57
+ outputs:1,
58
+ align: "right",
59
+ icon: "opcuanodeLogo.png",
60
+ label: function() {
61
+ return this.name || "OPC UA server";
62
+ },
63
+ labelStyle: function() {
64
+ return this.name?"node_label_italic":"";
65
+ }
66
+ });
67
+ </script>
68
+
69
+
70
+
71
+ <script type="text/x-red" data-template-name="OpcUa-Server">
72
+ <div class="form-row">
73
+ <label for="node-input-port"><i class="icon-tasks"></i> Port</label>
74
+ <!-- dynamic Ports from 49152 to 65535 (c000hex bis FFFFhex) -->
75
+ <input type="text" id="node-input-port" placeholder="Ports 49152 bis 65535 (c000hex bis FFFFhex)">
76
+ </div>
77
+ <div class="form-row">
78
+ <label for="node-input-name"><i class="icon-tasks"></i> Name</label>
79
+ <input type="text" id="node-input-name" placeholder="">
80
+ </div>
81
+ <div class="form-row">
82
+ <label for="node-input-endpoint"><i class="icon-tasks"></i> ResourcePath</label>
83
+ <input type="text" id="node-input-endpoint" placeholder="UA/SimpleNodeRedServer">
84
+ </div>
85
+ <div class="form-row">
86
+ <label for="node-input-usersFile"><i class="icon-tasks"></i> Users file</label>
87
+ <input type="text" id="node-input-usersFile" placeholder="users.json">
88
+ </div>
89
+ <div class="form-row">
90
+ <label for="node-input-nodesetDir"><i class="icon-tasks"></i> Custom nodeset directory</label>
91
+ <input type="text" id="node-input-nodesetDir" placeholder="">
92
+ </div>
93
+ <div class="form-row">
94
+ <label for="node-input-autoAcceptUnknownCertificate" style="width:72%;"><i class="icon-tasks"></i> Auto Accept Unknown Certificates</label>
95
+ <input type="checkbox" id="node-input-autoAcceptUnknownCertificate" style="max-width:20px">
96
+ </div>
97
+ <div class="form-row">
98
+ <label for="node-input-registerToDiscovery" style="width:72%;"><i class="icon-tasks"></i> Register to Local Discovery</label>
99
+ <input type="checkbox" id="node-input-registerToDiscovery" style="max-width:20px">
100
+ </div>
101
+ <div class="form-row">
102
+ <label for="node-input-constructDefaultAddressSpace" style="width:72%;"><i class="icon-tasks"></i> Build default AddressSpace</label>
103
+ <input type="checkbox" id="node-input-constructDefaultAddressSpace" style="max-width:20px">
104
+ </div>
105
+ <div class="form-row">
106
+ <label for="node-input-allowAnonymous" style="width:72%;"><i class="icon-tasks"></i> Allow anonymous user</label>
107
+ <input type="checkbox" id="node-input-allowAnonymous" style="max-width:20px">
108
+ </div>
109
+ <div class="form-row">
110
+ <label for="node-input-endpointNone" style="width:72%;"><i class="icon-tasks"></i> Security mode: None</label>
111
+ <input type="checkbox" id="node-input-endpointNone" style="max-width:20px">
112
+ </div>
113
+ <div class="form-row">
114
+ <label for="node-input-endpointSign" style="width:72%;"><i class="icon-tasks"></i> Security mode: Sign</label>
115
+ <input type="checkbox" id="node-input-endpointSign" style="max-width:20px">
116
+ </div>
117
+ <div class="form-row">
118
+ <label for="node-input-endpointSignEncrypt" style="width:72%;"><i class="icon-tasks"></i> Security mode: Sign & Encrypt</label>
119
+ <input type="checkbox" id="node-input-endpointSignEncrypt" style="max-width:20px">
120
+ </div>
121
+ <div class="form-row">
122
+ <label for="node-input-endpointBasic128Rsa15" style="width:72%;"><i class="icon-tasks"></i> Security policy: Basic128-Rsa15</label>
123
+ <input type="checkbox" id="node-input-endpointBasic128Rsa15" style="max-width:20px">
124
+ </div>
125
+ <div class="form-row">
126
+ <label for="node-input-endpointBasic256" style="width:72%;"><i class="icon-tasks"></i> Security policy: Basic256</label>
127
+ <input type="checkbox" id="node-input-endpointBasic256" style="max-width:20px">
128
+ </div>
129
+ <div class="form-row">
130
+ <label for="node-input-endpointBasic256Sha256" style="width:72%;"><i class="icon-tasks"></i> Security policy: Basic256-Sha256</label>
131
+ <input type="checkbox" id="node-input-endpointBasic256Sha256" style="max-width:20px">
132
+ </div>
133
+ <div class="form-row">
134
+ <label for="node-input-maxNodesPerBrowse" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerBrowse</label>
135
+ <input type="number" id="node-input-maxNodesPerBrowse" placeholder="number" style="max-width:100px">
136
+ </div>
137
+ <div class="form-row">
138
+ <label for="node-input-maxNodesPerHistoryReadData" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerHistoryReadData</label>
139
+ <input type="number" id="node-input-maxNodesPerHistoryReadData" placeholder="number" style="max-width:100px">
140
+ </div>
141
+ <div class="form-row">
142
+ <label for="node-input-maxNodesPerHistoryReadEvents" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerHistoryReadEvents</label>
143
+ <input type="number" id="node-input-maxNodesPerHistoryReadEvents" placeholder="number" style="max-width:100px">
144
+ </div>
145
+ <div class="form-row">
146
+ <label for="node-input-maxNodesPerHistoryUpdateData" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerHistoryUpdateData</label>
147
+ <input type="number" id="node-input-maxNodesPerHistoryUpdateData" placeholder="number" style="max-width:100px">
148
+ </div>
149
+ <div class="form-row">
150
+ <label for="node-input-maxNodesPerRead" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerRead</label>
151
+ <input type="number" id="node-input-maxNodesPerRead" placeholder="number" style="max-width:100px">
152
+ </div>
153
+ <div class="form-row">
154
+ <label for="node-input-maxNodesPerWrite" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerWrite</label>
155
+ <input type="number" id="node-input-maxNodesPerWrite" placeholder="number" style="max-width:100px">
156
+ </div>
157
+ <div class="form-row">
158
+ <label for="node-input-maxNodesPerMethodCall" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerMethodCall</label>
159
+ <input type="number" id="node-input-maxNodesPerMethodCall" placeholder="number" style="max-width:100px">
160
+ </div>
161
+ <div class="form-row">
162
+ <label for="node-input-maxNodesPerRegisterNodes" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerRegisterNodes</label>
163
+ <input type="number" id="node-input-maxNodesPerRegisterNodes" placeholder="number" style="max-width:100px">
164
+ </div>
165
+ <div class="form-row">
166
+ <label for="node-input-maxNodesPerNodeManagement" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerNodeManagement</label>
167
+ <input type="number" id="node-input-maxNodesPerNodeManagement" placeholder="number" style="max-width:100px">
168
+ </div>
169
+ <div class="form-row">
170
+ <label for="node-input-maxMonitoredItemsPerCall" style="width:72%;"><i class="icon-tasks"></i> maxMonitoredItemsPerCall</label>
171
+ <input type="number" id="node-input-maxMonitoredItemsPerCall" placeholder="number" style="max-width:100px">
172
+ </div>
173
+ <div class="form-row">
174
+ <label for="node-input-maxNodesPerHistoryUpdateEvents" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerHistoryUpdateEvents</label>
175
+ <input type="number" id="node-input-maxNodesPerHistoryUpdateEvents" placeholder="number" style="max-width:100px">
176
+ </div>
177
+ <div class="form-row">
178
+ <label for="node-input-maxNodesPerTranslateBrowsePathsToNodeIds" style="width:72%;"><i class="icon-tasks"></i> maxNodesPerTranslateBrowsePathsToNodeIds</label>
179
+ <input type="number" id="node-input-maxNodesPerTranslateBrowsePathsToNodeIds" placeholder="number" style="max-width:100px">
180
+ </div>
181
+ <div class="form-row">
182
+ <label for="node-input-maxConnectionsPerEndpoint" style="width:72%;"><i class="icon-tasks"></i> maxConnectionsPerEndpoint</label>
183
+ <input type="number" id="node-input-maxConnectionsPerEndpoint" placeholder="number" style="max-width:100px">
184
+ </div>
185
+ <div class="form-row">
186
+ <label for="node-input-maxMessageSize" style="width:72%;"><i class="icon-tasks"></i> maxMessageSize</label>
187
+ <input type="number" id="node-input-maxMessageSize" placeholder="4096" style="max-width:100px">
188
+ </div>
189
+ <div class="form-row">
190
+ <label for="node-input-maxBufferSize" style="width:72%;"><i class="icon-tasks"></i> maxBufferSize</label>
191
+ <input type="number" id="node-input-maxBufferSize" placeholder="4096" style="max-width:100px">
192
+ </div>
193
+ <div class="form-row">
194
+ <label for="node-input-maxSessions" style="width:72%;"><i class="icon-tasks"></i> maxSessions</label>
195
+ <input type="number" id="node-input-maxSessions" style="max-width:100px">
196
+ </div>
197
+ </script>
198
+
199
+ <script type="text/x-red" data-help-name="OpcUa-Server">
200
+ <p>Creates OPC UA server with own variables, object structures and methods to endpoint: opc.tcp://localhost:PORT/ResourcePath/</p>
201
+ <p>Parameters PORT and ResourcePath can be given for the server.</p>
202
+ <p>File that contains username, password and role.</p>
203
+ <p>Register to local Discover Server, if true => OPC UA Server will register itself to opc.tcp://localhost:4840</p>
204
+ <p>ConstructDefaultAddressSpace, if false then Server AddressSpace will be empty (no VendorName and sub objects)<p>
205
+ <p>Server active endpoints from security mode and policy:</p>
206
+ <p>Security mode: None Sign SignAndEncrypt<p>
207
+ <p>Security policy: Basic128-Rsa15 | Basic256 | Basic128-Sha256<p>
208
+ <p>maxSessions: Maximum number of sessions allowed by the server, default 20. Changing might impact performance.<p>
209
+ <p>
210
+ OPC UA server commands:
211
+ <ul>
212
+ <li><b>restartOPCUAServer</b></li>
213
+ <li><b>addEquipment</b></li>
214
+ <li><b>addPhysicalAsset</b></li>
215
+ <li><b>setFolder</b> msg.topic = "folderName" // Example topic format ns=1;s=FolderName (note: uses this as parentFolder)</li>
216
+ <li><b>addFolder</b> msg.topic = "ns=1;s=NewFolder" // Note parent folder is objects if not set by setFolder, newFolder is set to parentFolder</li>
217
+ <li><b>addVariable</b> msg.topic = "ns=1;s=VariableName;datatype=Double" // parent folder is set above</li>
218
+ <li><b>installHistorian</b> msg.topic = "ns=1;s=VariableName;datatype=Double</li>
219
+ <li><b>installDiscreteAlarm</b> msg.topic = "ns=1;s=VariableName;datatype=Double" parentObject msg.alarmText for the alarm, msg.priority for alarm severity</li>
220
+ <li><b>installLimitAlarm</b> msg.topic = "ns=1;s=VariableName;datatype=Double" parentObject msg.hh=highhighLimit, msg.h=highLimit, msg.l=lowLimit, msg.ll=lowlowLimit</li>
221
+ <li><b>addExtensionObject</b> msg.topic = "ns=1;s=VariableName;datatype=ExtensionObject;TypeId=ns=3;i=1001</li>
222
+ <li><b>deleteNode</b> msg.payload = "ns=1;s=VariableName"</li>
223
+ <li><b>registerNamespace</b> msg.topic = "www.acme.com" output msg.payload = ns=index </li>
224
+ <li><b>getNamespaceIndex</b> msg.topic = "www.acme.com" output msg.payload = ns=index </li>
225
+ <li><b>getNamespaces</b> output msg.payload = { nsuri1: 1, nsuri2: 2, ... }</li>
226
+ <li><b>setUsers</b> msg.topic = "" msg.users JSON structure of users (username, password role)</li>
227
+ <li><b>addFile</b> msg.topic = "ns=1;s=test.txt" // Note parent folder is objects if not set by setFolder/addFolder</li>
228
+ <li><b>saveAddressSpace</b> msg.filename ="./test.xml" // Saves current AddressSpace into the given filename. If msg.topic used, it should contain namespace index that will be saved. </li>
229
+ <li><b>loadAddressSpace</b> msg.filename ="./test.xml" // Load AddressSpace from the given filename.</li>
230
+ <li><b>bindVariables</b> Bind same node.send(msg) callbacks to get/set methods as addVariable</li>
231
+ <li><b>bindMethod</b> msg.topic = nodeId, msg.code can be given in function node that contains method function</li>
232
+ </ul>
233
+
234
+ Examples JSON Injects: <br />
235
+ <pre>
236
+ msg.payload = { "opcuaCommand": "addEquipment", "nodeName": "Machine" }
237
+ </pre>
238
+ <pre>
239
+ { "opcuaCommand": "restartOPCUAServer" }
240
+ { "opcuaCommand": "addEquipment", "nodeName": "Machine" }
241
+ { "opcuaCommand": "addPhysicalAsset", "nodeName": "PhysicalAsset" }
242
+ { "opcuaCommand": "deleteNode", "nodeId": "ns=4;s=PhysicalAsset2" }
243
+ </pre>
244
+ <pre>
245
+ msg.payload = { "opcuaCommand": "addFile", "fileName": "c:/temp/test.txt" }
246
+ </pre>
247
+ </p>
248
+ <p>
249
+ OPC UA message type to set variable Counter by JSON Inject
250
+ <pre>
251
+ { payload : { "messageType" : "Variable", "namespace" : "1", "variableName": "Counter", "variableValue": msg.payload }};
252
+ </pre>
253
+ </p>
254
+ <p>
255
+ Server will send message as client will connect or disconnect.<br>
256
+ Topic: Client-connected or Client-disconnected, payload: session name (depends on client implementation)
257
+ </p>
258
+ <p>
259
+ Server operation limits can be set by node UI dialog.
260
+ </p>
261
+ </script>