Add stationary listener option

pull/29/head
Mark Jessop 2021-03-20 16:02:04 +10:30
rodzic 13194ebf0f
commit f1b1a1d80d
10 zmienionych plików z 152 dodań i 30 usunięć

Wyświetl plik

@ -57,7 +57,7 @@ Edit this file with your preferred text editor. The configuration file is fairly
* At least one telemetry 'profile', which defines where payload and (optionally) car position telemetry data is sourced from.
* A default latitude and longitude for the map to centre on.
The example configuration file includes profiles suitable for receiving data from radiosonde_auto_rx, and from OziMux messages.
The example configuration file includes profiles suitable for receiving data from radiosonde_auto_rx, and from [Horus-GUI](https://github.com/projecthorus/horus-gui).
Once configured, you can start-up the horusmapper server with:
```

Wyświetl plik

@ -5,3 +5,7 @@
# Copyright (C) 2018 Mark Jessop <vk5qi@rfhead.net>
# Released under GNU GPL v3 or later
#
# Now using Semantic Versioning (https://semver.org/) MAJOR.MINOR.PATCH
__version__ = "1.0.1"

Wyświetl plik

@ -20,6 +20,7 @@ default_config = {
# Start location for the map (until either a chase car position, or balloon position is available.)
"default_lat": -34.9,
"default_lon": 138.6,
"default_alt": 0,
"payload_max_age": 180,
"thunderforest_api_key": "none",
# Predictor settings
@ -64,8 +65,8 @@ def parse_config_file(filename):
# Map Defaults
chase_config["flask_host"] = config.get("map", "flask_host")
chase_config["flask_port"] = config.getint("map", "flask_port")
chase_config["default_lat"] = config.get("map", "default_lat")
chase_config["default_lon"] = config.get("map", "default_lon")
chase_config["default_lat"] = config.getfloat("map", "default_lat")
chase_config["default_lon"] = config.getfloat("map", "default_lon")
chase_config["payload_max_age"] = config.getint("map", "payload_max_age")
chase_config["thunderforest_api_key"] = config.get("map", "thunderforest_api_key")
@ -156,6 +157,12 @@ def parse_config_file(filename):
logging.info("Missing Chase Car Speedo Setting, using default (disabled)")
chase_config["chase_car_speed"] = False
try:
chase_config["default_alt"] = config.getfloat("map", "default_alt")
except:
logging.info("Missing default_alt setting, using default (0m)")
chase_config["default_alt"] = 0
# Telemetry Source Profiles
_profile_count = config.getint("profile_selection", "profile_count")

Wyświetl plik

@ -32,6 +32,7 @@ telemetry_source_port = 55673
# horus_udp - Read Horus UDP Broadcast 'Car GPS' messages
# serial - Read GPS positions from a serial-connected GPS receiver.
# gpsd - Poll GPSD for positions.
# station - Stationary position (set in the [map] section below)
car_source_type = gpsd
# Car position source port (UDP) - only used if horus_udp is selected, but still needs to be provided.
car_source_port = 12345
@ -74,15 +75,18 @@ gps_port = /dev/ttyUSB0
gps_baud = 9600
# Map Defaults
# Map Settings
[map]
# Host/port to host webserver on
flask_host = 0.0.0.0
flask_port = 5001
# Default map centre
# Default Map Centre & Stationary Position
# If the profile's car_source_type is set to station, the following position will be indicated on the map
# as a stationary receiver.
default_lat = -34.9
default_lon = 138.6
default_alt = 0.0
# How long to keep payload data (minutes)
payload_max_age = 180
@ -191,7 +195,8 @@ range_ring_color = red
range_ring_custom_color = #FF0000
#
# Chase Car Speedometer
# Chase Car Speedometer
# If enabled display the chase car speed at the bottom left of the display.
#
[speedo]
chase_car_speed = True

Wyświetl plik

@ -18,6 +18,7 @@ from threading import Thread
from datetime import datetime, timedelta
from dateutil.parser import parse
from chasemapper import __version__ as CHASEMAPPER_VERSION
from chasemapper.config import *
from chasemapper.earthmaths import *
from chasemapper.geometry import *
@ -789,7 +790,7 @@ def udp_listener_car_callback(data):
# Handle when GPSD and/or other GPS data sources return a n/a for altitude.
try:
_alt = float(data["altitude"])
except ValueError:
except:
_alt = 0.0
_comment = "CAR"
@ -896,7 +897,7 @@ def start_listeners(profile):
'name' (str): Profile name
'telemetry_source_type' (str): Data source type (ozimux or horus_udp)
'telemetry_source_port' (int): Data source port
'car_source_type' (str): Car Position source type (none, horus_udp or gpsd)
'car_source_type' (str): Car Position source type (none, horus_udp, gpsd, or station)
'car_source_port' (int): Car Position source port
"""
global data_listeners
@ -994,6 +995,9 @@ def start_listeners(profile):
)
data_listeners.append(_serial_gps)
elif profile["car_source_type"] == "station":
logging.info("Using Stationary receiver position.")
else:
# No Car position.
logging.info("No car position data source.")
@ -1014,6 +1018,16 @@ def profile_change(data):
# Update all clients with the new profile selection
flask_emit_event("server_settings_update", chasemapper_config)
@socketio.on("device_position", namespace="/chasemapper")
def device_position_update(data):
""" Accept a device position update from a client and process it as if it was a chase car position """
try:
udp_listener_car_callback(data)
except:
pass
class WebHandler(logging.Handler):
""" Logging Handler for sending log messages via Socket.IO to a Web Client """
@ -1093,6 +1107,9 @@ if __name__ == "__main__":
logging.critical("Could not read configuration data. Exiting")
sys.exit(1)
# Add in Chasemapper version information.
chasemapper_config['version'] = CHASEMAPPER_VERSION
# Copy out the predictor settings to another dictionary.
pred_settings = {
"pred_binary": chasemapper_config["pred_binary"],

Wyświetl plik

@ -124,13 +124,21 @@ function updateSummaryDisplay(){
_summary_update.vel_v = _latest_telem.vel_v.toFixed(1) + " m/s";
// Work out if we have data to calculate look-angles from.
if (chase_car_position.latest_data.length == 3){
// We have a chase car position! Calculate relative position.
var _bal = {lat:_latest_telem.position[0], lon:_latest_telem.position[1], alt:_latest_telem.position[2]};
// Chase car position available - use that.
var _car = {lat:chase_car_position.latest_data[0], lon:chase_car_position.latest_data[1], alt:chase_car_position.latest_data[2]};
} else if (home_marker !== "NONE") {
// Home marker is on the map - use the home marker position
var _car = {lat:chase_config.default_lat, lon:chase_config.default_lon, alt:chase_config.default_alt};
} else {
// Otherwise, nothing we can use
var _car = null;
}
if(_car !== null){
var _bal = {lat:_latest_telem.position[0], lon:_latest_telem.position[1], alt:_latest_telem.position[2]};
var _look_angles = calculate_lookangles(_car, _bal);
_summary_update.elevation = _look_angles.elevation.toFixed(0) + "°";
_summary_update.azimuth = _look_angles.azimuth.toFixed(0) + "°";
_summary_update.range = (_look_angles.range/1000).toFixed(1) + "km";
@ -168,11 +176,21 @@ function updateSummaryDisplayImperial(){
_summary_update.vel_v = (_latest_telem.vel_v*3.28084*60).toFixed(0) + " ft/min";
// Work out if we have data to calculate look-angles from.
if (chase_car_position.latest_data.length == 3){
// Chase car position available - use that.
var _car = {lat:chase_car_position.latest_data[0], lon:chase_car_position.latest_data[1], alt:chase_car_position.latest_data[2]};
} else if (home_marker !== "NONE") {
// Home marker is on the map - use the home marker position
var _car = {lat:chase_config.default_lat, lon:chase_config.default_lon, alt:chase_config.default_alt};
} else {
// Otherwise, nothing we can use
var _car = null;
}
if(_car !== null){
// We have a chase car position! Calculate relative position.
var _bal = {lat:_latest_telem.position[0], lon:_latest_telem.position[1], alt:_latest_telem.position[2]};
var _car = {lat:chase_car_position.latest_data[0], lon:chase_car_position.latest_data[1], alt:chase_car_position.latest_data[2]};
var _look_angles = calculate_lookangles(_car, _bal);
_summary_update.elevation = _look_angles.elevation.toFixed(0) + "°";

Wyświetl plik

@ -109,3 +109,39 @@ function updateRangeRings(){
}
}
function reconfigureCarMarker(profile_name){
// Remove chase-car marker if it exists, and is not used.
if( (chase_config.profiles[profile_name].car_source_type === "none") || (chase_config.profiles[profile_name].car_source_type === "station")){
if (chase_car_position.marker !== "NONE"){
chase_car_position.marker.remove();
chase_car_position.path.remove();
}
}
if (chase_config.profiles[profile_name].car_source_type === "station") {
// If we are using a stationary profile, add the station icon to the map.
// Add our station location marker.
home_marker = L.marker([chase_config.default_lat, chase_config.default_lon, chase_config.default_alt],
{title: 'Receiver Location', icon: homeIcon}
).addTo(map);
}
// If we are switching to a profile with a live car position source, remove the home station Icon
if ((chase_config.profiles[profile_name].car_source_type === "serial") || (chase_config.profiles[profile_name].car_source_type === "gpsd") || (chase_config.profiles[profile_name].car_source_type === "horus_udp")){
if(home_marker !== "NONE"){
home_marker.remove();
}
}
}
var devicePositionCallback = function(position){
// Pass a Device position update onto the back-end for processing and re-distribution.
var device_pos = {time:position.timestamp, latitude:position.coords.latitude, longitude:position.coords.longitude, altitude:position.coords.altitude};
socket.emit('device_position', device_pos);
}
var devicePositionError = function(error){
console.log(error.message);
}

Wyświetl plik

@ -66,8 +66,6 @@ function serverSettingsUpdate(data){
$('#bearingCustomColor').val(chase_config.bearing_custom_color);
$('#bearingMaximumAge').val((chase_config.max_bearing_age/60.0).toFixed(0));
// Clear and populate the profile selection.
$('#profileSelect').children('option:not(:first)').remove();
@ -78,6 +76,9 @@ function serverSettingsUpdate(data){
.text(key));
});
$("#profileSelect").val(chase_config.selected_profile);
// Update version
$('#chasemapper_version').html(chase_config.version);
}
function clientSettingsUpdate(){

Wyświetl plik

@ -66,6 +66,14 @@ var carIconFlip = L.icon({
iconAnchor: [27,12] // Revisit this
});
// Home Icon.
var homeIcon = L.icon({
iconUrl: '/static/img/antenna-green.png',
iconSize: [26, 34],
iconAnchor: [13, 34]
});
// Habitat (or APRS?) sourced chase car icons.
var car_colour_values = ['red', 'green', 'yellow'];
var car_colour_idx = 0;

Wyświetl plik

@ -72,6 +72,9 @@
// marker: Leaflet marker
var chase_car_position = {latest_data: [], heading:0, marker: 'NONE', path: 'NONE'};
// Home position marker
var home_marker = 'NONE';
// Data Age variables - these are updated regularly to indicate
// if we haven't received data in a while.
var payload_data_age = 0.0;
@ -191,8 +194,11 @@
$("#profileSelect").change(function(){
// On a profile selection change, emit a message to the client.
socket.emit('profile_change', this.value);
});
// Remove chase car if switching to a profile which does not have live position updates.
_profile = this.value;
reconfigureCarMarker(this.value);
});
// Handle arrival of new log data.
socket.on('log_event', function(msg) {
@ -251,24 +257,20 @@
// Add measurement control.
if (chase_config['unitselection'] == "imperial") {
L.control.polylineMeasure({
position: 'topleft',
unit: 'landmiles',
showClearControl: true,
}).addTo(map);
L.control.polylineMeasure({
position: 'topleft',
unit: 'landmiles',
showClearControl: true,
}).addTo(map);
}
if (chase_config['unitselection'] == "metric") {
L.control.polylineMeasure({
position: 'topleft',
unit: 'metres',
showClearControl: true,
}).addTo(map);
L.control.polylineMeasure({
position: 'topleft',
unit: 'metres',
showClearControl: true,
}).addTo(map);
}
@ -462,6 +464,9 @@
// Initialise bearings
initialiseBearings();
// Initial setup of station marker, if using a profile which uses it.
reconfigureCarMarker(chase_config.selected_profile);
// Telemetry event handler.
// We will get one of these mesages with every new balloon position
@ -613,6 +618,16 @@
}, habitat_update_rate);
// window.setInterval(function(){
// if(document.getElementById('useDevicePosition').checked){
// if(navigator.geolocation){
// car_bad_age = 20.0;
// navigator.geolocation.getCurrentPosition(devicePositionCallback,devicePositionError,{enableHighAccuracy:true});
// }
// }
// }, 5000);
window.setInterval(function(){
if(Object.keys(bearing_store).length > 0){
$.ajax({
@ -673,6 +688,10 @@
<!-- Tab panes -->
<div class="sidebar-content">
<div class="sidebar-pane" id="home">
<div class="paramRow">
<b>Chasemapper Version: </b> <div id="chasemapper_version" class="paramEntry">Unknown</div></br>
</div>
</br>
<h1 class="sidebar-header">
Log Messages
<span class="sidebar-close"><i class="fa fa-caret-left"></i></span>
@ -742,6 +761,13 @@
<span class="sidebar-close"><i class="fa fa-caret-left"></i></span>
</h1>
<!--
<h3>Car Position Source</h3>
<div class="paramRow">
<b>Use Device Position:</b> <input type="checkbox" class="paramSelector" id="useDevicePosition">
</div>
-->
<h3>Habitat Chase Car</h3>
<div class="paramRow">
<b>Show Nearby Chase-Cars:</b> <input type="checkbox" class="paramSelector" id="showOtherCars" onclick="show_habitat_vehicles();">