Explorar o código

Support multiple rooms via one config entry per room

Config flow now prompts for a room name; device names are derived as
"{room name} Room State / Current / Next" rather than stored separately.
ZiB hai 4 meses
pai
achega
f8fbb2f8ae

+ 2 - 2
custom_components/room_cal_ha/button.py

@@ -6,7 +6,7 @@ from homeassistant.core import HomeAssistant
 from homeassistant.helpers.device_registry import DeviceInfo
 from homeassistant.helpers.entity_platform import AddEntitiesCallback
 
-from .const import CONF_ROOM_STATE_NAME, DEFAULT_ROOM_STATE_NAME, DOMAIN
+from .const import CONF_ROOM_NAME, DOMAIN
 from .coordinator import RoomCalCoordinator
 
 
@@ -16,7 +16,7 @@ async def async_setup_entry(
   async_add_entities: AddEntitiesCallback,
 ) -> None:
   coordinator: RoomCalCoordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"]
-  device_name = entry.data.get(CONF_ROOM_STATE_NAME, DEFAULT_ROOM_STATE_NAME)
+  device_name = f"{entry.data.get(CONF_ROOM_NAME, entry.title)} Room State"
   async_add_entities([
     ForceRefreshButton(coordinator, entry, device_name),
     PromoteFromNextButton(coordinator, entry, device_name),

+ 14 - 2
custom_components/room_cal_ha/config_flow.py

@@ -28,10 +28,10 @@ from .const import (
   CONF_CALENDAR_NAME,
   CONF_PASSWORD,
   CONF_REFRESH_INTERVAL,
+  CONF_ROOM_NAME,
   CONF_SYNC_MODE,
   CONF_USERNAME,
   DEFAULT_REFRESH_INTERVAL,
-  DEFAULT_ROOM_STATE_NAME,
   DOMAIN,
   SYNC_MODE_API,
   SYNC_MODE_CALDAV,
@@ -45,7 +45,19 @@ class RoomCalConfigFlow(ConfigFlow, domain=DOMAIN):
   async def async_step_user(
     self, user_input: dict[str, Any] | None = None
   ) -> ConfigFlowResult:
-    return self.async_create_entry(title=DEFAULT_ROOM_STATE_NAME, data={})
+    if user_input is not None:
+      room_name = user_input[CONF_ROOM_NAME].strip()
+      return self.async_create_entry(
+        title=room_name,
+        data={CONF_ROOM_NAME: room_name},
+      )
+
+    return self.async_show_form(
+      step_id="user",
+      data_schema=vol.Schema({
+        vol.Required(CONF_ROOM_NAME): str,
+      }),
+    )
 
   async def async_step_reauth(
     self, entry_data: dict[str, Any]

+ 1 - 8
custom_components/room_cal_ha/const.py

@@ -3,9 +3,7 @@ from __future__ import annotations
 DOMAIN = "room_cal_ha"
 
 # entry.data keys
-CONF_ROOM_STATE_NAME = "room_state_name"
-CONF_CURRENT_NAME = "current_name"
-CONF_NEXT_NAME = "next_name"
+CONF_ROOM_NAME = "room_name"
 CONF_USERNAME = "username"
 CONF_PASSWORD = "password"
 
@@ -40,11 +38,6 @@ SENSOR_KEYS: list[str] = [
   "door_code",
 ]
 
-# Default device names (suggested in config flow)
-DEFAULT_ROOM_STATE_NAME = "Room State"
-DEFAULT_CURRENT_NAME = "Current"
-DEFAULT_NEXT_NAME = "Next"
-
 # Update interval
 DEFAULT_REFRESH_INTERVAL = 15
 

+ 7 - 11
custom_components/room_cal_ha/sensor.py

@@ -11,13 +11,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
 from homeassistant.helpers.update_coordinator import CoordinatorEntity
 
 from .const import (
-  CONF_CURRENT_NAME,
-  CONF_NEXT_NAME,
-  CONF_ROOM_STATE_NAME,
+  CONF_ROOM_NAME,
   CONF_SYNC_MODE,
-  DEFAULT_CURRENT_NAME,
-  DEFAULT_NEXT_NAME,
-  DEFAULT_ROOM_STATE_NAME,
   DOMAIN,
   STORE_CURRENT,
   STORE_NEXT,
@@ -34,12 +29,14 @@ async def async_setup_entry(
 ) -> None:
   coordinator: RoomCalCoordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"]
 
-  current_name = entry.data.get(CONF_CURRENT_NAME, DEFAULT_CURRENT_NAME)
-  next_name = entry.data.get(CONF_NEXT_NAME, DEFAULT_NEXT_NAME)
+  room_name = entry.data.get(CONF_ROOM_NAME, entry.title)
 
   entities: list[SensorEntity] = []
 
-  for slot, device_name in ((STORE_CURRENT, current_name), (STORE_NEXT, next_name)):
+  for slot, device_name in (
+    (STORE_CURRENT, f"{room_name} Current"),
+    (STORE_NEXT, f"{room_name} Next"),
+  ):
     device_id = f"{entry.entry_id}_{slot}"
     device_info = DeviceInfo(
       identifiers={(DOMAIN, device_id)},
@@ -58,10 +55,9 @@ async def async_setup_entry(
     ]
 
   if entry.options.get(CONF_SYNC_MODE) == SYNC_MODE_API:
-    room_state_name = entry.data.get(CONF_ROOM_STATE_NAME, DEFAULT_ROOM_STATE_NAME)
     room_state_device = DeviceInfo(
       identifiers={(DOMAIN, entry.entry_id)},
-      name=room_state_name,
+      name=f"{room_name} Room State",
     )
     entities += [
       ApiStatusSensor(coordinator, entry, room_state_device),

+ 7 - 0
custom_components/room_cal_ha/strings.json

@@ -1,6 +1,13 @@
 {
   "config": {
     "step": {
+      "user": {
+        "title": "Add Room",
+        "description": "Enter a name for this room. Each room is a separate integration entry.",
+        "data": {
+          "room_name": "Room Name"
+        }
+      },
       "reauth_confirm": {
         "title": "Re-authenticate CalDAV",
         "description": "Enter your CalDAV credentials to restore the connection.",

+ 2 - 2
custom_components/room_cal_ha/switch.py

@@ -7,7 +7,7 @@ from homeassistant.helpers.device_registry import DeviceInfo
 from homeassistant.helpers.entity_platform import AddEntitiesCallback
 from homeassistant.helpers.restore_state import RestoreEntity
 
-from .const import CONF_ROOM_STATE_NAME, DEFAULT_ROOM_STATE_NAME, DOMAIN
+from .const import CONF_ROOM_NAME, DOMAIN
 from .coordinator import RoomCalCoordinator
 
 
@@ -17,7 +17,7 @@ async def async_setup_entry(
   async_add_entities: AddEntitiesCallback,
 ) -> None:
   coordinator: RoomCalCoordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"]
-  device_name = entry.data.get(CONF_ROOM_STATE_NAME, DEFAULT_ROOM_STATE_NAME)
+  device_name = f"{entry.data.get(CONF_ROOM_NAME, entry.title)} Room State"
 
   guest_mode = GuestModeSwitch(coordinator, entry, device_name)
   mode_sync = ModeSyncSwitch(coordinator, entry, device_name)

+ 7 - 0
custom_components/room_cal_ha/translations/en.json

@@ -1,6 +1,13 @@
 {
   "config": {
     "step": {
+      "user": {
+        "title": "Add Room",
+        "description": "Enter a name for this room. Each room is a separate integration entry.",
+        "data": {
+          "room_name": "Room Name"
+        }
+      },
       "reauth_confirm": {
         "title": "Re-authenticate CalDAV",
         "description": "Enter your CalDAV credentials to restore the connection.",

+ 3 - 8
tests/conftest.py

@@ -2,9 +2,7 @@ import pytest
 from pytest_homeassistant_custom_component.common import MockConfigEntry
 
 from custom_components.room_cal_ha.const import (
-  CONF_CURRENT_NAME,
-  CONF_NEXT_NAME,
-  CONF_ROOM_STATE_NAME,
+  CONF_ROOM_NAME,
   CONF_SYNC_MODE,
   DOMAIN,
   SYNC_MODE_MANUAL,
@@ -20,10 +18,7 @@ def auto_enable_custom_integrations(enable_custom_integrations):
 def mock_entry():
   return MockConfigEntry(
     domain=DOMAIN,
-    data={
-      CONF_ROOM_STATE_NAME: "Room State",
-      CONF_CURRENT_NAME: "Current",
-      CONF_NEXT_NAME: "Next",
-    },
+    title="Beach House",
+    data={CONF_ROOM_NAME: "Beach House"},
     options={CONF_SYNC_MODE: SYNC_MODE_MANUAL},
   )

+ 16 - 3
tests/test_config_flow.py

@@ -12,6 +12,7 @@ from custom_components.room_cal_ha.const import (
   CONF_CALENDAR_NAME,
   CONF_PASSWORD,
   CONF_REFRESH_INTERVAL,
+  CONF_ROOM_NAME,
   CONF_SYNC_MODE,
   CONF_USERNAME,
   DEFAULT_REFRESH_INTERVAL,
@@ -26,13 +27,25 @@ from custom_components.room_cal_ha.const import (
 # Config flow — user step
 # ---------------------------------------------------------------------------
 
-async def test_user_step_creates_entry_immediately(hass: HomeAssistant):
-  """async_step_user creates an entry without showing a form."""
+async def test_user_step_shows_form(hass: HomeAssistant):
   result = await hass.config_entries.flow.async_init(
     DOMAIN, context={"source": SOURCE_USER}
   )
+  assert result["type"] == "form"
+  assert result["step_id"] == "user"
+
+
+async def test_user_step_creates_entry_with_room_name(hass: HomeAssistant):
+  result = await hass.config_entries.flow.async_init(
+    DOMAIN, context={"source": SOURCE_USER}
+  )
+  result = await hass.config_entries.flow.async_configure(
+    result["flow_id"],
+    user_input={CONF_ROOM_NAME: "Beach House"},
+  )
   assert result["type"] == "create_entry"
-  assert result["title"] == "Room State"
+  assert result["title"] == "Beach House"
+  assert result["data"][CONF_ROOM_NAME] == "Beach House"
 
 
 # ---------------------------------------------------------------------------