2018-07-19 12:44:01 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
|
|
|
# Project Horus - Browser-Based Chase Mapper - Config Reader
|
|
|
|
#
|
|
|
|
# Copyright (C) 2018 Mark Jessop <vk5qi@rfhead.net>
|
|
|
|
# Released under GNU GPL v3 or later
|
|
|
|
#
|
|
|
|
import logging
|
2018-08-02 11:19:36 +00:00
|
|
|
import os
|
2018-07-19 12:44:01 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
# Python 2
|
|
|
|
from ConfigParser import RawConfigParser
|
|
|
|
except ImportError:
|
|
|
|
# Python 3
|
|
|
|
from configparser import RawConfigParser
|
|
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
2018-07-27 10:22:43 +00:00
|
|
|
'payload_max_age': 180,
|
2018-08-25 10:21:13 +00:00
|
|
|
'thunderforest_api_key': 'none',
|
2018-07-27 10:22:43 +00:00
|
|
|
|
2018-07-19 12:44:01 +00:00
|
|
|
# Predictor settings
|
2020-12-28 08:21:47 +00:00
|
|
|
'pred_enabled': True, # Enable running and display of predicted flight paths.
|
|
|
|
'offline_predictions': False, # Use an offline GFS model and predictor instead of Tawhiri.
|
2018-07-19 12:44:01 +00:00
|
|
|
# Default prediction settings (actual values will be used once the flight is underway)
|
|
|
|
'pred_model': "Disabled",
|
|
|
|
'pred_desc_rate': 6.0,
|
|
|
|
'pred_burst': 28000,
|
|
|
|
'show_abort': True, # Show a prediction of an 'abort' paths (i.e. if the balloon bursts *now*)
|
2019-04-27 05:26:49 +00:00
|
|
|
'pred_update_rate': 15, # Update predictor every 15 seconds.
|
|
|
|
|
|
|
|
# Range Rings
|
|
|
|
'range_rings_enabled': False,
|
|
|
|
'range_ring_quantity': 5,
|
|
|
|
'range_ring_spacing': 1000,
|
|
|
|
'range_ring_weight': 1.5,
|
|
|
|
'range_ring_color': 'red',
|
2019-08-10 12:10:40 +00:00
|
|
|
'range_ring_custom_color': '#FF0000',
|
|
|
|
|
2021-01-10 03:28:45 +00:00
|
|
|
# Chase Car Speedometer
|
|
|
|
'chase_car_speed': True,
|
2020-10-10 07:17:45 +00:00
|
|
|
|
2019-08-10 12:10:40 +00:00
|
|
|
# Bearing processing
|
|
|
|
'max_bearings': 300,
|
2019-08-11 08:16:31 +00:00
|
|
|
'max_bearing_age': 30*60,
|
2019-08-10 12:10:40 +00:00
|
|
|
'car_speed_gate': 10,
|
|
|
|
'bearing_length': 10,
|
|
|
|
'bearing_weight': 1.0,
|
|
|
|
'bearing_color': 'black',
|
|
|
|
'bearing_custom_color': '#FF0000',
|
2020-12-25 01:47:01 +00:00
|
|
|
|
2021-01-10 03:28:45 +00:00
|
|
|
# History
|
|
|
|
'reload_last_position': True
|
|
|
|
|
2018-07-19 12:44:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def parse_config_file(filename):
|
|
|
|
""" Parse a Configuration File """
|
|
|
|
|
|
|
|
chase_config = default_config.copy()
|
|
|
|
|
|
|
|
config = RawConfigParser()
|
|
|
|
config.read(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')
|
2018-07-27 10:22:43 +00:00
|
|
|
chase_config['payload_max_age'] = config.getint('map', 'payload_max_age')
|
2018-08-25 10:21:13 +00:00
|
|
|
chase_config['thunderforest_api_key'] = config.get('map', 'thunderforest_api_key')
|
2018-07-19 12:44:01 +00:00
|
|
|
|
|
|
|
|
2018-07-27 12:17:17 +00:00
|
|
|
# GPSD Settings
|
|
|
|
chase_config['car_gpsd_host'] = config.get('gpsd','gpsd_host')
|
|
|
|
chase_config['car_gpsd_port'] = config.getint('gpsd','gpsd_port')
|
2018-07-19 12:44:01 +00:00
|
|
|
|
2018-08-28 13:18:29 +00:00
|
|
|
# Serial GPS Settings
|
|
|
|
chase_config['car_serial_port'] = config.get('gps_serial', 'gps_port')
|
|
|
|
chase_config['car_serial_baud'] = config.getint('gps_serial', 'gps_baud')
|
|
|
|
|
2018-09-01 12:52:00 +00:00
|
|
|
# Habitat Settings
|
|
|
|
chase_config['habitat_upload_enabled'] = config.getboolean('habitat', 'habitat_upload_enabled')
|
|
|
|
chase_config['habitat_call'] = config.get('habitat', 'habitat_call')
|
|
|
|
chase_config['habitat_update_rate'] = config.getint('habitat', 'habitat_update_rate')
|
|
|
|
|
2018-07-19 12:44:01 +00:00
|
|
|
# Predictor
|
|
|
|
chase_config['pred_enabled'] = config.getboolean('predictor', 'predictor_enabled')
|
2020-12-28 08:21:47 +00:00
|
|
|
chase_config['offline_predictions'] = config.getboolean('predictor', 'offline_predictions')
|
2018-07-19 12:44:01 +00:00
|
|
|
chase_config['pred_burst'] = config.getfloat('predictor', 'default_burst')
|
|
|
|
chase_config['pred_desc_rate'] = config.getfloat('predictor', 'default_descent_rate')
|
|
|
|
chase_config['pred_binary'] = config.get('predictor','pred_binary')
|
|
|
|
chase_config['pred_gfs_directory'] = config.get('predictor', 'gfs_directory')
|
|
|
|
chase_config['pred_model_download'] = config.get('predictor', 'model_download')
|
|
|
|
|
2019-04-27 05:26:49 +00:00
|
|
|
# Range Ring Settings
|
|
|
|
chase_config['range_rings_enabled'] = config.getboolean('range_rings', 'range_rings_enabled')
|
|
|
|
chase_config['range_ring_quantity'] = config.getint('range_rings', 'range_ring_quantity')
|
|
|
|
chase_config['range_ring_spacing'] = config.getint('range_rings', 'range_ring_spacing')
|
|
|
|
chase_config['range_ring_weight'] = config.getfloat('range_rings', 'range_ring_weight')
|
|
|
|
chase_config['range_ring_color'] = config.get('range_rings', 'range_ring_color')
|
|
|
|
chase_config['range_ring_custom_color'] = config.get('range_rings', 'range_ring_custom_color')
|
|
|
|
|
2019-08-10 12:10:40 +00:00
|
|
|
# Bearing Processing
|
|
|
|
chase_config['max_bearings'] = config.getint('bearings', 'max_bearings')
|
|
|
|
chase_config['max_bearing_age'] = config.getint('bearings', 'max_bearing_age')*60 # Convert to seconds
|
|
|
|
if chase_config['max_bearing_age'] < 60:
|
|
|
|
chase_config['max_bearing_age'] = 60 # Make sure this number is something sane, otherwise things will break
|
2019-08-12 11:37:12 +00:00
|
|
|
chase_config['car_speed_gate'] = config.getfloat('bearings', 'car_speed_gate')/3.6 # Convert to m/s
|
2019-08-10 12:10:40 +00:00
|
|
|
chase_config['bearing_length'] = config.getfloat('bearings', 'bearing_length')
|
|
|
|
chase_config['bearing_weight'] = config.getfloat('bearings', 'bearing_weight')
|
|
|
|
chase_config['bearing_color'] = config.get('bearings', 'bearing_color')
|
|
|
|
chase_config['bearing_custom_color'] = config.get('bearings', 'bearing_custom_color')
|
|
|
|
|
2018-08-02 11:19:36 +00:00
|
|
|
# Offline Map Settings
|
|
|
|
chase_config['tile_server_enabled'] = config.getboolean('offline_maps', 'tile_server_enabled')
|
|
|
|
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']))
|
|
|
|
|
2020-10-10 07:17:45 +00:00
|
|
|
try:
|
|
|
|
chase_config['chase_car_speed'] = config.getboolean('speedo', 'chase_car_speed')
|
|
|
|
except:
|
|
|
|
logging.info("Missing Chase Car Speedo Setting, using default (disabled)")
|
|
|
|
chase_config['chase_car_speed'] = False
|
|
|
|
|
2018-07-27 12:17:17 +00:00
|
|
|
# Telemetry Source Profiles
|
|
|
|
|
|
|
|
_profile_count = config.getint('profile_selection', 'profile_count')
|
|
|
|
_default_profile = config.getint('profile_selection', 'default_profile')
|
|
|
|
|
|
|
|
chase_config['selected_profile'] = ""
|
|
|
|
chase_config['profiles'] = {}
|
|
|
|
|
2020-12-24 23:46:33 +00:00
|
|
|
|
|
|
|
# Unit Selection
|
|
|
|
|
2020-12-25 01:47:01 +00:00
|
|
|
chase_config['unitselection'] = config.get('units', 'unitselection', fallback='metric')
|
2020-12-30 03:15:59 +00:00
|
|
|
if chase_config['unitselection'] != "imperial":
|
|
|
|
chase_config['unitselection'] = 'metric' #unless imperial is explicitly requested do metric
|
2020-12-25 01:47:01 +00:00
|
|
|
chase_config['switch_miles_feet'] = config.get('units', 'switch_miles_feet', fallback = '400')
|
2020-12-24 23:48:46 +00:00
|
|
|
|
2018-07-27 12:17:17 +00:00
|
|
|
for i in range(1,_profile_count+1):
|
|
|
|
_profile_section = "profile_%d" % i
|
|
|
|
try:
|
|
|
|
_profile_name = config.get(_profile_section, 'profile_name')
|
|
|
|
_profile_telem_source_type = config.get(_profile_section, 'telemetry_source_type')
|
|
|
|
_profile_telem_source_port = config.getint(_profile_section, 'telemetry_source_port')
|
|
|
|
_profile_car_source_type = config.get(_profile_section, 'car_source_type')
|
|
|
|
_profile_car_source_port = config.getint(_profile_section, 'car_source_port')
|
|
|
|
|
|
|
|
chase_config['profiles'][_profile_name] = {
|
|
|
|
'name': _profile_name,
|
|
|
|
'telemetry_source_type': _profile_telem_source_type,
|
|
|
|
'telemetry_source_port': _profile_telem_source_port,
|
|
|
|
'car_source_type': _profile_car_source_type,
|
|
|
|
'car_source_port': _profile_car_source_port
|
|
|
|
}
|
|
|
|
if _default_profile == i:
|
|
|
|
chase_config['selected_profile'] = _profile_name
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
logging.error("Error reading profile section %d - %s" % (i, str(e)))
|
|
|
|
|
|
|
|
if len(chase_config['profiles'].keys()) == 0:
|
|
|
|
logging.critical("Could not read any profile data!")
|
|
|
|
return None
|
|
|
|
|
|
|
|
if chase_config['selected_profile'] not in chase_config['profiles']:
|
|
|
|
logging.critical("Default profile selection does not exist.")
|
|
|
|
return None
|
|
|
|
|
2021-01-10 03:28:45 +00:00
|
|
|
# History
|
|
|
|
logging.info("Checking to see if reload_last_position is set")
|
|
|
|
chase_config['reload_last_position'] = config.getboolean('history', 'reload_last_position', fallback=False)
|
|
|
|
if (chase_config['reload_last_position']):
|
|
|
|
logging.info("Scanning logs to reload last position")
|
|
|
|
else:
|
|
|
|
logging.info("Not scanning logs to reload last position")
|
|
|
|
|
|
|
|
|
2018-07-19 12:44:01 +00:00
|
|
|
return chase_config
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-01-10 03:28:45 +00:00
|
|
|
|
2018-07-19 12:44:01 +00:00
|
|
|
def read_config(filename, default_cfg="horusmapper.cfg.example"):
|
|
|
|
""" Read in a Horus Mapper configuration file,and return as a dict. """
|
|
|
|
|
|
|
|
try:
|
|
|
|
config_dict = parse_config_file(filename)
|
|
|
|
except Exception as e:
|
|
|
|
logging.error("Could not parse %s, trying default: %s" % (filename, str(e)))
|
|
|
|
try:
|
|
|
|
config_dict = parse_config_file(default_cfg)
|
|
|
|
except Exception as e:
|
|
|
|
logging.critical("Could not parse example config file! - %s" % str(e))
|
|
|
|
config_dict = None
|
|
|
|
|
|
|
|
return config_dict
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
import sys
|
2018-08-02 11:19:36 +00:00
|
|
|
logging.basicConfig(format='%(asctime)s %(levelname)s:%(message)s', stream=sys.stdout, level=logging.DEBUG)
|
2018-07-19 12:44:01 +00:00
|
|
|
print(read_config(sys.argv[1]))
|
|
|
|
|
|
|
|
|