@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/README.md +105 -105
- package/dist/umd/index.bundle.js.map +1 -1
- package/dist/umd/index.js.map +1 -1
- package/dist/umd/index.orbundle.js +49 -49
- package/dist/umd/index.orbundle.js.map +1 -1
- package/lib/asset-mixin.js +1 -161
- package/lib/console.js +1 -541
- package/lib/defaults.js +1 -16
- package/lib/event.js +1 -588
- package/lib/index.js +1 -1003
- package/lib/util.js +1 -1000
- package/package.json +4 -4
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;
|