kopia lustrzana https://github.com/projecthorus/radiosonde_auto_rx
Generate live KML using ElementTree
rodzic
0ea4558aa2
commit
58a183dffa
|
|
@ -564,7 +564,7 @@ def read_auto_rx_config(filename, no_sdr_test=False):
|
|||
logging.warning(
|
||||
"Config - Did not find kml_refresh_rate setting, using default (10 seconds)."
|
||||
)
|
||||
auto_rx_config["kml_refresh_rate"] = 11
|
||||
auto_rx_config["kml_refresh_rate"] = 10
|
||||
|
||||
# New Sondehub db Settings
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -522,17 +522,20 @@ def zip_log_files(serial_list=None):
|
|||
return data
|
||||
|
||||
|
||||
def _coordinates_to_kml_placemark(lat, lon, alt,
|
||||
name="Placemark Name",
|
||||
absolute=False,
|
||||
icon="http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png",
|
||||
scale=1.0):
|
||||
def coordinates_to_kml_placemark(lat, lon, alt,
|
||||
name="Placemark Name",
|
||||
description="Placemark Description",
|
||||
absolute=False,
|
||||
icon="https://maps.google.com/mapfiles/kml/shapes/placemark_circle.png",
|
||||
scale=1.0):
|
||||
""" Generate a generic placemark object """
|
||||
|
||||
placemark = ET.Element("Placemark")
|
||||
|
||||
pm_name = ET.SubElement(placemark, "name")
|
||||
pm_name.text = name
|
||||
pm_desc = ET.SubElement(placemark, "description")
|
||||
pm_desc.text = description
|
||||
|
||||
style = ET.SubElement(placemark, "Style")
|
||||
icon_style = ET.SubElement(style, "IconStyle")
|
||||
|
|
@ -552,13 +555,13 @@ def _coordinates_to_kml_placemark(lat, lon, alt,
|
|||
return placemark
|
||||
|
||||
|
||||
def _flight_path_to_kml_placemark(flight_path,
|
||||
name="Flight Path Name",
|
||||
track_color="aaffffff",
|
||||
poly_color="20000000",
|
||||
track_width=2.0,
|
||||
absolute=True,
|
||||
extrude=True):
|
||||
def path_to_kml_placemark(flight_path,
|
||||
name="Flight Path Name",
|
||||
track_color="ff03bafc",
|
||||
poly_color="8003bafc",
|
||||
track_width=2.0,
|
||||
absolute=True,
|
||||
extrude=True):
|
||||
''' Produce a placemark object from a flight path array '''
|
||||
|
||||
placemark = ET.Element("Placemark")
|
||||
|
|
@ -572,13 +575,14 @@ def _flight_path_to_kml_placemark(flight_path,
|
|||
color.text = track_color
|
||||
width = ET.SubElement(line_style, "width")
|
||||
width.text = str(track_width)
|
||||
poly_style = ET.SubElement(style, "PolyStyle")
|
||||
color = ET.SubElement(poly_style, "color")
|
||||
color.text = poly_color
|
||||
fill = ET.SubElement(poly_style, "fill")
|
||||
fill.text = "1"
|
||||
outline = ET.SubElement(poly_style, "outline")
|
||||
outline.text = "1"
|
||||
if extrude:
|
||||
poly_style = ET.SubElement(style, "PolyStyle")
|
||||
color = ET.SubElement(poly_style, "color")
|
||||
color.text = poly_color
|
||||
fill = ET.SubElement(poly_style, "fill")
|
||||
fill.text = "1"
|
||||
outline = ET.SubElement(poly_style, "outline")
|
||||
outline.text = "1"
|
||||
|
||||
line_string = ET.SubElement(placemark, "LineString")
|
||||
if absolute:
|
||||
|
|
@ -603,26 +607,19 @@ def _log_file_to_kml_folder(filename, absolute=True, extrude=True, last_only=Fal
|
|||
_flight_data = read_log_file(filename)
|
||||
|
||||
_flight_serial = _flight_data["serial"]
|
||||
_launch_time = parse(_flight_data["first_time"]).strftime("%Y%m%d-%H%M%SZ")
|
||||
# Generate a comment line to use in the folder and placemark descriptions
|
||||
_track_comment = "%s %s" % (_launch_time, _flight_serial)
|
||||
_landing_comment = "%s Last Position" % (_flight_serial)
|
||||
|
||||
# Grab last-seen position
|
||||
_landing_time = _flight_data["last_time"]
|
||||
_landing_pos = _flight_data["path"][-1]
|
||||
|
||||
_folder = ET.Element("Folder")
|
||||
_name = ET.SubElement(_folder, "name")
|
||||
_name.text = _track_comment
|
||||
_description = ET.SubElement(_folder, "description")
|
||||
_description.text = "Radiosonde Flight Path"
|
||||
_name.text = _flight_serial
|
||||
|
||||
# Generate the placemark & flight track.
|
||||
_folder.append(coordinates_to_kml_placemark(_landing_pos[0], _landing_pos[1], _landing_pos[2],
|
||||
name=_flight_serial, description=_landing_time, absolute=absolute))
|
||||
if not last_only:
|
||||
_folder.append(_flight_path_to_kml_placemark(_flight_data["path"], name=_track_comment,
|
||||
absolute=absolute, extrude=extrude))
|
||||
_folder.append(_coordinates_to_kml_placemark(_landing_pos[0], _landing_pos[1], _landing_pos[2],
|
||||
name=_landing_comment, absolute=absolute))
|
||||
_folder.append(path_to_kml_placemark(_flight_data["path"], name="Track",
|
||||
absolute=absolute, extrude=extrude))
|
||||
|
||||
return _folder
|
||||
|
||||
|
|
@ -630,7 +627,7 @@ def _log_file_to_kml_folder(filename, absolute=True, extrude=True, last_only=Fal
|
|||
def log_files_to_kml(file_list, kml_file, absolute=True, extrude=True, last_only=False):
|
||||
""" Convert a collection of log files to a KML file """
|
||||
|
||||
kml_root = ET.Element("kml", {"xmlns": "http://www.opengis.net/kml/2.2"})
|
||||
kml_root = ET.Element("kml", xmlns="http://www.opengis.net/kml/2.2")
|
||||
kml_doc = ET.SubElement(kml_root, "Document")
|
||||
|
||||
for file in file_list:
|
||||
|
|
|
|||
|
|
@ -18,12 +18,20 @@ import requests
|
|||
import time
|
||||
import traceback
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
import autorx
|
||||
import autorx.config
|
||||
import autorx.scan
|
||||
from autorx.geometry import GenericTrack
|
||||
from autorx.utils import check_autorx_versions
|
||||
from autorx.log_files import list_log_files, read_log_by_serial, zip_log_files, log_files_to_kml
|
||||
from autorx.log_files import (
|
||||
list_log_files,
|
||||
read_log_by_serial,
|
||||
zip_log_files,
|
||||
log_files_to_kml,
|
||||
coordinates_to_kml_placemark,
|
||||
path_to_kml_placemark
|
||||
)
|
||||
from autorx.decode import SondeDecoder
|
||||
from queue import Queue
|
||||
from threading import Thread
|
||||
|
|
@ -31,15 +39,6 @@ import flask
|
|||
from flask import request, abort, make_response, send_file
|
||||
from flask_socketio import SocketIO
|
||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
import re
|
||||
|
||||
try:
|
||||
from simplekml import Kml, AltitudeMode
|
||||
except ImportError:
|
||||
print(
|
||||
"Could not import simplekml! Try running: sudo pip3 install -r requirements.txt"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Inhibit Flask warning message about running a development server... (we know!)
|
||||
|
|
@ -149,47 +148,60 @@ def flask_get_task_list():
|
|||
def flask_get_kml():
|
||||
""" Return KML with autorefresh """
|
||||
|
||||
_config = autorx.config.global_config
|
||||
kml = Kml()
|
||||
netlink = kml.newnetworklink(name="Radiosonde Auto-RX Live Telemetry")
|
||||
netlink.open = 1
|
||||
netlink.link.href = flask.request.url_root + "rs_feed.kml"
|
||||
try:
|
||||
netlink.link.refreshinterval = _config["kml_refresh_rate"]
|
||||
except KeyError:
|
||||
netlink.link.refreshinterval = 10
|
||||
netlink.link.refreshmode = "onInterval"
|
||||
return kml.kml(), 200, {"content-type": "application/vnd.google-earth.kml+xml"}
|
||||
kml_root = ET.Element("kml", xmlns="http://www.opengis.net/kml/2.2")
|
||||
kml_doc = ET.SubElement(kml_root, "Document")
|
||||
|
||||
network_link = ET.SubElement(kml_doc, "NetworkLink")
|
||||
|
||||
name = ET.SubElement(network_link, "name")
|
||||
name.text = "Radiosonde Auto-RX Live Telemetry"
|
||||
|
||||
open = ET.SubElement(network_link, "open")
|
||||
open.text = "1"
|
||||
|
||||
link = ET.SubElement(network_link, "Link")
|
||||
|
||||
href = ET.SubElement(link, "href")
|
||||
href.text = flask.request.url_root + "rs_feed.kml"
|
||||
|
||||
refresh_mode = ET.SubElement(link, "refreshMode")
|
||||
refresh_mode.text = "onInterval"
|
||||
|
||||
refresh_interval = ET.SubElement(link, "refreshInterval")
|
||||
refresh_interval.text = str(autorx.config.global_config["kml_refresh_rate"])
|
||||
|
||||
kml_string = ET.tostring(kml_root, encoding="UTF-8", xml_declaration=True)
|
||||
return kml_string, 200, {"content-type": "application/vnd.google-earth.kml+xml"}
|
||||
|
||||
|
||||
@app.route("/rs_feed.kml")
|
||||
def flask_get_kml_feed():
|
||||
""" Return KML with RS telemetry """
|
||||
kml = Kml()
|
||||
kml.resetidcounter()
|
||||
kml.document.name = "Track"
|
||||
kml.document.open = 1
|
||||
kml_root = ET.Element("kml", xmlns="http://www.opengis.net/kml/2.2")
|
||||
kml_doc = ET.SubElement(kml_root, "Document")
|
||||
|
||||
name = ET.SubElement(kml_doc, "name")
|
||||
name.text = "Track"
|
||||
open = ET.SubElement(kml_doc, "open")
|
||||
open.text = "1"
|
||||
|
||||
# Station Placemark
|
||||
pnt = kml.newpoint(
|
||||
name="Ground Station",
|
||||
altitudemode=AltitudeMode.absolute,
|
||||
kml_doc.append(coordinates_to_kml_placemark(
|
||||
autorx.config.global_config["station_lat"],
|
||||
autorx.config.global_config["station_lon"],
|
||||
autorx.config.global_config["station_alt"],
|
||||
name=autorx.config.global_config["habitat_uploader_callsign"],
|
||||
description="AutoRX Ground Station",
|
||||
)
|
||||
pnt.open = 1
|
||||
pnt.iconstyle.icon.href = flask.request.url_root + "static/img/antenna-green.png"
|
||||
pnt.coords = [
|
||||
(
|
||||
autorx.config.global_config["station_lon"],
|
||||
autorx.config.global_config["station_lat"],
|
||||
autorx.config.global_config["station_alt"],
|
||||
)
|
||||
]
|
||||
absolute=True,
|
||||
icon=flask.request.url_root + "static/img/antenna-green.png"
|
||||
))
|
||||
|
||||
for rs_id in flask_telemetry_store:
|
||||
try:
|
||||
coordinates = []
|
||||
|
||||
for tp in flask_telemetry_store[rs_id]["track"].track_history:
|
||||
coordinates.append((tp[2], tp[1], tp[3]))
|
||||
coordinates.append((tp[1], tp[2], tp[3]))
|
||||
|
||||
rs_data = """\
|
||||
{type}/{subtype}
|
||||
|
|
@ -208,56 +220,59 @@ def flask_get_kml_feed():
|
|||
icon = flask.request.url_root + "static/img/parachute-green.png"
|
||||
|
||||
# Add folder
|
||||
fol = kml.newfolder(name=rs_id)
|
||||
folder = ET.SubElement(kml_doc, "Folder", id=f"folder_{rs_id}")
|
||||
name = ET.SubElement(folder, "name")
|
||||
name.text = rs_id
|
||||
open = ET.SubElement(folder, "open")
|
||||
open.text = "1"
|
||||
|
||||
# HAB Placemark
|
||||
pnt = fol.newpoint(
|
||||
folder.append(coordinates_to_kml_placemark(
|
||||
flask_telemetry_store[rs_id]["latest_telem"]["lat"],
|
||||
flask_telemetry_store[rs_id]["latest_telem"]["lon"],
|
||||
flask_telemetry_store[rs_id]["latest_telem"]["alt"],
|
||||
name=rs_id,
|
||||
altitudemode=AltitudeMode.absolute,
|
||||
description=rs_data.format(
|
||||
**flask_telemetry_store[rs_id]["latest_telem"]
|
||||
),
|
||||
)
|
||||
pnt.iconstyle.icon.href = icon
|
||||
pnt.coords = [
|
||||
description=rs_data.format(**flask_telemetry_store[rs_id]["latest_telem"]),
|
||||
absolute=True,
|
||||
icon=icon
|
||||
))
|
||||
|
||||
# Track
|
||||
folder.append(path_to_kml_placemark(
|
||||
coordinates,
|
||||
name="Track",
|
||||
absolute=True,
|
||||
extrude=True
|
||||
))
|
||||
|
||||
# LOS line
|
||||
coordinates = [
|
||||
(
|
||||
flask_telemetry_store[rs_id]["latest_telem"]["lon"],
|
||||
flask_telemetry_store[rs_id]["latest_telem"]["lat"],
|
||||
flask_telemetry_store[rs_id]["latest_telem"]["alt"],
|
||||
)
|
||||
]
|
||||
linestring = fol.newlinestring(name="Track")
|
||||
linestring.coords = coordinates
|
||||
linestring.altitudemode = AltitudeMode.absolute
|
||||
linestring.extrude = 1
|
||||
linestring.stylemap.normalstyle.linestyle.color = "ff03bafc"
|
||||
linestring.stylemap.highlightstyle.linestyle.color = "ff03bafc"
|
||||
linestring.stylemap.normalstyle.polystyle.color = "AA03bafc"
|
||||
linestring.stylemap.highlightstyle.polystyle.color = "CC03bafc"
|
||||
# Add LOS line
|
||||
linestring = fol.newlinestring(name="LOS")
|
||||
linestring.altitudemode = AltitudeMode.absolute
|
||||
linestring.coords = [
|
||||
(
|
||||
autorx.config.global_config["station_lon"],
|
||||
autorx.config.global_config["station_lat"],
|
||||
autorx.config.global_config["station_lon"],
|
||||
autorx.config.global_config["station_alt"],
|
||||
),
|
||||
(
|
||||
flask_telemetry_store[rs_id]["latest_telem"]["lon"],
|
||||
flask_telemetry_store[rs_id]["latest_telem"]["lat"],
|
||||
flask_telemetry_store[rs_id]["latest_telem"]["lon"],
|
||||
flask_telemetry_store[rs_id]["latest_telem"]["alt"],
|
||||
),
|
||||
]
|
||||
folder.append(path_to_kml_placemark(
|
||||
coordinates,
|
||||
name="LOS",
|
||||
track_color="ffffffff",
|
||||
absolute=True,
|
||||
extrude=False
|
||||
))
|
||||
|
||||
except Exception as e:
|
||||
logging.error(
|
||||
"KML - Could not parse data from RS %s - %s" % (rs_id, str(e))
|
||||
)
|
||||
|
||||
return (
|
||||
re.sub("<Document.*>", "<Document>", kml.kml()),
|
||||
200,
|
||||
{"content-type": "application/vnd.google-earth.kml+xml"},
|
||||
)
|
||||
kml_string = ET.tostring(kml_root, encoding="UTF-8", xml_declaration=True)
|
||||
return kml_string, 200, {"content-type": "application/vnd.google-earth.kml+xml"}
|
||||
|
||||
|
||||
@app.route("/get_config")
|
||||
|
|
|
|||
|
|
@ -5,5 +5,4 @@ flask-socketio
|
|||
numpy
|
||||
requests
|
||||
semver
|
||||
simplekml
|
||||
simple-websocket
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue