@openremote/core 1.8.0-snapshot.20250725120000 → 1.8.0-snapshot.20250725123024

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/lib/event.js CHANGED
@@ -1,588 +1 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import manager from "./index";
11
- import { arrayRemove, Deferred } from "./util";
12
- export var EventProviderStatus;
13
- (function (EventProviderStatus) {
14
- EventProviderStatus["DISCONNECTED"] = "DISCONNECTED";
15
- EventProviderStatus["CONNECTED"] = "CONNECTED";
16
- EventProviderStatus["CONNECTING"] = "CONNECTING";
17
- })(EventProviderStatus || (EventProviderStatus = {}));
18
- const SUBSCRIBE_MESSAGE_PREFIX = "SUBSCRIBE:";
19
- const SUBSCRIBED_MESSAGE_PREFIX = "SUBSCRIBED:";
20
- const UNSUBSCRIBE_MESSAGE_PREFIX = "UNSUBSCRIBE:";
21
- const UNAUTHORIZED_MESSAGE_PREFIX = "UNAUTHORIZED:";
22
- const TRIGGERED_MESSAGE_PREFIX = "TRIGGERED:";
23
- const EVENT_MESSAGE_PREFIX = "EVENT:";
24
- class EventProviderImpl {
25
- constructor() {
26
- this._disconnectRequested = false;
27
- this._reconnectDelayMillis = WebSocketEventProvider.MIN_RECONNECT_DELAY;
28
- this._reconnectTimer = null;
29
- this._status = EventProviderStatus.DISCONNECTED;
30
- this._connectingDeferred = null;
31
- this._statusCallbacks = [];
32
- this._pendingSubscription = null;
33
- this._queuedSubscriptions = [];
34
- this._subscriptionMap = new Map();
35
- this._assetEventCallbackMap = new Map();
36
- this._attributeEventCallbackMap = new Map();
37
- this._unloading = false;
38
- }
39
- get status() {
40
- return this._status;
41
- }
42
- subscribeStatusChange(callback) {
43
- this._statusCallbacks.push(callback);
44
- }
45
- unsubscribeStatusChange(callback) {
46
- arrayRemove(this._statusCallbacks, callback);
47
- }
48
- connect() {
49
- if (this._reconnectTimer) {
50
- window.clearTimeout(this._reconnectTimer);
51
- this._reconnectTimer = null;
52
- }
53
- if (this._status === EventProviderStatus.CONNECTED) {
54
- return Promise.resolve(true);
55
- }
56
- this._disconnectRequested = false;
57
- if (this._connectingDeferred) {
58
- return this._connectingDeferred.promise;
59
- }
60
- this._onStatusChanged(EventProviderStatus.CONNECTING);
61
- this._connectingDeferred = new Deferred();
62
- this._doConnect().then((connected) => {
63
- if (this._connectingDeferred) {
64
- const deferred = this._connectingDeferred;
65
- this._connectingDeferred = null;
66
- if (connected) {
67
- console.debug("Connected to event service: " + this.endpointUrl);
68
- this._reconnectDelayMillis = WebSocketEventProvider.MIN_RECONNECT_DELAY;
69
- this._onStatusChanged(EventProviderStatus.CONNECTED);
70
- window.setTimeout(() => {
71
- this._onConnect();
72
- }, 0);
73
- }
74
- else {
75
- console.debug("Failed to connect to event service: " + this.endpointUrl);
76
- this._scheduleReconnect();
77
- }
78
- deferred.resolve(connected);
79
- }
80
- });
81
- return this._connectingDeferred.promise;
82
- }
83
- disconnect() {
84
- console.debug("Disconnecting from event service: " + this.endpointUrl);
85
- if (this._disconnectRequested) {
86
- return;
87
- }
88
- this._disconnectRequested = true;
89
- if (this._reconnectTimer) {
90
- window.clearTimeout(this._reconnectTimer);
91
- this._reconnectTimer = null;
92
- }
93
- if (this.status === EventProviderStatus.DISCONNECTED) {
94
- return;
95
- }
96
- this._doDisconnect();
97
- }
98
- subscribe(eventSubscription, callback) {
99
- const subscriptionInfo = {
100
- eventSubscription: eventSubscription,
101
- callback: callback,
102
- deferred: new Deferred()
103
- };
104
- if (this._pendingSubscription != null || this._status !== EventProviderStatus.CONNECTED) {
105
- this._queuedSubscriptions.push(subscriptionInfo);
106
- return subscriptionInfo.deferred.promise;
107
- }
108
- this._pendingSubscription = subscriptionInfo;
109
- this._doSubscribe(eventSubscription).then(subscriptionId => {
110
- if (this._pendingSubscription) {
111
- const subscription = this._pendingSubscription;
112
- this._pendingSubscription = null;
113
- // Store subscriptionId and callback
114
- this._subscriptionMap.set(subscriptionId, subscription);
115
- this._processNextSubscription();
116
- const deferred = subscription.deferred;
117
- subscription.deferred = null;
118
- if (deferred) {
119
- deferred.resolve(subscriptionId);
120
- }
121
- }
122
- }, (reason) => {
123
- if (this._pendingSubscription) {
124
- const subscription = this._pendingSubscription;
125
- this._pendingSubscription = null;
126
- this._processNextSubscription();
127
- const deferred = subscription.deferred;
128
- subscription.deferred = null;
129
- if (deferred) {
130
- deferred.reject(reason);
131
- }
132
- }
133
- });
134
- return this._pendingSubscription.deferred.promise;
135
- }
136
- unsubscribe(subscriptionId) {
137
- return __awaiter(this, void 0, void 0, function* () {
138
- if (this._subscriptionMap.delete(subscriptionId)) {
139
- this._doUnsubscribe(subscriptionId);
140
- return;
141
- }
142
- if (this._assetEventCallbackMap.delete(subscriptionId)) {
143
- if (this._assetEventPromise && this._assetEventCallbackMap.size === 0) {
144
- // Remove the asset subscription
145
- const assetEventSubscriptionId = yield this._assetEventPromise;
146
- this._assetEventPromise = undefined;
147
- this.unsubscribe(assetEventSubscriptionId);
148
- }
149
- return;
150
- }
151
- if (this._attributeEventCallbackMap.delete(subscriptionId)) {
152
- if (this._attributeEventPromise && this._attributeEventCallbackMap.size === 0) {
153
- // Remove the attribute subscription
154
- const attributeEventSubscriptionId = yield this._attributeEventPromise;
155
- this._attributeEventPromise = undefined;
156
- this.unsubscribe(attributeEventSubscriptionId);
157
- }
158
- return;
159
- }
160
- });
161
- }
162
- sendEvent(event) {
163
- if (this._status === EventProviderStatus.CONNECTED) {
164
- this._doSend(event);
165
- }
166
- }
167
- sendEventWithReply(event) {
168
- if (this._status !== EventProviderStatus.CONNECTED) {
169
- return Promise.reject("Not connected");
170
- }
171
- return this._doSendWithReply(event);
172
- }
173
- subscribeAssetEvents(ids, requestCurrentValues, callback) {
174
- return __awaiter(this, void 0, void 0, function* () {
175
- const isAttributeRef = ids && typeof ids[0] !== "string";
176
- const assetIds = isAttributeRef ? ids.map((ref) => ref.id) : ids;
177
- const subscriptionId = "AssetEvent" + EventProviderImpl._subscriptionCounter++;
178
- // If not already done then create a single global subscription for asset events and filter for each callback
179
- if (!this._assetEventPromise) {
180
- let assetFilter;
181
- if (!manager.authenticated) {
182
- // Need to set the filter realm when anonymous
183
- assetFilter = {
184
- filterType: "asset",
185
- realm: manager.displayRealm
186
- };
187
- }
188
- const subscription = {
189
- eventType: "asset",
190
- filter: assetFilter
191
- };
192
- // if (assetIds) {
193
- // subscription.filter = {
194
- // filterType: "asset",
195
- // assetIds: assetIds
196
- // };
197
- // }
198
- this._assetEventPromise = this.subscribe(subscription, (event) => {
199
- this._assetEventCallbackMap.forEach((callback) => callback(event));
200
- });
201
- }
202
- const eventFilter = (e) => {
203
- const assetId = e.asset.id;
204
- if (assetIds) {
205
- if (assetIds.find((id => assetId === id))) {
206
- callback(e);
207
- }
208
- }
209
- else {
210
- const realm = e.asset.realm;
211
- if (realm === manager.displayRealm) {
212
- callback(e);
213
- }
214
- }
215
- };
216
- this._assetEventCallbackMap.set(subscriptionId, eventFilter);
217
- return this._assetEventPromise.then(() => {
218
- try {
219
- // Get the current state of the assets if requested
220
- if (assetIds && requestCurrentValues) {
221
- const readRequest = {
222
- messageID: "read-assets:" + assetIds.join(",") + ":" + subscriptionId,
223
- eventType: "read-assets",
224
- assetQuery: {
225
- ids: assetIds
226
- }
227
- };
228
- this.sendEventWithReply(readRequest)
229
- .then((e) => {
230
- const assetsEvent = e;
231
- // Check subscription still exists
232
- if (!assetsEvent.assets || !this._assetEventCallbackMap.has(subscriptionId)) {
233
- return;
234
- }
235
- assetsEvent.assets.forEach((asset) => {
236
- const assetEvent = {
237
- eventType: "asset",
238
- asset: asset,
239
- cause: "READ" /* AssetEventCause.READ */
240
- };
241
- callback(assetEvent);
242
- });
243
- });
244
- }
245
- }
246
- catch (e) {
247
- console.error("Failed to subscribe to asset events for assets: " + ids);
248
- if (subscriptionId) {
249
- this.unsubscribe(subscriptionId);
250
- }
251
- throw e;
252
- }
253
- return subscriptionId;
254
- });
255
- });
256
- }
257
- subscribeAttributeEvents(ids, requestCurrentValues, callback) {
258
- return __awaiter(this, void 0, void 0, function* () {
259
- const isAttributeRef = ids && typeof ids[0] !== "string";
260
- const assetIds = isAttributeRef ? ids.map((ref) => ref.id) : ids;
261
- const attributes = isAttributeRef ? ids : undefined;
262
- const subscriptionId = "AttributeEvent" + EventProviderImpl._subscriptionCounter++;
263
- // If not already done then create a single global subscription for attribute events and filter for each callback
264
- if (!this._attributeEventPromise) {
265
- let assetFilter;
266
- if (!manager.authenticated) {
267
- // Need to set the filter realm when anonymous
268
- assetFilter = {
269
- filterType: "asset",
270
- realm: manager.displayRealm
271
- };
272
- }
273
- const subscription = {
274
- eventType: "attribute",
275
- filter: assetFilter
276
- };
277
- this._attributeEventPromise = this.subscribe(subscription, (event) => {
278
- this._attributeEventCallbackMap.forEach((callback) => callback(event));
279
- });
280
- }
281
- // Build a filter to only respond to the callback for the requested attributes
282
- const eventFilter = (e) => {
283
- const eventRef = e.ref;
284
- if (isAttributeRef) {
285
- ids.forEach((ref) => {
286
- if (eventRef.id === ref.id && eventRef.name === ref.name) {
287
- callback(e);
288
- }
289
- });
290
- }
291
- else if (assetIds) {
292
- if (assetIds.find((id => eventRef.id === id))) {
293
- callback(e);
294
- }
295
- }
296
- else {
297
- const realm = e.realm;
298
- if (realm === manager.displayRealm) {
299
- callback(e);
300
- }
301
- }
302
- };
303
- this._attributeEventCallbackMap.set(subscriptionId, eventFilter);
304
- return this._attributeEventPromise.then(() => {
305
- try {
306
- // Get the current state of the attributes if requested
307
- if (requestCurrentValues && assetIds) {
308
- // Just request the whole asset(s) and let the event filter do the work
309
- const readRequest = {
310
- messageID: "read-assets:" + assetIds.join(",") + ":" + subscriptionId,
311
- eventType: "read-assets",
312
- assetQuery: {
313
- ids: assetIds
314
- }
315
- };
316
- this.sendEventWithReply(readRequest)
317
- .then((e) => {
318
- const assetsEvent = e;
319
- // Check subscription still exists
320
- if (!assetsEvent.assets || !this._attributeEventCallbackMap.has(subscriptionId)) {
321
- return;
322
- }
323
- assetsEvent.assets.forEach((asset) => {
324
- if (asset.attributes) {
325
- Object.entries(asset.attributes).forEach(([attributeName, attr]) => {
326
- if (!attributes || attributes.find((ref) => ref.id === asset.id && ref.name === attributeName)) {
327
- eventFilter({
328
- eventType: "attribute",
329
- timestamp: attr.timestamp,
330
- value: attr.value,
331
- ref: {
332
- id: asset.id,
333
- name: attributeName
334
- }
335
- });
336
- }
337
- });
338
- }
339
- });
340
- });
341
- }
342
- }
343
- catch (e) {
344
- console.error("Failed to subscribe to asset events for assets: " + ids);
345
- if (subscriptionId) {
346
- this.unsubscribe(subscriptionId);
347
- }
348
- throw e;
349
- }
350
- return subscriptionId;
351
- });
352
- });
353
- }
354
- _processNextSubscription() {
355
- if (this._status !== EventProviderStatus.CONNECTED || this._queuedSubscriptions.length === 0) {
356
- return;
357
- }
358
- setTimeout(() => {
359
- const subscriptionInfo = this._queuedSubscriptions.shift();
360
- if (subscriptionInfo) {
361
- this.subscribe(subscriptionInfo.eventSubscription, subscriptionInfo.callback)
362
- .then((id) => {
363
- const deferred = subscriptionInfo.deferred;
364
- subscriptionInfo.deferred = null;
365
- if (deferred) {
366
- deferred.resolve(id);
367
- }
368
- }, reason => {
369
- const deferred = subscriptionInfo.deferred;
370
- subscriptionInfo.deferred = null;
371
- if (deferred) {
372
- deferred.reject(reason);
373
- }
374
- });
375
- }
376
- }, 0);
377
- }
378
- _onStatusChanged(status) {
379
- if (status === this._status) {
380
- return;
381
- }
382
- console.debug("Event provider status changed: " + status);
383
- this._status = status;
384
- if (!this._unloading) {
385
- window.setTimeout(() => {
386
- this._statusCallbacks.forEach((cb) => cb(status));
387
- }, 0);
388
- }
389
- }
390
- _onMessageReceived(subscriptionId, event) {
391
- const subscriptionInfo = this._subscriptionMap.get(subscriptionId);
392
- if (subscriptionInfo) {
393
- subscriptionInfo.callback(event);
394
- }
395
- }
396
- _onConnect() {
397
- if (Object.keys(this._subscriptionMap).length > 0) {
398
- for (const subscriptionId in this._subscriptionMap) {
399
- if (this._subscriptionMap.has(subscriptionId)) {
400
- this._queuedSubscriptions.unshift(this._subscriptionMap.get(subscriptionId));
401
- }
402
- }
403
- this._subscriptionMap.clear();
404
- }
405
- this._processNextSubscription();
406
- }
407
- _onDisconnect() {
408
- if (this._status === EventProviderStatus.CONNECTED) {
409
- this._onStatusChanged(EventProviderStatus.DISCONNECTED);
410
- }
411
- if (this._pendingSubscription) {
412
- this._queuedSubscriptions.unshift(this._pendingSubscription);
413
- this._pendingSubscription = null;
414
- }
415
- this._onStatusChanged(EventProviderStatus.CONNECTING);
416
- this._scheduleReconnect();
417
- }
418
- _scheduleReconnect() {
419
- if (this._reconnectTimer) {
420
- return;
421
- }
422
- if (this._disconnectRequested) {
423
- return;
424
- }
425
- console.debug("Event provider scheduling reconnect in " + this._reconnectDelayMillis + "ms");
426
- this._reconnectTimer = window.setTimeout(() => {
427
- if (this._disconnectRequested) {
428
- return;
429
- }
430
- this.connect();
431
- }, this._reconnectDelayMillis);
432
- if (this._reconnectDelayMillis < WebSocketEventProvider.MAX_RECONNECT_DELAY) {
433
- this._reconnectDelayMillis = Math.min(WebSocketEventProvider.MAX_RECONNECT_DELAY, this._reconnectDelayMillis + 3000);
434
- }
435
- }
436
- }
437
- EventProviderImpl.MIN_RECONNECT_DELAY = 0;
438
- EventProviderImpl.MAX_RECONNECT_DELAY = 30000;
439
- EventProviderImpl._subscriptionCounter = 0;
440
- export class WebSocketEventProvider extends EventProviderImpl {
441
- get endpointUrl() {
442
- return this._endpointUrl;
443
- }
444
- constructor(managerUrl) {
445
- super();
446
- this._webSocket = undefined;
447
- this._connectDeferred = null;
448
- this._subscribeDeferred = null;
449
- this._repliesDeferred = new Map();
450
- this._endpointUrl = (managerUrl.startsWith("https:") ? "wss" : "ws") + "://" + managerUrl.substr(managerUrl.indexOf("://") + 3) + "/websocket/events";
451
- // Close socket on unload/refresh of page
452
- window.addEventListener("beforeunload", () => {
453
- this._unloading = true;
454
- this.disconnect();
455
- });
456
- }
457
- _doConnect() {
458
- let authorisedUrl = this._endpointUrl + "?Realm=" + manager.config.realm;
459
- if (manager.authenticated) {
460
- authorisedUrl += "&Authorization=" + manager.getAuthorizationHeader();
461
- }
462
- this._webSocket = new WebSocket(authorisedUrl);
463
- this._connectDeferred = new Deferred();
464
- this._webSocket.onopen = () => {
465
- if (this._connectDeferred) {
466
- const deferred = this._connectDeferred;
467
- this._connectDeferred = null;
468
- deferred.resolve(true);
469
- }
470
- };
471
- this._webSocket.onerror = (err) => {
472
- if (this._connectDeferred) {
473
- const deferred = this._connectDeferred;
474
- this._connectDeferred = null;
475
- deferred.resolve(false);
476
- }
477
- else {
478
- console.debug("Event provider error");
479
- // Could have inconsistent state so disconnect and let consumers decide what to do and when to reconnect
480
- this._beforeDisconnect();
481
- }
482
- };
483
- this._webSocket.onclose = () => {
484
- this._webSocket = undefined;
485
- if (this._connectDeferred) {
486
- const deferred = this._connectDeferred;
487
- this._connectDeferred = null;
488
- deferred.resolve(false);
489
- }
490
- else {
491
- this._beforeDisconnect();
492
- }
493
- };
494
- this._webSocket.onmessage = (e) => {
495
- const msg = e.data;
496
- if (msg && msg.startsWith(SUBSCRIBED_MESSAGE_PREFIX)) {
497
- const jsonStr = msg.substring(SUBSCRIBED_MESSAGE_PREFIX.length);
498
- const subscription = JSON.parse(jsonStr);
499
- const deferred = this._subscribeDeferred;
500
- this._subscribeDeferred = null;
501
- if (deferred) {
502
- deferred.resolve(subscription.subscriptionId);
503
- }
504
- }
505
- else if (msg.startsWith(UNAUTHORIZED_MESSAGE_PREFIX)) {
506
- const jsonStr = msg.substring(UNAUTHORIZED_MESSAGE_PREFIX.length);
507
- const subscription = JSON.parse(jsonStr);
508
- const deferred = this._subscribeDeferred;
509
- this._subscribeDeferred = null;
510
- if (deferred) {
511
- console.warn("Unauthorized event subscription: " + JSON.stringify(subscription, null, 2));
512
- deferred.reject("Unauthorized");
513
- }
514
- }
515
- else if (msg.startsWith(TRIGGERED_MESSAGE_PREFIX)) {
516
- const str = msg.substring(TRIGGERED_MESSAGE_PREFIX.length);
517
- const triggered = JSON.parse(str);
518
- if (triggered.events) {
519
- triggered.events.forEach((event) => {
520
- this._onMessageReceived(triggered.subscriptionId, event);
521
- });
522
- }
523
- }
524
- else if (msg.startsWith(EVENT_MESSAGE_PREFIX)) {
525
- const str = msg.substring(EVENT_MESSAGE_PREFIX.length);
526
- const event = JSON.parse(str);
527
- if (event.messageID) {
528
- const deferred = this._repliesDeferred.get(event.messageID);
529
- this._repliesDeferred.delete(event.messageID);
530
- if (deferred) {
531
- deferred.resolve(event);
532
- }
533
- }
534
- }
535
- };
536
- return this._connectDeferred.promise;
537
- }
538
- _beforeDisconnect() {
539
- this._onDisconnect();
540
- }
541
- _doDisconnect() {
542
- var _a;
543
- (_a = this._webSocket) === null || _a === void 0 ? void 0 : _a.close();
544
- this._subscribeDeferred = null;
545
- this._repliesDeferred.clear();
546
- }
547
- _doSubscribe(subscription) {
548
- if (!this._webSocket) {
549
- return Promise.reject("Not connected");
550
- }
551
- if (this._subscribeDeferred) {
552
- return Promise.reject("There's already a pending subscription");
553
- }
554
- this._subscribeDeferred = new Deferred();
555
- if (!subscription.subscriptionId) {
556
- subscription.subscriptionId = WebSocketEventProvider._subscriptionCounter++ + "";
557
- }
558
- this._webSocket.send(SUBSCRIBE_MESSAGE_PREFIX + JSON.stringify(subscription));
559
- return this._subscribeDeferred.promise;
560
- }
561
- _doUnsubscribe(subscriptionId) {
562
- if (!this._webSocket) {
563
- return;
564
- }
565
- const cancelSubscription = {
566
- subscriptionId: subscriptionId
567
- };
568
- this._webSocket.send(UNSUBSCRIBE_MESSAGE_PREFIX + JSON.stringify(cancelSubscription));
569
- }
570
- _doSend(event) {
571
- const message = EVENT_MESSAGE_PREFIX + JSON.stringify(event);
572
- this._webSocket.send(message);
573
- }
574
- _doSendWithReply(event) {
575
- if (!event.messageID) {
576
- event.messageID = (new Date().getTime() + (Math.random() * 10)).toString(10);
577
- }
578
- if (this._repliesDeferred.has(event.messageID)) {
579
- return Promise.reject("There's already a pending send and reply with this ID");
580
- }
581
- const deferred = new Deferred();
582
- this._repliesDeferred.set(event.messageID, deferred);
583
- this._webSocket.send(EVENT_MESSAGE_PREFIX + JSON.stringify(event));
584
- return deferred.promise;
585
- }
586
- }
587
- WebSocketEventProvider._subscriptionCounter = 1;
588
- //# sourceMappingURL=event.js.map
1
+ var __awaiter=this&&this.__awaiter||function(e,t,s,i){return new(s||(s=Promise))(function(n,r){function o(e){try{a(i.next(e))}catch(e){r(e)}}function c(e){try{a(i.throw(e))}catch(e){r(e)}}function a(e){var t;e.done?n(e.value):((t=e.value)instanceof s?t:new s(function(e){e(t)})).then(o,c)}a((i=i.apply(e,t||[])).next())})};import e from"./index";import{arrayRemove as t,Deferred as s}from"./util";export var EventProviderStatus;!function(e){e.DISCONNECTED="DISCONNECTED",e.CONNECTED="CONNECTED",e.CONNECTING="CONNECTING"}(EventProviderStatus||(EventProviderStatus={}));let SUBSCRIBE_MESSAGE_PREFIX="SUBSCRIBE:",SUBSCRIBED_MESSAGE_PREFIX="SUBSCRIBED:",UNSUBSCRIBE_MESSAGE_PREFIX="UNSUBSCRIBE:",UNAUTHORIZED_MESSAGE_PREFIX="UNAUTHORIZED:",TRIGGERED_MESSAGE_PREFIX="TRIGGERED:",EVENT_MESSAGE_PREFIX="EVENT:";class EventProviderImpl{constructor(){this._disconnectRequested=!1,this._reconnectDelayMillis=WebSocketEventProvider.MIN_RECONNECT_DELAY,this._reconnectTimer=null,this._status=EventProviderStatus.DISCONNECTED,this._connectingDeferred=null,this._statusCallbacks=[],this._pendingSubscription=null,this._queuedSubscriptions=[],this._subscriptionMap=new Map,this._assetEventCallbackMap=new Map,this._attributeEventCallbackMap=new Map,this._unloading=!1}get status(){return this._status}subscribeStatusChange(e){this._statusCallbacks.push(e)}unsubscribeStatusChange(e){t(this._statusCallbacks,e)}connect(){return(this._reconnectTimer&&(window.clearTimeout(this._reconnectTimer),this._reconnectTimer=null),this._status===EventProviderStatus.CONNECTED)?Promise.resolve(!0):(this._disconnectRequested=!1,this._connectingDeferred||(this._onStatusChanged(EventProviderStatus.CONNECTING),this._connectingDeferred=new s,this._doConnect().then(e=>{if(this._connectingDeferred){let t=this._connectingDeferred;this._connectingDeferred=null,e?(console.debug("Connected to event service: "+this.endpointUrl),this._reconnectDelayMillis=WebSocketEventProvider.MIN_RECONNECT_DELAY,this._onStatusChanged(EventProviderStatus.CONNECTED),window.setTimeout(()=>{this._onConnect()},0)):(console.debug("Failed to connect to event service: "+this.endpointUrl),this._scheduleReconnect()),t.resolve(e)}})),this._connectingDeferred.promise)}disconnect(){console.debug("Disconnecting from event service: "+this.endpointUrl),this._disconnectRequested||(this._disconnectRequested=!0,this._reconnectTimer&&(window.clearTimeout(this._reconnectTimer),this._reconnectTimer=null),this.status!==EventProviderStatus.DISCONNECTED&&this._doDisconnect())}subscribe(e,t){let i={eventSubscription:e,callback:t,deferred:new s};return null!=this._pendingSubscription||this._status!==EventProviderStatus.CONNECTED?(this._queuedSubscriptions.push(i),i.deferred.promise):(this._pendingSubscription=i,this._doSubscribe(e).then(e=>{if(this._pendingSubscription){let t=this._pendingSubscription;this._pendingSubscription=null,this._subscriptionMap.set(e,t),this._processNextSubscription();let s=t.deferred;t.deferred=null,s&&s.resolve(e)}},e=>{if(this._pendingSubscription){let t=this._pendingSubscription;this._pendingSubscription=null,this._processNextSubscription();let s=t.deferred;t.deferred=null,s&&s.reject(e)}}),this._pendingSubscription.deferred.promise)}unsubscribe(e){return __awaiter(this,void 0,void 0,function*(){if(this._subscriptionMap.delete(e))return void this._doUnsubscribe(e);if(this._assetEventCallbackMap.delete(e)){if(this._assetEventPromise&&0===this._assetEventCallbackMap.size){let e=yield this._assetEventPromise;this._assetEventPromise=void 0,this.unsubscribe(e)}return}if(this._attributeEventCallbackMap.delete(e)){if(this._attributeEventPromise&&0===this._attributeEventCallbackMap.size){let e=yield this._attributeEventPromise;this._attributeEventPromise=void 0,this.unsubscribe(e)}return}})}sendEvent(e){this._status===EventProviderStatus.CONNECTED&&this._doSend(e)}sendEventWithReply(e){return this._status!==EventProviderStatus.CONNECTED?Promise.reject("Not connected"):this._doSendWithReply(e)}subscribeAssetEvents(t,s,i){return __awaiter(this,void 0,void 0,function*(){let n=t&&"string"!=typeof t[0]?t.map(e=>e.id):t,r="AssetEvent"+EventProviderImpl._subscriptionCounter++;if(!this._assetEventPromise){let t;e.authenticated||(t={filterType:"asset",realm:e.displayRealm});let s={eventType:"asset",filter:t};this._assetEventPromise=this.subscribe(s,e=>{this._assetEventCallbackMap.forEach(t=>t(e))})}return this._assetEventCallbackMap.set(r,t=>{let s=t.asset.id;n?n.find(e=>s===e)&&i(t):t.asset.realm===e.displayRealm&&i(t)}),this._assetEventPromise.then(()=>{try{if(n&&s){let e={messageID:"read-assets:"+n.join(",")+":"+r,eventType:"read-assets",assetQuery:{ids:n}};this.sendEventWithReply(e).then(e=>{e.assets&&this._assetEventCallbackMap.has(r)&&e.assets.forEach(e=>{i({eventType:"asset",asset:e,cause:"READ"})})})}}catch(e){throw console.error("Failed to subscribe to asset events for assets: "+t),r&&this.unsubscribe(r),e}return r})})}subscribeAttributeEvents(t,s,i){return __awaiter(this,void 0,void 0,function*(){let n=t&&"string"!=typeof t[0],r=n?t.map(e=>e.id):t,o=n?t:void 0,c="AttributeEvent"+EventProviderImpl._subscriptionCounter++;if(!this._attributeEventPromise){let t;e.authenticated||(t={filterType:"asset",realm:e.displayRealm});let s={eventType:"attribute",filter:t};this._attributeEventPromise=this.subscribe(s,e=>{this._attributeEventCallbackMap.forEach(t=>t(e))})}let a=s=>{let o=s.ref;n?t.forEach(e=>{o.id===e.id&&o.name===e.name&&i(s)}):r?r.find(e=>o.id===e)&&i(s):s.realm===e.displayRealm&&i(s)};return this._attributeEventCallbackMap.set(c,a),this._attributeEventPromise.then(()=>{try{if(s&&r){let e={messageID:"read-assets:"+r.join(",")+":"+c,eventType:"read-assets",assetQuery:{ids:r}};this.sendEventWithReply(e).then(e=>{e.assets&&this._attributeEventCallbackMap.has(c)&&e.assets.forEach(e=>{e.attributes&&Object.entries(e.attributes).forEach(([t,s])=>{(!o||o.find(s=>s.id===e.id&&s.name===t))&&a({eventType:"attribute",timestamp:s.timestamp,value:s.value,ref:{id:e.id,name:t}})})})})}}catch(e){throw console.error("Failed to subscribe to asset events for assets: "+t),c&&this.unsubscribe(c),e}return c})})}_processNextSubscription(){this._status===EventProviderStatus.CONNECTED&&0!==this._queuedSubscriptions.length&&setTimeout(()=>{let e=this._queuedSubscriptions.shift();e&&this.subscribe(e.eventSubscription,e.callback).then(t=>{let s=e.deferred;e.deferred=null,s&&s.resolve(t)},t=>{let s=e.deferred;e.deferred=null,s&&s.reject(t)})},0)}_onStatusChanged(e){e!==this._status&&(console.debug("Event provider status changed: "+e),this._status=e,this._unloading||window.setTimeout(()=>{this._statusCallbacks.forEach(t=>t(e))},0))}_onMessageReceived(e,t){let s=this._subscriptionMap.get(e);s&&s.callback(t)}_onConnect(){if(Object.keys(this._subscriptionMap).length>0){for(let e in this._subscriptionMap)this._subscriptionMap.has(e)&&this._queuedSubscriptions.unshift(this._subscriptionMap.get(e));this._subscriptionMap.clear()}this._processNextSubscription()}_onDisconnect(){this._status===EventProviderStatus.CONNECTED&&this._onStatusChanged(EventProviderStatus.DISCONNECTED),this._pendingSubscription&&(this._queuedSubscriptions.unshift(this._pendingSubscription),this._pendingSubscription=null),this._onStatusChanged(EventProviderStatus.CONNECTING),this._scheduleReconnect()}_scheduleReconnect(){this._reconnectTimer||!this._disconnectRequested&&(console.debug("Event provider scheduling reconnect in "+this._reconnectDelayMillis+"ms"),this._reconnectTimer=window.setTimeout(()=>{this._disconnectRequested||this.connect()},this._reconnectDelayMillis),this._reconnectDelayMillis<WebSocketEventProvider.MAX_RECONNECT_DELAY&&(this._reconnectDelayMillis=Math.min(WebSocketEventProvider.MAX_RECONNECT_DELAY,this._reconnectDelayMillis+3e3)))}}EventProviderImpl.MIN_RECONNECT_DELAY=0,EventProviderImpl.MAX_RECONNECT_DELAY=3e4,EventProviderImpl._subscriptionCounter=0;export class WebSocketEventProvider extends EventProviderImpl{get endpointUrl(){return this._endpointUrl}constructor(e){super(),this._webSocket=void 0,this._connectDeferred=null,this._subscribeDeferred=null,this._repliesDeferred=new Map,this._endpointUrl=(e.startsWith("https:")?"wss":"ws")+"://"+e.substr(e.indexOf("://")+3)+"/websocket/events",window.addEventListener("beforeunload",()=>{this._unloading=!0,this.disconnect()})}_doConnect(){let t=this._endpointUrl+"?Realm="+e.config.realm;return e.authenticated&&(t+="&Authorization="+e.getAuthorizationHeader()),this._webSocket=new WebSocket(t),this._connectDeferred=new s,this._webSocket.onopen=()=>{if(this._connectDeferred){let e=this._connectDeferred;this._connectDeferred=null,e.resolve(!0)}},this._webSocket.onerror=e=>{if(this._connectDeferred){let e=this._connectDeferred;this._connectDeferred=null,e.resolve(!1)}else console.debug("Event provider error"),this._beforeDisconnect()},this._webSocket.onclose=()=>{if(this._webSocket=void 0,this._connectDeferred){let e=this._connectDeferred;this._connectDeferred=null,e.resolve(!1)}else this._beforeDisconnect()},this._webSocket.onmessage=e=>{let t=e.data;if(t&&t.startsWith(SUBSCRIBED_MESSAGE_PREFIX)){let e=JSON.parse(t.substring(SUBSCRIBED_MESSAGE_PREFIX.length)),s=this._subscribeDeferred;this._subscribeDeferred=null,s&&s.resolve(e.subscriptionId)}else if(t.startsWith(UNAUTHORIZED_MESSAGE_PREFIX)){let e=JSON.parse(t.substring(UNAUTHORIZED_MESSAGE_PREFIX.length)),s=this._subscribeDeferred;this._subscribeDeferred=null,s&&(console.warn("Unauthorized event subscription: "+JSON.stringify(e,null,2)),s.reject("Unauthorized"))}else if(t.startsWith(TRIGGERED_MESSAGE_PREFIX)){let e=JSON.parse(t.substring(TRIGGERED_MESSAGE_PREFIX.length));e.events&&e.events.forEach(t=>{this._onMessageReceived(e.subscriptionId,t)})}else if(t.startsWith(EVENT_MESSAGE_PREFIX)){let e=JSON.parse(t.substring(EVENT_MESSAGE_PREFIX.length));if(e.messageID){let t=this._repliesDeferred.get(e.messageID);this._repliesDeferred.delete(e.messageID),t&&t.resolve(e)}}},this._connectDeferred.promise}_beforeDisconnect(){this._onDisconnect()}_doDisconnect(){var e;null==(e=this._webSocket)||e.close(),this._subscribeDeferred=null,this._repliesDeferred.clear()}_doSubscribe(e){return this._webSocket?this._subscribeDeferred?Promise.reject("There's already a pending subscription"):(this._subscribeDeferred=new s,e.subscriptionId||(e.subscriptionId=WebSocketEventProvider._subscriptionCounter+++""),this._webSocket.send("SUBSCRIBE:"+JSON.stringify(e)),this._subscribeDeferred.promise):Promise.reject("Not connected")}_doUnsubscribe(e){this._webSocket&&this._webSocket.send("UNSUBSCRIBE:"+JSON.stringify({subscriptionId:e}))}_doSend(e){let t=EVENT_MESSAGE_PREFIX+JSON.stringify(e);this._webSocket.send(t)}_doSendWithReply(e){if(e.messageID||(e.messageID=(new Date().getTime()+10*Math.random()).toString(10)),this._repliesDeferred.has(e.messageID))return Promise.reject("There's already a pending send and reply with this ID");let t=new s;return this._repliesDeferred.set(e.messageID,t),this._webSocket.send(EVENT_MESSAGE_PREFIX+JSON.stringify(e)),t.promise}}WebSocketEventProvider._subscriptionCounter=1;