Add toggle visibility of markers of each device on map and select age of markers to show on map (#6)
This commit is contained in:
parent
0e61599269
commit
58afb30780
5 changed files with 97 additions and 21 deletions
|
@ -26,6 +26,8 @@ Successfully built this on the Raspberry Pi (Raspbian Buster) and a desktop PC (
|
||||||
- Measuring tool for measure distances between points
|
- Measuring tool for measure distances between points
|
||||||
- Map stays focused on the same point across page refreshes
|
- Map stays focused on the same point across page refreshes
|
||||||
- Clicking gateway or data point markers pops up information about them
|
- Clicking gateway or data point markers pops up information about them
|
||||||
|
- Toggle visibility of markers of each device on map
|
||||||
|
- Select age of markers to show on map
|
||||||
|
|
||||||
### TODO
|
### TODO
|
||||||
|
|
||||||
|
@ -40,19 +42,20 @@ Make sure you have your application set up on The Things Network with the integr
|
||||||
### Install dependencies
|
### Install dependencies
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo apt-get install libffi-dev libssl-dev
|
sudo apt-get install -y libffi-dev libssl-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install docker and docker-compose
|
### Install docker and docker-compose
|
||||||
|
|
||||||
```
|
```
|
||||||
curl -sSL https://get.docker.com | sh
|
curl -sSL https://get.docker.com | sh
|
||||||
sudo pip install docker-compose
|
sudo apt-get install -y python3 python3-pip
|
||||||
|
sudo pip3 install docker-compose
|
||||||
```
|
```
|
||||||
|
|
||||||
### Add user to docker group
|
### Add user to docker group
|
||||||
|
|
||||||
```sudo usermod -a -G docker YOUR_USER```
|
```sudo usermod -a -G docker $USER```
|
||||||
|
|
||||||
Then log out and back in again.
|
Then log out and back in again.
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,13 @@ RUN mkdir -pv /home/project/flask_app
|
||||||
RUN mkdir -pv /var/ttn_tracker/ssl_certs
|
RUN mkdir -pv /var/ttn_tracker/ssl_certs
|
||||||
|
|
||||||
WORKDIR /home/project/flask_app
|
WORKDIR /home/project/flask_app
|
||||||
COPY requirements.txt /home/project/flask_app
|
|
||||||
RUN pip install --upgrade pip
|
RUN pip install --upgrade pip
|
||||||
|
|
||||||
|
COPY requirements.txt /home/project/flask_app
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
COPY . /home/project/flask_app
|
COPY ssl-certs-generate.sh /home/project/flask_app/ssl-certs-generate.sh
|
||||||
|
|
||||||
RUN /bin/bash /home/project/flask_app/ssl-certs-generate.sh
|
RUN /bin/bash /home/project/flask_app/ssl-certs-generate.sh
|
||||||
|
|
||||||
|
COPY . /home/project/flask_app
|
||||||
|
|
|
@ -9,6 +9,12 @@ from math import sqrt
|
||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
from apscheduler.schedulers.background import BackgroundScheduler
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
|
from dateutil.parser import parser
|
||||||
|
from flask import Flask
|
||||||
|
from flask import jsonify
|
||||||
|
from flask import render_template
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
|
||||||
from config import app_key
|
from config import app_key
|
||||||
from config import application
|
from config import application
|
||||||
from config import bing_api_key
|
from config import bing_api_key
|
||||||
|
@ -19,11 +25,6 @@ from config import path_db
|
||||||
from config import refresh_period_seconds
|
from config import refresh_period_seconds
|
||||||
from config import start_lat
|
from config import start_lat
|
||||||
from config import start_lon
|
from config import start_lon
|
||||||
from dateutil.parser import parser
|
|
||||||
from flask import Flask
|
|
||||||
from flask import jsonify
|
|
||||||
from flask import render_template
|
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -90,6 +91,7 @@ def main_page():
|
||||||
get_new_data()
|
get_new_data()
|
||||||
return render_template('map.html',
|
return render_template('map.html',
|
||||||
bing_api_key=bing_api_key,
|
bing_api_key=bing_api_key,
|
||||||
|
devices=devices,
|
||||||
gateway_locations=gateway_locations,
|
gateway_locations=gateway_locations,
|
||||||
location_data=Location.query.all(),
|
location_data=Location.query.all(),
|
||||||
refresh_period_seconds=refresh_period_seconds,
|
refresh_period_seconds=refresh_period_seconds,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
apscheduler
|
apscheduler==3.6.3
|
||||||
python-dateutil
|
python-dateutil==2.8.1
|
||||||
gunicorn
|
gunicorn==20.0.4
|
||||||
Flask==1.1.1
|
Flask==1.1.2
|
||||||
flask_sqlalchemy
|
flask_sqlalchemy==2.4.4
|
||||||
requests
|
requests==2.25.1
|
||||||
|
|
|
@ -58,8 +58,7 @@
|
||||||
var default_zoom = true;
|
var default_zoom = true;
|
||||||
|
|
||||||
b = JSON.parse(localStorage.getItem('bounds'));
|
b = JSON.parse(localStorage.getItem('bounds'));
|
||||||
if (b == null)
|
if (b == null) {
|
||||||
{
|
|
||||||
map = L.map('mapid', {layers: [esri_Map]}).setView([{{start_lat}}, {{start_lon}}], 15);
|
map = L.map('mapid', {layers: [esri_Map]}).setView([{{start_lat}}, {{start_lon}}], 15);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -78,7 +77,6 @@
|
||||||
//disable inertia because it is irritating and slow
|
//disable inertia because it is irritating and slow
|
||||||
map.options.inertia=false;
|
map.options.inertia=false;
|
||||||
|
|
||||||
|
|
||||||
var measureControl = L.control.measure({
|
var measureControl = L.control.measure({
|
||||||
activeColor: '#FF0000',
|
activeColor: '#FF0000',
|
||||||
completedColor: '#FF8000',
|
completedColor: '#FF8000',
|
||||||
|
@ -112,6 +110,53 @@
|
||||||
var gateway = L.marker([{{each_gateway[1]}}, {{each_gateway[2]}}]).bindPopup('Gateway: {{each_gateway[0]}}<br />Lat/Lon: {{each_gateway[1]}}, {{each_gateway[2]}}').addTo(map);
|
var gateway = L.marker([{{each_gateway[1]}}, {{each_gateway[2]}}]).bindPopup('Gateway: {{each_gateway[0]}}<br />Lat/Lon: {{each_gateway[1]}}, {{each_gateway[2]}}').addTo(map);
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
var markers = {};
|
||||||
|
{% for each_device in devices %}
|
||||||
|
markers['{{each_device}}'] = new L.FeatureGroup();
|
||||||
|
map.addLayer(markers['{{each_device}}']);
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
var legend_age = L.control({position: 'topright'});
|
||||||
|
legend_age.onAdd = function(map) {
|
||||||
|
var div = L.DomUtil.create('div', 'info legend_age');
|
||||||
|
div.innerHTML = '<select>' +
|
||||||
|
'<option value="7day">Past 7 Days</option>' +
|
||||||
|
'<option value="1day">Past 1 Day</option>' +
|
||||||
|
'<option value="6hour">Past 6 Hours</option>' +
|
||||||
|
'<option value="1hour">Past 1 Hour</option>' +
|
||||||
|
'<option value="30min">Past 30 Min</option>' +
|
||||||
|
'</select>';
|
||||||
|
div.firstChild.onmousedown = div.firstChild.ondblclick = L.DomEvent.stopPropagation;
|
||||||
|
return div;
|
||||||
|
};
|
||||||
|
legend_age.addTo(map);
|
||||||
|
|
||||||
|
function toggleFunction(element) {
|
||||||
|
if (element.checked) {
|
||||||
|
map.addLayer(markers[element.value]);
|
||||||
|
} else {
|
||||||
|
map.removeLayer(markers[element.value]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var legend_devices = L.control({position: 'topright'});
|
||||||
|
legend_devices.onAdd = function(map) {
|
||||||
|
var div = L.DomUtil.create('div');
|
||||||
|
div.innerHTML = `
|
||||||
|
<div class="leaflet-control-layers leaflet-control-layers-expanded">
|
||||||
|
<form>
|
||||||
|
{% for each_device in devices -%}
|
||||||
|
<div>
|
||||||
|
<input class="leaflet-control-layers-overlays" id="command"
|
||||||
|
onclick=toggleFunction(this) type="checkbox" value="{{each_device}}" checked>{{each_device}}</input>
|
||||||
|
</div>
|
||||||
|
{%- endfor %}
|
||||||
|
</form>
|
||||||
|
</div>`;
|
||||||
|
return div;
|
||||||
|
};
|
||||||
|
legend_devices.addTo(map);
|
||||||
|
|
||||||
function add_new_markers(past_seconds) {
|
function add_new_markers(past_seconds) {
|
||||||
var url = '/dsf673bh_past/' + past_seconds;
|
var url = '/dsf673bh_past/' + past_seconds;
|
||||||
$.getJSON(url,
|
$.getJSON(url,
|
||||||
|
@ -121,13 +166,36 @@
|
||||||
var node = L.circleMarker([parseFloat(data[i]["latitude"]), parseFloat(data[i]["longitude"])], {
|
var node = L.circleMarker([parseFloat(data[i]["latitude"]), parseFloat(data[i]["longitude"])], {
|
||||||
color: 'red',
|
color: 'red',
|
||||||
radius: 5
|
radius: 5
|
||||||
}).bindPopup('Node: ' + data[i]["device_id"] + '<br />' + data[i]["datetime"] + '<br />Lat/Lon: ' + data[i]["latitude"] + ', ' + data[i]["longitude"] + '<br />Altitude: ' + data[i]["altitude"] + ' m, hdop: ' + data[i]["hdop"]).addTo(map);
|
});
|
||||||
|
node.bindPopup('Node: ' + data[i]["device_id"] + '<br />' + data[i]["datetime"] + '<br />Lat/Lon: ' + data[i]["latitude"] + ', ' + data[i]["longitude"] + '<br />Altitude: ' + data[i]["altitude"] + ' m, hdop: ' + data[i]["hdop"]);
|
||||||
|
markers[data[i]["device_id"]].addLayer(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$('select').change(function(){
|
||||||
|
for (var key in markers) {
|
||||||
|
map.removeLayer(markers[key]);
|
||||||
|
markers[key] = new L.FeatureGroup();
|
||||||
|
map.addLayer(markers[key]);
|
||||||
|
}
|
||||||
|
if ($(this).val() === "all") {
|
||||||
|
add_new_markers(0);
|
||||||
|
} else if ($(this).val() === "7day") {
|
||||||
|
add_new_markers(604800);
|
||||||
|
} else if ($(this).val() === "1day") {
|
||||||
|
add_new_markers(86400);
|
||||||
|
} else if ($(this).val() === "6hour") {
|
||||||
|
add_new_markers(21600);
|
||||||
|
} else if ($(this).val() === "1hour") {
|
||||||
|
add_new_markers(3600);
|
||||||
|
} else if ($(this).val() === "30min") {
|
||||||
|
add_new_markers(1800);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Repeat function for getLastData()
|
// Repeat function for getLastData()
|
||||||
function repeat_add_new_markers(past_seconds) {
|
function repeat_add_new_markers(past_seconds) {
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
|
|
Loading…
Add table
Reference in a new issue