|
|
@@ -7,6 +7,9 @@ from datetime import datetime, timedelta
|
|
|
|
|
|
@time_trigger("cron(* * * * *)") # run every minute
|
|
|
def car_heater_minute_job():
|
|
|
+ # Static variable to track one-time schedule state across calls
|
|
|
+ if not hasattr(car_heater_minute_job, 'old_once_active'):
|
|
|
+ car_heater_minute_job.old_once_active = False
|
|
|
|
|
|
now = datetime.now()
|
|
|
|
|
|
@@ -20,7 +23,7 @@ def car_heater_minute_job():
|
|
|
preheat = 60 # safe fallback
|
|
|
log.error(f"Car heater: preheat sensor returned invalid value '{preheat_raw}'")
|
|
|
|
|
|
- after_heat = 25 # minutes after departure to keep heater on
|
|
|
+ after_heat = 30 # minutes after departure to keep heater on
|
|
|
|
|
|
|
|
|
#
|
|
|
@@ -76,8 +79,10 @@ def car_heater_minute_job():
|
|
|
#
|
|
|
# ONE-TIME SCHEDULE (any day)
|
|
|
#
|
|
|
- if in_window("input_datetime.heater_once_time", "input_boolean.heater_once_active"):
|
|
|
+ once_in_window = in_window("input_datetime.heater_once_time", "input_boolean.heater_once_active")
|
|
|
+ if once_in_window:
|
|
|
should_on = True
|
|
|
+ car_heater_minute_job.old_once_active = True
|
|
|
|
|
|
|
|
|
#
|
|
|
@@ -100,22 +105,15 @@ def car_heater_minute_job():
|
|
|
|
|
|
|
|
|
#
|
|
|
- # 5. RESET ONE-TIME DEPARTURE IF WINDOW PASSED
|
|
|
+ # 5. RESET ONE-TIME DEPARTURE AFTER WINDOW ENDS
|
|
|
#
|
|
|
if state.get("input_boolean.heater_once_active") == "on":
|
|
|
-
|
|
|
- tstr = state.get("input_datetime.heater_once_time")
|
|
|
- if tstr:
|
|
|
- try:
|
|
|
- dep_time = datetime.strptime(tstr, "%H:%M:%S").time()
|
|
|
- except (ValueError, TypeError):
|
|
|
- log.error(f"Car heater: failed to parse heater_once_time '{tstr}'")
|
|
|
- return
|
|
|
-
|
|
|
- departure = datetime.combine(now.date(), dep_time)
|
|
|
- stop = departure + timedelta(minutes=after_heat)
|
|
|
-
|
|
|
- if now > stop:
|
|
|
- log.info("Car heater: resetting one-time schedule")
|
|
|
- service.call("input_boolean", "turn_off",
|
|
|
- entity_id="input_boolean.heater_once_active")
|
|
|
+ # If we were in the window last cycle but not anymore, reset the boolean
|
|
|
+ if car_heater_minute_job.old_once_active and not once_in_window:
|
|
|
+ log.info("Car heater: resetting one-time schedule (window ended)")
|
|
|
+ service.call("input_boolean", "turn_off",
|
|
|
+ entity_id="input_boolean.heater_once_active")
|
|
|
+ car_heater_minute_job.old_once_active = False
|
|
|
+ else:
|
|
|
+ # Boolean is off, reset tracking variable
|
|
|
+ car_heater_minute_job.old_once_active = False
|