Sulai2005 commited on
Commit
af897f1
·
verified ·
1 Parent(s): a9b1685

Streamlit code changed

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +340 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,342 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
1
  import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import time
5
+ import matplotlib.pyplot as plt
6
+ import datetime
7
+ from io import BytesIO
8
+ import base64
9
+
10
+ # Set page configuration
11
+ st.set_page_config(
12
+ page_title="AI Smart Umbrella System",
13
+ page_icon="☂️",
14
+ layout="wide",
15
+ initial_sidebar_state="expanded"
16
+ )
17
+
18
+ # Define the environmental thresholds for the umbrella system
19
+ THRESHOLDS = {
20
+ "temperature": {"open": 32, "close": 25}, # °C
21
+ "humidity": {"open": 40, "close": 70}, # %
22
+ "soil_moisture": {"open": 20, "close": 40}, # % VWC
23
+ "sunlight": {"open": 700, "close": 400} # W/m²
24
+ }
25
+
26
+ class SmartUmbrellaSystem:
27
+ def __init__(self):
28
+ self.umbrella_state = "Closed"
29
+ self.current_readings = {
30
+ "temperature": 25.0,
31
+ "humidity": 60.0,
32
+ "soil_moisture": 35.0,
33
+ "sunlight": 500
34
+ }
35
+ # Initialize empty lists for historical data
36
+ self.timestamps = []
37
+ self.temp_history = []
38
+ self.humidity_history = []
39
+ self.soil_moisture_history = []
40
+ self.sunlight_history = []
41
+ self.umbrella_history = []
42
+ self.log_messages = []
43
+
44
+ # Add initial log message
45
+ self.add_log("System initialized with umbrella closed")
46
+
47
+ def add_log(self, message):
48
+ """Add a log message with timestamp"""
49
+ timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
50
+ self.log_messages.insert(0, f"{timestamp}: {message}")
51
+
52
+ def update_readings(self, readings=None):
53
+ """Update sensor readings and determine umbrella state"""
54
+ if readings:
55
+ self.current_readings = readings
56
+ else:
57
+ # Simulate sensor readings with some variation
58
+ self.current_readings["temperature"] += np.random.uniform(-1.0, 1.0)
59
+ self.current_readings["humidity"] += np.random.uniform(-2.0, 2.0)
60
+ self.current_readings["soil_moisture"] += np.random.uniform(-1.0, 1.0)
61
+ self.current_readings["sunlight"] += np.random.uniform(-50, 50)
62
+
63
+ # Ensure values stay within realistic ranges
64
+ self.current_readings["temperature"] = max(10, min(45, self.current_readings["temperature"]))
65
+ self.current_readings["humidity"] = max(20, min(95, self.current_readings["humidity"]))
66
+ self.current_readings["soil_moisture"] = max(5, min(60, self.current_readings["soil_moisture"]))
67
+ self.current_readings["sunlight"] = max(0, min(1200, self.current_readings["sunlight"]))
68
+
69
+ # Record history
70
+ current_time = datetime.datetime.now()
71
+ self.timestamps.append(current_time)
72
+ self.temp_history.append(self.current_readings["temperature"])
73
+ self.humidity_history.append(self.current_readings["humidity"])
74
+ self.soil_moisture_history.append(self.current_readings["soil_moisture"])
75
+ self.sunlight_history.append(self.current_readings["sunlight"])
76
+
77
+ # Keep only the last 100 readings
78
+ if len(self.timestamps) > 100:
79
+ self.timestamps.pop(0)
80
+ self.temp_history.pop(0)
81
+ self.humidity_history.pop(0)
82
+ self.soil_moisture_history.pop(0)
83
+ self.sunlight_history.pop(0)
84
+ self.umbrella_history.pop(0)
85
+
86
+ # Determine umbrella state based on sensor readings
87
+ previous_state = self.umbrella_state
88
+ self.evaluate_umbrella_state()
89
+
90
+ # Record umbrella state
91
+ self.umbrella_history.append(1 if self.umbrella_state == "Open" else 0)
92
+
93
+ # Log state change if any
94
+ if previous_state != self.umbrella_state:
95
+ self.add_log(f"Umbrella state changed from {previous_state} to {self.umbrella_state}")
96
+
97
+ def evaluate_umbrella_state(self):
98
+ """Evaluate umbrella state based on environmental thresholds"""
99
+ # Open umbrella when any condition exceeds threshold
100
+ if (self.current_readings["temperature"] > THRESHOLDS["temperature"]["open"] or
101
+ self.current_readings["humidity"] < THRESHOLDS["humidity"]["open"] or
102
+ self.current_readings["soil_moisture"] < THRESHOLDS["soil_moisture"]["open"] or
103
+ self.current_readings["sunlight"] > THRESHOLDS["sunlight"]["open"]):
104
+ self.umbrella_state = "Open"
105
+
106
+ # Close umbrella when all conditions are below threshold
107
+ elif (self.current_readings["temperature"] < THRESHOLDS["temperature"]["close"] and
108
+ self.current_readings["humidity"] > THRESHOLDS["humidity"]["close"] and
109
+ self.current_readings["soil_moisture"] > THRESHOLDS["soil_moisture"]["close"] and
110
+ self.current_readings["sunlight"] < THRESHOLDS["sunlight"]["close"]):
111
+ self.umbrella_state = "Closed"
112
+
113
+ def manually_set_umbrella(self, state):
114
+ """Manually override umbrella state"""
115
+ previous_state = self.umbrella_state
116
+ self.umbrella_state = state
117
+ self.add_log(f"Manual override: Umbrella state set to {state}")
118
+
119
+ # Update umbrella history
120
+ if len(self.umbrella_history) > 0:
121
+ self.umbrella_history[-1] = 1 if state == "Open" else 0
122
+
123
+ def get_history_dataframe(self):
124
+ """Create a dataframe of historical data"""
125
+ data = {
126
+ "Timestamp": self.timestamps,
127
+ "Temperature (°C)": self.temp_history,
128
+ "Humidity (%)": self.humidity_history,
129
+ "Soil Moisture (%)": self.soil_moisture_history,
130
+ "Sunlight (W/m²)": self.sunlight_history,
131
+ "Umbrella State": ["Open" if state == 1 else "Closed" for state in self.umbrella_history]
132
+ }
133
+ return pd.DataFrame(data)
134
+
135
+ # Initialize session state for persistent data
136
+ if 'system' not in st.session_state:
137
+ st.session_state.system = SmartUmbrellaSystem()
138
+ st.session_state.simulation_running = False
139
+ st.session_state.update_interval = 1.0 # seconds
140
+
141
+ # Streamlit UI
142
+ st.title("☂️ AI-Controlled Solar-Powered Smart Umbrella System")
143
+
144
+ # Create sidebar for controls
145
+ with st.sidebar:
146
+ st.header("System Controls")
147
+
148
+ # Manual readings input
149
+ st.subheader("Manual Sensor Readings")
150
+ col1, col2 = st.columns(2)
151
+ with col1:
152
+ temp = st.number_input("Temperature (°C)", 10.0, 45.0, st.session_state.system.current_readings["temperature"], 0.1)
153
+ with col2:
154
+ humidity = st.number_input("Humidity (%)", 20.0, 95.0, st.session_state.system.current_readings["humidity"], 0.1)
155
+
156
+ col1, col2 = st.columns(2)
157
+ with col1:
158
+ soil_moisture = st.number_input("Soil Moisture (%)", 5.0, 60.0, st.session_state.system.current_readings["soil_moisture"], 0.1)
159
+ with col2:
160
+ sunlight = st.number_input("Sunlight (W/m²)", 0, 1200, int(st.session_state.system.current_readings["sunlight"]), 10)
161
+
162
+ if st.button("Update Readings"):
163
+ st.session_state.system.update_readings({
164
+ "temperature": temp,
165
+ "humidity": humidity,
166
+ "soil_moisture": soil_moisture,
167
+ "sunlight": sunlight
168
+ })
169
+ st.success("Readings updated!")
170
+
171
+ st.divider()
172
+
173
+ # Manual control
174
+ st.subheader("Manual Umbrella Control")
175
+ umbrella_control = st.radio("Set Umbrella State", ["Auto", "Force Open", "Force Closed"])
176
+
177
+ if umbrella_control == "Force Open":
178
+ st.session_state.system.manually_set_umbrella("Open")
179
+ elif umbrella_control == "Force Closed":
180
+ st.session_state.system.manually_set_umbrella("Closed")
181
+
182
+ st.divider()
183
+
184
+ # Simulation controls
185
+ st.subheader("Simulation Controls")
186
+ st.session_state.update_interval = st.slider("Update Interval (seconds)", 0.5, 5.0, st.session_state.update_interval, 0.1)
187
+
188
+ if st.button("Start Simulation" if not st.session_state.simulation_running else "Stop Simulation"):
189
+ st.session_state.simulation_running = not st.session_state.simulation_running
190
+ st.success(f"Simulation {'started' if st.session_state.simulation_running else 'stopped'}!")
191
+
192
+ # Main content area with multiple sections
193
+ col1, col2 = st.columns([3, 2])
194
+
195
+ # Left column - Current readings and umbrella state
196
+ with col1:
197
+ st.header("Current System Status")
198
+
199
+ # Umbrella state with icon
200
+ umbrella_icon = "🌂" if st.session_state.system.umbrella_state == "Closed" else "☂️"
201
+ st.subheader(f"Umbrella State: {umbrella_icon} {st.session_state.system.umbrella_state}")
202
+
203
+ # Create metrics for current readings
204
+ col_a, col_b, col_c, col_d = st.columns(4)
205
+
206
+ with col_a:
207
+ st.metric(
208
+ "Temperature (°C)",
209
+ f"{st.session_state.system.current_readings['temperature']:.1f}",
210
+ delta=f"{st.session_state.system.current_readings['temperature'] - THRESHOLDS['temperature']['open']:.1f}" if st.session_state.system.current_readings['temperature'] > THRESHOLDS['temperature']['open'] else None
211
+ )
212
+
213
+ with col_b:
214
+ # For humidity, lower is concerning so we reverse the delta
215
+ st.metric(
216
+ "Humidity (%)",
217
+ f"{st.session_state.system.current_readings['humidity']:.1f}",
218
+ delta=f"{THRESHOLDS['humidity']['open'] - st.session_state.system.current_readings['humidity']:.1f}" if st.session_state.system.current_readings['humidity'] < THRESHOLDS['humidity']['open'] else None
219
+ )
220
+
221
+ with col_c:
222
+ # For soil moisture, lower is concerning so we reverse the delta
223
+ st.metric(
224
+ "Soil Moisture (%)",
225
+ f"{st.session_state.system.current_readings['soil_moisture']:.1f}",
226
+ delta=f"{THRESHOLDS['soil_moisture']['open'] - st.session_state.system.current_readings['soil_moisture']:.1f}" if st.session_state.system.current_readings['soil_moisture'] < THRESHOLDS['soil_moisture']['open'] else None
227
+ )
228
+
229
+ with col_d:
230
+ st.metric(
231
+ "Sunlight (W/m²)",
232
+ f"{st.session_state.system.current_readings['sunlight']}",
233
+ delta=f"{st.session_state.system.current_readings['sunlight'] - THRESHOLDS['sunlight']['open']}" if st.session_state.system.current_readings['sunlight'] > THRESHOLDS['sunlight']['open'] else None
234
+ )
235
+
236
+ # Thresholds table
237
+ st.subheader("Environmental Thresholds")
238
+
239
+ threshold_data = {
240
+ "Parameter": ["Temperature (°C)", "Humidity (%)", "Soil Moisture (%)", "Sunlight (W/m²)"],
241
+ "Open Umbrella If": [
242
+ f"> {THRESHOLDS['temperature']['open']}",
243
+ f"< {THRESHOLDS['humidity']['open']}",
244
+ f"< {THRESHOLDS['soil_moisture']['open']}",
245
+ f"> {THRESHOLDS['sunlight']['open']}"
246
+ ],
247
+ "Close Umbrella If": [
248
+ f"< {THRESHOLDS['temperature']['close']}",
249
+ f"> {THRESHOLDS['humidity']['close']}",
250
+ f"> {THRESHOLDS['soil_moisture']['close']}",
251
+ f"< {THRESHOLDS['sunlight']['close']}"
252
+ ]
253
+ }
254
+
255
+ st.table(pd.DataFrame(threshold_data))
256
+
257
+ # Right column - System logs
258
+ with col2:
259
+ st.header("System Logs")
260
+ log_container = st.container(height=300)
261
+ with log_container:
262
+ for log in st.session_state.system.log_messages:
263
+ st.text(log)
264
+
265
+ # Data visualization section
266
+ st.header("Data Visualization")
267
+
268
+ # Get historical data
269
+ if st.session_state.system.timestamps:
270
+ # Create 4 plots for each parameter
271
+ fig, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(5, 1, figsize=(10, 12), sharex=True)
272
+
273
+ # Format timestamps for display
274
+ formatted_times = [t.strftime("%H:%M:%S") for t in st.session_state.system.timestamps]
275
+ x_ticks = range(0, len(formatted_times), max(1, len(formatted_times) // 10))
276
+
277
+ # Temperature plot
278
+ ax1.plot(st.session_state.system.temp_history, 'r-')
279
+ ax1.axhline(y=THRESHOLDS["temperature"]["open"], color='r', linestyle='--', alpha=0.5)
280
+ ax1.axhline(y=THRESHOLDS["temperature"]["close"], color='b', linestyle='--', alpha=0.5)
281
+ ax1.set_ylabel("Temperature (°C)")
282
+ ax1.grid(True)
283
+
284
+ # Humidity plot
285
+ ax2.plot(st.session_state.system.humidity_history, 'b-')
286
+ ax2.axhline(y=THRESHOLDS["humidity"]["open"], color='r', linestyle='--', alpha=0.5)
287
+ ax2.axhline(y=THRESHOLDS["humidity"]["close"], color='b', linestyle='--', alpha=0.5)
288
+ ax2.set_ylabel("Humidity (%)")
289
+ ax2.grid(True)
290
+
291
+ # Soil moisture plot
292
+ ax3.plot(st.session_state.system.soil_moisture_history, 'g-')
293
+ ax3.axhline(y=THRESHOLDS["soil_moisture"]["open"], color='r', linestyle='--', alpha=0.5)
294
+ ax3.axhline(y=THRESHOLDS["soil_moisture"]["close"], color='b', linestyle='--', alpha=0.5)
295
+ ax3.set_ylabel("Soil Moisture (%)")
296
+ ax3.grid(True)
297
+
298
+ # Sunlight plot
299
+ ax4.plot(st.session_state.system.sunlight_history, 'y-')
300
+ ax4.axhline(y=THRESHOLDS["sunlight"]["open"], color='r', linestyle='--', alpha=0.5)
301
+ ax4.axhline(y=THRESHOLDS["sunlight"]["close"], color='b', linestyle='--', alpha=0.5)
302
+ ax4.set_ylabel("Sunlight (W/m²)")
303
+ ax4.grid(True)
304
+
305
+ # Umbrella state plot
306
+ ax5.step(range(len(st.session_state.system.umbrella_history)), st.session_state.system.umbrella_history, 'k-', where='post')
307
+ ax5.set_ylim(-0.1, 1.1)
308
+ ax5.set_yticks([0, 1])
309
+ ax5.set_yticklabels(["Closed", "Open"])
310
+ ax5.set_ylabel("Umbrella State")
311
+ ax5.set_xlabel("Time")
312
+ ax5.grid(True)
313
+
314
+ # Set x-ticks to be timestamps
315
+ ax5.set_xticks(x_ticks)
316
+ ax5.set_xticklabels([formatted_times[i] for i in x_ticks], rotation=45)
317
+
318
+ plt.tight_layout()
319
+ st.pyplot(fig)
320
+
321
+ # Data table with historical values
322
+ with st.expander("View Historical Data Table"):
323
+ st.dataframe(st.session_state.system.get_history_dataframe())
324
+
325
+ # Add download button
326
+ csv = st.session_state.system.get_history_dataframe().to_csv(index=False)
327
+ b64 = base64.b64encode(csv.encode()).decode()
328
+ href = f'<a href="data:file/csv;base64,{b64}" download="smart_umbrella_data.csv">Download CSV File</a>'
329
+ st.markdown(href, unsafe_allow_html=True)
330
+ else:
331
+ st.info("No historical data available yet. Start the simulation or update readings manually.")
332
+
333
+ # Update system readings periodically if simulation is running
334
+ if st.session_state.simulation_running:
335
+ st.session_state.system.update_readings()
336
+ time.sleep(st.session_state.update_interval)
337
+ st.experimental_rerun()
338
 
339
+ # Footer
340
+ st.markdown("---")
341
+ st.markdown("**AI-Controlled Solar-Powered Smart Umbrella System for Agricultural Technology**")
342
+ st.markdown("This system uses environmental sensors and AI decision logic to automatically control an umbrella for crop protection.")