From fca6aa31de7342d4b7ffba93f86dbef2815821d1 Mon Sep 17 00:00:00 2001 From: LittleLishu Date: Fri, 18 Apr 2025 18:00:52 +0800 Subject: [PATCH] init --- __pycache__/globallight.cpython-313.pyc | Bin 0 -> 2852 bytes __pycache__/globallight.cpython-38.pyc | Bin 0 -> 1873 bytes cloud.py | 34 ++++ cloud.yml | 77 ++++++++ createdb.ipynb | 213 ++++++++++++++++++++++ globallight.py | 71 ++++++++ ihub.py | 233 ++++++++++++++++++++++++ light.db | Bin 0 -> 61440 bytes lightcluster.joblib | Bin 0 -> 1851 bytes lightcluster.py | 71 ++++++++ rcontroller.js | 80 ++++++++ rnode.js | 35 ++++ smartcontrol.py | 49 +++++ sqlite.txt | 7 + 14 files changed, 870 insertions(+) create mode 100644 __pycache__/globallight.cpython-313.pyc create mode 100644 __pycache__/globallight.cpython-38.pyc create mode 100644 cloud.py create mode 100644 cloud.yml create mode 100644 createdb.ipynb create mode 100644 globallight.py create mode 100644 ihub.py create mode 100644 light.db create mode 100644 lightcluster.joblib create mode 100644 lightcluster.py create mode 100644 rcontroller.js create mode 100644 rnode.js create mode 100644 smartcontrol.py create mode 100644 sqlite.txt diff --git a/__pycache__/globallight.cpython-313.pyc b/__pycache__/globallight.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..592ce5baca8f1ca367c43044b21da253089071a9 GIT binary patch literal 2852 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' + str(result[1]) + '' + str(result[2]) + '' + str(result[3]) + '' + + html += '' + + conn.close() + + return html + +# If we're running in stand alone mode, run the application +if __name__ == '__main__': + # app.run(host='0.0.0.0', port=5000, debug=True) + app.run(host='0.0.0.0', port=5000) diff --git a/cloud.yml b/cloud.yml new file mode 100644 index 0000000..916f200 --- /dev/null +++ b/cloud.yml @@ -0,0 +1,77 @@ +swagger: "2.0" +info: + description: This is the swagger file that goes with our server code + version: "1.0.0" + title: Swagger REST Article +consumes: + - "application/json" +produces: + - "application/json" + +basePath: "/api" + +# Paths supported by the server application +paths: + /globallight: + get: + operationId: "globallight.read" + tags: + - "Global Light" + summary: "The light data structure supported by the server application" + description: "Read the list of light" + responses: + 200: + description: "Successful read light list operation" + schema: + type: "array" + items: + properties: + id: + type: "number" + devicename: + type: "string" + light: + type: "number" + timestamp: + type: "string" + put: + operationId: "globallight.create" + tags: + - Global Light + summary: Create a light record in the database + description: Create a new light in the database + parameters: + - name: globallight + in: body + description: Light record to create + required: True + schema: + type: object + properties: + devicename: + type: "string" + light: + type: "number" + timestamp: + type: "string" + responses: + 200: + description: Successfully created light record in database + + /lightcluster: + get: + operationId: "globallight.cluster" + tags: + - Get cluster label of light + summary: "Get cluster label of light" + description: "Get cluster label of light" + parameters: + - name: light + in: query + description: Light + required: true + type: number + + responses: + 200: + description: "Successful prediction" \ No newline at end of file diff --git a/createdb.ipynb b/createdb.ipynb new file mode 100644 index 0000000..c62e96a --- /dev/null +++ b/createdb.ipynb @@ -0,0 +1,213 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "ename": "OperationalError", + "evalue": "unable to open database file", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mOperationalError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[8]\u001b[39m\u001b[32m, line 40\u001b[39m\n\u001b[32m 37\u001b[39m conn.close()\n\u001b[32m 38\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m (\u001b[33m\"\u001b[39m\u001b[33mTable \u001b[39m\u001b[33m'\u001b[39m\u001b[33mlight\u001b[39m\u001b[33m'\u001b[39m\u001b[33m does NOT exist.\u001b[39m\u001b[33m\"\u001b[39m, [])\n\u001b[32m---> \u001b[39m\u001b[32m40\u001b[39m init_message = \u001b[43minit_db\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 41\u001b[39m check_message, schema_info = check_db()\n\u001b[32m 43\u001b[39m init_message, check_message, schema_info\n", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[8]\u001b[39m\u001b[32m, line 5\u001b[39m, in \u001b[36minit_db\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m 4\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34minit_db\u001b[39m():\n\u001b[32m----> \u001b[39m\u001b[32m5\u001b[39m conn = \u001b[43msqlite3\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43msrc\u001b[39;49m\u001b[38;5;130;43;01m\\\\\u001b[39;49;00m\u001b[33;43mlight.db\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 6\u001b[39m c = conn.cursor()\n\u001b[32m 8\u001b[39m \u001b[38;5;66;03m# Create the 'light' table if it doesn't already exist\u001b[39;00m\n", + "\u001b[31mOperationalError\u001b[39m: unable to open database file" + ] + } + ], + "source": [ + "import sqlite3\n", + "\n", + "# Initialize the database and table\n", + "def init_db():\n", + " conn = sqlite3.connect('src\\\\light.db')\n", + " c = conn.cursor()\n", + "\n", + " # Create the 'light' table if it doesn't already exist\n", + " c.execute('''\n", + " CREATE TABLE IF NOT EXISTS light (\n", + " id INTEGER PRIMARY KEY AUTOINCREMENT,\n", + " devicename CHARACTER(5) NOT NULL,\n", + " light INTEGER NOT NULL,\n", + " timestamp DATETIME NOT NULL,\n", + " tocloud BOOLEAN DEFAULT 0 NOT NULL\n", + " )\n", + " ''')\n", + "\n", + " conn.commit()\n", + " conn.close()\n", + " return \"Database initialized and table 'light' is ready.\"\n", + "\n", + "# Check if the table exists and print the schema\n", + "def check_db():\n", + " conn = sqlite3.connect('src\\\\light.db')\n", + " c = conn.cursor()\n", + "\n", + " c.execute(\"SELECT name FROM sqlite_master WHERE type='table' AND name='light';\")\n", + " table_exists = c.fetchone()\n", + "\n", + " if table_exists:\n", + " c.execute(\"PRAGMA table_info(light);\")\n", + " columns = c.fetchall()\n", + " conn.close()\n", + " return (\"Table 'light' exists.\", columns)\n", + " else:\n", + " conn.close()\n", + " return (\"Table 'light' does NOT exist.\", [])\n", + "\n", + "init_message = init_db()\n", + "check_message, schema_info = check_db()\n", + "\n", + "init_message, check_message, schema_info\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "<>:3: SyntaxWarning: invalid escape sequence '\\l'\n", + "<>:3: SyntaxWarning: invalid escape sequence '\\l'\n", + "C:\\Users\\LittleLishu\\AppData\\Local\\Temp\\ipykernel_22052\\2500929216.py:3: SyntaxWarning: invalid escape sequence '\\l'\n", + " conn = sqlite3.connect('src\\light.db')\n" + ] + }, + { + "ename": "OperationalError", + "evalue": "unable to open database file", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mOperationalError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 18\u001b[39m\n\u001b[32m 15\u001b[39m conn.close()\n\u001b[32m 16\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m (\u001b[33m\"\u001b[39m\u001b[33mTable \u001b[39m\u001b[33m'\u001b[39m\u001b[33mlight\u001b[39m\u001b[33m'\u001b[39m\u001b[33m does NOT exist.\u001b[39m\u001b[33m\"\u001b[39m, [])\n\u001b[32m---> \u001b[39m\u001b[32m18\u001b[39m check_message, schema_info = \u001b[43mcheck_db\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 19\u001b[39m check_message, schema_info\n", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 3\u001b[39m, in \u001b[36mcheck_db\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m 2\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mcheck_db\u001b[39m():\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m conn = \u001b[43msqlite3\u001b[49m\u001b[43m.\u001b[49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43msrc\u001b[39;49m\u001b[33;43m\\\u001b[39;49m\u001b[33;43mlight.db\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 4\u001b[39m c = conn.cursor()\n\u001b[32m 6\u001b[39m c.execute(\u001b[33m\"\u001b[39m\u001b[33mSELECT name FROM sqlite_master WHERE type=\u001b[39m\u001b[33m'\u001b[39m\u001b[33mtable\u001b[39m\u001b[33m'\u001b[39m\u001b[33m AND name=\u001b[39m\u001b[33m'\u001b[39m\u001b[33mlight\u001b[39m\u001b[33m'\u001b[39m\u001b[33m;\u001b[39m\u001b[33m\"\u001b[39m)\n", + "\u001b[31mOperationalError\u001b[39m: unable to open database file" + ] + } + ], + "source": [ + "import sqlite3\n", + "def check_db():\n", + " conn = sqlite3.connect('src\\light.db')\n", + " c = conn.cursor()\n", + "\n", + " c.execute(\"SELECT name FROM sqlite_master WHERE type='table' AND name='light';\")\n", + " table_exists = c.fetchone()\n", + "\n", + " if table_exists:\n", + " c.execute(\"PRAGMA table_info(light);\")\n", + " columns = c.fetchall()\n", + " conn.close()\n", + " return (\"Table 'light' exists.\", columns)\n", + " else:\n", + " conn.close()\n", + " return (\"Table 'light' does NOT exist.\", [])\n", + "\n", + "check_message, schema_info = check_db()\n", + "check_message, schema_info" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tables in the database:\n", + "light\n", + "sqlite_sequence\n", + "Empty DataFrame\n", + "Columns: [id, devicename, light, timestamp, tocloud]\n", + "Index: []\n" + ] + } + ], + "source": [ + "import sqlite3\n", + "import pandas as pd\n", + "\n", + "db_path = r\"D:\\OneDrive - National University of Singapore\\Document\\NUSCourses\\Semester 2\\IS5451 AloT Solutions and Development\\Mock\\src\\lighttest.db\"\n", + "\n", + "conn = sqlite3.connect(db_path)\n", + "\n", + "cursor = conn.cursor()\n", + "\n", + "# 获取所有表名\n", + "cursor.execute(\"SELECT name FROM sqlite_master WHERE type='table';\")\n", + "tables = cursor.fetchall()\n", + "\n", + "print(\"Tables in the database:\")\n", + "for table in tables:\n", + " print(table[0])\n", + "\n", + "df = pd.read_sql_query(\"SELECT * FROM light\", conn)\n", + "\n", + "print(df)\n", + "\n", + "conn.close()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'d:\\\\OneDrive - National University of Singapore\\\\Document\\\\NUSCourses\\\\Semester 2\\\\IS5451 AloT Solutions and Development\\\\Mock\\\\src'" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import os\n", + "os.getcwd()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 将txt的command写入light.db,在树莓派上运行\n", + "sqlite3 light.db < sqlite.txt" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "is5451", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/globallight.py b/globallight.py new file mode 100644 index 0000000..c752a6f --- /dev/null +++ b/globallight.py @@ -0,0 +1,71 @@ +import sqlite3 +from flask import make_response, abort + +from joblib import dump, load + + + +def read(): + + lights = [] + + conn = sqlite3.connect('light.db') + + c = conn.cursor() + c.execute('SELECT id, devicename, light, timestamp FROM light ORDER BY id ASC') + results = c.fetchall() + + for result in results: + + lights.append({'id':result[0],'devicename':result[1],'light':result[2],'timestamp':result[3]}) + + conn.close() + + return lights + + + +def create(globallight): + ''' + This function creates a new light record in the database + based on the passed in light data + :param globallight: Global light record to create in the database + :return: 200 on success + ''' + devicename = globallight.get('devicename', None) + light = globallight.get('light', None) + timestamp = globallight.get('timestamp', None) + + conn = sqlite3.connect('light.db') + + c = conn.cursor() + sql = "INSERT INTO light (devicename, light, timestamp) VALUES('" + devicename + "', " + str(light) + ", '" + timestamp + "')" + print(sql) + c.execute(sql) + conn.commit() + conn.close() + + return make_response('Global light record successfully created', 200) + + + +def cluster(light): + + try: + + # predict new temperature and humidity observation + kmeans = load('lightcluster.joblib') + + # temperature, humidity + newX = [[light]] + result = kmeans.predict(newX) + + print('Cluster Light: light={}; cluster={}'.format(light, result[0])) + + return str(result[0]) + + except Exception as error: + + print('Error: {}'.format(error.args[0])) + + return 'Unknown' diff --git a/ihub.py b/ihub.py new file mode 100644 index 0000000..b8529bd --- /dev/null +++ b/ihub.py @@ -0,0 +1,233 @@ +import time +import random + +import serial +import RPi.GPIO as GPIO + +import sqlite3 +import requests +import json + +import paho.mqtt.client as mqtt + +import _thread as thread + + + +def sendCommand(command): + + command = command + '\n' + ser.write(str.encode(command)) + + + +def waitResponse(): + + response = ser.readline() + response = response.decode('utf-8').strip() + + return response + + + +def saveData(lights): + + conn = sqlite3.connect('light.db') + c = conn.cursor() + + for light in lights: + + data = light.split('=') + + sql = "INSERT INTO light (devicename, light, timestamp) VALUES('" + data[0] + "', " + data[1] + ", datetime('now', 'localtime'))" + c.execute(sql) + + conn.commit() + conn.close() + + lights.clear() + + + +def rhub(): + + global ser + ser = serial.Serial(port='/dev/ttyACM0', baudrate=115200, timeout=1) + print('rhub: Listening on /dev/ttyACM0... Press CTRL+C to exit') + + # Handshaking + sendCommand('handshake') + + strMicrobitDevices = '' + + while strMicrobitDevices == None or len(strMicrobitDevices) <= 0: + + strMicrobitDevices = waitResponse() + + print('rhub handshake: ' + strMicrobitDevices) + + time.sleep(0.1) + + strMicrobitDevices = strMicrobitDevices.split('=') + + if len(strMicrobitDevices[1]) > 0: + + listMicrobitDevices = strMicrobitDevices[1].split(',') + + if len(listMicrobitDevices) > 0: + + for mb in listMicrobitDevices: + + print('rhub: Connected to micro:bit device {}...'.format(mb)) + + while True: + + time.sleep(1) + + commandToTx = 'sensor=light' + sendCommand('cmd:' + commandToTx) + + if commandToTx.startswith('sensor='): + + strSensorValues = '' + + while strSensorValues == None or len(strSensorValues) <= 0: + + strSensorValues = waitResponse() + time.sleep(0.1) + + listSensorValues = strSensorValues.split(',') + + for sensorValue in listSensorValues: + + print('rhub: {}'.format(sensorValue)) + + saveData(listSensorValues) + + + +def cloudrelay(): + + conn = sqlite3.connect('light.db') + + base_uri = 'http://169.254.53.99:5000/' + globallight_uri = base_uri + 'api/globallight' + headers = {'content-type': 'application/json'} + + + + while True: + + time.sleep(10) + + print('Relaying data to cloud server...') + + c = conn.cursor() + c.execute('SELECT id, devicename, light, timestamp FROM light WHERE tocloud = 0') + results = c.fetchall() + c = conn.cursor() + + for result in results: + + print('Relaying id={}; devicename={}; light={}; timestamp={}'.format(result[0], result[1], result[2], result[3])) + + glight = { + 'devicename':result[1], + 'light':result[2], + 'timestamp':result[3] + } + req = requests.put(globallight_uri, headers = headers, data = json.dumps(glight)) + + c.execute('UPDATE light SET tocloud = 1 WHERE id = ' + str(result[0])) + + conn.commit() + + + +def on_message(client, userdata, msg): + + smartlight = str(msg.payload.decode()) + print('Smartlight command subscribed: ' + smartlight) + + if smartlight == 'on': + + GPIO.output(redLedPin, True) + + else: + + GPIO.output(redLedPin, False) + + + +def smartlight(): + + broker = 'broker.emqx.io' + port = 1883 + topic = "/is4151-is5451/mockpe/smartlight" + client_id = f'python-mqtt-{random.randint(0, 10000)}' + username = 'emqx' + password = 'public' + client = mqtt.Client(client_id) + client.username_pw_set(username, password) + client.connect(broker, port) + client.subscribe(topic) + client.on_message = on_message + client.loop_forever() + + + +def init(): + + GPIO.setmode(GPIO.BOARD) + + global redLedPin + redLedPin = 11 + GPIO.setup(redLedPin, GPIO.OUT) + GPIO.output(redLedPin, False) + + + +def main(): + + init() + + thread.start_new_thread(rhub, ()) + thread.start_new_thread(cloudrelay, ()) + thread.start_new_thread(smartlight, ()) + + print('Program running... Press CTRL+C to exit') + + while True: + + try: + + time.sleep(0.1) + + except RuntimeError as error: + + print('Error: {}'.format(error.args[0])) + + except Exception as error: + + print('Error: {}'.format(error.args[0])) + + except KeyboardInterrupt: + + if ser.is_open: + + ser.close() + + GPIO.cleanup() + + print('Program terminating...') + + break + + + print('Program exited...') + + + +if __name__ == '__main__': + + main() diff --git a/light.db b/light.db new file mode 100644 index 0000000000000000000000000000000000000000..aeb5bf2f7fc0e977704b55b658ab000ba4574de7 GIT binary patch literal 61440 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