node-opcua-address-space 2.168.0 → 2.170.1
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/source/loader/namespace_post_step.js +25 -17
- package/dist/source/loader/namespace_post_step.js.map +1 -1
- package/dist/source/session_context.d.ts +3 -1
- package/dist/source/session_context.js +26 -1
- package/dist/source/session_context.js.map +1 -1
- package/dist/source/ua_interface.d.ts +2 -3
- package/dist/source/ua_interface.js +10 -33
- package/dist/source/ua_interface.js.map +1 -1
- package/dist/src/_instantiate_helpers.d.ts +1 -1
- package/dist/src/_instantiate_helpers.js +32 -9
- package/dist/src/_instantiate_helpers.js.map +1 -1
- package/dist/src/_mandatory_child_or_requested_optional_filter.js +3 -3
- package/dist/src/_mandatory_child_or_requested_optional_filter.js.map +1 -1
- package/dist/src/address_space.d.ts +15 -12
- package/dist/src/address_space.js +63 -64
- package/dist/src/address_space.js.map +1 -1
- package/dist/src/alarms_and_conditions/condition_snapshot_impl.js +1 -1
- package/dist/src/alarms_and_conditions/condition_snapshot_impl.js.map +1 -1
- package/dist/src/alarms_and_conditions/ua_condition_impl.js +1 -1
- package/dist/src/alarms_and_conditions/ua_condition_impl.js.map +1 -1
- package/dist/src/base_node_impl.d.ts +1 -0
- package/dist/src/base_node_impl.js +11 -0
- package/dist/src/base_node_impl.js.map +1 -1
- package/dist/src/base_node_private.d.ts +10 -7
- package/dist/src/base_node_private.js +74 -50
- package/dist/src/base_node_private.js.map +1 -1
- package/dist/src/check_value_rank_compatibility.js +1 -1
- package/dist/src/check_value_rank_compatibility.js.map +1 -1
- package/dist/src/event_data.d.ts +8 -21
- package/dist/src/event_data.js +24 -19
- package/dist/src/event_data.js.map +1 -1
- package/dist/src/namespace_impl.d.ts +2 -0
- package/dist/src/namespace_impl.js +13 -0
- package/dist/src/namespace_impl.js.map +1 -1
- package/dist/src/ua_method_impl.d.ts +11 -9
- package/dist/src/ua_method_impl.js +24 -27
- package/dist/src/ua_method_impl.js.map +1 -1
- package/dist/src/ua_object_impl.d.ts +6 -5
- package/dist/src/ua_object_impl.js +30 -4
- package/dist/src/ua_object_impl.js.map +1 -1
- package/dist/src/ua_object_type_impl.js +2 -2
- package/dist/src/ua_object_type_impl.js.map +1 -1
- package/dist/src/ua_variable_impl.d.ts +1 -0
- package/dist/src/ua_variable_impl.js +79 -1
- package/dist/src/ua_variable_impl.js.map +1 -1
- package/dist/tsconfig_base.tsbuildinfo +1 -1
- package/distHelpers/get_address_space_fixture.js +14 -14
- package/distHelpers/get_address_space_fixture.js.map +1 -1
- package/distHelpers/index.d.ts +2 -2
- package/distHelpers/index.js +2 -2
- package/distHelpers/index.js.map +1 -1
- package/package.json +34 -34
- package/source/loader/namespace_post_step.ts +28 -19
- package/source/session_context.ts +30 -1
- package/source/ua_interface.ts +24 -38
- package/src/_instantiate_helpers.ts +67 -24
- package/src/_mandatory_child_or_requested_optional_filter.ts +5 -5
- package/src/address_space.ts +127 -124
- package/src/alarms_and_conditions/condition_snapshot_impl.ts +3 -3
- package/src/alarms_and_conditions/ua_condition_impl.ts +1 -1
- package/src/base_node_impl.ts +13 -0
- package/src/base_node_private.ts +163 -139
- package/src/check_value_rank_compatibility.ts +1 -1
- package/src/event_data.ts +57 -54
- package/src/namespace_impl.ts +16 -0
- package/src/ua_method_impl.ts +43 -50
- package/src/ua_object_impl.ts +51 -22
- package/src/ua_object_type_impl.ts +3 -3
- package/src/ua_variable_impl.ts +79 -2
package/src/event_data.ts
CHANGED
|
@@ -1,80 +1,83 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module node-opcua-address-space.Private
|
|
3
3
|
*/
|
|
4
|
+
|
|
5
|
+
import type { BaseNode, IEventData } from "node-opcua-address-space-base";
|
|
4
6
|
import { assert } from "node-opcua-assert";
|
|
5
7
|
import { coerceExpandedNodeId, NodeId, sameNodeId } from "node-opcua-nodeid";
|
|
6
8
|
import { StatusCodes } from "node-opcua-status-code";
|
|
7
|
-
import { BrowsePath, BrowsePathResult } from "node-opcua-types";
|
|
8
|
-
import { Variant, VariantLike } from "node-opcua-variant";
|
|
9
|
-
|
|
10
|
-
import { BaseNode, IEventData } from "node-opcua-address-space-base";
|
|
9
|
+
import { type BrowsePath, BrowsePathResult } from "node-opcua-types";
|
|
11
10
|
import { lowerFirstLetter } from "node-opcua-utils";
|
|
11
|
+
import { Variant, type VariantLike } from "node-opcua-variant";
|
|
12
12
|
|
|
13
13
|
type NodeIdString = string;
|
|
14
14
|
type FullBrowsePath = string;
|
|
15
15
|
|
|
16
|
-
|
|
17
16
|
/**
|
|
18
17
|
*/
|
|
19
18
|
export class EventData implements IEventData {
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
public eventId: NodeId;
|
|
20
|
+
#eventDataSource: BaseNode;
|
|
21
|
+
#cache: {
|
|
22
|
+
__values: { [key: NodeIdString]: Variant };
|
|
23
|
+
__nodeIdToNode: { [key: NodeIdString]: BaseNode };
|
|
24
|
+
__pathToNodeId: { [key: FullBrowsePath]: NodeId };
|
|
25
|
+
__nodeIdToFullPath: { [key: NodeIdString]: FullBrowsePath };
|
|
26
|
+
};
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
constructor(eventTypeNode: BaseNode) {
|
|
29
|
+
this.#cache = {
|
|
30
|
+
__values: {},
|
|
31
|
+
__nodeIdToNode: {},
|
|
32
|
+
__pathToNodeId: {},
|
|
33
|
+
__nodeIdToFullPath: {}
|
|
28
34
|
};
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
__nodeIdToNode: {},
|
|
34
|
-
__pathToNodeId: {},
|
|
35
|
-
__nodeIdToFullPath: {}
|
|
36
|
-
};
|
|
36
|
+
this.eventId = new NodeId();
|
|
37
|
+
this.#eventDataSource = eventTypeNode;
|
|
38
|
+
}
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
public getEventDataSource(): BaseNode {
|
|
41
|
+
return this.#eventDataSource;
|
|
42
|
+
}
|
|
43
|
+
public _createValue(fullBrowsePath: string, node: BaseNode, variant: VariantLike): void {
|
|
44
|
+
const eventData = this as Record<string, unknown>;
|
|
45
|
+
assert(!eventData[fullBrowsePath], `already exists ${fullBrowsePath}`);
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
const eventData = this as any;
|
|
44
|
-
assert(!eventData[fullBrowsePath], "already exists " + fullBrowsePath);
|
|
47
|
+
const lowerName = fullBrowsePath.split(".").map(lowerFirstLetter).join(".");
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
eventData[lowerName] = Variant.coerce(variant);
|
|
47
50
|
|
|
48
|
-
|
|
51
|
+
this.#cache.__pathToNodeId[fullBrowsePath] = node.nodeId;
|
|
52
|
+
this.#cache.__nodeIdToNode[node.nodeId.toString()] = node;
|
|
53
|
+
this.#cache.__nodeIdToFullPath[node.nodeId.toString()] = fullBrowsePath;
|
|
54
|
+
this.#cache.__values[node.nodeId.toString()] = eventData[lowerName] as Variant;
|
|
55
|
+
}
|
|
49
56
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
this.$cache.__values[node.nodeId.toString()] = eventData[lowerName];
|
|
57
|
+
public _browse(browsePath: BrowsePath): BrowsePathResult | null {
|
|
58
|
+
if (!sameNodeId(browsePath.startingNode, this.#eventDataSource.nodeId)) {
|
|
59
|
+
return null;
|
|
54
60
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
const fullBrowsePath = (browsePath.relativePath.elements || []).map((b) => b.targetName.toString()).join(".");
|
|
62
|
+
const nodeId = this.#cache.__pathToNodeId[fullBrowsePath];
|
|
63
|
+
if (!nodeId) return null;
|
|
64
|
+
return new BrowsePathResult({
|
|
65
|
+
statusCode: StatusCodes.Good,
|
|
66
|
+
targets: [
|
|
67
|
+
{
|
|
68
|
+
remainingPathIndex: 0,
|
|
69
|
+
targetId: coerceExpandedNodeId(nodeId)
|
|
59
70
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return new BrowsePathResult({
|
|
64
|
-
statusCode: StatusCodes.Good,
|
|
65
|
-
targets: [{
|
|
66
|
-
remainingPathIndex: 0,
|
|
67
|
-
targetId: coerceExpandedNodeId(nodeId),
|
|
68
|
-
}]
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
+
]
|
|
72
|
+
});
|
|
73
|
+
}
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
return null;
|
|
75
|
+
public _readValue(nodeId: NodeId): Variant | null {
|
|
76
|
+
const key = nodeId.toString();
|
|
77
|
+
const cached_value = this.#cache.__values[key];
|
|
78
|
+
if (cached_value) {
|
|
79
|
+
return cached_value;
|
|
79
80
|
}
|
|
80
|
-
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
package/src/namespace_impl.ts
CHANGED
|
@@ -287,6 +287,22 @@ export class NamespaceImpl implements NamespacePrivate {
|
|
|
287
287
|
return this.index === 0 ? this : this.addressSpace.getDefaultNamespace();
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
+
public toJSON(): Record<string, string | number | undefined> {
|
|
291
|
+
return {
|
|
292
|
+
index: this.index,
|
|
293
|
+
namespaceUri: this.namespaceUri,
|
|
294
|
+
version: this.version
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
public toString(): string {
|
|
299
|
+
return `Namespace({ index: ${this.index}, namespaceUri: "${this.namespaceUri}" })`;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
public [Symbol.for("nodejs.util.inspect.custom")](): string {
|
|
303
|
+
return this.toString();
|
|
304
|
+
}
|
|
305
|
+
|
|
290
306
|
public dispose(): void {
|
|
291
307
|
for (const node of this.nodeIterator()) {
|
|
292
308
|
(<BaseNodeImpl>node).dispose();
|
package/src/ua_method_impl.ts
CHANGED
|
@@ -1,41 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module node-opcua-address-space
|
|
3
3
|
*/
|
|
4
|
-
import { callbackify } from "util";
|
|
5
|
-
import chalk from "chalk";
|
|
6
|
-
import { assert } from "node-opcua-assert";
|
|
7
4
|
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import { DataValue, DataValueLike } from "node-opcua-data-value";
|
|
11
|
-
import { make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
|
|
12
|
-
import { NodeId } from "node-opcua-nodeid";
|
|
13
|
-
import { NumericRange } from "node-opcua-numeric-range";
|
|
14
|
-
import { Argument } from "node-opcua-service-call";
|
|
15
|
-
import { CallbackT, StatusCode, StatusCodes } from "node-opcua-status-code";
|
|
16
|
-
import { CallMethodResultOptions, PermissionType } from "node-opcua-types";
|
|
17
|
-
import { Variant } from "node-opcua-variant";
|
|
18
|
-
import { DataType, VariantLike } from "node-opcua-variant";
|
|
5
|
+
import { callbackify } from "node:util";
|
|
6
|
+
import chalk from "chalk";
|
|
19
7
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
UAMethod,
|
|
24
|
-
UAObject,
|
|
25
|
-
CloneExtraInfo,
|
|
26
|
-
CloneFilter,
|
|
27
|
-
CloneOptions,
|
|
28
|
-
UAObjectType,
|
|
29
|
-
ISessionContext,
|
|
30
|
-
UAVariable,
|
|
8
|
+
type CloneExtraInfo,
|
|
9
|
+
type CloneFilter,
|
|
10
|
+
type CloneOptions,
|
|
31
11
|
defaultCloneFilter,
|
|
32
|
-
|
|
12
|
+
type ISessionContext,
|
|
13
|
+
type MethodFunctor,
|
|
14
|
+
type MethodFunctorA,
|
|
15
|
+
type MethodFunctorC,
|
|
16
|
+
makeDefaultCloneExtraInfo,
|
|
17
|
+
type UAMethod,
|
|
18
|
+
type UAObject,
|
|
19
|
+
type UAObjectType,
|
|
20
|
+
type UAVariable
|
|
33
21
|
} from "node-opcua-address-space-base";
|
|
34
|
-
import {
|
|
22
|
+
import { assert } from "node-opcua-assert";
|
|
23
|
+
import { AttributeIds, type DiagnosticInfo, NodeClass, type QualifiedNameLike } from "node-opcua-data-model";
|
|
24
|
+
import { DataValue, type DataValueLike } from "node-opcua-data-value";
|
|
25
|
+
import { make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
|
|
26
|
+
import type { NodeId } from "node-opcua-nodeid";
|
|
27
|
+
import type { NumericRange } from "node-opcua-numeric-range";
|
|
28
|
+
import { Argument } from "node-opcua-service-call";
|
|
29
|
+
import { type CallbackT, type StatusCode, StatusCodes } from "node-opcua-status-code";
|
|
30
|
+
import { type CallMethodResultOptions, PermissionType } from "node-opcua-types";
|
|
31
|
+
import { DataType, Variant, type VariantLike } from "node-opcua-variant";
|
|
32
|
+
import type { SessionContext } from "../source/session_context";
|
|
33
|
+
import type { AddressSpacePrivate } from "./address_space_private";
|
|
34
|
+
import { BaseNodeImpl } from "./base_node_impl";
|
|
35
35
|
import { _clone } from "./base_node_private";
|
|
36
36
|
import { _handle_hierarchy_parent } from "./namespace_impl";
|
|
37
|
-
import { BaseNodeImpl } from "./base_node_impl";
|
|
38
|
-
import { AddressSpacePrivate } from "./address_space_private";
|
|
39
37
|
|
|
40
38
|
const warningLog = make_warningLog(__filename);
|
|
41
39
|
const debugLog = make_debugLog(__filename);
|
|
@@ -135,7 +133,7 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
|
|
|
135
133
|
if (async_func.length === 2) {
|
|
136
134
|
async_func = callbackify(async_func as MethodFunctorA) as MethodFunctorC;
|
|
137
135
|
}
|
|
138
|
-
assert(async_func.length === 3,
|
|
136
|
+
assert(async_func.length === 3, ` a method with callback should have 3 arguments : got ${async_func.length}`);
|
|
139
137
|
this._asyncExecutionFunction = async_func;
|
|
140
138
|
}
|
|
141
139
|
public execute(
|
|
@@ -181,17 +179,17 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
|
|
|
181
179
|
" " +
|
|
182
180
|
this.browseName.toString() +
|
|
183
181
|
" called for a node that is not a Object/ObjectType but " +
|
|
184
|
-
NodeClass[context.object
|
|
182
|
+
NodeClass[context.object?.nodeClass as number]
|
|
185
183
|
);
|
|
186
184
|
return callback(null, { statusCode: StatusCodes.BadNodeIdInvalid });
|
|
187
185
|
}
|
|
188
186
|
if (!this._asyncExecutionFunction) {
|
|
189
|
-
warningLog(
|
|
187
|
+
warningLog(`Method ${this.nodeId.toString()} ${this.browseName.toString()} has not been bound`);
|
|
190
188
|
return callback(null, { statusCode: StatusCodes.BadInternalError });
|
|
191
189
|
}
|
|
192
190
|
|
|
193
191
|
if (!this.getExecutableFlag(context)) {
|
|
194
|
-
warningLog(
|
|
192
|
+
warningLog(`Method ${this.nodeId.toString()} ${this.browseName.toString()} is not executable`);
|
|
195
193
|
return callback(null, { statusCode: StatusCodes.BadNotExecutable });
|
|
196
194
|
}
|
|
197
195
|
|
|
@@ -212,7 +210,7 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
|
|
|
212
210
|
// ── method call interceptors ──
|
|
213
211
|
const addressSpace = this.addressSpace as AddressSpacePrivate;
|
|
214
212
|
const interceptors = addressSpace._methodCallInterceptors;
|
|
215
|
-
|
|
213
|
+
|
|
216
214
|
const coercedInputArguments = inputArguments as Variant[];
|
|
217
215
|
const callObject = object;
|
|
218
216
|
|
|
@@ -221,13 +219,13 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
|
|
|
221
219
|
for (const interceptor of interceptors) {
|
|
222
220
|
let status: StatusCode;
|
|
223
221
|
try {
|
|
224
|
-
status = await interceptor(context, callObject,
|
|
222
|
+
status = await interceptor(context, callObject, this, coercedInputArguments);
|
|
225
223
|
} catch (err) {
|
|
226
224
|
if (err instanceof Error) {
|
|
227
225
|
warningLog(chalk.red("ERR in method interceptor"), err.message);
|
|
228
226
|
}
|
|
229
227
|
const callMethodResponse = { statusCode: StatusCodes.BadInternalError };
|
|
230
|
-
callback
|
|
228
|
+
callback?.(err as Error, callMethodResponse);
|
|
231
229
|
return;
|
|
232
230
|
}
|
|
233
231
|
if (status !== StatusCodes.Good) {
|
|
@@ -237,14 +235,14 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
|
|
|
237
235
|
inputArgumentResults: coercedInputArguments?.map(() => status) || [],
|
|
238
236
|
inputArgumentDiagnosticInfos
|
|
239
237
|
};
|
|
240
|
-
return callback
|
|
238
|
+
return callback?.(null, callMethodResult);
|
|
241
239
|
}
|
|
242
240
|
}
|
|
243
241
|
|
|
244
242
|
// All interceptors passed — execute the method body
|
|
245
243
|
try {
|
|
246
|
-
|
|
247
|
-
|
|
244
|
+
this._asyncExecutionFunction?.call(
|
|
245
|
+
this as UAMethodImpl,
|
|
248
246
|
coercedInputArguments,
|
|
249
247
|
context,
|
|
250
248
|
(err: Error | null, callMethodResult?: CallMethodResultOptions) => {
|
|
@@ -266,14 +264,14 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
|
|
|
266
264
|
|
|
267
265
|
// ── afterCall event ──
|
|
268
266
|
try {
|
|
269
|
-
|
|
267
|
+
this.emit("afterCall", context, coercedInputArguments, callMethodResult);
|
|
270
268
|
} catch (afterCallErr) {
|
|
271
269
|
if (afterCallErr instanceof Error) {
|
|
272
270
|
warningLog(chalk.red("ERR in afterCall listener"), afterCallErr.message);
|
|
273
271
|
}
|
|
274
272
|
}
|
|
275
273
|
|
|
276
|
-
callback
|
|
274
|
+
callback?.(err, callMethodResult);
|
|
277
275
|
}
|
|
278
276
|
);
|
|
279
277
|
} catch (err) {
|
|
@@ -282,7 +280,7 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
|
|
|
282
280
|
warningLog(err.stack);
|
|
283
281
|
}
|
|
284
282
|
const callMethodResponse = { statusCode: StatusCodes.BadInternalError };
|
|
285
|
-
callback
|
|
283
|
+
callback?.(err as Error, callMethodResponse);
|
|
286
284
|
}
|
|
287
285
|
};
|
|
288
286
|
|
|
@@ -291,7 +289,7 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
|
|
|
291
289
|
warningLog(chalk.red("ERR in method interceptor"), err.message);
|
|
292
290
|
}
|
|
293
291
|
const callMethodResponse = { statusCode: StatusCodes.BadInternalError };
|
|
294
|
-
callback
|
|
292
|
+
callback?.(err as Error, callMethodResponse);
|
|
295
293
|
});
|
|
296
294
|
}
|
|
297
295
|
|
|
@@ -310,13 +308,7 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
|
|
|
310
308
|
if (!extraInfo) {
|
|
311
309
|
extraInfo = makeDefaultCloneExtraInfo(this);
|
|
312
310
|
}
|
|
313
|
-
const clonedMethod = _clone(
|
|
314
|
-
this,
|
|
315
|
-
UAMethodImpl,
|
|
316
|
-
options,
|
|
317
|
-
optionalFilter || defaultCloneFilter,
|
|
318
|
-
extraInfo
|
|
319
|
-
) as UAMethodImpl;
|
|
311
|
+
const clonedMethod = _clone(this, UAMethodImpl, options, optionalFilter || defaultCloneFilter, extraInfo) as UAMethodImpl;
|
|
320
312
|
|
|
321
313
|
clonedMethod._asyncExecutionFunction = this._asyncExecutionFunction;
|
|
322
314
|
clonedMethod._getExecutableFlag = this._getExecutableFlag;
|
|
@@ -351,4 +343,5 @@ export class UAMethodImpl extends BaseNodeImpl implements UAMethod {
|
|
|
351
343
|
// tslint:disable:no-var-requires
|
|
352
344
|
// tslint:disable:max-line-length
|
|
353
345
|
import { withCallback } from "thenify-ex";
|
|
346
|
+
|
|
354
347
|
UAMethodImpl.prototype.execute = withCallback(UAMethodImpl.prototype.execute);
|
package/src/ua_object_impl.ts
CHANGED
|
@@ -5,36 +5,36 @@ import chalk from "chalk";
|
|
|
5
5
|
|
|
6
6
|
import { assert } from "node-opcua-assert";
|
|
7
7
|
import { isValidByte } from "node-opcua-basic-types";
|
|
8
|
-
import { NodeClass, QualifiedNameLike, QualifiedNameOptions } from "node-opcua-data-model";
|
|
8
|
+
import { NodeClass, type QualifiedNameLike, type QualifiedNameOptions } from "node-opcua-data-model";
|
|
9
9
|
import { AttributeIds } from "node-opcua-data-model";
|
|
10
|
-
import { DataValue, DataValueLike } from "node-opcua-data-value";
|
|
10
|
+
import { DataValue, type DataValueLike } from "node-opcua-data-value";
|
|
11
11
|
import { getCurrentClock } from "node-opcua-date-time";
|
|
12
12
|
import { NodeId } from "node-opcua-nodeid";
|
|
13
|
-
import { NumericRange } from "node-opcua-numeric-range";
|
|
13
|
+
import type { NumericRange } from "node-opcua-numeric-range";
|
|
14
14
|
import { StatusCodes } from "node-opcua-status-code";
|
|
15
15
|
import { DataType } from "node-opcua-variant";
|
|
16
16
|
import {
|
|
17
|
-
EventTypeLike,
|
|
18
|
-
RaiseEventData,
|
|
19
|
-
ISessionContext,
|
|
20
|
-
UAMethod,
|
|
21
|
-
UAObject,
|
|
22
|
-
UAObjectType,
|
|
23
|
-
CloneOptions,
|
|
24
|
-
CloneFilter,
|
|
25
|
-
CloneExtraInfo,
|
|
26
|
-
BaseNode,
|
|
27
|
-
UAEventType,
|
|
28
|
-
IEventData,
|
|
17
|
+
type EventTypeLike,
|
|
18
|
+
type RaiseEventData,
|
|
19
|
+
type ISessionContext,
|
|
20
|
+
type UAMethod,
|
|
21
|
+
type UAObject,
|
|
22
|
+
type UAObjectType,
|
|
23
|
+
type CloneOptions,
|
|
24
|
+
type CloneFilter,
|
|
25
|
+
type CloneExtraInfo,
|
|
26
|
+
type BaseNode,
|
|
27
|
+
type UAEventType,
|
|
28
|
+
type IEventData,
|
|
29
29
|
defaultCloneFilter,
|
|
30
30
|
makeDefaultCloneExtraInfo,
|
|
31
31
|
EventNotifierFlags
|
|
32
32
|
} from "node-opcua-address-space-base";
|
|
33
33
|
import { make_errorLog } from "node-opcua-debug";
|
|
34
34
|
|
|
35
|
-
import { BaseNodeImpl, InternalBaseNodeOptions } from "./base_node_impl";
|
|
35
|
+
import { BaseNodeImpl, type InternalBaseNodeOptions } from "./base_node_impl";
|
|
36
36
|
import { _clone, ToStringBuilder, UAObject_toString } from "./base_node_private";
|
|
37
|
-
import { apply_condition_refresh, ConditionRefreshCache } from "./apply_condition_refresh";
|
|
37
|
+
import { apply_condition_refresh, type ConditionRefreshCache } from "./apply_condition_refresh";
|
|
38
38
|
|
|
39
39
|
const errorLog = make_errorLog(__filename);
|
|
40
40
|
|
|
@@ -159,11 +159,11 @@ export class UAObjectImpl extends BaseNodeImpl implements UAObject {
|
|
|
159
159
|
} else if (eventType instanceof NodeId) {
|
|
160
160
|
const eventTypeFound = addressSpace.findNode(eventType) as BaseNode;
|
|
161
161
|
if (!eventTypeFound) {
|
|
162
|
-
throw new Error(
|
|
162
|
+
throw new Error(`raiseEvent: eventType cannot find event Type ${eventType.toString()}`);
|
|
163
163
|
}
|
|
164
164
|
eventType = eventTypeFound!;
|
|
165
165
|
if (!eventType || eventType.nodeClass !== NodeClass.ObjectType) {
|
|
166
|
-
throw new Error(
|
|
166
|
+
throw new Error(`eventType must exist and be an UAObjectType: ${eventType.toString()}`);
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
|
|
@@ -172,14 +172,14 @@ export class UAObjectImpl extends BaseNodeImpl implements UAObject {
|
|
|
172
172
|
let eventTypeNode: UAEventType = eventType as UAEventType;
|
|
173
173
|
// c8 ignore next
|
|
174
174
|
if (!eventTypeNode) {
|
|
175
|
-
throw new Error(
|
|
175
|
+
throw new Error(`UAObject#raiseEventType : Cannot find event type : ${eventType.toString()}`);
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
// coerce EventType
|
|
179
179
|
eventTypeNode = addressSpace.findEventType(eventType as UAEventType) as UAEventType;
|
|
180
|
-
const
|
|
180
|
+
const _baseEventType = addressSpace.findEventType("BaseEventType");
|
|
181
181
|
|
|
182
|
-
data.$eventDataSource =
|
|
182
|
+
data.$eventDataSource =eventTypeNode;
|
|
183
183
|
data.sourceNode = data.sourceNode || { dataType: DataType.NodeId, value: this.nodeId };
|
|
184
184
|
|
|
185
185
|
const eventData1 = addressSpace.constructEventData(eventTypeNode, data);
|
|
@@ -241,4 +241,33 @@ export class UAObjectImpl extends BaseNodeImpl implements UAObject {
|
|
|
241
241
|
UAObject_toString.call(this, options);
|
|
242
242
|
return options.toString();
|
|
243
243
|
}
|
|
244
|
+
|
|
245
|
+
public toJSON(): Record<string, unknown> {
|
|
246
|
+
return {
|
|
247
|
+
...super.toJSON(),
|
|
248
|
+
typeDefinition: this.typeDefinitionObj ? this.typeDefinitionObj.browseName.toString() : undefined,
|
|
249
|
+
eventNotifier: this._eventNotifier
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
public [Symbol.for("nodejs.util.inspect.custom")](depth: number | null, inspectOptions: { colors?: boolean }): string {
|
|
254
|
+
const c = inspectOptions?.colors === false ? plainChalk : chalk;
|
|
255
|
+
const typeName = this.typeDefinitionObj?.browseName.toString() ?? "?";
|
|
256
|
+
const displayName = this.displayName.length ? this.displayName.map((d) => d.text).join(" | ") : "";
|
|
257
|
+
if (depth !== null && depth <= 0) {
|
|
258
|
+
return `${c.cyan("UAObject<")}${c.green(this.browseName.toString())}${c.grey(` ${this.nodeId.toString()}`)}${c.cyan(">")}`;
|
|
259
|
+
}
|
|
260
|
+
const lines = [
|
|
261
|
+
`${c.cyan("UAObject ")}${c.green(this.browseName.toString())}${c.grey(` ${this.nodeId.toString()}`)}`,
|
|
262
|
+
c.yellow(" typeDefinition : ") + typeName,
|
|
263
|
+
c.yellow(" displayName : ") + displayName,
|
|
264
|
+
c.yellow(" eventNotifier : ") + this._eventNotifier
|
|
265
|
+
];
|
|
266
|
+
if (this.description?.text) {
|
|
267
|
+
lines.push(c.yellow(" description : ") + this.description.text);
|
|
268
|
+
}
|
|
269
|
+
return lines.join("\n");
|
|
270
|
+
}
|
|
244
271
|
}
|
|
272
|
+
|
|
273
|
+
const plainChalk = new Proxy(chalk, { get: () => (s: string) => s }) as typeof chalk;
|
|
@@ -112,12 +112,12 @@ export class UAObjectTypeImpl extends BaseNodeImpl implements UAObjectType {
|
|
|
112
112
|
"expecting a browse name"
|
|
113
113
|
);
|
|
114
114
|
|
|
115
|
-
assert(!Object.
|
|
116
|
-
assert(!Object.
|
|
115
|
+
assert(!Object.hasOwn(options, "propertyOf"), "an Object shall not be a PropertyOf an other object");
|
|
116
|
+
assert(!Object.hasOwn(options, "optional"), "do you mean optionals ?");
|
|
117
117
|
|
|
118
118
|
assertUnusedChildBrowseName(addressSpace, options);
|
|
119
119
|
|
|
120
|
-
const baseObjectType = addressSpace.findObjectType("BaseObjectType")
|
|
120
|
+
const baseObjectType = addressSpace.findObjectType("BaseObjectType") as UAObjectType;
|
|
121
121
|
assert(baseObjectType, "BaseObjectType must be defined in the address space");
|
|
122
122
|
|
|
123
123
|
const references: UAReference[] = [];
|
package/src/ua_variable_impl.ts
CHANGED
|
@@ -76,7 +76,7 @@ import { UAHistoricalDataConfiguration } from "node-opcua-nodeset-ua";
|
|
|
76
76
|
import { SessionContext } from "../source/session_context";
|
|
77
77
|
import { convertToCallbackFunction1 } from "../source/helpers/multiform_func";
|
|
78
78
|
import { BaseNodeImpl, InternalBaseNodeOptions } from "./base_node_impl";
|
|
79
|
-
import { _clone, ToStringBuilder, UAVariable_toString } from "./base_node_private";
|
|
79
|
+
import { _clone, ToStringBuilder, UAVariable_toString, valueRankToString } from "./base_node_private";
|
|
80
80
|
import { EnumerationInfo, IEnumItem, UADataTypeImpl } from "./ua_data_type_impl";
|
|
81
81
|
import { apply_condition_refresh, ConditionRefreshCache } from "./apply_condition_refresh";
|
|
82
82
|
import {
|
|
@@ -101,6 +101,8 @@ const warningLog = make_warningLog(__filename);
|
|
|
101
101
|
const doDebug = checkDebugFlag(__filename);
|
|
102
102
|
const errorLog = make_errorLog(__filename);
|
|
103
103
|
|
|
104
|
+
const plainChalk = new Proxy(chalk, { get: () => (s: string) => s }) as typeof chalk;
|
|
105
|
+
|
|
104
106
|
export function adjust_accessLevel(accessLevel: string | number | null): AccessLevelFlag {
|
|
105
107
|
accessLevel = isNullOrUndefined(accessLevel) ? "CurrentRead | CurrentWrite" : accessLevel;
|
|
106
108
|
accessLevel = makeAccessLevelFlag(accessLevel);
|
|
@@ -239,7 +241,9 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
239
241
|
// this could happen in faulty external nodeset and has been seen once
|
|
240
242
|
// in an nano server
|
|
241
243
|
warningLog(super.typeDefinitionObj.toString());
|
|
242
|
-
|
|
244
|
+
const baseVariableType= this.addressSpace.findVariableType("BaseVariableType");
|
|
245
|
+
if (!baseVariableType) throw new Error("Cannot find BaseVariableType in address space");
|
|
246
|
+
return baseVariableType;
|
|
243
247
|
}
|
|
244
248
|
return super.typeDefinitionObj as UAVariableType;
|
|
245
249
|
}
|
|
@@ -1522,6 +1526,79 @@ export class UAVariableImpl extends BaseNodeImpl implements UAVariable {
|
|
|
1522
1526
|
return options.toString();
|
|
1523
1527
|
}
|
|
1524
1528
|
|
|
1529
|
+
public toJSON(): Record<string, unknown> {
|
|
1530
|
+
let value: unknown;
|
|
1531
|
+
let statusCode: string | undefined;
|
|
1532
|
+
try {
|
|
1533
|
+
const dv = this.$dataValue;
|
|
1534
|
+
if (dv) {
|
|
1535
|
+
statusCode = dv.statusCode?.toString();
|
|
1536
|
+
if (dv.value && !(dv.value.value instanceof OpaqueStructure)) {
|
|
1537
|
+
value = dv.value.value;
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
} catch {
|
|
1541
|
+
// ignore — value access may fail for bound variables
|
|
1542
|
+
}
|
|
1543
|
+
return {
|
|
1544
|
+
...super.toJSON(),
|
|
1545
|
+
typeDefinition: this.typeDefinitionObj?.browseName.toString(),
|
|
1546
|
+
dataType: this.dataType?.toString(),
|
|
1547
|
+
valueRank: this.valueRank,
|
|
1548
|
+
arrayDimensions: this.arrayDimensions,
|
|
1549
|
+
accessLevel: AccessLevelFlag[this.accessLevel],
|
|
1550
|
+
statusCode,
|
|
1551
|
+
value
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
public [Symbol.for("nodejs.util.inspect.custom")](depth: number | null, inspectOptions: { colors?: boolean }): string {
|
|
1556
|
+
const c = inspectOptions?.colors === false ? plainChalk : chalk;
|
|
1557
|
+
const typeName = this.typeDefinitionObj?.browseName.toString() ?? "?";
|
|
1558
|
+
const displayName = this.displayName.length ? this.displayName.map((d) => d.text).join(" | ") : "";
|
|
1559
|
+
if (depth !== null && depth <= 0) {
|
|
1560
|
+
return `${c.cyan("UAVariable<")}${c.green(this.browseName.toString())}${c.grey(` ${this.nodeId.toString()}`)}${c.cyan(">")}`;
|
|
1561
|
+
}
|
|
1562
|
+
const dt = this.dataType?.toString() ?? "?";
|
|
1563
|
+
let valueStr = "";
|
|
1564
|
+
let statusStr = "";
|
|
1565
|
+
try {
|
|
1566
|
+
const dv = this.$dataValue;
|
|
1567
|
+
if (dv) {
|
|
1568
|
+
if (dv.statusCode) statusStr = dv.statusCode.toString();
|
|
1569
|
+
if (dv.value && dv.value.value !== undefined && dv.value.value !== null && !(dv.value.value instanceof OpaqueStructure)) {
|
|
1570
|
+
const v = dv.value.value;
|
|
1571
|
+
valueStr = typeof v === "object" ? Object.prototype.toString.call(v) : String(v);
|
|
1572
|
+
if (valueStr.length > 80) valueStr = `${valueStr.slice(0, 77)}...`;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
} catch {
|
|
1576
|
+
// ignore
|
|
1577
|
+
}
|
|
1578
|
+
const lines = [
|
|
1579
|
+
`${c.cyan("UAVariable ")}${c.green(this.browseName.toString())}${c.grey(` ${this.nodeId.toString()}`)}`,
|
|
1580
|
+
c.yellow(" typeDefinition : ") + typeName,
|
|
1581
|
+
c.yellow(" displayName : ") + displayName,
|
|
1582
|
+
c.yellow(" dataType : ") + dt,
|
|
1583
|
+
c.yellow(" valueRank : ") + valueRankToString(this.valueRank),
|
|
1584
|
+
c.yellow(" accessLevel : ") + AccessLevelFlag[this.accessLevel]
|
|
1585
|
+
];
|
|
1586
|
+
if (this.arrayDimensions?.length) {
|
|
1587
|
+
lines.push(c.yellow(" arrayDimensions: ") + JSON.stringify(this.arrayDimensions));
|
|
1588
|
+
}
|
|
1589
|
+
if (valueStr) {
|
|
1590
|
+
lines.push(c.yellow(" value : ") + valueStr);
|
|
1591
|
+
}
|
|
1592
|
+
if (statusStr && statusStr !== "Good (0x00000000)") {
|
|
1593
|
+
lines.push(c.yellow(" statusCode : ") + statusStr);
|
|
1594
|
+
}
|
|
1595
|
+
if (this.description?.text) {
|
|
1596
|
+
lines.push(c.yellow(" description : ") + this.description.text);
|
|
1597
|
+
}
|
|
1598
|
+
return lines.join("\n");
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
|
|
1525
1602
|
// ---------------------------------------------------------------------------------------------------
|
|
1526
1603
|
// History
|
|
1527
1604
|
// ---------------------------------------------------------------------------------------------------
|