2019-06-05 13:32:10 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
"""
|
|
|
|
A hub for controlling IOT devices.
|
|
|
|
"""
|
2019-06-13 20:28:47 -04:00
|
|
|
import os
|
2019-06-05 13:32:10 -04:00
|
|
|
import re
|
2019-06-08 03:56:30 -04:00
|
|
|
import copy
|
2019-06-05 13:32:10 -04:00
|
|
|
import json
|
|
|
|
|
2019-11-15 10:35:56 -05:00
|
|
|
from aiohttp import web, WSMsgType
|
2019-11-08 13:11:57 -05:00
|
|
|
import jinja2
|
|
|
|
import aiohttp_jinja2
|
|
|
|
from aiohttp_jinja2 import render_template
|
2019-11-15 10:35:56 -05:00
|
|
|
import uvloop
|
2019-11-08 13:11:57 -05:00
|
|
|
import requests
|
2019-06-13 20:28:47 -04:00
|
|
|
|
2019-11-18 13:05:37 -05:00
|
|
|
import mqtt
|
|
|
|
import tools
|
2019-06-22 18:37:16 -04:00
|
|
|
import config
|
2019-11-15 10:35:56 -05:00
|
|
|
import events
|
2019-07-02 08:56:17 -04:00
|
|
|
import models
|
2019-11-08 13:11:57 -05:00
|
|
|
import buckler_aiohttp
|
2019-11-15 10:35:56 -05:00
|
|
|
from models import network
|
2019-06-05 13:32:10 -04:00
|
|
|
|
2019-11-15 10:35:56 -05:00
|
|
|
uvloop.install()
|
2019-11-08 13:11:57 -05:00
|
|
|
routes = web.RouteTableDef()
|
2019-06-08 03:56:30 -04:00
|
|
|
|
2019-11-08 13:11:57 -05:00
|
|
|
@routes.get('/', name='index')
|
|
|
|
async def index(request):
|
|
|
|
"""The index page."""
|
2019-06-19 10:15:08 -04:00
|
|
|
init_state = {}
|
|
|
|
for device in network:
|
2019-11-17 19:46:57 -05:00
|
|
|
if device.type != "RelayDevice":
|
|
|
|
continue
|
2019-06-19 10:15:08 -04:00
|
|
|
device_state = {}
|
|
|
|
for sub_dev in device.sub_devices:
|
|
|
|
device_state[sub_dev.id] = sub_dev.state
|
|
|
|
init_state[device.id] = device_state
|
2019-11-15 10:35:56 -05:00
|
|
|
d = {'network': network, 'init_state': init_state, 'request': request}
|
2019-11-08 13:11:57 -05:00
|
|
|
return render_template('index.html', request, d)
|
2019-06-05 13:32:10 -04:00
|
|
|
|
|
|
|
|
2019-11-15 10:35:56 -05:00
|
|
|
@routes.get('/ws', name='ws')
|
|
|
|
async def websocket_handler(request):
|
|
|
|
"""The websocket endpoint."""
|
|
|
|
ws = web.WebSocketResponse(heartbeat=30)
|
|
|
|
ws_ready = ws.can_prepare(request)
|
|
|
|
if not ws_ready.ok:
|
|
|
|
return web.Response(text="Cannot start websocket.")
|
|
|
|
await ws.prepare(request)
|
2019-11-15 12:54:41 -05:00
|
|
|
request.app['websockets'].append(ws)
|
2019-06-06 13:16:59 -04:00
|
|
|
|
2019-11-15 10:35:56 -05:00
|
|
|
async for msg in ws:
|
|
|
|
if msg.type != WSMsgType.TEXT:
|
2019-06-06 13:16:59 -04:00
|
|
|
break
|
2019-11-15 10:35:56 -05:00
|
|
|
try:
|
|
|
|
data = json.loads(msg.data)
|
|
|
|
except json.JSONDecodeError:
|
2019-06-20 12:36:19 -04:00
|
|
|
break
|
|
|
|
|
2019-11-15 10:35:56 -05:00
|
|
|
event = data.get('event')
|
|
|
|
if not event or event not in events.events.keys():
|
2019-06-20 14:51:00 -04:00
|
|
|
break
|
2019-11-15 12:54:41 -05:00
|
|
|
await events.events[event](request, ws, data.get('data'))
|
2019-11-15 10:35:56 -05:00
|
|
|
await ws.close()
|
2019-11-15 12:54:41 -05:00
|
|
|
request.app['websockets'].remove(ws)
|
2019-11-15 10:35:56 -05:00
|
|
|
return ws
|
2019-11-08 13:11:57 -05:00
|
|
|
|
|
|
|
|
2019-11-15 12:54:41 -05:00
|
|
|
async def send_json_all(self, d):
|
|
|
|
"""Sends to all connected websockets."""
|
|
|
|
for ws in self['websockets']:
|
|
|
|
await ws.send_json(d)
|
|
|
|
|
|
|
|
|
2019-11-18 13:05:37 -05:00
|
|
|
async def start_background_tasks(app):
|
|
|
|
app['mqtt'] = mqtt.init_client(app)
|
|
|
|
|
|
|
|
|
|
|
|
async def cleanup_background_tasks(app):
|
|
|
|
app['mqtt'].loop_stop()
|
|
|
|
|
|
|
|
|
2019-11-08 13:11:57 -05:00
|
|
|
async def init_app():
|
|
|
|
"""Initializes the application."""
|
2019-11-15 12:54:41 -05:00
|
|
|
web.Application.send_json_all = send_json_all
|
2019-11-08 13:11:57 -05:00
|
|
|
app = web.Application(middlewares=[buckler_aiohttp.buckler_session])
|
2019-11-17 19:46:57 -05:00
|
|
|
aiohttp_jinja2.setup(
|
|
|
|
app,
|
|
|
|
trim_blocks=True,
|
|
|
|
lstrip_blocks=True,
|
|
|
|
undefined=jinja2.StrictUndefined,
|
|
|
|
loader=jinja2.FileSystemLoader('templates'),
|
2019-11-18 13:05:37 -05:00
|
|
|
filters={'html_color': tools.to_html_color},
|
2019-11-17 19:46:57 -05:00
|
|
|
)
|
2019-11-18 13:05:37 -05:00
|
|
|
app.on_startup.append(start_background_tasks)
|
|
|
|
app.on_cleanup.append(cleanup_background_tasks)
|
2019-11-15 12:54:41 -05:00
|
|
|
app['websockets'] = []
|
2019-06-13 20:28:47 -04:00
|
|
|
|
2019-11-08 13:11:57 -05:00
|
|
|
app.router.add_routes(routes)
|
2019-06-13 20:28:47 -04:00
|
|
|
|
2019-11-08 13:11:57 -05:00
|
|
|
app_wrap = web.Application()
|
|
|
|
app_wrap.add_subapp(config.url_prefix, app)
|
|
|
|
return app_wrap
|
2019-11-15 10:35:56 -05:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
app = init_app()
|
|
|
|
aiohttp.web.run_app(app, host='0.0.0.0', port=5300)
|