File size: 4,656 Bytes
f823761
 
5095fe6
f823761
 
 
 
 
 
9155fa7
f823761
 
 
 
9155fa7
f823761
 
 
 
9155fa7
f823761
 
 
 
9155fa7
f823761
 
9156c8e
 
f823761
 
 
 
 
 
9155fa7
 
 
 
f823761
 
 
 
 
9155fa7
 
 
 
 
f823761
 
 
 
 
 
 
 
 
 
9155fa7
f823761
 
09497f1
f823761
09497f1
f823761
 
 
 
 
09497f1
f823761
9156c8e
 
f823761
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9155fa7
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
135
136
137
138
139
140
import random
import pandas as pd
import streamlit as st
import pydeck as pdk

# ---- Area-Specific Configuration ----
AREA_DETAILS = {
    "Hyderabad": {
        "coords": [17.4036, 78.5247],
        "area_name": "Ramanthapur",
        "purpose": "Dairy Farm"
    },
    "Ballari": {
        "coords": [15.1468, 76.9237],
        "area_name": "Cowl Bazar",
        "purpose": "Power Station"
    },
    "Gadwal": {
        "coords": [16.2315, 77.7965],
        "area_name": "Bheem Nagar",
        "purpose": "Solar Station"
    },
    "Kurnool": {
        "coords": [15.8281, 78.0373],
        "area_name": "Venkata Ramana",
        "purpose": "Agriculture Monitoring"
    }
}

POLES_PER_SITE = 12

# ---- Generate Poles with Anomalies ----
def generate_open_area_poles(site_name, center_lat, center_lon, area, purpose):
    poles = []
    spacing = 0.0006
    anomalies_options = ['Sensor Fault', 'Overheat', 'Power Surge']
    anomaly_weights = [0.5, 0.3, 0.2]
    anomaly_options_with_none = ['None'] + anomalies_options
    anomaly_weights_with_none = [0.6] + [0.4 * w for w in anomaly_weights]

    for i in range(POLES_PER_SITE):
        lat = center_lat + random.uniform(-0.0002, 0.0002)
        lon = center_lon + (i - POLES_PER_SITE // 2) * spacing
        alert_level = random.choices(['Green', 'Yellow', 'Red'], weights=[6, 4, 2])[0]

        if alert_level == 'Red':
            anomaly = random.choices(anomalies_options, weights=anomaly_weights)[0]
        else:
            anomaly = random.choices(anomaly_options_with_none, weights=anomaly_weights_with_none)[0]

        poles.append({
            "Pole ID": f"{site_name[:3].upper()}-{i+1:03}",
            "Site": site_name,
            "Latitude": lat,
            "Longitude": lon,
            "Alert Level": alert_level,
            "Health Score": round(random.uniform(70, 100), 2),
            "Power Status": random.choice(['Sufficient', 'Insufficient']),
            "Camera Status": random.choice(['Online', 'Offline']),
            "Location Area": area,  # Only location name, no purpose here
            "Purpose": purpose,
            "Anomalies": anomaly
        })
    return poles

# ---- Prepare Full DataFrame ----
all_poles = []
for site, details in AREA_DETAILS.items():
    poles = generate_open_area_poles(site, *details['coords'], details['area_name'], details['purpose'])
    all_poles.extend(poles)

df = pd.DataFrame(all_poles)

# ---- Streamlit UI ----
st.set_page_config(page_title="Smart Pole Visual Dashboard", layout="wide")
st.title("🌐 Smart Renewable Pole Monitoring Dashboard")

site = st.selectbox("πŸ“ Select a site location:", list(AREA_DETAILS.keys()))
selected = AREA_DETAILS[site]

# ---- Filtered View ----
filtered_df = df[df["Site"] == site]

# ---- Display Site Description ----
st.markdown(f"### πŸ“Œ Location: **{selected['area_name']}**")
st.markdown(f"πŸ”§ **Poles Purpose**: {selected['purpose']}")

# ---- KPI Metrics ----
col1, col2, col3 = st.columns(3)
col1.metric("Total Poles", POLES_PER_SITE)
col2.metric("πŸ”΄ Red Alerts", filtered_df[filtered_df["Alert Level"] == "Red"].shape[0])
col3.metric("πŸ“· Offline Cameras", filtered_df[filtered_df["Camera Status"] == "Offline"].shape[0])

# ---- Alert Level to Color ----
def alert_color(alert):
    return {
        "Green": [0, 255, 0, 160],
        "Yellow": [255, 255, 0, 160],
        "Red": [255, 0, 0, 160]
    }[alert]

filtered_df = filtered_df.copy()
filtered_df["Color"] = filtered_df["Alert Level"].apply(alert_color)

# ---- Map Visualization ----
st.subheader("πŸ—ΊοΈ Pole Location & Health Status")
st.pydeck_chart(pdk.Deck(
    initial_view_state=pdk.ViewState(
        latitude=selected['coords'][0],
        longitude=selected['coords'][1],
        zoom=16.5,
        pitch=45
    ),
    layers=[
        pdk.Layer(
            "ScatterplotLayer",
            data=filtered_df,
            get_position='[Longitude, Latitude]',
            get_color='Color',
            get_radius=30,
            pickable=True
        )
    ],
    tooltip={
        "html": "<b>Pole ID:</b> {Pole ID}<br/>"
                "<b>Location:</b> {Location Area}<br/>"
                "<b>Purpose:</b> {Purpose}<br/>"
                "<b>Health Score:</b> {Health Score}<br/>"
                "<b>Alert Level:</b> {Alert Level}<br/>"
                "<b>Camera:</b> {Camera Status}<br/>"
                "<b>Power:</b> {Power Status}<br/>"
                "<b>Anomaly:</b> {Anomalies}",
        "style": {"color": "white", "backgroundColor": "black"}
    }
))

# ---- Data Table ----
st.subheader("πŸ“‹ Detailed Pole Information")
st.dataframe(filtered_df, use_container_width=True)