File size: 4,297 Bytes
8f319a2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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.")