Remise en état Logs
This commit is contained in:
1
.env
1
.env
@@ -3,6 +3,7 @@ DB_HOST=162.19.78.131
|
|||||||
DB_USER=excel
|
DB_USER=excel
|
||||||
DB_PASSWORD='%n#%3Lay1MPa$%kR^5@'
|
DB_PASSWORD='%n#%3Lay1MPa$%kR^5@'
|
||||||
DB_NAME=Acces
|
DB_NAME=Acces
|
||||||
|
DB_NAME2=Sondes
|
||||||
ADMIN_USER=Michel
|
ADMIN_USER=Michel
|
||||||
ADMIN_PASS_HASH='$2b$12$Dgv7jNLJuR.3hQminSVE9OP6hCSmW4nISArR3HF5LTPGFK0Zw29N2'
|
ADMIN_PASS_HASH='$2b$12$Dgv7jNLJuR.3hQminSVE9OP6hCSmW4nISArR3HF5LTPGFK0Zw29N2'
|
||||||
|
|
||||||
|
|||||||
2
.idea/dataSources.xml
generated
2
.idea/dataSources.xml
generated
@@ -5,7 +5,7 @@
|
|||||||
<driver-ref>mariadb</driver-ref>
|
<driver-ref>mariadb</driver-ref>
|
||||||
<synchronize>true</synchronize>
|
<synchronize>true</synchronize>
|
||||||
<jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver>
|
<jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver>
|
||||||
<jdbc-url>jdbc:mariadb://162.19.78.131:3306/Acces</jdbc-url>
|
<jdbc-url>jdbc:mariadb://162.19.78.131:3306/Sondes</jdbc-url>
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
</data-source>
|
</data-source>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import mysql.connector, os
|
|
||||||
cnx = mysql.connector.connect(
|
|
||||||
host=os.getenv("DB_HOST"),
|
|
||||||
port=int(os.getenv("DB_PORT", "3306")),
|
|
||||||
user=os.getenv("DB_USER"),
|
|
||||||
password=os.getenv("DB_PASS"),
|
|
||||||
database=os.getenv("DB_NAME"),
|
|
||||||
)
|
|
||||||
print("OK, connecté !")
|
|
||||||
cnx.close()
|
|
||||||
|
|
||||||
227
app/injection_tables.py
Normal file
227
app/injection_tables.py
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
import os
|
||||||
|
import datetime as dt
|
||||||
|
import pandas as pd
|
||||||
|
import streamlit as st
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import mysql.connector as mc
|
||||||
|
|
||||||
|
# ----------------------
|
||||||
|
# Config de la page
|
||||||
|
# ----------------------
|
||||||
|
st.set_page_config(page_title="Injection de données de test", page_icon="🧪", layout="centered")
|
||||||
|
st.title("🧪 Injecteur de relevés de test (Sondes)")
|
||||||
|
st.caption("Crée ~10 lignes au-dessus d'un seuil pour tester les alertes")
|
||||||
|
|
||||||
|
# ----------------------
|
||||||
|
# Connexion MySQL depuis .env
|
||||||
|
# ----------------------
|
||||||
|
@st.cache_resource(show_spinner=False)
|
||||||
|
def get_connection():
|
||||||
|
load_dotenv()
|
||||||
|
try:
|
||||||
|
cnx = mc.connect(
|
||||||
|
host=os.getenv("DB_HOST"),
|
||||||
|
user=os.getenv("DB_USER"),
|
||||||
|
password=os.getenv("DB_PASSWORD"),
|
||||||
|
database=os.getenv("DB_NAME2"),
|
||||||
|
autocommit=True,
|
||||||
|
)
|
||||||
|
return cnx
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"Échec de connexion MySQL : {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
# ----------------------
|
||||||
|
# Helpers : liste des sondes
|
||||||
|
# ----------------------
|
||||||
|
@st.cache_data(ttl=60, show_spinner=False)
|
||||||
|
def list_sondes(site: str) -> list:
|
||||||
|
"""
|
||||||
|
Retourne la liste des sondes pour un site donné.
|
||||||
|
1) Sondes actives dans Chambres_froides
|
||||||
|
2) À défaut : DISTINCT Sonde dans la table de mesures {site}
|
||||||
|
Affiche des messages DEBUG en cas d'erreur ou de liste vide.
|
||||||
|
"""
|
||||||
|
cnx = get_connection()
|
||||||
|
cur = cnx.cursor()
|
||||||
|
|
||||||
|
# 1) Chambres_froides
|
||||||
|
try:
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
SELECT Sonde
|
||||||
|
FROM `Chambres_froides`
|
||||||
|
WHERE Lieu = %s
|
||||||
|
AND (Etat = 'ON' OR Etat = 1)
|
||||||
|
ORDER BY Sonde
|
||||||
|
""",
|
||||||
|
(site,),
|
||||||
|
)
|
||||||
|
rows = [r[0] for r in cur.fetchall()]
|
||||||
|
if rows:
|
||||||
|
st.info(f"[DEBUG] {len(rows)} sonde(s) trouvée(s) dans Chambres_froides pour Lieu='{site}'.")
|
||||||
|
return rows
|
||||||
|
else:
|
||||||
|
st.info(f"[DEBUG] Aucune sonde active dans Chambres_froides pour Lieu='{site}'.")
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"[DEBUG] Erreur Chambres_froides : {e}")
|
||||||
|
|
||||||
|
# 2) Fallback : table de mesures `{site}`
|
||||||
|
try:
|
||||||
|
cur.execute(f"SELECT DISTINCT Sonde FROM `{site}` ORDER BY Sonde LIMIT 200")
|
||||||
|
rows = [r[0] for r in cur.fetchall()]
|
||||||
|
if rows:
|
||||||
|
st.info(f"[DEBUG] {len(rows)} sonde(s) trouvée(s) dans la table `{site}`.")
|
||||||
|
return rows
|
||||||
|
else:
|
||||||
|
st.info(f"[DEBUG] Aucune sonde trouvée dans la table `{site}`.")
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"[DEBUG] Erreur table `{site}` : {e}")
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
# ----------------------
|
||||||
|
# Helper : récupérer Temp_Max pour une sonde donnée
|
||||||
|
# ----------------------
|
||||||
|
@st.cache_data(ttl=60, show_spinner=False)
|
||||||
|
def get_temp_max(site: str, sonde: str):
|
||||||
|
"""
|
||||||
|
Retourne Temp_Max pour (site, sonde) depuis Chambres_froides.
|
||||||
|
Renvoie None si non trouvé, avec messages DEBUG.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
cnx = get_connection()
|
||||||
|
cur = cnx.cursor()
|
||||||
|
cur.execute(
|
||||||
|
"""
|
||||||
|
SELECT Temp_Max
|
||||||
|
FROM `Chambres_froides`
|
||||||
|
WHERE Lieu = %s AND Sonde = %s
|
||||||
|
LIMIT 1
|
||||||
|
""",
|
||||||
|
(site, sonde),
|
||||||
|
)
|
||||||
|
row = cur.fetchone()
|
||||||
|
if row and row[0] is not None:
|
||||||
|
st.info(f"[DEBUG] Temp_Max trouvé pour {site}/{sonde} : {row[0]}°C.")
|
||||||
|
return float(row[0])
|
||||||
|
else:
|
||||||
|
st.info(f"[DEBUG] Aucun Temp_Max trouvé dans Chambres_froides pour {site}/{sonde}.")
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"[DEBUG] Erreur get_temp_max : {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------
|
||||||
|
# UI paramètres
|
||||||
|
# ----------------------
|
||||||
|
with st.sidebar:
|
||||||
|
st.header("Paramètres")
|
||||||
|
site = st.selectbox("Site (table)", ["Saclay", "Meudon"], index=0)
|
||||||
|
|
||||||
|
# Sélecteur de sonde depuis la liste
|
||||||
|
options_sondes = list_sondes(site)
|
||||||
|
if not options_sondes:
|
||||||
|
st.warning("Aucune sonde trouvée pour ce site. Vous pouvez saisir un nom manuel.")
|
||||||
|
sonde = st.text_input("Nom de la sonde", value="TEST_Chambre1")
|
||||||
|
else:
|
||||||
|
sonde = st.selectbox("Sonde", options_sondes)
|
||||||
|
|
||||||
|
st.subheader("Température")
|
||||||
|
# Auto-remplissage du seuil depuis la base et verrouillage par défaut
|
||||||
|
_temp_db = get_temp_max(site, sonde)
|
||||||
|
if _temp_db is None:
|
||||||
|
st.warning("Temp_Max introuvable en base ; valeur par défaut 6.0°C.")
|
||||||
|
_temp_db = 6.0
|
||||||
|
allow_edit = st.checkbox("Autoriser la modification du seuil", value=False)
|
||||||
|
temp_max = st.number_input("Seuil (Temp_Max)", value=float(_temp_db), step=0.1, disabled=not allow_edit)
|
||||||
|
|
||||||
|
delta = st.number_input("Delta au-dessus du seuil", value=1.0, step=0.1)
|
||||||
|
absolute_override = st.checkbox("Définir une température absolue à la place")
|
||||||
|
absolute_temp = st.number_input(
|
||||||
|
"Température absolue (si coché)", value=12.5, step=0.1, disabled=not absolute_override
|
||||||
|
)
|
||||||
|
|
||||||
|
st.subheader("Série temporelle")
|
||||||
|
rows = st.number_input("Nombre de points", min_value=1, max_value=200, value=10, step=1)
|
||||||
|
step_min = st.number_input("Pas (minutes)", min_value=1, max_value=120, value=5, step=1)
|
||||||
|
start_offset = st.number_input("Début : il y a (minutes)", min_value=0, max_value=1440, value=5, step=5)
|
||||||
|
|
||||||
|
|
||||||
|
st.markdown("---")
|
||||||
|
st.caption("Nettoyage rapide")
|
||||||
|
cleanup_scope = st.selectbox("Supprimer", ["Cette sonde", "Toutes les TEST_ des dernières 24h"])
|
||||||
|
do_cleanup = st.button("🧹 Supprimer les données de test")
|
||||||
|
col1, col2 = st.columns(2)
|
||||||
|
# ----------------------
|
||||||
|
# Actions
|
||||||
|
# ----------------------
|
||||||
|
if col1.button("🚀 Injecter les données"):
|
||||||
|
try:
|
||||||
|
cnx = get_connection()
|
||||||
|
cur = cnx.cursor()
|
||||||
|
|
||||||
|
# Calcul des timestamps et de la valeur
|
||||||
|
now = dt.datetime.now()
|
||||||
|
t0 = now - dt.timedelta(minutes=int(start_offset))
|
||||||
|
if absolute_override:
|
||||||
|
value = float(absolute_temp)
|
||||||
|
else:
|
||||||
|
value = float(temp_max) + float(delta)
|
||||||
|
|
||||||
|
# Préparation batch INSERT
|
||||||
|
sql = f"INSERT INTO `{site}` (Sonde, Temperature, Date) VALUES (%s,%s,%s)"
|
||||||
|
batch = []
|
||||||
|
for i in range(int(rows)):
|
||||||
|
ts = t0 + dt.timedelta(minutes=i * int(step_min))
|
||||||
|
batch.append((sonde, value, ts.strftime("%Y-%m-%d %H:%M:%S")))
|
||||||
|
|
||||||
|
cur.executemany(sql, batch)
|
||||||
|
st.success(f"{len(batch)} lignes insérées dans `{site}` pour **{sonde}** à **{value}°C**.")
|
||||||
|
|
||||||
|
# Aperçu des données insérées
|
||||||
|
cur.execute(
|
||||||
|
f"""
|
||||||
|
SELECT Id, Sonde, Temperature, Date
|
||||||
|
FROM `{site}`
|
||||||
|
WHERE Sonde = %s AND Date >= %s AND Date <= %s
|
||||||
|
ORDER BY Date DESC
|
||||||
|
LIMIT 50
|
||||||
|
""",
|
||||||
|
(
|
||||||
|
sonde,
|
||||||
|
(t0 - dt.timedelta(minutes=1)).strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
|
(t0 + dt.timedelta(minutes=int(rows)*int(step_min) + 1)).strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
rows_preview = cur.fetchall()
|
||||||
|
if rows_preview:
|
||||||
|
df = pd.DataFrame(rows_preview, columns=["Id", "Sonde", "Temperature", "Date"])
|
||||||
|
st.dataframe(df, use_container_width=True, hide_index=True)
|
||||||
|
else:
|
||||||
|
st.info("Aucune ligne trouvée pour l'aperçu (vérifiez les filtres/horaires).")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"Erreur lors de l'injection : {e}")
|
||||||
|
|
||||||
|
# Nettoyage
|
||||||
|
def cleanup():
|
||||||
|
cnx = get_connection()
|
||||||
|
cur = cnx.cursor()
|
||||||
|
if cleanup_scope == "Cette sonde":
|
||||||
|
cur.execute(f"DELETE FROM `{site}` WHERE Sonde = %s", (sonde,))
|
||||||
|
st.success(f"Données supprimées pour la sonde **{sonde}** dans `{site}`.")
|
||||||
|
else:
|
||||||
|
cur.execute(
|
||||||
|
f"DELETE FROM `{site}` WHERE Sonde LIKE 'TEST\_%' ESCAPE '\\' AND Date >= NOW() - INTERVAL 1 DAY"
|
||||||
|
)
|
||||||
|
st.success(f"Toutes les sondes **TEST_** des dernières 24h supprimées dans `{site}`.")
|
||||||
|
|
||||||
|
if do_cleanup:
|
||||||
|
try:
|
||||||
|
cleanup()
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"Erreur de nettoyage : {e}")
|
||||||
|
|
||||||
Reference in New Issue
Block a user