Add GPX output option
This commit is contained in:
parent
b7476c5de2
commit
043f4a8569
1 changed files with 95 additions and 41 deletions
136
main.py
136
main.py
|
@ -4,6 +4,8 @@ import configparser
|
||||||
|
|
||||||
import pymysql
|
import pymysql
|
||||||
|
|
||||||
|
GJSON = 0
|
||||||
|
|
||||||
def getDatabase(path = "config.cfg"):
|
def getDatabase(path = "config.cfg"):
|
||||||
config = configparser.RawConfigParser()
|
config = configparser.RawConfigParser()
|
||||||
config.read(path)
|
config.read(path)
|
||||||
|
@ -18,6 +20,83 @@ def getDatabase(path = "config.cfg"):
|
||||||
|
|
||||||
return conn, cur
|
return conn, cur
|
||||||
|
|
||||||
|
def buildGJSON(data):
|
||||||
|
output = """{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
|
||||||
|
"features": [
|
||||||
|
{ "type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"Name": null,
|
||||||
|
"description": null,
|
||||||
|
"timestamp": null,
|
||||||
|
"begin": null,
|
||||||
|
"end": null,
|
||||||
|
"altitudeMode": null,
|
||||||
|
"tessellate": -1,
|
||||||
|
"extrude": 0,
|
||||||
|
"visibility": -1,
|
||||||
|
"drawOrder": null,
|
||||||
|
"icon": null,
|
||||||
|
"styleUrl": "#style",
|
||||||
|
"styleHash": "1a1ac94e",
|
||||||
|
"stroke": "#ffff00",
|
||||||
|
"stroke_opacity": "0.4980392156862745",
|
||||||
|
"stroke_width": "4",
|
||||||
|
"fill": "#00ff00",
|
||||||
|
"fill_opacity": "0.4980392156862745"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "LineString",
|
||||||
|
"coordinates": [
|
||||||
|
"""
|
||||||
|
|
||||||
|
for row in data:
|
||||||
|
output += " [ %s, %s ],\n" % (row["lon"], row["lat"])
|
||||||
|
|
||||||
|
output = "".join(output.rsplit(",", 1))
|
||||||
|
|
||||||
|
output += """ ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}"""
|
||||||
|
|
||||||
|
headers = [["Content-Type", "application/vnd.geo+json"], ['Content-Disposition', 'attachment; filename="export.geojson"']]
|
||||||
|
|
||||||
|
return headers, output
|
||||||
|
|
||||||
|
def buildGPX(data):
|
||||||
|
output = """<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<gpx xmlns="http://www.topografix.com/GPX/1/1" version="1.1" creator="pygps"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
|
||||||
|
<metadata>
|
||||||
|
<name>export.gpx</name>
|
||||||
|
<desc>GPS Data Export</desc>
|
||||||
|
<author>
|
||||||
|
<name>pygps</name>
|
||||||
|
</author>
|
||||||
|
</metadata>
|
||||||
|
<trk>
|
||||||
|
<trkseg>
|
||||||
|
"""
|
||||||
|
|
||||||
|
for row in data:
|
||||||
|
output += """ <trkpt lat="%s" lon="%s">
|
||||||
|
<time>%s</time>
|
||||||
|
</trkpt>
|
||||||
|
""" % (row["lat"], row["lon"], row["ts"].isoformat())
|
||||||
|
|
||||||
|
|
||||||
|
output += """ </trkseg>
|
||||||
|
</trk>
|
||||||
|
</gpx>
|
||||||
|
"""
|
||||||
|
|
||||||
|
headers = [["Content-Type", "application/gpx+xml"], ['Content-Disposition', 'attachment; filename="export.gpx"']]
|
||||||
|
return headers, output
|
||||||
|
|
||||||
def application(env, re):
|
def application(env, re):
|
||||||
if env["REQUEST_METHOD"] == "POST":
|
if env["REQUEST_METHOD"] == "POST":
|
||||||
args = cgi.parse_qs(env['wsgi.input'].readline().decode(), True)
|
args = cgi.parse_qs(env['wsgi.input'].readline().decode(), True)
|
||||||
|
@ -127,6 +206,19 @@ def application(env, re):
|
||||||
frm = on if on else args["from"][0] if "from" in args else None
|
frm = on if on else args["from"][0] if "from" in args else None
|
||||||
to = on if on else args["to"][0] if "to" in args else None
|
to = on if on else args["to"][0] if "to" in args else None
|
||||||
|
|
||||||
|
if "format" in args:
|
||||||
|
if args["format"][0] in ("json", "gjson", "geojson", "gj") or not args["format"]:
|
||||||
|
builder = buildGJSON
|
||||||
|
elif args["format"][0] == "gpx":
|
||||||
|
builder = buildGPX
|
||||||
|
else:
|
||||||
|
re("400 Bad Request", [])
|
||||||
|
yield "<h1>400 Bad Request</h1>".encode()
|
||||||
|
yield "Unknown format: %s" % args["format"]
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
builder = buildGJSON
|
||||||
|
|
||||||
frm = frm or "2000-01-01"
|
frm = frm or "2000-01-01"
|
||||||
to = to or datetime.datetime.now().strftime('%Y-%m-%d')
|
to = to or datetime.datetime.now().strftime('%Y-%m-%d')
|
||||||
|
|
||||||
|
@ -144,49 +236,11 @@ def application(env, re):
|
||||||
sql = "SELECT ts, lat, lon FROM tracker WHERE device=%s AND DATE(ts)>=%s and DATE(ts)<=%s ORDER BY ts ASC;";
|
sql = "SELECT ts, lat, lon FROM tracker WHERE device=%s AND DATE(ts)>=%s and DATE(ts)<=%s ORDER BY ts ASC;";
|
||||||
cur.execute(sql, (device, frm, to))
|
cur.execute(sql, (device, frm, to))
|
||||||
|
|
||||||
re("200 OK", [["Content-Type", "application/vnd.geo+json"], ['Content-Disposition', 'attachment; filename="export.geojson"']])
|
data = cur.fetchall()
|
||||||
|
|
||||||
output = """{
|
headers, output = builder(data)
|
||||||
"type": "FeatureCollection",
|
|
||||||
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
|
|
||||||
"features": [
|
|
||||||
{ "type": "Feature",
|
|
||||||
"properties": {
|
|
||||||
"Name": null,
|
|
||||||
"description": null,
|
|
||||||
"timestamp": null,
|
|
||||||
"begin": null,
|
|
||||||
"end": null,
|
|
||||||
"altitudeMode": null,
|
|
||||||
"tessellate": -1,
|
|
||||||
"extrude": 0,
|
|
||||||
"visibility": -1,
|
|
||||||
"drawOrder": null,
|
|
||||||
"icon": null,
|
|
||||||
"styleUrl": "#style",
|
|
||||||
"styleHash": "1a1ac94e",
|
|
||||||
"stroke": "#ffff00",
|
|
||||||
"stroke_opacity": "0.4980392156862745",
|
|
||||||
"stroke_width": "4",
|
|
||||||
"fill": "#00ff00",
|
|
||||||
"fill_opacity": "0.4980392156862745"
|
|
||||||
},
|
|
||||||
"geometry": {
|
|
||||||
"type": "LineString",
|
|
||||||
"coordinates": [
|
|
||||||
"""
|
|
||||||
|
|
||||||
for row in cur.fetchall():
|
|
||||||
output += " [ %s, %s ],\n" % (row["lon"], row["lat"])
|
|
||||||
|
|
||||||
output = "".join(output.rsplit(",", 1))
|
|
||||||
|
|
||||||
output += """ ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}"""
|
|
||||||
|
|
||||||
|
re("200 OK", headers)
|
||||||
|
|
||||||
cur.close()
|
cur.close()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
Loading…
Reference in a new issue