import streamlit as st import pandas as pd import plotly.express as px import plotly.graph_objects as go from salesforce_integration import fetch_poles # Title st.title("📡 VIEP Smart Poles Dashboard") # Fetch data df = fetch_poles() # Sidebar Filters st.sidebar.header("📁 Filter Data") # Dynamic values from Salesforce data alert_levels = df["Alert_Level__c"].dropna().unique().tolist() sites = df["Site__c"].dropna().unique().tolist() camera_statuses = df["Camera_Status__c"].dropna().unique().tolist() selected_alert_levels = st.sidebar.multiselect("Alert Level", alert_levels, default=alert_levels) selected_camera_status = st.sidebar.selectbox("Camera Status", ["All"] + camera_statuses) # Initial filtering by alert level and camera status filtered_df = df[ (df["Alert_Level__c"].isin(selected_alert_levels)) ] if selected_camera_status != "All": filtered_df = filtered_df[filtered_df["Camera_Status__c"] == selected_camera_status] # Site filter logic (place here) site_options = ["All"] + df["Site__c"].dropna().unique().tolist() selected_site = st.sidebar.selectbox("Site", site_options, index=0) if selected_site != "All": filtered_df = filtered_df[filtered_df["Site__c"] == selected_site] # Site filter logic (place here) if selected_site != "All": filtered_df = filtered_df[filtered_df["Site__c"] == selected_site] # --- System Summary --- st.subheader("📊 System Summary") col1, col2, col3 = st.columns(3) col1.metric("Total Poles", len(filtered_df)) col2.metric("Red Alerts", len(filtered_df[filtered_df["Alert_Level__c"] == "Red"])) col3.metric("Offline Cameras", len(filtered_df[filtered_df["Camera_Status__c"] == "Offline"])) # --- Pole Table --- st.subheader("📋 Pole Table") st.dataframe(filtered_df, use_container_width=True) # --- Energy Generation Chart --- st.subheader("⚙ Energy Generation (Solar vs Wind)") if not filtered_df.empty: energy_chart = px.bar( filtered_df, x="Name", y=["Solar_Generation__c", "Wind_Generation__c"], barmode="group", title="Solar vs Wind Energy Generation" ) st.plotly_chart(energy_chart, use_container_width=True) else: st.info("No data available for the selected filters.") # --- Alert Level Breakdown --- st.subheader("🚨 Alert Level Breakdown") if not filtered_df.empty: alert_counts = filtered_df["Alert_Level__c"].value_counts().reset_index() alert_counts.columns = ["Alert Level", "Count"] alert_pie = px.pie(alert_counts, values="Count", names="Alert Level", title="Alert Distribution") st.plotly_chart(alert_pie, use_container_width=True) else: st.info("No alerts to display.") # 5. Tilt vs Vibration Chart st.subheader("📉 Tilt vs Vibration") # Extract Tilt and Vibration from RFID_Tag__c filtered_df["Tilt"] = filtered_df["RFID_Tag__c"].str.extract(r'Tilt:(\d+\.?\d*)').astype(float) filtered_df["Vibration"] = filtered_df["RFID_Tag__c"].str.extract(r'Vib:(\d+\.?\d*)').astype(float) # Drop rows with no tilt or vibration data tilt_vib_df = filtered_df.dropna(subset=["Tilt", "Vibration"]) if not tilt_vib_df.empty: fig_tilt_vib = go.Figure() fig_tilt_vib.add_trace(go.Scatter( x=tilt_vib_df["Name"], y=tilt_vib_df["Tilt"], mode='lines+markers', name='Tilt' )) fig_tilt_vib.add_trace(go.Scatter( x=tilt_vib_df["Name"], y=tilt_vib_df["Vibration"], mode='lines+markers', name='Vibration' )) fig_tilt_vib.update_layout(title="Tilt vs Vibration by Pole", xaxis_title="Pole Name", yaxis_title="Value") st.plotly_chart(fig_tilt_vib, use_container_width=True) else: st.info("No Tilt or Vibration data available.")