diff --git a/modules/db.py b/modules/db.py index 0ad61c5..5e3afb9 100644 --- a/modules/db.py +++ b/modules/db.py @@ -43,6 +43,7 @@ def get_coffees(): return coffees def create_toggle_machine(): + """Create a command to toggle the coffee machine.""" randID = random.randint(1000, 9999) fullCommand = {'command': 'toggle_machine', 'status': 'pending', 'command_id': randID} conn = sqlite3.connect(DB_PATH) @@ -60,6 +61,7 @@ def create_toggle_machine(): return fullCommand def create_make_coffee(): + """Create a command to make coffee.""" randID = random.randint(1000, 9999) fullCommand = {'command': 'make_coffee', 'status': 'pending', 'command_id': randID} conn = sqlite3.connect(DB_PATH) @@ -75,6 +77,7 @@ def create_make_coffee(): return fullCommand def create_coffee_entry(): + """Create a coffee entry in the coffee database.""" conn = sqlite3.connect(DB_PATH_COFFEE) cursor = conn.cursor() cursor.execute(""" diff --git a/modules/other.py b/modules/other.py index ca4f071..7396f5f 100644 --- a/modules/other.py +++ b/modules/other.py @@ -23,6 +23,7 @@ from modules.socketio import resend_static_data from modules.db import create_coffee_entry def track_coffee_made(data, flanksUp, flanksDown): + """Track if coffee has been made based on the ESP data.""" coffee_made = False #logic for tracking coffee made @@ -34,18 +35,21 @@ def track_coffee_made(data, flanksUp, flanksDown): return def track_error_water(data, flanksUp, flanksDown): + """Track if there could be an error with water.""" water = load_dict("water") if water["fill"] <= 7: return True return False def track_error_beans(data, flanksUp, flanksDown): + """Track if there could be an error with beans.""" beans = load_dict("beans") if beans["fill"] <= 7: return True return False def track_error(data, flanksUp, flanksDown): + """Backrrack an Coffee machine error.""" if track_error_water(data, flanksUp, flanksDown): return "Wasser Leer" elif track_error_beans(data, flanksUp, flanksDown): @@ -53,6 +57,8 @@ def track_error(data, flanksUp, flanksDown): return "Unbekannter Fehler" def refactor_and_use_esp_data(data): + """Refactor and use the ESP data to update the machine state. + Calls track_coffee_made() and track_error functions().""" # global oldDataSet if 'oldDataSet' not in globals() or oldDataSet is None: oldDataSet = data # Initialize oldDataSet with default values diff --git a/modules/persistence.py b/modules/persistence.py index 74d6267..7030fc0 100644 --- a/modules/persistence.py +++ b/modules/persistence.py @@ -7,12 +7,15 @@ BASE_PATH = os.path.abspath(BASE_PATH) def save_dict(name, data): + """Saves a dictionary to a JSON file.""" path = os.path.join(BASE_PATH, f"{name}.json") os.makedirs(BASE_PATH, exist_ok=True) with open(path, "w") as f: json.dump(data, f, default=str, indent=2) def load_dict(name): + """Loads a dictionary from a JSON file. + returns the data or an empty dict if the file does not exist.""" path = os.path.join(BASE_PATH, f"{name}.json") if os.path.exists(path): with open(path, "r") as f: diff --git a/modules/socketio.py b/modules/socketio.py index 7c9bebc..4cc0233 100644 --- a/modules/socketio.py +++ b/modules/socketio.py @@ -8,6 +8,7 @@ socketio = SocketIO(cors_allowed_origins="*", async_mode='threading') # function to change the datetime format to isoformat because json does not support datetime def convert_datetimes(obj): + """Convert datetime objects in a dict or list to a specific string format.""" if isinstance(obj, dict): return {k: convert_datetimes(v) for k, v in obj.items()} elif isinstance(obj, list): @@ -19,6 +20,7 @@ def convert_datetimes(obj): def resend_static_data(): + """Resend static data to the frontend via SocketIO.""" water = load_dict("water") beans = load_dict("beans") machine = load_dict("machine") diff --git a/obj/user.py b/obj/user.py index aa6a3d4..a4dc770 100644 --- a/obj/user.py +++ b/obj/user.py @@ -74,7 +74,7 @@ class User: @staticmethod def validate_user(username, userid): - """Prüft, ob ein Benutzer mit E-Mail + Passwort existiert""" + """Prüft, ob ein Benutzer mit E-Mail + ID existiert""" db_path = os.path.join("db", "user.db") with sqlite3.connect(db_path) as conn: c = conn.cursor() diff --git a/routes/esp_routes.py b/routes/esp_routes.py index 9d5d67d..e909490 100644 --- a/routes/esp_routes.py +++ b/routes/esp_routes.py @@ -19,6 +19,7 @@ MQTT_TOPIC = "coffee/command" @esp.route('/online', methods=['POST']) def esp_online(): + """Endpoint to mark the ESP as online and update its connection info.""" data = request.get_json() sender_ip = request.headers.get('X-Forwarded-For', request.remote_addr) esp_ip = data.get("ip", "unknown") @@ -32,6 +33,7 @@ def esp_online(): @esp.route('/toggle-machine', methods=['POST']) def toggle_machine(): + """Endpoint to toggle the coffee machine state.""" fullCommand = create_toggle_machine() new_status = load_dict("machine") @@ -48,6 +50,7 @@ def toggle_machine(): @esp.route('/make_coffee', methods=['POST']) def make_coffee(): + """Endpoint to create a command to make coffee.""" fullCommand = create_make_coffee() client = mqtt.Client() diff --git a/routes/unsecure_routes.py b/routes/unsecure_routes.py index bc9b99b..835c9c7 100644 --- a/routes/unsecure_routes.py +++ b/routes/unsecure_routes.py @@ -11,6 +11,7 @@ import random @unsecure.route('/') def index(): + """Render the main page with user validation.""" username = request.args.get('username') userid = request.args.get('userid') @@ -32,6 +33,7 @@ def index(): @unsecure.route('/verify', methods=['POST']) def verify(): + """Verify user credentials and redirect accordingly.""" username = request.args.get('username') password = request.args.get('pass') @@ -48,6 +50,7 @@ def verify(): @unsecure.route('/register', methods=['POST']) def register(): + """Register a new user and redirect to the login page.""" username = request.args.get('username') password = request.args.get('pass') userid = random.randint(10000, 99999) @@ -61,10 +64,12 @@ def register(): @unsecure.route('/login') def login(): + """Render the login page.""" return render_template('login.html') @unsecure.route('/refill-water', methods=['POST']) def update_water(): + """Refill the water tank and update the water status.""" water = load_dict("water") water["lastFilled"] = datetime.now() water["fill"] = 100 @@ -76,6 +81,7 @@ def update_water(): @unsecure.route('/refill-beans', methods=['POST']) def update_beans(): + """Refill the beans container and update the beans status.""" beans = load_dict("beans") beans["lastFilled"] = datetime.now() beans["fill"] = 100 @@ -87,14 +93,17 @@ def update_beans(): @unsecure.route('/coffees-made') def coffees_made(): + """Render the coffees made page with a list of coffees.""" coffees = get_coffees() return render_template('coffees.html', title='gimmiCoffee', coffees=coffees) @unsecure.route('/water') def water(): + """Render the water status page.""" water = load_dict("water") return render_template('water.html', title='gimmiCoffee', last_filled=datetime.strptime(water["lastFilled"], "%Y-%m-%d %H:%M:%S.%f"), current_level=water["fill"], total_refills=water["refilled"], coffees_made=water["coffeesOnFill"]) @unsecure.route('/beans') def beans(): + """Render the beans status page.""" beans = load_dict("beans") return render_template('beans.html', title='gimmiCoffee', last_filled=datetime.strptime(beans["lastFilled"], "%Y-%m-%d %H:%M:%S.%f"), current_level=beans["fill"], total_refills=beans["refilled"], coffees_made=beans["coffeesOnFill"]) diff --git a/server.py b/server.py index 6cbc75e..29f49c9 100644 --- a/server.py +++ b/server.py @@ -32,6 +32,7 @@ app.register_blueprint(esp) # MQTT Callback-Funktionen def on_connect(client, userdata, flags, rc): + """Callback-Funktion, die aufgerufen wird, wenn der Client sich mit dem Broker verbindet.""" print(f"[MQTT] Verbunden mit Code {rc}") client.subscribe(MQTT_TOPIC_SUB) client.subscribe(MQTT_TOPIC_RETURN) @@ -39,6 +40,7 @@ def on_connect(client, userdata, flags, rc): print(f"[MQTT] Subscribed to topic: {MQTT_TOPIC_SUB}") def on_message(client, userdata, msg): + """Callback-Funktion, die aufgerufen wird, wenn eine Nachricht empfangen wird.""" if msg.topic == MQTT_TOPIC_SUB: print(f"[MQTT] Nachricht empfangen: {msg.topic} -> {msg.payload.decode()}") esp_conn_infos["last_seen"] = datetime.now() @@ -60,6 +62,7 @@ def on_message(client, userdata, msg): # MQTT-Thread def mqtt_thread(): + """Thread, der die MQTT-Verbindung aufbaut und Nachrichten verarbeitet.""" client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message @@ -68,7 +71,7 @@ def mqtt_thread(): # DB-Cleanup-Thread def cleanup_old_commands(): - + """Thread, der alle 5 Minuten die Datenbank nach 'pending' Befehlen durchsucht und diese auf 'failed' setzt, wenn sie älter als 5 Minuten sind.""" db_path = os.path.join(os.path.dirname(__file__), "db", "commands.db") while True: @@ -97,6 +100,7 @@ def cleanup_old_commands(): # Clear commands DB def clear_commands_db(): + """Löscht alle Einträge in der commands- und coffee-Tabelle der Datenbank.""" import os import sqlite3 @@ -121,6 +125,7 @@ def clear_commands_db(): # Motitior ESP-Connection def monitor_esp_connection(): + """Überwacht die Verbindung zum ESP und setzt die Verbindung auf ungültig, wenn der ESP länger als 3 Minuten nicht gesehen wurde.""" while True: if esp_conn_infos["last_seen"]: time_diff = datetime.now() - esp_conn_infos["last_seen"]