Browse Source

UI: Improve data simulation performance. Improve processing of default zoom level by map widgets.

pull/78/head
Igor Kulikov 10 years ago
parent
commit
5f606912fc
  1. 59
      ui/src/app/api/data-aggregator.js
  2. 39
      ui/src/app/api/datasource.service.js
  3. 31
      ui/src/app/widget/lib/google-map.js
  4. 10
      ui/src/app/widget/lib/map-widget.js
  5. 29
      ui/src/app/widget/lib/openstreet-map.js

59
ui/src/app/api/data-aggregator.js

@ -19,6 +19,10 @@ export default class DataAggregator {
constructor(onDataCb, tsKeyNames, startTs, limit, aggregationType, timeWindow, interval, types, $timeout, $filter) { constructor(onDataCb, tsKeyNames, startTs, limit, aggregationType, timeWindow, interval, types, $timeout, $filter) {
this.onDataCb = onDataCb; this.onDataCb = onDataCb;
this.tsKeyNames = tsKeyNames; this.tsKeyNames = tsKeyNames;
this.dataBuffer = {};
for (var k in tsKeyNames) {
this.dataBuffer[tsKeyNames[k]] = [];
}
this.startTs = startTs; this.startTs = startTs;
this.aggregationType = aggregationType; this.aggregationType = aggregationType;
this.types = types; this.types = types;
@ -120,11 +124,11 @@ export default class DataAggregator {
if (delta || !this.data) { if (delta || !this.data) {
this.startTs += delta * this.interval; this.startTs += delta * this.interval;
this.endTs += delta * this.interval; this.endTs += delta * this.interval;
this.data = toData(this.tsKeyNames, this.aggregationMap, this.startTs, this.endTs, this.$filter, this.limit); this.data = this.updateData();
this.elapsed = this.elapsed - delta * this.interval; this.elapsed = this.elapsed - delta * this.interval;
} }
} else { } else {
this.data = toData(this.tsKeyNames, this.aggregationMap, this.startTs, this.endTs, this.$filter, this.limit); this.data = this.updateData();
} }
if (this.onDataCb) { if (this.onDataCb) {
this.onDataCb(this.data, this.startTs, this.endTs, apply); this.onDataCb(this.data, this.startTs, this.endTs, apply);
@ -138,6 +142,31 @@ export default class DataAggregator {
} }
} }
updateData() {
for (var k in this.tsKeyNames) {
this.dataBuffer[this.tsKeyNames[k]] = [];
}
for (var key in this.aggregationMap) {
var aggKeyData = this.aggregationMap[key];
var keyData = this.dataBuffer[key];
for (var aggTimestamp in aggKeyData) {
if (aggTimestamp <= this.startTs) {
delete aggKeyData[aggTimestamp];
} else if (aggTimestamp <= this.endTs) {
var aggData = aggKeyData[aggTimestamp];
var kvPair = [Number(aggTimestamp), aggData.aggValue];
keyData.push(kvPair);
}
}
keyData = this.$filter('orderBy')(keyData, '+this[0]');
if (keyData.length > this.limit) {
keyData = keyData.slice(keyData.length - this.limit);
}
this.dataBuffer[key] = keyData;
}
return this.dataBuffer;
}
destroy() { destroy() {
if (this.intervalTimeoutHandle) { if (this.intervalTimeoutHandle) {
this.$timeout.cancel(this.intervalTimeoutHandle); this.$timeout.cancel(this.intervalTimeoutHandle);
@ -208,32 +237,6 @@ function updateAggregatedData(aggregationMap, isCount, noAggregation, aggFunctio
} }
} }
function toData(tsKeyNames, aggregationMap, startTs, endTs, $filter, limit) {
var data = {};
for (var k in tsKeyNames) {
data[tsKeyNames[k]] = [];
}
for (var key in aggregationMap) {
var aggKeyData = aggregationMap[key];
var keyData = data[key];
for (var aggTimestamp in aggKeyData) {
if (aggTimestamp <= startTs) {
delete aggKeyData[aggTimestamp];
} else if (aggTimestamp <= endTs) {
var aggData = aggKeyData[aggTimestamp];
var kvPair = [Number(aggTimestamp), aggData.aggValue];
keyData.push(kvPair);
}
}
keyData = $filter('orderBy')(keyData, '+this[0]');
if (keyData.length > limit) {
keyData = keyData.slice(keyData.length - limit);
}
data[key] = keyData;
}
return data;
}
function convertValue(value, noAggregation) { function convertValue(value, noAggregation) {
if (!noAggregation || value && isNumeric(value)) { if (!noAggregation || value && isNumeric(value)) {
return Number(value); return Number(value);

39
ui/src/app/api/datasource.service.js

@ -110,6 +110,8 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
datasourceSubscription.subscriptionTimewindow.realtimeWindowMs; datasourceSubscription.subscriptionTimewindow.realtimeWindowMs;
var timer; var timer;
var frequency; var frequency;
var tickElapsed = 0;
var tickScheduledTime = 0;
var dataAggregator; var dataAggregator;
var subscription = { var subscription = {
@ -353,11 +355,14 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
} }
dataAggregator = createRealtimeDataAggregator(subsTw, tsKeyNames, types.dataKeyType.function); dataAggregator = createRealtimeDataAggregator(subsTw, tsKeyNames, types.dataKeyType.function);
} }
tickScheduledTime = currentTime();
if (history) { if (history) {
onTick(false); onTick(false);
} else { } else {
timer = $timeout( timer = $timeout(
function() {onTick(true)}, function() {
onTick(true)
},
0, 0,
false false
); );
@ -393,6 +398,7 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
function unsubscribe() { function unsubscribe() {
if (timer) { if (timer) {
$timeout.cancel(timer); $timeout.cancel(timer);
timer = null;
} }
if (datasourceType === types.datasourceType.device) { if (datasourceType === types.datasourceType.device) {
for (var cmdId in subscribers) { for (var cmdId in subscribers) {
@ -456,15 +462,39 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
} }
} }
/* eslint-disable */
function currentTime() {
return window.performance && window.performance.now ?
window.performance.now() : Date.now();
}
/* eslint-enable */
function onTick(apply) { function onTick(apply) {
var now = currentTime();
tickElapsed += now - tickScheduledTime;
tickScheduledTime = now;
if (timer) {
$timeout.cancel(timer);
timer = null;
}
var key; var key;
if (datasourceSubscription.type === types.widgetType.timeseries.value) { if (datasourceSubscription.type === types.widgetType.timeseries.value) {
var startTime; var startTime;
var endTime; var endTime;
var delta;
var generatedData = { var generatedData = {
data: { data: {
} }
}; };
if (!history) {
delta = Math.floor(tickElapsed / frequency);
}
var deltaElapsed = history ? frequency : delta * frequency;
tickElapsed = tickElapsed - deltaElapsed;
for (key in dataKeys) { for (key in dataKeys) {
var dataKeyList = dataKeys[key]; var dataKeyList = dataKeys[key];
for (var index = 0; index < dataKeyList.length; index ++) { for (var index = 0; index < dataKeyList.length; index ++) {
@ -472,11 +502,12 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
if (!startTime) { if (!startTime) {
if (realtime) { if (realtime) {
if (dataKey.lastUpdateTime) { if (dataKey.lastUpdateTime) {
startTime = dataKey.lastUpdateTime + frequency startTime = dataKey.lastUpdateTime + frequency;
endTime = dataKey.lastUpdateTime + deltaElapsed;
} else { } else {
startTime = datasourceSubscription.subscriptionTimewindow.startTs; startTime = datasourceSubscription.subscriptionTimewindow.startTs;
endTime = startTime + datasourceSubscription.subscriptionTimewindow.realtimeWindowMs + frequency;
} }
endTime = startTime + datasourceSubscription.subscriptionTimewindow.realtimeWindowMs;
} else { } else {
startTime = datasourceSubscription.subscriptionTimewindow.fixedWindow.startTimeMs; startTime = datasourceSubscription.subscriptionTimewindow.fixedWindow.startTimeMs;
endTime = datasourceSubscription.subscriptionTimewindow.fixedWindow.endTimeMs; endTime = datasourceSubscription.subscriptionTimewindow.fixedWindow.endTimeMs;
@ -494,7 +525,7 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
} }
if (!history) { if (!history) {
timer = $timeout(function() {onTick(true)}, frequency / 2, false); timer = $timeout(function() {onTick(true)}, frequency, false);
} }
} }

31
ui/src/app/widget/lib/google-map.js

@ -246,26 +246,31 @@ export default class TbGoogleMap {
} }
/* eslint-enable no-undef */ /* eslint-enable no-undef */
/* eslint-disable no-undef */
fitBounds(bounds) { fitBounds(bounds) {
var tbMap = this; if (this.dontFitMapBounds && this.defaultZoomLevel) {
google.maps.event.addListenerOnce(this.map, 'bounds_changed', function() { // eslint-disable-line no-undef this.map.setZoom(this.defaultZoomLevel);
var newZoomLevel = tbMap.map.getZoom(); this.map.setCenter(bounds.getCenter());
if (tbMap.dontFitMapBounds && tbMap.defaultZoomLevel) { } else {
newZoomLevel = tbMap.defaultZoomLevel; var tbMap = this;
} google.maps.event.addListenerOnce(this.map, 'bounds_changed', function() { // eslint-disable-line no-undef
tbMap.map.setZoom(newZoomLevel); if (!tbMap.defaultZoomLevel && tbMap.map.getZoom() > tbMap.minZoomLevel) {
tbMap.map.setZoom(tbMap.minZoomLevel);
if (!tbMap.defaultZoomLevel && tbMap.map.getZoom() > tbMap.minZoomLevel) { }
tbMap.map.setZoom(tbMap.minZoomLevel); });
} this.map.fitBounds(bounds);
}); }
this.map.fitBounds(bounds);
} }
/* eslint-enable no-undef */
createLatLng(lat, lng) { createLatLng(lat, lng) {
return new google.maps.LatLng(lat, lng); // eslint-disable-line no-undef return new google.maps.LatLng(lat, lng); // eslint-disable-line no-undef
} }
extendBoundsWithMarker(bounds, marker) {
bounds.extend(marker.getPosition());
}
getMarkerPosition(marker) { getMarkerPosition(marker) {
return marker.getPosition(); return marker.getPosition();
} }

10
ui/src/app/widget/lib/map-widget.js

@ -386,7 +386,7 @@ export default class TbMapWidget {
if (location.polyline) { if (location.polyline) {
tbMap.map.extendBounds(bounds, location.polyline); tbMap.map.extendBounds(bounds, location.polyline);
} else if (location.marker) { } else if (location.marker) {
bounds.extend(tbMap.map.getMarkerPosition(location.marker)); tbMap.map.extendBoundsWithMarker(bounds, location.marker);
} }
} }
} }
@ -403,10 +403,10 @@ export default class TbMapWidget {
if (location.polyline) { if (location.polyline) {
tbMap.map.extendBounds(bounds, location.polyline); tbMap.map.extendBounds(bounds, location.polyline);
} else if (location.marker) { } else if (location.marker) {
bounds.extend(tbMap.map.getMarkerPosition(location.marker)); tbMap.map.extendBoundsWithMarker(bounds, location.marker);
} }
} }
if (!tbMap.dontFitMapBounds && locationsChanged) { if (locationsChanged) {
tbMap.map.fitBounds(bounds); tbMap.map.fitBounds(bounds);
} }
} }
@ -448,10 +448,10 @@ export default class TbMapWidget {
resize() { resize() {
if (this.map && this.map.inited()) { if (this.map && this.map.inited()) {
this.map.invalidateSize(); this.map.invalidateSize();
if (!this.dontFitMapBounds && this.locations && this.locations.size > 0) { if (this.locations && this.locations.size > 0) {
var bounds = this.map.createBounds(); var bounds = this.map.createBounds();
for (var m in this.markers) { for (var m in this.markers) {
bounds.extend(this.map.getMarkerPosition(this.markers[m])); this.map.extendBoundsWithMarker(bounds, this.markers[m]);
} }
if (this.polylines) { if (this.polylines) {
for (var p in this.polylines) { for (var p in this.polylines) {

29
ui/src/app/widget/lib/openstreet-map.js

@ -146,25 +146,30 @@ export default class TbOpenStreetMap {
} }
fitBounds(bounds) { fitBounds(bounds) {
var tbMap = this; if (bounds.isValid()) {
this.map.once('zoomend', function() { if (this.dontFitMapBounds && this.defaultZoomLevel) {
var newZoomLevel = tbMap.map.getZoom(); this.map.setZoom(this.defaultZoomLevel, {animate: false});
if (tbMap.dontFitMapBounds && tbMap.defaultZoomLevel) { this.map.panTo(bounds.getCenter(), {animate: false});
newZoomLevel = tbMap.defaultZoomLevel; } else {
} var tbMap = this;
tbMap.map.setZoom(newZoomLevel, {animate: false}); this.map.once('zoomend', function() {
if (!tbMap.defaultZoomLevel && tbMap.map.getZoom() > tbMap.minZoomLevel) {
if (!tbMap.defaultZoomLevel && tbMap.map.getZoom() > tbMap.minZoomLevel) { tbMap.map.setZoom(tbMap.minZoomLevel, {animate: false});
tbMap.map.setZoom(tbMap.minZoomLevel, {animate: false}); }
});
this.map.fitBounds(bounds, {padding: [50, 50], animate: false});
} }
}); }
this.map.fitBounds(bounds, {padding: [50, 50], animate: false});
} }
createLatLng(lat, lng) { createLatLng(lat, lng) {
return L.latLng(lat, lng); return L.latLng(lat, lng);
} }
extendBoundsWithMarker(bounds, marker) {
bounds.extend(marker.getLatLng());
}
getMarkerPosition(marker) { getMarkerPosition(marker) {
return marker.getLatLng(); return marker.getLatLng();
} }

Loading…
Cancel
Save