final
This commit is contained in:
@@ -241,5 +241,3 @@ def boucle_principale():
|
|||||||
|
|
||||||
|
|
||||||
# ════════════════════════════════════════════════════════════════════════════
|
# ════════════════════════════════════════════════════════════════════════════
|
||||||
if __name__ == "__main__":
|
|
||||||
boucle_principale()
|
|
||||||
@@ -1,19 +1,14 @@
|
|||||||
import Adafruit_DHT as dht
|
import Adafruit_DHT as dht
|
||||||
import time as t
|
|
||||||
import RPi.GPIO as GPIO
|
|
||||||
|
|
||||||
GPIO.setmode(GPIO.BOARD)
|
# On définit juste le capteur et la broche (Rappel : 25 en BCM = broche physique 22)
|
||||||
capteur = dht.DHT11
|
capteur = dht.DHT11
|
||||||
pin = 25
|
pin = 25
|
||||||
|
|
||||||
def lire_temperature():
|
def lire_temperature():
|
||||||
humidite, temperature = dht.read_retry(capteur, pin)
|
humidite, temperature = dht.read_retry(capteur, pin)
|
||||||
|
|
||||||
|
# On renvoie la température au script principal !
|
||||||
if temperature is not None:
|
if temperature is not None:
|
||||||
print("Temp :", temperature, "°C")
|
return temperature
|
||||||
else:
|
else:
|
||||||
print("Erreur")
|
return 0 # Sécurité si le capteur bugge, pour ne pas faire planter l'affichage
|
||||||
|
|
||||||
t.sleep(2)
|
|
||||||
|
|
||||||
lire_temperature()
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import time
|
import time
|
||||||
from alarme import SystemeAlarme
|
from ALARM_V1 import *
|
||||||
from porterfid import SystemePorteRFID
|
from porterfid import SystemePorteRFID
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
@@ -16,15 +16,18 @@ alarme = SystemeAlarme()
|
|||||||
porte = SystemePorteRFID()
|
porte = SystemePorteRFID()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def call_board1():
|
def call_board1():
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
# Mise à jour des deux modules locaux
|
# Mise à jour des deux modules locaux
|
||||||
alarme.mettreAJour()
|
ALARM_V1.boucle_principale()
|
||||||
porte.mettreAJour()
|
porte.mettreAJour()
|
||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
porte.cleanup()
|
||||||
|
alarme.cleanup()
|
||||||
print("\nArrêt manuel du programme.")
|
print("\nArrêt manuel du programme.")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import RPi.GPIO as GPIO
|
import RPi.GPIO as GPIO
|
||||||
import time as t
|
import time as t
|
||||||
from septsegments import afficher_temperature
|
from septsegments import afficher_temperature
|
||||||
|
from DHT11 import lire_temperature
|
||||||
|
|
||||||
GPIO.setmode(GPIO.BCM)
|
GPIO.setmode(GPIO.BCM)
|
||||||
GPIO.setwarnings(False)
|
GPIO.setwarnings(False)
|
||||||
@@ -11,32 +12,43 @@ GPIO.setup(bouton_up, GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
|||||||
GPIO.setup(bouton_down, GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
GPIO.setup(bouton_down, GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
||||||
|
|
||||||
def test_boutons():
|
def test_boutons():
|
||||||
temperature = 18
|
# 1. On lit la vraie température au démarrage
|
||||||
|
temperature_DHT = lire_temperature()
|
||||||
|
# 2. On fixe la température qu'on souhaite (la cible)
|
||||||
|
temperature_cible = 18
|
||||||
|
|
||||||
etatPrecedent_up = GPIO.input(bouton_up)
|
etatPrecedent_up = GPIO.input(bouton_up)
|
||||||
etatPrecedent_down = GPIO.input(bouton_down)
|
etatPrecedent_down = GPIO.input(bouton_down)
|
||||||
|
|
||||||
print("Test lancé ! Appuie sur UP (23) pour monter, DOWN (24) pour descendre.")
|
print("Thermostat lancé ! Appuie sur UP (23) ou DOWN (24).")
|
||||||
|
|
||||||
|
# On affiche une première fois pour que l'écran ne soit pas vide au lancement
|
||||||
|
afficher_temperature(temperature_DHT, temperature_cible)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
etat_up = GPIO.input(bouton_up)
|
etat_up = GPIO.input(bouton_up)
|
||||||
etat_down = GPIO.input(bouton_down)
|
etat_down = GPIO.input(bouton_down)
|
||||||
|
|
||||||
|
# --- BOUTON UP ---
|
||||||
if etat_up != etatPrecedent_up:
|
if etat_up != etatPrecedent_up:
|
||||||
if etat_up == 0:
|
if etat_up == 0:
|
||||||
print("Bouton UP Appuyé ⬆️")
|
print("Bouton UP Appuyé ⬆️")
|
||||||
temperature += 1
|
temperature_cible += 1
|
||||||
if temperature >= 40:
|
if temperature_cible >= 40:
|
||||||
temperature = 40
|
temperature_cible = 40
|
||||||
afficher_temperature(21,temperature)
|
# On met à jour l'écran
|
||||||
|
afficher_temperature(temperature_DHT, temperature_cible)
|
||||||
etatPrecedent_up = etat_up
|
etatPrecedent_up = etat_up
|
||||||
|
|
||||||
|
# --- BOUTON DOWN ---
|
||||||
if etat_down != etatPrecedent_down:
|
if etat_down != etatPrecedent_down:
|
||||||
if etat_down == 0:
|
if etat_down == 0:
|
||||||
print("Bouton DOWN Appuyé ⬇️")
|
print("Bouton DOWN Appuyé ⬇️")
|
||||||
temperature -= 1
|
temperature_cible -= 1
|
||||||
if temperature <= 0:
|
if temperature_cible <= 0:
|
||||||
temperature = 0
|
temperature_cible = 0
|
||||||
afficher_temperature(21,temperature)
|
# On met à jour l'écran
|
||||||
|
afficher_temperature(temperature_DHT, temperature_cible)
|
||||||
etatPrecedent_down = etat_down
|
etatPrecedent_down = etat_down
|
||||||
|
|
||||||
t.sleep(0.05)
|
t.sleep(0.05)
|
||||||
|
|||||||
@@ -20,3 +20,4 @@ def afficher_temperature(temperature, temperature_moyenne):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Erreur d'affichage : {e}")
|
print(f"Erreur d'affichage : {e}")
|
||||||
|
execpt keybo
|
||||||
@@ -19,6 +19,13 @@ from etatsysteme import EtatSysteme
|
|||||||
from septsegments import afficher_temperature
|
from septsegments import afficher_temperature
|
||||||
|
|
||||||
app = FastAPI(title="L'API des loustiques")
|
app = FastAPI(title="L'API des loustiques")
|
||||||
|
app.add_middleware(
|
||||||
|
CORSMiddleware,
|
||||||
|
allow_origins=["*"],
|
||||||
|
allow_credentials=False,
|
||||||
|
allow_methods=["*"],
|
||||||
|
allow_headers=["*"],
|
||||||
|
)
|
||||||
|
|
||||||
controleur_lumieres = SystemeLumieres()
|
controleur_lumieres = SystemeLumieres()
|
||||||
controleur_thermostat = SystemeThermostat()
|
controleur_thermostat = SystemeThermostat()
|
||||||
@@ -66,21 +73,11 @@ async def read_temp():
|
|||||||
return {"success": False, "message": str(e)}
|
return {"success": False, "message": str(e)}
|
||||||
|
|
||||||
|
|
||||||
app.add_middleware(
|
|
||||||
CORSMiddleware,
|
|
||||||
allow_origins=["*"], # Autorise tous les sites web (le fameux "*")
|
|
||||||
allow_credentials=False, # (Doit être False quand on met "*")
|
|
||||||
allow_methods=["*"], # Autorise toutes les méthodes (GET, POST, etc.)
|
|
||||||
allow_headers=["*"], # Autorise tous les en-têtes
|
|
||||||
)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# On prépare les chemins proprement pour éviter les erreurs de parenthèses
|
|
||||||
# (Vérifie bien que le dossier 'web_secu' est bien dans le dossier racine de ton Pi 2)
|
|
||||||
chemin_cle = os.path.join(BASE_DIR, 'web_secu', 'ssl', 'key.pem')
|
chemin_cle = os.path.join(BASE_DIR, 'web_secu', 'ssl', 'key.pem')
|
||||||
chemin_cert = os.path.join(BASE_DIR, 'web_secu', 'ssl', 'cert.pem')
|
chemin_cert = os.path.join(BASE_DIR, 'web_secu', 'ssl', 'cert.pem')
|
||||||
|
|
||||||
# On lance Uvicorn avec la bonne syntaxe
|
|
||||||
uvicorn.run(
|
uvicorn.run(
|
||||||
"main:app",
|
"main:app",
|
||||||
host="0.0.0.0",
|
host="0.0.0.0",
|
||||||
|
|||||||
@@ -65,4 +65,5 @@ EOF
|
|||||||
sleep 1
|
sleep 1
|
||||||
touch /var/log/loustique.log
|
touch /var/log/loustique.log
|
||||||
chown ${SUDO_USER}:${SUDO_USER} /var/log/loustique.log
|
chown ${SUDO_USER}:${SUDO_USER} /var/log/loustique.log
|
||||||
|
venv/bin/python composants/test/bouton.py
|
||||||
venv/bin/python main.py
|
venv/bin/python main.py
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
from flask import Flask, render_template, request, jsonify
|
from flask import Flask, render_template, request, jsonify
|
||||||
|
import requests
|
||||||
from flask_talisman import Talisman
|
from flask_talisman import Talisman
|
||||||
from led import led
|
from led import led
|
||||||
import os
|
import os
|
||||||
|
import threading
|
||||||
import sys
|
import sys
|
||||||
import log
|
import log
|
||||||
from add_user import add_user
|
from add_user import add_user
|
||||||
@@ -48,7 +50,6 @@ def call_led():
|
|||||||
else:
|
else:
|
||||||
SystemeLumieres.eteindreLumieres()
|
SystemeLumieres.eteindreLumieres()
|
||||||
return jsonify({"success": True})
|
return jsonify({"success": True})
|
||||||
# Variable temporaire pour stocker le dernier badge scanné
|
|
||||||
dernier_badge_scanne = None
|
dernier_badge_scanne = None
|
||||||
|
|
||||||
@app.route("/rfid-scan", methods=["POST"])
|
@app.route("/rfid-scan", methods=["POST"])
|
||||||
@@ -56,47 +57,29 @@ def rfid_scan():
|
|||||||
global dernier_badge_scanne
|
global dernier_badge_scanne
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
badge_id = data.get("badge_id")
|
badge_id = data.get("badge_id")
|
||||||
|
|
||||||
# On va créer cette fonction dans ton fichier auth.py juste après
|
|
||||||
username = auth.get_user_by_rfid(badge_id)
|
username = auth.get_user_by_rfid(badge_id)
|
||||||
|
|
||||||
if username:
|
if username:
|
||||||
# Le badge est dans la base de données ! On autorise.
|
|
||||||
dernier_badge_scanne = username
|
dernier_badge_scanne = username
|
||||||
return jsonify({"success": True, "username": username})
|
return jsonify({"success": True, "username": username})
|
||||||
else:
|
else:
|
||||||
# Badge inconnu
|
|
||||||
return jsonify({"success": False})
|
return jsonify({"success": False})
|
||||||
|
|
||||||
@app.route("/check-rfid-login", methods=["GET"])
|
@app.route("/check-rfid-login", methods=["GET"])
|
||||||
def check_rfid_login():
|
def check_rfid_login():
|
||||||
global dernier_badge_scanne
|
global dernier_badge_scanne
|
||||||
global current_user
|
global current_user
|
||||||
|
|
||||||
# Si le Raspberry Pi a signalé un badge validé récemment
|
|
||||||
if dernier_badge_scanne:
|
if dernier_badge_scanne:
|
||||||
user = dernier_badge_scanne
|
user = dernier_badge_scanne
|
||||||
|
|
||||||
# On valide la connexion côté serveur
|
|
||||||
current_user = user
|
current_user = user
|
||||||
|
|
||||||
# On vide la variable pour ne pas le reconnecter en boucle à l'infini
|
|
||||||
dernier_badge_scanne = None
|
dernier_badge_scanne = None
|
||||||
|
|
||||||
return jsonify({"success": True, "username": user})
|
return jsonify({"success": True, "username": user})
|
||||||
|
|
||||||
return jsonify({"success": False})
|
return jsonify({"success": False})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/alarme",methods=["POST"])
|
@app.route("/alarme",methods=["POST"])
|
||||||
def armer_alarme():
|
def armer_alarme():
|
||||||
SystemeAlarme.armer()
|
SystemeAlarme.armer()
|
||||||
return jsonify({"success": True})
|
return jsonify({"success": True})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/admin")
|
@app.route("/admin")
|
||||||
def admin_page():
|
def admin_page():
|
||||||
return render_template("admin.html")
|
return render_template("admin.html")
|
||||||
@@ -131,22 +114,32 @@ def get_users():
|
|||||||
users = auth.get_users()
|
users = auth.get_users()
|
||||||
return jsonify({"success": True, "users": users})
|
return jsonify({"success": True, "users": users})
|
||||||
|
|
||||||
@app.route("/api/relais-pi2/<action>", methods=["GET"])
|
@app.route("/api/<action>", methods=["GET"])
|
||||||
def relais_pi2(action):
|
def relais_pi2(action):
|
||||||
"""
|
|
||||||
Flask sert de relais. Le navigateur demande à Flask, et Flask demande au Pi 2.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
# L'adresse de ton Pi 2
|
|
||||||
url_pi2 = f"https://pi32.local:8000/{action}"
|
url_pi2 = f"https://pi32.local:8000/{action}"
|
||||||
|
print(f"\n[RELAIS] 1. Tentative de contact avec le Pi 2 : {url_pi2}")
|
||||||
|
|
||||||
# Le Pi 1 fait la requête ! verify=False permet d'ignorer le faux certificat
|
try:
|
||||||
reponse = requests.get(url_pi2, timeout=5, verify=False)
|
reponse = requests.get(url_pi2, timeout=5, verify=False)
|
||||||
|
print(f"[RELAIS] 2. Code HTTP reçu du Pi 2 : {reponse.status_code}")
|
||||||
|
print(f"[RELAIS] 3. Texte brut reçu du Pi 2 : {reponse.text}")
|
||||||
|
if not reponse.ok:
|
||||||
|
return jsonify({
|
||||||
|
"success": False,
|
||||||
|
"message": f"Le Pi 2 a refusé la requête (Code {reponse.status_code})"
|
||||||
|
}), reponse.status_code
|
||||||
|
|
||||||
return jsonify(reponse.json())
|
# Si tout va bien, on tente d'extraire le JSON
|
||||||
|
try:
|
||||||
|
data = reponse.json()
|
||||||
|
return jsonify(data)
|
||||||
|
except ValueError:
|
||||||
|
print("[RELAIS] 4. ERREUR : Le Pi 2 n'a pas renvoyé de JSON valide.")
|
||||||
|
return jsonify({"success": False, "message": "Réponse invalide du Pi 2"}), 502
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({"success": False, "message": str(e)})
|
print(f"[RELAIS] ERREUR CRITIQUE : Impossible de joindre le Pi 2. Raison : {e}")
|
||||||
|
return jsonify({"success": False, "message": f"Erreur de connexion : {str(e)}"}), 500
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -234,14 +234,14 @@
|
|||||||
<svg class="card-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
<svg class="card-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
||||||
<div class="card-label">Heure locale</div>
|
<div class="card-label">Heure locale</div>
|
||||||
<div class="card-value" id="clock">--:--</div>
|
<div class="card-value" id="clock">--:--</div>
|
||||||
<div class="card-sub" id="date-display">--</div>
|
<div class="card-sub" id="date-display">--</div></div>
|
||||||
</div>
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-label">Température</div>
|
|
||||||
<div class="card-sub" id="date-display">--</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
|
<div class="card-label">Température</div>
|
||||||
|
<div class="card-value" id="temp-display">-- °C</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="card"></div>
|
||||||
<div class="card-label">Porte</div>
|
<div class="card-label">Porte</div>
|
||||||
<div class="card-sub" id="date-display">--</div>
|
<div class="card-sub" id="date-display">--</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -273,7 +273,7 @@
|
|||||||
<span class="a-sub">Allumer la LED</span>
|
<span class="a-sub">Allumer la LED</span>
|
||||||
<span class="a-arrow">›</span>
|
<span class="a-arrow">›</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="action-btn" onclick="callAlarm()">
|
<button class="action-btn" onclick="call_led_down()">
|
||||||
<span class="a-label">DOWN led</span>
|
<span class="a-label">DOWN led</span>
|
||||||
<span class="a-sub">Eteindre la led</span>
|
<span class="a-sub">Eteindre la led</span>
|
||||||
<span class="a-arrow">›</span></button>
|
<span class="a-arrow">›</span></button>
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
setInterval(updateClock, 1000);
|
setInterval(updateClock, 1000);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
async function callAlarm() {
|
async function callAlarm() {
|
||||||
try {
|
try {
|
||||||
const res = await fetch('/alarme', {
|
const res = await fetch('/alarme', {
|
||||||
@@ -316,10 +316,34 @@
|
|||||||
showToast("alarme activée !");
|
showToast("alarme activée !");
|
||||||
} catch {
|
} catch {
|
||||||
showToast("Erreur lors de l'appel alarme.");
|
showToast("Erreur lors de l'appel alarme.");
|
||||||
|
}*/
|
||||||
|
|
||||||
|
async function get_temperature() {
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/temperature', {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
|
||||||
|
if (data.success) {
|
||||||
|
document.getElementById("temp-display").textContent = data.temperature + " °C";
|
||||||
|
} else {
|
||||||
|
document.getElementById("temp-display").textContent = "Erreur";
|
||||||
|
console.error("Erreur de température :", data.message);
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
document.getElementById("temp-display").textContent = "Hors ligne";
|
||||||
|
console.error("Impossible de joindre le relais pour la température.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get_temperature();
|
||||||
|
setInterval(get_temperature, 60000);
|
||||||
async function call_led_down() {
|
async function call_led_down() {
|
||||||
try {
|
try {
|
||||||
const res = await fetch('https://pi32.local:8000down_led', {
|
const res = await fetch('/api/down_led', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json' }
|
||||||
});
|
});
|
||||||
@@ -327,10 +351,10 @@
|
|||||||
} catch {
|
} catch {
|
||||||
showToast("Erreur lors de l'appel board1.");
|
showToast("Erreur lors de l'appel board1.");
|
||||||
}}
|
}}
|
||||||
}
|
|
||||||
async function call_led_up() {
|
async function call_led_up() {
|
||||||
try {
|
try {
|
||||||
const res = await fetch('https://pi32.local:8000/up_led', {
|
const res = await fetch('/api/up_led', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json' }
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user