from flask import Flask, jsonify, render_template, request, redirect, url_for, session from flask_cors import CORS from config import Config import psycopg2 app = Flask(__name__) app.config.from_object(Config) app.secret_key = app.config["SECRET_KEY"] CORS(app) def get_connection(): return psycopg2.connect( host=app.config["DB_HOST"], port=app.config["DB_PORT"], database=app.config["DB_NAME"], user=app.config["DB_USER"], password=app.config["DB_PASSWORD"] ) def get_setting_value(cur, key, default_value): cur.execute("SELECT value FROM settings WHERE key = %s", (key,)) row = cur.fetchone() return row[0] if row else default_value @app.route("/") def home(): return jsonify({ "message": "API EcoCharge en ligne" }) @app.route("/api/status") def status(): return jsonify({ "project": "EcoCharge", "api": "ok", "database": "postgresql_connected" }) @app.route("/api/data", methods=["POST"]) def receive_data(): data = request.get_json() if not data: return jsonify({"error": "Aucune donnée JSON reçue"}), 400 # Données environnement temperature_ext = data.get("temperature_ext") humidity_ext = data.get("humidity_ext") system_status_msg = data.get("system_status") # Données panneau solaire voltage_pv = data.get("voltage_pv") current_pv = data.get("current_pv") # compatible solar_power power_pv = data.get("power_pv", data.get("solar_power")) luminosity = data.get("luminosity") # Données batterie voltage_battery = data.get("voltage_battery", data.get("battery_voltage")) current_battery = data.get("current_battery") # compatible battery_temperature battery_temp = data.get("battery_temp", data.get("battery_temperature")) battery_level = data.get("battery_level") conn = get_connection() cur = conn.cursor() max_battery_temperature = float(get_setting_value(cur, "max_battery_temperature", "60")) min_battery_voltage = float(get_setting_value(cur, "min_battery_voltage", "11")) min_solar_power = float(get_setting_value(cur, "min_solar_power", "5")) battery_alert = "none" if battery_temp is not None and float(battery_temp) > max_battery_temperature: battery_alert = "Température batterie trop élevée" elif voltage_battery is not None and float(voltage_battery) < min_battery_voltage: battery_alert = "Tension batterie trop faible" elif power_pv is not None and float(power_pv) < min_solar_power: battery_alert = "Puissance solaire insuffisante" cur.execute(""" INSERT INTO telemetry ( temperature_ext, humidity_ext, system_status_msg, voltage_pv, current_pv, power_pv, luminosity, voltage_battery, current_battery, battery_temp, battery_level, battery_alert ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) """, ( temperature_ext, humidity_ext, system_status_msg, voltage_pv, current_pv, power_pv, luminosity, voltage_battery, current_battery, battery_temp, battery_level, battery_alert )) conn.commit() cur.close() conn.close() return jsonify({ "message": "Données enregistrées avec succès", "battery_alert": battery_alert }), 201 @app.route("/api/latest", methods=["GET"]) def latest_data(): conn = get_connection() cur = conn.cursor() cur.execute(""" SELECT id, created_at, temperature_ext, humidity_ext, system_status_msg, voltage_pv, current_pv, power_pv, luminosity, voltage_battery, current_battery, battery_temp, battery_level, battery_alert FROM telemetry ORDER BY created_at DESC LIMIT 1 """) row = cur.fetchone() cur.close() conn.close() if not row: return jsonify({"message": "Aucune donnée disponible"}), 404 return jsonify({ "id": row[0], "created_at": str(row[1]), "temperature_ext": row[2], "humidity_ext": row[3], "system_status": row[4], "voltage_pv": row[5], "current_pv": row[6], "power_pv": row[7], "luminosity": row[8], "voltage_battery": row[9], "current_battery": row[10], "battery_temp": row[11], "battery_level": row[12], "battery_alert": row[13] }) @app.route("/admin/login", methods=["GET", "POST"]) def admin_login(): if request.method == "POST": username = request.form.get("username") password = request.form.get("password") conn = get_connection() cur = conn.cursor() cur.execute( "SELECT id FROM users WHERE username = %s AND password = %s AND is_admin = TRUE", (username, password) ) user = cur.fetchone() cur.close() conn.close() if user: session["admin_logged_in"] = True return redirect(url_for("admin_dashboard")) return render_template("login.html", error="Identifiants incorrects") return render_template("login.html") @app.route("/admin/dashboard", methods=["GET", "POST"]) def admin_dashboard(): if not session.get("admin_logged_in"): return redirect(url_for("admin_login")) conn = get_connection() cur = conn.cursor() if request.method == "POST": min_battery = request.form.get("min_battery") max_temp = request.form.get("max_temp") min_power = request.form.get("min_power") cur.execute(""" INSERT INTO settings (key, value) VALUES ('min_battery_voltage', %s) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value """, (min_battery,)) cur.execute(""" INSERT INTO settings (key, value) VALUES ('max_battery_temperature', %s) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value """, (max_temp,)) cur.execute(""" INSERT INTO settings (key, value) VALUES ('min_solar_power', %s) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value """, (min_power,)) conn.commit() settings = { "min_battery": get_setting_value(cur, "min_battery_voltage", "11"), "max_temp": get_setting_value(cur, "max_battery_temperature", "60"), "min_power": get_setting_value(cur, "min_solar_power", "5") } cur.close() conn.close() return render_template("admin_dashboard.html", settings=settings) @app.route("/admin/logout") def admin_logout(): session.pop("admin_logged_in", None) return redirect(url_for("admin_login")) if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True)