kopia lustrzana https://github.com/projecthorus/chasemapper
Add tile server capability.
rodzic
24a4ac161f
commit
7350a85938
15
README.md
15
README.md
|
@ -61,9 +61,20 @@ At the moment Chasemapper only supports receiving chase-car positions via Horus
|
||||||
Eventually support will be added to get car positions from either GPSD, or from the client's device.
|
Eventually support will be added to get car positions from either GPSD, or from the client's device.
|
||||||
|
|
||||||
|
|
||||||
## Offline Mapping
|
## Offline Mapping via FoxtrotGPS's Tile Cache
|
||||||
(This is a work in progress)
|
(This is a work in progress)
|
||||||
By default Chasemapper is configured to use the online OSM and ESRI Satellite tileservers. There is also an 'offline OSM' entry in the map layer list (top right of the page), which attempt to gather maps from `http://server_ip:8080/roads/{z}/{x}/{y}.png`. I've been doing some testing with using [Tilestache](http://tilestache.org/) as a lightweight tileserver, serving tiles from mbtiles files. A guide on how to cache up OSM data for use with Tilestache is TBD...
|
Chasemapper can serve up map tiles from a specified directory to the web client. Of course, for this to be useful, we need map tiles to server! [FoxtrotGPS](https://www.foxtrotgps.org/) can help us with this, as it caches map tiles to `~/Maps/`, with one subdirectory per map layer (i.e. `~/Maps/OSM/`, `~/Maps/opencyclemap/`).
|
||||||
|
|
||||||
|
This can be enabled by setting `[offline_maps] tile_server_enabled = True`, and changing `[offline_maps] tile_server_path` to point to your tile cache directory (i.e. `/home/pi/Maps/`). Chasemapper will assume each subdirectory in this folder is a valid map layer and will add them to the map layer list at the top-right of the interface.
|
||||||
|
|
||||||
|
### Caching Maps
|
||||||
|
|
||||||
|
To grab map tiles to use with this, we're going to use FoxtrotGPS's [Cached Maps](https://www.foxtrotgps.org/doc/foxtrotgps.html#Cached-Maps) feature.
|
||||||
|
|
||||||
|
* Install FoxtrotGPS (Linux only unfortunately, works OK on a Pi!) either [from source](https://www.foxtrotgps.org/releases/), or via your system package manager (`sudo apt-get install foxtrotgps`).
|
||||||
|
* Load up FoxtrotGPS, and pan around the area you are intersted in caching. Pick the map layer you want, right-click on the map, and choose 'Map download'. You can then select how many zoom levels you want to cache, and start it downloading (this may take a while!)
|
||||||
|
* Once you have a set of folders within your `~/Maps` cache directory, you can startup Chasemapper and start using them! Tiles will be served up as they become available.
|
||||||
|
|
||||||
|
|
||||||
(If anyone has managed to get ECW support working in GDAL recently, please contact me! I would like to convert some topographic maps in ECW format to tiles for use with Chasemapper.)
|
(If anyone has managed to get ECW support working in GDAL recently, please contact me! I would like to convert some topographic maps in ECW format to tiles for use with Chasemapper.)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
# Released under GNU GPL v3 or later
|
# Released under GNU GPL v3 or later
|
||||||
#
|
#
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Python 2
|
# Python 2
|
||||||
|
@ -61,6 +62,19 @@ def parse_config_file(filename):
|
||||||
chase_config['pred_gfs_directory'] = config.get('predictor', 'gfs_directory')
|
chase_config['pred_gfs_directory'] = config.get('predictor', 'gfs_directory')
|
||||||
chase_config['pred_model_download'] = config.get('predictor', 'model_download')
|
chase_config['pred_model_download'] = config.get('predictor', 'model_download')
|
||||||
|
|
||||||
|
# Offline Map Settings
|
||||||
|
chase_config['tile_server_enabled'] = config.getboolean('offline_maps', 'tile_server_enabled')
|
||||||
|
chase_config['tile_server_port'] = config.getint('offline_maps', 'tile_server_port')
|
||||||
|
chase_config['tile_server_path'] = config.get('offline_maps', 'tile_server_path')
|
||||||
|
|
||||||
|
# Determine valid offline map layers.
|
||||||
|
chase_config['offline_tile_layers'] = []
|
||||||
|
if chase_config['tile_server_enabled']:
|
||||||
|
for _dir in os.listdir(chase_config['tile_server_path']):
|
||||||
|
if os.path.isdir(os.path.join(chase_config['tile_server_path'],_dir)):
|
||||||
|
chase_config['offline_tile_layers'].append(_dir)
|
||||||
|
logging.info("Found Map Layers: %s" % str(chase_config['offline_tile_layers']))
|
||||||
|
|
||||||
# Telemetry Source Profiles
|
# Telemetry Source Profiles
|
||||||
|
|
||||||
_profile_count = config.getint('profile_selection', 'profile_count')
|
_profile_count = config.getint('profile_selection', 'profile_count')
|
||||||
|
@ -121,6 +135,7 @@ def read_config(filename, default_cfg="horusmapper.cfg.example"):
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
|
logging.basicConfig(format='%(asctime)s %(levelname)s:%(message)s', stream=sys.stdout, level=logging.DEBUG)
|
||||||
print(read_config(sys.argv[1]))
|
print(read_config(sys.argv[1]))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -91,3 +91,22 @@ gfs_directory = ./gfs/
|
||||||
# The gfs directory (above) will be cleared of all .dat files prior to the above command being run.
|
# The gfs directory (above) will be cleared of all .dat files prior to the above command being run.
|
||||||
model_download = none
|
model_download = none
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Offline Tile Server
|
||||||
|
#
|
||||||
|
# Allows serving of map tiles from a directory.
|
||||||
|
# Each subdirectory is assumed to be a separate layer of map tiles, i.e. 'OSM', 'opencyclemap',
|
||||||
|
# and is added to the map interface as a separate layer.
|
||||||
|
# This feature can be used to serve up FoxtrotGPS's tile cache as layers, usually located in ~/Maps/
|
||||||
|
#
|
||||||
|
[offline_maps]
|
||||||
|
# Enable serving up maps from a directory of map tiles.
|
||||||
|
tile_server_enabled = False
|
||||||
|
|
||||||
|
# Path to map tiles. For FoxtrotGPS, this is usually ~/Maps/
|
||||||
|
# NOTE: This must be an ABSOLUTE directory, i.e. /home/pi/Maps/ - ~/Maps/ will not work.
|
||||||
|
tile_server_path = /home/pi/Maps/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import json
|
||||||
import logging
|
import logging
|
||||||
import flask
|
import flask
|
||||||
from flask_socketio import SocketIO
|
from flask_socketio import SocketIO
|
||||||
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
@ -48,6 +49,9 @@ data_listeners = []
|
||||||
# These settings are not editable by the client!
|
# These settings are not editable by the client!
|
||||||
pred_settings = {}
|
pred_settings = {}
|
||||||
|
|
||||||
|
# Offline map settings, again, not editable by the client.
|
||||||
|
map_settings = {'tile_server_enabled': False}
|
||||||
|
|
||||||
# Payload data Stores
|
# Payload data Stores
|
||||||
current_payloads = {} # Archive data which will be passed to the web client
|
current_payloads = {} # Archive data which will be passed to the web client
|
||||||
current_payload_tracks = {} # Store of payload Track objects which are used to calculate instantaneous parameters.
|
current_payload_tracks = {} # Store of payload Track objects which are used to calculate instantaneous parameters.
|
||||||
|
@ -75,6 +79,19 @@ def flask_get_telemetry_archive():
|
||||||
def flask_get_config():
|
def flask_get_config():
|
||||||
return json.dumps(chasemapper_config)
|
return json.dumps(chasemapper_config)
|
||||||
|
|
||||||
|
@app.route("/tiles/<path:filename>")
|
||||||
|
def flask_server_tiles(filename):
|
||||||
|
""" Serve up a file from the tile server location """
|
||||||
|
global map_settings
|
||||||
|
if map_settings['tile_server_enabled']:
|
||||||
|
_filename = flask.safe_join(map_settings['tile_server_path'], filename)
|
||||||
|
if os.path.isfile(_filename):
|
||||||
|
return flask.send_file(_filename)
|
||||||
|
else:
|
||||||
|
flask.abort(404)
|
||||||
|
else:
|
||||||
|
flask.abort(404)
|
||||||
|
|
||||||
|
|
||||||
def flask_emit_event(event_name="none", data={}):
|
def flask_emit_event(event_name="none", data={}):
|
||||||
""" Emit a socketio event to any clients. """
|
""" Emit a socketio event to any clients. """
|
||||||
|
@ -692,6 +709,12 @@ if __name__ == "__main__":
|
||||||
'pred_model_download': chasemapper_config['pred_model_download']
|
'pred_model_download': chasemapper_config['pred_model_download']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Copy out Offline Map Settings
|
||||||
|
map_settings = {
|
||||||
|
'tile_server_enabled': chasemapper_config['tile_server_enabled'],
|
||||||
|
'tile_server_path': chasemapper_config['tile_server_path']
|
||||||
|
}
|
||||||
|
|
||||||
# Start listeners using the default profile selection.
|
# Start listeners using the default profile selection.
|
||||||
start_listeners(chasemapper_config['profiles'][chasemapper_config['selected_profile']])
|
start_listeners(chasemapper_config['profiles'][chasemapper_config['selected_profile']])
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
pred_update_rate: 15,
|
pred_update_rate: 15,
|
||||||
pred_model: 'Disabled',
|
pred_model: 'Disabled',
|
||||||
show_abort: true, // Show a prediction of an 'abort' paths (i.e. if the balloon bursts *now*)
|
show_abort: true, // Show a prediction of an 'abort' paths (i.e. if the balloon bursts *now*)
|
||||||
|
offline_tile_layers: []
|
||||||
};
|
};
|
||||||
|
|
||||||
// Object which will contain balloon markers and traces.
|
// Object which will contain balloon markers and traces.
|
||||||
|
@ -198,13 +199,6 @@
|
||||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
|
|
||||||
// Experimental offline maps using a local tilestache server.
|
|
||||||
var offline_osm_map = L.tileLayer(location.protocol + '//' + document.domain + ':8080/roads/{z}/{x}/{y}.png', {
|
|
||||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
|
||||||
minNativeZoom:9,
|
|
||||||
maxNativeZoom:13
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add ESRI Satellite Maps.
|
// Add ESRI Satellite Maps.
|
||||||
var esrimapLink =
|
var esrimapLink =
|
||||||
'<a href="http://www.esri.com/">Esri</a>';
|
'<a href="http://www.esri.com/">Esri</a>';
|
||||||
|
@ -216,7 +210,18 @@
|
||||||
attribution: '© '+esrimapLink+', '+esriwholink,
|
attribution: '© '+esrimapLink+', '+esriwholink,
|
||||||
maxZoom: 18,
|
maxZoom: 18,
|
||||||
});
|
});
|
||||||
map.addControl(new L.Control.Layers({'OSM':osm_map, 'ESRI Satellite':esri_sat_map, 'Offline OSM': offline_osm_map}));
|
|
||||||
|
var map_layers = {'OSM':osm_map, 'ESRI Satellite':esri_sat_map};
|
||||||
|
|
||||||
|
// Add Offline map layers, if we have any.
|
||||||
|
for (var i = 0, len = chase_config.offline_tile_layers.length; i < len; i++) {
|
||||||
|
var _layer_name = chase_config.offline_tile_layers[i];
|
||||||
|
map_layers['Offline - ' + _layer_name] = L.tileLayer(location.protocol + '//' + document.domain + ':' + location.port + '/tiles/'+_layer_name+'/{z}/{x}/{y}.png');
|
||||||
|
}
|
||||||
|
// Add layer selection control (top right).
|
||||||
|
map.addControl(new L.Control.Layers(map_layers));
|
||||||
|
|
||||||
|
// Add sidebar to map (where all of our controls are!)
|
||||||
var sidebar = L.control.sidebar('sidebar').addTo(map);
|
var sidebar = L.control.sidebar('sidebar').addTo(map);
|
||||||
|
|
||||||
// Add custom controls, which show various sets of data.
|
// Add custom controls, which show various sets of data.
|
||||||
|
|
Ładowanie…
Reference in New Issue