|
@@ -0,0 +1,126 @@
|
|
|
+import { assert } from "./util/assert";
|
|
|
+
|
|
|
+
|
|
|
+export class NodeId {
|
|
|
+ public identifierType: NodeIdType;
|
|
|
+ public value: number | string;
|
|
|
+ public namespace: number;
|
|
|
+ constructor(identifierType?: NodeIdType | null, value?: number | string, namespace?: number) {
|
|
|
+ if (identifierType === null || identifierType === undefined) {
|
|
|
+ this.identifierType = NodeIdType.NUMERIC;
|
|
|
+ this.value = 0;
|
|
|
+ this.namespace = 0;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.identifierType = identifierType;
|
|
|
+ this.value = value || this.defaultValue(identifierType);
|
|
|
+ this.namespace = namespace || 0;
|
|
|
+
|
|
|
+ // namespace shall be a UInt16
|
|
|
+ assert(this.namespace >= 0 && this.namespace <= 0xffff, "NodeId: invalid namespace value");
|
|
|
+ assert(this.identifierType !== NodeIdType.NUMERIC || (this.value !== null && this.value as number >= 0 && this.value as number <= 0xffffffff));
|
|
|
+ assert(this.identifierType !== NodeIdType.STRING || typeof this.value === "string", "cannot empty string");
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ defaultValue(identifierType: NodeIdType): string | number {
|
|
|
+ switch (identifierType) {
|
|
|
+ case NodeIdType.STRING: return "";
|
|
|
+ case NodeIdType.NUMERIC: return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public toString(): string {
|
|
|
+ let str;
|
|
|
+ switch (this.identifierType) {
|
|
|
+ case NodeIdType.NUMERIC:
|
|
|
+ str = "ns=" + this.namespace + ";i=" + this.value;
|
|
|
+ break;
|
|
|
+ case NodeIdType.STRING:
|
|
|
+ str = "ns=" + this.namespace + ";s=" + this.value;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return str;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Convert a value into a nodeId:
|
|
|
+ * @class opcua
|
|
|
+ * @method coerceNodeId
|
|
|
+ * @static
|
|
|
+ *
|
|
|
+ * @description:
|
|
|
+ * - if nodeId is a string of form : "i=1234" => nodeId({value=1234, identifierType: NodeIdType.NUMERIC})
|
|
|
+ * - if nodeId is a string of form : "s=foo" => nodeId({value="foo", identifierType: NodeIdType.STRING})
|
|
|
+ * - if nodeId is a string of form : "b=ABCD=" => nodeId({value=decodeBase64("ABCD="), identifierType: NodeIdType.BYTESTRING})
|
|
|
+ * - if nodeId is a {@link NodeId} : coerceNodeId returns value
|
|
|
+ * @param value
|
|
|
+ * @param namespace {number}
|
|
|
+ */
|
|
|
+// eslint-disable-next-line max-statements
|
|
|
+ static coerceNodeId(value: unknown, namespace?: number): NodeId {
|
|
|
+ const regexNamespaceI = /ns=([0-9]+);i=([0-9]+)/;
|
|
|
+ const regexNamespaceS = /ns=([0-9]+);s=(.*)/;
|
|
|
+ let matches;
|
|
|
+ let twoFirst;
|
|
|
+ if (value instanceof NodeId) {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+ value = value || 0;
|
|
|
+ namespace = namespace || 0;
|
|
|
+
|
|
|
+ let identifierType = NodeIdType.NUMERIC;
|
|
|
+
|
|
|
+ if (typeof value === "string") {
|
|
|
+ identifierType = NodeIdType.STRING;
|
|
|
+
|
|
|
+ twoFirst = value.substring(0, 2);
|
|
|
+ if (twoFirst === "i=") {
|
|
|
+ identifierType = NodeIdType.NUMERIC;
|
|
|
+ value = parseInt(value.substring(2), 10);
|
|
|
+ } else if (twoFirst === "s=") {
|
|
|
+ identifierType = NodeIdType.STRING;
|
|
|
+ value = value.substring(2);
|
|
|
+
|
|
|
+ } else if ((matches = regexNamespaceI.exec(value)) !== null) {
|
|
|
+ identifierType = NodeIdType.NUMERIC;
|
|
|
+ namespace = parseInt(matches[1], 10);
|
|
|
+ value = parseInt(matches[2], 10);
|
|
|
+ } else if ((matches = regexNamespaceS.exec(value)) !== null) {
|
|
|
+ identifierType = NodeIdType.STRING;
|
|
|
+ namespace = parseInt(matches[1], 10);
|
|
|
+ value = matches[2];
|
|
|
+ } else {
|
|
|
+ throw new Error("String cannot be coerced to a nodeId : " + value);
|
|
|
+ }
|
|
|
+ } else if (value instanceof Object) {
|
|
|
+ // it could be a Enum or a NodeId Like object
|
|
|
+ const tmp = value as any;
|
|
|
+ value = tmp.value;
|
|
|
+ namespace = namespace || tmp.namespace;
|
|
|
+ identifierType = tmp.identifierType || identifierType;
|
|
|
+ return new NodeId(identifierType, value as any, namespace);
|
|
|
+ }
|
|
|
+ return new NodeId(identifierType, value as any, namespace);
|
|
|
+}
|
|
|
+}
|
|
|
+
|
|
|
+export enum NodeIdType {
|
|
|
+ /**
|
|
|
+ * @static
|
|
|
+ * @property NUMERIC
|
|
|
+ * @default 0x1
|
|
|
+ */
|
|
|
+ NUMERIC = 0x01,
|
|
|
+ /**
|
|
|
+ * @static
|
|
|
+ * @property STRING
|
|
|
+ * @default 0x2
|
|
|
+ */
|
|
|
+ STRING = 0x02,
|
|
|
+}
|
|
|
+
|