Juice/juice.py

184 lines
4.3 KiB
Python
Raw Normal View History

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
import copy
2019-06-05 13:32:10 -04:00
import json
2019-11-08 13:11:57 -05:00
from aiohttp import web
import jinja2
import aiohttp_jinja2
from aiohttp_jinja2 import render_template
#import uvloop
import requests
2019-06-13 20:28:47 -04:00
2019-06-22 18:37:16 -04:00
import config
2019-07-02 08:56:17 -04:00
import models
2019-11-08 13:11:57 -05:00
import buckler_aiohttp
2019-06-22 18:37:16 -04:00
from tools import make_error
2019-06-05 13:32:10 -04:00
2019-11-08 13:11:57 -05:00
#uvloop.install()
network = models.init_network()
routes = web.RouteTableDef()
2019-11-08 13:11:57 -05:00
@routes.get('/', name='index')
async def index(request):
"""The index page."""
2019-07-02 08:56:17 -04:00
global network
2019-06-19 10:15:08 -04:00
init_state = {}
for device in network:
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-08 13:11:57 -05:00
d = {'network': network, 'init_state': init_state}
return render_template('index.html', request, d)
2019-06-05 13:32:10 -04:00
2019-11-08 13:11:57 -05:00
@routes.get('/toggle', name='toggle')
async def toggle(request):
"""Toggles the state of a RelayDevice."""
2019-07-02 08:56:17 -04:00
global network
2019-11-08 13:11:57 -05:00
device_id = request.query.get('device_id')
sub_dev_id = request.query.get('sub_dev_id')
2019-06-06 13:16:59 -04:00
2019-06-18 13:44:35 -04:00
for device in network:
2019-06-06 13:16:59 -04:00
if device.id == device_id:
break
else:
2019-06-13 10:46:59 -04:00
return make_error(404, "device_id not found")
2019-06-06 13:16:59 -04:00
res = device.toggle(sub_dev_id)
if not res:
2019-06-13 10:46:59 -04:00
return make_error(404, "sub_dev_id not found")
2019-07-02 08:56:17 -04:00
models.save_network(network)
2019-11-08 13:11:57 -05:00
return web.json_response(res)
2019-06-06 13:16:59 -04:00
2019-11-08 13:11:57 -05:00
@routes.get('/edit', name='edit')
async def edit(request):
"""Edits the text of a particular field."""
2019-07-02 08:56:17 -04:00
global network
2019-11-08 13:11:57 -05:00
device_id = request.query.get('device_id')
sub_dev_id = request.query.get('sub_dev_id')
field = request.query.get('field')
value = request.query.get('value')
2019-06-13 10:46:59 -04:00
2019-06-18 13:44:35 -04:00
for device in network:
2019-06-13 10:46:59 -04:00
if device.id == device_id:
break
else:
return make_error(404, "device_id not found")
2019-06-20 12:36:19 -04:00
if device.locked:
return make_error(400, "device is locked for editing")
2019-06-13 10:46:59 -04:00
if sub_dev_id:
2019-06-18 13:44:35 -04:00
for sub_dev in device.sub_devices:
2019-06-13 10:46:59 -04:00
if sub_dev.id == sub_dev_id:
break
else:
return make_error(404, "sub_dev_id not found")
if hasattr(sub_dev, field):
setattr(sub_dev, field, value)
else:
return make_error(404, "sub_device field not found")
else:
if hasattr(device, field):
setattr(device, field, value)
else:
return make_error(404, "device field not found")
data = {
'ok': True,
'field': field,
'value': value
}
2019-07-02 08:56:17 -04:00
models.save_network(network)
2019-11-08 13:11:57 -05:00
return web.json_response(data)
2019-06-13 10:46:59 -04:00
2019-11-08 13:11:57 -05:00
@routes.get('/new_device', name='new_device')
async def new_device(request):
2019-06-20 07:49:29 -04:00
"""
Allows adding a new device. Accepts device_type parameter, returns
the device_id.
"""
2019-07-02 08:56:17 -04:00
global network
2019-11-08 13:11:57 -05:00
device_type = request.query.get('device_type')
2019-06-20 07:49:29 -04:00
if device_type == 'RelayDevice':
2019-09-25 19:57:54 -04:00
device = models.RelayDevice()
2019-06-20 07:49:29 -04:00
else:
return make_error(400, "Unknown device type")
devices = [dev for dev in network if dev.type == device_type]
devices.sort(key=lambda dev: dev.type)
if not devices:
device.id = device_type + '01'
else:
num = re.search(r'(\d*)$', devices[-1].id).groups()
if not num:
device.id = device_type + '01'
else:
num = str(int(num[0]) + 1).zfill(2)
device.id = device_type + num
network.append(device)
2019-07-02 08:56:17 -04:00
models.save_network(network)
2019-06-20 07:49:29 -04:00
data = {'device_id': device.id}
2019-11-08 13:11:57 -05:00
return web.json_response(data)
2019-06-20 07:49:29 -04:00
2019-11-08 13:11:57 -05:00
@routes.get('/lock_device', name='lock_device')
async def lock_device(request):
"""Locks or unlocks a device to prevent or allow editing it's fields."""
2019-07-02 08:56:17 -04:00
global network
2019-11-08 13:11:57 -05:00
device_id = request.query.get('device_id')
locked = request.query.get('locked') == 'true'
2019-06-20 12:36:19 -04:00
for device in network:
if device.id == device_id:
break
else:
return make_error(404, "device_id not found")
if locked:
device.locked = True
else:
device.locked = False
2019-07-02 08:56:17 -04:00
models.save_network(network)
2019-06-20 12:36:19 -04:00
2019-11-08 13:11:57 -05:00
return web.json_response({'device_id': device.id, 'locked': device.locked})
2019-06-20 12:36:19 -04:00
2019-11-08 13:11:57 -05:00
@routes.get('/delete', name='delete')
async def delete(request):
"""Deletes a device."""
2019-07-02 08:56:17 -04:00
global network
2019-11-08 13:11:57 -05:00
device_id = request.query.get('device_id')
2019-06-20 14:51:00 -04:00
for device in network:
if device.id == device_id:
break
else:
return make_error(404, "device_id not found")
network.remove(device)
2019-07-02 08:56:17 -04:00
models.save_network(network)
2019-06-20 14:51:00 -04:00
2019-11-08 13:11:57 -05:00
return web.json_response(True)
async def init_app():
"""Initializes the application."""
app = web.Application(middlewares=[buckler_aiohttp.buckler_session])
aiohttp_jinja2.setup(app, loader=jinja2.FileSystemLoader('templates'))
#app.on_startup.append(start_background_tasks)
#app.on_cleanup.append(cleanup_background_tasks)
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