Quellcode durchsuchen

Mode sync: promote next→current at check-in, clear current at check-out

Timers now fire on next.check_in (not current.check_in) and trigger
promotion before activating guest mode. Check-out timer clears the
current store record before deactivating. Guest mode is always toggled
last so listeners see fresh sensor data on state change.
ZiB vor 4 Monaten
Ursprung
Commit
f291f93567
1 geänderte Dateien mit 28 neuen und 11 gelöschten Zeilen
  1. 28 11
      custom_components/room_cal_ha/coordinator.py

+ 28 - 11
custom_components/room_cal_ha/coordinator.py

@@ -95,7 +95,7 @@ class RoomCalCoordinator(DataUpdateCoordinator[CoordinatorData]):
     new_current = self.store.get(STORE_CURRENT) or ReservationData()
     new_next = self.store.get(STORE_NEXT) or ReservationData()
 
-    self._reschedule_mode_sync(new_current)
+    self._reschedule_mode_sync(new_current, new_next)
 
     return CoordinatorData(
       current=new_current,
@@ -160,7 +160,7 @@ class RoomCalCoordinator(DataUpdateCoordinator[CoordinatorData]):
 
     return current, nxt
 
-  def _reschedule_mode_sync(self, current: ReservationData) -> None:
+  def _reschedule_mode_sync(self, current: ReservationData, nxt: ReservationData) -> None:
     for cancel in self._mode_sync_handles:
       cancel()
     self._mode_sync_handles.clear()
@@ -170,16 +170,18 @@ class RoomCalCoordinator(DataUpdateCoordinator[CoordinatorData]):
 
     now = dt_util.now()
 
-    if current.check_in_date and current.check_in_time:
+    # At next reservation's check-in: promote next → current, then activate guest mode.
+    if nxt.check_in_date and nxt.check_in_time:
       check_in = dt_util.as_local(
-        datetime.combine(current.check_in_date, current.check_in_time)
+        datetime.combine(nxt.check_in_date, nxt.check_in_time)
       )
       delay = (check_in - now).total_seconds()
       if delay > 0:
         self._mode_sync_handles.append(
-          async_call_later(self.hass, delay, self._async_activate_guest_mode)
+          async_call_later(self.hass, delay, self._async_handle_check_in)
         )
 
+    # At current reservation's check-out: clear current, then deactivate guest mode.
     if current.check_out_date and current.check_out_time:
       check_out = dt_util.as_local(
         datetime.combine(current.check_out_date, current.check_out_time)
@@ -187,7 +189,7 @@ class RoomCalCoordinator(DataUpdateCoordinator[CoordinatorData]):
       delay = (check_out - now).total_seconds()
       if delay > 0:
         self._mode_sync_handles.append(
-          async_call_later(self.hass, delay, self._async_deactivate_guest_mode)
+          async_call_later(self.hass, delay, self._async_handle_check_out)
         )
 
   def _is_mode_sync_on(self) -> bool:
@@ -198,17 +200,32 @@ class RoomCalCoordinator(DataUpdateCoordinator[CoordinatorData]):
     return False
 
   @callback
-  def _async_activate_guest_mode(self, _now: datetime) -> None:
+  def _async_handle_check_in(self, _now: datetime) -> None:
+    self.hass.async_create_task(self._async_do_check_in())
+
+  async def _async_do_check_in(self) -> None:
+    await self.async_promote_next_to_current()
     if self._guest_mode_switch is not None:
-      self.hass.async_create_task(self._guest_mode_switch.async_turn_on())
+      await self._guest_mode_switch.async_turn_on()
 
   @callback
-  def _async_deactivate_guest_mode(self, _now: datetime) -> None:
+  def _async_handle_check_out(self, _now: datetime) -> None:
+    self.hass.async_create_task(self._async_do_check_out())
+
+  async def _async_do_check_out(self) -> None:
+    await self.store.async_set(STORE_CURRENT, None)
+    self._current_last_refresh = dt_util.utcnow()
+    self.async_set_updated_data(CoordinatorData(
+      current=ReservationData(),
+      next=self.store.get(STORE_NEXT) or ReservationData(),
+      current_last_refresh=self._current_last_refresh,
+      next_last_refresh=self._next_last_refresh,
+    ))
     if self._guest_mode_switch is not None:
-      self.hass.async_create_task(self._guest_mode_switch.async_turn_off())
+      await self._guest_mode_switch.async_turn_off()
 
   async def async_promote_next_to_current(self) -> None:
-    """Copy the Next slot into Current and notify listeners."""
+    """Copy the Next slot into Current and notify listeners. Next is left unchanged."""
     next_data = self.store.get(STORE_NEXT) or ReservationData()
     await self.store.async_set(STORE_CURRENT, next_data)
     self._current_last_refresh = dt_util.utcnow()