node-opcua-extension-object 2.51.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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014-2021 Etienne Rossignon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,16 @@
1
+ /// <reference types="node" />
2
+ import { BinaryStream, OutputBinaryStream } from "node-opcua-binary-stream";
3
+ import { BaseUAObject, StructuredTypeSchema } from "node-opcua-factory";
4
+ import { NodeId } from "node-opcua-nodeid";
5
+ export declare class ExtensionObject extends BaseUAObject {
6
+ static schema: StructuredTypeSchema;
7
+ constructor(options: any);
8
+ }
9
+ export declare function encodeExtensionObject(object: BaseUAObject | null, stream: OutputBinaryStream): void;
10
+ export declare class OpaqueStructure extends ExtensionObject {
11
+ nodeId: NodeId;
12
+ buffer: Buffer;
13
+ constructor(nodeId: NodeId, buffer: Buffer);
14
+ toString(): string;
15
+ }
16
+ export declare function decodeExtensionObject(stream: BinaryStream, _value?: ExtensionObject | null): ExtensionObject | null;
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decodeExtensionObject = exports.OpaqueStructure = exports.encodeExtensionObject = exports.ExtensionObject = void 0;
4
+ /**
5
+ * @module node-opcua-extension-object
6
+ */
7
+ const node_opcua_basic_types_1 = require("node-opcua-basic-types");
8
+ const node_opcua_debug_1 = require("node-opcua-debug");
9
+ const node_opcua_factory_1 = require("node-opcua-factory");
10
+ const node_opcua_nodeid_1 = require("node-opcua-nodeid");
11
+ const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
12
+ const chalk = require("chalk");
13
+ /* tslint:disable:no-empty */
14
+ class ExtensionObject extends node_opcua_factory_1.BaseUAObject {
15
+ constructor(options) {
16
+ super();
17
+ }
18
+ }
19
+ exports.ExtensionObject = ExtensionObject;
20
+ ExtensionObject.schema = new node_opcua_factory_1.StructuredTypeSchema({
21
+ baseType: "",
22
+ documentation: "",
23
+ fields: [],
24
+ name: "ExtensionObject"
25
+ });
26
+ ExtensionObject.prototype.schema = ExtensionObject.schema;
27
+ function constructEmptyExtensionObject(expandedNodeId) {
28
+ return (0, node_opcua_factory_1.constructObject)(expandedNodeId);
29
+ }
30
+ // OPC-UA Part 6 - $5.2.2.15 ExtensionObject
31
+ // An ExtensionObject is encoded as sequence of bytes prefixed by the NodeId of its
32
+ // DataTypeEncoding and the number of bytes encoded.
33
+ // what the specs say: OCC/UA part 6 $5.2.2.15 ExtensionObject
34
+ //
35
+ // TypeId | NodeId | The identifier for the DataTypeEncoding node in the Server's AddressSpace.
36
+ // | ExtensionObjects defined by the OPC UA specification have a numeric node
37
+ // | identifier assigned to them with a NamespaceIndex of 0. The numeric
38
+ // | identifiers are defined in A.1.
39
+ //
40
+ // Encoding | Byte | An enumeration that indicates how the body is encoded.
41
+ // | The parameter may have the following values:
42
+ // | 0x00 No body is encoded.
43
+ // | 0x01 The body is encoded as a ByteString.
44
+ // | 0x02 The body is encoded as a XmlElement.
45
+ //
46
+ // Length | Int32 | The length of the object body.
47
+ // | The length shall be specified if the body is encoded. <<<<<<<( WTF ?)
48
+ //
49
+ // Body | Byte[*] | The object body
50
+ // | This field contains the raw bytes for ByteString bodies.
51
+ // | For XmlElement bodies this field contains the XML encoded as a UTF-8
52
+ // | string without any null terminator.
53
+ //
54
+ function encodeExtensionObject(object, stream) {
55
+ if (!object) {
56
+ (0, node_opcua_basic_types_1.encodeNodeId)((0, node_opcua_nodeid_1.makeNodeId)(0), stream);
57
+ stream.writeUInt8(0x00); // no body is encoded
58
+ // note : Length shall not hbe specified, end of the job!
59
+ }
60
+ else {
61
+ if (object instanceof OpaqueStructure) {
62
+ // Writing raw Opaque buffer as Opaque Structure ...
63
+ (0, node_opcua_basic_types_1.encodeNodeId)(object.nodeId, stream);
64
+ stream.writeUInt8(0x01); // 0x01 The body is encoded as a ByteString.
65
+ stream.writeByteStream(object.buffer);
66
+ return;
67
+ }
68
+ /* istanbul ignore next */
69
+ if (!(object instanceof node_opcua_factory_1.BaseUAObject)) {
70
+ throw new Error("Expecting a extension object");
71
+ }
72
+ // ensure we have a valid encoding Default Binary ID !!!
73
+ /* istanbul ignore next */
74
+ if (!object.schema) {
75
+ debugLog(" object = ", object);
76
+ throw new Error("object has no schema " + object.constructor.name);
77
+ }
78
+ const encodingDefaultBinary = object.schema.encodingDefaultBinary;
79
+ /* istanbul ignore next */
80
+ if (!encodingDefaultBinary) {
81
+ debugLog(chalk.yellow("encoding ExtObj "), object);
82
+ throw new Error("Cannot find encodingDefaultBinary for this object : " + object.schema.name);
83
+ }
84
+ /* istanbul ignore next */
85
+ if (encodingDefaultBinary.isEmpty()) {
86
+ debugLog(chalk.yellow("encoding ExtObj "), object.constructor.encodingDefaultBinary.toString());
87
+ throw new Error("Cannot find encodingDefaultBinary for this object : " + object.schema.name);
88
+ }
89
+ /* istanbul ignore next */
90
+ if ((0, node_opcua_factory_1.is_internal_id)(encodingDefaultBinary.value)) {
91
+ debugLog(chalk.yellow("encoding ExtObj "), object.constructor.encodingDefaultBinary.toString(), object.schema.name);
92
+ throw new Error("Cannot find valid OPCUA encodingDefaultBinary for this object : " + object.schema.name);
93
+ }
94
+ (0, node_opcua_basic_types_1.encodeNodeId)(encodingDefaultBinary, stream);
95
+ stream.writeUInt8(0x01); // 0x01 The body is encoded as a ByteString.
96
+ stream.writeUInt32(object.binaryStoreSize());
97
+ object.encode(stream);
98
+ }
99
+ }
100
+ exports.encodeExtensionObject = encodeExtensionObject;
101
+ // tslint:disable:max-classes-per-file
102
+ class OpaqueStructure extends ExtensionObject {
103
+ constructor(nodeId, buffer) {
104
+ super({});
105
+ this.nodeId = nodeId;
106
+ this.buffer = buffer;
107
+ }
108
+ toString() {
109
+ const str = "/* OpaqueStructure */ { \n" +
110
+ "nodeId " +
111
+ this.nodeId.toString() +
112
+ "\n" +
113
+ "buffer = \n" +
114
+ (0, node_opcua_debug_1.hexDump)(this.buffer) +
115
+ "\n" +
116
+ "}";
117
+ return str;
118
+ }
119
+ }
120
+ exports.OpaqueStructure = OpaqueStructure;
121
+ function decodeExtensionObject(stream, _value) {
122
+ const nodeId = (0, node_opcua_basic_types_1.decodeNodeId)(stream);
123
+ const encodingType = stream.readUInt8();
124
+ if (encodingType === 0) {
125
+ return null;
126
+ }
127
+ const length = stream.readUInt32();
128
+ /* istanbul ignore next */
129
+ if (nodeId.value === 0 || encodingType === 0) {
130
+ return {};
131
+ }
132
+ // let verify that decode will use the expected number of bytes
133
+ const streamLengthBefore = stream.length;
134
+ let object;
135
+ if (nodeId.namespace !== 0) {
136
+ // this is a extension object define in a other namespace
137
+ // we can only threat it as an opaque object for the time being
138
+ // the caller that may now more about the namespace Array and type
139
+ // definition will be able to turn the opaque object into a meaningful
140
+ // structure
141
+ // lets rewind before the length
142
+ stream.length -= 4;
143
+ object = new OpaqueStructure(nodeId, stream.readByteStream());
144
+ }
145
+ else {
146
+ object = constructEmptyExtensionObject(nodeId);
147
+ /* istanbul ignore next */
148
+ if (object === null) {
149
+ // this object is unknown to us ..
150
+ stream.length += length;
151
+ object = {};
152
+ }
153
+ else {
154
+ try {
155
+ object.decode(stream);
156
+ }
157
+ catch (err) {
158
+ debugLog("Cannot decode object ", err);
159
+ }
160
+ }
161
+ }
162
+ if (streamLengthBefore + length !== stream.length) {
163
+ // this may happen if the server or client do have a different OPCUA version
164
+ // for instance SubscriptionDiagnostics structure has been changed between OPCUA version 1.01 and 1.04
165
+ // causing 2 extra member to be added.
166
+ debugLog(chalk.bgWhiteBright.red("========================================="));
167
+ // tslint:disable-next-line:no-console
168
+ console.warn("WARNING => Extension object decoding error on ", object.constructor.name, " expected size was", length, "but only this amount of bytes have been read :", stream.length - streamLengthBefore);
169
+ stream.length = streamLengthBefore + length;
170
+ }
171
+ return object;
172
+ }
173
+ exports.decodeExtensionObject = decodeExtensionObject;
174
+ (0, node_opcua_factory_1.registerBuiltInType)({
175
+ name: "ExtensionObject",
176
+ subType: "",
177
+ encode: encodeExtensionObject,
178
+ decode: decodeExtensionObject,
179
+ defaultValue: () => null
180
+ });
181
+ //# sourceMappingURL=extension_object.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension_object.js","sourceRoot":"","sources":["../source/extension_object.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @module node-opcua-extension-object
3
+ */
4
+ export * from "./extension_object";
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ /**
14
+ * @module node-opcua-extension-object
15
+ */
16
+ __exportStar(require("./extension_object"), exports);
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../source/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA;;GAEG;AACH,qDAAmC"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "node-opcua-extension-object",
3
+ "version": "2.51.0",
4
+ "description": "pure nodejs OPCUA SDK - module -extension-object",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc -b",
9
+ "lint": "tslint source/**/*.ts",
10
+ "clean": "node -e \"require('rimraf').sync('dist');\"",
11
+ "test": "echo no test"
12
+ },
13
+ "dependencies": {
14
+ "chalk": "4.1.2",
15
+ "node-opcua-assert": "2.51.0",
16
+ "node-opcua-basic-types": "2.51.0",
17
+ "node-opcua-binary-stream": "2.51.0",
18
+ "node-opcua-debug": "2.51.0",
19
+ "node-opcua-factory": "2.51.0",
20
+ "node-opcua-nodeid": "2.51.0"
21
+ },
22
+ "author": "Etienne Rossignon",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git://github.com/node-opcua/node-opcua.git"
27
+ },
28
+ "keywords": [
29
+ "OPCUA",
30
+ "opcua",
31
+ "m2m",
32
+ "iot",
33
+ "opc ua",
34
+ "internet of things"
35
+ ],
36
+ "homepage": "http://node-opcua.github.io/",
37
+ "gitHead": "75feb111daf7ec65fa0111e4fa5beb8987fd4945"
38
+ }
@@ -0,0 +1,212 @@
1
+ /**
2
+ * @module node-opcua-extension-object
3
+ */
4
+ import { decodeNodeId, encodeNodeId } from "node-opcua-basic-types";
5
+ import { BinaryStream, OutputBinaryStream } from "node-opcua-binary-stream";
6
+ import { checkDebugFlag, hexDump, make_debugLog } from "node-opcua-debug";
7
+ import { BaseUAObject, constructObject, is_internal_id, registerBuiltInType, StructuredTypeSchema } from "node-opcua-factory";
8
+ import { ExpandedNodeId, makeNodeId, NodeId } from "node-opcua-nodeid";
9
+
10
+ const debugLog = make_debugLog(__filename);
11
+
12
+ import * as chalk from "chalk";
13
+
14
+ /* tslint:disable:no-empty */
15
+ export class ExtensionObject extends BaseUAObject {
16
+ public static schema: StructuredTypeSchema = new StructuredTypeSchema({
17
+ baseType: "",
18
+ documentation: "",
19
+ fields: [],
20
+ name: "ExtensionObject"
21
+ });
22
+
23
+ constructor(options: any) {
24
+ super();
25
+ }
26
+ }
27
+
28
+ ExtensionObject.prototype.schema = ExtensionObject.schema;
29
+
30
+ function constructEmptyExtensionObject(expandedNodeId: NodeId): ExtensionObject {
31
+ return constructObject(expandedNodeId as ExpandedNodeId);
32
+ }
33
+
34
+ // OPC-UA Part 6 - $5.2.2.15 ExtensionObject
35
+ // An ExtensionObject is encoded as sequence of bytes prefixed by the NodeId of its
36
+ // DataTypeEncoding and the number of bytes encoded.
37
+
38
+ // what the specs say: OCC/UA part 6 $5.2.2.15 ExtensionObject
39
+ //
40
+ // TypeId | NodeId | The identifier for the DataTypeEncoding node in the Server's AddressSpace.
41
+ // | ExtensionObjects defined by the OPC UA specification have a numeric node
42
+ // | identifier assigned to them with a NamespaceIndex of 0. The numeric
43
+ // | identifiers are defined in A.1.
44
+ //
45
+ // Encoding | Byte | An enumeration that indicates how the body is encoded.
46
+ // | The parameter may have the following values:
47
+ // | 0x00 No body is encoded.
48
+ // | 0x01 The body is encoded as a ByteString.
49
+ // | 0x02 The body is encoded as a XmlElement.
50
+ //
51
+ // Length | Int32 | The length of the object body.
52
+ // | The length shall be specified if the body is encoded. <<<<<<<( WTF ?)
53
+ //
54
+ // Body | Byte[*] | The object body
55
+ // | This field contains the raw bytes for ByteString bodies.
56
+ // | For XmlElement bodies this field contains the XML encoded as a UTF-8
57
+ // | string without any null terminator.
58
+ //
59
+
60
+ export function encodeExtensionObject(object: BaseUAObject | null, stream: OutputBinaryStream): void {
61
+ if (!object) {
62
+ encodeNodeId(makeNodeId(0), stream);
63
+ stream.writeUInt8(0x00); // no body is encoded
64
+ // note : Length shall not hbe specified, end of the job!
65
+ } else {
66
+ if (object instanceof OpaqueStructure) {
67
+ // Writing raw Opaque buffer as Opaque Structure ...
68
+ encodeNodeId(object.nodeId, stream);
69
+ stream.writeUInt8(0x01); // 0x01 The body is encoded as a ByteString.
70
+ stream.writeByteStream(object.buffer);
71
+ return;
72
+ }
73
+ /* istanbul ignore next */
74
+ if (!(object instanceof BaseUAObject)) {
75
+ throw new Error("Expecting a extension object");
76
+ }
77
+ // ensure we have a valid encoding Default Binary ID !!!
78
+ /* istanbul ignore next */
79
+ if (!object.schema) {
80
+ debugLog(" object = ", object);
81
+ throw new Error("object has no schema " + object.constructor.name);
82
+ }
83
+ const encodingDefaultBinary = object.schema.encodingDefaultBinary!;
84
+ /* istanbul ignore next */
85
+ if (!encodingDefaultBinary) {
86
+ debugLog(chalk.yellow("encoding ExtObj "), object);
87
+ throw new Error("Cannot find encodingDefaultBinary for this object : " + object.schema.name);
88
+ }
89
+ /* istanbul ignore next */
90
+ if (encodingDefaultBinary.isEmpty()) {
91
+ debugLog(chalk.yellow("encoding ExtObj "), (object.constructor as any).encodingDefaultBinary.toString());
92
+ throw new Error("Cannot find encodingDefaultBinary for this object : " + object.schema.name);
93
+ }
94
+ /* istanbul ignore next */
95
+ if (is_internal_id(encodingDefaultBinary.value as number)) {
96
+ debugLog(
97
+ chalk.yellow("encoding ExtObj "),
98
+ (object.constructor as any).encodingDefaultBinary.toString(),
99
+ object.schema.name
100
+ );
101
+ throw new Error("Cannot find valid OPCUA encodingDefaultBinary for this object : " + object.schema.name);
102
+ }
103
+
104
+ encodeNodeId(encodingDefaultBinary, stream);
105
+ stream.writeUInt8(0x01); // 0x01 The body is encoded as a ByteString.
106
+ stream.writeUInt32(object.binaryStoreSize());
107
+ object.encode(stream);
108
+ }
109
+ }
110
+
111
+ // tslint:disable:max-classes-per-file
112
+ export class OpaqueStructure extends ExtensionObject {
113
+
114
+ // the nodeId is the same as the encodingDefaultBinary
115
+ public nodeId: NodeId;
116
+
117
+ public buffer: Buffer;
118
+
119
+ constructor(nodeId: NodeId, buffer: Buffer) {
120
+ super({});
121
+ this.nodeId = nodeId;
122
+ this.buffer = buffer;
123
+ }
124
+
125
+ public toString(): string {
126
+ const str =
127
+ "/* OpaqueStructure */ { \n" +
128
+ "nodeId " +
129
+ this.nodeId.toString() +
130
+ "\n" +
131
+ "buffer = \n" +
132
+ hexDump(this.buffer) +
133
+ "\n" +
134
+ "}";
135
+ return str;
136
+ }
137
+ }
138
+
139
+ export function decodeExtensionObject(stream: BinaryStream, _value?: ExtensionObject | null): ExtensionObject | null {
140
+ const nodeId = decodeNodeId(stream);
141
+ const encodingType = stream.readUInt8();
142
+
143
+ if (encodingType === 0) {
144
+ return null;
145
+ }
146
+
147
+ const length = stream.readUInt32();
148
+
149
+ /* istanbul ignore next */
150
+ if (nodeId.value === 0 || encodingType === 0) {
151
+ return {} as ExtensionObject;
152
+ }
153
+
154
+ // let verify that decode will use the expected number of bytes
155
+ const streamLengthBefore = stream.length;
156
+
157
+ let object: any;
158
+ if (nodeId.namespace !== 0) {
159
+ // this is a extension object define in a other namespace
160
+ // we can only threat it as an opaque object for the time being
161
+ // the caller that may now more about the namespace Array and type
162
+ // definition will be able to turn the opaque object into a meaningful
163
+ // structure
164
+ // lets rewind before the length
165
+ stream.length -= 4;
166
+ object = new OpaqueStructure(nodeId, stream.readByteStream()!);
167
+ } else {
168
+ object = constructEmptyExtensionObject(nodeId);
169
+ /* istanbul ignore next */
170
+ if (object === null) {
171
+ // this object is unknown to us ..
172
+ stream.length += length;
173
+ object = {} as ExtensionObject;
174
+ } else {
175
+ try {
176
+ object.decode(stream);
177
+ } catch (err) {
178
+ debugLog("Cannot decode object ", err);
179
+ }
180
+ }
181
+ }
182
+
183
+ if (streamLengthBefore + length !== stream.length) {
184
+ // this may happen if the server or client do have a different OPCUA version
185
+ // for instance SubscriptionDiagnostics structure has been changed between OPCUA version 1.01 and 1.04
186
+ // causing 2 extra member to be added.
187
+ debugLog(chalk.bgWhiteBright.red("========================================="));
188
+
189
+ // tslint:disable-next-line:no-console
190
+ console.warn(
191
+ "WARNING => Extension object decoding error on ",
192
+ object.constructor.name,
193
+ " expected size was",
194
+ length,
195
+ "but only this amount of bytes have been read :",
196
+ stream.length - streamLengthBefore
197
+ );
198
+ stream.length = streamLengthBefore + length;
199
+ }
200
+ return object;
201
+ }
202
+
203
+ registerBuiltInType({
204
+ name: "ExtensionObject",
205
+ subType: "",
206
+
207
+ encode: encodeExtensionObject,
208
+
209
+ decode: decodeExtensionObject,
210
+
211
+ defaultValue: () => null
212
+ });
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @module node-opcua-extension-object
3
+ */
4
+ export * from "./extension_object";