@vitormnm/node-red-simple-opcua 1.4.1 → 1.4.3

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/README.md +5 -0
  2. package/client/icons/opcua.svg +132 -132
  3. package/client/lib/opcua-client-browser.js +330 -330
  4. package/client/lib/opcua-client-method-service.js +88 -88
  5. package/client/lib/opcua-client-read-service.js +15 -15
  6. package/client/lib/opcua-client-subscription-id-service.js +24 -24
  7. package/client/lib/opcua-client-subscription-service.js +170 -170
  8. package/client/lib/opcua-client-write-service.js +146 -146
  9. package/client/opcua-client-config.html +80 -80
  10. package/client/opcua-client.html +140 -140
  11. package/client/opcua-client.js +1 -7
  12. package/client/view/opcua-client.js +1140 -1140
  13. package/icons/opcua.svg +132 -132
  14. package/icons/opcua2.svg +132 -132
  15. package/package.json +42 -42
  16. package/resources/bmc-button.svg +22 -0
  17. package/server/icons/opcua.svg +132 -132
  18. package/server/lib/opcua-address-space-alarm.js +341 -341
  19. package/server/lib/opcua-address-space-builder.js +1484 -1484
  20. package/server/lib/opcua-config.js +546 -546
  21. package/server/lib/opcua-constants.js +109 -109
  22. package/server/lib/opcua-server-events-child.js +139 -139
  23. package/server/lib/opcua-server-runtime-child.js +819 -819
  24. package/server/lib/opcua-server-runtime.js +311 -311
  25. package/server/lib/opcua-server-status-child.js +187 -187
  26. package/server/lib/server-node-utils.js +16 -16
  27. package/server/opcua-server-io.html +346 -346
  28. package/server/opcua-server-io.js +496 -496
  29. package/server/opcua-server-registry.js +270 -270
  30. package/server/opcua-server.css +265 -265
  31. package/server/opcua-server.html +1643 -1643
  32. package/client/testClient.json +0 -18
@@ -1,109 +1,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
- } = 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
+ } = 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,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
  }