node-opcua-server 2.164.2 → 2.165.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/dist/base_server.d.ts +95 -18
- package/dist/base_server.js +211 -63
- package/dist/base_server.js.map +1 -1
- package/dist/opcua_server.d.ts +171 -123
- package/dist/opcua_server.js +419 -181
- package/dist/opcua_server.js.map +1 -1
- package/dist/server_end_point.d.ts +108 -12
- package/dist/server_end_point.js +146 -46
- package/dist/server_end_point.js.map +1 -1
- package/dist/server_engine.d.ts +32 -14
- package/dist/server_engine.js +155 -54
- package/dist/server_engine.js.map +1 -1
- package/package.json +42 -42
- package/source/base_server.ts +246 -84
- package/source/opcua_server.ts +621 -441
- package/source/server_end_point.ts +267 -83
- package/source/server_engine.ts +240 -130
package/source/server_engine.ts
CHANGED
|
@@ -1,86 +1,91 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module node-opcua-server
|
|
3
3
|
*/
|
|
4
|
-
import { EventEmitter } from "events";
|
|
5
|
-
import { types } from "util";
|
|
4
|
+
import { EventEmitter } from "node:events";
|
|
5
|
+
import { types } from "node:util";
|
|
6
|
+
|
|
6
7
|
import async from "async";
|
|
7
8
|
import chalk from "chalk";
|
|
8
|
-
import { assert } from "node-opcua-assert";
|
|
9
|
-
import { BinaryStream } from "node-opcua-binary-stream";
|
|
10
9
|
import {
|
|
11
|
-
addElement,
|
|
12
10
|
AddressSpace,
|
|
11
|
+
addElement,
|
|
12
|
+
type BindVariableOptions,
|
|
13
13
|
bindExtObjArrayNode,
|
|
14
|
+
type DTServerStatus,
|
|
14
15
|
ensureObjectIsSecure,
|
|
15
|
-
|
|
16
|
+
type IServerBase,
|
|
17
|
+
type ISessionContext,
|
|
18
|
+
type MethodFunctor,
|
|
16
19
|
removeElement,
|
|
17
|
-
SessionContext,
|
|
18
|
-
UADynamicVariableArray,
|
|
19
|
-
UAMethod,
|
|
20
|
-
UAObject,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
BindVariableOptions,
|
|
26
|
-
ISessionContext,
|
|
27
|
-
DTServerStatus,
|
|
28
|
-
IServerBase
|
|
20
|
+
type SessionContext,
|
|
21
|
+
type UADynamicVariableArray,
|
|
22
|
+
type UAMethod,
|
|
23
|
+
type UAObject,
|
|
24
|
+
type UAServerDiagnostics,
|
|
25
|
+
type UAServerDiagnosticsSummary,
|
|
26
|
+
type UAServerStatus,
|
|
27
|
+
type UAVariable
|
|
29
28
|
} from "node-opcua-address-space";
|
|
30
29
|
import { generateAddressSpace } from "node-opcua-address-space/nodeJS";
|
|
31
|
-
import {
|
|
30
|
+
import { assert } from "node-opcua-assert";
|
|
31
|
+
import type { UInt32 } from "node-opcua-basic-types";
|
|
32
|
+
import { BinaryStream } from "node-opcua-binary-stream";
|
|
33
|
+
import type { CreateSubscriptionRequestLike } from "node-opcua-client";
|
|
32
34
|
import {
|
|
33
35
|
ServerDiagnosticsSummaryDataType,
|
|
34
36
|
ServerState,
|
|
35
37
|
ServerStatusDataType,
|
|
36
38
|
SubscriptionDiagnosticsDataType
|
|
37
39
|
} from "node-opcua-common";
|
|
38
|
-
import { AttributeIds, coerceLocalizedText, LocalizedTextLike, makeAccessLevelFlag, NodeClass } from "node-opcua-data-model";
|
|
39
|
-
import { coerceNodeId, makeNodeId, NodeId, NodeIdLike, NodeIdType, resolveNodeId } from "node-opcua-nodeid";
|
|
40
|
-
import { BrowseResult } from "node-opcua-service-browse";
|
|
41
|
-
import { UInt32 } from "node-opcua-basic-types";
|
|
42
|
-
import { CreateSubscriptionRequestLike } from "node-opcua-client";
|
|
43
40
|
import { DataTypeIds, MethodIds, ObjectIds, VariableIds } from "node-opcua-constants";
|
|
41
|
+
import { AttributeIds, coerceLocalizedText, type LocalizedTextLike, makeAccessLevelFlag, NodeClass } from "node-opcua-data-model";
|
|
42
|
+
import type { DataValue } from "node-opcua-data-value";
|
|
44
43
|
import { getCurrentClock, getMinOPCUADate } from "node-opcua-date-time";
|
|
45
44
|
import { checkDebugFlag, make_debugLog, make_errorLog, make_warningLog, traceFromThisProjectOnly } from "node-opcua-debug";
|
|
45
|
+
import { coerceNodeId, makeNodeId, NodeId, type NodeIdLike, NodeIdType, resolveNodeId } from "node-opcua-nodeid";
|
|
46
46
|
import { nodesets } from "node-opcua-nodesets";
|
|
47
47
|
import { ObjectRegistry } from "node-opcua-object-registry";
|
|
48
|
+
import type { BrowseResult } from "node-opcua-service-browse";
|
|
48
49
|
import { CallMethodResult } from "node-opcua-service-call";
|
|
49
|
-
import { TransferResult } from "node-opcua-service-subscription";
|
|
50
50
|
import { ApplicationDescription } from "node-opcua-service-endpoints";
|
|
51
|
-
import { HistoryReadRequest, HistoryReadResult, HistoryReadValueId } from "node-opcua-service-history";
|
|
52
|
-
import {
|
|
51
|
+
import type { HistoryReadRequest, HistoryReadResult, HistoryReadValueId } from "node-opcua-service-history";
|
|
52
|
+
import { TransferResult } from "node-opcua-service-subscription";
|
|
53
|
+
import { type CallbackT, type StatusCode, StatusCodes } from "node-opcua-status-code";
|
|
53
54
|
import {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
ApplicationType,
|
|
56
|
+
type BrowseDescription,
|
|
57
|
+
type BrowseDescriptionOptions,
|
|
58
|
+
type BrowsePath,
|
|
59
|
+
type BrowsePathResult,
|
|
60
|
+
type BuildInfo,
|
|
61
|
+
type BuildInfoOptions,
|
|
62
|
+
type CallMethodRequest,
|
|
63
|
+
type CallMethodResultOptions,
|
|
64
|
+
ProgramDiagnosticDataType,
|
|
65
|
+
type ReadRequestOptions,
|
|
62
66
|
ReadValueId,
|
|
67
|
+
type SessionDiagnosticsDataType,
|
|
68
|
+
type SessionSecurityDiagnosticsDataType,
|
|
63
69
|
TimeZoneDataType,
|
|
64
|
-
|
|
65
|
-
CallMethodResultOptions,
|
|
66
|
-
ReadRequestOptions,
|
|
67
|
-
BrowseDescriptionOptions,
|
|
68
|
-
CallMethodRequest,
|
|
69
|
-
ApplicationType
|
|
70
|
+
type WriteValue
|
|
70
71
|
} from "node-opcua-types";
|
|
71
72
|
import { DataType, isValidVariant, Variant, VariantArrayType } from "node-opcua-variant";
|
|
72
|
-
|
|
73
|
-
import { HistoryServerCapabilities, HistoryServerCapabilitiesOptions } from "./history_server_capabilities";
|
|
73
|
+
import { AddressSpaceAccessor } from "./addressSpace_accessor";
|
|
74
|
+
import { HistoryServerCapabilities, type HistoryServerCapabilitiesOptions } from "./history_server_capabilities";
|
|
75
|
+
import type { IAddressSpaceAccessor } from "./i_address_space_accessor";
|
|
74
76
|
import { MonitoredItem } from "./monitored_item";
|
|
75
|
-
import {
|
|
77
|
+
import type { OPCUAServerOptions } from "./opcua_server";
|
|
78
|
+
import {
|
|
79
|
+
defaultServerCapabilities,
|
|
80
|
+
ServerCapabilities,
|
|
81
|
+
type ServerCapabilitiesOptions,
|
|
82
|
+
type ServerOperationLimits
|
|
83
|
+
} from "./server_capabilities";
|
|
76
84
|
import { ServerSidePublishEngine } from "./server_publish_engine";
|
|
77
85
|
import { ServerSidePublishEngineForOrphanSubscription } from "./server_publish_engine_for_orphan_subscriptions";
|
|
78
86
|
import { ServerSession } from "./server_session";
|
|
79
87
|
import { Subscription } from "./server_subscription";
|
|
80
88
|
import { sessionsCompatibleForTransfer } from "./sessions_compatible_for_transfer";
|
|
81
|
-
import { OPCUAServerOptions } from "./opcua_server";
|
|
82
|
-
import { IAddressSpaceAccessor } from "./i_address_space_accessor";
|
|
83
|
-
import { AddressSpaceAccessor } from "./addressSpace_accessor";
|
|
84
89
|
|
|
85
90
|
const debugLog = make_debugLog(__filename);
|
|
86
91
|
const errorLog = make_errorLog(__filename);
|
|
@@ -95,7 +100,7 @@ async function shutdownAndDisposeAddressSpace(this: ServerEngine) {
|
|
|
95
100
|
if (this.addressSpace) {
|
|
96
101
|
await this.addressSpace.shutdown();
|
|
97
102
|
this.addressSpace.dispose();
|
|
98
|
-
|
|
103
|
+
this.addressSpace = null;
|
|
99
104
|
}
|
|
100
105
|
}
|
|
101
106
|
|
|
@@ -220,7 +225,10 @@ function resendData(
|
|
|
220
225
|
assert(typeof callback === "function");
|
|
221
226
|
|
|
222
227
|
const data = _getSubscription.call(this, inputArguments, context);
|
|
223
|
-
if (data.statusCode)
|
|
228
|
+
if (data.statusCode) {
|
|
229
|
+
callback(null, { statusCode: data.statusCode });
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
224
232
|
const { subscription } = data;
|
|
225
233
|
|
|
226
234
|
subscription
|
|
@@ -260,11 +268,14 @@ function getMonitoredItemsId(
|
|
|
260
268
|
function __bindVariable(self: ServerEngine, nodeId: NodeIdLike, options?: BindVariableOptions) {
|
|
261
269
|
options = options || {};
|
|
262
270
|
|
|
263
|
-
|
|
264
|
-
|
|
271
|
+
if (!self.addressSpace) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const variable = self.addressSpace.findNode(nodeId) as UAVariable;
|
|
275
|
+
if (variable?.bindVariable) {
|
|
265
276
|
variable.bindVariable(options, true);
|
|
266
277
|
assert(typeof variable.asyncRefresh === "function");
|
|
267
|
-
assert(typeof (variable as
|
|
278
|
+
assert(typeof (variable as unknown as Record<string, unknown>).refreshFunc === "function");
|
|
268
279
|
} else {
|
|
269
280
|
warningLog(
|
|
270
281
|
"Warning: cannot bind object with id ",
|
|
@@ -419,8 +430,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
419
430
|
"http://opcfoundation.org/UA-Profile/Server/StandardEventSubscription",
|
|
420
431
|
"http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary",
|
|
421
432
|
"http://opcfoundation.org/UA-Profile/Server/FileAccess",
|
|
422
|
-
"http://opcfoundation.org/UA-Profile/Server/StateMachine"
|
|
423
|
-
|
|
433
|
+
"http://opcfoundation.org/UA-Profile/Server/StateMachine"
|
|
424
434
|
|
|
425
435
|
// "http://opcfoundation.org/UA-Profile/Transport/wss-uajson",
|
|
426
436
|
// "http://opcfoundation.org/UA-Profile/Transport/wss-uasc-uabinary"
|
|
@@ -445,8 +455,9 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
445
455
|
];
|
|
446
456
|
|
|
447
457
|
// make sure minSupportedSampleRate matches MonitoredItem.minimumSamplingInterval
|
|
448
|
-
(this.serverCapabilities
|
|
449
|
-
|
|
458
|
+
Object.defineProperty(this.serverCapabilities, "minSupportedSampleRate", {
|
|
459
|
+
get: () => options.serverCapabilities?.minSupportedSampleRate || MonitoredItem.minimumSamplingInterval,
|
|
460
|
+
configurable: true
|
|
450
461
|
});
|
|
451
462
|
|
|
452
463
|
this.serverConfiguration = options.serverConfiguration;
|
|
@@ -461,16 +472,19 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
461
472
|
// and sessionDiagnostics.currentSubscriptionsCount ( with an s)
|
|
462
473
|
assert(Object.prototype.hasOwnProperty.call(this.serverDiagnosticsSummary, "currentSubscriptionCount"));
|
|
463
474
|
|
|
464
|
-
(this.serverDiagnosticsSummary
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
475
|
+
Object.defineProperty(this.serverDiagnosticsSummary, "currentSubscriptionCount", {
|
|
476
|
+
get: () => {
|
|
477
|
+
// currentSubscriptionCount returns the total number of subscriptions
|
|
478
|
+
// that are currently active on all sessions
|
|
479
|
+
let counter = 0;
|
|
480
|
+
Object.values(this._sessions).forEach((session: ServerSession) => {
|
|
481
|
+
counter += session.currentSubscriptionCount;
|
|
482
|
+
});
|
|
483
|
+
// we also need to add the orphan subscriptions
|
|
484
|
+
counter += this._orphanPublishEngine ? this._orphanPublishEngine.subscriptions.length : 0;
|
|
485
|
+
return counter;
|
|
486
|
+
},
|
|
487
|
+
configurable: true
|
|
474
488
|
});
|
|
475
489
|
|
|
476
490
|
this._internalState = "creating";
|
|
@@ -483,7 +497,10 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
483
497
|
|
|
484
498
|
this._applicationUri = "";
|
|
485
499
|
if (typeof options.applicationUri === "function") {
|
|
486
|
-
(this
|
|
500
|
+
Object.defineProperty(this, "_applicationUri", {
|
|
501
|
+
get: options.applicationUri,
|
|
502
|
+
configurable: true
|
|
503
|
+
});
|
|
487
504
|
} else {
|
|
488
505
|
this._applicationUri = options.applicationUri || "<unset _applicationUri>";
|
|
489
506
|
}
|
|
@@ -492,10 +509,10 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
492
509
|
? options.serverDiagnosticsEnabled
|
|
493
510
|
: true;
|
|
494
511
|
|
|
495
|
-
this.serverDiagnosticsEnabled = options.serverDiagnosticsEnabled
|
|
512
|
+
this.serverDiagnosticsEnabled = options.serverDiagnosticsEnabled || false;
|
|
496
513
|
}
|
|
497
514
|
public isStarted(): boolean {
|
|
498
|
-
return !!this._serverStatus
|
|
515
|
+
return !!this._serverStatus;
|
|
499
516
|
}
|
|
500
517
|
|
|
501
518
|
public dispose(): void {
|
|
@@ -515,7 +532,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
515
532
|
}
|
|
516
533
|
|
|
517
534
|
this._shutdownTasks = [];
|
|
518
|
-
this._serverStatus = null as
|
|
535
|
+
this._serverStatus = null as unknown as ServerStatusDataType;
|
|
519
536
|
this._internalState = "disposed";
|
|
520
537
|
this.removeAllListeners();
|
|
521
538
|
|
|
@@ -523,11 +540,11 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
523
540
|
}
|
|
524
541
|
|
|
525
542
|
public get startTime(): Date {
|
|
526
|
-
return this._serverStatus.startTime
|
|
543
|
+
return this._serverStatus.startTime || new Date();
|
|
527
544
|
}
|
|
528
545
|
|
|
529
546
|
public get currentTime(): Date {
|
|
530
|
-
return this._serverStatus.currentTime
|
|
547
|
+
return this._serverStatus.currentTime || new Date();
|
|
531
548
|
}
|
|
532
549
|
|
|
533
550
|
public get buildInfo(): BuildInfo {
|
|
@@ -683,9 +700,11 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
683
700
|
this._expectedShutdownTime = date;
|
|
684
701
|
}
|
|
685
702
|
public setShutdownReason(reason: LocalizedTextLike): void {
|
|
703
|
+
const localizedReason = coerceLocalizedText(reason);
|
|
704
|
+
if (!localizedReason) return;
|
|
686
705
|
this.addressSpace?.rootFolder.objects.server.serverStatus.shutdownReason.setValueFromSource({
|
|
687
706
|
dataType: DataType.LocalizedText,
|
|
688
|
-
value:
|
|
707
|
+
value: localizedReason
|
|
689
708
|
});
|
|
690
709
|
}
|
|
691
710
|
/**
|
|
@@ -705,7 +724,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
705
724
|
* the name of the server
|
|
706
725
|
*/
|
|
707
726
|
public get serverName(): string {
|
|
708
|
-
return this._serverStatus.buildInfo
|
|
727
|
+
return this._serverStatus.buildInfo?.productName || "";
|
|
709
728
|
}
|
|
710
729
|
|
|
711
730
|
/**
|
|
@@ -733,8 +752,77 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
733
752
|
});
|
|
734
753
|
}
|
|
735
754
|
|
|
755
|
+
public getServerState(): ServerState {
|
|
756
|
+
return this._serverStatus.state;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Set the `ServerConfiguration.InApplicationSetup` property
|
|
761
|
+
* in the address space.
|
|
762
|
+
*
|
|
763
|
+
* This flag indicates whether the server is currently in
|
|
764
|
+
* its initial application setup phase (e.g. waiting for
|
|
765
|
+
* GDS provisioning).
|
|
766
|
+
*/
|
|
767
|
+
public setInApplicationSetup(value: boolean): void {
|
|
768
|
+
const addressSpace = this.addressSpace;
|
|
769
|
+
if (!addressSpace) {
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
const serverConfiguration = addressSpace.rootFolder?.objects?.server?.getChildByName(
|
|
773
|
+
"ServerConfiguration"
|
|
774
|
+
) as UAObject | null;
|
|
775
|
+
if (!serverConfiguration) {
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
let prop = serverConfiguration.getPropertyByName("InApplicationSetup") as UAVariable | null;
|
|
779
|
+
if (!prop) {
|
|
780
|
+
// InApplicationSetup is ModellingRule_Optional on
|
|
781
|
+
// ServerConfigurationType (i=19308) — instantiate
|
|
782
|
+
// it on the instance on first use.
|
|
783
|
+
const ns = addressSpace.getOwnNamespace();
|
|
784
|
+
prop = ns.addVariable({
|
|
785
|
+
browseName: { name: "InApplicationSetup", namespaceIndex: 0 },
|
|
786
|
+
propertyOf: serverConfiguration,
|
|
787
|
+
typeDefinition: "PropertyType",
|
|
788
|
+
dataType: DataType.Boolean,
|
|
789
|
+
minimumSamplingInterval: -1,
|
|
790
|
+
value: { dataType: DataType.Boolean, value }
|
|
791
|
+
});
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
prop.setValueFromSource({
|
|
795
|
+
dataType: DataType.Boolean,
|
|
796
|
+
value
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
* Read the current value of
|
|
802
|
+
* `ServerConfiguration.InApplicationSetup`.
|
|
803
|
+
*
|
|
804
|
+
* Returns `false` if the property does not exist in
|
|
805
|
+
* the address space.
|
|
806
|
+
*/
|
|
807
|
+
public getInApplicationSetup(): boolean {
|
|
808
|
+
const serverConfiguration = this.addressSpace?.rootFolder?.objects?.server?.getChildByName(
|
|
809
|
+
"ServerConfiguration"
|
|
810
|
+
) as UAObject | null;
|
|
811
|
+
if (!serverConfiguration) {
|
|
812
|
+
return false;
|
|
813
|
+
}
|
|
814
|
+
const prop = serverConfiguration.getPropertyByName("InApplicationSetup") as UAVariable | null;
|
|
815
|
+
if (!prop) {
|
|
816
|
+
return false;
|
|
817
|
+
}
|
|
818
|
+
return prop.readValue().value.value ?? false;
|
|
819
|
+
}
|
|
820
|
+
|
|
736
821
|
public getServerDiagnosticsEnabledFlag(): boolean {
|
|
737
|
-
|
|
822
|
+
if (!this.addressSpace) {
|
|
823
|
+
return false;
|
|
824
|
+
}
|
|
825
|
+
const server = this.addressSpace.rootFolder.objects.server;
|
|
738
826
|
const serverDiagnostics = server.getComponentByName("ServerDiagnostics") as UAVariable;
|
|
739
827
|
if (!serverDiagnostics) {
|
|
740
828
|
return false;
|
|
@@ -784,7 +872,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
784
872
|
const endTime = new Date();
|
|
785
873
|
debugLog("Loading ", options.nodeset_filename, " done : ", endTime.getTime() - startTime.getTime(), " ms");
|
|
786
874
|
|
|
787
|
-
const bindVariableIfPresent = (nodeId: NodeId, opts
|
|
875
|
+
const bindVariableIfPresent = (nodeId: NodeId, opts?: BindVariableOptions) => {
|
|
788
876
|
assert(!nodeId.isEmpty());
|
|
789
877
|
const obj = addressSpace.findNode(nodeId);
|
|
790
878
|
if (obj) {
|
|
@@ -842,8 +930,8 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
842
930
|
const bindStandardScalar = (
|
|
843
931
|
id: number,
|
|
844
932
|
dataType: DataType,
|
|
845
|
-
func: () =>
|
|
846
|
-
setter_func?: (value:
|
|
933
|
+
func: () => unknown,
|
|
934
|
+
setter_func?: (value: boolean) => void
|
|
847
935
|
) => {
|
|
848
936
|
assert(typeof id === "number", "expecting id to be a number");
|
|
849
937
|
assert(typeof func === "function");
|
|
@@ -867,7 +955,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
867
955
|
/* c8 ignore next */
|
|
868
956
|
if (!isValidVariant(VariantArrayType.Scalar, dataType, func())) {
|
|
869
957
|
errorLog("func", func());
|
|
870
|
-
throw new Error(
|
|
958
|
+
throw new Error(`bindStandardScalar : func doesn't provide an value of type ${DataType[dataType]}`);
|
|
871
959
|
}
|
|
872
960
|
|
|
873
961
|
return bindVariableIfPresent(nodeId, {
|
|
@@ -882,7 +970,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
882
970
|
});
|
|
883
971
|
};
|
|
884
972
|
|
|
885
|
-
const bindStandardArray = (id: number, variantDataType: DataType,
|
|
973
|
+
const bindStandardArray = (id: number, variantDataType: DataType, _dataType: unknown, func: () => unknown[]) => {
|
|
886
974
|
assert(typeof func === "function");
|
|
887
975
|
assert(variantDataType !== null); // check invalid dataType
|
|
888
976
|
|
|
@@ -909,7 +997,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
909
997
|
bindStandardScalar(VariableIds.Server_EstimatedReturnTime, DataType.DateTime, () => getMinOPCUADate());
|
|
910
998
|
|
|
911
999
|
// TimeZoneDataType
|
|
912
|
-
|
|
1000
|
+
addressSpace.findDataType(resolveNodeId(DataTypeIds.TimeZoneDataType));
|
|
913
1001
|
|
|
914
1002
|
const timeZone = new TimeZoneDataType({
|
|
915
1003
|
daylightSavingInOffset: /* boolean*/ false,
|
|
@@ -1005,7 +1093,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1005
1093
|
serverStatusNode.secondsTillShutdown.touchValue();
|
|
1006
1094
|
return engine.secondsTillShutdown();
|
|
1007
1095
|
}
|
|
1008
|
-
return (target as
|
|
1096
|
+
return (target as unknown as Record<string | symbol, unknown>)[prop];
|
|
1009
1097
|
}
|
|
1010
1098
|
});
|
|
1011
1099
|
this._serverStatus = serverStatusNode.$extensionObject;
|
|
@@ -1111,12 +1199,12 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1111
1199
|
const keys = Object.keys(operationLimits);
|
|
1112
1200
|
|
|
1113
1201
|
keys.forEach((key: string) => {
|
|
1114
|
-
const uid =
|
|
1115
|
-
const nodeId = makeNodeId((VariableIds as
|
|
1202
|
+
const uid = `Server_ServerCapabilities_OperationLimits_${upperCaseFirst(key)}`;
|
|
1203
|
+
const nodeId = makeNodeId((VariableIds as unknown as Record<string, number>)[uid]);
|
|
1116
1204
|
assert(!nodeId.isEmpty());
|
|
1117
1205
|
|
|
1118
|
-
bindStandardScalar((VariableIds as
|
|
1119
|
-
return (operationLimits as
|
|
1206
|
+
bindStandardScalar((VariableIds as unknown as Record<string, number>)[uid], DataType.UInt32, () => {
|
|
1207
|
+
return (operationLimits as unknown as Record<string, unknown>)[key];
|
|
1120
1208
|
});
|
|
1121
1209
|
});
|
|
1122
1210
|
};
|
|
@@ -1128,7 +1216,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1128
1216
|
const nodeId = coerceNodeId("i=2399"); // ProgramStateMachineType_ProgramDiagnostics
|
|
1129
1217
|
const variable = addressSpace.findNode(nodeId) as UAVariable;
|
|
1130
1218
|
if (variable) {
|
|
1131
|
-
(variable as
|
|
1219
|
+
(variable as unknown as Record<string, unknown>).$extensionObject = new ProgramDiagnosticDataType({});
|
|
1132
1220
|
// variable.setValueFromSource({
|
|
1133
1221
|
// dataType: DataType.ExtensionObject,
|
|
1134
1222
|
// // value: new ProgramDiagnostic2DataType()
|
|
@@ -1201,7 +1289,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1201
1289
|
function r<T>(a: undefined | T | Getter<T>, defaultValue: T): T {
|
|
1202
1290
|
if (a === undefined) return defaultValue;
|
|
1203
1291
|
if (typeof a === "function") {
|
|
1204
|
-
return (a as
|
|
1292
|
+
return (a as unknown as () => T)();
|
|
1205
1293
|
}
|
|
1206
1294
|
return a;
|
|
1207
1295
|
}
|
|
@@ -1294,15 +1382,18 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1294
1382
|
|
|
1295
1383
|
// fix getMonitoredItems.outputArguments arrayDimensions
|
|
1296
1384
|
const fixGetMonitoredItemArgs = () => {
|
|
1297
|
-
const objects = this.addressSpace
|
|
1385
|
+
const objects = this.addressSpace?.rootFolder?.objects;
|
|
1298
1386
|
if (!objects || !objects.server) {
|
|
1299
1387
|
return;
|
|
1300
1388
|
}
|
|
1301
|
-
const getMonitoredItemsMethod = objects.server.getMethodByName("GetMonitoredItems")
|
|
1389
|
+
const getMonitoredItemsMethod = objects.server.getMethodByName("GetMonitoredItems");
|
|
1302
1390
|
if (!getMonitoredItemsMethod) {
|
|
1303
1391
|
return;
|
|
1304
1392
|
}
|
|
1305
|
-
const outputArguments = getMonitoredItemsMethod.outputArguments
|
|
1393
|
+
const outputArguments = getMonitoredItemsMethod.outputArguments;
|
|
1394
|
+
if (!outputArguments) {
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1306
1397
|
const dataValue = outputArguments.readValue();
|
|
1307
1398
|
if (!dataValue.value?.value) {
|
|
1308
1399
|
// value is null or undefined , meaning no arguments necessary
|
|
@@ -1318,7 +1409,10 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1318
1409
|
fixGetMonitoredItemArgs();
|
|
1319
1410
|
|
|
1320
1411
|
const prepareServerDiagnostics = () => {
|
|
1321
|
-
const addressSpace1 = this.addressSpace
|
|
1412
|
+
const addressSpace1 = this.addressSpace;
|
|
1413
|
+
if (!addressSpace1) {
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1322
1416
|
|
|
1323
1417
|
if (!addressSpace1.rootFolder.objects) {
|
|
1324
1418
|
return;
|
|
@@ -1349,22 +1443,24 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1349
1443
|
);
|
|
1350
1444
|
if (samplingIntervalDiagnosticsArray) {
|
|
1351
1445
|
addressSpace.deleteNode(samplingIntervalDiagnosticsArray);
|
|
1352
|
-
const s = serverDiagnosticsNode.getComponents();
|
|
1353
1446
|
}
|
|
1354
1447
|
|
|
1355
1448
|
const subscriptionDiagnosticsArrayNode = serverDiagnosticsNode.getComponentByName(
|
|
1356
1449
|
"SubscriptionDiagnosticsArray"
|
|
1357
|
-
)
|
|
1450
|
+
) as UADynamicVariableArray<SessionDiagnosticsDataType>;
|
|
1358
1451
|
assert(subscriptionDiagnosticsArrayNode.nodeClass === NodeClass.Variable);
|
|
1359
1452
|
bindExtObjArrayNode(subscriptionDiagnosticsArrayNode, "SubscriptionDiagnosticsType", "subscriptionId");
|
|
1360
1453
|
|
|
1361
1454
|
makeNotReadableIfEnabledFlagIsFalse(subscriptionDiagnosticsArrayNode);
|
|
1362
1455
|
|
|
1363
|
-
const sessionsDiagnosticsSummary = serverDiagnosticsNode.getComponentByName("SessionsDiagnosticsSummary")
|
|
1456
|
+
const sessionsDiagnosticsSummary = serverDiagnosticsNode.getComponentByName("SessionsDiagnosticsSummary");
|
|
1364
1457
|
|
|
1458
|
+
if (!sessionsDiagnosticsSummary) {
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1365
1461
|
const sessionDiagnosticsArray = sessionsDiagnosticsSummary.getComponentByName(
|
|
1366
1462
|
"SessionDiagnosticsArray"
|
|
1367
|
-
)
|
|
1463
|
+
) as UADynamicVariableArray<SessionDiagnosticsDataType>;
|
|
1368
1464
|
assert(sessionDiagnosticsArray.nodeClass === NodeClass.Variable);
|
|
1369
1465
|
|
|
1370
1466
|
bindExtObjArrayNode(sessionDiagnosticsArray, "SessionDiagnosticsVariableType", "sessionId");
|
|
@@ -1375,7 +1471,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1375
1471
|
} else {
|
|
1376
1472
|
const sessionSecurityDiagnosticsArray = sessionsDiagnosticsSummary.getComponentByName(
|
|
1377
1473
|
"SessionSecurityDiagnosticsArray"
|
|
1378
|
-
)
|
|
1474
|
+
) as UADynamicVariableArray<SessionSecurityDiagnosticsDataType>;
|
|
1379
1475
|
assert(sessionSecurityDiagnosticsArray.nodeClass === NodeClass.Variable);
|
|
1380
1476
|
bindExtObjArrayNode(sessionSecurityDiagnosticsArray, "SessionSecurityDiagnosticsType", "sessionId");
|
|
1381
1477
|
ensureObjectIsSecure(sessionSecurityDiagnosticsArray);
|
|
@@ -1397,7 +1493,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1397
1493
|
// do expansion first
|
|
1398
1494
|
for (const browseDescription of nodesToBrowse) {
|
|
1399
1495
|
const nodeId = resolveNodeId(browseDescription.nodeId);
|
|
1400
|
-
const node = this.addressSpace
|
|
1496
|
+
const node = this.addressSpace?.findNode(nodeId);
|
|
1401
1497
|
if (node) {
|
|
1402
1498
|
if (node.onFirstBrowseAction) {
|
|
1403
1499
|
try {
|
|
@@ -1416,19 +1512,34 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1416
1512
|
return await this.browse(context, nodesToBrowse);
|
|
1417
1513
|
}
|
|
1418
1514
|
public async browse(context: ISessionContext, nodesToBrowse: BrowseDescriptionOptions[]): Promise<BrowseResult[]> {
|
|
1419
|
-
|
|
1515
|
+
if (!this.addressSpaceAccessor) {
|
|
1516
|
+
throw new Error("addressSpaceAccessor is not available");
|
|
1517
|
+
}
|
|
1518
|
+
return this.addressSpaceAccessor.browse(context, nodesToBrowse);
|
|
1420
1519
|
}
|
|
1421
1520
|
public async read(context: ISessionContext, readRequest: ReadRequestOptions): Promise<DataValue[]> {
|
|
1422
|
-
|
|
1521
|
+
if (!this.addressSpaceAccessor) {
|
|
1522
|
+
throw new Error("addressSpaceAccessor is not available");
|
|
1523
|
+
}
|
|
1524
|
+
return this.addressSpaceAccessor.read(context, readRequest);
|
|
1423
1525
|
}
|
|
1424
1526
|
public async write(context: ISessionContext, nodesToWrite: WriteValue[]): Promise<StatusCode[]> {
|
|
1425
|
-
|
|
1527
|
+
if (!this.addressSpaceAccessor) {
|
|
1528
|
+
throw new Error("addressSpaceAccessor is not available");
|
|
1529
|
+
}
|
|
1530
|
+
return await this.addressSpaceAccessor.write(context, nodesToWrite);
|
|
1426
1531
|
}
|
|
1427
1532
|
public async call(context: ISessionContext, methodsToCall: CallMethodRequest[]): Promise<CallMethodResultOptions[]> {
|
|
1428
|
-
|
|
1533
|
+
if (!this.addressSpaceAccessor) {
|
|
1534
|
+
throw new Error("addressSpaceAccessor is not available");
|
|
1535
|
+
}
|
|
1536
|
+
return await this.addressSpaceAccessor.call(context, methodsToCall);
|
|
1429
1537
|
}
|
|
1430
1538
|
public async historyRead(context: ISessionContext, historyReadRequest: HistoryReadRequest): Promise<HistoryReadResult[]> {
|
|
1431
|
-
|
|
1539
|
+
if (!this.addressSpaceAccessor) {
|
|
1540
|
+
throw new Error("addressSpaceAccessor is not available");
|
|
1541
|
+
}
|
|
1542
|
+
return this.addressSpaceAccessor.historyRead(context, historyReadRequest);
|
|
1432
1543
|
}
|
|
1433
1544
|
|
|
1434
1545
|
public getOldestInactiveSession(): ServerSession | null {
|
|
@@ -1467,7 +1578,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1467
1578
|
const sessionTimeout = options.sessionTimeout || 1000;
|
|
1468
1579
|
assert(typeof sessionTimeout === "number");
|
|
1469
1580
|
|
|
1470
|
-
const session = new ServerSession(this, options.server.userManager
|
|
1581
|
+
const session = new ServerSession(this, options.server.userManager || {}, sessionTimeout);
|
|
1471
1582
|
|
|
1472
1583
|
debugLog("createSession :sessionTimeout = ", session.sessionTimeout);
|
|
1473
1584
|
|
|
@@ -1479,13 +1590,13 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1479
1590
|
// TODO : When a Session is created, the Server adds an entry for the Client
|
|
1480
1591
|
// in its SessionDiagnosticsArray Variable
|
|
1481
1592
|
|
|
1482
|
-
session.on("new_subscription", (
|
|
1593
|
+
session.on("new_subscription", (_subscription: Subscription) => {
|
|
1483
1594
|
this.serverDiagnosticsSummary.cumulatedSubscriptionCount += 1;
|
|
1484
1595
|
// add the subscription diagnostics in our subscriptions diagnostics array
|
|
1485
1596
|
// note currentSubscriptionCount is handled directly with a special getter
|
|
1486
1597
|
});
|
|
1487
1598
|
|
|
1488
|
-
session.on("subscription_terminated", (
|
|
1599
|
+
session.on("subscription_terminated", (_subscription: Subscription) => {
|
|
1489
1600
|
// remove the subscription diagnostics in our subscriptions diagnostics array
|
|
1490
1601
|
// note currentSubscriptionCount is handled directly with a special getter
|
|
1491
1602
|
});
|
|
@@ -1555,7 +1666,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1555
1666
|
|
|
1556
1667
|
// c8 ignore next
|
|
1557
1668
|
if (!session) {
|
|
1558
|
-
throw new Error(
|
|
1669
|
+
throw new Error(`cannot find session with this authenticationToken ${authenticationToken.toString()}`);
|
|
1559
1670
|
}
|
|
1560
1671
|
|
|
1561
1672
|
if (!deleteSubscriptions) {
|
|
@@ -1586,7 +1697,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1586
1697
|
|
|
1587
1698
|
public findSubscription(subscriptionId: number): Subscription | null {
|
|
1588
1699
|
const subscriptions: Subscription[] = [];
|
|
1589
|
-
Object.values(this._sessions).
|
|
1700
|
+
Object.values(this._sessions).forEach((session) => {
|
|
1590
1701
|
if (subscriptions.length) {
|
|
1591
1702
|
return;
|
|
1592
1703
|
}
|
|
@@ -1655,7 +1766,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1655
1766
|
// warningLog("ServerEngine#transferSubscription => BadUserAccessDenied");
|
|
1656
1767
|
// return new TransferResult({ statusCode: StatusCodes.BadUserAccessDenied });
|
|
1657
1768
|
// }
|
|
1658
|
-
if (
|
|
1769
|
+
if (session.publishEngine === (subscription.publishEngine as unknown)) {
|
|
1659
1770
|
// subscription is already in this session !!
|
|
1660
1771
|
return new TransferResult({ statusCode: StatusCodes.BadNothingToDo });
|
|
1661
1772
|
}
|
|
@@ -1669,8 +1780,6 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1669
1780
|
// The number of times the subscription has been transferred to an alternate session for the same client.
|
|
1670
1781
|
subscription.subscriptionDiagnostics.transferredToSameClientCount++;
|
|
1671
1782
|
|
|
1672
|
-
const nbSubscriptionBefore = session.publishEngine.subscriptionCount;
|
|
1673
|
-
|
|
1674
1783
|
if (subscription.$session) {
|
|
1675
1784
|
subscription.$session._unexposeSubscriptionDiagnostics(subscription);
|
|
1676
1785
|
}
|
|
@@ -1681,7 +1790,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1681
1790
|
|
|
1682
1791
|
session._exposeSubscriptionDiagnostics(subscription);
|
|
1683
1792
|
|
|
1684
|
-
assert(
|
|
1793
|
+
assert(subscription.publishEngine === session.publishEngine);
|
|
1685
1794
|
// assert(session.publishEngine.subscriptionCount === nbSubscriptionBefore + 1);
|
|
1686
1795
|
|
|
1687
1796
|
const result = new TransferResult({
|
|
@@ -1728,7 +1837,10 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1728
1837
|
return browsePathResults;
|
|
1729
1838
|
}
|
|
1730
1839
|
public async translateBrowsePath(browsePath: BrowsePath): Promise<BrowsePathResult> {
|
|
1731
|
-
|
|
1840
|
+
if (!this.addressSpace) {
|
|
1841
|
+
throw new Error("addressSpace is not available");
|
|
1842
|
+
}
|
|
1843
|
+
return this.addressSpace.browsePath(browsePath);
|
|
1732
1844
|
}
|
|
1733
1845
|
|
|
1734
1846
|
/**
|
|
@@ -1765,12 +1877,12 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1765
1877
|
continue;
|
|
1766
1878
|
}
|
|
1767
1879
|
// ... and that are valid object and instances of Variables ...
|
|
1768
|
-
const uaNode = this.addressSpace
|
|
1880
|
+
const uaNode = this.addressSpace?.findNode(nodeToRefresh.nodeId);
|
|
1769
1881
|
if (!uaNode || !(uaNode.nodeClass === NodeClass.Variable)) {
|
|
1770
1882
|
continue;
|
|
1771
1883
|
}
|
|
1772
1884
|
// ... and that have been declared as asynchronously updating
|
|
1773
|
-
if (typeof (uaNode as
|
|
1885
|
+
if (typeof (uaNode as unknown as Record<string, unknown>).refreshFunc !== "function") {
|
|
1774
1886
|
continue;
|
|
1775
1887
|
}
|
|
1776
1888
|
const key = uaNode.nodeId.toString();
|
|
@@ -1783,7 +1895,8 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1783
1895
|
const uaVariableArray = Object.values(nodeMap);
|
|
1784
1896
|
if (uaVariableArray.length === 0) {
|
|
1785
1897
|
// nothing to do
|
|
1786
|
-
|
|
1898
|
+
callback(null, []);
|
|
1899
|
+
return;
|
|
1787
1900
|
}
|
|
1788
1901
|
// perform all asyncRefresh in parallel
|
|
1789
1902
|
async.map(
|
|
@@ -1810,7 +1923,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1810
1923
|
debugLog("ServerEngine#_exposeSubscriptionDiagnostics", subscription.subscriptionId);
|
|
1811
1924
|
const subscriptionDiagnosticsArray = this._getServerSubscriptionDiagnosticsArrayNode();
|
|
1812
1925
|
const subscriptionDiagnostics = subscription.subscriptionDiagnostics;
|
|
1813
|
-
assert((subscriptionDiagnostics as
|
|
1926
|
+
assert((subscriptionDiagnostics as unknown as Record<string, unknown>).$subscription === subscription);
|
|
1814
1927
|
assert(subscriptionDiagnostics instanceof SubscriptionDiagnosticsDataType);
|
|
1815
1928
|
|
|
1816
1929
|
if (subscriptionDiagnostics && subscriptionDiagnosticsArray) {
|
|
@@ -1826,7 +1939,6 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1826
1939
|
const subscriptionDiagnostics = subscription.subscriptionDiagnostics;
|
|
1827
1940
|
assert(subscriptionDiagnostics instanceof SubscriptionDiagnosticsDataType);
|
|
1828
1941
|
if (subscriptionDiagnostics && serverSubscriptionDiagnosticsArray) {
|
|
1829
|
-
const node = (serverSubscriptionDiagnosticsArray as any)[subscription.id];
|
|
1830
1942
|
removeElement(serverSubscriptionDiagnosticsArray, (a) => a.subscriptionId === subscription.id);
|
|
1831
1943
|
/*assert(
|
|
1832
1944
|
!(subscriptionDiagnosticsArray as any)[subscription.id],
|
|
@@ -1860,7 +1972,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1860
1972
|
maxKeepAliveCount,
|
|
1861
1973
|
maxNotificationsPerPublish: request.maxNotificationsPerPublish,
|
|
1862
1974
|
priority: request.priority || 0,
|
|
1863
|
-
publishEngine: session.publishEngine as
|
|
1975
|
+
publishEngine: session.publishEngine as unknown as ServerSidePublishEngine, //
|
|
1864
1976
|
publishingEnabled: request.publishingEnabled,
|
|
1865
1977
|
publishingInterval,
|
|
1866
1978
|
// -------------------
|
|
@@ -1872,7 +1984,7 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1872
1984
|
// add subscriptionDiagnostics
|
|
1873
1985
|
this._exposeSubscriptionDiagnostics(subscription);
|
|
1874
1986
|
|
|
1875
|
-
assert(
|
|
1987
|
+
assert(subscription.publishEngine === session.publishEngine);
|
|
1876
1988
|
session.publishEngine.add_subscription(subscription);
|
|
1877
1989
|
|
|
1878
1990
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
@@ -1890,19 +2002,18 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1890
2002
|
assert(typeof func === "function");
|
|
1891
2003
|
assert(nodeId instanceof NodeId);
|
|
1892
2004
|
|
|
1893
|
-
const methodNode = this.addressSpace
|
|
2005
|
+
const methodNode = this.addressSpace?.findNode(nodeId) as UAMethod | undefined;
|
|
1894
2006
|
if (!methodNode) {
|
|
1895
2007
|
return;
|
|
1896
2008
|
}
|
|
1897
|
-
if (methodNode
|
|
2009
|
+
if (methodNode?.bindMethod) {
|
|
1898
2010
|
methodNode.bindMethod(func);
|
|
1899
|
-
}
|
|
1900
|
-
|
|
1901
|
-
else {
|
|
2011
|
+
} else {
|
|
2012
|
+
/* c8 ignore next */
|
|
1902
2013
|
warningLog(
|
|
1903
2014
|
chalk.yellow("WARNING: cannot bind a method with id ") +
|
|
1904
|
-
|
|
1905
|
-
|
|
2015
|
+
chalk.cyan(nodeId.toString()) +
|
|
2016
|
+
chalk.yellow(". please check your nodeset.xml file or add this node programmatically")
|
|
1906
2017
|
);
|
|
1907
2018
|
warningLog(traceFromThisProjectOnly());
|
|
1908
2019
|
}
|
|
@@ -1917,14 +2028,13 @@ export class ServerEngine extends EventEmitter implements IAddressSpaceAccessor
|
|
|
1917
2028
|
}
|
|
1918
2029
|
const subscriptionDiagnosticsType = this.addressSpace.findVariableType("SubscriptionDiagnosticsType");
|
|
1919
2030
|
if (!subscriptionDiagnosticsType) {
|
|
1920
|
-
doDebug &&
|
|
1921
|
-
debugLog("ServerEngine#_getServerSubscriptionDiagnosticsArray " + ": cannot find SubscriptionDiagnosticsType");
|
|
2031
|
+
doDebug && debugLog(`ServerEngine#_getServerSubscriptionDiagnosticsArray : cannot find SubscriptionDiagnosticsType`);
|
|
1922
2032
|
}
|
|
1923
2033
|
|
|
1924
2034
|
// SubscriptionDiagnosticsArray = i=2290
|
|
1925
2035
|
const subscriptionDiagnosticsArrayNode = this.addressSpace.findNode(
|
|
1926
2036
|
makeNodeId(VariableIds.Server_ServerDiagnostics_SubscriptionDiagnosticsArray)
|
|
1927
|
-
)
|
|
2037
|
+
);
|
|
1928
2038
|
|
|
1929
2039
|
return subscriptionDiagnosticsArrayNode as UADynamicVariableArray<SubscriptionDiagnosticsDataType>;
|
|
1930
2040
|
}
|