From 8cf24308185d45000b1ce6f29a2edc6cdf00185c Mon Sep 17 00:00:00 2001 From: Matt Kohls Date: Mon, 4 Dec 2023 22:44:20 -0500 Subject: Adding JS graphs to dashboard Using new api + D3 and Plot to draw fancy graphs --- snag/data.py | 148 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 50 deletions(-) (limited to 'snag/data.py') diff --git a/snag/data.py b/snag/data.py index 7e65186..637f7f0 100644 --- a/snag/data.py +++ b/snag/data.py @@ -8,6 +8,7 @@ from flask import ( from werkzeug.exceptions import abort from datetime import datetime, timedelta from snag.db import get_db +from snag.graphs import get_table import time bp = Blueprint('data', __name__, url_prefix='/data') @@ -16,7 +17,7 @@ bp = Blueprint('data', __name__, url_prefix='/data') def is_dst_aware(deviceId): db = get_db() sql = "SELECT dstAware FROM devices WHERE deviceId = ?" - data = db.execute(sql, deviceId) + data = db.execute(sql, [deviceId]) if data is None: return False else: @@ -95,6 +96,7 @@ def unpack_json_scheme_1(req): return "Data received", 200 +## For submitting data to server @bp.route('/json', methods=['POST']) def add_json_data(): if request.is_json: @@ -110,8 +112,11 @@ def add_json_data(): else: abort(400, "Unknown payload type") -@bp.route('/devices', methods=['GET']) -def get_devices(): +### Information Routes ### + +## Gives information about all the devices +@bp.route('/info/devices', methods=['GET', 'POST']) +def get_info_devices(): db = get_db() out = [] @@ -134,22 +139,9 @@ def get_devices(): out.append(deviceLine) return out -def parse_measuremet_req(req): - req = req.lower() - if req == "": - req = "thp" - measurements = "date" - if 't' in req: - measurements = measurements + ", temperature" - if 'h' in req: - measurements = measurements + ", humidity" - if 'p' in req: - measurements = measurements + ", pressure" - - return measurements ## Grabs data from db, or None if not -def get_data_selection(device_id, start_time, end_time, columns, environment): +def get_data_selection(device_ids, start_time, end_time, columns, environment): if end_time is None: end_time = datetime.now() if start_time is None: @@ -159,15 +151,43 @@ def get_data_selection(device_id, start_time, end_time, columns, environment): db = get_db() if environment is not None: + devqs = "{0}".format(', '.join(['?'] * len(device_ids))) + argument_list = [start_time.isoformat(" ", "seconds"), end_time.isoformat(" ", "seconds")] + device_ids sql = (f"SELECT {columns} " f"FROM {environment} " - "WHERE (date BETWEEN ? AND ?) AND deviceId = ?") - subset = db.execute(sql, [start_time.isoformat(" ", "seconds"), end_time.isoformat(" ", "seconds"), device_id]).fetchall() + f"WHERE (date BETWEEN ? AND ?) AND deviceId IN ( {devqs} )") + subset = db.execute(sql, argument_list).fetchall() else: subset = None return subset +### Device Routes ### + +## Get data by devices +# +# Expected json payload +# { +# "devices" : [ "", "", .. ] ; Required +# "environment" : "", ; Required +# "startTime" : "", ; Optional +# "endTime" : "", ; Optional +# "measurements" : [ "", "", .. ] ; Required +# } +# +# Returns a json payload like this +# [ +# {"timeStamp":"2112-09-21T09:21:00", "":"", ..}, .. +# ] +# +@bp.route('/device', methods=['GET', 'POST']) +def get_n_device_data(): + if request.is_json: + payload = request.get_json() + return process_device_data_req(payload) + else: + abort(400, "Missing request data") + ## Get data by deviceId # # Expected json payload @@ -183,44 +203,72 @@ def get_data_selection(device_id, start_time, end_time, columns, environment): # {"timeStamp":"2112-09-21T09:21:00", "":"", ..}, .. # ] # -@bp.route('/', methods=['GET']) +@bp.route('/device/', methods=['GET', 'POST']) def get_device_data(device_id): if request.is_json: payload = request.get_json() - if 'environment' in payload and 'measurements' in payload: - env = payload['environment'] - end_time = datetime.now() - start_time = end_time - timedelta(hours=1) - if 'startTime' in payload: - start_time = payload['startTime'] - start_time = datetime.strptime(start_time, "%Y-%m-%dT%H:%M:%SZ") - if 'endTime' in payload: - end_time = payload['endTime'] - end_time = datetime.strptime(end_time, "%Y-%m-%dT%H:%M:%SZ") - selected_columns = "date" - for measurement in payload['measurements']: - selected_columns = selected_columns + ", " + measurement - if selected_columns == "date": - abort(400, "Bad json payload - missing measurements") - else: - data = get_data_selection(device_id, start_time, end_time, selected_columns, env) - if data is None: - abort(404, "No data found") - - outlist = [] - for row in data: - reading = { "timeStamp":row["date"].strftime('%Y-%m-%dT%H:%M:%SZ') } - for measurement in payload['measurements']: - reading[measurement] = row[measurement] - outlist.append(reading) - return outlist - else: - abort(400, "Bad json payload") + payload['devices'] = [device_id] + return process_device_data_req(payload) else: abort(400, "Missing request data") +## Processes a device data request +# +# Expected json payload +# { +# "devices" : [ "", "", .. ] ; Required +# "environment" : "", ; Required +# "startTime" : "", ; Optional +# "endTime" : "", ; Optional +# "measurements" : [ "", "", .. ] ; Required +# } +# +# Returns a json payload like this +# [ +# {"timeStamp":"2112-09-21T09:21:00", "":"", ..}, .. +# ] +# +def process_device_data_req(payload): + if 'environment' in payload and 'measurements' in payload and 'devices' in payload: + env = get_table(payload['environment']) + if env is None: + abort(400, "Unknown environment: " + payload['environment']) + end_time = datetime.now() + start_time = end_time - timedelta(days=1) + if 'startTime' in payload: + start_time = payload['startTime'] + start_time = datetime.strptime(start_time, "%Y-%m-%dT%H:%M:%SZ") + if 'endTime' in payload: + end_time = payload['endTime'] + end_time = datetime.strptime(end_time, "%Y-%m-%dT%H:%M:%SZ") + selected_columns = "date, deviceId" + for measurement in payload['measurements']: + selected_columns = selected_columns + ", " + measurement + if selected_columns == "date, deviceId": + abort(400, "Bad json payload - missing measurements") + else: + device_ids = [] + for device in payload['devices']: + device_ids.append(device) + if device_ids == []: + abort(400, "Bad json payload - missing devices") + data = get_data_selection(device_ids, start_time, end_time, selected_columns, env) + if data is None: + abort(404, "No data found") + + outlist = [] + for row in data: + reading = { "timeStamp":row["date"].strftime('%Y-%m-%dT%H:%M:%SZ'), + "deviceId":row["deviceId"]} + for measurement in payload['measurements']: + reading[measurement] = row[measurement] + outlist.append(reading) + return outlist + else: + abort(400, "Bad json payload") + # Get data by environment type -@bp.route('/environment', methods=['GET']) +@bp.route('/environment', methods=['GET', 'POST']) def get_env_data(): if request.args['type'] is not None: return "todo" -- cgit v1.2.3