feat: Implement temporary hold management with config integration and improved notifications
fixes #19
This commit is contained in:
parent
b6aae121bb
commit
9da21f7c89
@ -20,7 +20,6 @@ class ScheduleMonitor:
|
|||||||
self.last_check = 0
|
self.last_check = 0
|
||||||
self.current_schedule = None
|
self.current_schedule = None
|
||||||
self.last_applied_schedule = None
|
self.last_applied_schedule = None
|
||||||
self.temp_hold_start_time = None # When temporary hold was activated
|
|
||||||
self.temp_hold_duration = config.get('temp_hold_duration', 3600) # Use config value, default 1 hour
|
self.temp_hold_duration = config.get('temp_hold_duration', 3600) # Use config value, default 1 hour
|
||||||
|
|
||||||
def should_run(self):
|
def should_run(self):
|
||||||
@ -137,40 +136,33 @@ class ScheduleMonitor:
|
|||||||
|
|
||||||
# ===== START: Check if temporary hold has expired =====
|
# ===== START: Check if temporary hold has expired =====
|
||||||
if not self.config.get('schedule_enabled', False) and not self.config.get('permanent_hold', False):
|
if not self.config.get('schedule_enabled', False) and not self.config.get('permanent_hold', False):
|
||||||
# We're in temporary hold mode
|
# In temporary hold mode - check if timer expired
|
||||||
if self.temp_hold_start_time is None:
|
temp_hold_start = self.config.get('temp_hold_start_time') # <-- READ FROM CONFIG NOW
|
||||||
# Just entered hold mode, record start time
|
|
||||||
self.temp_hold_start_time = time.time()
|
if temp_hold_start is not None:
|
||||||
print("⏸️ Temporary hold started - will auto-resume in {} minutes".format(
|
elapsed = time.time() - temp_hold_start
|
||||||
self.temp_hold_duration // 60
|
|
||||||
))
|
|
||||||
else:
|
|
||||||
# Check if hold has expired
|
|
||||||
elapsed = time.time() - self.temp_hold_start_time
|
|
||||||
if elapsed >= self.temp_hold_duration:
|
if elapsed >= self.temp_hold_duration:
|
||||||
# Hold expired, resume schedules
|
# Timer expired - resume automatic scheduling
|
||||||
print("⏰ Temporary hold expired - resuming automatic mode")
|
print("⏰ Temporary hold expired - resuming schedule")
|
||||||
self.config['schedule_enabled'] = True
|
self.config['schedule_enabled'] = True
|
||||||
self.config['permanent_hold'] = False
|
self.config['temp_hold_start_time'] = None
|
||||||
self.temp_hold_start_time = None
|
|
||||||
|
|
||||||
# Save updated config
|
# Save updated config
|
||||||
try:
|
try:
|
||||||
import json
|
import json
|
||||||
with open('config.json', 'w') as f:
|
with open('config.json', 'w') as f:
|
||||||
json.dump(self.config, f)
|
json.dump(self.config, f)
|
||||||
except:
|
print("✅ Config updated - automatic mode resumed")
|
||||||
pass
|
except Exception as e:
|
||||||
|
print("⚠️ Could not save config: {}".format(e))
|
||||||
|
|
||||||
# Send Discord notification
|
# Notify user
|
||||||
try:
|
try:
|
||||||
from scripts.discord_webhook import send_discord_message
|
from scripts.discord_webhook import send_discord_message
|
||||||
send_discord_message("⏰ Temporary hold expired - Automatic mode resumed")
|
send_discord_message("⏰ Temporary hold expired - Schedule resumed automatically")
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
else:
|
|
||||||
# Not in temporary hold, reset timer
|
|
||||||
self.temp_hold_start_time = None
|
|
||||||
# ===== END: Check if temporary hold has expired =====
|
# ===== END: Check if temporary hold has expired =====
|
||||||
|
|
||||||
# Find and apply active schedule
|
# Find and apply active schedule
|
||||||
|
|||||||
@ -551,31 +551,37 @@ class TempWebServer:
|
|||||||
print("Heater swing updated to {}°F".format(params['heater_swing']))
|
print("Heater swing updated to {}°F".format(params['heater_swing']))
|
||||||
# ===== END: Update Heater Settings =====
|
# ===== END: Update Heater Settings =====
|
||||||
|
|
||||||
# ===== START: Disable scheduling ONLY if user manually changed temps =====
|
# ===== START: ALWAYS enter temporary hold when Save Settings is clicked =====
|
||||||
# Check if this is a user-initiated change (from web form)
|
# User clicked "Save Settings" - enter temporary hold mode
|
||||||
# If AC or heater targets were changed, it's a manual override
|
|
||||||
user_changed_temps = (
|
|
||||||
('ac_target' in params and params['ac_target'] != config.get('ac_target')) or
|
|
||||||
('heater_target' in params and params['heater_target'] != config.get('heater_target'))
|
|
||||||
)
|
|
||||||
|
|
||||||
if user_changed_temps and config.get('schedule_enabled'):
|
|
||||||
config['schedule_enabled'] = False
|
config['schedule_enabled'] = False
|
||||||
config['permanent_hold'] = False # Temporary hold
|
config['permanent_hold'] = False
|
||||||
print("⏸️ Schedule disabled - entering TEMPORARY HOLD mode (user override)")
|
config['temp_hold_start_time'] = time.time() # SET START TIME
|
||||||
|
print("⏸️ Temporary hold activated - Manual override")
|
||||||
|
|
||||||
# Reload schedule monitor to disable it
|
# Reload schedule monitor to disable it
|
||||||
if schedule_monitor:
|
if schedule_monitor:
|
||||||
schedule_monitor.reload_config(config)
|
schedule_monitor.reload_config(config)
|
||||||
# ===== END: Disable scheduling ONLY if user manually changed temps =====
|
# ===== END: ALWAYS enter temporary hold =====
|
||||||
|
|
||||||
|
|
||||||
# ===== START: Save settings to file =====
|
# ===== START: Save settings to file =====
|
||||||
if self._save_config_to_file(config):
|
if self._save_config_to_file(config):
|
||||||
print("Settings persisted to disk")
|
print("Settings persisted to disk")
|
||||||
|
|
||||||
|
# ===== RELOAD config into memory immediately =====
|
||||||
|
try:
|
||||||
|
with open('config.json', 'r') as f:
|
||||||
|
updated_config = json.load(f)
|
||||||
|
# Update the passed-in config dict (updates reference, not copy)
|
||||||
|
config.clear()
|
||||||
|
config.update(updated_config)
|
||||||
|
print("✅ Config reloaded into memory")
|
||||||
|
except Exception as e:
|
||||||
|
print("⚠️ Warning: Could not reload config: {}".format(e))
|
||||||
|
# ===== END: Reload config =====
|
||||||
# ===== END: Save settings to file =====
|
# ===== END: Save settings to file =====
|
||||||
|
|
||||||
# ===== START: Send Discord notification ONLY if user changed =====
|
# ===== START: Send Discord notification =====
|
||||||
if user_changed_temps:
|
|
||||||
try:
|
try:
|
||||||
from scripts.discord_webhook import send_discord_message
|
from scripts.discord_webhook import send_discord_message
|
||||||
ac_target_str = str(params.get('ac_target', 'N/A'))
|
ac_target_str = str(params.get('ac_target', 'N/A'))
|
||||||
@ -583,7 +589,7 @@ class TempWebServer:
|
|||||||
heater_target_str = str(params.get('heater_target', 'N/A'))
|
heater_target_str = str(params.get('heater_target', 'N/A'))
|
||||||
heater_swing_str = str(params.get('heater_swing', 'N/A'))
|
heater_swing_str = str(params.get('heater_swing', 'N/A'))
|
||||||
|
|
||||||
message = "⏸️ HOLD Mode - Manual override: AC: {}F +/- {}F | Heater: {}F +/- {}F (Schedule disabled)".format(
|
message = "⏸️ TEMPORARY HOLD - AC: {}F ± {}F | Heater: {}F ± {}F (1 hour)".format(
|
||||||
ac_target_str, ac_swing_str, heater_target_str, heater_swing_str
|
ac_target_str, ac_swing_str, heater_target_str, heater_swing_str
|
||||||
)
|
)
|
||||||
send_discord_message(message)
|
send_discord_message(message)
|
||||||
@ -712,13 +718,17 @@ class TempWebServer:
|
|||||||
# Calculate remaining time for temporary hold
|
# Calculate remaining time for temporary hold
|
||||||
temp_hold_remaining = ""
|
temp_hold_remaining = ""
|
||||||
if not config.get('schedule_enabled', False) and not config.get('permanent_hold', False):
|
if not config.get('schedule_enabled', False) and not config.get('permanent_hold', False):
|
||||||
# In temporary hold - check if we have schedule_monitor with timer
|
# In temporary hold - check timer from CONFIG (not schedule_monitor)
|
||||||
if schedule_monitor and hasattr(schedule_monitor, 'temp_hold_start_time'):
|
temp_hold_start = config.get('temp_hold_start_time') # READ FROM CONFIG
|
||||||
if schedule_monitor.temp_hold_start_time is not None:
|
|
||||||
|
if temp_hold_start is not None:
|
||||||
|
# Get hold duration from config
|
||||||
|
temp_hold_duration = config.get('temp_hold_duration', 3600)
|
||||||
|
|
||||||
# Calculate elapsed time
|
# Calculate elapsed time
|
||||||
elapsed = time.time() - schedule_monitor.temp_hold_start_time
|
elapsed = time.time() - temp_hold_start
|
||||||
# Calculate remaining time
|
# Calculate remaining time
|
||||||
remaining = schedule_monitor.temp_hold_duration - elapsed
|
remaining = temp_hold_duration - elapsed
|
||||||
|
|
||||||
if remaining > 0:
|
if remaining > 0:
|
||||||
# Convert to minutes
|
# Convert to minutes
|
||||||
@ -752,8 +762,7 @@ class TempWebServer:
|
|||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
elif not config.get('schedule_enabled', False) and has_schedules:
|
elif not config.get('schedule_enabled', False) and has_schedules:
|
||||||
# TEMPORARY HOLD - Show countdown timer if available
|
# TEMPORARY HOLD - Show countdown timer
|
||||||
# Note: We'll need to accept schedule_monitor as parameter to access timer
|
|
||||||
hold_banner = """
|
hold_banner = """
|
||||||
<div style="background: linear-gradient(135deg, #f39c12, #e67e22); color: white; padding: 15px; border-radius: 10px; text-align: center; font-weight: bold; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.2); animation: fadeIn 0.5s;">
|
<div style="background: linear-gradient(135deg, #f39c12, #e67e22); color: white; padding: 15px; border-radius: 10px; text-align: center; font-weight: bold; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.2); animation: fadeIn 0.5s;">
|
||||||
⏸️ TEMPORARY HOLD - Manual override active{remaining}
|
⏸️ TEMPORARY HOLD - Manual override active{remaining}
|
||||||
|
|||||||
2
main.py
2
main.py
@ -106,6 +106,8 @@ if 'schedule_enabled' in config:
|
|||||||
config['schedule_enabled'] = True # Always enable schedules on boot
|
config['schedule_enabled'] = True # Always enable schedules on boot
|
||||||
if 'permanent_hold' in config:
|
if 'permanent_hold' in config:
|
||||||
config['permanent_hold'] = False # Always clear permanent hold on boot
|
config['permanent_hold'] = False # Always clear permanent hold on boot
|
||||||
|
if 'temp_hold_start_time' in config:
|
||||||
|
config['temp_hold_start_time'] = None # Clear temp hold start time
|
||||||
|
|
||||||
# Save the reset config immediately
|
# Save the reset config immediately
|
||||||
try:
|
try:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user