As the gps time reading is quite unreliable, instead use current server system time when the gps time is farer away than 24h (timezone adjusted).
165 lines
5.7 KiB
Python
165 lines
5.7 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')
|
|
|
|
current_datetime = datetime.now(dttz.utc)
|
|
date_yesterday = current_datetime - timedelta(days=1)
|
|
date_tomorrow = current_datetime + timedelta(days=1)
|
|
|
|
|
|
@app.route('/')
|
|
def hello():
|
|
return 'Hello!'
|
|
|
|
@app.route('/updateGPS')
|
|
def getGpsDistance():
|
|
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')
|
|
if gpsDateTime > date_tomorrow or current_datetime < date_yesterday:
|
|
gpsDateTime = datetime.now(dttz.utc)
|
|
print(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:
|
|
print(timezone_str)
|
|
print(pytz.timezone(timezone_str))
|
|
rTime = rTime.replace(tzinfo=dttz.utc).astimezone(pytz.timezone(timezone_str))
|
|
|
|
print(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}')
|
|
|
|
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:
|
|
print(rTime)
|
|
|
|
|
|
|
|
else:
|
|
|
|
print(timezone_str)
|
|
print(pytz.timezone(timezone_str))
|
|
rTime = rTime.replace(tzinfo=dttz.utc).astimezone(pytz.timezone(timezone_str))
|
|
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
|