Commit 5f606912fc6cd8262f5d6b598772aac972c7d850
1 parent
b38a4d2f
UI: Improve data simulation performance. Improve processing of default zoom level by map widgets.
Showing
5 changed files
with
106 additions
and
62 deletions
@@ -19,6 +19,10 @@ export default class DataAggregator { | @@ -19,6 +19,10 @@ export default class DataAggregator { | ||
19 | constructor(onDataCb, tsKeyNames, startTs, limit, aggregationType, timeWindow, interval, types, $timeout, $filter) { | 19 | constructor(onDataCb, tsKeyNames, startTs, limit, aggregationType, timeWindow, interval, types, $timeout, $filter) { |
20 | this.onDataCb = onDataCb; | 20 | this.onDataCb = onDataCb; |
21 | this.tsKeyNames = tsKeyNames; | 21 | this.tsKeyNames = tsKeyNames; |
22 | + this.dataBuffer = {}; | ||
23 | + for (var k in tsKeyNames) { | ||
24 | + this.dataBuffer[tsKeyNames[k]] = []; | ||
25 | + } | ||
22 | this.startTs = startTs; | 26 | this.startTs = startTs; |
23 | this.aggregationType = aggregationType; | 27 | this.aggregationType = aggregationType; |
24 | this.types = types; | 28 | this.types = types; |
@@ -120,11 +124,11 @@ export default class DataAggregator { | @@ -120,11 +124,11 @@ export default class DataAggregator { | ||
120 | if (delta || !this.data) { | 124 | if (delta || !this.data) { |
121 | this.startTs += delta * this.interval; | 125 | this.startTs += delta * this.interval; |
122 | this.endTs += delta * this.interval; | 126 | this.endTs += delta * this.interval; |
123 | - this.data = toData(this.tsKeyNames, this.aggregationMap, this.startTs, this.endTs, this.$filter, this.limit); | 127 | + this.data = this.updateData(); |
124 | this.elapsed = this.elapsed - delta * this.interval; | 128 | this.elapsed = this.elapsed - delta * this.interval; |
125 | } | 129 | } |
126 | } else { | 130 | } else { |
127 | - this.data = toData(this.tsKeyNames, this.aggregationMap, this.startTs, this.endTs, this.$filter, this.limit); | 131 | + this.data = this.updateData(); |
128 | } | 132 | } |
129 | if (this.onDataCb) { | 133 | if (this.onDataCb) { |
130 | this.onDataCb(this.data, this.startTs, this.endTs, apply); | 134 | this.onDataCb(this.data, this.startTs, this.endTs, apply); |
@@ -138,6 +142,31 @@ export default class DataAggregator { | @@ -138,6 +142,31 @@ export default class DataAggregator { | ||
138 | } | 142 | } |
139 | } | 143 | } |
140 | 144 | ||
145 | + updateData() { | ||
146 | + for (var k in this.tsKeyNames) { | ||
147 | + this.dataBuffer[this.tsKeyNames[k]] = []; | ||
148 | + } | ||
149 | + for (var key in this.aggregationMap) { | ||
150 | + var aggKeyData = this.aggregationMap[key]; | ||
151 | + var keyData = this.dataBuffer[key]; | ||
152 | + for (var aggTimestamp in aggKeyData) { | ||
153 | + if (aggTimestamp <= this.startTs) { | ||
154 | + delete aggKeyData[aggTimestamp]; | ||
155 | + } else if (aggTimestamp <= this.endTs) { | ||
156 | + var aggData = aggKeyData[aggTimestamp]; | ||
157 | + var kvPair = [Number(aggTimestamp), aggData.aggValue]; | ||
158 | + keyData.push(kvPair); | ||
159 | + } | ||
160 | + } | ||
161 | + keyData = this.$filter('orderBy')(keyData, '+this[0]'); | ||
162 | + if (keyData.length > this.limit) { | ||
163 | + keyData = keyData.slice(keyData.length - this.limit); | ||
164 | + } | ||
165 | + this.dataBuffer[key] = keyData; | ||
166 | + } | ||
167 | + return this.dataBuffer; | ||
168 | + } | ||
169 | + | ||
141 | destroy() { | 170 | destroy() { |
142 | if (this.intervalTimeoutHandle) { | 171 | if (this.intervalTimeoutHandle) { |
143 | this.$timeout.cancel(this.intervalTimeoutHandle); | 172 | this.$timeout.cancel(this.intervalTimeoutHandle); |
@@ -208,32 +237,6 @@ function updateAggregatedData(aggregationMap, isCount, noAggregation, aggFunctio | @@ -208,32 +237,6 @@ function updateAggregatedData(aggregationMap, isCount, noAggregation, aggFunctio | ||
208 | } | 237 | } |
209 | } | 238 | } |
210 | 239 | ||
211 | -function toData(tsKeyNames, aggregationMap, startTs, endTs, $filter, limit) { | ||
212 | - var data = {}; | ||
213 | - for (var k in tsKeyNames) { | ||
214 | - data[tsKeyNames[k]] = []; | ||
215 | - } | ||
216 | - for (var key in aggregationMap) { | ||
217 | - var aggKeyData = aggregationMap[key]; | ||
218 | - var keyData = data[key]; | ||
219 | - for (var aggTimestamp in aggKeyData) { | ||
220 | - if (aggTimestamp <= startTs) { | ||
221 | - delete aggKeyData[aggTimestamp]; | ||
222 | - } else if (aggTimestamp <= endTs) { | ||
223 | - var aggData = aggKeyData[aggTimestamp]; | ||
224 | - var kvPair = [Number(aggTimestamp), aggData.aggValue]; | ||
225 | - keyData.push(kvPair); | ||
226 | - } | ||
227 | - } | ||
228 | - keyData = $filter('orderBy')(keyData, '+this[0]'); | ||
229 | - if (keyData.length > limit) { | ||
230 | - keyData = keyData.slice(keyData.length - limit); | ||
231 | - } | ||
232 | - data[key] = keyData; | ||
233 | - } | ||
234 | - return data; | ||
235 | -} | ||
236 | - | ||
237 | function convertValue(value, noAggregation) { | 240 | function convertValue(value, noAggregation) { |
238 | if (!noAggregation || value && isNumeric(value)) { | 241 | if (!noAggregation || value && isNumeric(value)) { |
239 | return Number(value); | 242 | return Number(value); |
@@ -110,6 +110,8 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic | @@ -110,6 +110,8 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic | ||
110 | datasourceSubscription.subscriptionTimewindow.realtimeWindowMs; | 110 | datasourceSubscription.subscriptionTimewindow.realtimeWindowMs; |
111 | var timer; | 111 | var timer; |
112 | var frequency; | 112 | var frequency; |
113 | + var tickElapsed = 0; | ||
114 | + var tickScheduledTime = 0; | ||
113 | var dataAggregator; | 115 | var dataAggregator; |
114 | 116 | ||
115 | var subscription = { | 117 | var subscription = { |
@@ -353,11 +355,14 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic | @@ -353,11 +355,14 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic | ||
353 | } | 355 | } |
354 | dataAggregator = createRealtimeDataAggregator(subsTw, tsKeyNames, types.dataKeyType.function); | 356 | dataAggregator = createRealtimeDataAggregator(subsTw, tsKeyNames, types.dataKeyType.function); |
355 | } | 357 | } |
358 | + tickScheduledTime = currentTime(); | ||
356 | if (history) { | 359 | if (history) { |
357 | onTick(false); | 360 | onTick(false); |
358 | } else { | 361 | } else { |
359 | timer = $timeout( | 362 | timer = $timeout( |
360 | - function() {onTick(true)}, | 363 | + function() { |
364 | + onTick(true) | ||
365 | + }, | ||
361 | 0, | 366 | 0, |
362 | false | 367 | false |
363 | ); | 368 | ); |
@@ -393,6 +398,7 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic | @@ -393,6 +398,7 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic | ||
393 | function unsubscribe() { | 398 | function unsubscribe() { |
394 | if (timer) { | 399 | if (timer) { |
395 | $timeout.cancel(timer); | 400 | $timeout.cancel(timer); |
401 | + timer = null; | ||
396 | } | 402 | } |
397 | if (datasourceType === types.datasourceType.device) { | 403 | if (datasourceType === types.datasourceType.device) { |
398 | for (var cmdId in subscribers) { | 404 | for (var cmdId in subscribers) { |
@@ -456,15 +462,39 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic | @@ -456,15 +462,39 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic | ||
456 | } | 462 | } |
457 | } | 463 | } |
458 | 464 | ||
465 | + /* eslint-disable */ | ||
466 | + function currentTime() { | ||
467 | + return window.performance && window.performance.now ? | ||
468 | + window.performance.now() : Date.now(); | ||
469 | + } | ||
470 | + /* eslint-enable */ | ||
471 | + | ||
472 | + | ||
459 | function onTick(apply) { | 473 | function onTick(apply) { |
474 | + | ||
475 | + var now = currentTime(); | ||
476 | + tickElapsed += now - tickScheduledTime; | ||
477 | + tickScheduledTime = now; | ||
478 | + | ||
479 | + if (timer) { | ||
480 | + $timeout.cancel(timer); | ||
481 | + timer = null; | ||
482 | + } | ||
483 | + | ||
460 | var key; | 484 | var key; |
461 | if (datasourceSubscription.type === types.widgetType.timeseries.value) { | 485 | if (datasourceSubscription.type === types.widgetType.timeseries.value) { |
462 | var startTime; | 486 | var startTime; |
463 | var endTime; | 487 | var endTime; |
488 | + var delta; | ||
464 | var generatedData = { | 489 | var generatedData = { |
465 | data: { | 490 | data: { |
466 | } | 491 | } |
467 | }; | 492 | }; |
493 | + if (!history) { | ||
494 | + delta = Math.floor(tickElapsed / frequency); | ||
495 | + } | ||
496 | + var deltaElapsed = history ? frequency : delta * frequency; | ||
497 | + tickElapsed = tickElapsed - deltaElapsed; | ||
468 | for (key in dataKeys) { | 498 | for (key in dataKeys) { |
469 | var dataKeyList = dataKeys[key]; | 499 | var dataKeyList = dataKeys[key]; |
470 | for (var index = 0; index < dataKeyList.length; index ++) { | 500 | for (var index = 0; index < dataKeyList.length; index ++) { |
@@ -472,11 +502,12 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic | @@ -472,11 +502,12 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic | ||
472 | if (!startTime) { | 502 | if (!startTime) { |
473 | if (realtime) { | 503 | if (realtime) { |
474 | if (dataKey.lastUpdateTime) { | 504 | if (dataKey.lastUpdateTime) { |
475 | - startTime = dataKey.lastUpdateTime + frequency | 505 | + startTime = dataKey.lastUpdateTime + frequency; |
506 | + endTime = dataKey.lastUpdateTime + deltaElapsed; | ||
476 | } else { | 507 | } else { |
477 | startTime = datasourceSubscription.subscriptionTimewindow.startTs; | 508 | startTime = datasourceSubscription.subscriptionTimewindow.startTs; |
509 | + endTime = startTime + datasourceSubscription.subscriptionTimewindow.realtimeWindowMs + frequency; | ||
478 | } | 510 | } |
479 | - endTime = startTime + datasourceSubscription.subscriptionTimewindow.realtimeWindowMs; | ||
480 | } else { | 511 | } else { |
481 | startTime = datasourceSubscription.subscriptionTimewindow.fixedWindow.startTimeMs; | 512 | startTime = datasourceSubscription.subscriptionTimewindow.fixedWindow.startTimeMs; |
482 | endTime = datasourceSubscription.subscriptionTimewindow.fixedWindow.endTimeMs; | 513 | endTime = datasourceSubscription.subscriptionTimewindow.fixedWindow.endTimeMs; |
@@ -494,7 +525,7 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic | @@ -494,7 +525,7 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic | ||
494 | } | 525 | } |
495 | 526 | ||
496 | if (!history) { | 527 | if (!history) { |
497 | - timer = $timeout(function() {onTick(true)}, frequency / 2, false); | 528 | + timer = $timeout(function() {onTick(true)}, frequency, false); |
498 | } | 529 | } |
499 | } | 530 | } |
500 | 531 |
@@ -246,26 +246,31 @@ export default class TbGoogleMap { | @@ -246,26 +246,31 @@ export default class TbGoogleMap { | ||
246 | } | 246 | } |
247 | /* eslint-enable no-undef */ | 247 | /* eslint-enable no-undef */ |
248 | 248 | ||
249 | + /* eslint-disable no-undef */ | ||
249 | fitBounds(bounds) { | 250 | fitBounds(bounds) { |
250 | - var tbMap = this; | ||
251 | - google.maps.event.addListenerOnce(this.map, 'bounds_changed', function() { // eslint-disable-line no-undef | ||
252 | - var newZoomLevel = tbMap.map.getZoom(); | ||
253 | - if (tbMap.dontFitMapBounds && tbMap.defaultZoomLevel) { | ||
254 | - newZoomLevel = tbMap.defaultZoomLevel; | ||
255 | - } | ||
256 | - tbMap.map.setZoom(newZoomLevel); | ||
257 | - | ||
258 | - if (!tbMap.defaultZoomLevel && tbMap.map.getZoom() > tbMap.minZoomLevel) { | ||
259 | - tbMap.map.setZoom(tbMap.minZoomLevel); | ||
260 | - } | ||
261 | - }); | ||
262 | - this.map.fitBounds(bounds); | 251 | + if (this.dontFitMapBounds && this.defaultZoomLevel) { |
252 | + this.map.setZoom(this.defaultZoomLevel); | ||
253 | + this.map.setCenter(bounds.getCenter()); | ||
254 | + } else { | ||
255 | + var tbMap = this; | ||
256 | + google.maps.event.addListenerOnce(this.map, 'bounds_changed', function() { // eslint-disable-line no-undef | ||
257 | + if (!tbMap.defaultZoomLevel && tbMap.map.getZoom() > tbMap.minZoomLevel) { | ||
258 | + tbMap.map.setZoom(tbMap.minZoomLevel); | ||
259 | + } | ||
260 | + }); | ||
261 | + this.map.fitBounds(bounds); | ||
262 | + } | ||
263 | } | 263 | } |
264 | + /* eslint-enable no-undef */ | ||
264 | 265 | ||
265 | createLatLng(lat, lng) { | 266 | createLatLng(lat, lng) { |
266 | return new google.maps.LatLng(lat, lng); // eslint-disable-line no-undef | 267 | return new google.maps.LatLng(lat, lng); // eslint-disable-line no-undef |
267 | } | 268 | } |
268 | 269 | ||
270 | + extendBoundsWithMarker(bounds, marker) { | ||
271 | + bounds.extend(marker.getPosition()); | ||
272 | + } | ||
273 | + | ||
269 | getMarkerPosition(marker) { | 274 | getMarkerPosition(marker) { |
270 | return marker.getPosition(); | 275 | return marker.getPosition(); |
271 | } | 276 | } |
@@ -386,7 +386,7 @@ export default class TbMapWidget { | @@ -386,7 +386,7 @@ export default class TbMapWidget { | ||
386 | if (location.polyline) { | 386 | if (location.polyline) { |
387 | tbMap.map.extendBounds(bounds, location.polyline); | 387 | tbMap.map.extendBounds(bounds, location.polyline); |
388 | } else if (location.marker) { | 388 | } else if (location.marker) { |
389 | - bounds.extend(tbMap.map.getMarkerPosition(location.marker)); | 389 | + tbMap.map.extendBoundsWithMarker(bounds, location.marker); |
390 | } | 390 | } |
391 | } | 391 | } |
392 | } | 392 | } |
@@ -403,10 +403,10 @@ export default class TbMapWidget { | @@ -403,10 +403,10 @@ export default class TbMapWidget { | ||
403 | if (location.polyline) { | 403 | if (location.polyline) { |
404 | tbMap.map.extendBounds(bounds, location.polyline); | 404 | tbMap.map.extendBounds(bounds, location.polyline); |
405 | } else if (location.marker) { | 405 | } else if (location.marker) { |
406 | - bounds.extend(tbMap.map.getMarkerPosition(location.marker)); | 406 | + tbMap.map.extendBoundsWithMarker(bounds, location.marker); |
407 | } | 407 | } |
408 | } | 408 | } |
409 | - if (!tbMap.dontFitMapBounds && locationsChanged) { | 409 | + if (locationsChanged) { |
410 | tbMap.map.fitBounds(bounds); | 410 | tbMap.map.fitBounds(bounds); |
411 | } | 411 | } |
412 | } | 412 | } |
@@ -448,10 +448,10 @@ export default class TbMapWidget { | @@ -448,10 +448,10 @@ export default class TbMapWidget { | ||
448 | resize() { | 448 | resize() { |
449 | if (this.map && this.map.inited()) { | 449 | if (this.map && this.map.inited()) { |
450 | this.map.invalidateSize(); | 450 | this.map.invalidateSize(); |
451 | - if (!this.dontFitMapBounds && this.locations && this.locations.size > 0) { | 451 | + if (this.locations && this.locations.size > 0) { |
452 | var bounds = this.map.createBounds(); | 452 | var bounds = this.map.createBounds(); |
453 | for (var m in this.markers) { | 453 | for (var m in this.markers) { |
454 | - bounds.extend(this.map.getMarkerPosition(this.markers[m])); | 454 | + this.map.extendBoundsWithMarker(bounds, this.markers[m]); |
455 | } | 455 | } |
456 | if (this.polylines) { | 456 | if (this.polylines) { |
457 | for (var p in this.polylines) { | 457 | for (var p in this.polylines) { |
@@ -146,25 +146,30 @@ export default class TbOpenStreetMap { | @@ -146,25 +146,30 @@ export default class TbOpenStreetMap { | ||
146 | } | 146 | } |
147 | 147 | ||
148 | fitBounds(bounds) { | 148 | fitBounds(bounds) { |
149 | - var tbMap = this; | ||
150 | - this.map.once('zoomend', function() { | ||
151 | - var newZoomLevel = tbMap.map.getZoom(); | ||
152 | - if (tbMap.dontFitMapBounds && tbMap.defaultZoomLevel) { | ||
153 | - newZoomLevel = tbMap.defaultZoomLevel; | ||
154 | - } | ||
155 | - tbMap.map.setZoom(newZoomLevel, {animate: false}); | ||
156 | - | ||
157 | - if (!tbMap.defaultZoomLevel && tbMap.map.getZoom() > tbMap.minZoomLevel) { | ||
158 | - tbMap.map.setZoom(tbMap.minZoomLevel, {animate: false}); | 149 | + if (bounds.isValid()) { |
150 | + if (this.dontFitMapBounds && this.defaultZoomLevel) { | ||
151 | + this.map.setZoom(this.defaultZoomLevel, {animate: false}); | ||
152 | + this.map.panTo(bounds.getCenter(), {animate: false}); | ||
153 | + } else { | ||
154 | + var tbMap = this; | ||
155 | + this.map.once('zoomend', function() { | ||
156 | + if (!tbMap.defaultZoomLevel && tbMap.map.getZoom() > tbMap.minZoomLevel) { | ||
157 | + tbMap.map.setZoom(tbMap.minZoomLevel, {animate: false}); | ||
158 | + } | ||
159 | + }); | ||
160 | + this.map.fitBounds(bounds, {padding: [50, 50], animate: false}); | ||
159 | } | 161 | } |
160 | - }); | ||
161 | - this.map.fitBounds(bounds, {padding: [50, 50], animate: false}); | 162 | + } |
162 | } | 163 | } |
163 | 164 | ||
164 | createLatLng(lat, lng) { | 165 | createLatLng(lat, lng) { |
165 | return L.latLng(lat, lng); | 166 | return L.latLng(lat, lng); |
166 | } | 167 | } |
167 | 168 | ||
169 | + extendBoundsWithMarker(bounds, marker) { | ||
170 | + bounds.extend(marker.getLatLng()); | ||
171 | + } | ||
172 | + | ||
168 | getMarkerPosition(marker) { | 173 | getMarkerPosition(marker) { |
169 | return marker.getLatLng(); | 174 | return marker.getLatLng(); |
170 | } | 175 | } |