Files

276 lines
7.0 KiB
Python

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)