# snag # Matt Kohls # (c) 2023 from flask import ( Blueprint, flash, g, redirect, render_template, request, url_for, json ) from werkzeug.exceptions import abort from datetime import datetime, timedelta from snag.db import get_db import time bp = Blueprint('data', __name__, url_prefix='/data') # Temp dst function, should add this to database to track instead def is_dst_aware(deviceId): if (deviceId in [2]): return False else: return True # Process json data # # Expects something like this: # { # "scheme": "1", # "deviceId": 1, # "readings": [ # { # "env": "outdoor", # "temp": 123 # }, # { # "env": "enclosed", # "temp": 456 # } # ], # "status": [ # { # "heater": "off", # "battery": 10 # } # ] # } def unpack_json_scheme_1(req): try: deviceId = req['deviceId'] db = get_db() # Status only has one object in it, and is optional if 'status' in req: if 'timeStamp' in req['status'][0]: now = req['status'][0]['timeStamp'] now = datetime.strptime(now, "%Y-%m-%dT%H:%M:%SZ") if not is_dst_aware(deviceId) and time.daylight: now = now + timedelta(hours=1) now = now.strftime("%Y-%m-%d %H:%M:%S") else: now = datetime.now() battery = req['status'][0]['battery'] heater = req['status'][0]['heater'] db.execute('INSERT INTO device_status (date, deviceId, batteryCharge, heaterRunning) VALUES (?, ?, ?, ?)', [now, deviceId, battery, heater]) for environment in req['readings']: env = environment['environment'] temp = environment['temperature'] humidity = environment['humidity'] pressure = environment['pressure'] now = environment['timeStamp'] now = datetime.strptime(now, "%Y-%m-%dT%H:%M:%SZ") if not is_dst_aware(deviceId) and time.daylight: now = now + timedelta(hours=1) now = now.strftime("%Y-%m-%d %H:%M:%S") if env == 'outdoor': lux = environment['lux'] uv = environment['uv'] db.execute('INSERT INTO env_outdoor (date, deviceId, temperature, humidity, pressure, lux, uv_intensity) VALUES (?, ?, ?, ?, ?, ?, ?)', [now, deviceId, temp, humidity, pressure, lux, uv]) elif env == 'indoor': db.execute('INSERT INTO env_indoor (date, deviceId, temperature, humidity, pressure) VALUES (?, ?, ?, ?, ?)', [now, deviceId, temp, humidity, pressure]) elif env == 'enclosed': light = environment['light'] db.execute('INSERT INTO env_enclosed (date, deviceId, temperature, humidity, pressure, light) VALUES (?, ?, ?, ?, ?, ?)', [now, deviceId, temp, humidity, pressure, light]) else: raise 'Bad reading environment' db.commit() except Exception as err: print(err) return "Bad JSON", 400 return "Data received", 200 @bp.route('/json', methods=['POST']) def add_json_data(): if request.is_json: req = request.get_json() if 'scheme' in req: if req['scheme'] == '1': return unpack_json_scheme_1(req) else: abort(400, "Unknown scheme") else: abort(400, "Unknown JSON") else: abort(400, "Unknown payload type") @bp.route('/devices', methods=['GET']) def get_devices(): db = get_db() out = [] devices = db.execute('SELECT * FROM devices ORDER BY deviceId').fetchall() for device in devices: envList = [] envs = db.execute('SELECT * FROM device_env WHERE deviceId = ?', [device['deviceId']]).fetchall() for env in envs: envDict = { "environment" : env["environment"], "environmentDesc" : env["environmentDescription"] } envList.append(envDict) deviceLine = { "deviceId" : device["deviceId"], "deviceName" : device["deviceName"], "deviceDescription" : device["deviceLocation"] } deviceLine['environments'] = envList out.append(deviceLine) return out