Compare commits
4 Commits
52562bd8e6
...
81137a4c5e
| Author | SHA1 | Date | |
|---|---|---|---|
| 81137a4c5e | |||
| 954cd144b9 | |||
| 1c9f1d731e | |||
| 37be801270 |
96
Scripts/memory_check.py
Normal file
96
Scripts/memory_check.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import gc
|
||||||
|
|
||||||
|
class MemoryMonitor:
|
||||||
|
"""Monitor and display Pico W memory usage."""
|
||||||
|
|
||||||
|
def __init__(self, interval=300):
|
||||||
|
"""
|
||||||
|
Initialize memory monitor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
interval: Seconds between memory checks (default: 300 = 5 minutes)
|
||||||
|
"""
|
||||||
|
self.interval = interval
|
||||||
|
self.last_check = 0
|
||||||
|
self.initial_free = None # Track initial free memory
|
||||||
|
|
||||||
|
def should_run(self, current_time):
|
||||||
|
"""Check if it's time to run memory check."""
|
||||||
|
if current_time - self.last_check >= self.interval:
|
||||||
|
self.last_check = current_time
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""Check and display memory usage."""
|
||||||
|
# Force garbage collection before checking
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
# Get memory stats
|
||||||
|
free = gc.mem_free()
|
||||||
|
allocated = gc.mem_alloc()
|
||||||
|
total = free + allocated
|
||||||
|
|
||||||
|
# Store initial free memory on first run
|
||||||
|
if self.initial_free is None:
|
||||||
|
self.initial_free = free
|
||||||
|
|
||||||
|
# Calculate memory leak (if any)
|
||||||
|
leaked = self.initial_free - free if self.initial_free else 0
|
||||||
|
|
||||||
|
# Print memory report
|
||||||
|
print("\n" + "="*50)
|
||||||
|
print("Pico W Memory (RAM):")
|
||||||
|
print("="*50)
|
||||||
|
print("Total: {:.1f} KB".format(total / 1024))
|
||||||
|
print("Used: {:.1f} KB ({:.1f}%)".format(
|
||||||
|
allocated / 1024,
|
||||||
|
(allocated/total)*100
|
||||||
|
))
|
||||||
|
print("Free: {:.1f} KB ({:.1f}%)".format(
|
||||||
|
free / 1024,
|
||||||
|
(free/total)*100
|
||||||
|
))
|
||||||
|
|
||||||
|
# Show memory leak warning if detected
|
||||||
|
if leaked > 5120: # More than 5 KB leaked
|
||||||
|
print("⚠️ Leaked: {:.1f} KB since startup".format(leaked / 1024))
|
||||||
|
|
||||||
|
print("="*50 + "\n")
|
||||||
|
|
||||||
|
# Return memory info for other uses (like web server)
|
||||||
|
return {
|
||||||
|
'total_kb': total / 1024,
|
||||||
|
'used_kb': allocated / 1024,
|
||||||
|
'free_kb': free / 1024,
|
||||||
|
'usage_percent': (allocated/total)*100,
|
||||||
|
'leaked_kb': leaked / 1024 if leaked > 0 else 0
|
||||||
|
}
|
||||||
|
|
||||||
|
def check_memory_once():
|
||||||
|
"""One-time memory check (for startup diagnostics)."""
|
||||||
|
gc.collect()
|
||||||
|
free = gc.mem_free()
|
||||||
|
allocated = gc.mem_alloc()
|
||||||
|
total = free + allocated
|
||||||
|
|
||||||
|
print("\n" + "="*50)
|
||||||
|
print("Startup Memory Check:")
|
||||||
|
print("="*50)
|
||||||
|
print("Total: {:.1f} KB".format(total / 1024))
|
||||||
|
print("Used: {:.1f} KB ({:.1f}%)".format(
|
||||||
|
allocated / 1024,
|
||||||
|
(allocated/total)*100
|
||||||
|
))
|
||||||
|
print("Free: {:.1f} KB ({:.1f}%)".format(
|
||||||
|
free / 1024,
|
||||||
|
(free/total)*100
|
||||||
|
))
|
||||||
|
print("="*50 + "\n")
|
||||||
|
|
||||||
|
return {
|
||||||
|
'total_kb': total / 1024,
|
||||||
|
'used_kb': allocated / 1024,
|
||||||
|
'free_kb': free / 1024,
|
||||||
|
'usage_percent': (allocated/total)*100
|
||||||
|
}
|
||||||
@@ -184,6 +184,24 @@ class TempWebServer:
|
|||||||
|
|
||||||
config['schedules'] = schedules
|
config['schedules'] = schedules
|
||||||
|
|
||||||
|
# ===== START: Validate all schedules =====
|
||||||
|
for i, schedule in enumerate(schedules):
|
||||||
|
heater_temp = schedule.get('heater_target', 80.0)
|
||||||
|
ac_temp = schedule.get('ac_target', 77.0)
|
||||||
|
|
||||||
|
if heater_temp > ac_temp:
|
||||||
|
print("❌ Schedule validation failed: Schedule {} has heater ({}) > AC ({})".format(
|
||||||
|
i+1, heater_temp, ac_temp
|
||||||
|
))
|
||||||
|
return self._get_error_page(
|
||||||
|
"Invalid Schedule",
|
||||||
|
"Schedule {} ({}): Heater target ({:.1f}°F) cannot be greater than AC target ({:.1f}°F)".format(
|
||||||
|
i+1, schedule.get('name', 'Unnamed'), heater_temp, ac_temp
|
||||||
|
),
|
||||||
|
sensors, ac_monitor, heater_monitor
|
||||||
|
)
|
||||||
|
# ===== END: Validate all schedules =====
|
||||||
|
|
||||||
# Save to file
|
# Save to file
|
||||||
if self._save_config_to_file(config):
|
if self._save_config_to_file(config):
|
||||||
print("Schedule configuration saved")
|
print("Schedule configuration saved")
|
||||||
@@ -224,6 +242,26 @@ class TempWebServer:
|
|||||||
# Load current config
|
# Load current config
|
||||||
config = self._load_config()
|
config = self._load_config()
|
||||||
|
|
||||||
|
# ===== START: Validate Heat <= AC =====
|
||||||
|
# Get the values that will be set
|
||||||
|
new_heater_target = params.get('heater_target', config.get('heater_target', 80.0))
|
||||||
|
new_ac_target = params.get('ac_target', config.get('ac_target', 77.0))
|
||||||
|
|
||||||
|
# Validation: Heater must be <= AC
|
||||||
|
if new_heater_target > new_ac_target:
|
||||||
|
print("❌ Validation failed: Heater target ({}) cannot be greater than AC target ({})".format(
|
||||||
|
new_heater_target, new_ac_target
|
||||||
|
))
|
||||||
|
# Return error page
|
||||||
|
return self._get_error_page(
|
||||||
|
"Invalid Settings",
|
||||||
|
"Heater target ({:.1f}°F) cannot be greater than AC target ({:.1f}°F)".format(
|
||||||
|
new_heater_target, new_ac_target
|
||||||
|
),
|
||||||
|
sensors, ac_monitor, heater_monitor
|
||||||
|
)
|
||||||
|
# ===== END: Validate Heat <= AC =====
|
||||||
|
|
||||||
# ===== START: Update AC Settings =====
|
# ===== START: Update AC Settings =====
|
||||||
if 'ac_target' in params and ac_monitor:
|
if 'ac_target' in params and ac_monitor:
|
||||||
ac_monitor.target_temp = params['ac_target'] # Update monitor
|
ac_monitor.target_temp = params['ac_target'] # Update monitor
|
||||||
@@ -630,35 +668,26 @@ class TempWebServer:
|
|||||||
|
|
||||||
<div class="card full-width">
|
<div class="card full-width">
|
||||||
<div class="status">
|
<div class="status">
|
||||||
<div class="status-item">
|
<!-- ===== HEATER FIRST (LEFT) ===== -->
|
||||||
<div class="status-icon">❄️</div>
|
|
||||||
<div class="label">Air Conditioning</div>
|
|
||||||
<div class="status-indicator {ac_class}">{ac_status}</div>
|
|
||||||
<div class="targets">Target: {ac_target}°F ± {ac_swing}°F</div>
|
|
||||||
</div>
|
|
||||||
<div class="status-item">
|
<div class="status-item">
|
||||||
<div class="status-icon">🔥</div>
|
<div class="status-icon">🔥</div>
|
||||||
<div class="label">Heating System</div>
|
<div class="label">Heating System</div>
|
||||||
<div class="status-indicator {heater_class}">{heater_status}</div>
|
<div class="status-indicator {heater_class}">{heater_status}</div>
|
||||||
<div class="targets">Target: {heater_target}°F ± {heater_swing}°F</div>
|
<div class="targets">Target: {heater_target}°F ± {heater_swing}°F</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- ===== AC SECOND (RIGHT) ===== -->
|
||||||
|
<div class="status-item">
|
||||||
|
<div class="status-icon">❄️</div>
|
||||||
|
<div class="label">Air Conditioning</div>
|
||||||
|
<div class="status-indicator {ac_class}">{ac_status}</div>
|
||||||
|
<div class="targets">Target: {ac_target}°F ± {ac_swing}°F</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form method="POST" action="/update" class="controls">
|
<form method="POST" action="/update" class="controls">
|
||||||
<h2 style="text-align: center; color: #34495e; margin-bottom: 20px;">⚙️ Adjust Settings</h2>
|
<h2 style="text-align: center; color: #34495e; margin-bottom: 20px;">⚙️ Adjust Settings</h2>
|
||||||
|
|
||||||
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px;">
|
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px;">
|
||||||
<div>
|
<!-- ===== LEFT COLUMN: Heater ===== -->
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label">❄️ AC Target (°F)</label>
|
|
||||||
<input type="number" name="ac_target" value="{ac_target}" step="0.5" min="60" max="85">
|
|
||||||
</div>
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label">❄️ AC Swing (°F)</label>
|
|
||||||
<input type="number" name="ac_swing" value="{ac_swing}" step="0.5" min="0.5" max="5">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label">🔥 Heater Target (°F)</label>
|
<label class="control-label">🔥 Heater Target (°F)</label>
|
||||||
@@ -669,6 +698,18 @@ class TempWebServer:
|
|||||||
<input type="number" name="heater_swing" value="{heater_swing}" step="0.5" min="0.5" max="5">
|
<input type="number" name="heater_swing" value="{heater_swing}" step="0.5" min="0.5" max="5">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- ===== RIGHT COLUMN: AC ===== -->
|
||||||
|
<div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label">❄️ AC Target (°F)</label>
|
||||||
|
<input type="number" name="ac_target" value="{ac_target}" step="0.5" min="60" max="85">
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label">❄️ AC Swing (°F)</label>
|
||||||
|
<input type="number" name="ac_swing" value="{ac_swing}" step="0.5" min="0.5" max="5">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group" style="margin-top: 20px;">
|
<div class="control-group" style="margin-top: 20px;">
|
||||||
@@ -724,6 +765,134 @@ class TempWebServer:
|
|||||||
import sys
|
import sys
|
||||||
sys.print_exception(e)
|
sys.print_exception(e)
|
||||||
return "<html><body><h1>Error loading page</h1><pre>{}</pre></body></html>".format(str(e))
|
return "<html><body><h1>Error loading page</h1><pre>{}</pre></body></html>".format(str(e))
|
||||||
|
|
||||||
|
def _get_error_page(self, error_title, error_message, sensors, ac_monitor, heater_monitor):
|
||||||
|
"""Generate error page with message."""
|
||||||
|
# Get current temps
|
||||||
|
inside_temps = sensors['inside'].read_all_temps(unit='F')
|
||||||
|
outside_temps = sensors['outside'].read_all_temps(unit='F')
|
||||||
|
|
||||||
|
inside_temp = list(inside_temps.values())[0] if inside_temps else "N/A"
|
||||||
|
outside_temp = list(outside_temps.values())[0] if outside_temps else "N/A"
|
||||||
|
|
||||||
|
inside_temp_str = "{:.1f}".format(inside_temp) if isinstance(inside_temp, float) else str(inside_temp)
|
||||||
|
outside_temp_str = "{:.1f}".format(outside_temp) if isinstance(outside_temp, float) else str(outside_temp)
|
||||||
|
|
||||||
|
# Get current statuses
|
||||||
|
ac_status = "ON" if ac_monitor and ac_monitor.ac.get_state() else "OFF"
|
||||||
|
heater_status = "ON" if heater_monitor and heater_monitor.heater.get_state() else "OFF"
|
||||||
|
|
||||||
|
html = """
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Error - Climate Control</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<style>
|
||||||
|
body {{
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 40px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
}}
|
||||||
|
.container {{
|
||||||
|
background: white;
|
||||||
|
border-radius: 15px;
|
||||||
|
padding: 30px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
|
||||||
|
}}
|
||||||
|
.error-banner {{
|
||||||
|
background: linear-gradient(135deg, #e74c3c, #c0392b);
|
||||||
|
color: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||||||
|
}}
|
||||||
|
.error-title {{
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}}
|
||||||
|
.error-message {{
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}}
|
||||||
|
.btn {{
|
||||||
|
background: linear-gradient(135deg, #3498db, #2980b9);
|
||||||
|
color: white;
|
||||||
|
padding: 12px 24px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 20px;
|
||||||
|
}}
|
||||||
|
.btn:hover {{
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(52, 152, 219, 0.4);
|
||||||
|
}}
|
||||||
|
.status-grid {{
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 15px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}}
|
||||||
|
.status-card {{
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-align: center;
|
||||||
|
}}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="error-banner">
|
||||||
|
<div class="error-title">❌ {error_title}</div>
|
||||||
|
<div class="error-message">{error_message}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="status-grid">
|
||||||
|
<div class="status-card">
|
||||||
|
<div style="font-size: 14px; color: #7f8c8d; margin-bottom: 5px;">🏠 Inside</div>
|
||||||
|
<div style="font-size: 24px; font-weight: bold; color: #2c3e50;">{inside_temp}°F</div>
|
||||||
|
</div>
|
||||||
|
<div class="status-card">
|
||||||
|
<div style="font-size: 14px; color: #7f8c8d; margin-bottom: 5px;">🌡️ Outside</div>
|
||||||
|
<div style="font-size: 24px; font-weight: bold; color: #2c3e50;">{outside_temp}°F</div>
|
||||||
|
</div>
|
||||||
|
<div class="status-card">
|
||||||
|
<div style="font-size: 14px; color: #7f8c8d; margin-bottom: 5px;">🔥 Heater</div>
|
||||||
|
<div style="font-size: 24px; font-weight: bold; color: #2c3e50;">{heater_status}</div>
|
||||||
|
</div>
|
||||||
|
<div class="status-card">
|
||||||
|
<div style="font-size: 14px; color: #7f8c8d; margin-bottom: 5px;">❄️ AC</div>
|
||||||
|
<div style="font-size: 24px; font-weight: bold; color: #2c3e50;">{ac_status}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<a href="/" class="btn">⬅️ Go Back</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
""".format(
|
||||||
|
error_title=error_title,
|
||||||
|
error_message=error_message,
|
||||||
|
inside_temp=inside_temp_str,
|
||||||
|
outside_temp=outside_temp_str,
|
||||||
|
heater_status=heater_status,
|
||||||
|
ac_status=ac_status
|
||||||
|
)
|
||||||
|
|
||||||
|
return html
|
||||||
|
|
||||||
def _build_schedule_form(self, config):
|
def _build_schedule_form(self, config):
|
||||||
"""Build the schedule editing form."""
|
"""Build the schedule editing form."""
|
||||||
|
|||||||
19
config.json
19
config.json
@@ -1,33 +1,34 @@
|
|||||||
{
|
{
|
||||||
"ac_target": 77.0,
|
"ac_target": 77.0,
|
||||||
"ac_swing": 1.0,
|
"ac_swing": 1.0,
|
||||||
"heater_target": 80.0,
|
"heater_target": 72.0,
|
||||||
"heater_swing": 2.0,
|
"heater_swing": 2.0,
|
||||||
"schedules": [
|
"schedules": [
|
||||||
{
|
{
|
||||||
"time": "06:00",
|
"time": "06:00",
|
||||||
"ac_target": 75.0,
|
"ac_target": 75.0,
|
||||||
"heater_target": 78.0,
|
"heater_target": 72.0,
|
||||||
"name": "Morning"
|
"name": "Morning"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "12:00",
|
"time": "12:00",
|
||||||
"ac_target": 77.0,
|
"ac_target": 75.0,
|
||||||
"heater_target": 80.0,
|
"heater_target": 72.0,
|
||||||
"name": "Midday"
|
"name": "Midday"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "18:00",
|
"time": "18:00",
|
||||||
"ac_target": 76.0,
|
"ac_target": 75.0,
|
||||||
"heater_target": 79.0,
|
"heater_target": 72.0,
|
||||||
"name": "Evening"
|
"name": "Evening"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "22:00",
|
"time": "22:00",
|
||||||
"ac_target": 74.0,
|
"ac_target": 75.0,
|
||||||
"heater_target": 77.0,
|
"heater_target": 72.0,
|
||||||
"name": "Night"
|
"name": "Night"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"schedule_enabled": true
|
"schedule_enabled": true,
|
||||||
|
"permanent_hold": false
|
||||||
}
|
}
|
||||||
62
main.py
62
main.py
@@ -27,6 +27,7 @@ from scripts.air_conditioning import ACController
|
|||||||
from scripts.heating import HeaterController
|
from scripts.heating import HeaterController
|
||||||
from scripts.web_server import TempWebServer
|
from scripts.web_server import TempWebServer
|
||||||
from scripts.scheduler import ScheduleMonitor # NEW: Import scheduler for time-based temp changes
|
from scripts.scheduler import ScheduleMonitor # NEW: Import scheduler for time-based temp changes
|
||||||
|
from scripts.memory_check import MemoryMonitor, check_memory_once # NEW: Import memory checker
|
||||||
|
|
||||||
# ===== START: Configuration Loading =====
|
# ===== START: Configuration Loading =====
|
||||||
# Load saved settings from config.json file on Pico
|
# Load saved settings from config.json file on Pico
|
||||||
@@ -38,16 +39,55 @@ def load_config():
|
|||||||
print("Loaded saved settings from config.json")
|
print("Loaded saved settings from config.json")
|
||||||
return config
|
return config
|
||||||
except:
|
except:
|
||||||
# If file doesn't exist or is corrupted, use defaults
|
# If file doesn't exist or is corrupted, create default config
|
||||||
print("No saved config found, using defaults")
|
print("No saved config found, creating default config.json...")
|
||||||
return {
|
|
||||||
'ac_target': 77.0, # Default AC target temp
|
default_config = {
|
||||||
|
'ac_target': 75.0, # Default AC target temp
|
||||||
'ac_swing': 1.0, # Default AC tolerance (+/- degrees)
|
'ac_swing': 1.0, # Default AC tolerance (+/- degrees)
|
||||||
'heater_target': 80.0, # Default heater target temp
|
'heater_target': 72.0, # Default heater target temp
|
||||||
'heater_swing': 2.0, # Default heater tolerance (+/- degrees)
|
'heater_swing': 2.0, # Default heater tolerance (+/- degrees)
|
||||||
'schedules': [], # No schedules by default
|
'schedules': [ # Default 4 schedules
|
||||||
'schedule_enabled': False # Schedules disabled by default
|
{
|
||||||
|
'time': '06:00',
|
||||||
|
'name': 'Morning',
|
||||||
|
'ac_target': 75.0,
|
||||||
|
'heater_target': 72.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'time': '12:00',
|
||||||
|
'name': 'Midday',
|
||||||
|
'ac_target': 75.0,
|
||||||
|
'heater_target': 72.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'time': '18:00',
|
||||||
|
'name': 'Evening',
|
||||||
|
'ac_target': 75.0,
|
||||||
|
'heater_target': 72.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'time': '22:00',
|
||||||
|
'name': 'Night',
|
||||||
|
'ac_target': 75.0,
|
||||||
|
'heater_target': 72.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'schedule_enabled': False, # Schedules disabled by default (user can enable via web)
|
||||||
|
'permanent_hold': False # Permanent hold disabled by default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ===== START: Save default config to file =====
|
||||||
|
try:
|
||||||
|
with open('config.json', 'w') as f:
|
||||||
|
json.dump(default_config, f)
|
||||||
|
print("✅ Default config.json created successfully with 4 sample schedules")
|
||||||
|
except Exception as e:
|
||||||
|
print("⚠️ Warning: Could not create config.json: {}".format(e))
|
||||||
|
print(" (Program will continue with defaults in memory)")
|
||||||
|
# ===== END: Save default config to file =====
|
||||||
|
|
||||||
|
return default_config
|
||||||
|
|
||||||
# Load configuration from file
|
# Load configuration from file
|
||||||
config = load_config()
|
config = load_config()
|
||||||
@@ -196,6 +236,11 @@ if config.get('schedules'):
|
|||||||
print("="*50 + "\n")
|
print("="*50 + "\n")
|
||||||
# ===== END: Print Current Settings =====
|
# ===== END: Print Current Settings =====
|
||||||
|
|
||||||
|
# ===== START: Startup Memory Check =====
|
||||||
|
# Check memory usage after all imports and initialization
|
||||||
|
check_memory_once()
|
||||||
|
# ===== END: Startup Memory Check =====
|
||||||
|
|
||||||
# ===== START: Monitor Setup =====
|
# ===== START: Monitor Setup =====
|
||||||
# Set up all monitoring systems (run in order during main loop)
|
# Set up all monitoring systems (run in order during main loop)
|
||||||
monitors = [
|
monitors = [
|
||||||
@@ -204,6 +249,9 @@ monitors = [
|
|||||||
|
|
||||||
# Schedule monitor: Changes temp targets based on time of day
|
# Schedule monitor: Changes temp targets based on time of day
|
||||||
schedule_monitor,
|
schedule_monitor,
|
||||||
|
|
||||||
|
# Memory monitor: Checks RAM usage every 5 minutes
|
||||||
|
MemoryMonitor(interval=300), # 300 seconds = 5 minutes
|
||||||
|
|
||||||
# AC monitor: Automatically turns AC on/off based on temperature
|
# AC monitor: Automatically turns AC on/off based on temperature
|
||||||
ac_monitor,
|
ac_monitor,
|
||||||
|
|||||||
Reference in New Issue
Block a user