diff --git a/RaspberryPie/dataHandling.py b/RaspberryPie/dataHandling.py index c53566b..5c4b919 100644 --- a/RaspberryPie/dataHandling.py +++ b/RaspberryPie/dataHandling.py @@ -1,6 +1,7 @@ #general imports import datetime import sqlite3 +import base64 # imports from Project from RaspberryPie.logger import captScribe @@ -12,6 +13,7 @@ class BGenSecretary: self.database = database_path self.image_path = image_path + def _record(self, data: dict): connection = None try: @@ -31,13 +33,65 @@ class BGenSecretary: if connection is sqlite3.Connection: connection.close() - def recordPicture(self, picture): + def recordPicture(self, picture: bytes): with open("{}/{}.jpg".format(self.image_path, str(datetime.datetime.now())), "w") as f: f.write(picture) - self._record({"picture": {"picture": picture}}) + self._record({"picture": {"picture": base64.encodebytes(picture).decode('ascii').replace("\n", "")}}) def recordAir(self, data): self._record({"air": {"temperature": data[0], "humidity": data[1]}}) + + def _fetchSingle(self, table, time: datetime.datetime): + unix_time = int(time.timestamp()) + command = "SELECT * FROM {} ORDER BY ABS(unix_time - {}) ASC LIMIT 1".format(table, unix_time) + connection, entry = None + try: + connection = sqlite3.connect(self.database) + cursor = connection.cursor() + cursor.execute(command) + entry = cursor.fetchone() + captScribe.info("Fetched entry for {} from {}".format(str(unix_time), table), "BGenSecretary._fetchSingle") + except sqlite3.Error as e: + captScribe.error(str(e), "BGenSecretary._fetchSingle") + finally: + if connection is sqlite3.Connection: + connection.close() + return tuple(entry) if entry is sqlite3.Row else None + + def _fetchMultiple(self, table, end:datetime.datetime, start: datetime.datetime): + unix_time_end = int(end.timestamp()) + unix_time_start = int(start.timestamp()) + command = "SELECT * FROM {} WHERE unix_time BETWEEN {} AND {}".format(unix_time_start, unix_time_end) + connection, entries = None + try: + connection = sqlite3.connect(self.database) + cursor = connection.cursor() + cursor.execute(command) + entries = cursor.fetchall() + captScribe.info("Fetched entries for {} from {}".format(str((unix_time_start, unix_time_end)), table), "BGenSecretary._fetchSingle") + except sqlite3.Error as e: + captScribe.error(str(e), "BGenSecretary._fetchSingle") + finally: + if connection is sqlite3.Connection: + connection.close() + return [tuple(entry) for entry in entries] if entries is not None else None + + def fetchAir(self, time=datetime.datetime.now(), start_time=None): # time is either one point or the end point if start is given + if not start_time: + entry = self._fetchSingle("air", time) + return {"unix_time": entry[0], "time_string": entry[1], "temperature": entry[2], "humidity": entry[3]} + else: + entries = self._fetchMultiple("air", time, start_time) + return {"unix_time": [entry[0] for entry in entries], "time_string": [entry[1] for entry in entries], "temperature": [entry[2] for entry in entries], "humidity": [entry[3] for entry in entries]} + + def fetchPicture(self, time=datetime.datetime.now(), start_time=None): + if not start_time: + entry = self._fetchSingle("picture", time) + return {"unix_time": entry[0], "time_string": entry[1], "picture": entry[2]} + else: + entries = self._fetchMultiple("picture", time, start_time) + return {"unix_time": [entry[0] for entry in entries], "time_string": [entry[1] for entry in entries], "picture": [entry[2] for entry in entries]} + bGenSecretary = BGenSecretary(config["File Locations"]["database_file"], config["File Locations"],["image_path"]) \ No newline at end of file diff --git a/RaspberryPie/database.db b/RaspberryPie/database.db index bd5446f..c964cd1 100644 Binary files a/RaspberryPie/database.db and b/RaspberryPie/database.db differ diff --git a/RaspberryPie/flaskAddons.py b/RaspberryPie/flaskAddons.py new file mode 100644 index 0000000..1771b62 --- /dev/null +++ b/RaspberryPie/flaskAddons.py @@ -0,0 +1,19 @@ +import datetime +from RaspberryPie.config import config +from RaspberryPie.dataHandling import bGenSecretary + +def time(): return "" + +def weatherUrls(): return [config["WeatherUrls"][i] for i in config["WeatherUrls"]] + +def getLatestAirData(): return bGenSecretary.fetchAir() + +def getLatestPicture(): return bGenSecretary.fetchAir() + +def getDataRangeAir(start: int, end: int): return bGenSecretary.fetchAir(datetime.datetime.utcfromtimestamp(end), datetime.datetime.utcfromtimestamp(start)) + +def getDataRangePictures(start: int, end: int): return bGenSecretary.fetchPicture(datetime.datetime.utcfromtimestamp(end), datetime.datetime.utcfromtimestamp(start)) + +def getSingleAirData(time: int): return bGenSecretary.fetchAir(datetime.datetime.utcfromtimestamp(time)) + +def getSinglePicture(time: int): return bGenSecretary.fetchPicture(datetime.datetime.utcfromtimestamp(time)) \ No newline at end of file diff --git a/RaspberryPie/flask_backend.py b/RaspberryPie/flask_backend.py index 59a3eed..f0a03b9 100644 --- a/RaspberryPie/flask_backend.py +++ b/RaspberryPie/flask_backend.py @@ -1,15 +1,56 @@ from flask import Flask, render_template, make_response import json +import RaspberryPie.flaskAddons as fa + app = Flask(__name__) @app.route("/") def index(): - pass + latestAirData = fa.getLatestAirData() + latestPicture = fa.getLatestPicture() + return render_template("index.html", + WeatherTime = latestAirData["time_string"], + temp = latestAirData["temperature"], + humi = latestAirData["humidity"], + weather_urls=fa.weatherUrls(), + PictureTime = latestPicture["time_string"], + picture = latestPicture["picture"]) + + @app.route("/data///") -def functionName(start, end): - data = {} - db_entries = getEnvironment(int(start), int(end)) - data["labels"] = db_entries["temperature"][0] - data["temp"] = db_entries["temperature"][1] - data["humi"] = db_entries["humidity"][1] - return json.dumps(data) \ No newline at end of file +def airData(start, end): + data = fa.getDataRangeAir(int(start), int(end)) + return json.dumps(data) + +@app.route("/picture/