node-opcua-server 2.167.0 → 2.168.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/addressSpace_accessor.d.ts +6 -6
- package/dist/addressSpace_accessor.js +2 -2
- package/dist/addressSpace_accessor.js.map +1 -1
- package/dist/base_server.d.ts +14 -3
- package/dist/base_server.js +63 -41
- package/dist/base_server.js.map +1 -1
- package/dist/extract_password_from_blob.js +1 -3
- package/dist/extract_password_from_blob.js.map +1 -1
- package/dist/factory.d.ts +2 -3
- package/dist/factory.js.map +1 -1
- package/dist/filter/check_where_clause_on_address_space.d.ts +2 -2
- package/dist/filter/check_where_clause_on_address_space.js +1 -2
- package/dist/filter/check_where_clause_on_address_space.js.map +1 -1
- package/dist/filter/extract_event_fields.d.ts +3 -3
- package/dist/filter/extract_event_fields.js +1 -2
- package/dist/filter/extract_event_fields.js.map +1 -1
- package/dist/helper.d.ts +3 -3
- package/dist/helper.js +4 -8
- package/dist/helper.js.map +1 -1
- package/dist/i_address_space_accessor.d.ts +4 -4
- package/dist/i_channel_data.d.ts +1 -1
- package/dist/i_register_server_manager.d.ts +1 -1
- package/dist/i_server_side_publish_engine.d.ts +8 -6
- package/dist/i_server_side_publish_engine.js +7 -2
- package/dist/i_server_side_publish_engine.js.map +1 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/dist/invalidate_server_certificate_cache.d.ts +16 -0
- package/dist/invalidate_server_certificate_cache.js +28 -0
- package/dist/invalidate_server_certificate_cache.js.map +1 -0
- package/dist/monitored_item.d.ts +10 -11
- package/dist/monitored_item.js +38 -39
- package/dist/monitored_item.js.map +1 -1
- package/dist/node_sampler.d.ts +1 -1
- package/dist/node_sampler.js +2 -4
- package/dist/node_sampler.js.map +1 -1
- package/dist/opcua_server.d.ts +57 -62
- package/dist/opcua_server.js +7 -7
- package/dist/opcua_server.js.map +1 -1
- package/dist/register_server_manager_hidden.d.ts +1 -1
- package/dist/register_server_manager_hidden.js +2 -4
- package/dist/register_server_manager_hidden.js.map +1 -1
- package/dist/register_server_manager_mdns_only.d.ts +1 -1
- package/dist/register_server_manager_mdns_only.js.map +1 -1
- package/dist/sampling_func.d.ts +2 -2
- package/dist/server_capabilities.d.ts +3 -3
- package/dist/server_capabilities.js.map +1 -1
- package/dist/server_end_point.d.ts +45 -2
- package/dist/server_end_point.js +130 -32
- package/dist/server_end_point.js.map +1 -1
- package/dist/server_engine.js +29 -25
- package/dist/server_engine.js.map +1 -1
- package/dist/server_publish_engine.d.ts +5 -5
- package/dist/server_publish_engine.js +29 -23
- package/dist/server_publish_engine.js.map +1 -1
- package/dist/server_publish_engine_for_orphan_subscriptions.d.ts +2 -2
- package/dist/server_publish_engine_for_orphan_subscriptions.js.map +1 -1
- package/dist/server_session.d.ts +9 -10
- package/dist/server_session.js +11 -12
- package/dist/server_session.js.map +1 -1
- package/dist/server_subscription.d.ts +13 -13
- package/dist/server_subscription.js +100 -79
- package/dist/server_subscription.js.map +1 -1
- package/dist/sessions_compatible_for_transfer.d.ts +1 -1
- package/dist/sessions_compatible_for_transfer.js +1 -1
- package/dist/sessions_compatible_for_transfer.js.map +1 -1
- package/dist/user_manager.d.ts +4 -4
- package/dist/user_manager.js +1 -1
- package/dist/user_manager.js.map +1 -1
- package/dist/user_manager_ua.d.ts +2 -2
- package/dist/user_manager_ua.js +2 -2
- package/dist/user_manager_ua.js.map +1 -1
- package/dist/validate_filter.d.ts +7 -4
- package/dist/validate_filter.js +5 -6
- package/dist/validate_filter.js.map +1 -1
- package/package.json +46 -46
- package/source/addressSpace_accessor.ts +24 -24
- package/source/base_server.ts +73 -59
- package/source/extract_password_from_blob.ts +3 -11
- package/source/factory.ts +2 -4
- package/source/filter/check_where_clause_on_address_space.ts +4 -7
- package/source/filter/extract_event_fields.ts +4 -5
- package/source/helper.ts +9 -13
- package/source/i_address_space_accessor.ts +13 -4
- package/source/i_channel_data.ts +1 -1
- package/source/i_register_server_manager.ts +2 -4
- package/source/i_server_side_publish_engine.ts +16 -9
- package/source/index.ts +10 -9
- package/source/invalidate_server_certificate_cache.ts +26 -0
- package/source/monitored_item.ts +44 -42
- package/source/node_sampler.ts +9 -11
- package/source/opcua_server.ts +68 -88
- package/source/register_server_manager_hidden.ts +3 -5
- package/source/register_server_manager_mdns_only.ts +1 -3
- package/source/sampling_func.ts +2 -2
- package/source/server_capabilities.ts +9 -6
- package/source/server_end_point.ts +142 -42
- package/source/server_engine.ts +22 -22
- package/source/server_publish_engine.ts +35 -30
- package/source/server_publish_engine_for_orphan_subscriptions.ts +3 -3
- package/source/server_session.ts +36 -33
- package/source/server_subscription.ts +182 -184
- package/source/sessions_compatible_for_transfer.ts +9 -9
- package/source/user_manager.ts +7 -7
- package/source/user_manager_ua.ts +3 -5
- package/source/validate_filter.ts +9 -11
|
@@ -3,53 +3,58 @@
|
|
|
3
3
|
*/
|
|
4
4
|
// tslint:disable:no-console
|
|
5
5
|
|
|
6
|
-
import { EventEmitter } from "events";
|
|
6
|
+
import { EventEmitter } from "node:events";
|
|
7
7
|
import chalk from "chalk";
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
|
+
type BaseNode,
|
|
11
|
+
type Duration,
|
|
12
|
+
type IAddressSpace,
|
|
13
|
+
type ISessionContext,
|
|
10
14
|
SessionContext,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
ISessionContext,
|
|
16
|
-
IAddressSpace,
|
|
17
|
-
UAVariable,
|
|
18
|
-
UAObject,
|
|
19
|
-
UAMethod
|
|
15
|
+
type UAMethod,
|
|
16
|
+
type UAObject,
|
|
17
|
+
type UAObjectType,
|
|
18
|
+
type UAVariable
|
|
20
19
|
} from "node-opcua-address-space";
|
|
21
20
|
import { assert } from "node-opcua-assert";
|
|
22
|
-
import { Byte, UInt32 } from "node-opcua-basic-types";
|
|
21
|
+
import type { Byte, UInt32 } from "node-opcua-basic-types";
|
|
23
22
|
import { SubscriptionDiagnosticsDataType } from "node-opcua-common";
|
|
24
|
-
import {
|
|
25
|
-
import { DataValue, TimestampsToReturn } from "node-opcua-data-value";
|
|
23
|
+
import { AttributeIds, isValidDataEncoding, NodeClass, type QualifiedNameLike } from "node-opcua-data-model";
|
|
24
|
+
import type { DataValue, TimestampsToReturn } from "node-opcua-data-value";
|
|
26
25
|
import { checkDebugFlag, make_debugLog, make_warningLog } from "node-opcua-debug";
|
|
27
26
|
import { NodeId } from "node-opcua-nodeid";
|
|
28
|
-
import { NumericRange } from "node-opcua-numeric-range";
|
|
27
|
+
import type { NumericRange } from "node-opcua-numeric-range";
|
|
29
28
|
import { ObjectRegistry } from "node-opcua-object-registry";
|
|
30
29
|
import { SequenceNumberGenerator } from "node-opcua-secure-channel";
|
|
31
|
-
import {
|
|
32
|
-
import { AggregateFilter } from "node-opcua-service-subscription";
|
|
30
|
+
import { checkSelectClauses, EventFilter } from "node-opcua-service-filter";
|
|
33
31
|
import {
|
|
32
|
+
AggregateFilter,
|
|
33
|
+
DataChangeFilter,
|
|
34
34
|
DataChangeNotification,
|
|
35
35
|
EventNotificationList,
|
|
36
|
-
|
|
36
|
+
MonitoredItemCreateRequest,
|
|
37
37
|
MonitoredItemCreateResult,
|
|
38
38
|
MonitoredItemNotification,
|
|
39
|
-
|
|
39
|
+
MonitoringMode,
|
|
40
40
|
NotificationMessage,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
MonitoredItemCreateRequest
|
|
41
|
+
PublishResponse,
|
|
42
|
+
StatusChangeNotification
|
|
44
43
|
} from "node-opcua-service-subscription";
|
|
45
|
-
import { StatusCode, StatusCodes } from "node-opcua-status-code";
|
|
46
|
-
import {
|
|
44
|
+
import { type StatusCode, StatusCodes } from "node-opcua-status-code";
|
|
45
|
+
import {
|
|
46
|
+
AggregateFilterResult,
|
|
47
|
+
ContentFilterResult,
|
|
48
|
+
EventFieldList,
|
|
49
|
+
EventFilterResult,
|
|
50
|
+
type MonitoringFilter
|
|
51
|
+
} from "node-opcua-types";
|
|
52
|
+
import { type IServerSidePublishEngine, TransferredSubscription } from "./i_server_side_publish_engine";
|
|
53
|
+
|
|
54
|
+
import { MonitoredItem, type MonitoredItemOptions, type QueueItem } from "./monitored_item";
|
|
47
55
|
import { Queue } from "./queue";
|
|
48
|
-
|
|
49
|
-
import { MonitoredItem, MonitoredItemOptions, QueueItem } from "./monitored_item";
|
|
50
|
-
import { ServerSession } from "./server_session";
|
|
56
|
+
import type { ServerSession } from "./server_session";
|
|
51
57
|
import { validateFilter } from "./validate_filter";
|
|
52
|
-
import { IServerSidePublishEngine, TransferredSubscription } from "./i_server_side_publish_engine";
|
|
53
58
|
|
|
54
59
|
const debugLog = make_debugLog(__filename);
|
|
55
60
|
const doDebug = checkDebugFlag(__filename);
|
|
@@ -138,11 +143,11 @@ function _adjust_maxNotificationsPerPublish(maxNotificationsPerPublish?: number)
|
|
|
138
143
|
}
|
|
139
144
|
|
|
140
145
|
function w(s: string | number, length: number): string {
|
|
141
|
-
return
|
|
146
|
+
return `000${s}`.padStart(length);
|
|
142
147
|
}
|
|
143
148
|
|
|
144
149
|
function t(d: Date): string {
|
|
145
|
-
return w(d.getHours(), 2)
|
|
150
|
+
return `${w(d.getHours(), 2)}:${w(d.getMinutes(), 2)}:${w(d.getSeconds(), 2)}:${w(d.getMilliseconds(), 3)}`;
|
|
146
151
|
}
|
|
147
152
|
|
|
148
153
|
function _getSequenceNumbers(arr: NotificationMessage[]): number[] {
|
|
@@ -166,18 +171,18 @@ function analyzeEventFilterResult(node: BaseNode, eventFilter: EventFilter): Eve
|
|
|
166
171
|
});
|
|
167
172
|
}
|
|
168
173
|
|
|
169
|
-
function analyzeDataChangeFilterResult(
|
|
174
|
+
function analyzeDataChangeFilterResult(_node: BaseNode, dataChangeFilter: DataChangeFilter): null {
|
|
170
175
|
assert(dataChangeFilter instanceof DataChangeFilter);
|
|
171
176
|
// the opcua specification doesn't provide dataChangeFilterResult
|
|
172
177
|
return null;
|
|
173
178
|
}
|
|
174
179
|
|
|
175
|
-
function analyzeAggregateFilterResult(
|
|
180
|
+
function analyzeAggregateFilterResult(_node: BaseNode, aggregateFilter: AggregateFilter): AggregateFilterResult {
|
|
176
181
|
assert(aggregateFilter instanceof AggregateFilter);
|
|
177
182
|
return new AggregateFilterResult({});
|
|
178
183
|
}
|
|
179
184
|
|
|
180
|
-
function _process_filter(node: BaseNode, filter:
|
|
185
|
+
function _process_filter(node: BaseNode, filter: MonitoringFilter | null): EventFilterResult | AggregateFilterResult | null {
|
|
181
186
|
if (!filter) {
|
|
182
187
|
return null;
|
|
183
188
|
}
|
|
@@ -201,99 +206,77 @@ function createSubscriptionDiagnostics(subscription: Subscription): Subscription
|
|
|
201
206
|
|
|
202
207
|
const subscriptionDiagnostics = new SubscriptionDiagnosticsDataType({});
|
|
203
208
|
|
|
204
|
-
const
|
|
205
|
-
|
|
209
|
+
const sd = subscriptionDiagnostics as SubscriptionDiagnosticsDataTypePriv;
|
|
210
|
+
sd.$subscription = subscription;
|
|
211
|
+
|
|
212
|
+
const defineGetter = <T>(name: string, getter: (this: SubscriptionDiagnosticsDataTypePriv) => T) => {
|
|
213
|
+
Object.defineProperty(sd, name, { get: getter, configurable: true });
|
|
214
|
+
};
|
|
215
|
+
|
|
206
216
|
// "sessionId"
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
if (!this.$subscription) {
|
|
211
|
-
return NodeId.nullNodeId;
|
|
212
|
-
}
|
|
213
|
-
return this.$subscription.getSessionId();
|
|
214
|
-
}
|
|
215
|
-
);
|
|
216
|
-
subscription_subscriptionDiagnostics.__defineGetter__(
|
|
217
|
-
"subscriptionId",
|
|
218
|
-
function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
219
|
-
if (!this.$subscription) {
|
|
220
|
-
return 0;
|
|
221
|
-
}
|
|
222
|
-
return this.$subscription.id;
|
|
217
|
+
defineGetter("sessionId", function (this: SubscriptionDiagnosticsDataTypePriv): NodeId {
|
|
218
|
+
if (!this.$subscription) {
|
|
219
|
+
return NodeId.nullNodeId;
|
|
223
220
|
}
|
|
224
|
-
|
|
225
|
-
|
|
221
|
+
return this.$subscription.getSessionId();
|
|
222
|
+
});
|
|
223
|
+
defineGetter("subscriptionId", function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
224
|
+
if (!this.$subscription) {
|
|
225
|
+
return 0;
|
|
226
|
+
}
|
|
227
|
+
return this.$subscription.id;
|
|
228
|
+
});
|
|
229
|
+
defineGetter("priority", function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
226
230
|
if (!this.$subscription) {
|
|
227
231
|
return 0;
|
|
228
232
|
}
|
|
229
233
|
return this.$subscription.priority;
|
|
230
234
|
});
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if (!this.$subscription) {
|
|
235
|
-
return 0;
|
|
236
|
-
}
|
|
237
|
-
return this.$subscription.publishingInterval;
|
|
235
|
+
defineGetter("publishingInterval", function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
236
|
+
if (!this.$subscription) {
|
|
237
|
+
return 0;
|
|
238
238
|
}
|
|
239
|
-
|
|
240
|
-
|
|
239
|
+
return this.$subscription.publishingInterval;
|
|
240
|
+
});
|
|
241
|
+
defineGetter("maxLifetimeCount", function (this: SubscriptionDiagnosticsDataTypePriv) {
|
|
241
242
|
return this.$subscription.lifeTimeCount;
|
|
242
243
|
});
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
);
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
subscription_subscriptionDiagnostics.__defineGetter__(
|
|
271
|
-
"monitoredItemCount",
|
|
272
|
-
function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
273
|
-
if (!this.$subscription) {
|
|
274
|
-
return 0;
|
|
275
|
-
}
|
|
276
|
-
return this.$subscription.monitoredItemCount;
|
|
277
|
-
}
|
|
278
|
-
);
|
|
279
|
-
subscription_subscriptionDiagnostics.__defineGetter__(
|
|
280
|
-
"nextSequenceNumber",
|
|
281
|
-
function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
282
|
-
if (!this.$subscription) {
|
|
283
|
-
return 0;
|
|
284
|
-
}
|
|
285
|
-
return this.$subscription.futureSequenceNumber;
|
|
286
|
-
}
|
|
287
|
-
);
|
|
288
|
-
subscription_subscriptionDiagnostics.__defineGetter__(
|
|
289
|
-
"disabledMonitoredItemCount",
|
|
290
|
-
function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
291
|
-
if (!this.$subscription) {
|
|
292
|
-
return 0;
|
|
293
|
-
}
|
|
294
|
-
return this.$subscription.disabledMonitoredItemCount;
|
|
244
|
+
defineGetter("maxKeepAliveCount", function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
245
|
+
if (!this.$subscription) {
|
|
246
|
+
return 0;
|
|
247
|
+
}
|
|
248
|
+
return this.$subscription.maxKeepAliveCount;
|
|
249
|
+
});
|
|
250
|
+
defineGetter("maxNotificationsPerPublish", function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
251
|
+
if (!this.$subscription) {
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
return this.$subscription.maxNotificationsPerPublish;
|
|
255
|
+
});
|
|
256
|
+
defineGetter("publishingEnabled", function (this: SubscriptionDiagnosticsDataTypePriv): boolean {
|
|
257
|
+
if (!this.$subscription) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
return this.$subscription.publishingEnabled;
|
|
261
|
+
});
|
|
262
|
+
defineGetter("monitoredItemCount", function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
263
|
+
if (!this.$subscription) {
|
|
264
|
+
return 0;
|
|
265
|
+
}
|
|
266
|
+
return this.$subscription.monitoredItemCount;
|
|
267
|
+
});
|
|
268
|
+
defineGetter("nextSequenceNumber", function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
269
|
+
if (!this.$subscription) {
|
|
270
|
+
return 0;
|
|
295
271
|
}
|
|
296
|
-
|
|
272
|
+
return this.$subscription.futureSequenceNumber;
|
|
273
|
+
});
|
|
274
|
+
defineGetter("disabledMonitoredItemCount", function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
275
|
+
if (!this.$subscription) {
|
|
276
|
+
return 0;
|
|
277
|
+
}
|
|
278
|
+
return this.$subscription.disabledMonitoredItemCount;
|
|
279
|
+
});
|
|
297
280
|
|
|
298
281
|
/* those member of self.subscriptionDiagnostics are handled directly
|
|
299
282
|
|
|
@@ -320,24 +303,18 @@ function createSubscriptionDiagnostics(subscription: Subscription): Subscription
|
|
|
320
303
|
"monitoringQueueOverflowCount",
|
|
321
304
|
"eventQueueOverflowCount"
|
|
322
305
|
*/
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if (!this.$subscription) {
|
|
327
|
-
return 0;
|
|
328
|
-
}
|
|
329
|
-
return this.$subscription.currentKeepAliveCount;
|
|
330
|
-
}
|
|
331
|
-
);
|
|
332
|
-
subscription_subscriptionDiagnostics.__defineGetter__(
|
|
333
|
-
"currentLifetimeCount",
|
|
334
|
-
function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
335
|
-
if (!this.$subscription) {
|
|
336
|
-
return 0;
|
|
337
|
-
}
|
|
338
|
-
return this.$subscription.currentLifetimeCount;
|
|
306
|
+
defineGetter("currentKeepAliveCount", function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
307
|
+
if (!this.$subscription) {
|
|
308
|
+
return 0;
|
|
339
309
|
}
|
|
340
|
-
|
|
310
|
+
return this.$subscription.currentKeepAliveCount;
|
|
311
|
+
});
|
|
312
|
+
defineGetter("currentLifetimeCount", function (this: SubscriptionDiagnosticsDataTypePriv): number {
|
|
313
|
+
if (!this.$subscription) {
|
|
314
|
+
return 0;
|
|
315
|
+
}
|
|
316
|
+
return this.$subscription.currentLifetimeCount;
|
|
317
|
+
});
|
|
341
318
|
// add object in Variable SubscriptionDiagnosticArray (i=2290) ( Array of SubscriptionDiagnostics)
|
|
342
319
|
// add properties in Variable to reflect
|
|
343
320
|
return subscriptionDiagnostics as SubscriptionDiagnosticsDataTypePriv;
|
|
@@ -597,7 +574,7 @@ export class Subscription extends EventEmitter {
|
|
|
597
574
|
private _sent_notification_messages: NotificationMessage[];
|
|
598
575
|
private readonly _sequence_number_generator: SequenceNumberGenerator;
|
|
599
576
|
private readonly monitoredItems: { [key: number]: MonitoredItem };
|
|
600
|
-
private timerId:
|
|
577
|
+
private timerId: ReturnType<typeof setTimeout> | null;
|
|
601
578
|
private _hasUncollectedMonitoredItemNotifications = false;
|
|
602
579
|
|
|
603
580
|
private globalCounter: IGlobalMonitoredItemCounter;
|
|
@@ -612,7 +589,7 @@ export class Subscription extends EventEmitter {
|
|
|
612
589
|
|
|
613
590
|
assert(this.sessionId instanceof NodeId, "expecting a sessionId NodeId");
|
|
614
591
|
|
|
615
|
-
this.publishEngine = options.publishEngine
|
|
592
|
+
this.publishEngine = options.publishEngine;
|
|
616
593
|
|
|
617
594
|
this.id = options.id || INVALID_ID;
|
|
618
595
|
|
|
@@ -676,14 +653,14 @@ export class Subscription extends EventEmitter {
|
|
|
676
653
|
|
|
677
654
|
public toString(): string {
|
|
678
655
|
let str = "Subscription:\n";
|
|
679
|
-
str +=
|
|
680
|
-
str +=
|
|
681
|
-
|
|
682
|
-
str +=
|
|
683
|
-
str +=
|
|
684
|
-
str +=
|
|
685
|
-
str +=
|
|
686
|
-
str +=
|
|
656
|
+
str += ` subscriptionId ${this.id}\n`;
|
|
657
|
+
str += ` sessionId ${this.getSessionId()?.toString()}\n`;
|
|
658
|
+
|
|
659
|
+
str += ` publishingEnabled ${this.publishingEnabled}\n`;
|
|
660
|
+
str += ` maxKeepAliveCount ${this.maxKeepAliveCount}\n`;
|
|
661
|
+
str += ` publishingInterval ${this.publishingInterval}\n`;
|
|
662
|
+
str += ` lifeTimeCount ${this.lifeTimeCount}\n`;
|
|
663
|
+
str += ` maxKeepAliveCount ${this.maxKeepAliveCount}\n`;
|
|
687
664
|
return str;
|
|
688
665
|
}
|
|
689
666
|
|
|
@@ -793,7 +770,6 @@ export class Subscription extends EventEmitter {
|
|
|
793
770
|
*
|
|
794
771
|
*/
|
|
795
772
|
public terminate(): void {
|
|
796
|
-
assert(arguments.length === 0);
|
|
797
773
|
debugLog("Subscription#terminate status", SubscriptionState[this.state]);
|
|
798
774
|
|
|
799
775
|
if (this.state === SubscriptionState.CLOSED) {
|
|
@@ -815,7 +791,7 @@ export class Subscription extends EventEmitter {
|
|
|
815
791
|
}
|
|
816
792
|
assert(this.monitoredItemCount === 0);
|
|
817
793
|
|
|
818
|
-
if (this.$session
|
|
794
|
+
if (this.$session?._unexposeSubscriptionDiagnostics) {
|
|
819
795
|
this.$session._unexposeSubscriptionDiagnostics(this);
|
|
820
796
|
}
|
|
821
797
|
this.state = SubscriptionState.CLOSED;
|
|
@@ -891,7 +867,7 @@ export class Subscription extends EventEmitter {
|
|
|
891
867
|
assert(this.timerId === null, "Subscription timer haven't been terminated");
|
|
892
868
|
|
|
893
869
|
if (this.subscriptionDiagnostics) {
|
|
894
|
-
(this.subscriptionDiagnostics as SubscriptionDiagnosticsDataTypePriv).$subscription = null as
|
|
870
|
+
(this.subscriptionDiagnostics as SubscriptionDiagnosticsDataTypePriv).$subscription = null as unknown as Subscription;
|
|
895
871
|
}
|
|
896
872
|
|
|
897
873
|
this.publishEngine = undefined;
|
|
@@ -1011,7 +987,7 @@ export class Subscription extends EventEmitter {
|
|
|
1011
987
|
}
|
|
1012
988
|
|
|
1013
989
|
const node_minimumSamplingInterval =
|
|
1014
|
-
node && (node as
|
|
990
|
+
node && (node as UAVariable).minimumSamplingInterval ? (node as UAVariable).minimumSamplingInterval : 0;
|
|
1015
991
|
|
|
1016
992
|
samplingInterval = Math.max(samplingInterval, node_minimumSamplingInterval);
|
|
1017
993
|
|
|
@@ -1041,7 +1017,10 @@ export class Subscription extends EventEmitter {
|
|
|
1041
1017
|
const itemToMonitor = monitoredItemCreateRequest.itemToMonitor;
|
|
1042
1018
|
|
|
1043
1019
|
const node = addressSpace.findNode(itemToMonitor.nodeId) as UAObject | UAVariable | UAMethod;
|
|
1044
|
-
if (
|
|
1020
|
+
if (
|
|
1021
|
+
!node ||
|
|
1022
|
+
(node.nodeClass !== NodeClass.Variable && node.nodeClass !== NodeClass.Object && node.nodeClass !== NodeClass.Method)
|
|
1023
|
+
) {
|
|
1045
1024
|
return handle_error(StatusCodes.BadNodeIdUnknown);
|
|
1046
1025
|
}
|
|
1047
1026
|
|
|
@@ -1114,7 +1093,7 @@ export class Subscription extends EventEmitter {
|
|
|
1114
1093
|
public postCreateMonitoredItem(
|
|
1115
1094
|
monitoredItem: MonitoredItem,
|
|
1116
1095
|
monitoredItemCreateRequest: MonitoredItemCreateRequest,
|
|
1117
|
-
|
|
1096
|
+
_createResult: MonitoredItemCreateResult
|
|
1118
1097
|
): void {
|
|
1119
1098
|
this._createMonitoredItemStep3(monitoredItem, monitoredItemCreateRequest);
|
|
1120
1099
|
}
|
|
@@ -1129,7 +1108,10 @@ export class Subscription extends EventEmitter {
|
|
|
1129
1108
|
timestampsToReturn,
|
|
1130
1109
|
monitoredItemCreateRequest
|
|
1131
1110
|
);
|
|
1132
|
-
|
|
1111
|
+
if (!monitoredItem) {
|
|
1112
|
+
return createResult;
|
|
1113
|
+
}
|
|
1114
|
+
this.postCreateMonitoredItem(monitoredItem, monitoredItemCreateRequest, createResult);
|
|
1133
1115
|
return createResult;
|
|
1134
1116
|
}
|
|
1135
1117
|
/**
|
|
@@ -1147,7 +1129,7 @@ export class Subscription extends EventEmitter {
|
|
|
1147
1129
|
*/
|
|
1148
1130
|
public removeMonitoredItem(monitoredItemId: number): StatusCode {
|
|
1149
1131
|
debugLog("Removing monitoredIem ", monitoredItemId);
|
|
1150
|
-
if (!Object.
|
|
1132
|
+
if (!Object.hasOwn(this.monitoredItems, monitoredItemId.toString())) {
|
|
1151
1133
|
return StatusCodes.BadMonitoredItemIdInvalid;
|
|
1152
1134
|
}
|
|
1153
1135
|
|
|
@@ -1207,8 +1189,8 @@ export class Subscription extends EventEmitter {
|
|
|
1207
1189
|
* @param notification
|
|
1208
1190
|
*/
|
|
1209
1191
|
public notificationHasExpired(notification: { start_tick: number }): boolean {
|
|
1210
|
-
assert(Object.
|
|
1211
|
-
assert(isFinite(notification.start_tick + this.maxKeepAliveCount));
|
|
1192
|
+
assert(Object.hasOwn(notification, "start_tick"));
|
|
1193
|
+
assert(Number.isFinite(notification.start_tick + this.maxKeepAliveCount));
|
|
1212
1194
|
return notification.start_tick + this.maxKeepAliveCount < this.publishIntervalCount;
|
|
1213
1195
|
}
|
|
1214
1196
|
|
|
@@ -1269,7 +1251,11 @@ export class Subscription extends EventEmitter {
|
|
|
1269
1251
|
for (let index = 0; index < monitoredItemCount; index++) {
|
|
1270
1252
|
const monitoredItemId = monitoredItems[index];
|
|
1271
1253
|
const serverHandle = parseInt(monitoredItemId, 10);
|
|
1272
|
-
const monitoredItem = this.getMonitoredItem(serverHandle)
|
|
1254
|
+
const monitoredItem = this.getMonitoredItem(serverHandle);
|
|
1255
|
+
// c8 ignore next
|
|
1256
|
+
if (!monitoredItem) {
|
|
1257
|
+
throw new Error("monitoredItem is null");
|
|
1258
|
+
}
|
|
1273
1259
|
result.clientHandles[index] = monitoredItem.clientHandle;
|
|
1274
1260
|
// TODO: serverHandle is defined anywhere in the OPCUA Specification 1.02
|
|
1275
1261
|
// I am not sure what shall be reported for serverHandle...
|
|
@@ -1298,7 +1284,7 @@ export class Subscription extends EventEmitter {
|
|
|
1298
1284
|
"resendInitialValues:",
|
|
1299
1285
|
monitoredItem.node?.nodeId.toString(),
|
|
1300
1286
|
"error:",
|
|
1301
|
-
(err as
|
|
1287
|
+
(err as Error).message
|
|
1302
1288
|
);
|
|
1303
1289
|
}
|
|
1304
1290
|
})()
|
|
@@ -1306,10 +1292,10 @@ export class Subscription extends EventEmitter {
|
|
|
1306
1292
|
}
|
|
1307
1293
|
await Promise.all(promises);
|
|
1308
1294
|
} catch (err) {
|
|
1309
|
-
warningLog("resendInitialValues: error:", (err as
|
|
1295
|
+
warningLog("resendInitialValues: error:", (err as Error).message);
|
|
1310
1296
|
}
|
|
1311
1297
|
// make sure data will be sent immediately
|
|
1312
|
-
this._keep_alive_counter = this.maxKeepAliveCount - 1
|
|
1298
|
+
this._keep_alive_counter = this.maxKeepAliveCount - 1;
|
|
1313
1299
|
this.state = SubscriptionState.NORMAL;
|
|
1314
1300
|
this._harvestMonitoredItems();
|
|
1315
1301
|
}
|
|
@@ -1328,13 +1314,18 @@ export class Subscription extends EventEmitter {
|
|
|
1328
1314
|
status: StatusCodes.GoodSubscriptionTransferred
|
|
1329
1315
|
});
|
|
1330
1316
|
|
|
1331
|
-
if (this.publishEngine
|
|
1317
|
+
if (this.publishEngine?.pendingPublishRequestCount) {
|
|
1332
1318
|
// the GoodSubscriptionTransferred can be processed immediately
|
|
1333
1319
|
this._addNotificationMessage(notificationData);
|
|
1334
1320
|
debugLog(chalk.red("pendingPublishRequestCount"), this.publishEngine?.pendingPublishRequestCount);
|
|
1335
1321
|
this._publish_pending_notifications();
|
|
1336
1322
|
} else {
|
|
1337
1323
|
debugLog(chalk.red("Cannot send GoodSubscriptionTransferred => lets create a TransferredSubscription "));
|
|
1324
|
+
// c8 ignore next
|
|
1325
|
+
if (!this.publishEngine) {
|
|
1326
|
+
warningLog("notifyTransfer: publishEngine is not available");
|
|
1327
|
+
return;
|
|
1328
|
+
}
|
|
1338
1329
|
const ts = new TransferredSubscription({
|
|
1339
1330
|
generator: this._sequence_number_generator,
|
|
1340
1331
|
id: this.id,
|
|
@@ -1342,7 +1333,7 @@ export class Subscription extends EventEmitter {
|
|
|
1342
1333
|
});
|
|
1343
1334
|
|
|
1344
1335
|
ts._pending_notification = notificationData;
|
|
1345
|
-
(this.publishEngine as
|
|
1336
|
+
(this.publishEngine as unknown as { _closed_subscriptions: TransferredSubscription[] })._closed_subscriptions.push(ts);
|
|
1346
1337
|
}
|
|
1347
1338
|
}
|
|
1348
1339
|
|
|
@@ -1363,11 +1354,11 @@ export class Subscription extends EventEmitter {
|
|
|
1363
1354
|
for (const notificationData of notificationMessage.notificationData || []) {
|
|
1364
1355
|
// update diagnostics
|
|
1365
1356
|
if (notificationData instanceof DataChangeNotification) {
|
|
1366
|
-
const nbNotifs = notificationData.monitoredItems
|
|
1357
|
+
const nbNotifs = notificationData.monitoredItems?.length || 0;
|
|
1367
1358
|
this.subscriptionDiagnostics.dataChangeNotificationsCount += nbNotifs;
|
|
1368
1359
|
this.subscriptionDiagnostics.notificationsCount += nbNotifs;
|
|
1369
1360
|
} else if (notificationData instanceof EventNotificationList) {
|
|
1370
|
-
const nbNotifs = notificationData.events
|
|
1361
|
+
const nbNotifs = notificationData.events?.length || 0;
|
|
1371
1362
|
this.subscriptionDiagnostics.eventNotificationsCount += nbNotifs;
|
|
1372
1363
|
this.subscriptionDiagnostics.notificationsCount += nbNotifs;
|
|
1373
1364
|
} else {
|
|
@@ -1381,19 +1372,23 @@ export class Subscription extends EventEmitter {
|
|
|
1381
1372
|
* _publish_pending_notifications send a "notification" event:
|
|
1382
1373
|
*
|
|
1383
1374
|
* @private
|
|
1384
|
-
*
|
|
1375
|
+
*
|
|
1385
1376
|
* precondition
|
|
1386
1377
|
* - pendingPublishRequestCount > 0
|
|
1387
1378
|
*/
|
|
1388
1379
|
public _publish_pending_notifications(): void {
|
|
1389
|
-
const publishEngine = this.publishEngine
|
|
1380
|
+
const publishEngine = this.publishEngine;
|
|
1381
|
+
// c8 ignore next
|
|
1382
|
+
if (!publishEngine) {
|
|
1383
|
+
throw new Error("publishEngine is null");
|
|
1384
|
+
}
|
|
1390
1385
|
const subscriptionId = this.id;
|
|
1391
1386
|
// preconditions
|
|
1392
|
-
assert(publishEngine
|
|
1387
|
+
assert(publishEngine.pendingPublishRequestCount > 0);
|
|
1393
1388
|
assert(this.hasPendingNotifications);
|
|
1394
1389
|
|
|
1395
1390
|
const notificationMessage = this._popNotificationToSend();
|
|
1396
|
-
if (notificationMessage.notificationData
|
|
1391
|
+
if (notificationMessage.notificationData?.length === 0) {
|
|
1397
1392
|
return; // nothing to do
|
|
1398
1393
|
}
|
|
1399
1394
|
const moreNotifications = this.hasPendingNotifications;
|
|
@@ -1402,8 +1397,8 @@ export class Subscription extends EventEmitter {
|
|
|
1402
1397
|
// Update counters ....
|
|
1403
1398
|
this._updateCounters(notificationMessage);
|
|
1404
1399
|
|
|
1405
|
-
assert(Object.
|
|
1406
|
-
assert(Object.
|
|
1400
|
+
assert(Object.hasOwn(notificationMessage, "sequenceNumber"));
|
|
1401
|
+
assert(Object.hasOwn(notificationMessage, "notificationData"));
|
|
1407
1402
|
// update diagnostics
|
|
1408
1403
|
this.subscriptionDiagnostics.publishRequestCount += 1;
|
|
1409
1404
|
|
|
@@ -1422,7 +1417,7 @@ export class Subscription extends EventEmitter {
|
|
|
1422
1417
|
const availableSequenceNumbers = this.getAvailableSequenceNumbers();
|
|
1423
1418
|
assert(
|
|
1424
1419
|
!response.notificationMessage ||
|
|
1425
|
-
|
|
1420
|
+
availableSequenceNumbers[availableSequenceNumbers.length - 1] === response.notificationMessage.sequenceNumber
|
|
1426
1421
|
);
|
|
1427
1422
|
response.availableSequenceNumbers = availableSequenceNumbers;
|
|
1428
1423
|
|
|
@@ -1447,14 +1442,14 @@ export class Subscription extends EventEmitter {
|
|
|
1447
1442
|
}
|
|
1448
1443
|
|
|
1449
1444
|
if (this.state !== SubscriptionState.CLOSED) {
|
|
1450
|
-
assert(notificationMessage.notificationData
|
|
1445
|
+
assert((notificationMessage.notificationData?.length || 0) > 0, "We are not expecting a keep-alive message here");
|
|
1451
1446
|
this.state = SubscriptionState.NORMAL;
|
|
1452
|
-
debugLog(
|
|
1447
|
+
debugLog(`subscription ${this.id}${chalk.bgYellow(" set to NORMAL")}`);
|
|
1453
1448
|
}
|
|
1454
1449
|
}
|
|
1455
1450
|
|
|
1456
1451
|
public process_subscription(): void {
|
|
1457
|
-
assert(this.publishEngine
|
|
1452
|
+
assert((this.publishEngine?.pendingPublishRequestCount || 0) > 0);
|
|
1458
1453
|
|
|
1459
1454
|
if (!this.publishingEnabled) {
|
|
1460
1455
|
// no publish to do, except keep alive
|
|
@@ -1499,7 +1494,7 @@ export class Subscription extends EventEmitter {
|
|
|
1499
1494
|
} else {
|
|
1500
1495
|
debugLog(
|
|
1501
1496
|
" -> subscription.state === LATE , " +
|
|
1502
|
-
|
|
1497
|
+
"because keepAlive Response cannot be send due to lack of PublishRequest"
|
|
1503
1498
|
);
|
|
1504
1499
|
if (this.messageSent || this.keepAliveCounterHasExpired) {
|
|
1505
1500
|
this.state = SubscriptionState.LATE;
|
|
@@ -1578,7 +1573,7 @@ export class Subscription extends EventEmitter {
|
|
|
1578
1573
|
// c8 ignore next
|
|
1579
1574
|
if (doDebug) {
|
|
1580
1575
|
debugLog(
|
|
1581
|
-
t(new Date())
|
|
1576
|
+
`${t(new Date())} ${this._life_time_counter}/${this.lifeTimeCount}${chalk.cyan(" Subscription#_tick")}`,
|
|
1582
1577
|
" processing subscriptionId=",
|
|
1583
1578
|
this.id,
|
|
1584
1579
|
"hasUncollectedMonitoredItemNotifications = ",
|
|
@@ -1589,7 +1584,7 @@ export class Subscription extends EventEmitter {
|
|
|
1589
1584
|
}
|
|
1590
1585
|
|
|
1591
1586
|
// give a chance to the publish engine to cancel timed out publish requests
|
|
1592
|
-
this.publishEngine
|
|
1587
|
+
this.publishEngine?._on_tick();
|
|
1593
1588
|
|
|
1594
1589
|
this.publishIntervalCount += 1;
|
|
1595
1590
|
|
|
@@ -1618,7 +1613,10 @@ export class Subscription extends EventEmitter {
|
|
|
1618
1613
|
return;
|
|
1619
1614
|
}
|
|
1620
1615
|
|
|
1621
|
-
const publishEngine = this.publishEngine
|
|
1616
|
+
const publishEngine = this.publishEngine;
|
|
1617
|
+
if (!publishEngine) {
|
|
1618
|
+
throw new Error("publishEngine is null");
|
|
1619
|
+
}
|
|
1622
1620
|
|
|
1623
1621
|
// c8 ignore next
|
|
1624
1622
|
doDebug && debugLog("Subscription#_tick self._pending_notifications= ", this._pending_notifications.size);
|
|
@@ -1664,7 +1662,7 @@ export class Subscription extends EventEmitter {
|
|
|
1664
1662
|
private _sendKeepAliveResponse(): boolean {
|
|
1665
1663
|
const future_sequence_number = this._get_future_sequence_number();
|
|
1666
1664
|
|
|
1667
|
-
if (this.publishEngine
|
|
1665
|
+
if (this.publishEngine?.send_keep_alive_response(this.id, future_sequence_number)) {
|
|
1668
1666
|
this.messageSent = true;
|
|
1669
1667
|
// c8 ignore next
|
|
1670
1668
|
doDebug &&
|
|
@@ -1771,18 +1769,18 @@ export class Subscription extends EventEmitter {
|
|
|
1771
1769
|
const m = this.maxNotificationsPerPublish;
|
|
1772
1770
|
while (i < m && this._pending_notifications.size > 0) {
|
|
1773
1771
|
if (hasEventFieldList || hasMonitoredItemNotification) {
|
|
1774
|
-
const notification1 = this._pending_notifications.first()
|
|
1772
|
+
const notification1 = this._pending_notifications.first()?.notification;
|
|
1775
1773
|
if (notification1 instanceof StatusChangeNotification) {
|
|
1776
1774
|
break;
|
|
1777
1775
|
}
|
|
1778
1776
|
}
|
|
1779
|
-
const notification = this._pending_notifications.shift()
|
|
1777
|
+
const notification = this._pending_notifications.shift()?.notification;
|
|
1780
1778
|
if (notification instanceof MonitoredItemNotification) {
|
|
1781
1779
|
assert(notification.clientHandle !== 4294967295);
|
|
1782
|
-
dataChangeNotifications.monitoredItems
|
|
1780
|
+
dataChangeNotifications.monitoredItems?.push(notification);
|
|
1783
1781
|
hasMonitoredItemNotification = 1;
|
|
1784
1782
|
} else if (notification instanceof EventFieldList) {
|
|
1785
|
-
eventNotificationList.events
|
|
1783
|
+
eventNotificationList.events?.push(notification);
|
|
1786
1784
|
hasEventFieldList = 1;
|
|
1787
1785
|
} else if (notification instanceof StatusChangeNotification) {
|
|
1788
1786
|
// to do
|
|
@@ -1792,14 +1790,14 @@ export class Subscription extends EventEmitter {
|
|
|
1792
1790
|
i += 1;
|
|
1793
1791
|
}
|
|
1794
1792
|
|
|
1795
|
-
if (dataChangeNotifications.monitoredItems
|
|
1796
|
-
notificationMessage.notificationData
|
|
1793
|
+
if (dataChangeNotifications.monitoredItems?.length) {
|
|
1794
|
+
notificationMessage.notificationData?.push(dataChangeNotifications);
|
|
1797
1795
|
}
|
|
1798
|
-
if (eventNotificationList.events
|
|
1799
|
-
notificationMessage.notificationData
|
|
1796
|
+
if (eventNotificationList.events?.length) {
|
|
1797
|
+
notificationMessage.notificationData?.push(eventNotificationList);
|
|
1800
1798
|
}
|
|
1801
1799
|
if (statusChangeNotification) {
|
|
1802
|
-
notificationMessage.notificationData
|
|
1800
|
+
notificationMessage.notificationData?.push(statusChangeNotification);
|
|
1803
1801
|
}
|
|
1804
1802
|
return notificationMessage;
|
|
1805
1803
|
}
|
|
@@ -1858,7 +1856,7 @@ export class Subscription extends EventEmitter {
|
|
|
1858
1856
|
requestedParameters.samplingInterval = this.adjustSamplingInterval(requestedParameters.samplingInterval, node);
|
|
1859
1857
|
|
|
1860
1858
|
// reincorporate monitoredItemId and itemToMonitor into the requestedParameters
|
|
1861
|
-
const options = requestedParameters as
|
|
1859
|
+
const options = requestedParameters as unknown as MonitoredItemOptions;
|
|
1862
1860
|
|
|
1863
1861
|
options.monitoredItemId = monitoredItemId;
|
|
1864
1862
|
options.itemToMonitor = itemToMonitor;
|