File size: 3,493 Bytes
0d4f97b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | from flask import Flask, jsonify, render_template
import joblib, pandas as pd, numpy as np
from datetime import datetime
import psycopg2
from psycopg2 import pool
app = Flask(_name_)
# ---------- Load model bundle ----------
bundle = joblib.load('gas_danger_model.pkl')
model = bundle['model']
FEATURES = bundle['features'] # ['Hour', 'Weekday', 'Month', 'Afternoon']
# ---------- PostgreSQL connection pool ----------
PG_POOL = pool.SimpleConnectionPool(
1, 5,
user="postgres.czytuqnowdogaowfnfhe",
password="235711",
host="aws-0-eu-central-1.pooler.supabase.com",
port="5432",
dbname="postgres"
)
# ---------- Per‑gas safety limits ----------
SAFETY_THRESHOLDS = {
'alcohol': 1000, 'NH3': 25, 'CO': 35, 'CO2': 5000,
'Toluene': 100, 'acetone': 750, 'lpg': 1000, 'smoke': 1.0
}
# ---------- Helper to fetch latest row ----------
def fetch_latest_reading():
"""
Returns a dict with keys exactly matching the ones used elsewhere:
CO2, NH3, alcohol, Toluene, acetone, lpg, CO, smoke, timestamp
"""
sql = """
SELECT co2,
nh3,
alcohol,
toluene,
acetone,
lpg,
co,
smoke,
"timestamp"
FROM gas_data
ORDER BY "timestamp" DESC
LIMIT 1;
"""
conn = PG_POOL.getconn()
try:
with conn.cursor() as cur:
cur.execute(sql)
row = cur.fetchone()
if row is None:
return None
raw_keys = ['co2','nh3','alcohol','toluene','acetone',
'lpg','co','smoke','timestamp']
raw = dict(zip(raw_keys, row))
# Map to mixed‑case keys expected elsewhere
return {
'CO2': raw['co2'],
'NH3': raw['nh3'],
'alcohol': raw['alcohol'],
'Toluene': raw['toluene'],
'acetone': raw['acetone'],
'lpg': raw['lpg'],
'CO': raw['co'],
'smoke': raw['smoke'],
'timestamp':raw['timestamp']
}
finally:
PG_POOL.putconn(conn)
# ---------- Routes ----------
@app.route('/api/predict', methods=['GET'])
def predict():
current = fetch_latest_reading()
if current is None:
return jsonify({'error': 'No rows in gas_data table'}), 404
ts = current['timestamp']
now = ts if ts else datetime.now()
# Add time‑based features
current.update({
'Hour': now.hour,
'Weekday': now.weekday(),
'Month': now.month,
'Afternoon': int(12 <= now.hour <= 15)
})
# Build feature vector in training order
X = pd.DataFrame([[current.get(f, np.nan) for f in FEATURES]], columns=FEATURES)
prob = float(model.predict_proba(X)[0, 1])
# Per‑gas alert block
alerts = {
g: {
'value': current[g],
'threshold': thr,
'status': 'danger' if current[g] > thr else 'safe'
} for g, thr in SAFETY_THRESHOLDS.items()
}
return jsonify({
'prediction': prob,
'alerts': alerts,
'overall_status': 'danger' if prob > 0.4 else 'safe',
'timestamp': now.isoformat()
})
@app.route('/')
def dashboard():
return render_template('dashboard.html') # supply your own template
if _name_ == '_main_':
app.run(debug=True, port=5000)
|