@vitormnm/node-red-simple-opcua 1.4.3 → 1.5.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 (32) hide show
  1. package/client/icons/opcua.svg +132 -132
  2. package/client/lib/opcua-client-browser.js +368 -330
  3. package/client/lib/opcua-client-method-service.js +88 -88
  4. package/client/lib/opcua-client-read-service.js +15 -15
  5. package/client/lib/opcua-client-subscription-id-service.js +24 -24
  6. package/client/lib/opcua-client-subscription-service.js +170 -170
  7. package/client/lib/opcua-client-write-service.js +146 -146
  8. package/client/opcua-client-config.html +80 -80
  9. package/client/opcua-client-utils.js +12 -11
  10. package/client/opcua-client.html +140 -140
  11. package/client/view/opcua-client.js +1144 -1140
  12. package/icons/opcua.svg +132 -132
  13. package/icons/opcua2.svg +132 -132
  14. package/package.json +3 -3
  15. package/server/icons/opcua.svg +132 -132
  16. package/server/lib/opcua-address-space-alarm.js +341 -341
  17. package/server/lib/opcua-address-space-builder.js +1603 -1485
  18. package/server/lib/opcua-config.js +677 -546
  19. package/server/lib/opcua-constants.js +119 -109
  20. package/server/lib/opcua-server-events-child.js +139 -139
  21. package/server/lib/opcua-server-runtime-child.js +873 -819
  22. package/server/lib/opcua-server-runtime.js +376 -311
  23. package/server/lib/opcua-server-status-child.js +187 -187
  24. package/server/lib/server-node-utils.js +16 -16
  25. package/server/opcua-server-io.html +346 -346
  26. package/server/opcua-server-io.js +497 -496
  27. package/server/opcua-server-registry.js +270 -270
  28. package/server/opcua-server.css +265 -265
  29. package/server/opcua-server.html +155 -1643
  30. package/server/opcua-server.js +24 -13
  31. package/server/view/opcua-server.css +492 -0
  32. package/server/view/opcua-server.js +1435 -0
@@ -1,109 +1,119 @@
1
- "use strict";
2
-
3
- const os = require("os");
4
- const opcua = require("node-opcua");
5
-
6
- const {
7
- OPCUAServer,
8
- Variant,
9
- DataType,
10
- StatusCodes,
11
- SecurityPolicy,
12
- VariantArrayType,
13
- MessageSecurityMode,
14
- UserTokenType,
15
- coerceNodeId ,
16
- } = opcua;
17
-
18
- const DEFAULT_PORT = 4840;
19
- const DEFAULT_SERVER_NAME = "Node-RED OPC UA Server";
20
- const DEFAULT_NAMESPACE_URI = "urn:node-red:opc-ua-server";
21
- const DEFAULT_RESOURCE_PATH = "/";
22
-
23
- const SECURITY_POLICY_MAP = {
24
- None: SecurityPolicy.None,
25
- Basic128Rsa15: SecurityPolicy.Basic128Rsa15,
26
- Basic256: SecurityPolicy.Basic256,
27
- Basic256Sha256: SecurityPolicy.Basic256Sha256,
28
- Aes128_Sha256_RsaOaep: SecurityPolicy.Aes128_Sha256_RsaOaep,
29
- Aes256_Sha256_RsaPss: SecurityPolicy.Aes256_Sha256_RsaPss
30
- };
31
-
32
- const SECURITY_MODE_MAP = {
33
- None: MessageSecurityMode.None,
34
- Sign: MessageSecurityMode.Sign,
35
- SignAndEncrypt: MessageSecurityMode.SignAndEncrypt
36
- };
37
-
38
- const DATA_TYPE_MAP = {
39
- Int16: DataType.Int16,
40
- UInt16: DataType.UInt16,
41
- Int32: DataType.Int32,
42
- UInt32: DataType.UInt32,
43
- Float: DataType.Float,
44
- Boolean: DataType.Boolean,
45
- String: DataType.String,
46
- ByteString : DataType.ByteString,
47
- LocalizedText : DataType.LocalizedText
48
- };
49
-
50
- function normalizePort(port) {
51
- const parsed = Number(port);
52
- if (!Number.isInteger(parsed) || parsed <= 0) {
53
- return DEFAULT_PORT;
54
- }
55
-
56
- return parsed;
57
- }
58
-
59
- function buildApplicationUri(serverName) {
60
- const host = os.hostname() || "localhost";
61
- return "urn:" + host + ":node-red:" + sanitizeUriSegment(serverName);
62
- }
63
-
64
- function sanitizeUriSegment(value) {
65
- return String(value || "opc-ua-server")
66
- .trim()
67
- .replace(/\s+/g, "-")
68
- .replace(/[^a-zA-Z0-9:_-]/g, "")
69
- .toLowerCase();
70
- }
71
-
72
- function sanitizeNodeIdPath(path) {
73
- return String(path || "")
74
- .split(".")
75
- .map((segment) => sanitizeNodeIdSegment(segment))
76
- .filter((segment) => segment !== "")
77
- .join(".");
78
- }
79
-
80
- function sanitizeNodeIdSegment(segment) {
81
- const normalized = String(segment || "")
82
- .trim()
83
- .replace(/\s+/g, "_")
84
- .replace(/[^a-zA-Z0-9._-]/g, "_");
85
-
86
- return normalized || "item";
87
- }
88
-
89
- module.exports = {
90
- OPCUAServer,
91
- Variant,
92
- DataType,
93
- StatusCodes,
94
- VariantArrayType,
95
- SecurityPolicy,
96
- MessageSecurityMode,
97
- UserTokenType,
98
- coerceNodeId,
99
- DEFAULT_PORT,
100
- DEFAULT_SERVER_NAME,
101
- DEFAULT_NAMESPACE_URI,
102
- DEFAULT_RESOURCE_PATH,
103
- SECURITY_POLICY_MAP,
104
- SECURITY_MODE_MAP,
105
- DATA_TYPE_MAP,
106
- normalizePort,
107
- buildApplicationUri,
108
- sanitizeNodeIdPath
109
- };
1
+ "use strict";
2
+
3
+ const os = require("os");
4
+ const opcua = require("node-opcua");
5
+
6
+ const {
7
+ OPCUAServer,
8
+ Variant,
9
+ DataType,
10
+ StatusCodes,
11
+ SecurityPolicy,
12
+ VariantArrayType,
13
+ MessageSecurityMode,
14
+ UserTokenType,
15
+ coerceNodeId ,
16
+ resolveNodeId,
17
+ PermissionType,
18
+ makeRoles,
19
+ WellKnownRoles,
20
+ OPCUACertificateManager,
21
+ } = opcua;
22
+
23
+ const DEFAULT_PORT = 4840;
24
+ const DEFAULT_SERVER_NAME = "Node-RED OPC UA Server";
25
+ const DEFAULT_NAMESPACE_URI = "urn:node-red:opc-ua-server";
26
+ const DEFAULT_RESOURCE_PATH = "/";
27
+
28
+ const SECURITY_POLICY_MAP = {
29
+ None: SecurityPolicy.None,
30
+ Basic128Rsa15: SecurityPolicy.Basic128Rsa15,
31
+ Basic256: SecurityPolicy.Basic256,
32
+ Basic256Sha256: SecurityPolicy.Basic256Sha256,
33
+ Aes128_Sha256_RsaOaep: SecurityPolicy.Aes128_Sha256_RsaOaep,
34
+ Aes256_Sha256_RsaPss: SecurityPolicy.Aes256_Sha256_RsaPss
35
+ };
36
+
37
+ const SECURITY_MODE_MAP = {
38
+ None: MessageSecurityMode.None,
39
+ Sign: MessageSecurityMode.Sign,
40
+ SignAndEncrypt: MessageSecurityMode.SignAndEncrypt
41
+ };
42
+
43
+ const DATA_TYPE_MAP = {
44
+ Int16: DataType.Int16,
45
+ UInt16: DataType.UInt16,
46
+ Int32: DataType.Int32,
47
+ UInt32: DataType.UInt32,
48
+ Float: DataType.Float,
49
+ Boolean: DataType.Boolean,
50
+ String: DataType.String,
51
+ ByteString : DataType.ByteString,
52
+ LocalizedText : DataType.LocalizedText
53
+ };
54
+
55
+ function normalizePort(port) {
56
+ const parsed = Number(port);
57
+ if (!Number.isInteger(parsed) || parsed <= 0) {
58
+ return DEFAULT_PORT;
59
+ }
60
+
61
+ return parsed;
62
+ }
63
+
64
+ function buildApplicationUri(serverName) {
65
+ const host = os.hostname() || "localhost";
66
+ return "urn:" + host + ":node-red:" + sanitizeUriSegment(serverName);
67
+ }
68
+
69
+ function sanitizeUriSegment(value) {
70
+ return String(value || "opc-ua-server")
71
+ .trim()
72
+ .replace(/\s+/g, "-")
73
+ .replace(/[^a-zA-Z0-9:_-]/g, "")
74
+ .toLowerCase();
75
+ }
76
+
77
+ function sanitizeNodeIdPath(path) {
78
+ return String(path || "")
79
+ .split(".")
80
+ .map((segment) => sanitizeNodeIdSegment(segment))
81
+ .filter((segment) => segment !== "")
82
+ .join(".");
83
+ }
84
+
85
+ function sanitizeNodeIdSegment(segment) {
86
+ const normalized = String(segment || "")
87
+ .trim()
88
+ .replace(/\s+/g, "_")
89
+ .replace(/[^a-zA-Z0-9._-]/g, "_");
90
+
91
+ return normalized || "item";
92
+ }
93
+
94
+ module.exports = {
95
+ OPCUAServer,
96
+ Variant,
97
+ DataType,
98
+ OPCUACertificateManager,
99
+ StatusCodes,
100
+ VariantArrayType,
101
+ SecurityPolicy,
102
+ MessageSecurityMode,
103
+ UserTokenType,
104
+ coerceNodeId,
105
+ resolveNodeId,
106
+ PermissionType,
107
+ makeRoles,
108
+ WellKnownRoles,
109
+ DEFAULT_PORT,
110
+ DEFAULT_SERVER_NAME,
111
+ DEFAULT_NAMESPACE_URI,
112
+ DEFAULT_RESOURCE_PATH,
113
+ SECURITY_POLICY_MAP,
114
+ SECURITY_MODE_MAP,
115
+ DATA_TYPE_MAP,
116
+ normalizePort,
117
+ buildApplicationUri,
118
+ sanitizeNodeIdPath
119
+ };
@@ -1,140 +1,140 @@
1
- "use strict";
2
-
3
-
4
- const registry = require("../opcua-server-registry");
5
- const { resolveRegisteredServer } = require("./server-node-utils");
6
-
7
-
8
-
9
-
10
- function eventsServer(node, rootNode, nodeId) {
11
-
12
-
13
-
14
- // 🔥 ALTERADO: usar Map para garantir unicidade por nodeID
15
- node.queue = {
16
- read: new Map(),
17
- write: new Map(),
18
- alarm: new Map()
19
- };
20
-
21
- if (node.flushTimer) {
22
- clearInterval(node.flushTimer);
23
- node.flushTimer = null;
24
- }
25
-
26
-
27
- node.flushTimer = setInterval(() => {
28
- flushQueue(node, nodeId);
29
-
30
- }, rootNode.intervalMs);
31
-
32
- ///rootNode.intervalMs
33
- node.enqueueAccessEvent = function (event) {
34
- if (!matchesServer(node.serverRef, event)) {
35
-
36
- }
37
-
38
- if (event.operation === "read") {
39
- upsertEvent(node.queue.read, event);
40
-
41
- }
42
-
43
- if (event.operation === "write") {
44
- upsertEvent(node.queue.write, event);
45
- }
46
-
47
- if (event.operation === "alarm") {
48
- upsertEvent(node.queue.alarm, event);
49
- }
50
- };
51
-
52
- registry.registerAccessListener(node.id, node);
53
- }
54
-
55
-
56
-
57
-
58
-
59
- function flushQueue(node, nodeId) {
60
-
61
-
62
-
63
- // ALTERADO: usar size (Map)
64
- if (!node.queue.read.size && !node.queue.write.size) {
65
-
66
- }
67
-
68
-
69
- const payload = {
70
- serverRef: node.serverRef || "",
71
- intervalMs: node.intervalMs,
72
- timestamp: new Date().toISOString(),
73
-
74
- // 🔥 ALTERADO: converter Map -> Array
75
- read: Array.from(node.queue.read.values()),
76
- write: Array.from(node.queue.write.values()),
77
- alarm: Array.from(node.queue.alarm.values())
78
- };
79
-
80
- // ALTERADO: limpar Maps
81
- node.queue.read.clear();
82
- node.queue.write.clear();
83
- node.queue.alarm.clear();
84
-
85
- process.send({
86
- type: "send",
87
- data: {
88
- payload,
89
- opcua: {
90
- server: payload.serverRef
91
- }
92
- },
93
- nodeId: nodeId
94
- });
95
-
96
- process.send({
97
- type: "status",
98
- data: {
99
- fill: "green",
100
- shape: "dot",
101
- text: "read " + payload.read.length + " write " + payload.write.length
102
- },
103
- nodeId: nodeId
104
- });
105
-
106
-
107
-
108
-
109
- }
110
-
111
-
112
- function upsertEvent(map, event) {
113
- const key = String(event.nodeID || "").trim();
114
- if (!key) return;
115
-
116
- map.set(key, event); // sobrescreve automaticamente
117
- }
118
-
119
- function matchesServer(serverRef, event) {
120
- if (!serverRef) {
121
- return true;
122
- }
123
-
124
- const normalizedRef = String(serverRef).trim();
125
- return normalizedRef === String(event.serverId || "").trim()
126
- || normalizedRef === String(event.serverNodeName || "").trim()
127
- || normalizedRef === String(event.serverName || "").trim();
128
- }
129
-
130
- function normalizeInterval(value) {
131
- const interval = Number(value);
132
- if (!Number.isFinite(interval) || interval <= 0) {
133
- return 500;
134
- }
135
-
136
- return Math.trunc(interval);
137
- }
138
- module.exports = {
139
- "eventsServer": eventsServer
1
+ "use strict";
2
+
3
+
4
+ const registry = require("../opcua-server-registry");
5
+ const { resolveRegisteredServer } = require("./server-node-utils");
6
+
7
+
8
+
9
+
10
+ function eventsServer(node, rootNode, nodeId) {
11
+
12
+
13
+
14
+ // 🔥 ALTERADO: usar Map para garantir unicidade por nodeID
15
+ node.queue = {
16
+ read: new Map(),
17
+ write: new Map(),
18
+ alarm: new Map()
19
+ };
20
+
21
+ if (node.flushTimer) {
22
+ clearInterval(node.flushTimer);
23
+ node.flushTimer = null;
24
+ }
25
+
26
+
27
+ node.flushTimer = setInterval(() => {
28
+ flushQueue(node, nodeId);
29
+
30
+ }, rootNode.intervalMs);
31
+
32
+ ///rootNode.intervalMs
33
+ node.enqueueAccessEvent = function (event) {
34
+ if (!matchesServer(node.serverRef, event)) {
35
+
36
+ }
37
+
38
+ if (event.operation === "read") {
39
+ upsertEvent(node.queue.read, event);
40
+
41
+ }
42
+
43
+ if (event.operation === "write") {
44
+ upsertEvent(node.queue.write, event);
45
+ }
46
+
47
+ if (event.operation === "alarm") {
48
+ upsertEvent(node.queue.alarm, event);
49
+ }
50
+ };
51
+
52
+ registry.registerAccessListener(node.id, node);
53
+ }
54
+
55
+
56
+
57
+
58
+
59
+ function flushQueue(node, nodeId) {
60
+
61
+
62
+
63
+ // ALTERADO: usar size (Map)
64
+ if (!node.queue.read.size && !node.queue.write.size) {
65
+
66
+ }
67
+
68
+
69
+ const payload = {
70
+ serverRef: node.serverRef || "",
71
+ intervalMs: node.intervalMs,
72
+ timestamp: new Date().toISOString(),
73
+
74
+ // 🔥 ALTERADO: converter Map -> Array
75
+ read: Array.from(node.queue.read.values()),
76
+ write: Array.from(node.queue.write.values()),
77
+ alarm: Array.from(node.queue.alarm.values())
78
+ };
79
+
80
+ // ALTERADO: limpar Maps
81
+ node.queue.read.clear();
82
+ node.queue.write.clear();
83
+ node.queue.alarm.clear();
84
+
85
+ process.send({
86
+ type: "send",
87
+ data: {
88
+ payload,
89
+ opcua: {
90
+ server: payload.serverRef
91
+ }
92
+ },
93
+ nodeId: nodeId
94
+ });
95
+
96
+ process.send({
97
+ type: "status",
98
+ data: {
99
+ fill: "green",
100
+ shape: "dot",
101
+ text: "read " + payload.read.length + " write " + payload.write.length
102
+ },
103
+ nodeId: nodeId
104
+ });
105
+
106
+
107
+
108
+
109
+ }
110
+
111
+
112
+ function upsertEvent(map, event) {
113
+ const key = String(event.nodeID || "").trim();
114
+ if (!key) return;
115
+
116
+ map.set(key, event); // sobrescreve automaticamente
117
+ }
118
+
119
+ function matchesServer(serverRef, event) {
120
+ if (!serverRef) {
121
+ return true;
122
+ }
123
+
124
+ const normalizedRef = String(serverRef).trim();
125
+ return normalizedRef === String(event.serverId || "").trim()
126
+ || normalizedRef === String(event.serverNodeName || "").trim()
127
+ || normalizedRef === String(event.serverName || "").trim();
128
+ }
129
+
130
+ function normalizeInterval(value) {
131
+ const interval = Number(value);
132
+ if (!Number.isFinite(interval) || interval <= 0) {
133
+ return 500;
134
+ }
135
+
136
+ return Math.trunc(interval);
137
+ }
138
+ module.exports = {
139
+ "eventsServer": eventsServer
140
140
  }