import json import os import random import sys import psycopg2 import tornado.ioloop import tornado.web import tornado.websocket sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import config from utils import get_store, format_value, Notifications conn = psycopg2.connect("dbname={} user={} password={}".format(config.DBNAME, config.DBUSER, config.DBPASS)) def get_cursor(): global conn return conn.cursor() class MainHandler(tornado.web.RequestHandler): def get(self): from plugins import gateway_led, yeelight cursor = get_cursor() cursor.execute('SELECT DISTINCT ON (sid) sid, temperature, humidity FROM ht ORDER BY sid, dt DESC') sensors_current = [] sensors_data = {} for sid, temperature, humidity in cursor.fetchall(): sensors_current.append({ 'sid': sid, 'name': config.SENSORS.get(sid, {}).get('name', sid), 'temperature': format_value(temperature, split=True), #'{:0.2f}'.format(temperature/100.0), 'humidity': format_value(humidity, split=True) #'{:0.2f}'.format(humidity/100.0) }) sensors_data[sid] = { 'labels': [], 'datasets': [ { 'label': 'Temperature', 'data': [], 'borderColor': '#bf3d3d' }, { 'label': 'Humidity', 'data': [], 'borderColor': '#b7bce5' } ] } cursor.execute('SELECT sid, temperature, humidity, dt FROM ht WHERE sid = %s ORDER BY dt DESC LIMIT 25', (sid,)) for sid, temperature, humidity, dt in reversed(cursor.fetchall()): sensors_data[sid]['labels'].append(dt.isoformat()) sensors_data[sid]['datasets'][0]['data'].append(format_value(temperature)) sensors_data[sid]['datasets'][1]['data'].append(format_value(humidity)) bg_images = map(lambda x: '/static/img/bg/%s' % x, os.listdir(os.path.join(os.path.dirname(__file__), "static", "img", "bg"))) bg_images = list(filter(lambda x: x.endswith('.jpg'), bg_images)) brightness, color, status = gateway_led.get_status() brightness = int(brightness, 16) / 100 magnets = [] for sid, sensor in config.SENSORS.items(): if sensor.get('device') == 'magnet': magnet_status = get_store().get('magnet_{}'.format(sid)) magnets.append({ 'sid': sid, 'name': sensor.get('name'), 'status': magnet_status.decode() if magnet_status else 'open', }) self.render( "templates/index.html", sensors=config.SENSORS, sensors_current=sensors_current, sensors_data=sensors_data, magnets=magnets, bg_images=bg_images, gateway_led={ 'brightness': hex(int(brightness*100))[2:], 'color': color, 'status': status }, bulbs=yeelight.get_devices(), notifications=Notifications.list() ) class UpdatesHandler(tornado.websocket.WebSocketHandler): socket_clients = set() def open(self): self.socket_clients.add(self) def on_message(self, message): from plugins import gateway_led, yeelight message = json.loads(message) device = message.get('device') command = message.get('command') if device == gateway_led.DEVICE: if command == 'color': value = message['value'].replace('#', '') gateway_led.set_color(value) elif command == 'brightness': value = message['value'] gateway_led.set_brightness(value) elif command == 'rgb': value = message['value'].replace('#', '') gateway_led.set_rgb(value) elif command == 'toggle': gateway_led.toggle() self.write_message({'device': gateway_led.DEVICE, 'return': 'ok'}) elif device == yeelight.DEVICE: return_result = 'ok' if command == 'set_power': yeelight.set_power(message['power'], device_id=message['id']) elif command == 'set_name': yeelight.set_name(message['name'], device_id=message['id']) elif command == 'set_bright': yeelight.set_bright(message['bright'], device_id=message['id']) else: return_result = 'error' data = { 'device': yeelight.DEVICE, 'return': return_result } self.write_message(data) if message.get('kind') == 'notification': if message.get('command') == 'read': Notifications.remove(message.get('uuid')) def on_close(self): self.socket_clients.remove(self) @classmethod def send_updates(cls, data): for client in cls.socket_clients: client.write_message(data) def make_app(): static_path = os.path.join(os.path.dirname(__file__), "static") settings = { 'static_path': static_path, 'debug': config.DEBUG } return tornado.web.Application([ (r"/", MainHandler), (r"/updates", UpdatesHandler), (r"/static/(.*)", tornado.web.StaticFileHandler, {'path': static_path}), ], **settings) def run_app(): app = make_app() app.listen(config.WEB_APP_PORT) tornado.ioloop.IOLoop.current().start()