@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,223 @@
1
+ <!--
2
+
3
+ Copyright 2022 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-Rights', {
21
+ category: "opcua",
22
+ color:"#3FADB5",
23
+ defaults: {
24
+ accessLevelCurrentRead: {value: true},
25
+ accessLevelCurrentWrite: {value: true},
26
+ accessLevelStatusWrite: {value: true},
27
+ accessLevelHistoryRead: {value: true},
28
+ accessLevelHistoryWrite: {value: true},
29
+ accessLevelSemanticChange: {value: true},
30
+ role: {value: "a"}, // User Role like Anonymous, Operator, Engineer,...
31
+ // Permissions
32
+ permissionBrowse: {value: true},
33
+ permissionRead: {value: true},
34
+ permissionWrite: {value: true},
35
+ permissionWriteAttribute: {value: true},
36
+ permissionReadRole: {value: true},
37
+ permissionWriteRole: {value: true},
38
+ permissionReadHistory: {value: true},
39
+ permissionWriteHistory: {value: true},
40
+ permissionInsertHistory: {value: true},
41
+ permissionModifyHistory: {value: true},
42
+ permissionDeleteHistory: {value: true},
43
+ permissionReceiveEvents: {value: true},
44
+ permissionCall: {value: true},
45
+ permissionAddReference: {value: true},
46
+ permissionRemoveReference: {value: true},
47
+ permissionDeleteNode: {value: true},
48
+ permissionAddNode: {value: true},
49
+ name: {value: ""},
50
+ },
51
+ inputs: 1,
52
+ outputs: 1,
53
+ align: "right",
54
+ icon: "opcuanodeLogo.png",
55
+ label: function () {
56
+ return this.name || "OPC UA Rights";
57
+ },
58
+ labelStyle: function () {
59
+ return this.name ? "node_label_italic" : "";
60
+ }
61
+ });
62
+ </script>
63
+
64
+ <script type="text/x-red" data-template-name="OpcUa-Rights">
65
+ <div class="form-row">
66
+ <label for="node-input-accessLevelCurrentRead" style="width:72%;"><i class="icon-tasks"></i> Access level: read</label>
67
+ <input type="checkbox" id="node-input-accessLevelCurrentRead" style="max-width:20px">
68
+ </div>
69
+ <div class="form-row">
70
+ <label for="node-input-accessLevelCurrentWrite" style="width:72%;"><i class="icon-tasks"></i> Access level: write</label>
71
+ <input type="checkbox" id="node-input-accessLevelCurrentWrite" style="max-width:20px">
72
+ </div>
73
+ <div class="form-row">
74
+ <label for="node-input-accessLevelStatusWrite" style="width:72%;"><i class="icon-tasks"></i> Access level: status write</label>
75
+ <input type="checkbox" id="node-input-accessLevelStatusWrite" style="max-width:20px">
76
+ </div>
77
+ <div class="form-row">
78
+ <label for="node-input-accessLevelHistoryRead" style="width:72%;"><i class="icon-tasks"></i> Access level: history read</label>
79
+ <input type="checkbox" id="node-input-accessLevelHistoryRead" style="max-width:20px">
80
+ </div>
81
+ <div class="form-row">
82
+ <label for="node-input-accessLevelHistoryWrite" style="width:72%;"><i class="icon-tasks"></i> Access level: history write</label>
83
+ <input type="checkbox" id="node-input-accessLevelHistoryWrite" style="max-width:20px">
84
+ </div>
85
+ <div class="form-row">
86
+ <label for="node-input-accessLevelSemanticChange" style="width:72%;"><i class="icon-tasks"></i> Access level: semantic change</label>
87
+ <input type="checkbox" id="node-input-accessLevelSemanticChange" style="max-width:20px">
88
+ </div>
89
+ <hr>
90
+ <div class="form-row">
91
+ <label for="node-input-role"><i class="icon-time"></i> User role</label>
92
+ <select type="text" id="node-input-role" style="max-width:160px">
93
+ <option value="a">Anonymous</option>
94
+ <option value="u">Authenticated user</option>
95
+ <option value="b">Observer</option>
96
+ <option value="e">Engineer</option>
97
+ <option value="o">Operator</option>
98
+ <option value="c">Configure admin</option>
99
+ <option value="s">Security admin</option>
100
+ <option value="v">Supervisor</option>
101
+ </select>
102
+ </div>
103
+ <div class="form-row">
104
+ <label for="node-input-permissionBrowse" style="width:72%;"><i class="icon-tasks"></i> Permission: browse</label>
105
+ <input type="checkbox" id="node-input-permissionBrowse" style="max-width:20px">
106
+ </div>
107
+ <div class="form-row">
108
+ <label for="node-input-permissionRead" style="width:72%;"><i class="icon-tasks"></i> Permission: read</label>
109
+ <input type="checkbox" id="node-input-permissionRead" style="max-width:20px">
110
+ </div>
111
+ <div class="form-row">
112
+ <label for="node-input-permissionWrite" style="width:72%;"><i class="icon-tasks"></i> Permission: write</label>
113
+ <input type="checkbox" id="node-input-permissionWrite" style="max-width:20px">
114
+ </div>
115
+ <div class="form-row">
116
+ <label for="node-input-permissionWriteAttribute" style="width:72%;"><i class="icon-tasks"></i> Permission: write attribute</label>
117
+ <input type="checkbox" id="node-input-permissionWriteAttribute" style="max-width:20px">
118
+ </div>
119
+ <div class="form-row">
120
+ <label for="node-input-permissionReadRole" style="width:72%;"><i class="icon-tasks"></i> Permission: read role</label>
121
+ <input type="checkbox" id="node-input-permissionReadRole" style="max-width:20px">
122
+ </div>
123
+ <div class="form-row">
124
+ <label for="node-input-permissionWriteRole" style="width:72%;"><i class="icon-tasks"></i> Permission: write role</label>
125
+ <input type="checkbox" id="node-input-permissionWriteRole" style="max-width:20px">
126
+ </div>
127
+ <div class="form-row">
128
+ <label for="node-input-permissionReadHistory" style="width:72%;"><i class="icon-tasks"></i> Permission: read history</label>
129
+ <input type="checkbox" id="node-input-permissionReadHistory" style="max-width:20px">
130
+ </div>
131
+ <div class="form-row">
132
+ <label for="node-input-permissionWriteHistory" style="width:72%;"><i class="icon-tasks"></i> Permission: write history</label>
133
+ <input type="checkbox" id="node-input-permissionWriteHistory" style="max-width:20px">
134
+ </div>
135
+ <div class="form-row">
136
+ <label for="node-input-permissionInsertHistory" style="width:72%;"><i class="icon-tasks"></i> Permission: insert history</label>
137
+ <input type="checkbox" id="node-input-permissionInsertHistory" style="max-width:20px">
138
+ </div>
139
+ <div class="form-row">
140
+ <label for="node-input-permissionModifyHistory" style="width:72%;"><i class="icon-tasks"></i> Permission: modify history</label>
141
+ <input type="checkbox" id="node-input-permissionModifyHistory" style="max-width:20px">
142
+ </div>
143
+ <div class="form-row">
144
+ <label for="node-input-permissionDeleteHistory" style="width:72%;"><i class="icon-tasks"></i> Permission: delete history</label>
145
+ <input type="checkbox" id="node-input-permissionDeleteHistory" style="max-width:20px">
146
+ </div>
147
+ <div class="form-row">
148
+ <label for="node-input-permissionReceiveEvents" style="width:72%;"><i class="icon-tasks"></i> Permission: receive events</label>
149
+ <input type="checkbox" id="node-input-permissionReceiveEvents" style="max-width:20px">
150
+ </div>
151
+ <div class="form-row">
152
+ <label for="node-input-permissionCall" style="width:72%;"><i class="icon-tasks"></i> Permission: call methods</label>
153
+ <input type="checkbox" id="node-input-permissionCall" style="max-width:20px">
154
+ </div>
155
+ <div class="form-row">
156
+ <label for="node-input-permissionAddReference" style="width:72%;"><i class="icon-tasks"></i> Permission: add reference</label>
157
+ <input type="checkbox" id="node-input-permissionAddReference" style="max-width:20px">
158
+ </div>
159
+ <div class="form-row">
160
+ <label for="node-input-permissionRemoveReference" style="width:72%;"><i class="icon-tasks"></i> Permission: remove reference</label>
161
+ <input type="checkbox" id="node-input-permissionRemoveReference" style="max-width:20px">
162
+ </div>
163
+ <div class="form-row">
164
+ <label for="node-input-permissionDeleteNode" style="width:72%;"><i class="icon-tasks"></i> Permission: delete node</label>
165
+ <input type="checkbox" id="node-input-permissionDeleteNode" style="max-width:20px">
166
+ </div>
167
+ <div class="form-row">
168
+ <label for="node-input-permissionAddNode" style="width:72%;"><i class="icon-tasks"></i> Permission: add node</label>
169
+ <input type="checkbox" id="node-input-permissionAddNode" style="max-width:20px">
170
+ </div>
171
+ <hr>
172
+ <div class="form-row">
173
+ <label for="node-input-name"><i class="icon-tag"></i>Name</label>
174
+ <input type="text" id="node-input-name" placeholder="">
175
+ </div>
176
+ </script>
177
+
178
+ <script type="text/x-red" data-help-name="OpcUa-Rights">
179
+ <p>Set object / variable access level, user access level and permissions</p>
180
+ <h2>Access rights</h2>
181
+ <h3>Access level parameters inside node</h3>
182
+ <ul>
183
+ <li>CurrentRead
184
+ <li>CurrentWrite
185
+ <li>StatusWrite
186
+ <li>HistoryRead
187
+ <li>HistoryWrite
188
+ <li>SemanticChange
189
+ </ul>
190
+ <h2>User role, only well known roles available</h2>
191
+ <ul>
192
+ <li>Anonymous
193
+ <li>Authenticated user; username & password
194
+ <li>Observer
195
+ <li>Engineer
196
+ <li>Operator
197
+ <li>Configure admin
198
+ <li>Security admin
199
+ <li>Supervisor
200
+ </ul>
201
+ <h3>Permissions</h3>
202
+ <ul>
203
+ <li>Browse
204
+ <li>Read
205
+ <li>Write
206
+ <li>Write attribute
207
+ <li>Read role
208
+ <li>Write role
209
+ <li>Read history
210
+ <li>Write history
211
+ <li>Insert history
212
+ <li>Modify history
213
+ <li>Delete history
214
+ <li>Receive events
215
+ <li>Call methods
216
+ <li>Add reference
217
+ <li>Remove reference
218
+ <li>Delete node
219
+ <li>Add node
220
+ </ul>
221
+ <strong>Name</strong>
222
+ <p>Name in the flow of Node-RED.</p>
223
+ </script>
@@ -0,0 +1,156 @@
1
+ /**
2
+
3
+ Copyright 2022 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
+ 'use strict'
20
+
21
+ // const { WellKnownRoles } = require("node-opcua");
22
+
23
+ /**
24
+ * OPC UA rights node representation for Node-RED to add msg object OPC UA access rights, role and permissions
25
+ *
26
+ * @param RED
27
+ */
28
+ module.exports = function (RED) {
29
+ var opcua = require('node-opcua');
30
+ const chalk = require("chalk");
31
+ function OPCUARightsNode(n) {
32
+ RED.nodes.createNode(this, n)
33
+ this.name = n.name;
34
+ this.accessLevelCurrentRead = n.accessLevelCurrentRead;
35
+ this.accessLevelCurrentWrite = n.accessLevelCurrentWrite;
36
+ this.accessLevelStatusWrite = n.accessLevelStatusWrite;
37
+ this.accessLevelHistoryRead = n.accessLevelHistoryRead;
38
+ this.accessLevelHistoryWrite = n.accessLevelHistoryWrite;
39
+ this.accessLevelSemanticChange = n.accessLevelSemanticChange;
40
+ this.role = n.role;
41
+ // TODO Permissions
42
+ this.permissionBrowse = n.permissionBrowse;
43
+ this.permissionRead = n.permissionRead;
44
+ this.permissionWrite = n.permissionWrite;
45
+ this.permissionWriteAttribute = n.permissionWriteAttribute;
46
+ this.permissionReadRole = n.permissionReadRole;
47
+ this.permissionWriteRole = n.permissionWriteRole;
48
+ this.permissionReadHistory = n.permissionReadHistory;
49
+ this.permissionWriteHistory = n.permissionWriteHistory;
50
+ this.permissionInsertHistory = n.permissionInsertHistory;
51
+ this.permissionModifyHistory = n.permissionModifyHistory;
52
+ this.permissionDeleteHistory = n.permissionDeleteHistory;
53
+ this.permissionReceiveEvents = n.permissionReceiveEvents;
54
+ this.permissionCall = n.permissionCall;
55
+ this.permissionAddReference = n.permissionAddReference;
56
+ this.permissionRemoveReference = n.permissionRemoveReference;
57
+ this.permissionDeleteNode = n.permissionDeleteNode;
58
+ this.permissionAddNode = n.permissionAddNode;
59
+ var node = this;
60
+
61
+ node.debug(chalk.yellow("Node parameters: ") + chalk.cyan(JSON.stringify(node)));
62
+
63
+ node.on("input", function (msg) {
64
+ // This node will extend new field to msg so addVariable can set needed access level and permissions
65
+ // From the selected values
66
+ // TODO
67
+ var levelString = "";
68
+ if (node.accessLevelCurrentRead === true) levelString += "CurrentRead |";
69
+ if (node.accessLevelCurrentWrite === true) levelString += " CurrentWrite |";
70
+ if (node.accessLevelStatusWrite === true) levelString += " StatusWrite |";
71
+ if (node.accessLevelHistoryRead === true) levelString += " HistoryRead |";
72
+ if (node.accessLevelHistoryWrite === true) levelString += " HistoryWrite |";
73
+ if (node.accessLevelSemanticChange === true) levelString += " SemanticChange";
74
+ console.log("Access level string: " + levelString);
75
+ var accessLevel = opcua.makeAccessLevelFlag(levelString);
76
+ var userAccessLevel = opcua.makeAccessLevelFlag(levelString);
77
+ // var accessLevel = opcua.makeAccessLevelFlag("CurrentRead | CurrentWrite | StatusWrite | HistoryRead | HistoryWrite | SemanticChange");
78
+ // var userAccessLevel = opcua.makeAccessLevelFlag("CurrentRead | CurrentWrite | StatusWrite | HistoryRead | HistoryWrite | SemanticChange");
79
+ msg.accessLevel = accessLevel;
80
+ msg.userAccessLevel = userAccessLevel; // Uses same, TODO add option to select which one to use
81
+ msg.accessRestrictions = opcua.AccessRestrictionsFlag.None; // TODO extend when needed
82
+ console.log("Access level: " + msg.accessLevel + " user access level: " + msg.userAccessLevel + " restrictions: " + msg.accessRestrictions);
83
+
84
+ // TODO node.role == "a" Anonymous etc.
85
+ let role;
86
+ if (node.role === "a") {
87
+ role = opcua.WellKnownRoles.Anonymous;
88
+ }
89
+ if (node.role === "u") {
90
+ role = opcua.WellKnownRoles.AuthenticatedUser;
91
+ }
92
+ if (node.role === "e") {
93
+ role = opcua.WellKnownRoles.Engineer;
94
+ }
95
+ if (node.role === "b") {
96
+ role = opcua.WellKnownRoles.Observer;
97
+ }
98
+ if (node.role === "o") {
99
+ role = opcua.WellKnownRoles.Operator;
100
+ }
101
+ if (node.role === "c") {
102
+ role = opcua.WellKnownRoles.ConfigureAdmin;
103
+ }
104
+ if (node.role === "s") {
105
+ role = opcua.WellKnownRoles.SecurityAdmin;
106
+ }
107
+ if (node.role === "v") {
108
+ role = opcua.WellKnownRoles.Supervisor;
109
+ }
110
+ console.log("Role: " + role + " selection was " + node.role);
111
+
112
+ // Collect multiple role permissions together
113
+ let permissionString = "";
114
+ if (node.permissionBrowse === true) permissionString += "Browse |";
115
+ if (node.permissionRead === true) permissionString += " Read |";
116
+ if (node.permissionWrite === true) permissionString += " Write |";
117
+ if (node.permissionWriteAttribute === true) permissionString += " WriteAttribute |";
118
+ if (node.permissionReadRole === true) permissionString += " ReadRolePermissions |";
119
+ if (node.permissionWriteRole === true) permissionString += " WriteRolePermissions |";
120
+ if (node.permissionReadHistory === true) permissionString += " ReadHistory |";
121
+ if (node.permissionWriteHistory === true) permissionString += " WriteHistorizing |";
122
+ if (node.permissionInsertHistory === true) permissionString += " InsertHistory |";
123
+ if (node.permissionModifyHistory === true) permissionString += " ModifyHistory |";
124
+ if (node.permissionDeleteHistory === true) permissionString += " DeleteHistory |";
125
+ if (node.permissionReceiveEvents === true) permissionString += " ReceiveEvents |";
126
+ if (node.permissionCall === true) permissionString += " Call |";
127
+ if (node.permissionAddReference === true) permissionString += " AddReference |";
128
+ if (node.permissionRemoveReference === true) permissionString += " RemoveReference |";
129
+ if (node.permissionDeleteNode === true) permissionString += " DeleteNode |";
130
+ if (node.permissionAddNode === true) permissionString += " AddNode";
131
+ console.log("Permission string: " + permissionString);
132
+ const permissionFlag = opcua. makePermissionFlag(permissionString);
133
+ console.log("Permission flag: " + permissionFlag);
134
+ if (msg.permissions && Array.isArray(msg.permissions)) {
135
+ var merged = msg.permissions.concat([{ roleId: role, permissions: permissionFlag }]);
136
+ console.log("Concatenated permissions: " + JSON.stringify(merged));
137
+ msg.permissions = merged;
138
+ // msg.permissions.concat([{ roleId: opcua.WellKnownRoles.Anonymous, permissions: opcua.allPermissions }]);
139
+ }
140
+ else {
141
+ // Current node
142
+ msg.permissions = [{ roleId: role, permissions: permissionFlag }];
143
+ }
144
+ console.log("Permissions: " + JSON.stringify(msg.permissions));
145
+
146
+ node.send(msg);
147
+ });
148
+
149
+ node.on("close", function () {
150
+ console.log("Closed");
151
+ });
152
+
153
+ }
154
+
155
+ RED.nodes.registerType("OpcUa-Rights", OPCUARightsNode);
156
+ }
@@ -0,0 +1,51 @@
1
+ <!--
2
+
3
+ Copyright 2023 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-Discovery',{
21
+ category: 'opcua',
22
+ color:"#3FADB5",
23
+ defaults: {
24
+ name: {value:""}
25
+ },
26
+ inputs:1,
27
+ outputs:1,
28
+ align: "right",
29
+ icon: "opcuanodeLogo.png",
30
+ label: function() {
31
+ return this.name || "OPC UA Discovery";
32
+ },
33
+ labelStyle: function() {
34
+ return this.name?"node_label_italic":"";
35
+ }
36
+ });
37
+ </script>
38
+
39
+ <script type="text/x-red" data-template-name="OpcUa-Discovery">
40
+ <div class="form-row">
41
+ <label for="node-input-name"><i class="icon-tag"></i> Name</label>
42
+ <input type="text" id="node-input-name" placeholder="">
43
+ </div>
44
+ </script>
45
+
46
+ <script type="text/x-red" data-help-name="OpcUa-Discovery">
47
+ <p>OPC UA Discovery server for the OPC UA Servers to register themselves.</p>
48
+ <p>UAExpert and other OPC UA Clients can look available servers from the discovery server.</p>
49
+ <p>NOTE: You can check port status on Windows with command: netstat -ano | findstr :4840</p>
50
+ <p> UaExpert can be listening port and then you will get error message: 'port is in use'</p>
51
+ </script>
@@ -0,0 +1,180 @@
1
+ /**
2
+
3
+ Copyright 2023 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
+ 'use strict'
20
+
21
+
22
+ /**
23
+ * OPC UA Discovery server uses default port 4840 for the discovery
24
+ *
25
+ * @param RED
26
+ */
27
+ module.exports = function (RED) {
28
+ const opcua = require('node-opcua');
29
+ const utils = require("./utils");
30
+ const path = require('path');
31
+ const os = require('os');
32
+ const chalk = require("chalk");
33
+
34
+ function OPCUADiscoveryNode(n) {
35
+ RED.nodes.createNode(this, n)
36
+ this.name = n.name;
37
+ var node = this;
38
+ var xmlFiles = [path.join(__dirname, 'public/vendor/opc-foundation/xml/Opc.Ua.NodeSet2.xml')]; // Standard & basic types
39
+
40
+ const certificateManager = new opcua.OPCUACertificateManager({
41
+ rootFolder: path.join(path.dirname(__dirname), "./Discovery"), // Own PKI storage for discovery LDS certificates
42
+ automaticallyAcceptUnknownCertificate: true // TODO implement configuration / argument option to turn this on/off
43
+ });
44
+
45
+ const server_options = {
46
+ port: 4840,
47
+ // resourcePath: "UADiscovery", // Do not use this, most of servers / client expect discovery is on port 4840 directly
48
+ nodeset_filename: xmlFiles,
49
+ buildInfo: {
50
+ buildNumber: "",
51
+ buildDate: ""
52
+ },
53
+ serverCapabilities: {
54
+ maxBrowseContinuationPoints: 10,
55
+ maxHistoryContinuationPoints: 10,
56
+ maxSessions: 20
57
+ },
58
+ serverInfo: {
59
+ applicationUri: opcua.makeApplicationUrn(os.hostname(), "Node-Red-OPCUA-Discovery"),
60
+ productUri: "Node-Red-OPCUA-Discovery",
61
+ applicationName: {
62
+ text: "Node-Red-OPCUA-Discovery",
63
+ locale: "en"
64
+ },
65
+ gatewayServerUri: null,
66
+ discoveryProfileUri: null,
67
+ discoveryUrls: []
68
+ }
69
+ };
70
+
71
+ server_options.buildInfo = {
72
+ buildNumber: "0.2.300",
73
+ buildDate: "2023-03-13T16:30:00"
74
+ };
75
+ const server = new opcua.OPCUADiscoveryServer(server_options);
76
+ const hostname = os.hostname();
77
+ node.debug(" server host :" + chalk.cyan(hostname));
78
+ node.debug(" server PID :" + chalk.cyan(process.pid));
79
+ (async () => {
80
+ try {
81
+ await certificateManager.initialize();
82
+ await server.start(function (err) {
83
+ if (err) {
84
+ node.status({
85
+ fill: "red",
86
+ shape: "ring",
87
+ text: "Not running, error: " + err
88
+ });
89
+ node.error("Server failed to start... error: ", err);
90
+ node.error("In Windows you can check port status with command: netstat -ano | findstr :4840");
91
+ node.error("UaExpert can be running and listening port");
92
+ // process.exit(-3);
93
+ return;
94
+ }
95
+ node.debug(" server on port :" + chalk.cyan(server.endpoints[0].port.toString()));
96
+ node.debug(" serverInfo :");
97
+ node.debug(chalk.cyan(JSON.stringify(server.serverInfo)));
98
+ node.debug("Discovery server now waiting for server register calls. CTRL+C to stop");
99
+ node.status({
100
+ fill: "green",
101
+ shape: "dot",
102
+ text: "Discovery on port: " + server.endpoints[0].port.toString()
103
+ });
104
+
105
+ server.on("response", (response) => {
106
+ node.debug(
107
+ // "Time: ", response.responseHeader.timestamp, " handle: ", response.responseHeader.requestHandle,
108
+ // Show messages
109
+ " request: " + response.schema.name +
110
+ " status: " + response.responseHeader.serviceResult.toString()
111
+ );
112
+ });
113
+
114
+ server.on(
115
+ "request",
116
+ (request, channel) => {
117
+ node.debug(
118
+ // "Time: ", request.requestHeader.timestamp,
119
+ // " handle: ", request.requestHeader.requestHandle,
120
+ " request: " + request.schema.name,
121
+ // " channel ID: ", channel.channelId.toString()
122
+ );
123
+ }
124
+ );
125
+ });
126
+ } catch (err) {
127
+ node.error("Cannot start server, error: ", err);
128
+ return;
129
+ }
130
+ })();
131
+
132
+ // List servers registered to discovery
133
+ node.on("input", function (msg) {
134
+ const discovery_server_endpointUrl = "opc.tcp://localhost:4840";
135
+ const allservers = [];
136
+ node.debug("Interrogating ", discovery_server_endpointUrl);
137
+ (async () => {
138
+ try {
139
+ const { servers, endpoints } = await opcua.findServers(discovery_server_endpointUrl);
140
+ // Servers on network
141
+ node.debug("--------------------------------------------------------------");
142
+ for (const server of servers) {
143
+ node.debug(" applicationUri:", chalk.cyan.bold(server.applicationUri));
144
+ node.debug(" productUri:", chalk.cyan.bold(server.productUri));
145
+ node.debug(" applicationName:", chalk.cyan.bold(server.applicationName.text));
146
+ // node.debug(" type:", chalk.cyan.bold(ApplicationType[server.applicationType]));
147
+ node.debug(" gatewayServerUri:", server.gatewayServerUri ? chalk.cyan.bold(server.gatewayServerUri) : "");
148
+ node.debug("discoveryProfileUri:", server.discoveryProfileUri ? chalk.cyan.bold(server.discoveryProfileUri) : "");
149
+ node.debug(" discoveryUrls:");
150
+ for (const discoveryUrl of server.discoveryUrls) {
151
+ node.debug(" " + chalk.cyan.bold(discoveryUrl));
152
+ allservers.push(discoveryUrl);
153
+ }
154
+ node.debug("--------------------------------------------------------------");
155
+ }
156
+ // Registered server endpoints
157
+ for (const endpoint of endpoints) {
158
+ node.debug(endpoint.endpointUrl.toString(), endpoint.securityLevel, endpoint.securityPolicyUri, endpoint.securityMode);
159
+ // allservers.push(endpoint);
160
+ }
161
+ // node.debug("Registered servers: " + JSON.stringify(allservers));
162
+ msg.payload = allservers;
163
+ node.send(msg);
164
+ } catch (err) {
165
+ node.debug("err ", err.message);
166
+ // process.exit(-2);
167
+ return;
168
+ }
169
+ })();
170
+ });
171
+
172
+ node.on("close", function () {
173
+ server.shutdown(() => {
174
+ node.debug(" shutting down completed ");
175
+ });
176
+ });
177
+ }
178
+
179
+ RED.nodes.registerType("OpcUa-Discovery", OPCUADiscoveryNode);
180
+ }
@@ -0,0 +1,55 @@
1
+ const path = require("path");
2
+ const fs = require("fs");
3
+ const { crypto_utils } = require("node-opcua");
4
+
5
+ exports.dumpCertificates = async function dumpCertificates(client) {
6
+
7
+
8
+ try {
9
+
10
+ const endpoints = await client.getEndpoints();
11
+ var i = 0;
12
+ endpoints.forEach(function (endpoint, i) {
13
+ /*
14
+ verbose_log("endpoint " + endpoint.endpointUrl + "");
15
+ verbose_log("Application URI " + endpoint.server.applicationUri);
16
+ verbose_log("Product URI " + endpoint.server.productUri);
17
+ verbose_log("Application Name " + endpoint.server.applicationName.text);
18
+ */
19
+ var applicationName = endpoint.server.applicationName.text;
20
+ if (!applicationName) {
21
+ applicationName = "OPCUA_Server";
22
+ }
23
+ /*
24
+ verbose_log("Security Mode " + endpoint.securityMode.toString());
25
+ verbose_log("securityPolicyUri " + endpoint.securityPolicyUri);
26
+ verbose_log("Type " + endpoint.server.applicationType);
27
+ */
28
+ // verbose_log("certificate " + "..." + " endpoint.serverCertificate");
29
+ endpoint.server.discoveryUrls = endpoint.server.discoveryUrls || [];
30
+ // verbose_log("discoveryUrls " + endpoint.server.discoveryUrls.join(" - "));
31
+ serverCertificate = endpoint.serverCertificate;
32
+ // Use applicationName instead of fixed server_certificate
33
+ var certificate_filename = path.join(__dirname, "../../PKI/" + applicationName + i + ".pem");
34
+ if (serverCertificate) {
35
+ fs.writeFileSync(certificate_filename, crypto_utils.toPem(serverCertificate, "CERTIFICATE"));
36
+ }
37
+ });
38
+
39
+ endpoints.forEach(function (endpoint) {
40
+ // verbose_log("Identify Token for : Security Mode= " + endpoint.securityMode.toString(), " Policy=", endpoint.securityPolicyUri);
41
+ endpoint.userIdentityTokens.forEach(function (token) {
42
+ /*
43
+ verbose_log("policyId " + token.policyId);
44
+ verbose_log("tokenType " + token.tokenType.toString());
45
+ verbose_log("issuedTokenType " + token.issuedTokenType);
46
+ verbose_log("issuerEndpointUrl " + token.issuerEndpointUrl);
47
+ verbose_log("securityPolicyUri " + token.securityPolicyUri);
48
+ */
49
+ });
50
+ });
51
+ } catch(err) {
52
+ console.log(err);
53
+ }
54
+
55
+ }
Binary file
Binary file