node-opcua-client-dynamic-extension-object 2.98.0 → 2.98.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.
Files changed (40) hide show
  1. package/dist/convert_data_type_definition_to_structuretype_schema.d.ts +14 -0
  2. package/dist/convert_data_type_definition_to_structuretype_schema.js +411 -0
  3. package/dist/convert_data_type_definition_to_structuretype_schema.js.map +1 -0
  4. package/dist/convert_structuretype_schema_to_structure_definition.d.ts +3 -0
  5. package/dist/convert_structuretype_schema_to_structure_definition.js +54 -0
  6. package/dist/convert_structuretype_schema_to_structure_definition.js.map +1 -0
  7. package/dist/extra_data_type_manager.d.ts +16 -0
  8. package/dist/extra_data_type_manager.js +79 -0
  9. package/dist/extra_data_type_manager.js.map +1 -0
  10. package/dist/get_extension_object_constructor.d.ts +7 -0
  11. package/dist/get_extension_object_constructor.js +38 -0
  12. package/dist/get_extension_object_constructor.js.map +1 -0
  13. package/dist/get_extra_data_type_manager.d.ts +3 -0
  14. package/dist/get_extra_data_type_manager.js +52 -0
  15. package/dist/get_extra_data_type_manager.js.map +1 -0
  16. package/dist/index.d.ts +13 -0
  17. package/dist/index.js +30 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/populate_data_type_manager.d.ts +3 -0
  20. package/dist/populate_data_type_manager.js +89 -0
  21. package/dist/populate_data_type_manager.js.map +1 -0
  22. package/dist/private/find_encodings.d.ts +4 -0
  23. package/dist/private/find_encodings.js +56 -0
  24. package/dist/private/find_encodings.js.map +1 -0
  25. package/dist/private/populate_data_type_manager_103.d.ts +9 -0
  26. package/dist/private/populate_data_type_manager_103.js +640 -0
  27. package/dist/private/populate_data_type_manager_103.js.map +1 -0
  28. package/dist/private/populate_data_type_manager_104.d.ts +9 -0
  29. package/dist/private/populate_data_type_manager_104.js +218 -0
  30. package/dist/private/populate_data_type_manager_104.js.map +1 -0
  31. package/dist/promote_opaque_structure.d.ts +7 -0
  32. package/dist/promote_opaque_structure.js +47 -0
  33. package/dist/promote_opaque_structure.js.map +1 -0
  34. package/dist/promote_opaque_structure_in_notification_data.d.ts +3 -0
  35. package/dist/promote_opaque_structure_in_notification_data.js +52 -0
  36. package/dist/promote_opaque_structure_in_notification_data.js.map +1 -0
  37. package/dist/resolve_dynamic_extension_object.d.ts +6 -0
  38. package/dist/resolve_dynamic_extension_object.js +178 -0
  39. package/dist/resolve_dynamic_extension_object.js.map +1 -0
  40. package/package.json +22 -18
@@ -0,0 +1,640 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.populateDataTypeManager103 = void 0;
13
+ /* eslint-disable max-statements */
14
+ // tslint:disable: no-console
15
+ /**
16
+ * @module node-opcua-client-dynamic-extension-object
17
+ */
18
+ const chalk = require("chalk");
19
+ const node_opcua_assert_1 = require("node-opcua-assert");
20
+ const node_opcua_data_model_1 = require("node-opcua-data-model");
21
+ const node_opcua_debug_1 = require("node-opcua-debug");
22
+ const node_opcua_factory_1 = require("node-opcua-factory");
23
+ const node_opcua_nodeid_1 = require("node-opcua-nodeid");
24
+ const node_opcua_pseudo_session_1 = require("node-opcua-pseudo-session");
25
+ const node_opcua_schemas_1 = require("node-opcua-schemas");
26
+ const node_opcua_service_browse_1 = require("node-opcua-service-browse");
27
+ const node_opcua_service_translate_browse_path_1 = require("node-opcua-service-translate-browse-path");
28
+ const node_opcua_types_1 = require("node-opcua-types");
29
+ const convert_data_type_definition_to_structuretype_schema_1 = require("../convert_data_type_definition_to_structuretype_schema");
30
+ const doDebug = (0, node_opcua_debug_1.checkDebugFlag)(__filename);
31
+ const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
32
+ const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
33
+ const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
34
+ // DataType
35
+ // | 1
36
+ // | n
37
+ // +- HasEncoding-> "Default Binary" (O)[DataTypeEncodingType]
38
+ // |
39
+ // +-- HasDescription -> "MyItemType" (V)[DataTypeDescriptionType]
40
+ // |
41
+ // +- ComponentOf -> Schema(V) []
42
+ // |
43
+ // +- ComponentOf -> OPC Binary(V)[DataTypeSystemType]
44
+ //
45
+ // Note that in 1.04 compliant server, DataType definition might be available
46
+ // in a DataTypeDefinition attributes of the DataType object
47
+ // However this is a brand new aspect of the specification and is not widely implemented
48
+ // it is also optional
49
+ // It will takes time for old opcua server to be refurbished and we may have to
50
+ // keep the current method to access type definition from embedded xsd.
51
+ //
52
+ function _readDeprecatedFlag(session, dataTypeDictionary) {
53
+ return __awaiter(this, void 0, void 0, function* () {
54
+ const browsePath = (0, node_opcua_service_translate_browse_path_1.makeBrowsePath)(dataTypeDictionary, ".Deprecated");
55
+ const a = yield session.translateBrowsePath(browsePath);
56
+ /* istanbul ignore next */
57
+ if (!a.targets || a.targets.length === 0) {
58
+ // the server is probably version < 1.04.
59
+ debugLog("Cannot find Deprecated property for dataTypeDictionary " + dataTypeDictionary.toString());
60
+ return false;
61
+ }
62
+ const deprecatedFlagNodeId = a.targets[0].targetId;
63
+ const dataValue = yield session.read({ nodeId: deprecatedFlagNodeId, attributeId: node_opcua_data_model_1.AttributeIds.Value });
64
+ return dataValue.value.value;
65
+ });
66
+ }
67
+ function _readNamespaceUriProperty(session, dataTypeDictionary) {
68
+ return __awaiter(this, void 0, void 0, function* () {
69
+ const a = yield session.translateBrowsePath((0, node_opcua_service_translate_browse_path_1.makeBrowsePath)(dataTypeDictionary, ".NamespaceUri"));
70
+ /* istanbul ignore next */
71
+ if (!a.targets || a.targets.length === 0) {
72
+ return "??dataTypeDictionary doesn't expose NamespaceUri property??";
73
+ }
74
+ const namespaceUriProp = a.targets[0].targetId;
75
+ const dataValue = yield session.read({ nodeId: namespaceUriProp, attributeId: node_opcua_data_model_1.AttributeIds.Value });
76
+ return dataValue.value.value || "<not set>";
77
+ });
78
+ }
79
+ function _getDataTypeDescriptions(session, dataTypeDictionaryNodeId) {
80
+ return __awaiter(this, void 0, void 0, function* () {
81
+ const nodeToBrowse2 = {
82
+ browseDirection: node_opcua_service_browse_1.BrowseDirection.Forward,
83
+ includeSubtypes: false,
84
+ nodeClassMask: (0, node_opcua_data_model_1.makeNodeClassMask)("Variable"),
85
+ nodeId: dataTypeDictionaryNodeId,
86
+ referenceTypeId: (0, node_opcua_nodeid_1.resolveNodeId)("HasComponent"),
87
+ // resultMask: makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
88
+ resultMask: (0, node_opcua_data_model_1.makeResultMask)("NodeId | BrowseName")
89
+ };
90
+ const result2 = yield (0, node_opcua_pseudo_session_1.browseAll)(session, nodeToBrowse2);
91
+ result2.references = result2.references || [];
92
+ return result2.references.map((r) => ({ nodeId: r.nodeId, browseName: r.browseName }));
93
+ });
94
+ }
95
+ function _enrichWithDescriptionOf(session, dataTypeDescriptions) {
96
+ return __awaiter(this, void 0, void 0, function* () {
97
+ const nodesToBrowse3 = [];
98
+ for (const ref of dataTypeDescriptions) {
99
+ ref.browseName.toString();
100
+ nodesToBrowse3.push({
101
+ browseDirection: node_opcua_service_browse_1.BrowseDirection.Inverse,
102
+ includeSubtypes: false,
103
+ nodeClassMask: (0, node_opcua_data_model_1.makeNodeClassMask)("Object"),
104
+ nodeId: ref.nodeId.toString(),
105
+ referenceTypeId: (0, node_opcua_nodeid_1.resolveNodeId)("HasDescription"),
106
+ // resultMask: makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
107
+ resultMask: (0, node_opcua_data_model_1.makeResultMask)("NodeId")
108
+ });
109
+ }
110
+ /* istanbul ignore next */
111
+ if (nodesToBrowse3.length === 0) {
112
+ return [];
113
+ }
114
+ const results3 = yield (0, node_opcua_pseudo_session_1.browseAll)(session, nodesToBrowse3);
115
+ const binaryEncodings = [];
116
+ const nodesToBrowseDataType = [];
117
+ for (let i = 0; i < results3.length; i++) {
118
+ const result3 = results3[i];
119
+ const dataTypeDescription = dataTypeDescriptions[i];
120
+ result3.references = result3.references || [];
121
+ if (result3.references.length === 0) {
122
+ // may be the dataType is abstract and as no need for DescriptionOF
123
+ continue;
124
+ }
125
+ if (result3.references.length !== 1) {
126
+ warningLog("_enrichWithDescriptionOf : expecting 1 reference for ", dataTypeDescription.browseName.toString());
127
+ warningLog(result3.toString());
128
+ continue;
129
+ }
130
+ for (const ref of result3.references) {
131
+ const binaryEncodingNodeId = ref.nodeId;
132
+ dataTypeDescription.encodings = dataTypeDescription.encodings || {
133
+ binaryEncodingNodeId: node_opcua_nodeid_1.NodeId.nullNodeId,
134
+ dataTypeNodeId: node_opcua_nodeid_1.NodeId.nullNodeId,
135
+ jsonEncodingNodeId: node_opcua_nodeid_1.NodeId.nullNodeId,
136
+ xmlEncodingNodeId: node_opcua_nodeid_1.NodeId.nullNodeId
137
+ };
138
+ dataTypeDescription.encodings.binaryEncodingNodeId = binaryEncodingNodeId;
139
+ binaryEncodings.push(binaryEncodingNodeId);
140
+ nodesToBrowseDataType.push({
141
+ browseDirection: node_opcua_service_browse_1.BrowseDirection.Inverse,
142
+ includeSubtypes: false,
143
+ nodeClassMask: node_opcua_data_model_1.NodeClassMask.DataType,
144
+ nodeId: ref.nodeId,
145
+ referenceTypeId: (0, node_opcua_nodeid_1.resolveNodeId)("HasEncoding"),
146
+ // resultMask: makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
147
+ resultMask: (0, node_opcua_data_model_1.makeResultMask)("NodeId | BrowseName")
148
+ });
149
+ }
150
+ }
151
+ const dataTypeNodeIds = [];
152
+ if (nodesToBrowseDataType.length > 0) {
153
+ const results4 = yield (0, node_opcua_pseudo_session_1.browseAll)(session, nodesToBrowseDataType);
154
+ for (let i = 0; i < results4.length; i++) {
155
+ const result4 = results4[i];
156
+ result4.references = result4.references || [];
157
+ /* istanbul ignore next */
158
+ if (result4.references.length !== 1) {
159
+ errorLog("What's going on ?", result4.toString(), "result4.references.length = ", result4.references.length);
160
+ }
161
+ const ref = result4.references[0];
162
+ const dataTypeNodeId = ref.nodeId;
163
+ dataTypeNodeIds[i] = dataTypeNodeId;
164
+ const dataTypeDescription = dataTypeDescriptions[i];
165
+ dataTypeDescription.encodings.dataTypeNodeId = dataTypeNodeId;
166
+ }
167
+ }
168
+ const otherEncodingBrowse = dataTypeNodeIds.map((dataTypeNodeId) => ({
169
+ browseDirection: node_opcua_service_browse_1.BrowseDirection.Forward,
170
+ includeSubtypes: false,
171
+ nodeClassMask: node_opcua_data_model_1.NodeClassMask.Object,
172
+ nodeId: dataTypeNodeId,
173
+ referenceTypeId: (0, node_opcua_nodeid_1.resolveNodeId)("HasEncoding"),
174
+ // resultMask: makeResultMask("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
175
+ resultMask: (0, node_opcua_data_model_1.makeResultMask)("NodeId | BrowseName")
176
+ }));
177
+ const results5 = yield (0, node_opcua_pseudo_session_1.browseAll)(session, otherEncodingBrowse);
178
+ for (let i = 0; i < results5.length; i++) {
179
+ const result5 = results5[i];
180
+ const dataTypeDescription = dataTypeDescriptions[i];
181
+ for (const ref of result5.references || []) {
182
+ switch (ref.browseName.name) {
183
+ case "Default XML":
184
+ dataTypeDescription.encodings.xmlEncodingNodeId = ref.nodeId;
185
+ break;
186
+ case "Default Binary":
187
+ dataTypeDescription.encodings.binaryEncodingNodeId = ref.nodeId;
188
+ break;
189
+ case "Default JSON":
190
+ dataTypeDescription.encodings.jsonEncodingNodeId = ref.nodeId;
191
+ break;
192
+ default:
193
+ errorLog("Cannot handle unknown encoding", ref.browseName.name);
194
+ }
195
+ }
196
+ }
197
+ return dataTypeNodeIds;
198
+ });
199
+ }
200
+ function sortStructure(dataTypeDefinitions) {
201
+ const dataTypeDefinitionsSorted = [];
202
+ const _visited = {};
203
+ const _map = {};
204
+ for (const d of dataTypeDefinitions) {
205
+ _map[d.dataTypeNodeId.toString()] = d;
206
+ }
207
+ function _visit(d) {
208
+ const hash = d.dataTypeNodeId.toString();
209
+ if (_visited[hash]) {
210
+ return;
211
+ }
212
+ _visited[hash] = d;
213
+ const bbb = _map[d.dataTypeDefinition.baseDataType.toString()];
214
+ if (bbb) {
215
+ _visit(bbb);
216
+ }
217
+ for (const f of d.dataTypeDefinition.fields || []) {
218
+ const ddd = _map[f.dataType.toString()];
219
+ if (!ddd) {
220
+ continue;
221
+ }
222
+ _visit(ddd);
223
+ }
224
+ dataTypeDefinitionsSorted.push(d);
225
+ }
226
+ for (const d of dataTypeDefinitions) {
227
+ _visit(d);
228
+ }
229
+ return dataTypeDefinitionsSorted;
230
+ }
231
+ function _extractDataTypeDictionaryFromDefinition(session, dataTypeDictionaryNodeId, dataTypeFactory) {
232
+ return __awaiter(this, void 0, void 0, function* () {
233
+ (0, node_opcua_assert_1.assert)(dataTypeFactory, "expecting a dataTypeFactory");
234
+ const dataTypeDescriptions = yield _getDataTypeDescriptions(session, dataTypeDictionaryNodeId);
235
+ const dataTypeNodeIds = yield _enrichWithDescriptionOf(session, dataTypeDescriptions);
236
+ // now read DataTypeDefinition attributes of all the dataTypeNodeIds, this will only contains concrete structure
237
+ const nodesToRead = dataTypeNodeIds.map((nodeId) => ({
238
+ attributeId: node_opcua_data_model_1.AttributeIds.DataTypeDefinition,
239
+ nodeId
240
+ }));
241
+ const cache = {};
242
+ const dataValuesWithDataTypeDefinition = nodesToRead.length > 0 ? yield session.read(nodesToRead) : [];
243
+ // in some circumstances like Euromap, this assert fails:
244
+ // assert(dataValuesWithDataTypeDefinition.length === dataTypeDescriptions.length);
245
+ const dataTypeDefinitions = [];
246
+ let index = 0;
247
+ for (const dataValue of dataValuesWithDataTypeDefinition) {
248
+ const dataTypeNodeId = dataTypeNodeIds[index];
249
+ const dataTypeDescription = dataTypeDescriptions[index];
250
+ /* istanbul ignore else */
251
+ if (dataValue.statusCode.isGood()) {
252
+ const dataTypeDefinition = dataValue.value.value;
253
+ if (dataTypeDefinition && dataTypeDefinition instanceof node_opcua_types_1.StructureDefinition) {
254
+ const className = dataTypeDescription.browseName.name;
255
+ dataTypeDefinitions.push({ className, dataTypeNodeId, dataTypeDefinition, isAbstract: false });
256
+ }
257
+ }
258
+ else {
259
+ debugLog("dataTypeNodeId ", dataTypeNodeId.toString(), " has no DataTypeDescription attribute", dataValue.statusCode.toString());
260
+ }
261
+ index++;
262
+ }
263
+ // to do put in logical order
264
+ const dataTypeDefinitionsSorted = sortStructure(dataTypeDefinitions);
265
+ if (doDebug) {
266
+ debugLog("order ", dataTypeDefinitionsSorted.map((a) => a.className + " " + a.dataTypeNodeId).join(" -> "));
267
+ }
268
+ for (const { className, dataTypeNodeId, dataTypeDefinition, isAbstract } of dataTypeDefinitionsSorted) {
269
+ // istanbul ignore next
270
+ if (doDebug) {
271
+ debugLog(chalk.yellow("--------------------------------------- "), className, dataTypeNodeId.toString());
272
+ }
273
+ if (dataTypeFactory.hasStructureByTypeName(className)) {
274
+ continue; // this structure has already been seen
275
+ }
276
+ // now fill typeDictionary
277
+ try {
278
+ const schema = yield (0, convert_data_type_definition_to_structuretype_schema_1.convertDataTypeDefinitionToStructureTypeSchema)(session, dataTypeNodeId, className, dataTypeDefinition, dataTypeFactory, isAbstract, cache);
279
+ // istanbul ignore next
280
+ if (doDebug) {
281
+ debugLog(chalk.red("Registering "), chalk.cyan(className.padEnd(30, " ")), schema.dataTypeNodeId.toString());
282
+ }
283
+ const Constructor = (0, node_opcua_schemas_1.createDynamicObjectConstructor)(schema, dataTypeFactory);
284
+ (0, node_opcua_assert_1.assert)(Constructor.schema === schema);
285
+ }
286
+ catch (err) {
287
+ console.log("Constructor verification err: ", err.message);
288
+ console.log("For this reason class " + className + " has not been registered");
289
+ console.log(err);
290
+ }
291
+ }
292
+ });
293
+ }
294
+ function _extractNodeIds(session, dataTypeDictionaryNodeId) {
295
+ return __awaiter(this, void 0, void 0, function* () {
296
+ const map = {};
297
+ const dataTypeDescriptions = yield _getDataTypeDescriptions(session, dataTypeDictionaryNodeId);
298
+ /* const dataTypeNodeIds = */
299
+ yield _enrichWithDescriptionOf(session, dataTypeDescriptions);
300
+ for (const dataTypeDescription of dataTypeDescriptions) {
301
+ map[dataTypeDescription.browseName.name.toString()] = dataTypeDescription.encodings;
302
+ }
303
+ return {
304
+ getDataTypeAndEncodingId(key) {
305
+ return map[key] || null;
306
+ }
307
+ };
308
+ });
309
+ }
310
+ function _isOldDataTypeDictionary(d) {
311
+ const isDictionaryDeprecated = d.isDictionaryDeprecated; // await _readDeprecatedFlag(session, dataTypeDictionaryNodeId);
312
+ const rawSchema = d.rawSchema; // DataValue = await session.read({ nodeId: dataTypeDictionaryNodeId, attributeId: AttributeIds.Value });
313
+ return !isDictionaryDeprecated && rawSchema.length >= 0;
314
+ }
315
+ function _extractDataTypeDictionary(session, d, dataTypeManager) {
316
+ return __awaiter(this, void 0, void 0, function* () {
317
+ const dataTypeDictionaryNodeId = d.reference.nodeId;
318
+ const name = yield session.read({ nodeId: dataTypeDictionaryNodeId, attributeId: node_opcua_data_model_1.AttributeIds.BrowseName });
319
+ const namespace = yield _readNamespaceUriProperty(session, dataTypeDictionaryNodeId);
320
+ if (!_isOldDataTypeDictionary(d)) {
321
+ debugLog("DataTypeDictionary is deprecated or BSD schema stored in dataValue is null !", chalk.cyan(name.value.value.toString()), "namespace =", namespace);
322
+ debugLog("let's use the new way (1.04) and let's crawl all dataTypes exposed by this name space");
323
+ // dataType definition in store directly in UADataType under the definition attribute
324
+ const dataTypeFactory2 = dataTypeManager.getDataTypeFactory(dataTypeDictionaryNodeId.namespace);
325
+ if (!dataTypeFactory2) {
326
+ throw new Error("cannot find dataTypeFactory for namespace " + dataTypeDictionaryNodeId.namespace);
327
+ }
328
+ yield _extractDataTypeDictionaryFromDefinition(session, dataTypeDictionaryNodeId, dataTypeFactory2);
329
+ }
330
+ else {
331
+ const rawSchema = d.rawSchema; // DataValue = await session.read({ nodeId: dataTypeDictionaryNodeId, attributeId: AttributeIds.Value });
332
+ debugLog(" ----- Using old method for extracting schema => with BSD files");
333
+ // old method ( until 1.03 )
334
+ // one need to read the schema file store in the dataTypeDictionary node and parse it !
335
+ /* istanbul ignore next */
336
+ if (doDebug) {
337
+ debugLog("---------------------------------------------");
338
+ debugLog(rawSchema.toString());
339
+ debugLog("---------------------------------------------");
340
+ }
341
+ const idProvider = yield _extractNodeIds(session, dataTypeDictionaryNodeId);
342
+ const dataTypeFactory1 = dataTypeManager.getDataTypeFactory(dataTypeDictionaryNodeId.namespace);
343
+ yield (0, node_opcua_schemas_1.parseBinaryXSDAsync)(rawSchema, idProvider, dataTypeFactory1);
344
+ }
345
+ });
346
+ }
347
+ function _exploreDataTypeDefinition(session, dataTypeDictionaryTypeNode, dataTypeFactory, namespaces) {
348
+ return __awaiter(this, void 0, void 0, function* () {
349
+ const nodeToBrowse = {
350
+ browseDirection: node_opcua_service_browse_1.BrowseDirection.Forward,
351
+ includeSubtypes: false,
352
+ nodeClassMask: (0, node_opcua_data_model_1.makeNodeClassMask)("Variable"),
353
+ nodeId: dataTypeDictionaryTypeNode,
354
+ referenceTypeId: (0, node_opcua_nodeid_1.resolveNodeId)("HasComponent"),
355
+ resultMask: (0, node_opcua_data_model_1.makeResultMask)("ReferenceType | IsForward | BrowseName | NodeClass | TypeDefinition")
356
+ };
357
+ const result = yield (0, node_opcua_pseudo_session_1.browseAll)(session, nodeToBrowse);
358
+ const references = result.references || [];
359
+ /* istanbul ignore next */
360
+ if (references.length === 0) {
361
+ return;
362
+ }
363
+ // request the Definition of each nodes
364
+ const nodesToBrowse2 = references.map((ref) => {
365
+ return {
366
+ browseDirection: node_opcua_service_browse_1.BrowseDirection.Inverse,
367
+ includeSubtypes: false,
368
+ nodeClassMask: (0, node_opcua_data_model_1.makeNodeClassMask)("Object | Variable"),
369
+ nodeId: ref.nodeId,
370
+ referenceTypeId: (0, node_opcua_nodeid_1.resolveNodeId)("HasDescription"),
371
+ resultMask: (0, node_opcua_data_model_1.makeResultMask)("NodeId | ReferenceType | BrowseName | NodeClass | TypeDefinition")
372
+ };
373
+ });
374
+ const results2 = yield (0, node_opcua_pseudo_session_1.browseAll)(session, nodesToBrowse2);
375
+ const binaryEncodingNodeIds = results2.map((br) => {
376
+ const defaultBin = br.references.filter((r) => r.browseName.toString() === "Default Binary");
377
+ /* istanbul ignore next */
378
+ if (defaultBin.length < 1) {
379
+ return node_opcua_nodeid_1.ExpandedNodeId;
380
+ }
381
+ return node_opcua_nodeid_1.ExpandedNodeId.fromNodeId(defaultBin[0].nodeId, namespaces[defaultBin[0].nodeId.namespace]);
382
+ });
383
+ // follow now Default Binary <= [Has Encoding] = [DataType]
384
+ /* istanbul ignore next */
385
+ if (doDebug) {
386
+ console.log(chalk.bgWhite.red("testing new constructors"));
387
+ for (let i = 0; i < references.length; i++) {
388
+ const ref = references[i];
389
+ const binaryEncoding = binaryEncodingNodeIds[i];
390
+ const name = ref.browseName.name.toString();
391
+ if (doDebug) {
392
+ debugLog(" type ", name.padEnd(30, " "), binaryEncoding.toString());
393
+ }
394
+ // let's verify that constructor is operational
395
+ try {
396
+ const Constructor = dataTypeFactory.getStructureInfoByTypeName(name).constructor;
397
+ if (!Constructor) {
398
+ throw new Error(`Cannot instantiate abstract DataType(name=${name})`);
399
+ }
400
+ // xx const constructor = getOrCreateConstructor(name, dataTypeFactory, defaultBinary);
401
+ const testObject = new Constructor();
402
+ debugLog(testObject.toString());
403
+ }
404
+ catch (err) {
405
+ debugLog(" Error cannot construct Extension Object " + name);
406
+ debugLog(" " + err.message);
407
+ }
408
+ }
409
+ }
410
+ });
411
+ }
412
+ const regexTargetNamespaceAttribute = /TargetNamespace="([^"]+)"|TargetNamespace='([^']+)'/;
413
+ function extractTargetNamespaceAttribute(xmlElement) {
414
+ // warning TargetNamespace could have ' or " , Wago PLC for instance uses simple quotes
415
+ const c2 = xmlElement.match(regexTargetNamespaceAttribute);
416
+ if (c2) {
417
+ return c2[1] || c2[2];
418
+ }
419
+ return "";
420
+ }
421
+ const regexNamespaceRef = /xmlns:(.*)=(("([^"]+)")|('([^']+)'))/;
422
+ function extraNamespaceRef(attribute) {
423
+ const c = attribute.match(regexNamespaceRef);
424
+ if (c) {
425
+ const xmlns = c[1];
426
+ const namespace = c[4] || c[5];
427
+ return { xmlns, namespace };
428
+ }
429
+ return null;
430
+ }
431
+ /**
432
+ * Extract all custom dataType
433
+ * @param session
434
+ * @param dataTypeManager
435
+ * @async
436
+ */
437
+ function populateDataTypeManager103(session, dataTypeManager) {
438
+ var _a;
439
+ return __awaiter(this, void 0, void 0, function* () {
440
+ debugLog("in ... populateDataTypeManager");
441
+ // read namespace array
442
+ const dataValueNamespaceArray = yield session.read({
443
+ attributeId: node_opcua_data_model_1.AttributeIds.Value,
444
+ nodeId: (0, node_opcua_nodeid_1.resolveNodeId)("Server_NamespaceArray")
445
+ });
446
+ const namespaceArray = dataValueNamespaceArray.value.value;
447
+ // istanbul ignore next
448
+ if (!namespaceArray) {
449
+ debugLog("session: cannot read Server_NamespaceArray");
450
+ // throw new Error("Cannot get Server_NamespaceArray as a array of string");
451
+ return;
452
+ }
453
+ // istanbul ignore next
454
+ if (doDebug) {
455
+ debugLog("namespaceArray ", namespaceArray.map((a, index) => " " + index.toString().padEnd(3) + ":" + a).join(" "));
456
+ }
457
+ if (dataValueNamespaceArray.statusCode.isGood() && namespaceArray && namespaceArray.length > 0) {
458
+ dataTypeManager.setNamespaceArray(namespaceArray);
459
+ for (let namespaceIndex = 1; namespaceIndex < namespaceArray.length; namespaceIndex++) {
460
+ if (!dataTypeManager.hasDataTypeFactory(namespaceIndex)) {
461
+ const dataTypeFactory1 = new node_opcua_factory_1.DataTypeFactory([(0, node_opcua_factory_1.getStandardDataTypeFactory)()]);
462
+ dataTypeManager.registerDataTypeFactory(namespaceIndex, dataTypeFactory1);
463
+ }
464
+ }
465
+ }
466
+ /// to do :: may be not useful
467
+ if (!dataValueNamespaceArray.value.value && dataTypeManager.namespaceArray.length === 0) {
468
+ dataTypeManager.setNamespaceArray([]);
469
+ }
470
+ const dataTypeDictionaryType = (0, node_opcua_nodeid_1.resolveNodeId)("DataTypeDictionaryType");
471
+ // DataType/OPCBinary => i=93 [OPCBinarySchema_TypeSystem]
472
+ // "OPC Binary"[DataSystemType]
473
+ const opcBinaryNodeId = (0, node_opcua_nodeid_1.resolveNodeId)("OPCBinarySchema_TypeSystem");
474
+ // let find all DataType dictionary node corresponding to a given namespace
475
+ // (have DataTypeDictionaryType)
476
+ const nodeToBrowse = {
477
+ browseDirection: node_opcua_service_browse_1.BrowseDirection.Forward,
478
+ includeSubtypes: false,
479
+ nodeClassMask: (0, node_opcua_data_model_1.makeNodeClassMask)("Variable"),
480
+ nodeId: opcBinaryNodeId,
481
+ referenceTypeId: (0, node_opcua_nodeid_1.resolveNodeId)("HasComponent"),
482
+ resultMask: (0, node_opcua_data_model_1.makeResultMask)("ReferenceType | IsForward | BrowseName | NodeClass | TypeDefinition")
483
+ };
484
+ const result = yield (0, node_opcua_pseudo_session_1.browseAll)(session, nodeToBrowse);
485
+ if (doDebug) {
486
+ debugLog(result.statusCode.toString());
487
+ debugLog((_a = result.references) === null || _a === void 0 ? void 0 : _a.map((r) => { var _a; return (_a = r.browseName) === null || _a === void 0 ? void 0 : _a.toString(); }).join(" "));
488
+ }
489
+ // filter nodes that have the expected namespace Index
490
+ // ( more specifically we want to filter out DataStructure from namespace 0)
491
+ // we also want to keep only object of type DataTypeDictionaryType
492
+ const references = result.references.filter((e) => e.nodeId.namespace !== 0 && (0, node_opcua_nodeid_1.sameNodeId)(e.typeDefinition, dataTypeDictionaryType));
493
+ debugLog(`found ${references.length} dictionary`);
494
+ function putInCorrectOrder() {
495
+ return __awaiter(this, void 0, void 0, function* () {
496
+ const infos = [];
497
+ const innerMap = {};
498
+ for (const reference of references) {
499
+ const dataTypeDictionaryNodeId = reference.nodeId;
500
+ const isDictionaryDeprecated = yield _readDeprecatedFlag(session, dataTypeDictionaryNodeId);
501
+ const rawSchemaDataValue = yield session.read({
502
+ attributeId: node_opcua_data_model_1.AttributeIds.Value,
503
+ nodeId: dataTypeDictionaryNodeId
504
+ });
505
+ const rawSchema = rawSchemaDataValue.value.value ? rawSchemaDataValue.value.value.toString() : "";
506
+ const info = {
507
+ dataTypeDictionaryNodeId,
508
+ dependencies: {},
509
+ isDictionaryDeprecated,
510
+ rawSchema,
511
+ reference,
512
+ targetNamespace: ""
513
+ };
514
+ infos.push(info);
515
+ if (!isDictionaryDeprecated && rawSchema.length > 0) {
516
+ if (doDebug) {
517
+ console.log("schema", rawSchema);
518
+ }
519
+ const matches = rawSchema.match(/<opc:TypeDictionary([^>]+)>/);
520
+ if (matches) {
521
+ // extract xml:NS="namespace" from attribute list
522
+ // for instance:
523
+ // <opc:TypeDictionary
524
+ // xmlns:opc="http://opcfoundation.org/BinarySchema/"
525
+ // xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
526
+ // xmlns:ua="http://opcfoundation.org/UA/"
527
+ // xmlns:tns="urn:SomeName:Ua:Types:GlobalTypes"
528
+ // DefaultByteOrder="LittleEndian"
529
+ // TargetNamespace="urn:SomeName:Ua:Types:GlobalTypes">
530
+ const typeDictionaryElementAttributes = matches[1];
531
+ info.targetNamespace = extractTargetNamespaceAttribute(typeDictionaryElementAttributes);
532
+ const nsKeyNamespace = {};
533
+ for (const attribute of typeDictionaryElementAttributes.split(" ")) {
534
+ const r = extraNamespaceRef(attribute);
535
+ if (r) {
536
+ const { xmlns, namespace } = r;
537
+ nsKeyNamespace[xmlns] = namespace;
538
+ debugLog("xxxx ns= ", xmlns, "=>", namespace);
539
+ }
540
+ }
541
+ info.dependencies = nsKeyNamespace;
542
+ debugLog("xxx targetNamespace = ", info.targetNamespace);
543
+ innerMap[info.targetNamespace] = info;
544
+ }
545
+ }
546
+ else {
547
+ // may be 1.04 => the rawSchema is no more needed in new version
548
+ info.targetNamespace = namespaceArray[dataTypeDictionaryNodeId.namespace];
549
+ debugLog("xxx targetNamespace = ", info.targetNamespace);
550
+ innerMap[info.targetNamespace] = info;
551
+ }
552
+ // assert(info.targetNamespace.length !== 0);
553
+ }
554
+ // ----------------------------------
555
+ const orderedList = [];
556
+ const visited = {};
557
+ function explore(d) {
558
+ if (visited[d.targetNamespace]) {
559
+ return;
560
+ }
561
+ visited[d.targetNamespace] = 1;
562
+ for (const [xmlns, namespace] of Object.entries(d.dependencies)) {
563
+ if (!innerMap[namespace] || namespace === d.targetNamespace) {
564
+ continue;
565
+ }
566
+ explore(innerMap[namespace]);
567
+ }
568
+ orderedList.push(d);
569
+ }
570
+ for (const d of infos) {
571
+ explore(d);
572
+ }
573
+ debugLog(" Ordered List = ", orderedList.map((a) => a.targetNamespace).join(" "));
574
+ return orderedList;
575
+ });
576
+ }
577
+ const dataTypeDictionaryInfo = yield putInCorrectOrder();
578
+ // setup dependencies
579
+ const map = {};
580
+ for (const d of dataTypeDictionaryInfo) {
581
+ map[d.targetNamespace] = d;
582
+ debugLog(" fixing based dataTypeFactory dependencies for ", d.targetNamespace, "index = ", d.dataTypeDictionaryNodeId.namespace);
583
+ const baseDataFactories = [(0, node_opcua_factory_1.getStandardDataTypeFactory)()];
584
+ for (const namespace of Object.values(d.dependencies)) {
585
+ if (namespace === d.targetNamespace) {
586
+ continue;
587
+ }
588
+ const baseDataFactory = map[namespace];
589
+ if (!baseDataFactory) {
590
+ // xx console.log("xxxxx baseDataFactory = ", namespace);
591
+ continue;
592
+ }
593
+ const namespaceIndex = baseDataFactory.dataTypeDictionaryNodeId.namespace;
594
+ if (dataTypeManager.hasDataTypeFactory(namespaceIndex)) {
595
+ const dep = dataTypeManager.getDataTypeFactory(namespaceIndex);
596
+ baseDataFactories.push(dep);
597
+ debugLog(" considering , ", baseDataFactory.targetNamespace, "index = ", baseDataFactory.dataTypeDictionaryNodeId.namespace);
598
+ }
599
+ }
600
+ const dataTypeFactory = dataTypeManager.getDataTypeFactory(d.dataTypeDictionaryNodeId.namespace);
601
+ if (dataTypeFactory) {
602
+ dataTypeFactory.repairBaseDataFactories(baseDataFactories);
603
+ }
604
+ }
605
+ // --------------------
606
+ // now investigate DataTypeDescriptionType
607
+ function processReferenceOnDataTypeDictionaryType(d) {
608
+ return __awaiter(this, void 0, void 0, function* () {
609
+ debugLog(chalk.cyan("processReferenceOnDataTypeDictionaryType on "), d.targetNamespace);
610
+ const ref = d.reference;
611
+ const dataTypeDictionaryNodeId = d.reference.nodeId;
612
+ yield _extractDataTypeDictionary(session, d, dataTypeManager);
613
+ /* istanbul ignore next */
614
+ if (doDebug) {
615
+ debugLog(chalk.bgWhite(" => "), ref.browseName.toString(), ref.nodeId.toString());
616
+ }
617
+ const dataTypeFactory = dataTypeManager.getDataTypeFactoryForNamespace(dataTypeDictionaryNodeId.namespace);
618
+ yield _exploreDataTypeDefinition(session, dataTypeDictionaryNodeId, dataTypeFactory, dataTypeManager.namespaceArray);
619
+ });
620
+ }
621
+ // https://medium.com/swlh/dealing-with-multiple-promises-in-javascript-41d6c21f20ff
622
+ for (const d of dataTypeDictionaryInfo) {
623
+ try {
624
+ yield processReferenceOnDataTypeDictionaryType(d).catch((e) => {
625
+ console.log(e);
626
+ debugLog("processReferenceOnDataTypeDictionaryType has failed ");
627
+ debugLog("Error", e.message);
628
+ debugLog(e);
629
+ return e;
630
+ });
631
+ }
632
+ catch (err) {
633
+ debugLog(chalk.red("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx "), err);
634
+ }
635
+ }
636
+ debugLog("out ... populateDataTypeManager");
637
+ });
638
+ }
639
+ exports.populateDataTypeManager103 = populateDataTypeManager103;
640
+ //# sourceMappingURL=populate_data_type_manager_103.js.map