mobility-toolbox-js 1.6.4-beta.1 → 1.6.4
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/api/routing/RoutingAPI.js +1 -1
- package/api/stops/StopsAPI.js +1 -1
- package/api/trajserv/TrajservAPI.js +3 -3
- package/api/trajserv/TrajservAPIUtils.js +3 -3
- package/api/tralis/TralisAPI.js +34 -29
- package/api/tralis/TralisAPI.test.js +75 -0
- package/api/tralis/WebSocketConnector.js +18 -4
- package/api/tralis/WebSocketConnector.test.js +115 -5
- package/common/Tracker.js +17 -5
- package/common/layers/Layer.js +5 -5
- package/common/mixins/CopyrightMixin.js +1 -1
- package/common/mixins/MapMixin.js +3 -3
- package/common/mixins/SearchMixin.js +1 -1
- package/common/mixins/TrackerLayerMixin.js +4 -7
- package/common/mixins/TrajservLayerMixin.js +1 -1
- package/common/mixins/TralisLayerMixin.js +209 -133
- package/common/utils/delayTrackerStyle.js +1 -1
- package/common/utils/timeUtils.js +0 -28
- package/common/utils/timeUtils.test.js +1 -14
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/mapbox/layers/Layer.js +1 -1
- package/mapbox/layers/TrackerLayer.js +1 -1
- package/mapbox/layers/TrajservLayer.js +1 -1
- package/mapbox/layers/TralisLayer.js +7 -16
- package/ol/layers/Layer.js +1 -1
- package/ol/layers/MapboxLayer.js +2 -2
- package/ol/layers/MapboxStyleLayer.js +2 -2
- package/ol/layers/RoutingLayer.js +1 -1
- package/ol/layers/TrackerLayer.js +2 -2
- package/ol/layers/TrajservLayer.js +2 -2
- package/ol/layers/TralisLayer.js +30 -20
- package/ol/layers/VectorLayer.js +2 -2
- package/ol/layers/WMSLayer.js +3 -3
- package/package.json +1 -1
|
@@ -32,7 +32,7 @@ class RoutingAPI extends API {
|
|
|
32
32
|
*
|
|
33
33
|
* @param {RoutingSearchParams} params Request parameters. See [Routing service documentation](https://developer.geops.io/apis/routing/).
|
|
34
34
|
* @param {AbortController} abortController Abort controller used to cancel the request.
|
|
35
|
-
* @
|
|
35
|
+
* @return {Promise<GeoJSONFeatureCollection>} An GeoJSON feature collection with coordinates in [EPSG:4326](http://epsg.io/4326).
|
|
36
36
|
*/
|
|
37
37
|
route(params, abortController = new AbortController()) {
|
|
38
38
|
return this.fetch('', params, {
|
package/api/stops/StopsAPI.js
CHANGED
|
@@ -29,7 +29,7 @@ class StopsAPI extends API {
|
|
|
29
29
|
*
|
|
30
30
|
* @param {StopsSearchParams} params Request parameters. See [Stops service documentation](https://developer.geops.io/apis/5dcbd702a256d90001cf1361/).
|
|
31
31
|
* @param {AbortController} abortController Abort controller used to cancel the request.
|
|
32
|
-
* @
|
|
32
|
+
* @return {Promise<Array<GeoJSONFeature>>} An array of GeoJSON features with coordinates in [EPSG:4326](http://epsg.io/4326).
|
|
33
33
|
*/
|
|
34
34
|
search(params, abortController = {}) {
|
|
35
35
|
return this.fetch('', params, {
|
|
@@ -33,7 +33,7 @@ class TrajservAPI extends API {
|
|
|
33
33
|
*
|
|
34
34
|
* @param {GetTrajectoryByIdParams} params Request parameters. See [Realtime service documentation](https://developer.geops.io/apis/5dcbd5c9a256d90001cf1360/#/default/get_trajectorybyid).
|
|
35
35
|
* @param {AbortController} abortController Abort controller used to cancel the request.
|
|
36
|
-
* @
|
|
36
|
+
* @return {Promise<TrajservTrajectory>} A trajectory.
|
|
37
37
|
*/
|
|
38
38
|
fetchTrajectoryById(params, abortController = {}) {
|
|
39
39
|
return this.fetch(`/trajectorybyid`, params, {
|
|
@@ -46,7 +46,7 @@ class TrajservAPI extends API {
|
|
|
46
46
|
*
|
|
47
47
|
* @param {GetTrajectoriesParams} params Request parameters. See [Realtime service documentation](https://developer.geops.io/apis/5dcbd5c9a256d90001cf1360/#/default/get_trajectory_collection).
|
|
48
48
|
* @param {AbortController} abortController Abort controller used to cancel the request.
|
|
49
|
-
* @
|
|
49
|
+
* @return {Promise<Array<Trajectory>>} A list of trajectories.
|
|
50
50
|
*/
|
|
51
51
|
fetchTrajectories(params, abortController = {}) {
|
|
52
52
|
return this.fetch(`/trajectory_collection`, params, {
|
|
@@ -61,7 +61,7 @@ class TrajservAPI extends API {
|
|
|
61
61
|
*
|
|
62
62
|
* @param {GetTrajectoryStationsParams} params Request parameters. See [Realtime service documentation](https://developer.geops.io/apis/5dcbd5c9a256d90001cf1360/#/default/get_trajstations).
|
|
63
63
|
* @param {AbortController} abortController Abort controller used to cancel the request.
|
|
64
|
-
* @
|
|
64
|
+
* @return {Promise<Array<TrajectoryStation>>} A list of stations.
|
|
65
65
|
*/
|
|
66
66
|
fetchTrajectoryStations(params, abortController = {}) {
|
|
67
67
|
return this.fetch(`/trajstations`, params, {
|
|
@@ -2,7 +2,7 @@ import { LineString } from 'ol/geom';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Translate the response date object into a readable object.
|
|
5
|
-
* @
|
|
5
|
+
* @return {Date[]}
|
|
6
6
|
* @ignore
|
|
7
7
|
*/
|
|
8
8
|
const translateDates = (dates = []) => {
|
|
@@ -21,7 +21,7 @@ const translateDates = (dates = []) => {
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Translate the trajstations response into a readable object.
|
|
24
|
-
* @
|
|
24
|
+
* @return {Object} returns a readable object
|
|
25
25
|
* @private
|
|
26
26
|
*/
|
|
27
27
|
export const translateTrajStationsResp = (data) => {
|
|
@@ -125,7 +125,7 @@ export const translateTrajStationsResp = (data) => {
|
|
|
125
125
|
|
|
126
126
|
/**
|
|
127
127
|
* Translate the trajectory_collection response into a js usable object.
|
|
128
|
-
* @
|
|
128
|
+
* @return {Array} returns an array of trajectories.
|
|
129
129
|
* @ignore
|
|
130
130
|
*/
|
|
131
131
|
export const translateTrajCollResponse = (features = []) => {
|
package/api/tralis/TralisAPI.js
CHANGED
|
@@ -65,7 +65,8 @@ class TralisAPI {
|
|
|
65
65
|
/** @ignore */
|
|
66
66
|
this.prefix = options.prefix || '';
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
/** @ignore */
|
|
69
|
+
this.onOpen = this.onOpen.bind(this);
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
defineProperties(options) {
|
|
@@ -80,7 +81,7 @@ class TralisAPI {
|
|
|
80
81
|
const conn = new WebSocketConnector();
|
|
81
82
|
|
|
82
83
|
if (apiKey) {
|
|
83
|
-
url = `${url}?key=${apiKey}`;
|
|
84
|
+
url = `${url || 'wss://tralis-tracker-api.geops.io/ws'}?key=${apiKey}`;
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
Object.defineProperties(this, {
|
|
@@ -151,16 +152,8 @@ class TralisAPI {
|
|
|
151
152
|
|
|
152
153
|
open() {
|
|
153
154
|
this.close();
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
// Register BBOX and PROJECTION messages on open.
|
|
157
|
-
if (this.conn.connecting) {
|
|
158
|
-
this.conn.websocket.addEventListener('open', () => {
|
|
159
|
-
this.onOpen();
|
|
160
|
-
});
|
|
161
|
-
} else {
|
|
162
|
-
this.onOpen();
|
|
163
|
-
}
|
|
155
|
+
// Register BBOX and PROJECTION messages must be send before previous subscriptions.
|
|
156
|
+
this.conn.connect(this.url, this.onOpen);
|
|
164
157
|
|
|
165
158
|
// Register reconnection on close.
|
|
166
159
|
this.conn.websocket.onclose = () => {
|
|
@@ -202,7 +195,7 @@ class TralisAPI {
|
|
|
202
195
|
window.clearInterval(this.pingInterval);
|
|
203
196
|
/** @ignore */
|
|
204
197
|
this.pingInterval = setInterval(() => {
|
|
205
|
-
this.send('PING');
|
|
198
|
+
this.conn.send('PING');
|
|
206
199
|
}, this.pingIntervalMs);
|
|
207
200
|
}
|
|
208
201
|
}
|
|
@@ -264,7 +257,7 @@ class TralisAPI {
|
|
|
264
257
|
*
|
|
265
258
|
* @param {Object} depObject The object containing departures by id.
|
|
266
259
|
* @param {boolean} [sortByMinArrivalTime=false] If true sort departures by arrival time.
|
|
267
|
-
* @
|
|
260
|
+
* @return {Array<departure>} Return departures array.
|
|
268
261
|
* @private
|
|
269
262
|
*/
|
|
270
263
|
filterDepartures(depObject, sortByMinArrivalTime = false) {
|
|
@@ -396,7 +389,7 @@ class TralisAPI {
|
|
|
396
389
|
*
|
|
397
390
|
* @param {number} uic UIC of the station.
|
|
398
391
|
* @param {TralisMode} mode Tralis mode.
|
|
399
|
-
* @
|
|
392
|
+
* @return {Promise<Station>} A station.
|
|
400
393
|
*/
|
|
401
394
|
getStation(uic, mode) {
|
|
402
395
|
const params = {
|
|
@@ -419,7 +412,7 @@ class TralisAPI {
|
|
|
419
412
|
* Update the model's station list for a given mode and a bbox.
|
|
420
413
|
*
|
|
421
414
|
* @param {TralisMode} mode Tralis mode.
|
|
422
|
-
* @
|
|
415
|
+
* @return {Promise<Array<Station>>} An array of stations.
|
|
423
416
|
*/
|
|
424
417
|
getStations(mode) {
|
|
425
418
|
const stations = [];
|
|
@@ -448,7 +441,6 @@ class TralisAPI {
|
|
|
448
441
|
* One message pro station.
|
|
449
442
|
*
|
|
450
443
|
* @param {TralisMode} mode Tralis mode.
|
|
451
|
-
* @param {number[4]} bbox The extent where to request.
|
|
452
444
|
* @param {function(station: Station)} onMessage Function called on each message of the channel.
|
|
453
445
|
*/
|
|
454
446
|
subscribeStations(mode, onMessage) {
|
|
@@ -507,14 +499,15 @@ class TralisAPI {
|
|
|
507
499
|
*
|
|
508
500
|
* @param {TralisMode} mode Tralis mode.
|
|
509
501
|
* @param {function(trajectory: TralisTrajectory)} onMessage Function called on each message of the channel.
|
|
502
|
+
* @param {boolean} quiet If true, the subscription will not send GET and SUB requests to the websocket.
|
|
510
503
|
*/
|
|
511
|
-
subscribeTrajectory(mode, onMessage) {
|
|
504
|
+
subscribeTrajectory(mode, onMessage, quiet = false) {
|
|
512
505
|
this.unsubscribeTrajectory(onMessage);
|
|
513
506
|
this.subscribe(
|
|
514
507
|
`trajectory${getModeSuffix(mode, TralisModes)}`,
|
|
515
508
|
onMessage,
|
|
516
509
|
null,
|
|
517
|
-
|
|
510
|
+
quiet,
|
|
518
511
|
);
|
|
519
512
|
}
|
|
520
513
|
|
|
@@ -531,14 +524,15 @@ class TralisAPI {
|
|
|
531
524
|
*
|
|
532
525
|
* @param {TralisMode} mode Tralis mode.
|
|
533
526
|
* @param {function(response: { content: Vehicle })} onMessage Function called on each message of the channel.
|
|
527
|
+
* @param {boolean} quiet If true, the subscription will not send GET and SUB requests to the websocket.
|
|
534
528
|
*/
|
|
535
|
-
subscribeDeletedVehicles(mode, onMessage) {
|
|
529
|
+
subscribeDeletedVehicles(mode, onMessage, quiet = false) {
|
|
536
530
|
this.unsubscribeDeletedVehicles(onMessage);
|
|
537
531
|
this.subscribe(
|
|
538
532
|
`deleted_vehicles${getModeSuffix(mode, TralisModes)}`,
|
|
539
533
|
onMessage,
|
|
540
534
|
null,
|
|
541
|
-
|
|
535
|
+
quiet,
|
|
542
536
|
);
|
|
543
537
|
}
|
|
544
538
|
|
|
@@ -555,11 +549,21 @@ class TralisAPI {
|
|
|
555
549
|
*
|
|
556
550
|
* @param {string} id A vehicle id.
|
|
557
551
|
* @param {TralisMode} mode Tralis mode.
|
|
558
|
-
* @
|
|
552
|
+
* @param {string} generalizationLevel The generalization level to request. Can be one of 5 (more generalized), 10, 30, 100, undefined (less generalized).
|
|
553
|
+
* @return {Promise<FullTrajectory>} Return a full trajectory.
|
|
559
554
|
*/
|
|
560
|
-
getFullTrajectory(id, mode) {
|
|
555
|
+
getFullTrajectory(id, mode, generalizationLevel) {
|
|
556
|
+
const channel = [`full_trajectory${getModeSuffix(mode, TralisModes)}`];
|
|
557
|
+
if (id) {
|
|
558
|
+
channel.push(id);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if ((!mode || mode === TralisModes.TOPOGRAPHIC) && generalizationLevel) {
|
|
562
|
+
channel.push(`gen${generalizationLevel}`);
|
|
563
|
+
}
|
|
564
|
+
|
|
561
565
|
const params = {
|
|
562
|
-
channel:
|
|
566
|
+
channel: channel.join('_'),
|
|
563
567
|
};
|
|
564
568
|
|
|
565
569
|
return new Promise((resolve) => {
|
|
@@ -576,11 +580,12 @@ class TralisAPI {
|
|
|
576
580
|
*
|
|
577
581
|
* @param {string[]} ids List of vehicles ids.
|
|
578
582
|
* @param {TralisMode} mode Tralis mode.
|
|
579
|
-
* @
|
|
583
|
+
* @param {string} generalizationLevel The generalization level to request. Can be one of '', 'gen5', 'gen10', 'gen30', 'gen100'.
|
|
584
|
+
* @return {Promise<Array<FullTrajectory>>} Return an array of full trajectories.
|
|
580
585
|
*/
|
|
581
|
-
getFullTrajectories(ids, mode) {
|
|
586
|
+
getFullTrajectories(ids, mode, generalizationLevel) {
|
|
582
587
|
const promises = ids.map((id) => {
|
|
583
|
-
return this.getFullTrajectory(id, mode);
|
|
588
|
+
return this.getFullTrajectory(id, mode, generalizationLevel);
|
|
584
589
|
});
|
|
585
590
|
return Promise.all(promises);
|
|
586
591
|
}
|
|
@@ -621,7 +626,7 @@ class TralisAPI {
|
|
|
621
626
|
* Get the list of stops for this vehicle.
|
|
622
627
|
*
|
|
623
628
|
* @param {string} id A vehicle id.
|
|
624
|
-
* @
|
|
629
|
+
* @return {Promise<StopSequence>} Returns a stop sequence object.
|
|
625
630
|
*/
|
|
626
631
|
getStopSequence(id) {
|
|
627
632
|
const params = {
|
|
@@ -652,7 +657,7 @@ class TralisAPI {
|
|
|
652
657
|
* Get a list of stops for a list of vehicles.
|
|
653
658
|
*
|
|
654
659
|
* @param {string[]} ids List of vehicles ids.
|
|
655
|
-
* @
|
|
660
|
+
* @return {Promise<Array<StopSequence>>} Return an array of stop sequences.
|
|
656
661
|
*/
|
|
657
662
|
getStopSequences(ids) {
|
|
658
663
|
const promises = ids.map((id) => {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { TralisAPI, TralisModes } from '..';
|
|
2
|
+
|
|
3
|
+
describe('TralisAPI', () => {
|
|
4
|
+
let tralisAPI;
|
|
5
|
+
let get;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
get = jest.fn((params, cb) => {
|
|
9
|
+
cb({ content: 'content' });
|
|
10
|
+
});
|
|
11
|
+
tralisAPI = new TralisAPI();
|
|
12
|
+
tralisAPI.conn = {
|
|
13
|
+
get,
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('#getFullTrajectory() calls fullTrajectory channel', () => {
|
|
18
|
+
test('without parameters', (done) => {
|
|
19
|
+
tralisAPI.getFullTrajectory().then(() => {
|
|
20
|
+
expect(get.mock.calls.length).toBe(1);
|
|
21
|
+
expect(get.mock.calls[0][0]).toEqual({
|
|
22
|
+
channel: 'full_trajectory',
|
|
23
|
+
});
|
|
24
|
+
done();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
[null, TralisModes.TOPOGRAPHIC].forEach((mode) => {
|
|
29
|
+
describe(`using mode ${mode}`, () => {
|
|
30
|
+
test('using id', (done) => {
|
|
31
|
+
tralisAPI.getFullTrajectory('foo', mode).then(() => {
|
|
32
|
+
expect(get.mock.calls.length).toBe(1);
|
|
33
|
+
expect(get.mock.calls[0][0]).toEqual({
|
|
34
|
+
channel: 'full_trajectory_foo',
|
|
35
|
+
});
|
|
36
|
+
done();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('using id and generalizationLevel param', (done) => {
|
|
41
|
+
tralisAPI.getFullTrajectory('foo', mode, 5).then(() => {
|
|
42
|
+
expect(get.mock.calls.length).toBe(1);
|
|
43
|
+
expect(get.mock.calls[0][0]).toEqual({
|
|
44
|
+
channel: 'full_trajectory_foo_gen5',
|
|
45
|
+
});
|
|
46
|
+
done();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('using schematic mode ', () => {
|
|
53
|
+
test('using id', (done) => {
|
|
54
|
+
tralisAPI.getFullTrajectory('foo', TralisModes.SCHEMATIC).then(() => {
|
|
55
|
+
expect(get.mock.calls.length).toBe(1);
|
|
56
|
+
expect(get.mock.calls[0][0]).toEqual({
|
|
57
|
+
channel: 'full_trajectory_schematic_foo',
|
|
58
|
+
});
|
|
59
|
+
done();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
test("doesn't use generalizationLevel param", (done) => {
|
|
63
|
+
tralisAPI
|
|
64
|
+
.getFullTrajectory('foo', TralisModes.SCHEMATIC, 10)
|
|
65
|
+
.then(() => {
|
|
66
|
+
expect(get.mock.calls.length).toBe(1);
|
|
67
|
+
expect(get.mock.calls[0][0]).toEqual({
|
|
68
|
+
channel: 'full_trajectory_schematic_foo',
|
|
69
|
+
});
|
|
70
|
+
done();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -82,7 +82,7 @@ class WebSocketConnector {
|
|
|
82
82
|
* @param {string} params.channel Channel name
|
|
83
83
|
* @param {string} [params.args] Request arguments
|
|
84
84
|
* @param {Number} [params.id] Request identifier
|
|
85
|
-
* @
|
|
85
|
+
* @return {string} request string
|
|
86
86
|
* @private
|
|
87
87
|
*/
|
|
88
88
|
static getRequestString(method, params) {
|
|
@@ -95,9 +95,11 @@ class WebSocketConnector {
|
|
|
95
95
|
/**
|
|
96
96
|
* (Re)connect the websocket.
|
|
97
97
|
*
|
|
98
|
+
* @param {strin} url Websocket url.
|
|
99
|
+
* @param {function} onOpen Callback called when the websocket connection is opened and before subscriptions of previous subscriptions.
|
|
98
100
|
* @private
|
|
99
101
|
*/
|
|
100
|
-
connect(url) {
|
|
102
|
+
connect(url, onOpen = () => {}) {
|
|
101
103
|
if (this.websocket && !this.closed) {
|
|
102
104
|
this.websocket.close();
|
|
103
105
|
}
|
|
@@ -107,9 +109,11 @@ class WebSocketConnector {
|
|
|
107
109
|
|
|
108
110
|
if (!this.open) {
|
|
109
111
|
this.websocket.addEventListener('open', () => {
|
|
112
|
+
onOpen();
|
|
110
113
|
this.subscribePreviousSubscriptions();
|
|
111
114
|
});
|
|
112
115
|
} else {
|
|
116
|
+
onOpen();
|
|
113
117
|
this.subscribePreviousSubscriptions();
|
|
114
118
|
}
|
|
115
119
|
}
|
|
@@ -124,6 +128,7 @@ class WebSocketConnector {
|
|
|
124
128
|
this.websocket.onclose = null;
|
|
125
129
|
this.websocket.close();
|
|
126
130
|
this.websocket = null;
|
|
131
|
+
this.messagesOnOpen = [];
|
|
127
132
|
}
|
|
128
133
|
}
|
|
129
134
|
|
|
@@ -148,6 +153,9 @@ class WebSocketConnector {
|
|
|
148
153
|
this.messagesOnOpen = [];
|
|
149
154
|
send();
|
|
150
155
|
});
|
|
156
|
+
this.websocket.addEventListener('close', () => {
|
|
157
|
+
this.messagesOnOpen = [];
|
|
158
|
+
});
|
|
151
159
|
}
|
|
152
160
|
} else if (!this.messagesOnOpen.includes(message)) {
|
|
153
161
|
send();
|
|
@@ -160,7 +168,7 @@ class WebSocketConnector {
|
|
|
160
168
|
* @param {Object} params Parameters for the websocket get request
|
|
161
169
|
* @param {function} cb callback on listen
|
|
162
170
|
* @param {function} errorCb Callback on error
|
|
163
|
-
* @
|
|
171
|
+
* @return {{onMessage: function, errorCb: function}} Object with onMessage and error callbacks
|
|
164
172
|
* @private
|
|
165
173
|
*/
|
|
166
174
|
listen(params, cb, errorCb) {
|
|
@@ -260,7 +268,6 @@ class WebSocketConnector {
|
|
|
260
268
|
this.send(`GET ${reqStr}`);
|
|
261
269
|
this.send(`SUB ${reqStr}`);
|
|
262
270
|
}
|
|
263
|
-
|
|
264
271
|
this.subscribed[reqStr] = true;
|
|
265
272
|
}
|
|
266
273
|
}
|
|
@@ -307,6 +314,13 @@ class WebSocketConnector {
|
|
|
307
314
|
* After an auto reconnection we need to re-subscribe to the channels.
|
|
308
315
|
*/
|
|
309
316
|
subscribePreviousSubscriptions() {
|
|
317
|
+
// Before to subscribe previous subscriptions we make sure they
|
|
318
|
+
// are all defined as unsubscribed, because this code is asynchrone
|
|
319
|
+
// and a subscription could have been added in between.
|
|
320
|
+
Object.keys(this.subscribed).forEach((key) => {
|
|
321
|
+
this.subscribed[key] = false;
|
|
322
|
+
});
|
|
323
|
+
|
|
310
324
|
// Subscribe all previous subscriptions.
|
|
311
325
|
[...this.subscriptions].forEach((s) => {
|
|
312
326
|
this.subscribe(s.params, s.cb, s.errorCb, s.quiet);
|
|
@@ -28,6 +28,31 @@ describe('WebSocketConnector', () => {
|
|
|
28
28
|
});
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
+
describe('#close', () => {
|
|
32
|
+
test('should close the websocket and clear some property', async () => {
|
|
33
|
+
// eslint-disable-next-line no-unused-vars
|
|
34
|
+
const client = new Connector();
|
|
35
|
+
const subsc2 = {
|
|
36
|
+
params: 'foo',
|
|
37
|
+
cb: () => {},
|
|
38
|
+
errorCb: () => {},
|
|
39
|
+
quiet: false,
|
|
40
|
+
};
|
|
41
|
+
client.subscriptions = [subsc2];
|
|
42
|
+
client.messagesOnOpen = ['GET foo'];
|
|
43
|
+
client.connect(`ws://foo:1234`);
|
|
44
|
+
client.websocket.addEventListener = jest.fn();
|
|
45
|
+
client.websocket.removeEventListener = jest.fn();
|
|
46
|
+
client.websocket.close = jest.fn();
|
|
47
|
+
await server.connected;
|
|
48
|
+
expect(client.websocket).toBeDefined();
|
|
49
|
+
expect(client.messagesOnOpen).toEqual(['GET foo']);
|
|
50
|
+
client.close();
|
|
51
|
+
expect(client.messagesOnOpen).toEqual([]);
|
|
52
|
+
expect(client.websocket).toBeNull();
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
31
56
|
describe('#connect', () => {
|
|
32
57
|
test('create a new WebSocket.', async () => {
|
|
33
58
|
const client = new Connector();
|
|
@@ -50,23 +75,44 @@ describe('WebSocketConnector', () => {
|
|
|
50
75
|
expect(client.websocket.readyState).toBe(WebSocket.CONNECTING);
|
|
51
76
|
});
|
|
52
77
|
|
|
53
|
-
test('
|
|
78
|
+
test('call onOpen function', async () => {
|
|
79
|
+
const onOpen = jest.fn();
|
|
54
80
|
const client = new Connector();
|
|
55
81
|
client.subscribe = jest.fn();
|
|
56
|
-
client.connect(`ws://foo:1234
|
|
82
|
+
client.connect(`ws://foo:1234`, onOpen);
|
|
57
83
|
await server.connected;
|
|
58
84
|
expect(client.websocket.readyState).toBe(WebSocket.OPEN);
|
|
85
|
+
expect(onOpen).toHaveBeenCalledTimes(1);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('subscribe previous subscriptions on open (quiet or not)', async () => {
|
|
89
|
+
const client = new Connector();
|
|
90
|
+
client.subscribe = jest.fn();
|
|
91
|
+
client.send = jest.fn();
|
|
59
92
|
const subsc = {
|
|
60
93
|
params: 'foo',
|
|
61
94
|
cb: () => {},
|
|
62
95
|
errorCb: () => {},
|
|
63
96
|
quiet: true,
|
|
64
97
|
};
|
|
65
|
-
|
|
98
|
+
const subsc2 = {
|
|
99
|
+
params: 'foo',
|
|
100
|
+
cb: () => {},
|
|
101
|
+
errorCb: () => {},
|
|
102
|
+
quiet: false,
|
|
103
|
+
};
|
|
104
|
+
client.subscriptions = [subsc, subsc2];
|
|
105
|
+
|
|
106
|
+
client.connect(`ws://foo:1234`);
|
|
107
|
+
await server.connected;
|
|
108
|
+
expect(client.websocket.readyState).toBe(WebSocket.OPEN);
|
|
109
|
+
expect(client.subscribe).toHaveBeenCalledTimes(2);
|
|
110
|
+
client.subscribe.mockReset();
|
|
111
|
+
|
|
66
112
|
client.connect(`ws://foo:12345`);
|
|
67
113
|
await server2.connected;
|
|
68
114
|
expect(client.websocket.readyState).toBe(WebSocket.OPEN);
|
|
69
|
-
expect(client.subscribe).toHaveBeenCalledTimes(
|
|
115
|
+
expect(client.subscribe).toHaveBeenCalledTimes(2);
|
|
70
116
|
expect(client.subscribe).toHaveBeenCalledWith(
|
|
71
117
|
subsc.params,
|
|
72
118
|
subsc.cb,
|
|
@@ -74,6 +120,66 @@ describe('WebSocketConnector', () => {
|
|
|
74
120
|
subsc.quiet,
|
|
75
121
|
);
|
|
76
122
|
});
|
|
123
|
+
|
|
124
|
+
test('send GET and SUB for not quiet previous subscriptions', async () => {
|
|
125
|
+
const client = new Connector();
|
|
126
|
+
client.send = jest.fn();
|
|
127
|
+
const subsc = {
|
|
128
|
+
params: { channel: 'foo' },
|
|
129
|
+
cb: () => {},
|
|
130
|
+
errorCb: () => {},
|
|
131
|
+
quiet: false,
|
|
132
|
+
};
|
|
133
|
+
client.subscriptions = [subsc];
|
|
134
|
+
|
|
135
|
+
client.connect(`ws://foo:1234`);
|
|
136
|
+
client.websocket.addEventListener = jest.fn();
|
|
137
|
+
client.websocket.removeEventListener = jest.fn();
|
|
138
|
+
await server.connected;
|
|
139
|
+
expect(client.websocket.readyState).toBe(WebSocket.OPEN);
|
|
140
|
+
expect(client.send).toHaveBeenCalledTimes(2);
|
|
141
|
+
expect(client.send.mock.calls[0]).toEqual(['GET foo']);
|
|
142
|
+
expect(client.send.mock.calls[1]).toEqual(['SUB foo']);
|
|
143
|
+
client.send.mockReset();
|
|
144
|
+
|
|
145
|
+
client.connect(`ws://foo:12345`);
|
|
146
|
+
client.websocket.addEventListener = jest.fn();
|
|
147
|
+
client.websocket.removeEventListener = jest.fn();
|
|
148
|
+
await server2.connected;
|
|
149
|
+
expect(client.websocket.readyState).toBe(WebSocket.OPEN);
|
|
150
|
+
// not quiet subscriptions will send GET and SUB requests.
|
|
151
|
+
expect(client.send).toHaveBeenCalledTimes(2);
|
|
152
|
+
expect(client.send.mock.calls[0]).toEqual(['GET foo']);
|
|
153
|
+
expect(client.send.mock.calls[1]).toEqual(['SUB foo']);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test('doesn\t send GET and SUB for quiet previous subscriptions', async () => {
|
|
157
|
+
const client = new Connector();
|
|
158
|
+
client.send = jest.fn();
|
|
159
|
+
const subsc = {
|
|
160
|
+
params: { channel: 'foo' },
|
|
161
|
+
cb: () => {},
|
|
162
|
+
errorCb: () => {},
|
|
163
|
+
quiet: true,
|
|
164
|
+
};
|
|
165
|
+
client.subscriptions = [subsc];
|
|
166
|
+
|
|
167
|
+
client.connect(`ws://foo:1234`);
|
|
168
|
+
client.websocket.addEventListener = jest.fn();
|
|
169
|
+
client.websocket.removeEventListener = jest.fn();
|
|
170
|
+
await server.connected;
|
|
171
|
+
expect(client.websocket.readyState).toBe(WebSocket.OPEN);
|
|
172
|
+
expect(client.send).toHaveBeenCalledTimes(0);
|
|
173
|
+
client.send.mockReset();
|
|
174
|
+
|
|
175
|
+
client.connect(`ws://foo:12345`);
|
|
176
|
+
client.websocket.addEventListener = jest.fn();
|
|
177
|
+
client.websocket.removeEventListener = jest.fn();
|
|
178
|
+
await server2.connected;
|
|
179
|
+
expect(client.websocket.readyState).toBe(WebSocket.OPEN);
|
|
180
|
+
// not quiet subscriptions will send GET and SUB requests.
|
|
181
|
+
expect(client.send).toHaveBeenCalledTimes(0);
|
|
182
|
+
});
|
|
77
183
|
});
|
|
78
184
|
|
|
79
185
|
describe('#subscribe', () => {
|
|
@@ -199,7 +305,11 @@ describe('WebSocketConnector', () => {
|
|
|
199
305
|
client.subscribe(params2, cb2);
|
|
200
306
|
expect(client.subscriptions.length).toBe(3);
|
|
201
307
|
expect(client.websocket.removeEventListener).toBeCalledTimes(2);
|
|
202
|
-
expect(
|
|
308
|
+
expect(
|
|
309
|
+
client.websocket.addEventListener.mock.calls.filter(
|
|
310
|
+
(c) => c[0] === 'message',
|
|
311
|
+
).length,
|
|
312
|
+
).toBe(5);
|
|
203
313
|
|
|
204
314
|
client.unsubscribe('foo');
|
|
205
315
|
expect(client.subscriptions.length).toBe(1);
|
package/common/Tracker.js
CHANGED
|
@@ -123,7 +123,7 @@ export default class Tracker {
|
|
|
123
123
|
|
|
124
124
|
/**
|
|
125
125
|
* Return the trajectories.
|
|
126
|
-
* @
|
|
126
|
+
* @return {array<trajectory>} trajectories
|
|
127
127
|
*/
|
|
128
128
|
getTrajectories() {
|
|
129
129
|
return this.trajectories || [];
|
|
@@ -203,6 +203,8 @@ export default class Tracker {
|
|
|
203
203
|
for (let i = (this.trajectories || []).length - 1; i >= 0; i -= 1) {
|
|
204
204
|
const traj = this.trajectories[i];
|
|
205
205
|
|
|
206
|
+
this.trajectories[i].rendered = false;
|
|
207
|
+
|
|
206
208
|
// We simplify the traj object
|
|
207
209
|
const { geometry, timeIntervals, timeOffset } = traj;
|
|
208
210
|
|
|
@@ -293,16 +295,26 @@ export default class Tracker {
|
|
|
293
295
|
return p * pixelRatio;
|
|
294
296
|
});
|
|
295
297
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
298
|
+
if (
|
|
299
|
+
px[0] < 0 ||
|
|
300
|
+
px[0] > this.canvas.width ||
|
|
301
|
+
px[1] < 0 ||
|
|
302
|
+
px[1] > this.canvas.height
|
|
303
|
+
) {
|
|
304
|
+
// eslint-disable-next-line no-continue
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
300
307
|
|
|
308
|
+
const vehicleImg = this.style(traj, viewState);
|
|
301
309
|
if (!vehicleImg) {
|
|
302
310
|
// eslint-disable-next-line no-continue
|
|
303
311
|
continue;
|
|
304
312
|
}
|
|
305
313
|
|
|
314
|
+
// Trajectory with pixel (i.e. within map extent) will be in renderedTrajectories.
|
|
315
|
+
this.trajectories[i].rendered = true;
|
|
316
|
+
this.renderedTrajectories.push(this.trajectories[i]);
|
|
317
|
+
|
|
306
318
|
const imgWidth = vehicleImg.width;
|
|
307
319
|
const imgHeight = vehicleImg.height;
|
|
308
320
|
|
package/common/layers/Layer.js
CHANGED
|
@@ -186,7 +186,7 @@ export default class Layer extends Observable {
|
|
|
186
186
|
* Get a layer property.
|
|
187
187
|
*
|
|
188
188
|
* @param {string} name Property name.
|
|
189
|
-
* @
|
|
189
|
+
* @return {property} Property
|
|
190
190
|
*/
|
|
191
191
|
get(name) {
|
|
192
192
|
return this.properties[name];
|
|
@@ -239,7 +239,7 @@ export default class Layer extends Observable {
|
|
|
239
239
|
/**
|
|
240
240
|
* Returns an array with visible child layers
|
|
241
241
|
*
|
|
242
|
-
* @
|
|
242
|
+
* @return {Layer[]} Visible children
|
|
243
243
|
*/
|
|
244
244
|
getVisibleChildren() {
|
|
245
245
|
return this.children.filter((child) => child.visible);
|
|
@@ -248,7 +248,7 @@ export default class Layer extends Observable {
|
|
|
248
248
|
/**
|
|
249
249
|
* Checks whether the layer has child layers with visible set to True
|
|
250
250
|
*
|
|
251
|
-
* @
|
|
251
|
+
* @return {boolean} True if the layer has visible child layers
|
|
252
252
|
* @deprecated
|
|
253
253
|
*/
|
|
254
254
|
hasVisibleChildren() {
|
|
@@ -259,7 +259,7 @@ export default class Layer extends Observable {
|
|
|
259
259
|
* Checks whether the layer has any child layers with visible equal to the input parameter
|
|
260
260
|
*
|
|
261
261
|
* @param {boolean} visible The state to check the childlayers against
|
|
262
|
-
* @
|
|
262
|
+
* @return {boolean} True if the layer has children with the given visibility
|
|
263
263
|
*/
|
|
264
264
|
hasChildren(visible) {
|
|
265
265
|
return !!this.children.find((child) => child.visible === visible);
|
|
@@ -302,7 +302,7 @@ export default class Layer extends Observable {
|
|
|
302
302
|
*
|
|
303
303
|
* @param {ol/coordinate~Coordinate} coordinate Coordinate.
|
|
304
304
|
* @param {Object} options Some options. See child classes to see which are supported.
|
|
305
|
-
* @
|
|
305
|
+
* @return {Promise<FeatureInfo>} An empty response.
|
|
306
306
|
*/
|
|
307
307
|
// eslint-disable-next-line no-unused-vars
|
|
308
308
|
getFeatureInfoAtCoordinate(coordinate, options) {
|