further additions
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#general imports
|
#general imports
|
||||||
import datetime
|
import datetime
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
import base64
|
||||||
|
|
||||||
# imports from Project
|
# imports from Project
|
||||||
from RaspberryPie.logger import captScribe
|
from RaspberryPie.logger import captScribe
|
||||||
@@ -12,6 +13,7 @@ class BGenSecretary:
|
|||||||
self.database = database_path
|
self.database = database_path
|
||||||
self.image_path = image_path
|
self.image_path = image_path
|
||||||
|
|
||||||
|
|
||||||
def _record(self, data: dict):
|
def _record(self, data: dict):
|
||||||
connection = None
|
connection = None
|
||||||
try:
|
try:
|
||||||
@@ -31,13 +33,65 @@ class BGenSecretary:
|
|||||||
if connection is sqlite3.Connection:
|
if connection is sqlite3.Connection:
|
||||||
connection.close()
|
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:
|
with open("{}/{}.jpg".format(self.image_path, str(datetime.datetime.now())), "w") as f:
|
||||||
f.write(picture)
|
f.write(picture)
|
||||||
|
|
||||||
self._record({"picture": {"picture": picture}})
|
self._record({"picture": {"picture": base64.encodebytes(picture).decode('ascii').replace("\n", "")}})
|
||||||
|
|
||||||
def recordAir(self, data):
|
def recordAir(self, data):
|
||||||
self._record({"air": {"temperature": data[0], "humidity": data[1]}})
|
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"])
|
bGenSecretary = BGenSecretary(config["File Locations"]["database_file"], config["File Locations"],["image_path"])
|
||||||
Binary file not shown.
@@ -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))
|
||||||
@@ -1,15 +1,56 @@
|
|||||||
from flask import Flask, render_template, make_response
|
from flask import Flask, render_template, make_response
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
import RaspberryPie.flaskAddons as fa
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
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/<start>/<end>/")
|
@app.route("/data/<start>/<end>/")
|
||||||
def functionName(start, end):
|
def airData(start, end):
|
||||||
data = {}
|
data = fa.getDataRangeAir(int(start), int(end))
|
||||||
db_entries = getEnvironment(int(start), int(end))
|
return json.dumps(data)
|
||||||
data["labels"] = db_entries["temperature"][0]
|
|
||||||
data["temp"] = db_entries["temperature"][1]
|
@app.route("/picture/<time>/")
|
||||||
data["humi"] = db_entries["humidity"][1]
|
def picture(time):
|
||||||
return json.dumps(data)
|
if time == "latest":
|
||||||
|
return json.dumps(fa.getLatestPicture())
|
||||||
|
else:
|
||||||
|
return json.dumps(fa.getLatestPicture(int(time)))
|
||||||
|
|
||||||
|
@app.route("/initiate/picture/")
|
||||||
|
def inititatePicture():
|
||||||
|
pass
|
||||||
|
|
||||||
|
@app.route("/inititate/air/")
|
||||||
|
def ininitiateAir():
|
||||||
|
pass
|
||||||
|
|
||||||
|
@app.route("/initiate/gpio/<state>/")
|
||||||
|
def ininitisteGPIO(state):
|
||||||
|
try:
|
||||||
|
state = int(state)
|
||||||
|
except:
|
||||||
|
state = state
|
||||||
|
|
||||||
|
if state == "open" or state == 0:
|
||||||
|
return "Opened", 200
|
||||||
|
elif state == "close" or state == 1:
|
||||||
|
return "Closed", 200
|
||||||
|
return "state not found", 404
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/initiate/shutdown/")
|
||||||
|
def initiateShutdown():
|
||||||
|
pass
|
||||||
@@ -58,7 +58,7 @@ class MajGenObserver:
|
|||||||
def write(self, text):
|
def write(self, text):
|
||||||
self.captured = text
|
self.captured = text
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.captured)
|
return self.captured
|
||||||
|
|
||||||
def __init__(self, schedule_timing):
|
def __init__(self, schedule_timing):
|
||||||
self.schedule_timing = schedule_timing
|
self.schedule_timing = schedule_timing
|
||||||
|
|||||||
@@ -19,11 +19,11 @@
|
|||||||
<h2>Weather Forecast</h2>
|
<h2>Weather Forecast</h2>
|
||||||
<canvas id="ForecastChart" width="400" height="200"></canvas>
|
<canvas id="ForecastChart" width="400" height="200"></canvas>
|
||||||
<h2>Third party weather providers</h2>
|
<h2>Third party weather providers</h2>
|
||||||
{% for image in urls %}
|
{% for image in weather_urls %}
|
||||||
<img src="{{ image }}">
|
<img src="{{ image }}">
|
||||||
<h2>Webcam</h2>
|
<h2>Webcam</h2>
|
||||||
<a id="PictureTime">{{ PictureTime }}</a><br>
|
<a id="PictureTime">{{ PictureTime }}</a><br>
|
||||||
<img id="Webcam" src="/latest.jpg">
|
<img id="Webcam" src="data:image/jpg;base64,{{ picture }}">
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user