File size: 14,599 Bytes
276f260
af897f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276f260
af897f1
 
 
 
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
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'<a href="data:file/csv;base64,{b64}" download="smart_umbrella_data.csv">Download CSV File</a>'
        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.")