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