node-opcua-client-dynamic-extension-object
Advanced tools
Comparing version 2.1.0 to 2.1.1
@@ -0,1 +1,2 @@ | ||
import { StructuredTypeSchema } from "node-opcua-factory"; | ||
import { NodeId } from "node-opcua-nodeid"; | ||
@@ -6,3 +7,9 @@ import { IBasicSession } from "node-opcua-pseudo-session"; | ||
export declare function exploreDataTypeDefinition(session: IBasicSession, dataTypeDictionaryTypeNode: NodeId, typeDictionary: TypeDictionary, namespaces: string[]): Promise<void>; | ||
/** | ||
* Extract all custom dataType | ||
* @param session | ||
* @param dataTypeManager | ||
* @async | ||
*/ | ||
export declare function extractNamespaceDataType(session: IBasicSession, dataTypeManager: ExtraDataTypeManager): Promise<void>; | ||
export declare function getDataTypeDefinition(session: IBasicSession, dataTypeNodeId: NodeId): Promise<void>; | ||
export declare function getDataTypeDefinition(session: IBasicSession, dataTypeNodeId: NodeId, extraDataTypeManager: ExtraDataTypeManager): Promise<StructuredTypeSchema>; |
@@ -57,3 +57,3 @@ "use strict"; | ||
} | ||
// request the Definition of each not | ||
// request the Definition of each nodes | ||
const nodesToBrowse2 = references.map((ref) => { | ||
@@ -84,2 +84,3 @@ return { | ||
if (doDebug) { | ||
// let's verify that constructor is operational | ||
try { | ||
@@ -97,2 +98,8 @@ const testObject = new constructor(); | ||
exports.exploreDataTypeDefinition = exploreDataTypeDefinition; | ||
/** | ||
* Extract all custom dataType | ||
* @param session | ||
* @param dataTypeManager | ||
* @async | ||
*/ | ||
function extractNamespaceDataType(session, dataTypeManager) { | ||
@@ -110,2 +117,4 @@ return __awaiter(this, void 0, void 0, function* () { | ||
const opcBinaryNodeId = node_opcua_nodeid_1.resolveNodeId("OPCBinarySchema_TypeSystem"); | ||
// let find all DataType dictionary node corresponding to a given namespace | ||
// (have DataTypeDictionaryType) | ||
const nodeToBrowse = { | ||
@@ -121,16 +130,22 @@ browseDirection: node_opcua_service_browse_1.BrowseDirection.Forward, | ||
// filter nodes that have the expected namespace Index | ||
// ( more specifically we want to filter out DataStructure from namespace 0) | ||
const references = result.references.filter((e) => e.nodeId.namespace !== 0); | ||
/* istanbul ignore next */ | ||
if (references.length === 0) { | ||
return; | ||
const promises = []; | ||
const dataTypeDictionaryType = node_opcua_nodeid_1.resolveNodeId("DataTypeDictionaryType"); | ||
function processReference(ref) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
node_opcua_assert_1.assert(ref.typeDefinition.toString() === dataTypeDictionaryType.toString()); | ||
const typeDictionary = yield extractSchema(session, ref.nodeId); | ||
yield exploreDataTypeDefinition(session, ref.nodeId, typeDictionary, dataTypeManager.namespaceArray); | ||
dataTypeManager.registerTypeDictionary(ref.nodeId, typeDictionary); | ||
}); | ||
} | ||
for (const ref of references) { | ||
const typeDictionary = yield extractSchema(session, ref.nodeId); | ||
yield exploreDataTypeDefinition(session, ref.nodeId, typeDictionary, dataTypeManager.namespaceArray); | ||
dataTypeManager.registerTypeDictionary(ref.nodeId, typeDictionary); | ||
promises.push(processReference(ref)); | ||
} | ||
yield Promise.all(promises); | ||
}); | ||
} | ||
exports.extractNamespaceDataType = extractNamespaceDataType; | ||
function getDataTypeDefinition(session, dataTypeNodeId) { | ||
function getDataTypeDefinition(session, dataTypeNodeId, extraDataTypeManager) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -161,3 +176,23 @@ // DataType | ||
const result1 = yield session.browse(nodeToBrowse1); | ||
node_opcua_assert_1.assert(result1.references && result1.references.length === 1); | ||
if (result1.references && result1.references.length > 1) { | ||
// we have more than one possible Encoding .... only keep "Default Binary" | ||
result1.references = result1.references.filter((r) => r.browseName.toString() === "Default Binary"); | ||
} | ||
/* istanbul ignore next */ | ||
if (!(result1.references && result1.references.length === 1)) { | ||
const nodeClass = yield session.read({ | ||
attributeId: node_opcua_data_model_1.AttributeIds.NodeClass, | ||
nodeId: dataTypeNodeId | ||
}); | ||
const browseName = yield session.read({ | ||
attributeId: node_opcua_data_model_1.AttributeIds.BrowseName, | ||
nodeId: dataTypeNodeId | ||
}); | ||
// tslint:disable:no-console | ||
console.log("node-id :", dataTypeNodeId.toString()); | ||
console.log("nodeClass :", node_opcua_data_model_1.NodeClass[nodeClass.value.value]); | ||
console.log("browseName :", browseName.value.value.toString()); | ||
console.log(result1.toString()); | ||
throw new Error("getDataTypeDefinition invalid HasEncoding reference"); | ||
} | ||
const encodingReference = result1.references[0]; | ||
@@ -196,4 +231,16 @@ node_opcua_assert_1.assert(encodingReference.browseName.toString() === "Default Binary"); | ||
const schemaNode = result3.references[0].nodeId; | ||
const typeDictionary = yield extractSchema(session, schemaNode); | ||
return typeDictionary.structuredTypes[name]; | ||
let schema; | ||
if (extraDataTypeManager) { | ||
const typeDictionary = extraDataTypeManager.getTypeDictionaryForNamespace(schemaNode.namespace); | ||
schema = typeDictionary.structuredTypes[name]; | ||
} | ||
else { | ||
const typeDictionary = yield extractSchema(session, schemaNode); | ||
schema = typeDictionary.structuredTypes[name]; | ||
} | ||
// associate DataTypeId with schema if not already done | ||
if (schema.id.value === 0) { | ||
schema.id = dataTypeNodeId; | ||
} | ||
return schema; | ||
}); | ||
@@ -200,0 +247,0 @@ } |
@@ -1,9 +0,7 @@ | ||
/** | ||
* @module node-opcua-client-dynamic-extension-object | ||
*/ | ||
import { NodeId } from "node-opcua-nodeid"; | ||
import { TypeDictionary } from "node-opcua-schemas"; | ||
import { AnyConstructorFunc, TypeDictionary } from "node-opcua-schemas"; | ||
export declare class ExtraDataTypeManager { | ||
namespaceArray: string[]; | ||
private readonly typeDictionaries; | ||
private readonly typeDictionariesByNamespace; | ||
constructor(); | ||
@@ -13,3 +11,6 @@ setNamespaceArray(namespaceArray: string[]): void; | ||
registerTypeDictionary(nodeId: NodeId, typeDictionary: TypeDictionary): void; | ||
getTypeDictionaryForNamespace(namespaceIndex: number): TypeDictionary; | ||
getExtensionObjectConstructorFromDataType(dataTypeNodeId: NodeId): AnyConstructorFunc; | ||
getExtensionObjectConstructorFromBinaryEncoding(binaryEncodingNodeId: NodeId): AnyConstructorFunc; | ||
private makeKey; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* @module node-opcua-client-dynamic-extension-object | ||
*/ | ||
const node_opcua_assert_1 = require("node-opcua-assert"); | ||
const node_opcua_schemas_1 = require("node-opcua-schemas"); | ||
class ExtraDataTypeManager { | ||
@@ -7,2 +12,3 @@ constructor() { | ||
this.typeDictionaries = {}; | ||
this.typeDictionariesByNamespace = {}; | ||
/* */ | ||
@@ -22,3 +28,24 @@ } | ||
this.typeDictionaries[this.makeKey(nodeId)] = typeDictionary; | ||
node_opcua_assert_1.default(nodeId.namespace !== 0, "registerTypeDictionary cannot be used for namespace 0"); | ||
node_opcua_assert_1.default(!this.typeDictionariesByNamespace.hasOwnProperty(nodeId.namespace), "already registered"); | ||
this.typeDictionariesByNamespace[nodeId.namespace] = typeDictionary; | ||
} | ||
getTypeDictionaryForNamespace(namespaceIndex) { | ||
node_opcua_assert_1.default(namespaceIndex !== 0, "getTypeDictionaryForNamespace cannot be used for namespace 0"); | ||
return this.typeDictionariesByNamespace[namespaceIndex]; | ||
} | ||
getExtensionObjectConstructorFromDataType(dataTypeNodeId) { | ||
const typeDictionary = this.getTypeDictionaryForNamespace(dataTypeNodeId.namespace); | ||
// find schema corresponding to dataTypeNodeId in typeDictionary | ||
const schema = findSchemaForDataType(typeDictionary, dataTypeNodeId); | ||
const Constructor = node_opcua_schemas_1.createDynamicObjectConstructor(schema, typeDictionary); | ||
return Constructor; | ||
} | ||
getExtensionObjectConstructorFromBinaryEncoding(binaryEncodingNodeId) { | ||
const typeDictionary = this.getTypeDictionaryForNamespace(binaryEncodingNodeId.namespace); | ||
// find schema corresponding to binaryEncodingNodeId in typeDictionary | ||
const schema = findSchemaForBinaryEncoding(typeDictionary, binaryEncodingNodeId); | ||
const Constructor = node_opcua_schemas_1.createDynamicObjectConstructor(schema, typeDictionary); | ||
return Constructor; | ||
} | ||
makeKey(nodeId) { | ||
@@ -29,2 +56,30 @@ return this.namespaceArray[nodeId.namespace] + "@" + nodeId.value.toString(); | ||
exports.ExtraDataTypeManager = ExtraDataTypeManager; | ||
function findSchemaForDataType(typeDictionary, dataTypeNodeId) { | ||
for (const k of Object.keys(typeDictionary.structuredTypes)) { | ||
const schema = typeDictionary.structuredTypes[k]; | ||
if (schema.id.value === dataTypeNodeId.value) { | ||
node_opcua_assert_1.default(schema.id.namespace === dataTypeNodeId.namespace); | ||
return schema; | ||
} | ||
} | ||
throw new Error("findSchemaForDataType: Cannot find schema for " + dataTypeNodeId.toString() | ||
+ " in " + | ||
Object.keys(typeDictionary.structuredTypes).map((a) => a + ":" + | ||
typeDictionary.structuredTypes[a].id.toString()).join("\n")); | ||
} | ||
function findSchemaForBinaryEncoding(typeDictionary, binaryEncodingNodeId) { | ||
for (const k of Object.keys(typeDictionary.structuredTypes)) { | ||
const schema = typeDictionary.structuredTypes[k]; | ||
if (schema.encodingDefaultBinary && | ||
schema.encodingDefaultBinary.value === binaryEncodingNodeId.value) { | ||
node_opcua_assert_1.default(schema.encodingDefaultBinary.namespace === binaryEncodingNodeId.namespace); | ||
return schema; | ||
} | ||
} | ||
throw new Error("findSchemaForBinaryEncoding: Cannot find schema for " + binaryEncodingNodeId.toString() | ||
+ " in " + | ||
Object.keys(typeDictionary.structuredTypes).map((a) => a + " " + | ||
(typeDictionary.structuredTypes[a].encodingDefaultBinary ? | ||
typeDictionary.structuredTypes[a].encodingDefaultBinary.toString() : "None")).join("\n")); | ||
} | ||
//# sourceMappingURL=extra_data_type_manager.js.map |
@@ -7,1 +7,2 @@ /** | ||
export * from "./resolve_dynamic_extension_object"; | ||
export * from "./promote_opaque_structure"; |
@@ -12,2 +12,3 @@ "use strict"; | ||
__export(require("./resolve_dynamic_extension_object")); | ||
__export(require("./promote_opaque_structure")); | ||
//# sourceMappingURL=index.js.map |
@@ -13,5 +13,21 @@ "use strict"; | ||
const node_opcua_extension_object_1 = require("node-opcua-extension-object"); | ||
const node_opcua_factory_1 = require("node-opcua-factory"); | ||
const node_opcua_nodeid_1 = require("node-opcua-nodeid"); | ||
const node_opcua_variant_1 = require("node-opcua-variant"); | ||
function resolveDynamicExtensionObjectV(opaque, extraDataType) { | ||
try { | ||
const namespaceUri = extraDataType.namespaceArray[opaque.nodeId.namespace]; | ||
const expandedNodeId = node_opcua_nodeid_1.ExpandedNodeId.fromNodeId(opaque.nodeId, namespaceUri); | ||
const typeDictionary = extraDataType.getTypeDictionaryForNamespace(opaque.nodeId.namespace); | ||
const Constructor = extraDataType.getExtensionObjectConstructorFromBinaryEncoding(opaque.nodeId); | ||
const object = new Constructor(); | ||
const stream = new node_opcua_binary_stream_1.BinaryStream(opaque.buffer); | ||
object.decode(stream); | ||
return object; | ||
} | ||
catch (err) { | ||
// tslint:disable-next-line:no-console | ||
console.log("resolveDynamicExtensionObjectV err = ", err); | ||
return opaque; | ||
} | ||
} | ||
function resolveDynamicExtensionObject(variant, extraDataType) { | ||
@@ -22,12 +38,18 @@ return __awaiter(this, void 0, void 0, function* () { | ||
} | ||
if (variant.arrayType !== node_opcua_variant_1.VariantArrayType.Scalar) { | ||
if (variant.value instanceof Array) { | ||
variant.value = variant.value.map((v) => { | ||
if (!(v instanceof node_opcua_extension_object_1.OpaqueStructure)) { | ||
return v; | ||
} | ||
const obj = resolveDynamicExtensionObjectV(v, extraDataType); | ||
return obj; | ||
}); | ||
} | ||
return; | ||
} | ||
if (!(variant.value instanceof node_opcua_extension_object_1.OpaqueStructure)) { | ||
return; | ||
} | ||
const opaque = variant.value; | ||
const namespaceUri = extraDataType.namespaceArray[opaque.nodeId.namespace]; | ||
const exapndedNodeId = node_opcua_nodeid_1.ExpandedNodeId.fromNodeId(opaque.nodeId, namespaceUri); | ||
const object = node_opcua_factory_1.constructObject(exapndedNodeId); | ||
const stream = new node_opcua_binary_stream_1.BinaryStream(opaque.buffer); | ||
object.decode(stream); | ||
variant.value = object; | ||
variant.value = resolveDynamicExtensionObjectV(variant.value, extraDataType); | ||
}); | ||
@@ -34,0 +56,0 @@ } |
{ | ||
"name": "node-opcua-client-dynamic-extension-object", | ||
"version": "2.1.0", | ||
"version": "2.1.1", | ||
"description": "pure nodejs OPCUA SDK - module -extension-object", | ||
@@ -15,12 +15,13 @@ "main": "./dist/index.js", | ||
"node-opcua-binary-stream": "^2.1.0", | ||
"node-opcua-data-model": "^2.1.0", | ||
"node-opcua-data-model": "^2.1.1", | ||
"node-opcua-data-value": "^2.1.1", | ||
"node-opcua-debug": "^2.1.0", | ||
"node-opcua-extension-object": "^2.1.0", | ||
"node-opcua-factory": "^2.1.0", | ||
"node-opcua-extension-object": "^2.1.1", | ||
"node-opcua-factory": "^2.1.1", | ||
"node-opcua-nodeid": "^2.1.0", | ||
"node-opcua-pseudo-session": "^2.1.0", | ||
"node-opcua-schemas": "^2.1.0", | ||
"node-opcua-service-browse": "^2.1.0", | ||
"node-opcua-status-code": "^2.1.0", | ||
"node-opcua-variant": "^2.1.0" | ||
"node-opcua-pseudo-session": "^2.1.1", | ||
"node-opcua-schemas": "^2.1.1", | ||
"node-opcua-service-browse": "^2.1.1", | ||
"node-opcua-status-code": "^2.1.1", | ||
"node-opcua-variant": "^2.1.1" | ||
}, | ||
@@ -42,3 +43,3 @@ "author": "Etienne Rossignon", | ||
"homepage": "http://node-opcua.github.io/", | ||
"gitHead": "ddce2b6e3e13371510e63d839c1a4c4ff0be2c15" | ||
"gitHead": "672816a1babe8c9347f85e47cf4e947f4749507e" | ||
} |
@@ -11,3 +11,3 @@ /** | ||
makeNodeClassMask, | ||
makeResultMask, | ||
makeResultMask, NodeClass | ||
} from "node-opcua-data-model"; | ||
@@ -19,7 +19,11 @@ import { | ||
import { | ||
StructuredTypeSchema | ||
} from "node-opcua-factory"; | ||
import { | ||
ExpandedNodeId, | ||
NodeId, | ||
resolveNodeId, | ||
resolveNodeId | ||
} from "node-opcua-nodeid"; | ||
import { | ||
BrowseDescriptionLike, | ||
IBasicSession | ||
@@ -33,8 +37,13 @@ } from "node-opcua-pseudo-session"; | ||
import { | ||
BrowseDescription, | ||
BrowseDirection, | ||
BrowseResult, | ||
ReferenceDescription, | ||
ReferenceDescription | ||
} from "node-opcua-service-browse"; | ||
import { StatusCodes } from "node-opcua-status-code"; | ||
import { ExtraDataTypeManager } from "./extra_data_type_manager"; | ||
import { | ||
StatusCodes | ||
} from "node-opcua-status-code"; | ||
import { | ||
ExtraDataTypeManager | ||
} from "./extra_data_type_manager"; | ||
@@ -61,6 +70,6 @@ const doDebug = checkDebugFlag(__filename); | ||
export async function exploreDataTypeDefinition( | ||
session: IBasicSession, | ||
dataTypeDictionaryTypeNode: NodeId, | ||
typeDictionary: TypeDictionary, | ||
namespaces: string[] | ||
session: IBasicSession, | ||
dataTypeDictionaryTypeNode: NodeId, | ||
typeDictionary: TypeDictionary, | ||
namespaces: string[] | ||
) { | ||
@@ -84,3 +93,3 @@ | ||
// request the Definition of each not | ||
// request the Definition of each nodes | ||
const nodesToBrowse2 = references.map((ref: ReferenceDescription) => { | ||
@@ -99,3 +108,3 @@ return { | ||
const binaryEncodingNodeIds = results2.map((br: BrowseResult) => { | ||
const defaultBin = br.references!.filter((r: ReferenceDescription) => r.browseName.toString() === "Default Binary"); | ||
const defaultBin = br.references!.filter((r: ReferenceDescription) => r.browseName.toString() === "Default Binary"); | ||
@@ -117,2 +126,3 @@ /* istanbul ignore next */ | ||
if (doDebug) { | ||
// let's verify that constructor is operational | ||
try { | ||
@@ -128,5 +138,11 @@ const testObject = new constructor(); | ||
/** | ||
* Extract all custom dataType | ||
* @param session | ||
* @param dataTypeManager | ||
* @async | ||
*/ | ||
export async function extractNamespaceDataType( | ||
session: IBasicSession, | ||
dataTypeManager: ExtraDataTypeManager | ||
session: IBasicSession, | ||
dataTypeManager: ExtraDataTypeManager | ||
) { | ||
@@ -147,3 +163,5 @@ | ||
const nodeToBrowse = { | ||
// let find all DataType dictionary node corresponding to a given namespace | ||
// (have DataTypeDictionaryType) | ||
const nodeToBrowse: BrowseDescriptionLike = { | ||
browseDirection: BrowseDirection.Forward, | ||
@@ -159,10 +177,12 @@ includeSubtypes: false, | ||
// filter nodes that have the expected namespace Index | ||
// ( more specifically we want to filter out DataStructure from namespace 0) | ||
const references = result.references!.filter( | ||
(e: ReferenceDescription) => e.nodeId.namespace !== 0); | ||
(e: ReferenceDescription) => e.nodeId.namespace !== 0); | ||
/* istanbul ignore next */ | ||
if (references.length === 0) { | ||
return; | ||
} | ||
for (const ref of references) { | ||
const promises: Array<Promise<void>> = []; | ||
const dataTypeDictionaryType = resolveNodeId("DataTypeDictionaryType"); | ||
async function processReference(ref: ReferenceDescription): Promise<void> { | ||
assert(ref.typeDefinition.toString() === dataTypeDictionaryType.toString()); | ||
const typeDictionary = await extractSchema(session, ref.nodeId); | ||
@@ -173,5 +193,14 @@ await exploreDataTypeDefinition(session, ref.nodeId, typeDictionary, dataTypeManager.namespaceArray); | ||
for (const ref of references) { | ||
promises.push(processReference(ref)); | ||
} | ||
await Promise.all(promises); | ||
} | ||
export async function getDataTypeDefinition(session: IBasicSession, dataTypeNodeId: NodeId): Promise<void> { | ||
export async function getDataTypeDefinition( | ||
session: IBasicSession, | ||
dataTypeNodeId: NodeId, | ||
extraDataTypeManager: ExtraDataTypeManager | ||
): Promise<StructuredTypeSchema> { | ||
@@ -202,4 +231,29 @@ // DataType | ||
const result1 = await session.browse(nodeToBrowse1); | ||
assert(result1.references && result1.references.length === 1); | ||
if (result1.references && result1.references.length > 1) { | ||
// we have more than one possible Encoding .... only keep "Default Binary" | ||
result1.references = result1.references.filter((r: ReferenceDescription) => | ||
r.browseName.toString() === "Default Binary"); | ||
} | ||
/* istanbul ignore next */ | ||
if (!(result1.references && result1.references.length === 1)) { | ||
const nodeClass = await session.read({ | ||
attributeId: AttributeIds.NodeClass, | ||
nodeId: dataTypeNodeId | ||
}); | ||
const browseName = await session.read({ | ||
attributeId: AttributeIds.BrowseName, | ||
nodeId: dataTypeNodeId | ||
}); | ||
// tslint:disable:no-console | ||
console.log("node-id :", dataTypeNodeId.toString()); | ||
console.log("nodeClass :", NodeClass[nodeClass.value.value]); | ||
console.log("browseName :", browseName.value.value.toString()); | ||
console.log(result1.toString()); | ||
throw new Error("getDataTypeDefinition invalid HasEncoding reference"); | ||
} | ||
const encodingReference = result1.references![0]!; | ||
@@ -243,4 +297,18 @@ assert(encodingReference.browseName.toString() === "Default Binary"); | ||
const schemaNode = result3.references![0]!.nodeId; | ||
const typeDictionary = await extractSchema(session, schemaNode); | ||
return (typeDictionary.structuredTypes as any)[name]; | ||
let schema: StructuredTypeSchema; | ||
if (extraDataTypeManager) { | ||
const typeDictionary = extraDataTypeManager.getTypeDictionaryForNamespace(schemaNode.namespace); | ||
schema = typeDictionary.structuredTypes[name]; | ||
} else { | ||
const typeDictionary = await extractSchema(session, schemaNode); | ||
schema = typeDictionary.structuredTypes[name]; | ||
} | ||
// associate DataTypeId with schema if not already done | ||
if (schema.id.value === 0 ) { | ||
schema.id = dataTypeNodeId; | ||
} | ||
return schema; | ||
} |
/** | ||
* @module node-opcua-client-dynamic-extension-object | ||
*/ | ||
import assert from "node-opcua-assert"; | ||
import { StructuredTypeSchema } from "node-opcua-factory"; | ||
import { NodeId } from "node-opcua-nodeid"; | ||
import { TypeDictionary } from "node-opcua-schemas"; | ||
import { AnyConstructorFunc, createDynamicObjectConstructor, TypeDictionary } from "node-opcua-schemas"; | ||
@@ -11,3 +13,4 @@ export class ExtraDataTypeManager { | ||
private readonly typeDictionaries: any = {}; | ||
private readonly typeDictionaries: { [key: string]: TypeDictionary } = {}; | ||
private readonly typeDictionariesByNamespace: { [key: number]: TypeDictionary } = {}; | ||
@@ -33,4 +36,35 @@ constructor() { | ||
this.typeDictionaries[this.makeKey(nodeId)] = typeDictionary; | ||
assert(nodeId.namespace !== 0, | ||
"registerTypeDictionary cannot be used for namespace 0"); | ||
assert(!this.typeDictionariesByNamespace.hasOwnProperty(nodeId.namespace), | ||
"already registered"); | ||
this.typeDictionariesByNamespace[nodeId.namespace] = typeDictionary; | ||
} | ||
public getTypeDictionaryForNamespace(namespaceIndex: number): TypeDictionary { | ||
assert(namespaceIndex !== 0, | ||
"getTypeDictionaryForNamespace cannot be used for namespace 0"); | ||
return this.typeDictionariesByNamespace[namespaceIndex]; | ||
} | ||
public getExtensionObjectConstructorFromDataType( | ||
dataTypeNodeId: NodeId | ||
): AnyConstructorFunc { | ||
const typeDictionary = this.getTypeDictionaryForNamespace(dataTypeNodeId.namespace); | ||
// find schema corresponding to dataTypeNodeId in typeDictionary | ||
const schema = findSchemaForDataType(typeDictionary, dataTypeNodeId); | ||
const Constructor = createDynamicObjectConstructor(schema, typeDictionary); | ||
return Constructor; | ||
} | ||
public getExtensionObjectConstructorFromBinaryEncoding( | ||
binaryEncodingNodeId: NodeId | ||
): AnyConstructorFunc { | ||
const typeDictionary = this.getTypeDictionaryForNamespace(binaryEncodingNodeId.namespace); | ||
// find schema corresponding to binaryEncodingNodeId in typeDictionary | ||
const schema = findSchemaForBinaryEncoding(typeDictionary, binaryEncodingNodeId); | ||
const Constructor = createDynamicObjectConstructor(schema, typeDictionary); | ||
return Constructor; | ||
} | ||
private makeKey(nodeId: NodeId): string { | ||
@@ -41,1 +75,43 @@ return this.namespaceArray[nodeId.namespace] + "@" + nodeId.value.toString(); | ||
} | ||
function findSchemaForDataType( | ||
typeDictionary: TypeDictionary, | ||
dataTypeNodeId: NodeId | ||
): StructuredTypeSchema { | ||
for (const k of Object.keys(typeDictionary.structuredTypes)) { | ||
const schema = typeDictionary.structuredTypes[k]; | ||
if (schema.id.value === dataTypeNodeId.value) { | ||
assert(schema.id.namespace === dataTypeNodeId.namespace); | ||
return schema; | ||
} | ||
} | ||
throw new Error("findSchemaForDataType: Cannot find schema for " + dataTypeNodeId.toString() | ||
+ " in " + | ||
Object.keys(typeDictionary.structuredTypes).map( | ||
(a) => a + ":" + | ||
typeDictionary.structuredTypes[a].id.toString()).join("\n")); | ||
} | ||
function findSchemaForBinaryEncoding( | ||
typeDictionary: TypeDictionary, | ||
binaryEncodingNodeId: NodeId | ||
): StructuredTypeSchema { | ||
for (const k of Object.keys(typeDictionary.structuredTypes)) { | ||
const schema = typeDictionary.structuredTypes[k]; | ||
if (schema.encodingDefaultBinary && | ||
schema.encodingDefaultBinary!.value === binaryEncodingNodeId.value) { | ||
assert(schema.encodingDefaultBinary!.namespace === binaryEncodingNodeId.namespace); | ||
return schema; | ||
} | ||
} | ||
throw new Error("findSchemaForBinaryEncoding: Cannot find schema for " + binaryEncodingNodeId.toString() | ||
+ " in " + | ||
Object.keys(typeDictionary.structuredTypes).map( | ||
(a) => a + " " + | ||
(typeDictionary.structuredTypes[a].encodingDefaultBinary ? | ||
typeDictionary.structuredTypes[a].encodingDefaultBinary!.toString() : "None")).join("\n")); | ||
} |
@@ -7,1 +7,2 @@ /** | ||
export * from "./resolve_dynamic_extension_object"; | ||
export * from "./promote_opaque_structure"; |
import { BinaryStream } from "node-opcua-binary-stream"; | ||
import { OpaqueStructure } from "node-opcua-extension-object"; | ||
import { ExtensionObject, OpaqueStructure } from "node-opcua-extension-object"; | ||
import { constructObject } from "node-opcua-factory"; | ||
import { ExpandedNodeId } from "node-opcua-nodeid"; | ||
import { DataType, Variant } from "node-opcua-variant"; | ||
import { DataType, Variant, VariantArrayType } from "node-opcua-variant"; | ||
import { ExtraDataTypeManager } from "./extra_data_type_manager"; | ||
function resolveDynamicExtensionObjectV( | ||
opaque: OpaqueStructure, | ||
extraDataType: ExtraDataTypeManager | ||
): ExtensionObject { | ||
try { | ||
const namespaceUri = extraDataType.namespaceArray[opaque.nodeId.namespace]; | ||
const expandedNodeId = ExpandedNodeId.fromNodeId(opaque.nodeId, namespaceUri); | ||
const typeDictionary = extraDataType.getTypeDictionaryForNamespace(opaque.nodeId.namespace); | ||
const Constructor = extraDataType.getExtensionObjectConstructorFromBinaryEncoding(opaque.nodeId); | ||
const object = new Constructor(); | ||
const stream = new BinaryStream(opaque.buffer); | ||
object.decode(stream); | ||
return object; | ||
} catch (err) { | ||
// tslint:disable-next-line:no-console | ||
console.log("resolveDynamicExtensionObjectV err = ", err); | ||
return opaque; | ||
} | ||
} | ||
export async function resolveDynamicExtensionObject( | ||
variant: Variant, | ||
extraDataType: ExtraDataTypeManager | ||
) { | ||
variant: Variant, | ||
extraDataType: ExtraDataTypeManager | ||
): Promise<void> { | ||
@@ -17,18 +41,23 @@ if (variant.dataType !== DataType.ExtensionObject) { | ||
} | ||
if (variant.arrayType !== VariantArrayType.Scalar) { | ||
if (variant.value instanceof Array) { | ||
variant.value = (variant.value as any[]).map((v: any) => { | ||
if (!(v instanceof OpaqueStructure)) { | ||
return v; | ||
} | ||
const obj = resolveDynamicExtensionObjectV(v as OpaqueStructure, extraDataType); | ||
return obj; | ||
}); | ||
} | ||
return; | ||
} | ||
if (!(variant.value instanceof OpaqueStructure)) { | ||
return; | ||
} | ||
variant.value = resolveDynamicExtensionObjectV( | ||
variant.value as OpaqueStructure, extraDataType); | ||
const opaque = variant.value as OpaqueStructure; | ||
const namespaceUri = extraDataType.namespaceArray[opaque.nodeId.namespace]; | ||
const exapndedNodeId = ExpandedNodeId.fromNodeId(opaque.nodeId, namespaceUri); | ||
const object = constructObject(exapndedNodeId); | ||
const stream = new BinaryStream(opaque.buffer); | ||
object.decode(stream); | ||
variant.value = object; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
61723
23
934
14
+ Addednode-opcua-data-value@^2.1.1
Updatednode-opcua-data-model@^2.1.1
Updatednode-opcua-factory@^2.1.1
Updatednode-opcua-schemas@^2.1.1
Updatednode-opcua-variant@^2.1.1