From ce8991bebf3239b23e54429a8e886dc4b588d4e4 Mon Sep 17 00:00:00 2001 From: Adnan Memic Date: Sun, 16 Feb 2020 18:40:08 +0000 Subject: [PATCH] init --- .gitignore | 14 ++++ _scripts/setup.sh | 5 ++ location_app/.flaskenv | 5 ++ location_app/app/__init__.py | 13 ++++ location_app/app/configuration.cfg | 9 +++ .../app/functions/auth/password_check.py | 70 +++++++++++++++++++ .../app/functions/data_tools/data_getter.py | 51 ++++++++++++++ location_app/app/mqtt/__init__.py | 13 ++++ location_app/app/mqtt/mqtt_message_handler.py | 33 +++++++++ location_app/app/routes/__init__.py | 4 ++ location_app/app/routes/login.py | 21 ++++++ location_app/app/static/css/base.css | 3 + location_app/app/templates/_template.html | 19 +++++ location_app/app/templates/base.html | 18 +++++ location_app/app/templates/index.html | 21 ++++++ location_app/app/templates/index2.html | 19 +++++ location_app/app/templates/main.html | 53 ++++++++++++++ location_app/location_app.py | 1 + location_app/mqtt.coventry.ac.uk.crt | 31 ++++++++ location_app/requirements.txt | 12 ++++ 20 files changed, 415 insertions(+) create mode 100644 .gitignore create mode 100644 _scripts/setup.sh create mode 100644 location_app/.flaskenv create mode 100644 location_app/app/__init__.py create mode 100644 location_app/app/configuration.cfg create mode 100644 location_app/app/functions/auth/password_check.py create mode 100644 location_app/app/functions/data_tools/data_getter.py create mode 100644 location_app/app/mqtt/__init__.py create mode 100644 location_app/app/mqtt/mqtt_message_handler.py create mode 100644 location_app/app/routes/__init__.py create mode 100644 location_app/app/routes/login.py create mode 100644 location_app/app/static/css/base.css create mode 100644 location_app/app/templates/_template.html create mode 100644 location_app/app/templates/base.html create mode 100644 location_app/app/templates/index.html create mode 100644 location_app/app/templates/index2.html create mode 100644 location_app/app/templates/main.html create mode 100644 location_app/location_app.py create mode 100644 location_app/mqtt.coventry.ac.uk.crt create mode 100644 location_app/requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f084d1d --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# Codio +.codio + +# Databases +databases/ + +# Python +__pycache__/ + +# Flask +venv/ + +# Test +*_test/ \ No newline at end of file diff --git a/_scripts/setup.sh b/_scripts/setup.sh new file mode 100644 index 0000000..8fb45d9 --- /dev/null +++ b/_scripts/setup.sh @@ -0,0 +1,5 @@ +sudo apt-get update +sudo apt-get install python3-venv + +mkdir location_app location_app/app +python3 -m venv location_app/venv diff --git a/location_app/.flaskenv b/location_app/.flaskenv new file mode 100644 index 0000000..6664273 --- /dev/null +++ b/location_app/.flaskenv @@ -0,0 +1,5 @@ +FLASK_APP=location_app.py +FLASK_ENV=development +FLASK_RUN_HOST='0.0.0.0' +FLASK_RUN_PORT=3000 +MYAPP_SETTINGS=configuration.cfg diff --git a/location_app/app/__init__.py b/location_app/app/__init__.py new file mode 100644 index 0000000..d3fc97f --- /dev/null +++ b/location_app/app/__init__.py @@ -0,0 +1,13 @@ +from flask import Flask +from app import mqtt, routes + + +app = Flask(__name__) +app.config.from_envvar('MYAPP_SETTINGS') + +mqtt.init_app(app) + +routes.init_app(app) + + + diff --git a/location_app/app/configuration.cfg b/location_app/app/configuration.cfg new file mode 100644 index 0000000..01bc240 --- /dev/null +++ b/location_app/app/configuration.cfg @@ -0,0 +1,9 @@ +MQTT_BROKER_URL='mqtt.coventry.ac.uk' +MQTT_BROKER_PORT=8883 +MQTT_USERNAME='4009user' +MQTT_PASSWORD='mqttBROKER' +MQTT_TLS_ENABLED=True +MQTT_TLS_INSECURE=True +MQTT_TLS_CA_CERTS='mqtt.coventry.ac.uk.crt' +MQTT_REFRESH_TIME=1.0 +TEMPLATES_AUTO_RELOAD=True \ No newline at end of file diff --git a/location_app/app/functions/auth/password_check.py b/location_app/app/functions/auth/password_check.py new file mode 100644 index 0000000..be9a672 --- /dev/null +++ b/location_app/app/functions/auth/password_check.py @@ -0,0 +1,70 @@ +import sqlite3 as sql + + +database_user = "app/databases/users.db" +database_locations = 'app/databases/locations.db' + +def if_user_exists(username): + print(f"checked for existance - {username}") + with sql.connect(database_user) as cur: + res = cur.execute(f"SELECT count(*) FROM UserDatabase WHERE username='{username}';").fetchone()[0] + if res == 0: + return False + else: + return True + +def if_tid_exists(username): + print(f"checked for tid existance - {username}") + with sql.connect(database_locations) as cur: + res = cur.execute(f"SELECT count(*) FROM Location WHERE tid='{username}';").fetchone()[0] + if res == 0: + return False + else: + return True + +def password_for(username, password): + print(f"checked password - {username}") + with sql.connect(database_user) as cur: + res = cur.execute(f"SELECT password FROM UserDatabase WHERE username='{username}';").fetchone()[0] + if password == res: + return True + else: + return False + +def make_user(username, password): + print(f"created a new user - {username}") + con = sql.connect(database_user) + cur = con.cursor() + cur.execute(f"INSERT INTO UserDatabase values('{username}','{password}');") + con.commit() + cur.close() + con.close() + +def change_password(username, new_password): + print(f"created a new password - {username}") + con = sql.connect(database_user) + cur = con.cursor() + cur.execute(f"UPDATE UserDatabase SET password='{new_password}' WHERE username='{username}';") + con.commit() + cur.close() + con.close() + +def username_and_password(username, password): + with sql.connect(database_user) as cur: + try: + cur.execute("CREATE TABLE UserDatabase(username VARCHAR2(20), password VARCHAR2(20));") + except: + pass + if username == "admin" and password == "admin": + return "L" + if if_user_exists(username): + if password_for(username, password): + return "L" + else: + return "WP" + else: + if if_tid_exists(username): + make_user(username, password) + return "L" + else: + return "NO" \ No newline at end of file diff --git a/location_app/app/functions/data_tools/data_getter.py b/location_app/app/functions/data_tools/data_getter.py new file mode 100644 index 0000000..747348f --- /dev/null +++ b/location_app/app/functions/data_tools/data_getter.py @@ -0,0 +1,51 @@ +import sqlite3 as sql +import time + + +database_user = "app/databases/users.db" +database_locations = "app/databases/locations.db" + +def get_user_for(username): + with sql.connect(database_user) as cur: + res = cur.execute(f"SELECT * FROM UserDatabase WHERE username='{username}';").fetchone() + +def get_filtered_data_for(tid): + data_city = get_frequency_for('city', tid) + data_road = get_frequency_for('road', tid) + data_batt = get_frequency_for('battery', tid) + return [data_city, data_road, data_batt] + +def get_all_tids(): + with sql.connect(database_locations) as cur: + tids = cur.execute("SELECT DISTINCT tid From Location;") + tids_list = list(map(lambda x: x[0], tids)) + return tids_list + +def get_frequency_for(data_type, tid): + with sql.connect(database_locations) as cur: + data = cur.execute(f"SELECT {data_type} From Location WHERE tid = '{tid}';") + data_list = list(map(lambda x: x[0], data)) + frequent_data = max(set(data_list), key = data_list.count) + frequency_data = str(int((data_list.count(frequent_data)/len(data_list)) * 100)) + return [frequent_data, frequency_data] + +def get_filtered_data_for_admin(): + all_data = [] + tids = get_all_tids() + for tid in tids: + data_city = get_frequency_for('city', tid) + data_road = get_frequency_for('road', tid) + data_batt = get_frequency_for('battery', tid) + all_data.append([tid, data_city, data_road, data_batt]) + return all_data + +def get_locations(): + locations = [] + with sql.connect(database_locations) as cur: + res = cur.execute(f"SELECT DISTINCT * From Location ORDER BY tid, timestamp;") + for tid, batt, lon, lat, city, road, tst, in res: + rtst = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(tst)) + locations.append([tid, batt, lon, lat, city, road, rtst]) + print(locations) + return locations + \ No newline at end of file diff --git a/location_app/app/mqtt/__init__.py b/location_app/app/mqtt/__init__.py new file mode 100644 index 0000000..8056420 --- /dev/null +++ b/location_app/app/mqtt/__init__.py @@ -0,0 +1,13 @@ +from flask_mqtt import Mqtt +from app.mqtt import mqtt_message_handler + +def init_app(app): + mqtt = Mqtt(app) + + @mqtt.on_connect() + def handle_connect(client, userdata, flags, rc): + mqtt.subscribe('owntracks/4009user/#') + + @mqtt.on_message() + def handle_mqtt_message(client, userdata, msg): + mqtt_message_handler.getMsg(msg) diff --git a/location_app/app/mqtt/mqtt_message_handler.py b/location_app/app/mqtt/mqtt_message_handler.py new file mode 100644 index 0000000..995460f --- /dev/null +++ b/location_app/app/mqtt/mqtt_message_handler.py @@ -0,0 +1,33 @@ +from geopy.geocoders import Nominatim +import sqlite3 as sql +import json, os, time + + +database_locations = 'app/databases/locations.db' + +def getMsg(msg): + con = sql.connect(database_locations) + cur = con.cursor() + geolocator = Nominatim(user_agent="Web_app") + try: + cur.execute("CREATE TABLE Location(tid VARCHAR2(2), battery INT(3), longitude NUMBER(10,6), latitude NUMBER(10,6), city VARCHAR2(20), road VARCHAR2(30), timestamp INT(20));") + except: + pass + data = json.loads(msg.payload.decode("utf8")) + tid = data["tid"] + batt = data["batt"] + lat = data["lat"] + lon = data["lon"] + location = geolocator.reverse(f"{data['lat']},{data['lon']}") + city = location.raw["address"]["city"] + road = location.raw["address"]["road"] + tstamp = data["tst"] + + print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(tstamp)), ' ---- ', tid) + + cur.execute(f"INSERT INTO Location values('{tid}','{batt}','{lat}','{lon}','{city}','{road}','{tstamp}');") + + con.commit() + cur.close() + con.close() + \ No newline at end of file diff --git a/location_app/app/routes/__init__.py b/location_app/app/routes/__init__.py new file mode 100644 index 0000000..2011db0 --- /dev/null +++ b/location_app/app/routes/__init__.py @@ -0,0 +1,4 @@ +from .login import main_bl + +def init_app(app): + app.register_blueprint(main_bl) \ No newline at end of file diff --git a/location_app/app/routes/login.py b/location_app/app/routes/login.py new file mode 100644 index 0000000..860fa6b --- /dev/null +++ b/location_app/app/routes/login.py @@ -0,0 +1,21 @@ +from flask import Blueprint, render_template, request, url_for, escape, redirect +from app.functions.auth import password_check +from app.functions.data_tools import data_getter + +main_bl = Blueprint('main', __name__) + +@main_bl.route("/", methods = ["GET", "POST"]) +@main_bl.route("/index", methods = ["GET", "POST"]) +def login(): + if request.method == "POST": + username = request.form["username"] + password = request.form["password"] + status = password_check.username_and_password(username, password) + if status == "L": + return redirect(url_for("testt", username = username)) + elif status == "WP": + return render_template("index.html", error = 1) + elif status == "NO": + return render_template("index.html", error = 2) + else: + return render_template("index.html", error = 0) \ No newline at end of file diff --git a/location_app/app/static/css/base.css b/location_app/app/static/css/base.css new file mode 100644 index 0000000..438954d --- /dev/null +++ b/location_app/app/static/css/base.css @@ -0,0 +1,3 @@ +body { + background-color: red; +} \ No newline at end of file diff --git a/location_app/app/templates/_template.html b/location_app/app/templates/_template.html new file mode 100644 index 0000000..30e6843 --- /dev/null +++ b/location_app/app/templates/_template.html @@ -0,0 +1,19 @@ +{% extends 'base.html' %} + + +{% block title %} " Insert title here " {% endblock %} + + +{% block css %} + + " Insert css here " + +{% endblock %} + + +{% block body %} + + " Insert body here " + +{% endblock %} + diff --git a/location_app/app/templates/base.html b/location_app/app/templates/base.html new file mode 100644 index 0000000..c578e43 --- /dev/null +++ b/location_app/app/templates/base.html @@ -0,0 +1,18 @@ + + + + + + + + + {% block title %}{% endblock %} + + {% block css %}{% endblock %} + + + + {% block body %}{% endblock %} + + + \ No newline at end of file diff --git a/location_app/app/templates/index.html b/location_app/app/templates/index.html new file mode 100644 index 0000000..e272b52 --- /dev/null +++ b/location_app/app/templates/index.html @@ -0,0 +1,21 @@ +{% extends 'base.html' %} + +{% block title %} Trackmaster {% endblock %} + +{% block body %} + +{% if error == 1 %} +

WRONG PASSWORD!!!

+{% endif %} +{% if error == 2 %} +

WRONG TID!!!

+{% endif %} +
+ + + + + +
+ +{% endblock %} diff --git a/location_app/app/templates/index2.html b/location_app/app/templates/index2.html new file mode 100644 index 0000000..9e704e0 --- /dev/null +++ b/location_app/app/templates/index2.html @@ -0,0 +1,19 @@ +{% extends 'base.html' %} + + +{% block title %} " Insert title here " {% endblock %} + + +{% block body %} + +{% for idd in tids %} +

{{idd}}

+{% endfor %} +
+ + +
+ +{% endblock %} + + diff --git a/location_app/app/templates/main.html b/location_app/app/templates/main.html new file mode 100644 index 0000000..3e6bf08 --- /dev/null +++ b/location_app/app/templates/main.html @@ -0,0 +1,53 @@ + + + + + + Trackmaster + + + + + + + + + + + + + + + + + {% for item in locations %} + + + + + + + + + + + + {% endfor %} +
Locations
IDBatteryLongitudeLatitudeCityRoadTST
{{ item[0] }}{{ item[1] }} %{{ item[2] }}{{ item[3] }}{{ item[4] }}{{ item[5] }}{{ item[6] }}
+ + + diff --git a/location_app/location_app.py b/location_app/location_app.py new file mode 100644 index 0000000..e524e69 --- /dev/null +++ b/location_app/location_app.py @@ -0,0 +1 @@ +from app import app \ No newline at end of file diff --git a/location_app/mqtt.coventry.ac.uk.crt b/location_app/mqtt.coventry.ac.uk.crt new file mode 100644 index 0000000..df5a27f --- /dev/null +++ b/location_app/mqtt.coventry.ac.uk.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 +MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf +qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW +n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym +c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ +O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 +o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j +IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq +IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz +8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh +vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l +7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG +cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD +ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC +roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga +W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n +lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE ++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV +csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd +dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg +KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM +HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 +WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M +-----END CERTIFICATE----- diff --git a/location_app/requirements.txt b/location_app/requirements.txt new file mode 100644 index 0000000..1b25853 --- /dev/null +++ b/location_app/requirements.txt @@ -0,0 +1,12 @@ +Click==7.0 +Flask==1.1.1 +Flask-MQTT==1.1.0 +geographiclib==1.50 +geopy==1.21.0 +itsdangerous==1.1.0 +Jinja2==2.11.1 +MarkupSafe==1.1.1 +paho-mqtt==1.5.0 +pkg-resources==0.0.0 +python-dotenv==0.11.0 +Werkzeug==1.0.0