🐞 Issue Summary I am encountering a serial connection error when trying to access COM13 on my Windows machine. Here's the error message I get: #12056
Labels
Type: Duplicate
Another item already exists for this topic
THIS IS MY PYTHON CODE
import sys
import dash
from dash import dcc, html, dash_table
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import pandas as pd
import serial
import psycopg2
import re
from datetime import datetime
import time
import threading
import atexit
Configuration initiale
SERIAL_PORT = 'COM13' # Adjust to your port
BAUD_RATE = 9600
TIME_WINDOW = 50 # Number of points to display in graphs (same as first script)
Global serial and database objects for cleanup
ser = None
conn = None
Connexion à PostgreSQL
try:
conn = psycopg2.connect(
host="localhost",
user="postgres",
password="123",
database="capteurs",
port="5432"
)
print("✅ Database connection established")
except Exception as e:
print(f"❌ Database connection failed: {e}")
sys.exit(1)
Connexion au port série avec tentative de réessai
def open_serial_port():
global ser
for _ in range(3): # Try 3 times
try:
ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)
print("✅ Serial connection established")
return True
except serial.SerialException as e:
print(f"❌ Serial connection attempt failed: {e}")
time.sleep(2) # Wait before retry
print(f"❌ Failed to open {SERIAL_PORT} after retries")
return False
if not open_serial_port():
conn.close()
sys.exit(1)
Initialisation de l'application Dash
external_stylesheets = [
'https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap',
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css'
]
app = dash.Dash(name, external_stylesheets=external_stylesheets)
CSS pour respecter le design cool
<style> body { background-color: #0F142F; font-family: 'Montserrat', sans-serif; color: white; } .dashboard-container { padding: 20px; max-width: 1400px; margin: auto; } .dashboard-header { background: linear-gradient(90deg, #1A2242, #2A3158); padding: 20px; border-radius: 10px; text-align: center; margin-bottom: 20px; } .dashboard-title { font-size: 36px; font-weight: 700; color: #FFFFFF; } .update-container { display: flex; align-items: center; justify-content: center; margin-top: 10px; } .blinking-dot { width: 10px; height: 10px; background-color: #24E07B; border-radius: 50%; margin-right: 10px; animation: blink 1s infinite; } @Keyframes blink { 0% { opacity: 1; } 50% { opacity: 0; } 100% { opacity: 1; } } .last-update-text { font-size: 16px; color: #A6B0CF; } .metrics-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 20px; } .metric-card { background: #1A2242; padding: 20px; border-radius: 10px; text-align: center; box-shadow: 0 4px 8px rgba(0,0,0,0.3); } .metric-header { display: flex; align-items: center; justify-content: center; margin-bottom: 10px; } .metric-icon { font-size: 24px; margin-right: 10px; color: #00CFFF; } .metric-title { font-size: 18px; font-weight: 600; } .metric-value { font-size: 28px; font-weight: 700; color: #FFFFFF; } .metric-time { font-size: 14px; color: #A6B0CF; } .temp-high { color: #F25F5C; } .temp-normal { color: #00CFFF; } .gas-value, .flame-value, .mouvement-value { font-size: 20px; } .graphs-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 20px; margin-bottom: 20px; } .graph-container { background: #131A3A; padding: 15px; border-radius: 10px; } .table-container { background: #1A2242; padding: 20px; border-radius: 10px; } .table-title { font-size: 24px; font-weight: 600; text-align: center; margin-bottom: 15px; } </style>app.css.append_css({
"external_url": """
"""
})
Layout du dashboard
app.layout = html.Div([
html.Div([
html.H1("SMART HOUSE MONITORING", className="dashboard-title"),
html.Div([
html.Span(className="blinking-dot"),
html.Span(id='last-update', className="last-update-text")
], className="update-container")
], className="dashboard-header"),
html.Div([
html.Div([
html.Div([
html.I(className="fas fa-thermometer-half metric-icon"),
html.Span("Température", className="metric-title")
], className="metric-header"),
html.Div(id='temp-value', className="metric-value"),
html.Div(id='temp-time', className="metric-time")
], className="metric-card temperature-card"),
], className="metrics-container"),
html.Div([
dcc.Graph(id='temp-hum-graph', className="graph-container"),
dcc.Graph(id='gas-graph', className="graph-container"),
dcc.Graph(id='flame-motion-graph', className="graph-container")
], className="graphs-row"),
html.Div([
html.H3("ALERTES CRITIQUES", className="table-title"),
dash_table.DataTable(
id='alerts-table',
columns=[
{"name": "Timestamp", "id": "timestamp"},
{"name": "Type Alerte", "id": "type_alerte"},
{"name": "Valeur", "id": "valeur"},
{"name": "Criticité", "id": "criticite"}
],
style_table={'overflowX': 'auto'},
style_cell={
'textAlign': 'center', 'padding': '12px', 'border': '1px solid #2A3158',
'backgroundColor': '#131A3A', 'color': 'white', 'fontFamily': 'Montserrat', 'minWidth': '100px'
},
style_header={
'backgroundColor': '#2A3158', 'color': 'white', 'fontWeight': 'bold',
'fontFamily': 'Montserrat', 'border': '1px solid #3A4277', 'textTransform': 'uppercase',
'letterSpacing': '1px', 'fontSize': '12px'
},
style_data_conditional=[
{'if': {'row_index': 'odd'}, 'backgroundColor': '#1A2242'},
{'if': {'column_id': 'criticite', 'filter_query': '{criticite} >= 3'}, 'backgroundColor': '#F25F5C', 'color': 'white', 'fontWeight': 'bold'}
],
page_size=5, page_action='native', filter_action='native', sort_action='native'
)
], className="table-container"),
html.Div([
html.H3("HISTORIQUE DES DONNÉES", className="table-title"),
dash_table.DataTable(
id='sensor-table',
columns=[
{"name": "Timestamp", "id": "timestamp"},
{"name": "Température (°C)", "id": "temperature"},
{"name": "Humidité (%)", "id": "humidite"},
{"name": "CH4 (ppm)", "id": "ch4"},
{"name": "LPG (ppm)", "id": "lpg"},
{"name": "H2 (ppm)", "id": "h2"},
{"name": "CO (ppm)", "id": "co"},
{"name": "Flamme", "id": "flame"},
{"name": "Mouvement", "id": "mouvement"}
],
style_table={'overflowX': 'auto'},
style_cell={
'textAlign': 'center', 'padding': '12px', 'border': '1px solid #2A3158',
'backgroundColor': '#131A3A', 'color': 'white', 'fontFamily': 'Montserrat', 'minWidth': '100px'
},
style_header={
'backgroundColor': '#2A3158', 'color': 'white', 'fontWeight': 'bold',
'fontFamily': 'Montserrat', 'border': '1px solid #3A4277', 'textTransform': 'uppercase',
'letterSpacing': '1px', 'fontSize': '12px'
},
style_data_conditional=[
{'if': {'row_index': 'odd'}, 'backgroundColor': '#1A2242'},
{'if': {'column_id': 'flame', 'filter_query': '{flame} eq "Oui"'}, 'backgroundColor': '#F25F5C', 'color': 'white', 'fontWeight': 'bold'},
{'if': {'column_id': 'mouvement', 'filter_query': '{mouvement} eq "Oui"'}, 'backgroundColor': '#FFD700', 'color': 'white', 'fontWeight': 'bold'}
],
page_size=10, page_action='native', filter_action='native', sort_action='native'
)
], className="table-container"),
dcc.Interval(id='interval-component', interval=1000, n_intervals=0)
], className="dashboard-container")
Fonctions pour le traitement des données série (adapté au format de votre sortie)
def extract_value(text):
match = re.search(r"[-+]?\d*.\d+|\d+", text)
return float(match.group()) if match else 0.0
def parse_serial_data(line):
data = {}
try:
if not line or line.startswith(("-----", "Initialisation", "Concentrations de gaz:", "Ventilation:", "Condition climatique:", "RFID:", "Heure:", "Date:", "Position:", "Vitesse:", "Satellites:", "Statut GPS:")):
return None
if "Température:" in line:
data['Temp'] = extract_value(line.split("Température:")[1].split("°C")[0])
elif "Humidité:" in line:
data['Hum'] = extract_value(line.split("Humidité:")[1].split("%")[0])
elif "Mouvement:" in line:
data['Mouvement'] = "Détecté" in line
elif "CH4 (Méthane):" in line:
data['CH4'] = extract_value(line.split("CH4 (Méthane):")[1].split("ppm")[0])
elif "LPG (GPL):" in line:
data['LPG'] = extract_value(line.split("LPG (GPL):")[1].split("ppm")[0])
elif "H2 (Hydrogène):" in line:
data['H2'] = extract_value(line.split("H2 (Hydrogène):")[1].split("ppm")[0])
elif "CO (Monoxyde):" in line:
data['CO'] = extract_value(line.split("CO (Monoxyde):")[1].split("ppm")[0])
elif "Flamme:" in line:
parts = line.split("Flamme:")[1].split("-")
data['Flamme'] = extract_value(parts[0])
data['Flamme_detected'] = "Non détectée" not in parts[1]
return data if data else None
except Exception as e:
print(f"Erreur de parsing: {e}, Line: {line}")
return None
Fonction pour enregistrer dans la base de données
def save_to_database(data_type, values, timestamp):
try:
cursor = conn.cursor()
if data_type == "dht22" and 'Temp' in values and 'Hum' in values:
cursor.execute(
"INSERT INTO dht22 (temperature, humidite, timestamp) VALUES (%s, %s, %s)",
(values['Temp'], values['Hum'], timestamp)
)
elif data_type == "mq5":
cursor.execute(
"INSERT INTO mq5 (ch4, lpg, h2, co, timestamp) VALUES (%s, %s, %s, %s, %s)",
(values.get('CH4', 0), values.get('LPG', 0), values.get('H2', 0), values.get('CO', 0), timestamp)
)
elif data_type == "flamme" and 'Flamme_detected' in values:
cursor.execute(
"INSERT INTO flamme (detecte, valeur_analog, timestamp) VALUES (%s, %s, %s)",
(values['Flamme_detected'], values.get('Flamme', 0), timestamp)
)
elif data_type == "mouvement" and 'Mouvement' in values:
cursor.execute(
"INSERT INTO mouvement (detecte, timestamp) VALUES (%s, %s)",
(values['Mouvement'], timestamp)
)
Insert alerts
if data_type == "mq5" and 'CH4' in values and values['CH4'] > 5:
cursor.execute(
"INSERT INTO alertes (type_alerte, valeur, timestamp, criticite) VALUES (%s, %s, %s, %s)",
("Gaz CH4", f"{values['CH4']:.2f} ppm", timestamp, 3)
)
if data_type == "flamme" and 'Flamme_detected' in values and values['Flamme_detected']:
cursor.execute(
"INSERT INTO alertes (type_alerte, valeur, timestamp, criticite) VALUES (%s, %s, %s, %s)",
("Flamme", "Détectée", timestamp, 4)
)
if data_type == "dht22" and 'Temp' in values and values['Temp'] > 30:
cursor.execute(
"INSERT INTO alertes (type_alerte, valeur, timestamp, criticite) VALUES (%s, %s, %s, %s)",
("Température", f"{values['Temp']:.1f} °C", timestamp, 2)
)
if data_type == "dht22" and 'Hum' in values and values['Hum'] > 70:
cursor.execute(
"INSERT INTO alertes (type_alerte, valeur, timestamp, criticite) VALUES (%s, %s, %s, %s)",
("Humidité", f"{values['Hum']:.1f} %", timestamp, 2)
)
conn.commit()
cursor.close()
except psycopg2.Error as e:
print(f"Erreur d'insertion dans {data_type}: {e}")
conn.rollback()
Thread pour la lecture série
def serial_reader():
global ser
current_data = {}
while True:
try:
if not ser or not ser.is_open:
if not open_serial_port():
time.sleep(5)
continue
while True:
if ser.in_waiting:
line = ser.readline().decode('utf-8', errors='ignore').strip()
print(f"📡 Donnée reçue: {line}")
parsed = parse_serial_data(line)
if parsed:
current_data.update(parsed)
if {'Temp', 'Hum', 'CH4', 'LPG', 'H2', 'CO', 'Flamme', 'Flamme_detected', 'Mouvement'}.issubset(current_data.keys()):
timestamp = datetime.now()
save_to_database("dht22", current_data, timestamp)
save_to_database("mq5", current_data, timestamp)
save_to_database("flamme", current_data, timestamp)
save_to_database("mouvement", current_data, timestamp)
current_data = {}
time.sleep(0.1)
except serial.SerialException as e:
print(f"❌ Erreur série: {e}")
if ser and ser.is_open:
ser.close()
ser = None
time.sleep(5)
serial_thread = threading.Thread(target=serial_reader, daemon=True)
serial_thread.start()
def cleanup_resources():
global ser, conn
if ser and ser.is_open:
ser.close()
print("✅ Serial port closed")
if conn:
conn.close()
print("✅ Database connection closed")
atexit.register(cleanup_resources)
Fonctions pour créer les graphiques⚠️ Using fallback data for temp/hum graph")
def create_temp_hum_fig(df):
if df.empty or df[['temperature', 'humidite']].isna().all().all():
now = datetime.now()
df = pd.DataFrame({
'timestamp': [now],
'temperature': [25.7],
'humidite': [47.6]
})
print("
fig = go.Figure()⚠️ Using fallback data for gas graph")
fig.add_trace(go.Scatter(
x=df['timestamp'], y=df['temperature'], name='Température (°C)',
line=dict(color='#FF0000', width=3), fill='tozeroy', fillcolor='rgba(255, 0, 0, 0.1)',
hovertemplate='%{y:.1f}°C'
))
fig.add_trace(go.Scatter(
x=df['timestamp'], y=df['humidite'], name='Humidité (%)', yaxis='y2',
line=dict(color='#0000FF', width=3), fill='tozeroy', fillcolor='rgba(0, 0, 255, 0.1)',
hovertemplate='%{y:.1f}%'
))
fig.update_layout(
title={'text': 'TEMPÉRATURE & HUMIDITÉ', 'font': {'color': 'white', 'family': 'Montserrat', 'size': 18}, 'x': 0.5},
plot_bgcolor='#131A3A', paper_bgcolor='#131A3A', font={'color': 'white', 'family': 'Montserrat'},
xaxis={'gridcolor': '#2A3158', 'linecolor': '#2A3158', 'showgrid': True, 'tickfont': {'size': 10}, 'tickformat': '%H:%M:%S'},
yaxis={'title': 'Température (°C)', 'color': '#FF0000', 'gridcolor': '#2A3158', 'zeroline': False},
yaxis2={'title': 'Humidité (%)', 'overlaying': 'y', 'side': 'right', 'color': '#0000FF', 'zeroline': False},
legend={'orientation': 'h', 'yanchor': 'bottom', 'y': 1.02, 'xanchor': 'right', 'x': 1},
margin={'l': 50, 'r': 50, 't': 70, 'b': 50}, hovermode='x unified'
)
return fig
def create_gas_fig(df):
if df.empty or df[['ch4', 'lpg', 'h2', 'co']].isna().all().all():
now = datetime.now()
df = pd.DataFrame({
'timestamp': [now],
'ch4': [2.28], 'lpg': [1.94], 'h2': [2.18], 'co': [1.77]
})
print("
fig = go.Figure()⚠️ Using fallback data for flame/motion graph")
for gas, color in [('ch4', '#24E07B'), ('lpg', '#FF7D34'), ('h2', '#00CFFF'), ('co', '#A259FF')]:
fig.add_trace(go.Scatter(
x=df['timestamp'], y=df[gas], name=gas.upper(),
line=dict(color=color, width=3), fill='tozeroy', fillcolor=f'rgba({int(color[1:3], 16)}, {int(color[3:5], 16)}, {int(color[5:7], 16)}, 0.1)',
hovertemplate='%{y:.2f} ppm'
))
fig.update_layout(
title={'text': 'NIVEAUX DE GAZ DANGEREUX', 'font': {'color': 'white', 'family': 'Montserrat', 'size': 18}, 'x': 0.5},
plot_bgcolor='#131A3A', paper_bgcolor='#131A3A', font={'color': 'white', 'family': 'Montserrat'},
xaxis={'gridcolor': '#2A3158', 'linecolor': '#2A3158', 'showgrid': True, 'tickfont': {'size': 10}, 'tickformat': '%H:%M:%S'},
yaxis={'title': 'Concentration (ppm)', 'gridcolor': '#2A3158', 'zeroline': False},
legend={'orientation': 'h', 'yanchor': 'bottom', 'y': 1.02, 'xanchor': 'right', 'x': 1},
margin={'l': 50, 'r': 50, 't': 70, 'b': 50}, hovermode='x unified'
)
return fig
def create_flame_motion_fig(df):
if df.empty or df[['flame', 'mouvement']].isna().all().all():
now = datetime.now()
df = pd.DataFrame({
'timestamp': [now],
'flame': [False],
'mouvement': [True]
})
print("
fig = go.Figure()
fig.add_trace(go.Scatter(
x=df['timestamp'], y=df['flame'].astype(int), name='Flamme détectée',
line=dict(color='#FFA500', width=3), mode='lines+markers', marker=dict(size=6)
))
fig.add_trace(go.Scatter(
x=df['timestamp'], y=df['mouvement'].astype(int), name='Mouvement détecté',
line=dict(color='#00FF00', width=3), mode='lines+markers', marker=dict(size=6)
))
fig.update_layout(
title={'text': 'DÉTECTION FLAMME & MOUVEMENT', 'font': {'color': 'white', 'family': 'Montserrat', 'size': 18}, 'x': 0.5},
plot_bgcolor='#131A3A', paper_bgcolor='#131A3A', font={'color': 'white', 'family': 'Montserrat'},
xaxis={'gridcolor': '#2A3158', 'linecolor': '#2A3158', 'showgrid': True, 'tickfont': {'size': 10}, 'tickformat': '%H:%M:%S'},
yaxis={'title': 'État (0=Non, 1=Oui)', 'gridcolor': '#2A3158', 'zeroline': False, 'tickvals': [0, 1], 'ticktext': ['Non', 'Oui']},
legend={'orientation': 'h', 'yanchor': 'bottom', 'y': 1.02, 'xanchor': 'right', 'x': 1},
margin={'l': 50, 'r': 50, 't': 70, 'b': 50}, hovermode='x unified'
)
return fig
@app.callback(
[Output('temp-value', 'children'), Output('temp-value', 'className'), Output('temp-time', 'children'),
Output('hum-value', 'children'), Output('hum-time', 'children'),
Output('gas-value', 'children'), Output('gas-time', 'children'),
Output('flame-value', 'children'), Output('flame-time', 'children'),
Output('mouvement-value', 'children'), Output('mouvement-time', 'children'),
Output('temp-hum-graph', 'figure'), Output('gas-graph', 'figure'), Output('flame-motion-graph', 'figure'),
Output('sensor-table', 'data'), Output('alerts-table', 'data'), Output('last-update', 'children')],
[Input('interval-component', 'n_intervals')]
)
def update_dashboard(n):
try:
cursor = conn.cursor()
queries = {
'dht22': "SELECT timestamp, temperature, humidite FROM dht22 WHERE timestamp > NOW() - INTERVAL '1 hour' ORDER BY timestamp DESC LIMIT 50",
'mq5': "SELECT timestamp, ch4, lpg, h2, co FROM mq5 WHERE timestamp > NOW() - INTERVAL '1 hour' ORDER BY timestamp DESC LIMIT 50",
'flamme': "SELECT timestamp, detecte AS flame, valeur_analog AS flame_value FROM flamme WHERE timestamp > NOW() - INTERVAL '1 hour' ORDER BY timestamp DESC LIMIT 50",
'mouvement': "SELECT timestamp, detecte AS mouvement FROM mouvement WHERE timestamp > NOW() - INTERVAL '1 hour' ORDER BY timestamp DESC LIMIT 50"
}
except Exception as e:⚠️ Dernière tentative: {now}"
print(f"❌ Erreur dashboard: {e}")
now = datetime.now().strftime("%H:%M:%S")
empty_fig = go.Figure().update_layout(
plot_bgcolor='#131A3A', paper_bgcolor='#131A3A',
annotations=[dict(text=f'Erreur: {str(e)}', showarrow=False, font=dict(color='white', size=16))]
)
return [
"25.7°C", "metric-value temp-normal", f"Erreur: {str(e)}",
"47.6%", f"Erreur: {str(e)}",
"CH4: 2.28ppm | LPG: 1.94ppm
H2: 2.18ppm | CO: 1.77ppm", f"Erreur: {str(e)}",
"Non détectée", f"Valeur: 889.0",
"Non détecté", f"Erreur: {str(e)}",
empty_fig, empty_fig, empty_fig,
[], [], f"
]
finally:
if 'cursor' in locals():
cursor.close()
if name == 'main':
try:
app.run(debug=True, host='127.0.0.1', port=8050)
except Exception as e:
print(f"❌ Erreur lors du démarrage du serveur Dash: {e}")
cleanup_resources()
sys.exit(1)
AND THIS IS MY ARDUINO CODE
#include <DHT.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <MFRC522.h>
#include <SoftwareSerial.h>
#include <TinyGPS++.h>
// Configuration OLED
#define i2c_Address 0x3c
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SH1106G display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Définition des broches
#define DHTPIN 2 // Broche du capteur DHT22
#define DHTTYPE DHT22 // Type de capteur DHT
#define PIR_PIN 8 // Broche du capteur PIR (HC-SR501)
#define FLAME_SENSOR A0 // Broche du capteur de flamme
#define GAS_SENSOR A1 // Broche du capteur de gaz
#define SPEAKER_PIN 7 // Broche du buzzer
#define VEN_PIN 6 // Broche de la ventilation
// Configuration RFID
#define RFID_SS_PIN 53 // Broche SS (Slave Select) pour Arduino Mega
#define RFID_RST_PIN 9 // Broche RST (Reset)
MFRC522 rfid(RFID_SS_PIN, RFID_RST_PIN);
// Configuration GPS
#define GPS_RX 3 // Connecté au TX du GPS
#define GPS_TX 4 // Connecté au RX du GPS
SoftwareSerial gpsSerial(GPS_RX, GPS_TX);
TinyGPSPlus gps;
// Constantes pour le calcul des gaz
#define RL 1000.0 // Résistance de charge en ohms
#define VCC 5.0 // Tension d'alimentation
#define RO 10.0 // Résistance de référence en ohms
#define M_CH4 -0.38
#define B_CH4 1.5
#define M_LPG -0.47
#define B_LPG 1.7
#define M_H2 -0.42
#define B_H2 1.6
#define M_CO -0.35
#define B_CO 1.3
// Seuils des gaz réduits à 10 ppm
#define SEUIL_CH4 5 // Seuil pour le méthane
#define SEUIL_LPG 5 // Seuil pour le GPL
#define SEUIL_H2 5 // Seuil pour l'hydrogène
#define SEUIL_CO 5 // Seuil pour le monoxyde de carbone
// Variables globales
float humidity, temperature;
int valeurGaz, valeurFlamme;
float tensionGaz;
float Rs;
float ppm_CH4, ppm_LPG, ppm_H2, ppm_CO;
bool mouvementDetecte = false;
bool flammeDetectee = false;
bool alarmeGaz = false;
bool climatAlarme = false;
String rfidStatus = "En attente"; // Statut RFID
String lastUID = ""; // Dernier UID lu
// Variables GPS
bool gpsActif = false;
String gpsTime = "N/A";
String gpsDate = "N/A";
String gpsLocation = "N/A";
String gpsSpeed = "N/A";
String gpsSatellites = "N/A";
// Tons pour le buzzer
int tonesStart[] = {262};
int tonesAlarm[] = {440, 494};
int tonesAccessGranted[] = {523, 659}; // Do, Mi
int tonesAccessDenied[] = {349, 294}; // Fa, Ré
// Initialisation du capteur DHT
DHT dht(DHTPIN, DHTTYPE);
void setup() {
// Initialisation série
Serial.begin(9600);
Serial.println("Initialisation du système Smart House...");
// Configuration des broches
pinMode(PIR_PIN, INPUT);
pinMode(VEN_PIN, OUTPUT);
pinMode(FLAME_SENSOR, INPUT);
pinMode(SPEAKER_PIN, OUTPUT);
digitalWrite(VEN_PIN, LOW);
// Initialisation OLED
if(!display.begin(i2c_Address, true)) {
Serial.println("Échec de l'initialisation de l'OLED");
while(1);
}
display.display();
delay(2000);
display.clearDisplay();
// Initialisation DHT
dht.begin();
Serial.println("Capteurs initialisés avec succès");
// Initialisation RFID
SPI.begin();
rfid.PCD_Init();
Serial.println("RFID initialisé");
// Initialisation GPS
gpsSerial.begin(9600);
Serial.println("GPS initialisé");
// Séquence de démarrage
for (int i = 0; i < 1; i++) {
tone(SPEAKER_PIN, tonesStart[i]);
delay(200);
}
noTone(SPEAKER_PIN);
// Affichage écran de démarrage
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.setCursor(0, 0);
display.print("Smart House");
display.setCursor(20, 20);
display.print("2025");
display.setCursor(0, 40);
display.print("RFID & GPS Ready");
display.display();
delay(1000);
Serial.println("Système prêt");
Serial.println("------------------------");
}
void loop() {
// Lecture des capteurs
lireGaz();
lireTemperatureHumidite();
detecterMouvement();
detecterFlamme();
lireRFID();
lireGPS();
// Gestion des alarmes et actions
gererAlarmes();
// Affichage OLED
afficherDonnees();
// Affichage Serial Monitor
afficherSerialMonitor();
delay(500); // Pause entre les lectures
}
void lireTemperatureHumidite() {
humidity = dht.readHumidity();
temperature = dht.readTemperature();
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Erreur de lecture du capteur DHT !");
}
}
void detecterMouvement() {
mouvementDetecte = digitalRead(PIR_PIN) == HIGH;
}
void lireGaz() {
valeurGaz = analogRead(GAS_SENSOR);
tensionGaz = valeurGaz * (VCC / 1023.0);
Rs = ((VCC - tensionGaz) * RL) / tensionGaz;
ppm_CH4 = pow(10, (M_CH4 * log10(Rs / RO) + B_CH4));
ppm_LPG = pow(10, (M_LPG * log10(Rs / RO) + B_LPG));
ppm_H2 = pow(10, (M_H2 * log10(Rs / RO) + B_H2));
ppm_CO = pow(10, (M_CO * log10(Rs / RO) + B_CO));
alarmeGaz = (ppm_CH4 > SEUIL_CH4) ||
(ppm_LPG > SEUIL_LPG) ||
(ppm_H2 > SEUIL_H2) ||
(ppm_CO > SEUIL_CO);
}
void detecterFlamme() {
valeurFlamme = analogRead(FLAME_SENSOR);
flammeDetectee = (valeurFlamme < 200);
}
void lireRFID() {
if (!rfid.PICC_IsNewCardPresent()) return;
if (!rfid.PICC_ReadCardSerial()) return;
String uid = "";
for (byte i = 0; i < rfid.uid.size; i++) {
uid += String(rfid.uid.uidByte[i] < 0x10 ? "0" : "");
uid += String(rfid.uid.uidByte[i], HEX);
}
uid.toUpperCase();
lastUID = uid;
String uidsAutorises[] = {"4AEDF803", "B442CA01"};
bool accesAutorise = false;
for (int i = 0; i < 2; i++) {
if (uid.equalsIgnoreCase(uidsAutorises[i])) {
accesAutorise = true;
break;
}
}
if (accesAutorise) {
rfidStatus = "Acces OK";
jouerTons(tonesAccessGranted, 2);
} else {
rfidStatus = "Acces Refuse";
jouerTons(tonesAccessDenied, 2);
}
Serial.print("RFID UID: ");
Serial.print(uid);
Serial.print(" - ");
Serial.println(rfidStatus);
rfid.PICC_HaltA();
}
void lireGPS() {
while (gpsSerial.available() > 0) {
if (gps.encode(gpsSerial.read())) {
updateGPSData();
}
}
if (millis() > 5000 && gps.charsProcessed() < 10) {
gpsActif = false;
gpsTime = "N/A";
gpsDate = "N/A";
gpsLocation = "N/A";
gpsSpeed = "N/A";
gpsSatellites = "N/A";
}
}
void updateGPSData() {
gpsActif = true;
if (gps.time.isValid()) {
byte hour = (gps.time.hour() + 2) % 24;
gpsTime = String(hour < 10 ? "0" : "") + String(hour) + ":" +
String(gps.time.minute() < 10 ? "0" : "") + String(gps.time.minute()) + ":" +
String(gps.time.second() < 10 ? "0" : "") + String(gps.time.second()) + " (UTC+2)";
} else {
gpsTime = "N/A";
}
if (gps.date.isValid()) {
gpsDate = String(gps.date.day() < 10 ? "0" : "") + String(gps.date.day()) + "/" +
String(gps.date.month() < 10 ? "0" : "") + String(gps.date.month()) + "/" +
String(gps.date.year());
} else {
gpsDate = "N/A";
}
if (gps.location.isValid()) {
gpsLocation = String(gps.location.lat(), 6) + ", " + String(gps.location.lng(), 6);
} else {
gpsLocation = "N/A";
}
if (gps.speed.isValid()) {
gpsSpeed = String(gps.speed.kmph(), 1) + " km/h";
} else {
gpsSpeed = "N/A";
}
if (gps.satellites.isValid()) {
gpsSatellites = String(gps.satellites.value()) + " sats";
} else {
gpsSatellites = "N/A";
}
}
void jouerTons(int tones[], int length) {
for (int i = 0; i < length; i++) {
tone(SPEAKER_PIN, tones[i]);
delay(300);
}
noTone(SPEAKER_PIN);
}
void gererAlarmes() {
climatAlarme = (humidity > 70) || (temperature > 30);
if (alarmeGaz || flammeDetectee || climatAlarme) {
digitalWrite(VEN_PIN, HIGH);
if (alarmeGaz || flammeDetectee) {
jouerAlarme();
}
} else {
digitalWrite(VEN_PIN, LOW);
}
}
void jouerAlarme() {
for (int i = 0; i < 2; i++) {
tone(SPEAKER_PIN, tonesAlarm[i]);
delay(200);
}
noTone(SPEAKER_PIN);
}
void afficherDonnees() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.setCursor(0, 0);
display.print("Temp: ");
display.print(temperature, 1);
display.print("C");
if (temperature > 30) display.print("!");
display.setCursor(0, 12);
display.print("Hum: ");
display.print(humidity, 1);
display.print("%");
if (humidity > 70) display.print("!");
display.setCursor(0, 24);
display.print("Mouv: ");
display.print(mouvementDetecte ? "OUI" : "NON");
display.setCursor(0, 36);
display.print("Gaz: ");
float max_ppm = max(max(ppm_CH4, ppm_LPG), max(ppm_H2, ppm_CO));
display.print(max_ppm, 1);
display.print(" ppm");
if (alarmeGaz) display.print("!");
display.setCursor(0, 48);
if (gpsActif) {
display.print("GPS: ");
display.print(gpsSpeed);
} else {
display.print("GPS: No Signal");
}
display.setCursor(0, 60);
display.print("RFID:");
display.print(rfidStatus);
display.display();
}
void afficherSerialMonitor() {
Serial.println("----- Données des capteurs -----");
Serial.print("Température: ");
Serial.print(temperature);
Serial.print(" °C - ");
if (temperature > 30) Serial.println("Trop élevée!");
else Serial.println("Normale");
Serial.print("Humidité: ");
Serial.print(humidity);
Serial.print(" % - ");
if (humidity > 70) Serial.println("Trop élevée!");
else Serial.println("Normale");
dashboard python.txt
Serial.print("Mouvement: ");
Serial.println(mouvementDetecte ? "Détecté" : "Non détecté");
Serial.println("Concentrations de gaz:");
Serial.print(" CH4 (Méthane): ");
Serial.print(ppm_CH4, 2);
Serial.print(" ppm (Seuil: 10) - ");
if (ppm_CH4 > 10) Serial.println("DANGER!");
else Serial.println("Normale");
Serial.print(" LPG (GPL): ");
Serial.print(ppm_LPG, 2);
Serial.print(" ppm (Seuil: 10) - ");
if (ppm_LPG > 10) Serial.println("DANGER!");
else Serial.println("Normale");
Serial.print(" H2 (Hydrogène): ");
Serial.print(ppm_H2, 2);
Serial.print(" ppm (Seuil: 10) - ");
if (ppm_H2 > 10) Serial.println("DANGER!");
else Serial.println("Normale");
Serial.print(" CO (Monoxyde): ");
Serial.print(ppm_CO, 2);
Serial.print(" ppm (Seuil: 10) - ");
if (ppm_CO > 10) Serial.println("DANGER!");
else Serial.println("Normale");
Serial.print("Flamme: ");
Serial.print(valeurFlamme);
Serial.print(" - ");
Serial.println(flammeDetectee ? "ALARME FLAMME!" : "Non détectée");
Serial.print("Ventilation: ");
Serial.println(digitalRead(VEN_PIN) ? "ACTIVE" : "INACTIVE");
Serial.print("Condition climatique: ");
Serial.println(climatAlarme ? "Ventilation nécessaire (T>30°C ou H>70%)" : "Normale");
Serial.print("RFID: ");
Serial.print(lastUID);
Serial.print(" - ");
Serial.println(rfidStatus);
Serial.println("\n----- Données GPS -----");
Serial.print("Heure: ");
Serial.println(gpsTime);
Serial.print("Date: ");
Serial.println(gpsDate);
Serial.print("Position: ");
Serial.println(gpsLocation);
Serial.print("Vitesse: ");
Serial.println(gpsSpeed);
Serial.print("Satellites: ");
Serial.println(gpsSatellites);
Serial.print("Statut GPS: ");
Serial.println(gpsActif ? "Actif" : "Inactif");
if (alarmeGaz || flammeDetectee) {
Serial.println("!!! ALARME ACTIVE !!!");
}
Serial.println("-------------------------------");
Serial.println();
}
💻 Environment
Operating System: Windows (please specify the version if needed)
Programming Language: Python (or specify)
Library Used: (e.g., pyserial, etc.)
Hardware: (e.g., Arduino, ESP32, etc.)
🧪 Steps Taken So Far
Closed all other software that may use the serial port (e.g., Arduino IDE, PuTTY)
Restarted the machine
Tried running the script as Administrator
Checked Device Manager for port conflicts
❓ What I Need Help With
I would appreciate any advice on how to:
Diagnose if another process is locking the COM13 port
Properly access the port from my program
Bypass or fix the "Access is denied" issue
Thank you in advance!
The text was updated successfully, but these errors were encountered: