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