festival_finder/server/python_server.py

167 lines
6.1 KiB
Python

from flask import Flask, request, jsonify
from datetime import datetime, timedelta
import pint
import sqlite3
from pyproj import Geod
import timezonefinder, pytz
from datetime import timezone as dttz
app = Flask(__name__)
bear_correction = False
with sqlite3.connect('location.db', check_same_thread=False) as conn:
cur = conn.cursor()
cur.execute("""CREATE TABLE IF NOT EXISTS location_data (
row_id INTEGER PRIMARY KEY,
sender_id INTEGER,
lat REAL,
long REAL,
gpsDateTime INTEGER,
insertDateTime TEXT DEFAULT CURRENT_TIMESTAMP
);"""
)
ureg = pint.UnitRegistry()
geodesic = Geod(ellps='WGS84')
@app.route('/')
def hello():
return 'Hello!'
@app.route('/updateGPS')
def getGpsDistance():
current_datetime = datetime.now(dttz.utc)
date_yesterday = current_datetime - timedelta(days=1)
date_tomorrow = current_datetime + timedelta(days=1)
own_id = request.args.get('id')
req_id = request.args.get('req_id')
lat = request.args.get('lat').translate(str.maketrans('', '', ':'))
long = request.args.get('long').translate(str.maketrans('', '', ':'))
lat = dm(lat) if lat and len(lat) > 1 else 0.0
long = dm(long) if long and len(long) > 1 else 0.0
valid_date = True
print(request.args)
try:
gpsDateTime = datetime.strptime(request.args.get('gpsDateTime')[:11], '%d%m%y%H%M%S').replace(tzinfo=dttz.utc)
if gpsDateTime > date_tomorrow or current_datetime < date_yesterday:
gpsDateTime = datetime.now(dttz.utc)
print(f'GPS datetime out of boundaries - replacing with system time: {gpsDateTime}')
except ValueError:
print("No gpsDateTime")
gpsDateTime = datetime.now(dttz.utc)
with sqlite3.connect('location.db', check_same_thread=False) as conn:
timezone = None
rTime = None
cur = conn.cursor()
try:
res = cur.execute(f'SELECT lat, long, gpsDateTime, insertDateTime FROM location_data WHERE sender_id = {req_id} ORDER BY ROWID DESC LIMIT 1;')
row = res.fetchone()
if row:
req_lat, req_long, req_dateTime, insertDateTime = row
rTime = datetime.fromisoformat(req_dateTime)
else:
req_lat = 0.0
req_long = 0.0
req_dateTime = datetime.now(dttz.utc)
rTime = datetime.now(dttz.utc)
except sqlite3.Error as error:
print("Failed to read data from table, using default values", error)
req_lat = 0.0
req_long = 0.0
req_dateTime = datetime.now(dttz.utc)
if (((lat > 0.005 or lat < -0.005) and (long > 0.005 or long < - 0.005)) and valid_date):
cur.execute(f'INSERT INTO location_data(sender_id, lat, long, gpsDateTime) VALUES({own_id}, {lat}, {long}, "{gpsDateTime.isoformat()}");')
conn.commit()
print(f'lat: {lat}, long: {long}, req_lat: {req_lat}, req_long: {req_long}, req_dateTime: {req_dateTime}')
fwd_azimuth, back_azimuth, distance = geodesic.inv(long, lat, req_long, req_lat)
distance = distance * ureg.meter
prettyDistance = f"{distance:.1f~#P}" + ' (N)' if not bear_correction else ''
print(f'fwd: {fwd_azimuth}, bwd: {back_azimuth}, dist: {prettyDistance}')
tf = timezonefinder.TimezoneFinder()
timezone_str = tf.certain_timezone_at(lat=lat, lng=long)
if timezone_str is None:
print("Could not determine the time zone")
else:
rTime = rTime.replace(tzinfo=dttz.utc).astimezone(pytz.timezone(timezone_str))
print(f'GPS datetime of requested database entry: {rTime}')
else:
try:
res = cur.execute(f'SELECT lat, long, gpsDateTime, insertDateTime FROM location_data WHERE sender_id = {own_id} ORDER BY ROWID DESC LIMIT 1;')
row = res.fetchone()
if row:
lat, long, lastOwnDateTime, lastOwnInsertDateTime = row
print(f'lat: {lat}, long: {long}, req_lat: {req_lat}, req_long: {req_long}, req_dateTime: {req_dateTime}')
rTime = datetime.fromisoformat(req_dateTime)
if rTime < date_tomorrow and current_datetime > date_yesterday:
fwd_azimuth, back_azimuth, distance = geodesic.inv(long, lat, req_long, req_lat)
distance = distance * ureg.meter
prettyDistance = f"{distance:.1f~#P}" + ' (N)' if not bear_correction else ''
print(f'fwd: {fwd_azimuth}, bwd: {back_azimuth}, dist: {prettyDistance}')
tf = timezonefinder.TimezoneFinder()
timezone_str = tf.certain_timezone_at(lat=lat, lng=long)
if timezone_str is None:
print("Could not determine the time zone")
else:
rTime = rTime.replace(tzinfo=dttz.utc).astimezone(pytz.timezone(timezone_str))
else:
prettyDistance = "Invalid GPS Signal"
fwd_azimuth = 0.0
rTime = datetime.utcnow()
else:
prettyDistance = "Invalid GPS Signal"
fwd_azimuth = 0.0
rTime = datetime.utcnow()
except sqlite3.Error as error:
print("Failed to read data for last own entry from table -- ignore", error)
prettyDistance = "Invalid GPS Signal"
fwd_azimuth = 0.0
rTime = datetime.now(dttz.utc)
return jsonify({'distance': prettyDistance, 'azimuth': fwd_azimuth, 'lastUpdateTZ': rTime.strftime("%m/%d %H:%M:%S"), 'bear_correction': bear_correction})
def dm(ddmm: str):
south = False
south = 'S' in str(ddmm) or 'W' in str(ddmm)
ddmm = float(str(ddmm)[:-1])
degrees = int(ddmm) // 100
minutes = ddmm - 100*degrees
x = degrees + minutes/60
if south:
x = -x
return x