Add ScheduleMonitor class to manage temperature schedules and apply settings
This commit is contained in:
parent
1fb3511ed5
commit
f50f4baff0
143
Scripts/scheduler.py
Normal file
143
Scripts/scheduler.py
Normal file
@ -0,0 +1,143 @@
|
||||
import time
|
||||
|
||||
class ScheduleMonitor:
|
||||
"""Monitor that checks and applies temperature schedules."""
|
||||
|
||||
def __init__(self, ac_monitor, heater_monitor, config, interval=60):
|
||||
"""
|
||||
Initialize schedule monitor.
|
||||
|
||||
Args:
|
||||
ac_monitor: ACMonitor instance
|
||||
heater_monitor: HeaterMonitor instance
|
||||
config: Configuration dict with schedules
|
||||
interval: How often to check schedule (seconds)
|
||||
"""
|
||||
self.ac_monitor = ac_monitor
|
||||
self.heater_monitor = heater_monitor
|
||||
self.config = config
|
||||
self.interval = interval
|
||||
self.last_check = 0
|
||||
self.current_schedule = None
|
||||
self.last_applied_schedule = None
|
||||
|
||||
def _parse_time(self, time_str):
|
||||
"""Convert time string 'HH:MM' to minutes since midnight."""
|
||||
try:
|
||||
parts = time_str.split(':')
|
||||
hours = int(parts[0])
|
||||
minutes = int(parts[1])
|
||||
return hours * 60 + minutes
|
||||
except:
|
||||
return None
|
||||
|
||||
def _get_current_minutes(self):
|
||||
"""Get current time in minutes since midnight."""
|
||||
t = time.localtime()
|
||||
return t[3] * 60 + t[4] # hours * 60 + minutes
|
||||
|
||||
def _find_active_schedule(self):
|
||||
"""Find which schedule should be active right now."""
|
||||
if not self.config.get('schedule_enabled', False):
|
||||
return None
|
||||
|
||||
schedules = self.config.get('schedules', [])
|
||||
if not schedules:
|
||||
return None
|
||||
|
||||
current_minutes = self._get_current_minutes()
|
||||
|
||||
# Sort schedules by time
|
||||
sorted_schedules = []
|
||||
for schedule in schedules:
|
||||
schedule_minutes = self._parse_time(schedule['time'])
|
||||
if schedule_minutes is not None:
|
||||
sorted_schedules.append((schedule_minutes, schedule))
|
||||
|
||||
sorted_schedules.sort()
|
||||
|
||||
# Find the most recent schedule that has passed
|
||||
active_schedule = None
|
||||
for schedule_minutes, schedule in sorted_schedules:
|
||||
if current_minutes >= schedule_minutes:
|
||||
active_schedule = schedule
|
||||
else:
|
||||
break
|
||||
|
||||
# If no schedule found (before first schedule), use last schedule from yesterday
|
||||
if active_schedule is None and sorted_schedules:
|
||||
active_schedule = sorted_schedules[-1][1]
|
||||
|
||||
return active_schedule
|
||||
|
||||
def _apply_schedule(self, schedule):
|
||||
"""Apply a schedule's settings to the monitors."""
|
||||
if not schedule:
|
||||
return
|
||||
|
||||
# Check if this is a different schedule than last applied
|
||||
schedule_id = schedule.get('time', '') + schedule.get('name', '')
|
||||
if schedule_id == self.last_applied_schedule:
|
||||
return # Already applied
|
||||
|
||||
try:
|
||||
# Update AC settings if provided
|
||||
if 'ac_target' in schedule:
|
||||
self.ac_monitor.target_temp = float(schedule['ac_target'])
|
||||
|
||||
if 'ac_swing' in schedule:
|
||||
self.ac_monitor.temp_swing = float(schedule['ac_swing'])
|
||||
|
||||
# Update heater settings if provided
|
||||
if 'heater_target' in schedule:
|
||||
self.heater_monitor.target_temp = float(schedule['heater_target'])
|
||||
|
||||
if 'heater_swing' in schedule:
|
||||
self.heater_monitor.temp_swing = float(schedule['heater_swing'])
|
||||
|
||||
# Log the change
|
||||
schedule_name = schedule.get('name', 'Unnamed')
|
||||
print("\n" + "="*50)
|
||||
print("Schedule Applied: {}".format(schedule_name))
|
||||
print("="*50)
|
||||
print("AC Target: {}°F".format(self.ac_monitor.target_temp))
|
||||
print("Heater Target: {}°F".format(self.heater_monitor.target_temp))
|
||||
print("="*50 + "\n")
|
||||
|
||||
# Send Discord notification
|
||||
try:
|
||||
from scripts.discord_webhook import send_discord_message
|
||||
message = "🕐 Schedule '{}' applied - AC: {}°F | Heater: {}°F".format(
|
||||
schedule_name,
|
||||
self.ac_monitor.target_temp,
|
||||
self.heater_monitor.target_temp
|
||||
)
|
||||
send_discord_message(message)
|
||||
except:
|
||||
pass
|
||||
|
||||
self.last_applied_schedule = schedule_id
|
||||
|
||||
except Exception as e:
|
||||
print("Error applying schedule: {}".format(e))
|
||||
|
||||
def run(self):
|
||||
"""Check if schedule needs to be updated."""
|
||||
current_time = time.time()
|
||||
|
||||
# Only check at specified interval
|
||||
if current_time - self.last_check < self.interval:
|
||||
return
|
||||
|
||||
self.last_check = current_time
|
||||
|
||||
# Find and apply active schedule
|
||||
active_schedule = self._find_active_schedule()
|
||||
if active_schedule:
|
||||
self._apply_schedule(active_schedule)
|
||||
|
||||
def reload_config(self, new_config):
|
||||
"""Reload configuration (called when settings are updated via web)."""
|
||||
self.config = new_config
|
||||
self.last_applied_schedule = None # Force re-application
|
||||
print("Schedule configuration reloaded")
|
||||
Loading…
x
Reference in New Issue
Block a user