diff --git a/Backend/README.md b/Backend/README.md index 8c83b61..073c453 100644 --- a/Backend/README.md +++ b/Backend/README.md @@ -7,10 +7,49 @@ https://levelup.gitconnected.com/full-stack-web-app-with-python-react-and-bootst # packages # coapthon (for py3) -pip install CoAPthon3 +pip install CoAPthon3 +# aiocoap +pip install aiocoap # install flask package -pip install Flask +pip install Flask # install flask_cors package -pip install Flask_cors +pip install Flask_cors # Only if you don't have sqlite installed -pip install db-sqlite3 +pip install db-sqlite3 + + +# api +path +Payload if needed +description +response + +/getall (GET) +-> Return alls rooms with their puzzles +{'Roomname':['Puzzlename']} + +/Rooms/room (DELETE) +-> delete room and returns the deleted room +{'name': text, 'state': 'text'} + +/Rooms/room (POST) +-> adds room +{'name': text, 'state': 'text'} + +/Rooms/room (PUT) +Payload: {'state': text} +-> update the state of room and returns the updated room +{'name': text, 'state': 'text'} + +'/Rooms/room (GET) +-> returns name and state of the room +{'name': text, 'state': 'text'} + +/Rooms/movepuzzle/puzzle (PUT) +Payload:{'newRoom': text, 'oldRoom': text} +-> moves puzzle from oldRoom to newRoom and returns the room after update +{'name': text, 'room':text, 'state': text} + +/Rooms/room/puzzle (GET) +-> Returns info about puzzle in room +{'name': text, 'room': text, 'state': text} \ No newline at end of file diff --git a/Backend/database.db b/Backend/database.db deleted file mode 100644 index 3f13eed..0000000 Binary files a/Backend/database.db and /dev/null differ diff --git a/Backend/src/coap_server.py b/Backend/src/coap_server.py new file mode 100644 index 0000000..bec9ddb --- /dev/null +++ b/Backend/src/coap_server.py @@ -0,0 +1,45 @@ +import asyncio +import aiocoap.resource as resource +from aiocoap import * + + +class WhoAmI(resource.Resource): + async def render_get(self, request): + text = ["Used protocol: %s." % request.remote.scheme] + + text.append("Request came from %s." % request.remote.hostinfo) + text.append("The server address used %s." % request.remote.hostinfo_local) + + claims = list(request.remote.authenticated_claims) + if claims: + text.append("Authenticated claims of the client: %s." % ", ".join(repr(c) for c in claims)) + else: + text.append("No claims authenticated.") + + return Message(content_format=0, + payload="\n".join(text).encode('utf8')) + + +async def main(): + root = resource.Site() + + root.add_resource(['.well-known', 'core'], + resource.WKCResource(root.get_resources_as_linkheader)) + root.add_resource(['whoami'], WhoAmI()) + + con = await Context.create_server_context(root,bind=("0.0.0.0",5555)) + + request = Message(code=GET, uri="coap://127.0.0.1:5683/resource-lookup/", observe=0) + req = con.request(request) + res = await req.response + print(res.payload) + print("start async loop") + async for r in req.observation: + print(r.payload) + # Run forever + print("server running now") + await asyncio.get_running_loop().create_future() + + +if __name__ == '__main__': + asyncio.run(main()) \ No newline at end of file diff --git a/Backend/src/coapthon_client.py b/Backend/src/coapthon_client.py index 31f6756..2e071f7 100644 --- a/Backend/src/coapthon_client.py +++ b/Backend/src/coapthon_client.py @@ -1,10 +1,10 @@ from coapthon.client.helperclient import HelperClient -host = "127.0.0.1" +host = "2001:db8::814c:35fc:fd31:5fde" port = 5683 def get_led(led): - path = "led{}".format(led) + path = "led/{}".format(led) client = HelperClient(server=(host, port)) response = client.get(path) @@ -14,7 +14,7 @@ def get_led(led): def set_led(led, value): - path = "led{}".format(led) + path = "led/{}".format(led) client = HelperClient(server=(host, port)) response = client.put(path, payload=value) diff --git a/Backend/src/coapthon_server.py b/Backend/src/coapthon_server.py deleted file mode 100644 index 41568e9..0000000 --- a/Backend/src/coapthon_server.py +++ /dev/null @@ -1,48 +0,0 @@ -from coapthon.resources.resource import Resource -from coapthon.server.coap import CoAP -from coapthon import defines - - -class LEDResource(Resource): - def __init__(self, name="led", coap_server=None): - super(LEDResource, self).__init__(name, coap_server, visible=True, - observable=True, allow_children=True) - self.state = "0" - - def render_PUT_advanced(self, request, response): - self.state = request.payload - from coapthon.messages.response import Response - assert(isinstance(response, Response)) - response.payload = self.state - response.code = defines.Codes.CHANGED.number - return self, response - - def render_GET_advanced(self, request, response): - response.payload = self.state - response.max_age = 20 - response.code = defines.Codes.CONTENT.number - return self, response - - -class CoAPServer(CoAP): - def __init__(self, host, port): - CoAP.__init__(self, (host, port)) - self.add_resource('led0', LEDResource(name='led0')) - self.add_resource('led1', LEDResource(name='led1')) - self.add_resource('led2', LEDResource(name='led2')) - self.add_resource('led3', LEDResource(name='led3')) - - -def main(): - print("Server start") - server = CoAPServer("127.0.0.1", 5683) - try: - server.listen(10) - except KeyboardInterrupt: - print("Server Shutdown") - server.close() - print("Exiting...") - - -if __name__ == '__main__': - main() diff --git a/Backend/src/requirements.txt b/Backend/src/requirements.txt new file mode 100644 index 0000000..768ab70 Binary files /dev/null and b/Backend/src/requirements.txt differ diff --git a/Backend/src/rest.py b/Backend/src/rest.py index b8ad879..17e2ac1 100644 --- a/Backend/src/rest.py +++ b/Backend/src/rest.py @@ -1,12 +1,59 @@ from coapthon_client import * from sqlite import * -from flask import Flask, request, jsonify +from flask import Flask, request, jsonify, render_template from flask_cors import CORS app = Flask(__name__) CORS(app, resources={r"/*": {"origins": "*"}}) +# get all rooms and puzzles +@app.route('/getall', methods=['GET']) +def api_getall(): + response = get_rooms_with_puzzles() + return jsonify(response) + + +# rooms + +@app.route('/Rooms/', methods=['DELETE']) +def api_delete_room(room): + response = delete_room(room) + return jsonify(response) + + +@app.route('/Roomm/', methods=['POST']) +def api_add_room(room): + response = add_room(room) + return jsonify(response) + +@app.route('/Rooms/', methods=['PUT']) +def api_update_room(room): + request_data = request.get_json() + response = update_room(request_data['state'],room) + return jsonify(response) + + +@app.route('/Rooms/', methods=['GET']) +def api_get_room(room): + response = get_room_by_name(room) + return jsonify(response) + + +@app.route('/Rooms/movepuzzle/', methods=['PUT']) +def api_moovepuzzle(puzzle): + request_data = request.get_json() + response = update_puzzle(request_data['newRoom'],[request_data['oldRoom']], puzzle) + return jsonify({'name': response.name, 'room':response.room, 'state': response.state}) + + +# puzzles +@app.route('/Rooms//', methods=['GET']) +def api_get_puzzle(room, puzzle): + response = get_room_by_name(room, puzzle) + return jsonify({'name': response.name, 'room':response.room, 'state': response.state}) + + # coap @app.route('/coap/led', methods=['GET']) def api_get_led_value(id): @@ -32,24 +79,8 @@ def api_set_box_value(id): return jsonify(response) -# db -@app.route('/db/led', methods=['GET']) -def api_db_get_led_value(id): - return jsonify(get_led_by_name("led" + id)) - - -@app.route('/db/led', methods=['POST']) -def api_db_set_led_value(id): - request_data = request.get_json() - to_update = {"name": "led{}".format(id), - "value": request_data["value"]} - return(update_led(to_update)) - - -@app.route('/db/add/led', methods=['POST']) -def api_db_add_led(id): - return jsonify(insert_led("led{}".format(id))) - - if __name__ == "__main__": + # from waitress import serve + + # serve(app, host="0.0.0.0") app.run(host="0.0.0.0") diff --git a/Backend/src/sqlite.py b/Backend/src/sqlite.py index 61a3cf8..1bb9885 100644 --- a/Backend/src/sqlite.py +++ b/Backend/src/sqlite.py @@ -6,85 +6,216 @@ def connect_to_db(): return conn -def create_db_table(): +# Rooms + +def create_table_room(): + try: + conn = connect_to_db() + conn.execute(''' + CREATE TABLE Rooms ( + id INTEGER PRIMARY KEY NOT NULL, + name TEXT UNIQUE NOT NULL, + state TEXT + ); + ''') + + conn.commit() + print("rooms table created successfully") + except: + print("rooms table creation failed - Maybe table") + finally: + conn.close() + + +def add_room(room): + inserted_room = {} + try: + conn = connect_to_db() + cur = conn.cursor() + cur.execute("INSERT INTO rooms (name) VALUES ('{}')".format(room)) + conn.commit() + inserted_room = get_room_by_name(room) + except: + conn().rollback() + + finally: + conn.close() + return inserted_room + + +def delete_room(room): + deleted_room = {} + try: + conn = connect_to_db() + cur = conn.cursor() + deleted_room = get_room_by_name(room) + cur.execute("DELETE from rooms where name = ('{}')".format(room)) + conn.commit() + except: + conn().rollback() + + finally: + conn.close() + return deleted_room + + +def update_room(state, room): + updated_room = {} + try: + conn = connect_to_db() + cur = conn.cursor() + cur.execute("UPDATE rooms SET state = {} WHERE name = '{}' ".format(state,room)) + conn.commit() + updated_room = get_room_by_name(room) + except: + conn().rollback() + + finally: + conn.close() + return updated_room + + +def get_room_by_name(room): + fetched_room = {} + try: + conn = connect_to_db() + cur = conn.cursor() + cur.execute("SELECT * from rooms where name = '{}'".format(room)) + row = cur.fetchone() + fetched_room["name"] = row[1] + fetched_room["state"] = row[2] + except: + conn().rollback() + + finally: + conn.close() + return (fetched_room) + + +# Puzzles + +def create_table_puzzle(): try: conn = connect_to_db() conn.execute(''' - CREATE TABLE ledtest ( - ledid INTEGER PRIMARY KEY NOT NULL, - led TEXT NOT NULL, - value INTEGER NOT NULL + CREATE TABLE Puzzles ( + id INTEGER PRIMARY KEY NOT NULL, + name TEXT NOT NULL, + path TEXT NOT NULL, + room TEXT NOT NULL, + state TEXT, + FOREIGN KEY(room) REFERENCES name(rooms) ); ''') conn.commit() - print("ledtest table created successfully") + print("puzzles table created successfully") + except: + print("puzzles table creation failed - Maybe table") + finally: + conn.close() + + +def add_puzzle(puzzlename, path): + inserted_puzzle = {} + try: + conn = connect_to_db() + cur = conn.cursor() + cur.execute("INSERT INTO puzzles (name, path, room, state) VALUES ('{}','{}','Default','Open')".format(puzzlename,path)) + conn.commit() + inserted_puzzle = get_puzzle_by_name(puzzlename) except: - print("ledtest table creation failed - Maybe table") + conn().rollback() + finally: conn.close() + return inserted_puzzle -def insert_led(led): - inserted_led = {} +def delete_puzzle(puzzle): + deleted_puzzle = {} try: conn = connect_to_db() cur = conn.cursor() - cur.execute("INSERT INTO ledtest (led, value) VALUES ('{}', 0)".format(led)) + deleted_puzzle = get_puzzle_by_name(puzzle) + cur.execute("DELETE from puzzles where name = ('{}')".format(puzzle)) conn.commit() - inserted_led = get_led_by_name(led) except: conn().rollback() finally: conn.close() - return inserted_led + return deleted_puzzle -def update_led(led): - updated_led = {} +def update_puzzle(newRoom, oldRoom, puzzle): + updated_puzzle = {} try: conn = connect_to_db() cur = conn.cursor() - cur.execute("UPDATE ledtest SET value = {} WHERE led = '{}'".format(led['value'], led['name'])) + cur.execute("UPDATE puzzles SET room = {} WHERE name = '{}' and room = '{}'".format(newRoom, puzzle, oldRoom)) conn.commit() - updated_led = get_led_by_name(led['name']) + updated_puzzle = get_room_by_name(puzzle['name']) except: conn().rollback() finally: conn.close() - return updated_led + return updated_puzzle -def get_led_value(led): - value = 0 +def get_puzzle_by_name(puzzle): + fetched_puzzle = {} try: conn = connect_to_db() cur = conn.cursor() - cur.execute("SELECT value from ledtest where led = '{}'".format(led)) + cur.execute("SELECT * from puzzles where name = '{}'".format(puzzle)) row = cur.fetchone() - value = row[0] + fetched_puzzle["name"] = row[1] + fetched_puzzle["path"] = row[2] + fetched_puzzle["room"] = row[3] + fetched_puzzle["state"] = row[4] except: conn().rollback() finally: conn.close() - return value + return (fetched_puzzle) -def get_led_by_name(led): - fetched_led = {} +def get_puzzle_by_name_and_room(puzzle, room): + fetched_puzzle = {} try: conn = connect_to_db() cur = conn.cursor() - cur.execute("SELECT * from ledtest where led = '{}'".format(led)) + cur.execute("SELECT * from puzzles where name = '{}' and room = '{}'".format(puzzle, room)) row = cur.fetchone() - fetched_led["name"] = row[1] - fetched_led["value"] = row[2] + fetched_puzzle["name"] = row[1] + fetched_puzzle["path"] = row[2] + fetched_puzzle["room"] = row[3] + fetched_puzzle["state"] = row[4] + except: + conn().rollback() + + finally: + conn.close() + return (fetched_puzzle) + + +def get_rooms_with_puzzles(): + rooms = {} + + try: + conn = connect_to_db() + cur = conn.cursor() + cursor = cur.execute("SELECT * from puzzles") + for row in cursor: + if row[3] not in rooms: + rooms[row[3]] = [] + rooms[row[3]].append(row[1]) except: conn().rollback() finally: conn.close() - return (fetched_led) + return (rooms)