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

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.
@@ -214,6 +214,8 @@ class OpcUaServerProcess {
214
214
  msg.payload = result.payload;
215
215
  this.assignReadMetadata(msg, identifierType, result.identifiers);
216
216
 
217
+
218
+
217
219
  if (result.identifiers.length === 1) {
218
220
  msg.topic = result.identifiers[0];
219
221
  }
@@ -306,49 +308,137 @@ class OpcUaServerProcess {
306
308
  }
307
309
 
308
310
 
309
-
310
311
  writeFromPayload(msg, nodeId) {
311
312
  try {
312
- var writtenPaths = null
313
- const payload = msg ? msg.payload : undefined;
313
+ let writtenPaths = null;
314
+ let payload = msg ? msg.payload : undefined;
315
+
314
316
  const target = msg && msg.opcuaServerIo ? msg.opcuaServerIo : {};
315
317
  const identifierType = this.resolveIdentifierType(target);
316
318
 
319
+ // Buffer serializado pelo IPC
320
+ if (
321
+ payload &&
322
+ typeof payload === "object" &&
323
+ payload.type === "Buffer" &&
324
+ Array.isArray(payload.data)
325
+ ) {
326
+ payload = Buffer.from(payload.data);
327
+ }
317
328
 
329
+ const dataType =
330
+ target.dataType ||
331
+ target.type ||
332
+ target.builtInType ||
333
+ "";
334
+
335
+ const isByteString =
336
+ typeof dataType === "string" &&
337
+ dataType.toLowerCase() === "bytestring";
338
+
339
+
340
+
341
+ // Buffer ou Uint8Array
342
+ if (Buffer.isBuffer(payload) || payload instanceof Uint8Array) {
343
+
344
+ const identifier = this.resolveIdentifier(target);
345
+
346
+ this.node.writeValue(
347
+ identifierType,
348
+ identifier,
349
+ Buffer.isBuffer(payload)
350
+ ? payload
351
+ : Buffer.from(payload)
352
+ );
353
+
354
+ writtenPaths = [identifier];
355
+ }
356
+
357
+ // Array de números
358
+ else if (
359
+ Array.isArray(payload) &&
360
+ payload.every(item => typeof item === "number")
361
+ ) {
362
+
363
+ const identifier = this.resolveIdentifier(target);
364
+
365
+ this.node.writeValue(
366
+ identifierType,
367
+ identifier,
368
+ isByteString
369
+ ? Buffer.from(payload)
370
+ : payload
371
+ );
372
+
373
+ writtenPaths = [identifier];
374
+ }
375
+
376
+ // Array de objetos
377
+ else if (Array.isArray(payload)) {
318
378
 
319
- if (Array.isArray(payload)) {
320
379
  if (!payload.length) {
321
380
  throw new Error("msg.payload array does not contain any items");
322
381
  }
323
382
 
324
- payload.forEach((item) => {
383
+ payload.forEach(item => {
325
384
  this.writePayloadItem(identifierType, item);
326
385
  });
327
386
 
328
- writtenPaths = payload.map((item) => this.resolvePayloadItemIdentifier(item));
329
- } else if (payload && typeof payload === "object" && !Array.isArray(payload)) {
387
+ writtenPaths = payload.map(item =>
388
+ this.resolvePayloadItemIdentifier(item)
389
+ );
390
+ }
391
+
392
+ // Objeto { path: value }
393
+ else if (
394
+ payload &&
395
+ typeof payload === "object" &&
396
+ !Array.isArray(payload)
397
+ ) {
330
398
 
331
399
  const identifiers = Object.keys(payload);
400
+
332
401
  if (!identifiers.length) {
333
- throw new Error("msg.payload object does not contain any " + this.getIdentifierLabel(identifierType));
402
+ throw new Error(
403
+ "msg.payload object does not contain any " +
404
+ this.getIdentifierLabel(identifierType)
405
+ );
334
406
  }
335
407
 
336
- identifiers.forEach((identifier) => {
337
- this.node.writeValue(identifierType, identifier, payload[identifier]);
408
+ identifiers.forEach(identifier => {
409
+ this.node.writeValue(
410
+ identifierType,
411
+ identifier,
412
+ payload[identifier]
413
+ );
338
414
  });
339
415
 
340
416
  writtenPaths = identifiers;
341
- } else {
417
+ }
418
+
419
+ // Valor simples
420
+ else {
342
421
 
343
422
  const identifier = this.resolveIdentifier(target);
344
- this.node.writeValue(identifierType, identifier, payload);
345
423
 
424
+ this.node.writeValue(
425
+ identifierType,
426
+ identifier,
427
+ payload
428
+ );
346
429
 
347
- writtenPaths = [identifier]
430
+ writtenPaths = [identifier];
348
431
  }
349
432
 
350
433
  msg.opcua = msg.opcua || {};
351
- this.assignWriteMetadata(msg, identifierType, writtenPaths);
434
+
435
+ this.assignWriteMetadata(
436
+ msg,
437
+ identifierType,
438
+ writtenPaths
439
+ );
440
+
441
+
352
442
  if (writtenPaths.length === 1) {
353
443
  msg.topic = writtenPaths[0];
354
444
  }
@@ -356,7 +446,7 @@ class OpcUaServerProcess {
356
446
  process.send({
357
447
  type: "send",
358
448
  data: msg,
359
- nodeId: nodeId
449
+ nodeId
360
450
  });
361
451
 
362
452
  process.send({
@@ -364,28 +454,29 @@ class OpcUaServerProcess {
364
454
  data: {
365
455
  fill: "green",
366
456
  shape: "dot",
367
- text: writtenPaths.length > 1 ? "write " + writtenPaths.length + " tags" : "write " + writtenPaths[0]
457
+ text:
458
+ writtenPaths.length > 1
459
+ ? `write ${writtenPaths.length} tags`
460
+ : `write ${writtenPaths[0]}`
368
461
  },
369
- nodeId: nodeId
462
+ nodeId
370
463
  });
371
464
 
372
-
373
465
  } catch (error) {
374
466
 
375
467
  process.send({
376
468
  type: "error",
377
- data: { fill: "red", shape: "ring", text: "failed write" },
469
+ data: {
470
+ fill: "red",
471
+ shape: "ring",
472
+ text: "failed write"
473
+ },
378
474
  error: error.message,
379
- nodeId: nodeId
475
+ nodeId
380
476
  });
381
477
  }
382
-
383
-
384
-
385
- //return [path];
386
478
  }
387
479
 
388
-
389
480
  resolveIdentifierType(target) {
390
481
  return target && target.identifierType === "nodeId" ? "nodeId" : "path";
391
482
  }
@@ -726,4 +817,4 @@ process.on("unhandledRejection", (reason) => {
726
817
  data: "Unhandled Rejection: " + (reason?.message || reason),
727
818
  nodeId: nodeId
728
819
  });
729
- });
820
+ });
@@ -98,7 +98,7 @@
98
98
  },
99
99
  inputs: 1,
100
100
  outputs: 1,
101
- icon: "bridge.svg",
101
+ icon: "opcua.svg",
102
102
  label: function () {
103
103
  return this.name || this.methodName || this.tagPath || this.tagNodeId || "opcua-server-io";
104
104
  },
@@ -12,10 +12,19 @@ module.exports = function (RED) {
12
12
  }
13
13
  });
14
14
 
15
+
16
+ const path = require("path");
17
+
18
+
19
+
20
+
21
+
22
+
15
23
  function OpcUaServerIoNode(config) {
16
24
  RED.nodes.createNode(this, config);
17
25
  const node = this;
18
26
 
27
+
19
28
  node.name = (config.name || "").trim();
20
29
  node.serverRef = (config.serverRef || "").trim();
21
30
  node.mode = config.mode || "read";
@@ -106,6 +115,20 @@ module.exports = function (RED) {
106
115
  });
107
116
  }
108
117
 
118
+ function restoreBuffers(value) {
119
+ // Formato exato que o Node.js IPC gera ao serializar um Buffer
120
+ if (
121
+ value !== null &&
122
+ typeof value === "object" &&
123
+ value.type === "Buffer" &&
124
+ Array.isArray(value.data)
125
+ ) {
126
+ return Buffer.from(value.data);
127
+ }
128
+
129
+ return value;
130
+ }
131
+
109
132
  function onMessage(msg, node) {
110
133
  if (msg.nodeId == node.id) {
111
134
 
@@ -115,7 +138,13 @@ module.exports = function (RED) {
115
138
  }
116
139
 
117
140
  if (msg.type === "send") {
118
- node.send(msg.data);
141
+ const data = msg.data;
142
+
143
+ if (data && data.payload !== undefined) {
144
+ data.payload = restoreBuffers(data.payload);
145
+ }
146
+
147
+ node.send(data);
119
148
  }
120
149
 
121
150
  if (msg.type === "error") {
@@ -132,7 +161,7 @@ module.exports = function (RED) {
132
161
  });
133
162
 
134
163
  node.send({
135
- topic : msg.data.nodeId,
164
+ topic: msg.data.nodeId,
136
165
  payload: msg.data.inputArguments,
137
166
  opcua: {
138
167
  server: msg.data.serverName,