import streamlit as st import pandas as pd import numpy as np import time import matplotlib.pyplot as plt import datetime from io import BytesIO import base64 # Set page configuration st.set_page_config( page_title="AI Smart Umbrella System", page_icon="☂️", layout="wide", initial_sidebar_state="expanded" ) # Define the environmental thresholds for the umbrella system THRESHOLDS = { "temperature": {"open": 32, "close": 25}, # °C "humidity": {"open": 40, "close": 70}, # % "soil_moisture": {"open": 20, "close": 40}, # % VWC "sunlight": {"open": 700, "close": 400} # W/m² } class SmartUmbrellaSystem: def __init__(self): self.umbrella_state = "Closed" self.current_readings = { "temperature": 25.0, "humidity": 60.0, "soil_moisture": 35.0, "sunlight": 500 } # Initialize empty lists for historical data self.timestamps = [] self.temp_history = [] self.humidity_history = [] self.soil_moisture_history = [] self.sunlight_history = [] self.umbrella_history = [] self.log_messages = [] # Add initial log message self.add_log("System initialized with umbrella closed") def add_log(self, message): """Add a log message with timestamp""" timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.log_messages.insert(0, f"{timestamp}: {message}") def update_readings(self, readings=None): """Update sensor readings and determine umbrella state""" if readings: self.current_readings = readings else: # Simulate sensor readings with some variation self.current_readings["temperature"] += np.random.uniform(-1.0, 1.0) self.current_readings["humidity"] += np.random.uniform(-2.0, 2.0) self.current_readings["soil_moisture"] += np.random.uniform(-1.0, 1.0) self.current_readings["sunlight"] += np.random.uniform(-50, 50) # Ensure values stay within realistic ranges self.current_readings["temperature"] = max(10, min(45, self.current_readings["temperature"])) self.current_readings["humidity"] = max(20, min(95, self.current_readings["humidity"])) self.current_readings["soil_moisture"] = max(5, min(60, self.current_readings["soil_moisture"])) self.current_readings["sunlight"] = max(0, min(1200, self.current_readings["sunlight"])) # Record history current_time = datetime.datetime.now() self.timestamps.append(current_time) self.temp_history.append(self.current_readings["temperature"]) self.humidity_history.append(self.current_readings["humidity"]) self.soil_moisture_history.append(self.current_readings["soil_moisture"]) self.sunlight_history.append(self.current_readings["sunlight"]) # Keep only the last 100 readings if len(self.timestamps) > 100: self.timestamps.pop(0) self.temp_history.pop(0) self.humidity_history.pop(0) self.soil_moisture_history.pop(0) self.sunlight_history.pop(0) self.umbrella_history.pop(0) # Determine umbrella state based on sensor readings previous_state = self.umbrella_state self.evaluate_umbrella_state() # Record umbrella state self.umbrella_history.append(1 if self.umbrella_state == "Open" else 0) # Log state change if any if previous_state != self.umbrella_state: self.add_log(f"Umbrella state changed from {previous_state} to {self.umbrella_state}") def evaluate_umbrella_state(self): """Evaluate umbrella state based on environmental thresholds""" # Open umbrella when any condition exceeds threshold if (self.current_readings["temperature"] > THRESHOLDS["temperature"]["open"] or self.current_readings["humidity"] < THRESHOLDS["humidity"]["open"] or self.current_readings["soil_moisture"] < THRESHOLDS["soil_moisture"]["open"] or self.current_readings["sunlight"] > THRESHOLDS["sunlight"]["open"]): self.umbrella_state = "Open" # Close umbrella when all conditions are below threshold elif (self.current_readings["temperature"] < THRESHOLDS["temperature"]["close"] and self.current_readings["humidity"] > THRESHOLDS["humidity"]["close"] and self.current_readings["soil_moisture"] > THRESHOLDS["soil_moisture"]["close"] and self.current_readings["sunlight"] < THRESHOLDS["sunlight"]["close"]): self.umbrella_state = "Closed" def manually_set_umbrella(self, state): """Manually override umbrella state""" previous_state = self.umbrella_state self.umbrella_state = state self.add_log(f"Manual override: Umbrella state set to {state}") # Update umbrella history if len(self.umbrella_history) > 0: self.umbrella_history[-1] = 1 if state == "Open" else 0 def get_history_dataframe(self): """Create a dataframe of historical data""" data = { "Timestamp": self.timestamps, "Temperature (°C)": self.temp_history, "Humidity (%)": self.humidity_history, "Soil Moisture (%)": self.soil_moisture_history, "Sunlight (W/m²)": self.sunlight_history, "Umbrella State": ["Open" if state == 1 else "Closed" for state in self.umbrella_history] } return pd.DataFrame(data) # Initialize session state for persistent data if 'system' not in st.session_state: st.session_state.system = SmartUmbrellaSystem() st.session_state.simulation_running = False st.session_state.update_interval = 1.0 # seconds # Streamlit UI st.title("☂️ AI-Controlled Solar-Powered Smart Umbrella System") # Create sidebar for controls with st.sidebar: st.header("System Controls") # Manual readings input st.subheader("Manual Sensor Readings") col1, col2 = st.columns(2) with col1: temp = st.number_input("Temperature (°C)", 10.0, 45.0, st.session_state.system.current_readings["temperature"], 0.1) with col2: humidity = st.number_input("Humidity (%)", 20.0, 95.0, st.session_state.system.current_readings["humidity"], 0.1) col1, col2 = st.columns(2) with col1: soil_moisture = st.number_input("Soil Moisture (%)", 5.0, 60.0, st.session_state.system.current_readings["soil_moisture"], 0.1) with col2: sunlight = st.number_input("Sunlight (W/m²)", 0, 1200, int(st.session_state.system.current_readings["sunlight"]), 10) if st.button("Update Readings"): st.session_state.system.update_readings({ "temperature": temp, "humidity": humidity, "soil_moisture": soil_moisture, "sunlight": sunlight }) st.success("Readings updated!") st.divider() # Manual control st.subheader("Manual Umbrella Control") umbrella_control = st.radio("Set Umbrella State", ["Auto", "Force Open", "Force Closed"]) if umbrella_control == "Force Open": st.session_state.system.manually_set_umbrella("Open") elif umbrella_control == "Force Closed": st.session_state.system.manually_set_umbrella("Closed") st.divider() # Simulation controls st.subheader("Simulation Controls") st.session_state.update_interval = st.slider("Update Interval (seconds)", 0.5, 5.0, st.session_state.update_interval, 0.1) if st.button("Start Simulation" if not st.session_state.simulation_running else "Stop Simulation"): st.session_state.simulation_running = not st.session_state.simulation_running st.success(f"Simulation {'started' if st.session_state.simulation_running else 'stopped'}!") # Main content area with multiple sections col1, col2 = st.columns([3, 2]) # Left column - Current readings and umbrella state with col1: st.header("Current System Status") # Umbrella state with icon umbrella_icon = "🌂" if st.session_state.system.umbrella_state == "Closed" else "☂️" st.subheader(f"Umbrella State: {umbrella_icon} {st.session_state.system.umbrella_state}") # Create metrics for current readings col_a, col_b, col_c, col_d = st.columns(4) with col_a: st.metric( "Temperature (°C)", f"{st.session_state.system.current_readings['temperature']:.1f}", 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 ) with col_b: # For humidity, lower is concerning so we reverse the delta st.metric( "Humidity (%)", f"{st.session_state.system.current_readings['humidity']:.1f}", 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 ) with col_c: # For soil moisture, lower is concerning so we reverse the delta st.metric( "Soil Moisture (%)", f"{st.session_state.system.current_readings['soil_moisture']:.1f}", 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 ) with col_d: st.metric( "Sunlight (W/m²)", f"{st.session_state.system.current_readings['sunlight']}", 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 ) # Thresholds table st.subheader("Environmental Thresholds") threshold_data = { "Parameter": ["Temperature (°C)", "Humidity (%)", "Soil Moisture (%)", "Sunlight (W/m²)"], "Open Umbrella If": [ f"> {THRESHOLDS['temperature']['open']}", f"< {THRESHOLDS['humidity']['open']}", f"< {THRESHOLDS['soil_moisture']['open']}", f"> {THRESHOLDS['sunlight']['open']}" ], "Close Umbrella If": [ f"< {THRESHOLDS['temperature']['close']}", f"> {THRESHOLDS['humidity']['close']}", f"> {THRESHOLDS['soil_moisture']['close']}", f"< {THRESHOLDS['sunlight']['close']}" ] } st.table(pd.DataFrame(threshold_data)) # Right column - System logs with col2: st.header("System Logs") log_container = st.container(height=300) with log_container: for log in st.session_state.system.log_messages: st.text(log) # Data visualization section st.header("Data Visualization") # Get historical data if st.session_state.system.timestamps: # Create 4 plots for each parameter fig, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(5, 1, figsize=(10, 12), sharex=True) # Format timestamps for display formatted_times = [t.strftime("%H:%M:%S") for t in st.session_state.system.timestamps] x_ticks = range(0, len(formatted_times), max(1, len(formatted_times) // 10)) # Temperature plot ax1.plot(st.session_state.system.temp_history, 'r-') ax1.axhline(y=THRESHOLDS["temperature"]["open"], color='r', linestyle='--', alpha=0.5) ax1.axhline(y=THRESHOLDS["temperature"]["close"], color='b', linestyle='--', alpha=0.5) ax1.set_ylabel("Temperature (°C)") ax1.grid(True) # Humidity plot ax2.plot(st.session_state.system.humidity_history, 'b-') ax2.axhline(y=THRESHOLDS["humidity"]["open"], color='r', linestyle='--', alpha=0.5) ax2.axhline(y=THRESHOLDS["humidity"]["close"], color='b', linestyle='--', alpha=0.5) ax2.set_ylabel("Humidity (%)") ax2.grid(True) # Soil moisture plot ax3.plot(st.session_state.system.soil_moisture_history, 'g-') ax3.axhline(y=THRESHOLDS["soil_moisture"]["open"], color='r', linestyle='--', alpha=0.5) ax3.axhline(y=THRESHOLDS["soil_moisture"]["close"], color='b', linestyle='--', alpha=0.5) ax3.set_ylabel("Soil Moisture (%)") ax3.grid(True) # Sunlight plot ax4.plot(st.session_state.system.sunlight_history, 'y-') ax4.axhline(y=THRESHOLDS["sunlight"]["open"], color='r', linestyle='--', alpha=0.5) ax4.axhline(y=THRESHOLDS["sunlight"]["close"], color='b', linestyle='--', alpha=0.5) ax4.set_ylabel("Sunlight (W/m²)") ax4.grid(True) # Umbrella state plot ax5.step(range(len(st.session_state.system.umbrella_history)), st.session_state.system.umbrella_history, 'k-', where='post') ax5.set_ylim(-0.1, 1.1) ax5.set_yticks([0, 1]) ax5.set_yticklabels(["Closed", "Open"]) ax5.set_ylabel("Umbrella State") ax5.set_xlabel("Time") ax5.grid(True) # Set x-ticks to be timestamps ax5.set_xticks(x_ticks) ax5.set_xticklabels([formatted_times[i] for i in x_ticks], rotation=45) plt.tight_layout() st.pyplot(fig) # Data table with historical values with st.expander("View Historical Data Table"): st.dataframe(st.session_state.system.get_history_dataframe()) # Add download button csv = st.session_state.system.get_history_dataframe().to_csv(index=False) b64 = base64.b64encode(csv.encode()).decode() href = f'Download CSV File' st.markdown(href, unsafe_allow_html=True) else: st.info("No historical data available yet. Start the simulation or update readings manually.") # Update system readings periodically if simulation is running if st.session_state.simulation_running: st.session_state.system.update_readings() time.sleep(st.session_state.update_interval) st.experimental_rerun() # Footer st.markdown("---") st.markdown("**AI-Controlled Solar-Powered Smart Umbrella System for Agricultural Technology**") st.markdown("This system uses environmental sensors and AI decision logic to automatically control an umbrella for crop protection.")