You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.9 KiB
154 lines
5.9 KiB
import { Component, AfterViewInit, ViewChild, ElementRef, OnInit } from '@angular/core';
|
|
|
|
import { environment } from '@env/environment';
|
|
|
|
import * as mapboxgl from 'mapbox-gl';
|
|
import { LogsService } from '@app/logs.service';
|
|
|
|
import { interval } from 'rxjs';
|
|
|
|
@Component({
|
|
selector: 'app-map',
|
|
templateUrl: './map.component.html',
|
|
styleUrls: ['./map.component.scss']
|
|
})
|
|
export class MapComponent implements OnInit {
|
|
// Global map object
|
|
map: mapboxgl.Map;
|
|
|
|
// Style of the map we'll be loading.
|
|
// Can also be 'mapbox://styles/mapbox/satellite-v9' for a satellite map
|
|
style = 'mapbox://styles/mapbox/streets-v11';
|
|
|
|
// Coordinates for the location we're going to focus initially.
|
|
// In this case Athens, Greece.
|
|
lat = 37.9838;
|
|
lng = 23.7275;
|
|
|
|
// The subscribe object for the rxjs interval
|
|
sub: any;
|
|
|
|
// The last point we've added to the map.
|
|
// It's going to be a two element array, one for longitude and one for latitude.
|
|
lastPoint: number[];
|
|
|
|
// The maximum number of points to display on the first load.
|
|
// This will be the last X points we get from the logs API.
|
|
pointsToDisplay = 10;
|
|
|
|
// The number of displayed points in the map
|
|
// and how many we've ommited in order to increase performance
|
|
displayedPoints: number = 0;
|
|
ommitedPoints: number = 0;
|
|
|
|
constructor(private logsService: LogsService) {}
|
|
|
|
async ngOnInit() {
|
|
// Load access token into the mapboxx object
|
|
Object.getOwnPropertyDescriptor(mapboxgl, 'accessToken').set(environment.mapbox.accessToken);
|
|
// Create map on the #map div
|
|
this.map = new mapboxgl.Map({
|
|
container: 'map',
|
|
style: this.style,
|
|
center: [this.lng, this.lat],
|
|
zoom: 9
|
|
});
|
|
|
|
// Check to see if it's the first run of the component
|
|
var firstRun: Boolean = true;
|
|
|
|
// Run every second
|
|
this.sub = interval(1000).subscribe(async val => {
|
|
// If it's the first time we run this or if live updates are enabled (firstTime overides liveUpdate)
|
|
if (this.logsService.liveUpdate || firstRun) {
|
|
let data: Array<Object>;
|
|
if (firstRun) {
|
|
// Get logs for the first time
|
|
data = await this.logsService.getLogsFirstRun();
|
|
// Since we got our data, set firstRun to false
|
|
firstRun = false;
|
|
// If we get more data than the maximum allowed displayed points,
|
|
// ommit the excess data points and keep the count of how many points we ommited.
|
|
if (data.length > this.pointsToDisplay) {
|
|
this.ommitedPoints = data.length - this.pointsToDisplay;
|
|
data = data.slice(data.length - this.pointsToDisplay, data.length);
|
|
}
|
|
} else {
|
|
// If this is not the first time we run this, get only the changes since the last time we got the logs
|
|
data = await this.logsService.getUpdates();
|
|
}
|
|
|
|
// Here we are now getting new points every second.
|
|
// Those will be added on top of the maximum loaded points
|
|
// so we should keep count of how many points we're adding so we can display
|
|
// the number of displayed points on the map.
|
|
|
|
// Initialize new point counter.
|
|
// This will decide if we actually got any new points
|
|
// and whether we actually have to fly to the new marker in the map.
|
|
let newPointsCount = 0;
|
|
// Add the number of data points we got to the number of displayed points
|
|
this.displayedPoints = this.displayedPoints + data.length;
|
|
|
|
// For every log we got
|
|
for (let log of data) {
|
|
// We only add markers for logs with valid GPS data, aka only status == A.
|
|
if (log['gps_data']['status'] == 'A') {
|
|
// We got a new valid point to add a marker for.
|
|
// This means we'll have to fly to it.
|
|
// Increase the relevant counter.
|
|
newPointsCount++;
|
|
|
|
// Some dirty templating for the data inside the popup box.
|
|
// This should normally be done in a new component but yeah...
|
|
|
|
// Here we will display the sensor readings for the specific log,
|
|
// as well as it's date and time.
|
|
|
|
// Those are going to be displayed withing an HTML table.
|
|
// Create the table and add the header.
|
|
let html =
|
|
log['gps_data']['datestamp'] +
|
|
' ' +
|
|
log['gps_data']['timestamp'] +
|
|
'<br><table><tr><th>Sensor </th><th>Reading</th></tr>';
|
|
// Add tr with name and value for every sensor
|
|
for (let record in log['sensorReadings']) {
|
|
if (Object.prototype.hasOwnProperty.call(log['sensorReadings'], record)) {
|
|
html += '<tr><td>' + record + '</td>' + '<td>' + log['sensorReadings'][record] + '</td></tr>';
|
|
}
|
|
}
|
|
|
|
// Finally, add the table closing tag.
|
|
html += '</table>';
|
|
|
|
// Create a new popup with the HTML code we created above
|
|
var popup = new mapboxgl.Popup({ offset: 25 }).setHTML(html);
|
|
|
|
// Create a new marker on the log location and attach the newly created popup to it
|
|
var marker = new mapboxgl.Marker({
|
|
draggable: false
|
|
})
|
|
.setLngLat([log['gps_data']['longitude'], log['gps_data']['latitude']])
|
|
.setPopup(popup)
|
|
.addTo(this.map);
|
|
|
|
// When we are adding multiple markers, we need a way to keep track of the last one,
|
|
// in order to be able to fly to it. That's what we'll be doing here.
|
|
this.lastPoint = [log['gps_data']['longitude'], log['gps_data']['latitude']];
|
|
}
|
|
}
|
|
|
|
// If we got any new markers
|
|
if (newPointsCount) {
|
|
// fly to the last marker we added.
|
|
this.map.flyTo({
|
|
center: [this.lastPoint[0], this.lastPoint[1]],
|
|
essential: true, // this animation is considered essential with respect to prefers-reduced-motion
|
|
zoom: 22
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|