UNPKG

node-opcua-factory

Version:

pure nodejs OPCUA SDK - module factory

106 lines (88 loc) 4.16 kB
/** * @module node-opcua-factory */ import { assert } from "node-opcua-assert"; import { BinaryStream, OutputBinaryStream } from "node-opcua-binary-stream"; import { DataTypeIds } from "node-opcua-constants"; import { Enum, EnumItem, _TypescriptEnum, adaptTypescriptEnum } from "node-opcua-enum"; import { NodeId, resolveNodeId } from "node-opcua-nodeid"; import { TypeSchemaBase } from "./builtin_types"; import { EnumerationDefinition, TypeSchemaConstructorOptions } from "./types"; function _encode_enumeration(typedEnum: Enum, value: number, stream: OutputBinaryStream): void { assert(typeof value === "number", "Expecting a number here"); assert(typedEnum.get(value) !== undefined, "expecting a valid value"); stream.writeInteger(value); } function _decode_enumeration(typedEnum: Enum, stream: BinaryStream): number { const value = stream.readInteger(); const e = typedEnum.get(value) as any as string; // istanbul ignore next if (!e) { throw new Error("cannot coerce value=" + value + " to " + typedEnum.constructor.name); } return value; } export interface EnumerationDefinitionOptions extends TypeSchemaConstructorOptions { enumValues: _TypescriptEnum | string[]; typedEnum?: Enum; lengthInBits?: number; // specialized methods defaultValue?: EnumItem; encode?: (value: EnumItem, stream: OutputBinaryStream) => void; decode?: (stream: BinaryStream) => EnumItem; } export class EnumerationDefinitionSchema extends TypeSchemaBase implements EnumerationDefinition { public enumValues: _TypescriptEnum; public typedEnum: Enum; public lengthInBits: number; public dataTypeNodeId: NodeId; // xx encode: (value: EnumItem, stream: OutputBinaryStream) => void; // xx decode: (stream: BinaryStream) => EnumItem; constructor(dataTypeNodeId: NodeId, options: EnumerationDefinitionOptions) { super(options); this.dataTypeNodeId = dataTypeNodeId; // create a new Enum this.enumValues = adaptTypescriptEnum(options.enumValues); const typedEnum = new Enum(options.enumValues); options.typedEnum = typedEnum; assert(!options.encode || typeof options.encode === "function"); assert(!options.decode || typeof options.decode === "function"); this.encode = options.encode || _encode_enumeration.bind(null, typedEnum); this.decode = options.decode || _decode_enumeration.bind(null, typedEnum); this.typedEnum = options.typedEnum; this.defaultValue = this.typedEnum.getDefaultValue().value; this.lengthInBits = options.lengthInBits || 32; } } const _enumerations: Map<string, EnumerationDefinitionSchema> = new Map<string, EnumerationDefinitionSchema>(); /** * @param options * @param options.name {string} * @param options.enumValues [{key:Name, value:values}] * @param options.encode * @param options.decode * @param options.typedEnum * @param options.defaultValue * @return {Enum} */ export function registerEnumeration(options: EnumerationDefinitionOptions): Enum { const dataTypeNodeId = resolveNodeId(DataTypeIds[options.name as any]); assert(Object.prototype.hasOwnProperty.call(options, "name")); assert(Object.prototype.hasOwnProperty.call(options, "enumValues")); const name = options.name; if (Object.prototype.hasOwnProperty.call(_enumerations, name)) { throw new Error("factories.registerEnumeration : Enumeration " + options.name + " has been already inserted"); } const enumerationDefinition = new EnumerationDefinitionSchema(dataTypeNodeId, options); _enumerations.set(name, enumerationDefinition); return enumerationDefinition.typedEnum; } export function hasBuiltInEnumeration(enumerationName: string): boolean { return _enumerations.has(enumerationName); } export function getBuiltInEnumeration(enumerationName: string): EnumerationDefinitionSchema { if (!hasBuiltInEnumeration(enumerationName)) { throw new Error("Cannot find enumeration with type " + enumerationName); } return _enumerations.get(enumerationName) as EnumerationDefinitionSchema; }