Tigernawin commited on
Commit
843aaf6
Β·
verified Β·
1 Parent(s): 82336a9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +8 -22
app.py CHANGED
@@ -6,16 +6,19 @@ from datetime import datetime, timedelta
6
  import altair as alt
7
  import time
8
 
9
- # ---- Auto-refresh trigger every 1 hour ----
10
- st.experimental_set_query_params(updated=int(time.time() // 3600))
 
 
 
11
 
12
  # ---- Constants ----
13
  POLES_PER_SITE = 12
14
  POLE_GRID_ROWS = 3
15
  POLE_GRID_COLS = 4
16
  POLE_SPACING_FEET = 10
17
- FEET_TO_LAT_DEG = 0.00003 # Approximate conversion
18
- FEET_TO_LON_DEG = 0.00003 # Can be tuned per site longitude
19
 
20
  SITES = {
21
  "Hyderabad": {"coords": [17.385044, 78.486671], "zone": "Dairy Farm Zone"},
@@ -24,7 +27,6 @@ SITES = {
24
  "Ballari": {"coords": [12.9716, 77.5946], "zone": "Urban Grid"}
25
  }
26
 
27
- # ---- Fixed Pole Grid Placement ----
28
  def generate_fixed_pole_locations(base_lat, base_lon, num_poles):
29
  locations = []
30
  for i in range(POLE_GRID_ROWS):
@@ -34,26 +36,21 @@ def generate_fixed_pole_locations(base_lat, base_lon, num_poles):
34
  locations.append([lat, lon])
35
  return locations[:num_poles]
36
 
37
- # ---- Simulate a Single Pole ----
38
  def simulate_pole(pole_id, site_name, lat, lon):
39
  solar_kwh = round(random.uniform(3.0, 7.5), 2)
40
  wind_kwh = round(random.uniform(0.5, 2.0), 2)
41
  power_required = round(random.uniform(4.0, 8.0), 2)
42
  total_power = solar_kwh + wind_kwh
43
  power_status = 'Sufficient' if total_power >= power_required else 'Insufficient'
44
-
45
  vibration = round(random.uniform(0, 5), 2)
46
  camera_status = random.choice(['Online', 'Offline'])
47
-
48
  alert_level = 'Green'
49
  if vibration > 3:
50
  alert_level = 'Yellow'
51
  if vibration > 4.5:
52
  alert_level = 'Red'
53
-
54
  health_score = max(0, 100 - (vibration * 10))
55
  timestamp = datetime.now() - timedelta(minutes=random.randint(0, 59))
56
-
57
  return {
58
  'Pole ID': f'{site_name[:3].upper()}-{pole_id:03}',
59
  'Site': site_name,
@@ -72,21 +69,18 @@ def simulate_pole(pole_id, site_name, lat, lon):
72
  'Last Checked': timestamp.strftime('%Y-%m-%d %H:%M:%S')
73
  }
74
 
75
- # ---- Cache Data for 1 Hour ----
76
  @st.cache_data(ttl=3600)
77
  def get_simulated_data():
78
  all_data = []
79
  for site_name, site_data in SITES.items():
80
  base_lat, base_lon = site_data["coords"]
81
  locations = generate_fixed_pole_locations(base_lat, base_lon, POLES_PER_SITE)
82
-
83
  for i, (lat, lon) in enumerate(locations):
84
  pole_data = simulate_pole(i + 1, site_name, lat, lon)
85
  all_data.append(pole_data)
86
  return pd.DataFrame(all_data)
87
 
88
- # ---- Streamlit UI ----
89
- st.set_page_config(page_title="Smart Pole Monitoring", layout="wide")
90
  st.title("🌍 Smart Renewable Pole Monitoring - Multi-Site")
91
 
92
  selected_site = st.selectbox("Select a site to view:", options=list(SITES.keys()), index=0)
@@ -97,13 +91,11 @@ with st.spinner(f"Loading data for {selected_site}..."):
97
  df = get_simulated_data()
98
  site_df = df[df['Site'] == selected_site]
99
 
100
- # ---- Summary Metrics ----
101
  col1, col2, col3 = st.columns(3)
102
  col1.metric("Total Poles", site_df.shape[0])
103
  col2.metric("Red Alerts", site_df[site_df['Alert Level'] == 'Red'].shape[0])
104
  col3.metric("Power Insufficiencies", site_df[site_df['Power Status'] == 'Insufficient'].shape[0])
105
 
106
- # ---- Table & Filters ----
107
  st.subheader(f"πŸ“‹ Pole Data Table for {selected_site}")
108
  with st.expander("Filter Options"):
109
  alert_filter = st.multiselect("Alert Level", options=site_df['Alert Level'].unique(), default=site_df['Alert Level'].unique())
@@ -115,7 +107,6 @@ filtered_df = site_df[
115
  ]
116
  st.dataframe(filtered_df, use_container_width=True)
117
 
118
- # ---- Energy Chart ----
119
  st.subheader("πŸ”‹ Energy Generation per Pole")
120
 
121
  energy_long_df = site_df[['Pole ID', 'Solar (kWh)', 'Wind (kWh)']].melt(
@@ -137,9 +128,7 @@ bar_chart = alt.Chart(energy_long_df).mark_bar().encode(
137
 
138
  st.altair_chart(bar_chart, use_container_width=True)
139
 
140
- # ---- Fault Filter ----
141
  st.subheader("⚠️ Map Filter: Select Fault Type(s)")
142
-
143
  fault_options = ['High Vibration (>3g)', 'Camera Offline', 'Power Insufficient']
144
  selected_faults = st.multiselect("Show poles with these fault conditions:", options=fault_options, default=fault_options)
145
 
@@ -152,7 +141,6 @@ def fault_condition(row):
152
 
153
  fault_df = site_df[site_df.apply(fault_condition, axis=1)] if selected_faults else site_df
154
 
155
- # ---- Color Mapping ----
156
  def get_color(alert):
157
  if alert == 'Green':
158
  return [0, 255, 0, 160]
@@ -164,7 +152,6 @@ def get_color(alert):
164
 
165
  fault_df['color'] = fault_df['Alert Level'].apply(get_color)
166
 
167
- # ---- Map Visualization ----
168
  st.subheader("πŸ“ Pole Locations with Selected Faults")
169
  st.pydeck_chart(pdk.Deck(
170
  initial_view_state=pdk.ViewState(
@@ -203,4 +190,3 @@ st.pydeck_chart(pdk.Deck(
203
  }
204
  }
205
  ))
206
-
 
6
  import altair as alt
7
  import time
8
 
9
+ # ---- SET PAGE CONFIG MUST BE FIRST ----
10
+ st.set_page_config(page_title="Smart Pole Monitoring", layout="wide")
11
+
12
+ # ---- Update query params every hour to trigger refresh
13
+ st.query_params["updated"] = str(int(time.time() // 3600))
14
 
15
  # ---- Constants ----
16
  POLES_PER_SITE = 12
17
  POLE_GRID_ROWS = 3
18
  POLE_GRID_COLS = 4
19
  POLE_SPACING_FEET = 10
20
+ FEET_TO_LAT_DEG = 0.00003
21
+ FEET_TO_LON_DEG = 0.00003
22
 
23
  SITES = {
24
  "Hyderabad": {"coords": [17.385044, 78.486671], "zone": "Dairy Farm Zone"},
 
27
  "Ballari": {"coords": [12.9716, 77.5946], "zone": "Urban Grid"}
28
  }
29
 
 
30
  def generate_fixed_pole_locations(base_lat, base_lon, num_poles):
31
  locations = []
32
  for i in range(POLE_GRID_ROWS):
 
36
  locations.append([lat, lon])
37
  return locations[:num_poles]
38
 
 
39
  def simulate_pole(pole_id, site_name, lat, lon):
40
  solar_kwh = round(random.uniform(3.0, 7.5), 2)
41
  wind_kwh = round(random.uniform(0.5, 2.0), 2)
42
  power_required = round(random.uniform(4.0, 8.0), 2)
43
  total_power = solar_kwh + wind_kwh
44
  power_status = 'Sufficient' if total_power >= power_required else 'Insufficient'
 
45
  vibration = round(random.uniform(0, 5), 2)
46
  camera_status = random.choice(['Online', 'Offline'])
 
47
  alert_level = 'Green'
48
  if vibration > 3:
49
  alert_level = 'Yellow'
50
  if vibration > 4.5:
51
  alert_level = 'Red'
 
52
  health_score = max(0, 100 - (vibration * 10))
53
  timestamp = datetime.now() - timedelta(minutes=random.randint(0, 59))
 
54
  return {
55
  'Pole ID': f'{site_name[:3].upper()}-{pole_id:03}',
56
  'Site': site_name,
 
69
  'Last Checked': timestamp.strftime('%Y-%m-%d %H:%M:%S')
70
  }
71
 
 
72
  @st.cache_data(ttl=3600)
73
  def get_simulated_data():
74
  all_data = []
75
  for site_name, site_data in SITES.items():
76
  base_lat, base_lon = site_data["coords"]
77
  locations = generate_fixed_pole_locations(base_lat, base_lon, POLES_PER_SITE)
 
78
  for i, (lat, lon) in enumerate(locations):
79
  pole_data = simulate_pole(i + 1, site_name, lat, lon)
80
  all_data.append(pole_data)
81
  return pd.DataFrame(all_data)
82
 
83
+ # ---- UI Starts ----
 
84
  st.title("🌍 Smart Renewable Pole Monitoring - Multi-Site")
85
 
86
  selected_site = st.selectbox("Select a site to view:", options=list(SITES.keys()), index=0)
 
91
  df = get_simulated_data()
92
  site_df = df[df['Site'] == selected_site]
93
 
 
94
  col1, col2, col3 = st.columns(3)
95
  col1.metric("Total Poles", site_df.shape[0])
96
  col2.metric("Red Alerts", site_df[site_df['Alert Level'] == 'Red'].shape[0])
97
  col3.metric("Power Insufficiencies", site_df[site_df['Power Status'] == 'Insufficient'].shape[0])
98
 
 
99
  st.subheader(f"πŸ“‹ Pole Data Table for {selected_site}")
100
  with st.expander("Filter Options"):
101
  alert_filter = st.multiselect("Alert Level", options=site_df['Alert Level'].unique(), default=site_df['Alert Level'].unique())
 
107
  ]
108
  st.dataframe(filtered_df, use_container_width=True)
109
 
 
110
  st.subheader("πŸ”‹ Energy Generation per Pole")
111
 
112
  energy_long_df = site_df[['Pole ID', 'Solar (kWh)', 'Wind (kWh)']].melt(
 
128
 
129
  st.altair_chart(bar_chart, use_container_width=True)
130
 
 
131
  st.subheader("⚠️ Map Filter: Select Fault Type(s)")
 
132
  fault_options = ['High Vibration (>3g)', 'Camera Offline', 'Power Insufficient']
133
  selected_faults = st.multiselect("Show poles with these fault conditions:", options=fault_options, default=fault_options)
134
 
 
141
 
142
  fault_df = site_df[site_df.apply(fault_condition, axis=1)] if selected_faults else site_df
143
 
 
144
  def get_color(alert):
145
  if alert == 'Green':
146
  return [0, 255, 0, 160]
 
152
 
153
  fault_df['color'] = fault_df['Alert Level'].apply(get_color)
154
 
 
155
  st.subheader("πŸ“ Pole Locations with Selected Faults")
156
  st.pydeck_chart(pdk.Deck(
157
  initial_view_state=pdk.ViewState(
 
190
  }
191
  }
192
  ))