Skip to content

Feature/routing #14

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
@@ -1 +1,2 @@
ignorecase = true
__pycache__
Binary file removed lights/__pycache__/discover.cpython-35.pyc
Binary file not shown.
Binary file removed lights/__pycache__/protocol.cpython-35.pyc
Binary file not shown.
Binary file removed lights/__pycache__/smartbulb.cpython-35.pyc
Binary file not shown.
13 changes: 12 additions & 1 deletion postgres/create_schema.sql
Expand Up @@ -21,7 +21,7 @@ CREATE TABLE guests (
city text,
state text,
zip text,
room_uuid uuid REFERENCES rooms(uuid).
room_uuid uuid REFERENCES rooms(uuid)
);

-- Sessions table to keep track of tokens for authentication.
Expand Down Expand Up @@ -129,3 +129,14 @@ CREATE TABLE employees (
last_name text,
admin boolean DEFAULT false
);

-- Routing Table.
-- We can redirect based on peripheral OR by room.
CREATE TABLE routing (
uuid uuid PRIMARY KEY DEFAULT gen_random_uuid(),
room_uuid uuid REFERENCES rooms(uuid),
peripheral_uuid uuid REFERENCES peripherals(uuid),
metric integer DEFAULT 0,
target text NOT NULL,
enabled BOOLEAN default true
);
2 changes: 2 additions & 0 deletions web/Dockerfile
Expand Up @@ -17,6 +17,8 @@ RUN pip install -r /src/requirements.txt
COPY index.py /src/index.py
COPY static/ManagementApp.html /src/static/ManagementApp.html
COPY postgresLibrary.py /src/postgresLibrary.py
COPY peripherals.py /src/peripherals.py
COPY lights/ /src/lights/

# Add entrypoint
COPY docker-entrypoint.sh /usr/local/bin/
Expand Down
75 changes: 64 additions & 11 deletions web/index.py
@@ -1,12 +1,14 @@
#!/usr/bin/python
from flask import Flask
from flask_restful import Resource, Api
from flask import request
from flask import request, Response
from flask.json import jsonify
from flask import render_template
import requests
import json
import postgresLibrary as pL
import uuid
import peripherals as peripherals

from datetime import date, datetime

Expand All @@ -21,16 +23,10 @@ PORT_NUMBER = 8000
app = Flask(__name__)
api = Api(app)

class Index(Resource):
def get(self):
# rooms = pL.getRooms()
# for room in rooms:
# print(room)
# room['pheripherals'] = pL.getPeripheralsbyRoom(room['uuid'])
# return rooms
return app.send_static_file('static/ManagementApp.html')

api.add_resource(Index, '/')
# class Index(Resource):
# def get(self):
# return app.send_static_file('/src/static/ManagementApp.html')
# api.add_resource(Index, '/')


####################################
Expand All @@ -41,6 +37,63 @@ api.add_resource(Index, '/')
# Room Info
####################################

@app.route('/api/peripheral/<uuid>', methods=['GET'])
def getPeripheral(uuid):
per = pL.getPeripheralbyUUID(uuid)

return jsonify(per)

@app.route('/api/peripheral/<uuid>', methods=['POST'])
def setPeripheralID(uuid):
body = request.get_json()

if body == None:
return None

per = pL.getPeripheralbyUUID(uuid)
roomRoutes = pL.roomRoutingEntries(per['room_uuid'])
peripheralRoutes = pL.peripheralRoutingEntries(uuid)

# At the room level, we simply proxy requests.
# If there's a specific peripheral IP in a peripheral route, it will be ignored if there is a room route.
if len(roomRoutes) == 0:
# We're doing a peripheral specific handling.
return peripherals.handlePeripheral(per, body, peripheralRoutes)
else:
dest = roomRoutes[0]
resp = requests.request(
method=request.method,
url='http://' + dest['target'] + request.script_root + request.full_path,
headers={key: value for (key, value) in request.headers if key != 'Host'},
data=request.get_data(),
cookies=request.cookies,
timeout=0.5,
allow_redirects=False
)

excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
headers = [(name, value) for (name, value) in resp.raw.headers.items()
if name.lower() not in excluded_headers]

response = Response(resp.content, resp.status_code, headers)
return response


@app.route('/api/guest/rooms', methods=['GET','POST'])
def getGuestRooms():
rooms = pL.getRooms()
for room in rooms:
print(room)
room['peripherals'] = pL.getPeripheralsbyRoom(room['uuid'])
return jsonify({
'rooms': rooms,
'hotel_name': 'Hotel'
})

@app.route('/api/routes/<uuid>/entries', methods=['GET','POST'])
def getRoutes(uuid):
return jsonify(pL.routingEntries(uuid, uuid))

# Get all rooms
@app.route('/api/admin/rooms', methods=['GET', 'POST'])
def getRooms():
Expand Down
File renamed without changes.
Empty file added web/lights/__init__.py
Empty file.
2 changes: 1 addition & 1 deletion lights/discover.py → web/lights/discover.py
@@ -1,6 +1,6 @@
import socket, json
from typing import Dict, Type, List
from protocol import TPLinkSmartHomeProtocol
from .protocol import TPLinkSmartHomeProtocol


class Discover:
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion lights/smartbulb.py → web/lights/smartbulb.py
@@ -1,4 +1,4 @@
from protocol import TPLinkSmartHomeProtocol
from .protocol import TPLinkSmartHomeProtocol
from typing import Optional, Dict


Expand Down
4 changes: 2 additions & 2 deletions lights/test.py → web/lights/test.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python3

import time
from discover import Discover
from smartbulb import SmartBulb
from .discover import Discover
from .smartbulb import SmartBulb

"""
This is a test file to show how things work.
Expand Down
51 changes: 51 additions & 0 deletions web/peripherals.py
@@ -0,0 +1,51 @@
from lights.smartbulb import SmartBulb
import postgresLibrary as pL
import requests
from flask.json import jsonify
from flask import request, Response

def handlePeripheral(peripheral, body, routes):
print(peripheral, body, routes)
if len(routes) == 0:
return "No Route to Host."
elif peripheral['type'] == 'thermostat':
dest = routes[0]
url = 'http://' + dest['target'] + '/api/set-temp'
print(url)

power = "false"
if body['power']:
power = "true"

pL.updatePeripheralStateAndPower(int(body['state']), body['power'], peripheral['uuid'])

resp = requests.request(
method='POST',
url=url,
headers= {
'Content-Type': 'application/json'
},
data='{ "state": ' + str(int(body['state'])) + ', "power": ' + power + ' }' ,
cookies={},
timeout=0.5,
allow_redirects=False
)

response = Response(resp.content, resp.status_code, {})
return response

elif peripheral['type'] == 'lightDimmable':
bulb = SmartBulb(routes[0]['target'])
power = body['power']
brightness = int(body['state'])

if power:
bulb.state('ON')
bulb.brightness(brightness)
else:
bulb.state('OFF')

pL.updatePeripheralStateAndPower(brightness, power, peripheral['uuid'])
return "OK"
else:
return "Unknown Type."
50 changes: 49 additions & 1 deletion web/postgresLibrary.py
Expand Up @@ -26,6 +26,13 @@ def getAll( query ):
closeConnection(conn, cur)
return values

def getAllParams( query, params ):
conn, cur = setupConnection()
cur.execute(query, params)
values = cur.fetchall()
closeConnection(conn, cur)
return values

def getItembyUUID( query, uuid ):
conn, cur = setupConnection()
cur.execute(query, (uuid,))
Expand Down Expand Up @@ -223,7 +230,7 @@ def getPeripheralbyUUID( periUUID ):

def getPeripheralsbyRoom( roomUUID ):
"""returns information by room_uuid for all peripherals in room"""
query = "SELECT * from peripherals WHERE room_uuid = (%s);"
query = "SELECT * from peripherals WHERE room_uuid = (%s) ORDER BY name DESC;"
peripherals = getItemsbyCol(query, roomUUID)
return peripherals

Expand Down Expand Up @@ -253,6 +260,10 @@ def updatePeripheralActive( active, periUUID):
query = "UPDATE peripherals SET active = (%s) WHERE uuid = (%s);"
return updateItem( query, (active, periUUID))

def updatePeripheralStateAndPower( state, power, periUUID):
query = "UPDATE peripherals SET state = (%s), power = (%s), last_update = CURRENT_TIMESTAMP WHERE uuid = (%s);"
return updateItem( query, (state, power, periUUID))

#TV Channel Select Functions
def getChannels():
query = "SELECT * from tv_channels;"
Expand Down Expand Up @@ -464,3 +475,40 @@ def deleteEmployee( empUUID ):
def updateEmployeeAdmin( admin, empUUID):
query = "UPDATE employees SET admin = (%s) WHERE uuid = (%s);"
return updateItem(query, (admin,empUUID))

# Get routing table entries for a room / peripheral ID.
def routingEntries ( room_uuid, peripheral_uuid ):
return getAllParams("""
SELECT *
FROM routing
WHERE
(
room_uuid = %s OR
peripheral_uuid = %s
)
AND enabled
ORDER BY metric ASC
""", (room_uuid, peripheral_uuid))

# Get routing table entries for a room / peripheral ID.
def roomRoutingEntries ( room_uuid ):
return getAllParams("""
SELECT *
FROM routing
WHERE
room_uuid = %s
AND enabled
ORDER BY metric ASC
""", (room_uuid,))

# Get routing table entries for a room / peripheral ID.
def peripheralRoutingEntries ( peripheral_uuid ):
return getAllParams("""
SELECT *
FROM routing
WHERE
peripheral_uuid = %s
AND enabled
ORDER BY metric ASC
""", (peripheral_uuid,))

3 changes: 2 additions & 1 deletion web/requirements.txt
@@ -1,3 +1,4 @@
psycopg2
flask
flask_restful
flask_restful
requests