grid_demo / app.py
OlamideKayode's picture
Upload app.py
7aa7428 verified
raw
history blame
4.3 kB
import os
import time
import pandas as pd
import numpy as np
import joblib
import requests
import streamlit as st
from streamlit_autorefresh import st_autorefresh
# Auto-refresh every 5 seconds
st_autorefresh(interval=5000, key="refresh")
# Load model
@st.cache_resource
def load_model():
return joblib.load("rf_model.pkl")
model = load_model()
# Supabase config
SUPABASE_URL = os.environ["SUPABASE_URL"]
SUPABASE_KEY = os.environ["SUPABASE_KEY"]
TABLE = "smart_meter_readings_1year"
# Initialize session state
if "row_index" not in st.session_state:
st.session_state.row_index = 0
if "history" not in st.session_state:
st.session_state.history = pd.DataFrame()
# Fetch all data
@st.cache_data
def fetch_all_data():
url = f"{SUPABASE_URL}/rest/v1/{TABLE}?select=*&order=timestamp.asc"
headers = {
"apikey": SUPABASE_KEY,
"Authorization": f"Bearer {SUPABASE_KEY}"
}
r = requests.get(url, headers=headers)
if r.ok:
return pd.DataFrame(r.json())
else:
st.error(f"โŒ Error fetching data: {r.status_code}")
return pd.DataFrame()
df_all = fetch_all_data()
# Debug sidebar
st.sidebar.title("๐Ÿ›  Debug Info")
st.sidebar.write("Row index:", st.session_state.row_index)
st.sidebar.write("Total rows:", len(df_all))
if not df_all.empty and st.session_state.row_index < len(df_all):
st.sidebar.write("Next row:", df_all.iloc[st.session_state.row_index].to_dict())
# Get next row
def get_next_row():
if st.session_state.row_index < len(df_all):
row = df_all.iloc[[st.session_state.row_index]]
st.session_state.row_index += 1
return row
return pd.DataFrame()
# Feature engineering
def engineer(df):
# Handle timestamp
if pd.api.types.is_numeric_dtype(df["timestamp"]):
df["datetime"] = pd.to_datetime(df["timestamp"], unit="s")
else:
df["datetime"] = pd.to_datetime(df["timestamp"])
df["hour_of_day"] = df["datetime"].dt.hour
df["lag_30min"] = df["power_consumption_kwh"].shift(1)
df["lag_1h"] = df["power_consumption_kwh"].shift(2)
df["rolling_avg_1h"] = df["power_consumption_kwh"].rolling(2).mean()
df["rolling_avg_2h"] = df["power_consumption_kwh"].rolling(4).mean()
df["is_weekend"] = df["datetime"].dt.weekday >= 5
df["hour_sin"] = np.sin(2 * np.pi * df["hour_of_day"] / 24)
df["hour_cos"] = np.cos(2 * np.pi * df["hour_of_day"] / 24)
# One-hot encode property_type and region
df = pd.get_dummies(df, columns=["property_type", "region"], drop_first=False)
# Ensure all expected features exist
expected_features = [
'lag_30min', 'lag_1h',
'rolling_avg_1h', 'rolling_avg_2h',
'hour_of_day', 'is_weekend',
'hour_sin', 'hour_cos',
'temperature_c', 'ev_owner', 'solar_installed',
'property_type_commercial', 'property_type_residential',
'region_north', 'region_south', 'region_east', 'region_west'
]
for col in expected_features:
if col not in df.columns:
df[col] = 0
return df
# UI layout
st.title("โšก Gridflux: Live Smart-Meter Forecast")
placeholder_chart = st.empty()
placeholder_metric = st.empty()
new_row = get_next_row()
if not new_row.empty:
st.session_state.history = pd.concat([st.session_state.history, new_row], ignore_index=True)
df_feat = engineer(st.session_state.history).dropna()
if not df_feat.empty:
latest_input = df_feat.iloc[[-1]][[
'lag_30min', 'lag_1h',
'rolling_avg_1h', 'rolling_avg_2h',
'hour_of_day', 'is_weekend',
'hour_sin', 'hour_cos',
'temperature_c', 'ev_owner', 'solar_installed',
'property_type_commercial', 'property_type_residential',
'region_north', 'region_south', 'region_east', 'region_west'
]]
prediction = model.predict(latest_input)[0]
# Show outputs
chart_df = st.session_state.history.copy()
chart_df["datetime"] = pd.to_datetime(chart_df["timestamp"])
chart_df.set_index("datetime", inplace=True)
placeholder_chart.line_chart(chart_df["power_consumption_kwh"])
placeholder_metric.metric("๐Ÿ”ฎ Predicted Power Usage (kWh)", f"{prediction:.3f}")
else:
st.success("โœ… All data processed.")