import sys import os import logging from flask import Flask, jsonify, send_from_directory, request from dotenv import load_dotenv from sqlalchemy.orm import sessionmaker, Session from modules.driverHandler import DriverHandler from modules.gpxInterpreter import GPXHandler from modules.vehicleHandler import VehicleHandler from modules.geoObjects import Waypoint, create_table, db_connect, Driver, Vehicle from flask_cors import CORS, cross_origin root = logging.getLogger() root.setLevel(logging.DEBUG) handler = logging.StreamHandler(sys.stdout) handler.setLevel(logging.DEBUG) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) root.addHandler(handler) print("load environment") load_dotenv() print("create flask application") app = Flask(__name__, static_folder='web/dist') cors = CORS(app) # allow CORS for all domains on all routes. app.config['CORS_HEADERS'] = 'Content-Type' app.logger.setLevel(logging.DEBUG) print("initialize database") engine = db_connect() SessionFactory = sessionmaker(bind=engine) session = SessionFactory() create_table(engine) print("pushing initial data if not already happened") try: defDriver = session.query(Driver).filter(id=1) defVehicle = session.query(Vehicle).filter(id=1) if not defDriver and not defVehicle: defaultVehicle = Vehicle(id=1, name="default", licenseplate="default") defaultDriver = Driver(id=1, name="default") session.add(defaultVehicle) session.add(defaultDriver) session.commit() session.flush() except: print("default data not pushed as already present") session.flush() print("initialize handlers") gpxHandler = GPXHandler(session) driverHandler = DriverHandler(session) vehicleHandler = VehicleHandler(session) @app.route('/') @cross_origin() def serve_vue_app(): return send_from_directory(app.static_folder, 'index.html') @app.route("/track", methods=['GET', 'DELETE']) @cross_origin() def getTrack(): app.logger.debug(f"found arguments {request.args}") match request.method: case "GET": if ("start" in request.args and "end" in request.args) or ("id" in request.args): if "start" in request.args and "end" in request.args: if "asMap" in request.args: # get tracks by filter start = request.args["start"] end = request.args["end"] # Die GeoJSON-Daten aus der Datenbank abrufen geojson_data = gpxHandler.getTracksInTimeWithGeoData( start, end) app.logger.debug(f"returned track {geojson_data}") # Die GeoJSON-Daten als JSON zurückgeben return jsonify(geojson_data) # get tracks by filter start = request.args["start"] end = request.args["end"] try: return gpxHandler.getTracksInTime(start, request.args["end"]), 200 except Exception as e: app.logger.debug(f"failed to search tracks error { e} values: start={start}, end={end}") return f"error {e}", 500 elif "id" in request.args: # get track by id trackID = int(request.args["id"]) try: app.logger.debug(f"Request args: {request.args}") app.logger.debug(f"track id {trackID}") track = gpxHandler.getTrack(trackID) app.logger.debug(f"returned track {track}") return jsonify(track), 200 except Exception as e: app.logger.debug(f"fetching track failed with error {e}") return f"error {e}", 500 else: try: tracks = gpxHandler.getTracks() if len(tracks) > 0: # gets all tracks as list return tracks, 200 else: return [], 200 except Exception as e: app.logger.debug(f"fetching all tracks failed with error {e}") return f"error {e}", 500 case "DELETE": data = request.get_json() if "id" not in data: return "no if found", 400 try: gpxHandler.deleteTrack(data["id"]) return "track deleted", 200 except Exception as e: return f"couldnt delete track due to error: {e}", 500 @app.route("/track/meta", methods=['GET']) @cross_origin() def getTrackMeta(): app.logger.debug(f"found arguments {request.args}") if "id" in request.args: # get track by id trackID = int(request.args["id"]) try: app.logger.debug(f"Request args: {request.args}") app.logger.debug(f"track id {trackID}") track = gpxHandler.getTrackMeta(trackID) app.logger.debug(f"returned track {track}") return jsonify(track), 200 except Exception as e: app.logger.debug(f"fetching track failed with error {e}") return f"error {e}", 500 @app.route("/driver", methods=['GET', 'POST', 'PUT', 'DELETE']) @cross_origin() def handleDriverRoute(): match request.method: case "GET": if 'driver' in request.args: try: driver = driverHandler.getDriver(int(request.args["driver"])) return driver, 200 except Exception as e: app.logger.debug(f"getting driver failed with error {e}") return "error" + " " + str(e), 500 else: try: drivers = driverHandler.getDrivers() if len(drivers) > 0: return drivers, 200 except Exception as e: app.logger.debug(f"getting drivers failed with error {e}") return "error" + " " + str(e), 500 case "POST": # grabbing json from request data = request.get_json() app.logger.debug(f"json request payload: {data}") if "name" not in data: app.logger.debug(f"no driver name was found in request") return "missing name", 400 app.logger.debug(f"driver name has passed check {data["name"]}") # handle creating vehicle try: app.logger.debug(f"json request name: {data["name"]}") driver = driverHandler.createDriver(data["name"]) return jsonify({"name": driver.name, "id": driver.id}), 200 except Exception as e: app.logger.debug(f"creating drivers failed with error {e}") return "error" + " " + str(e), 500 case "DELETE": data = request.get_json() if "id" not in data: return "no if found", 400 try: if data["id"] == 1: return "deleting defaults is forbidden", 400 driverHandler.deleteDriver(data["id"]) return "driver deleted", 200 except Exception as e: return f"couldnt delete driver due to error: {e}", 500 @app.route("/vehicle", methods=['GET', 'POST', 'PUT', 'DELETE']) @cross_origin() def handleVehicleRoute(): match request.method: case "GET": if 'vehicle' in request.args: app.logger.debug(f"no vehicle id was found in request") vehicle = int(request.args["vehicle"]) try: foundVehicle = vehicleHandler.getVehicle(vehicle) return foundVehicle, 200 except Exception as e: app.logger.debug(f"getting vehicle {vehicle} failed with error {e}") return "error" + " " + str(e), 500 else: try: foundVehicles = vehicleHandler.getVehicles() return foundVehicles, 200 except Exception as e: app.logger.debug( f"getting all vehicles failed with error {e}") return "error" + " " + str(e), 500 case "POST": data = request.get_json() app.logger.debug(f"json request payload: {data}") if "name" not in data: return "missing name", 400 licenseplate = "" if "licensePlate" not in data: licenseplate = "N/A" else: licenseplate = data["licensePlate"] name = data["name"] # handle creating vehicle try: vehicle = vehicleHandler.createVehicle(name, licenseplate) return jsonify({"id": vehicle.id, "name": vehicle.name}), 200 except Exception as e: app.logger.debug(f"creating vehicle with name {name} failed with error {e}") return "error" + " " + str(e), 500 case "DELETE": data = request.get_json() if "id" not in data: return "no if found", 400 try: if data["id"] == 1: return "deleting defaults is forbidden", 400 vehicleHandler.deleteVehicle(data["id"]) return "vehicle deleted", 200 except Exception as e: return f"couldnt delete vehicle due to error: {e}", 500 @app.route('/upload', methods=['POST']) @cross_origin() def uploadFile(): if 'file' not in request.files: app.logger.debug("no file was found in clients request") return "no file provided", 400 file = request.files['file'] if file.filename == '': app.logger.debug("filename was found empty") return "no file selected", 400 try: app.logger.debug(f"Received file: {file.filename}, size: {len(file.read())} bytes") file.seek(0) file_path = f'./uploads/{file.filename}' with open(file_path, 'wb') as f: f.write(file.read()) driverID = int(request.form.get('driverID')) vehicleID = int(request.form.get('vehicleID')) driver = driverHandler.getDriver(driverID) vehicle = vehicleHandler.getVehicle(vehicleID) app.logger.debug(f"driver {driver.id}") app.logger.debug(f"vehicle {vehicle.id}") if not driver or not vehicle: raise ValueError("Driver or vehicle not found") app.logger.debug(f"attempting to parse file: {file.filename}") gpxHandler.parse(file.filename, driver, vehicle) return "file stored succesfull", 200 except Exception as e: app.logger.debug(f"storing gpx file failed with error {e}") return "error" + " " + str(e), 500 if __name__ == '__main__': app.run(debug=True) app.logger.debug("flask app started")