@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.
- package/README.md +7 -4
- package/client/icons/opcua.svg +132 -0
- package/client/lib/opcua-client-browser.js +46 -7
- package/client/lib/opcua-client-method-service.js +88 -0
- package/client/lib/opcua-client-write-service.js +127 -33
- package/client/opcua-client-config.js +5 -0
- package/client/opcua-client-help.html +61 -0
- package/client/opcua-client-utils.js +68 -2
- package/client/opcua-client.html +14 -1098
- package/client/opcua-client.js +108 -53
- package/client/testClient.json +18 -0
- package/client/view/opcua-client.css +411 -0
- package/client/view/opcua-client.js +1141 -0
- package/icons/opcua.svg +132 -0
- package/icons/opcua2.svg +132 -0
- package/package.json +3 -3
- package/server/icons/opcua.svg +132 -0
- package/server/lib/opcua-address-space-builder.js +24 -2
- package/server/lib/opcua-server-runtime-child.js +117 -26
- package/server/opcua-server-io.html +1 -1
- package/server/opcua-server-io.js +31 -2
- package/server/opcua-server.html +154 -58
- package/server/opcua-server.js +7 -3
- package/object.json +0 -65
|
@@ -4,6 +4,7 @@ const {
|
|
|
4
4
|
AttributeIds,
|
|
5
5
|
BrowseDirection,
|
|
6
6
|
coerceNodeId,
|
|
7
|
+
VariantArrayType,
|
|
7
8
|
DataType,
|
|
8
9
|
MessageSecurityMode,
|
|
9
10
|
NodeClass,
|
|
@@ -13,6 +14,18 @@ const {
|
|
|
13
14
|
Variant
|
|
14
15
|
} = require("node-opcua");
|
|
15
16
|
|
|
17
|
+
// Mapa DataType → TypedArray nativo para escrita eficiente no servidor OPC UA
|
|
18
|
+
const TYPED_ARRAY_MAP = {
|
|
19
|
+
[DataType.SByte]: Int8Array,
|
|
20
|
+
[DataType.Byte]: Uint8Array,
|
|
21
|
+
[DataType.Int16]: Int16Array,
|
|
22
|
+
[DataType.UInt16]: Uint16Array,
|
|
23
|
+
[DataType.Int32]: Int32Array,
|
|
24
|
+
[DataType.UInt32]: Uint32Array,
|
|
25
|
+
[DataType.Float]: Float32Array,
|
|
26
|
+
[DataType.Double]: Float64Array,
|
|
27
|
+
};
|
|
28
|
+
|
|
16
29
|
function resolveSecurityPolicy(name) {
|
|
17
30
|
return SecurityPolicy[name] || SecurityPolicy.None;
|
|
18
31
|
}
|
|
@@ -61,19 +74,26 @@ function inferTypeName(value) {
|
|
|
61
74
|
if (value instanceof Date) {
|
|
62
75
|
return "DateTime";
|
|
63
76
|
}
|
|
64
|
-
if (Buffer.isBuffer(value)) {
|
|
77
|
+
if (Buffer.isBuffer(value) || (value && typeof value === 'object' && value.type === 'Buffer' && Array.isArray(value.data))) {
|
|
65
78
|
return "ByteString";
|
|
66
79
|
}
|
|
67
80
|
return "String";
|
|
68
81
|
}
|
|
69
82
|
|
|
70
83
|
function coerceValue(value, typeName) {
|
|
84
|
+
|
|
85
|
+
if (Array.isArray(value)) {
|
|
86
|
+
return value.map(element => coerceValue(element, typeName));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
71
90
|
switch (typeName) {
|
|
72
91
|
case "Boolean":
|
|
73
92
|
if (typeof value === "string") {
|
|
74
93
|
return value.trim().toLowerCase() === "true";
|
|
75
94
|
}
|
|
76
95
|
return Boolean(value);
|
|
96
|
+
|
|
77
97
|
case "Byte":
|
|
78
98
|
case "SByte":
|
|
79
99
|
case "Int16":
|
|
@@ -81,16 +101,44 @@ function coerceValue(value, typeName) {
|
|
|
81
101
|
case "UInt16":
|
|
82
102
|
case "UInt32":
|
|
83
103
|
return Number.parseInt(value, 10);
|
|
104
|
+
|
|
84
105
|
case "Int64":
|
|
85
106
|
case "UInt64":
|
|
86
107
|
return BigInt(value);
|
|
108
|
+
|
|
87
109
|
case "Float":
|
|
88
110
|
case "Double":
|
|
89
111
|
return Number.parseFloat(value);
|
|
112
|
+
|
|
113
|
+
case "ByteString":
|
|
114
|
+
if (value && typeof value === "object" && value.type === "Buffer" && Array.isArray(value.data)) {
|
|
115
|
+
return Buffer.from(value.data);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (Buffer.isBuffer(value)) {
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (value instanceof Uint8Array) {
|
|
123
|
+
return Buffer.from(value);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (Array.isArray(value)) {
|
|
127
|
+
return Buffer.from(value);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (typeof value === "string") {
|
|
131
|
+
return Buffer.from(value, "base64");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return Buffer.alloc(0);
|
|
135
|
+
|
|
90
136
|
case "DateTime":
|
|
91
137
|
return value instanceof Date ? value : new Date(value);
|
|
138
|
+
|
|
92
139
|
case "String":
|
|
93
140
|
return value === undefined || value === null ? "" : String(value);
|
|
141
|
+
|
|
94
142
|
default:
|
|
95
143
|
return value;
|
|
96
144
|
}
|
|
@@ -104,8 +152,26 @@ function buildVariantFromItem(item, fallbackTypeName) {
|
|
|
104
152
|
throw new Error("Unsupported OPC UA data type: " + typeName);
|
|
105
153
|
}
|
|
106
154
|
|
|
155
|
+
const isArray = Array.isArray(item.value);
|
|
156
|
+
|
|
157
|
+
if (isArray) {
|
|
158
|
+
// Coerce cada elemento e converte para TypedArray se disponível
|
|
159
|
+
const coercedArray = coerceValue(item.value, typeName); // retorna JS Array
|
|
160
|
+
const TypedArrayCtor = TYPED_ARRAY_MAP[dataType];
|
|
161
|
+
|
|
162
|
+
return new Variant({
|
|
163
|
+
dataType,
|
|
164
|
+
arrayType: VariantArrayType.Array,
|
|
165
|
+
value: TypedArrayCtor
|
|
166
|
+
? TypedArrayCtor.from(coercedArray) // Int32Array, Float32Array, etc.
|
|
167
|
+
: coercedArray // String[], Boolean[], DateTime[]
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Escalar — comportamento original preservado
|
|
107
172
|
return new Variant({
|
|
108
173
|
dataType,
|
|
174
|
+
arrayType: VariantArrayType.Scalar,
|
|
109
175
|
value: coerceValue(item.value, typeName)
|
|
110
176
|
});
|
|
111
177
|
}
|
|
@@ -317,4 +383,4 @@ module.exports = {
|
|
|
317
383
|
resolveSecurityMode,
|
|
318
384
|
resolveSecurityPolicy,
|
|
319
385
|
statusCodeToString
|
|
320
|
-
};
|
|
386
|
+
};
|