@vitormnm/node-red-simple-opcua 1.0.0 → 1.0.2

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.
@@ -1,320 +0,0 @@
1
- "use strict";
2
-
3
- const {
4
- AttributeIds,
5
- BrowseDirection,
6
- coerceNodeId,
7
- DataType,
8
- MessageSecurityMode,
9
- NodeClass,
10
- OPCUAClient,
11
- SecurityPolicy,
12
- TimestampsToReturn,
13
- Variant
14
- } = require("node-opcua");
15
-
16
- function resolveSecurityPolicy(name) {
17
- return SecurityPolicy[name] || SecurityPolicy.None;
18
- }
19
-
20
- function resolveSecurityMode(name) {
21
- return MessageSecurityMode[name] || MessageSecurityMode.None;
22
- }
23
-
24
- function normalizeTypeName(type) {
25
- const raw = String(type || "").trim();
26
- if (!raw) {
27
- return "";
28
- }
29
-
30
- const aliases = {
31
- Bool: "Boolean",
32
- Boolean: "Boolean",
33
- Byte: "Byte",
34
- SByte: "SByte",
35
- Int: "Int32",
36
- Int16: "Int16",
37
- Int32: "Int32",
38
- Int64: "Int64",
39
- UInt16: "UInt16",
40
- UInt32: "UInt32",
41
- UInt64: "UInt64",
42
- Float: "Float",
43
- Double: "Double",
44
- String: "String",
45
- DateTime: "DateTime"
46
- };
47
-
48
- return aliases[raw] || raw;
49
- }
50
-
51
- function inferTypeName(value) {
52
- if (typeof value === "boolean") {
53
- return "Boolean";
54
- }
55
- if (typeof value === "string") {
56
- return "String";
57
- }
58
- if (typeof value === "number") {
59
- return Number.isInteger(value) ? "Int32" : "Double";
60
- }
61
- if (value instanceof Date) {
62
- return "DateTime";
63
- }
64
- if (Buffer.isBuffer(value)) {
65
- return "ByteString";
66
- }
67
- return "String";
68
- }
69
-
70
- function coerceValue(value, typeName) {
71
- switch (typeName) {
72
- case "Boolean":
73
- if (typeof value === "string") {
74
- return value.trim().toLowerCase() === "true";
75
- }
76
- return Boolean(value);
77
- case "Byte":
78
- case "SByte":
79
- case "Int16":
80
- case "Int32":
81
- case "UInt16":
82
- case "UInt32":
83
- return Number.parseInt(value, 10);
84
- case "Int64":
85
- case "UInt64":
86
- return BigInt(value);
87
- case "Float":
88
- case "Double":
89
- return Number.parseFloat(value);
90
- case "DateTime":
91
- return value instanceof Date ? value : new Date(value);
92
- case "String":
93
- return value === undefined || value === null ? "" : String(value);
94
- default:
95
- return value;
96
- }
97
- }
98
-
99
- function buildVariantFromItem(item, fallbackTypeName) {
100
- const typeName = normalizeTypeName(item.type || fallbackTypeName || inferTypeName(item.value));
101
- const dataType = DataType[typeName];
102
-
103
- if (dataType === undefined) {
104
- throw new Error("Unsupported OPC UA data type: " + typeName);
105
- }
106
-
107
- return new Variant({
108
- dataType,
109
- value: coerceValue(item.value, typeName)
110
- });
111
- }
112
-
113
- function ensureArrayPayload(msg, contextName) {
114
- const payload = msg ? msg.payload : undefined;
115
-
116
- if (!Array.isArray(payload) || payload.length === 0) {
117
- throw new Error(contextName + " expects msg.payload as a non-empty array");
118
- }
119
-
120
- return payload;
121
- }
122
-
123
- function resolveNodeId(item) {
124
- const nodeId = item && (item.nodeID || item.nodeId);
125
- if (!nodeId || !String(nodeId).trim()) {
126
- throw new Error("Each item must contain nodeID");
127
- }
128
- return String(nodeId).trim();
129
- }
130
-
131
- function resolveName(item, fallback) {
132
- return String(item && item.name ? item.name : fallback || "").trim();
133
- }
134
-
135
- function statusCodeToString(statusCode) {
136
- if (!statusCode) {
137
- return "Unknown";
138
- }
139
- return statusCode.name || statusCode.toString();
140
- }
141
-
142
- function timestampToIso(value) {
143
- return value instanceof Date && !Number.isNaN(value.getTime())
144
- ? value.toISOString()
145
- : null;
146
- }
147
-
148
- function variantTypeToName(variant) {
149
- if (!variant || variant.dataType === undefined || variant.dataType === null) {
150
- return null;
151
- }
152
- return DataType[variant.dataType] || String(variant.dataType);
153
- }
154
-
155
- function dataValueToItemResult(item, dataValue) {
156
- const variant = dataValue && dataValue.value ? dataValue.value : null;
157
- return {
158
- name: resolveName(item, resolveNodeId(item)),
159
- nodeID: resolveNodeId(item),
160
- value: variant ? variant.value : null,
161
- type: variantTypeToName(variant),
162
- status: statusCodeToString(dataValue && dataValue.statusCode),
163
- sourceTimestamp: timestampToIso(dataValue && dataValue.sourceTimestamp),
164
- serverTimestamp: timestampToIso(dataValue && dataValue.serverTimestamp)
165
- };
166
- }
167
-
168
- async function dataValueToItemResultEvent(item, eventFields, session) {
169
- const variant = eventFields && eventFields.value ? eventFields.value : null;
170
-
171
- // lê BrowseName do tipo
172
- const dv = await session.read({
173
- nodeId: eventFields[1].value,
174
- attributeId: AttributeIds.BrowseName
175
- });
176
-
177
- const eventTypeName = dv.value.value.name;
178
-
179
- return {
180
- eventId: eventFields[0].value,
181
- eventType: eventFields[1].value,
182
- eventTypeName: eventTypeName,
183
- sourceNode: eventFields[2].value.toString(),
184
- sourceName: eventFields[3].value,
185
- message: eventFields[4].value?.text,
186
- severity: eventFields[5].value,
187
- active: eventFields[6].value?.text, // Active / Inactive
188
- AckedState: eventFields[7].value?.text, // Active / Inactive
189
- ConfirmedState: eventFields[8].value?.text, // Active / Inactive
190
- time: eventFields[9].value
191
- };
192
- }
193
-
194
- function callResultToItemResult(item, callResult, argumentDefinition) {
195
- const methodId = resolveMethodNodeId(item);
196
- const outputDefinitions = argumentDefinition && Array.isArray(argumentDefinition.outputArguments)
197
- ? argumentDefinition.outputArguments
198
- : [];
199
- const outputArguments = Array.isArray(callResult.outputArguments)
200
- ? callResult.outputArguments
201
- : [];
202
-
203
- return {
204
- name: resolveName(item, methodId),
205
- nodeID: methodId,
206
- status: statusCodeToString(callResult.statusCode),
207
- outputs: outputArguments.map((variant, index) => ({
208
- name: outputDefinitions[index] && outputDefinitions[index].name
209
- ? String(outputDefinitions[index].name)
210
- : "output" + (index + 1),
211
- type: variantTypeToName(variant),
212
- value: variant ? variant.value : null
213
- }))
214
- };
215
- }
216
-
217
- function resolveMethodNodeId(item) {
218
- const methodId = item && (item.methodID || item.methodId || item.nodeID || item.nodeId);
219
- if (!methodId || !String(methodId).trim()) {
220
- throw new Error("Each method item must contain methodId or nodeID");
221
- }
222
-
223
- return String(methodId).trim();
224
- }
225
-
226
- async function resolveMethodObjectId(session, methodNodeId, cache) {
227
- const cacheKey = String(methodNodeId);
228
- if (cache && cache.has(cacheKey)) {
229
- return cache.get(cacheKey);
230
- }
231
-
232
- const browseResult = await session.browse({
233
- nodeId: methodNodeId,
234
- browseDirection: BrowseDirection.Inverse,
235
- includeSubtypes: true,
236
- resultMask: 63
237
- });
238
-
239
- const references = browseResult && Array.isArray(browseResult.references)
240
- ? browseResult.references
241
- : [];
242
-
243
- const objectReferences = references.filter((reference) => {
244
- const nodeClassName = resolveNodeClassName(reference.nodeClass);
245
- return nodeClassName === "Object" || nodeClassName === "ObjectType";
246
- });
247
-
248
- const parentReference = objectReferences.find((reference) => isComponentReference(reference.referenceTypeId))
249
- || objectReferences[0]
250
- || references[0];
251
-
252
- if (!parentReference) {
253
- throw new Error("Unable to resolve parent object for method " + methodNodeId);
254
- }
255
-
256
- const objectId = parentReference.nodeId.toString();
257
- if (cache) {
258
- cache.set(cacheKey, objectId);
259
- }
260
- return objectId;
261
- }
262
-
263
- function resolveNodeClassName(nodeClass) {
264
- if (!nodeClass && nodeClass !== 0) {
265
- return "";
266
- }
267
-
268
- if (typeof nodeClass === "object" && typeof nodeClass.key === "string") {
269
- return nodeClass.key;
270
- }
271
-
272
- if (typeof nodeClass === "string") {
273
- return nodeClass;
274
- }
275
-
276
- return NodeClass[nodeClass] || String(nodeClass);
277
- }
278
-
279
- function isComponentReference(referenceTypeId) {
280
- const value = referenceTypeId && typeof referenceTypeId.toString === "function"
281
- ? referenceTypeId.toString()
282
- : String(referenceTypeId || "");
283
-
284
- return value === "i=47" || value === "i=49";
285
- }
286
-
287
- async function getMethodArgumentDefinition(session, methodNodeId, cache) {
288
- const cacheKey = String(methodNodeId);
289
- if (cache && cache.has(cacheKey)) {
290
- return cache.get(cacheKey);
291
- }
292
-
293
- const definition = await session.getArgumentDefinition(methodNodeId);
294
- if (cache) {
295
- cache.set(cacheKey, definition);
296
- }
297
- return definition;
298
- }
299
-
300
- module.exports = {
301
- AttributeIds,
302
- coerceNodeId,
303
- DataType,
304
- OPCUAClient,
305
- TimestampsToReturn,
306
- buildVariantFromItem,
307
- callResultToItemResult,
308
- dataValueToItemResult,
309
- dataValueToItemResultEvent,
310
- ensureArrayPayload,
311
- getMethodArgumentDefinition,
312
- inferTypeName,
313
- normalizeTypeName,
314
- resolveMethodObjectId,
315
- resolveName,
316
- resolveNodeId,
317
- resolveSecurityMode,
318
- resolveSecurityPolicy,
319
- statusCodeToString
320
- };