mirror of
https://github.com/home-assistant/core.git
synced 2026-05-26 10:45:11 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1d58d51e51 |
@@ -31,6 +31,7 @@ from .const import ( # noqa: F401
|
||||
ATTR_LOCATION_NAME,
|
||||
ATTR_MAC,
|
||||
ATTR_SOURCE_TYPE,
|
||||
CONF_ASSOCIATED_ZONE,
|
||||
CONF_CONSIDER_HOME,
|
||||
CONF_NEW_DEVICE_DEFAULTS,
|
||||
CONF_SCAN_INTERVAL,
|
||||
|
||||
@@ -17,8 +17,19 @@ from homeassistant.const import (
|
||||
STATE_NOT_HOME,
|
||||
EntityCategory,
|
||||
)
|
||||
from homeassistant.core import Event, HomeAssistant, State, callback
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.core import (
|
||||
CALLBACK_TYPE,
|
||||
Event,
|
||||
EventStateChangedData,
|
||||
HomeAssistant,
|
||||
State,
|
||||
callback,
|
||||
)
|
||||
from homeassistant.helpers import (
|
||||
device_registry as dr,
|
||||
entity_registry as er,
|
||||
issue_registry as ir,
|
||||
)
|
||||
from homeassistant.helpers.device_registry import (
|
||||
DeviceInfo,
|
||||
EventDeviceRegistryUpdatedData,
|
||||
@@ -27,6 +38,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.helpers.entity import Entity, EntityDescription
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.entity_platform import EntityPlatform
|
||||
from homeassistant.helpers.event import async_track_state_change_event
|
||||
from homeassistant.helpers.typing import StateType
|
||||
from homeassistant.util.hass_dict import HassKey
|
||||
|
||||
@@ -36,6 +48,7 @@ from .const import (
|
||||
ATTR_IP,
|
||||
ATTR_MAC,
|
||||
ATTR_SOURCE_TYPE,
|
||||
CONF_ASSOCIATED_ZONE,
|
||||
CONNECTED_DEVICE_REGISTERED,
|
||||
DOMAIN,
|
||||
LOGGER,
|
||||
@@ -343,14 +356,116 @@ class BaseScannerEntity(BaseTrackerEntity):
|
||||
addresses being used to identify the device.
|
||||
"""
|
||||
|
||||
_scanner_option_associated_zone: str = zone.ENTITY_ID_HOME
|
||||
_scanner_option_associated_zone_unsub: CALLBACK_TYPE | None = None
|
||||
|
||||
async def async_internal_added_to_hass(self) -> None:
|
||||
"""Call when the scanner entity is added to hass."""
|
||||
await super().async_internal_added_to_hass()
|
||||
if not self.registry_entry:
|
||||
return
|
||||
self._async_read_entity_options()
|
||||
|
||||
async def async_internal_will_remove_from_hass(self) -> None:
|
||||
"""Call when the scanner entity is about to be removed from hass."""
|
||||
if self._scanner_option_associated_zone_unsub is not None:
|
||||
self._scanner_option_associated_zone_unsub()
|
||||
self._scanner_option_associated_zone_unsub = None
|
||||
self._async_clear_associated_zone_issue()
|
||||
await super().async_internal_will_remove_from_hass()
|
||||
|
||||
@callback
|
||||
def async_registry_entry_updated(self) -> None:
|
||||
"""Run when the entity registry entry has been updated."""
|
||||
self._async_read_entity_options()
|
||||
|
||||
@callback
|
||||
def _async_read_entity_options(self) -> None:
|
||||
"""Read entity options from the entity registry.
|
||||
|
||||
Called when the entity registry entry has been updated and before the
|
||||
scanner entity is added to the state machine.
|
||||
"""
|
||||
assert self.registry_entry
|
||||
if (scanner_options := self.registry_entry.options.get(DOMAIN)) and (
|
||||
associated_zone := scanner_options.get(CONF_ASSOCIATED_ZONE)
|
||||
):
|
||||
new_zone = associated_zone
|
||||
else:
|
||||
new_zone = zone.ENTITY_ID_HOME
|
||||
|
||||
if new_zone == self._scanner_option_associated_zone:
|
||||
return
|
||||
|
||||
# Tear down tracking for the previous zone.
|
||||
if self._scanner_option_associated_zone_unsub is not None:
|
||||
self._scanner_option_associated_zone_unsub()
|
||||
self._scanner_option_associated_zone_unsub = None
|
||||
self._async_clear_associated_zone_issue()
|
||||
|
||||
self._scanner_option_associated_zone = new_zone
|
||||
|
||||
# zone.home is always present so no tracking or issue handling needed.
|
||||
if new_zone == zone.ENTITY_ID_HOME:
|
||||
return
|
||||
|
||||
self._scanner_option_associated_zone_unsub = async_track_state_change_event(
|
||||
self.hass, new_zone, self._async_associated_zone_state_changed
|
||||
)
|
||||
if self.hass.states.get(new_zone) is None:
|
||||
self._async_create_associated_zone_issue()
|
||||
|
||||
@callback
|
||||
def _async_associated_zone_state_changed(
|
||||
self, event: Event[EventStateChangedData]
|
||||
) -> None:
|
||||
"""Open or clear the repair issue when the associated zone appears or disappears."""
|
||||
if event.data["new_state"] is None:
|
||||
self._async_create_associated_zone_issue()
|
||||
else:
|
||||
self._async_clear_associated_zone_issue()
|
||||
self.async_write_ha_state()
|
||||
|
||||
@callback
|
||||
def _async_create_associated_zone_issue(self) -> None:
|
||||
"""Create a repair issue prompting the user to reconfigure the scanner."""
|
||||
ir.async_create_issue(
|
||||
self.hass,
|
||||
DOMAIN,
|
||||
self._associated_zone_issue_id,
|
||||
is_fixable=False,
|
||||
severity=ir.IssueSeverity.WARNING,
|
||||
translation_key="associated_zone_missing",
|
||||
translation_placeholders={
|
||||
"entity_id": self.entity_id,
|
||||
"zone": self._scanner_option_associated_zone,
|
||||
},
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_clear_associated_zone_issue(self) -> None:
|
||||
"""Clear the associated-zone-missing repair issue if it exists."""
|
||||
ir.async_delete_issue(self.hass, DOMAIN, self._associated_zone_issue_id)
|
||||
|
||||
@property
|
||||
def _associated_zone_issue_id(self) -> str:
|
||||
"""Return the issue id for the associated-zone-missing repair."""
|
||||
return f"associated_zone_missing_{self.entity_id}"
|
||||
|
||||
@property
|
||||
def state(self) -> str | None:
|
||||
"""Return the state of the device."""
|
||||
if self.is_connected is None:
|
||||
return None
|
||||
if self.is_connected:
|
||||
if not self.is_connected:
|
||||
return STATE_NOT_HOME
|
||||
associated_zone = self._scanner_option_associated_zone
|
||||
if associated_zone == zone.ENTITY_ID_HOME:
|
||||
return STATE_HOME
|
||||
return STATE_NOT_HOME
|
||||
if zone_state := self.hass.states.get(associated_zone):
|
||||
return zone_state.name
|
||||
# Configured zone has been removed; state is unknown.
|
||||
return None
|
||||
|
||||
@property
|
||||
def is_connected(self) -> bool | None:
|
||||
@@ -367,9 +482,18 @@ class BaseScannerEntity(BaseTrackerEntity):
|
||||
if not self.is_connected:
|
||||
return attr
|
||||
|
||||
associated_zone = self._scanner_option_associated_zone
|
||||
# If the configured zone has been removed, in_zones stays empty so the
|
||||
# attribute does not claim membership in a zone that no longer exists.
|
||||
if (
|
||||
associated_zone != zone.ENTITY_ID_HOME
|
||||
and self.hass.states.get(associated_zone) is None
|
||||
):
|
||||
return attr
|
||||
|
||||
attr[ATTR_IN_ZONES] = [
|
||||
zone.ENTITY_ID_HOME,
|
||||
*zone.async_get_enclosing_zones(self.hass, zone.ENTITY_ID_HOME),
|
||||
associated_zone,
|
||||
*zone.async_get_enclosing_zones(self.hass, associated_zone),
|
||||
]
|
||||
|
||||
return attr
|
||||
|
||||
@@ -36,6 +36,8 @@ DEFAULT_CONSIDER_HOME: Final = timedelta(seconds=180)
|
||||
|
||||
CONF_NEW_DEVICE_DEFAULTS: Final = "new_device_defaults"
|
||||
|
||||
CONF_ASSOCIATED_ZONE: Final = "associated_zone"
|
||||
|
||||
ATTR_ATTRIBUTES: Final = "attributes"
|
||||
ATTR_BATTERY: Final = "battery"
|
||||
ATTR_DEV_ID: Final = "dev_id"
|
||||
|
||||
@@ -44,6 +44,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"associated_zone_missing": {
|
||||
"description": "The scanner entity `{entity_id}` is associated with the zone `{zone}`, but that zone has been removed.\n\nTo fix this, reconfigure the scanner to use a different zone or recreate the missing zone.",
|
||||
"title": "Scanner is associated with a removed zone"
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"see": {
|
||||
"description": "Manually update the records of a seen legacy device tracker in the known_devices.yaml file.",
|
||||
|
||||
@@ -11,6 +11,7 @@ from homeassistant.components.device_tracker import (
|
||||
ATTR_IP,
|
||||
ATTR_MAC,
|
||||
ATTR_SOURCE_TYPE,
|
||||
CONF_ASSOCIATED_ZONE,
|
||||
DOMAIN,
|
||||
SourceType,
|
||||
)
|
||||
@@ -35,7 +36,11 @@ from homeassistant.const import (
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.helpers import (
|
||||
device_registry as dr,
|
||||
entity_registry as er,
|
||||
issue_registry as ir,
|
||||
)
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
@@ -893,6 +898,322 @@ async def test_base_scanner_entity_in_zones_when_connected(
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("unique_id", ["unique_scanner"])
|
||||
async def test_base_scanner_entity_associated_zone_option(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
entity_id: str,
|
||||
base_scanner_entity: MockBaseScannerEntity,
|
||||
) -> None:
|
||||
"""Test the associated_zone entity option overrides which zone in_zones reports.
|
||||
|
||||
The scanner reports being connected to a non-default zone; state and in_zones
|
||||
must follow the configured zone, and a zone enclosing the configured one is
|
||||
included in in_zones too.
|
||||
"""
|
||||
hass.states.async_set(
|
||||
"zone.home",
|
||||
"0",
|
||||
{ATTR_LATITUDE: 50.0, ATTR_LONGITUDE: 60.0, ATTR_RADIUS: 1000},
|
||||
)
|
||||
hass.states.async_set(
|
||||
"zone.kitchen",
|
||||
"0",
|
||||
{ATTR_LATITUDE: 50.0, ATTR_LONGITUDE: 60.0, ATTR_RADIUS: 50},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
base_scanner_entity._connected = True
|
||||
|
||||
config_entry = await create_mock_platform(hass, config_entry, [base_scanner_entity])
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
# Default: no option set -> associated with zone.home.
|
||||
entity_state = hass.states.get(entity_id)
|
||||
assert entity_state
|
||||
assert entity_state.state == STATE_HOME
|
||||
assert entity_state.attributes[ATTR_IN_ZONES] == ["zone.home"]
|
||||
|
||||
# Set the option -> associated_zone replaces zone.home; zone.home now shows
|
||||
# up via the enclosing-zones lookup.
|
||||
entity_registry.async_update_entity_options(
|
||||
entity_id,
|
||||
DOMAIN,
|
||||
{CONF_ASSOCIATED_ZONE: "zone.kitchen"},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert base_scanner_entity._scanner_option_associated_zone == "zone.kitchen"
|
||||
|
||||
entity_state = hass.states.get(entity_id)
|
||||
assert entity_state
|
||||
# zone.kitchen is the configured zone -> state is the zone's name.
|
||||
assert entity_state.state == "kitchen"
|
||||
assert entity_state.attributes[ATTR_IN_ZONES] == ["zone.kitchen", "zone.home"]
|
||||
|
||||
# Clearing the option falls back to zone.home.
|
||||
entity_registry.async_update_entity_options(entity_id, DOMAIN, None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert base_scanner_entity._scanner_option_associated_zone == "zone.home"
|
||||
|
||||
entity_state = hass.states.get(entity_id)
|
||||
assert entity_state
|
||||
assert entity_state.state == STATE_HOME
|
||||
assert entity_state.attributes[ATTR_IN_ZONES] == ["zone.home"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("unique_id", ["unique_scanner"])
|
||||
async def test_base_scanner_entity_associated_zone_removed_after_set(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
entity_id: str,
|
||||
base_scanner_entity: MockBaseScannerEntity,
|
||||
) -> None:
|
||||
"""Test scanner state and repair issue when associated zone is removed.
|
||||
|
||||
When the user picks a zone via the associated_zone option and then deletes
|
||||
that zone, the scanner falls back to ``state == "unknown"`` and a repair
|
||||
issue is opened prompting the user to reconfigure.
|
||||
"""
|
||||
hass.states.async_set(
|
||||
"zone.home",
|
||||
"0",
|
||||
{ATTR_LATITUDE: 50.0, ATTR_LONGITUDE: 60.0, ATTR_RADIUS: 1000},
|
||||
)
|
||||
hass.states.async_set(
|
||||
"zone.kitchen",
|
||||
"0",
|
||||
{ATTR_LATITUDE: 50.0, ATTR_LONGITUDE: 60.0, ATTR_RADIUS: 50},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
base_scanner_entity._connected = True
|
||||
|
||||
config_entry = await create_mock_platform(hass, config_entry, [base_scanner_entity])
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
entity_registry.async_update_entity_options(
|
||||
entity_id,
|
||||
DOMAIN,
|
||||
{CONF_ASSOCIATED_ZONE: "zone.kitchen"},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Sanity check before removal.
|
||||
entity_state = hass.states.get(entity_id)
|
||||
assert entity_state
|
||||
assert entity_state.state == "kitchen"
|
||||
assert entity_state.attributes[ATTR_IN_ZONES] == ["zone.kitchen", "zone.home"]
|
||||
issue_id = f"associated_zone_missing_{entity_id}"
|
||||
assert issue_registry.async_get_issue(DOMAIN, issue_id) is None
|
||||
|
||||
# Remove the associated zone.
|
||||
hass.states.async_remove("zone.kitchen")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_state = hass.states.get(entity_id)
|
||||
assert entity_state
|
||||
assert entity_state.state == STATE_UNKNOWN
|
||||
assert entity_state.attributes[ATTR_IN_ZONES] == []
|
||||
issue = issue_registry.async_get_issue(DOMAIN, issue_id)
|
||||
assert issue is not None
|
||||
assert issue.severity is ir.IssueSeverity.WARNING
|
||||
assert issue.translation_key == "associated_zone_missing"
|
||||
assert issue.translation_placeholders == {
|
||||
"entity_id": entity_id,
|
||||
"zone": "zone.kitchen",
|
||||
}
|
||||
|
||||
# Restore the zone -> issue is cleared, state recovers.
|
||||
hass.states.async_set(
|
||||
"zone.kitchen",
|
||||
"0",
|
||||
{ATTR_LATITUDE: 50.0, ATTR_LONGITUDE: 60.0, ATTR_RADIUS: 50},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_state = hass.states.get(entity_id)
|
||||
assert entity_state
|
||||
assert entity_state.state == "kitchen"
|
||||
assert entity_state.attributes[ATTR_IN_ZONES] == ["zone.kitchen", "zone.home"]
|
||||
assert issue_registry.async_get_issue(DOMAIN, issue_id) is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("unique_id", ["unique_scanner"])
|
||||
async def test_base_scanner_entity_associated_zone_missing_at_setup(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
entity_id: str,
|
||||
base_scanner_entity: MockBaseScannerEntity,
|
||||
) -> None:
|
||||
"""Test repair issue is created when the configured zone is missing at setup."""
|
||||
hass.states.async_set(
|
||||
"zone.home",
|
||||
"0",
|
||||
{ATTR_LATITUDE: 50.0, ATTR_LONGITUDE: 60.0, ATTR_RADIUS: 1000},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Pre-register the entity option pointing at a zone that does not exist.
|
||||
entity_registry.async_get_or_create(
|
||||
DOMAIN,
|
||||
TEST_DOMAIN,
|
||||
base_scanner_entity.unique_id,
|
||||
suggested_object_id="entity1",
|
||||
)
|
||||
entity_registry.async_update_entity_options(
|
||||
entity_id,
|
||||
DOMAIN,
|
||||
{CONF_ASSOCIATED_ZONE: "zone.never_existed"},
|
||||
)
|
||||
|
||||
base_scanner_entity._connected = True
|
||||
config_entry = await create_mock_platform(hass, config_entry, [base_scanner_entity])
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
entity_state = hass.states.get(entity_id)
|
||||
assert entity_state
|
||||
assert entity_state.state == STATE_UNKNOWN
|
||||
assert entity_state.attributes[ATTR_IN_ZONES] == []
|
||||
issue_id = f"associated_zone_missing_{entity_id}"
|
||||
issue = issue_registry.async_get_issue(DOMAIN, issue_id)
|
||||
assert issue is not None
|
||||
assert issue.translation_placeholders == {
|
||||
"entity_id": entity_id,
|
||||
"zone": "zone.never_existed",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("unique_id", ["unique_scanner"])
|
||||
async def test_base_scanner_entity_associated_zone_issue_cleared_on_option_change(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
entity_id: str,
|
||||
base_scanner_entity: MockBaseScannerEntity,
|
||||
) -> None:
|
||||
"""Test the repair issue is cleared when the user clears the option."""
|
||||
hass.states.async_set(
|
||||
"zone.home",
|
||||
"0",
|
||||
{ATTR_LATITUDE: 50.0, ATTR_LONGITUDE: 60.0, ATTR_RADIUS: 1000},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
base_scanner_entity._connected = True
|
||||
config_entry = await create_mock_platform(hass, config_entry, [base_scanner_entity])
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
entity_registry.async_update_entity_options(
|
||||
entity_id,
|
||||
DOMAIN,
|
||||
{CONF_ASSOCIATED_ZONE: "zone.never_existed"},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue_id = f"associated_zone_missing_{entity_id}"
|
||||
assert issue_registry.async_get_issue(DOMAIN, issue_id) is not None
|
||||
|
||||
# Clearing the option restores the default and clears the repair issue.
|
||||
entity_registry.async_update_entity_options(entity_id, DOMAIN, None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert issue_registry.async_get_issue(DOMAIN, issue_id) is None
|
||||
entity_state = hass.states.get(entity_id)
|
||||
assert entity_state
|
||||
assert entity_state.state == STATE_HOME
|
||||
|
||||
|
||||
@pytest.mark.parametrize("unique_id", ["unique_scanner"])
|
||||
async def test_base_scanner_entity_associated_zone_issue_cleared_on_unload(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
entity_id: str,
|
||||
base_scanner_entity: MockBaseScannerEntity,
|
||||
) -> None:
|
||||
"""Test the repair issue is cleared when the entity is removed from hass."""
|
||||
hass.states.async_set(
|
||||
"zone.home",
|
||||
"0",
|
||||
{ATTR_LATITUDE: 50.0, ATTR_LONGITUDE: 60.0, ATTR_RADIUS: 1000},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
base_scanner_entity._connected = True
|
||||
config_entry = await create_mock_platform(hass, config_entry, [base_scanner_entity])
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
entity_registry.async_update_entity_options(
|
||||
entity_id,
|
||||
DOMAIN,
|
||||
{CONF_ASSOCIATED_ZONE: "zone.never_existed"},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue_id = f"associated_zone_missing_{entity_id}"
|
||||
assert issue_registry.async_get_issue(DOMAIN, issue_id) is not None
|
||||
|
||||
assert await hass.config_entries.async_unload(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert issue_registry.async_get_issue(DOMAIN, issue_id) is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("unique_id", ["unique_scanner"])
|
||||
async def test_base_scanner_entity_associated_zone_option_set_before_add(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
entity_id: str,
|
||||
base_scanner_entity: MockBaseScannerEntity,
|
||||
) -> None:
|
||||
"""Test associated_zone option set before the entity is added is honored."""
|
||||
hass.states.async_set(
|
||||
"zone.home",
|
||||
"0",
|
||||
{ATTR_LATITUDE: 50.0, ATTR_LONGITUDE: 60.0, ATTR_RADIUS: 1000},
|
||||
)
|
||||
hass.states.async_set(
|
||||
"zone.kitchen",
|
||||
"0",
|
||||
{ATTR_LATITUDE: 50.0, ATTR_LONGITUDE: 60.0, ATTR_RADIUS: 50},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Pre-register the entity with the option set before the platform is set up.
|
||||
entity_registry.async_get_or_create(
|
||||
DOMAIN,
|
||||
TEST_DOMAIN,
|
||||
base_scanner_entity.unique_id,
|
||||
suggested_object_id="entity1",
|
||||
)
|
||||
entity_registry.async_update_entity_options(
|
||||
entity_id,
|
||||
DOMAIN,
|
||||
{CONF_ASSOCIATED_ZONE: "zone.kitchen"},
|
||||
)
|
||||
|
||||
base_scanner_entity._connected = True
|
||||
config_entry = await create_mock_platform(hass, config_entry, [base_scanner_entity])
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
assert base_scanner_entity._scanner_option_associated_zone == "zone.kitchen"
|
||||
|
||||
entity_state = hass.states.get(entity_id)
|
||||
assert entity_state
|
||||
assert entity_state.state == "kitchen"
|
||||
assert entity_state.attributes[ATTR_IN_ZONES] == ["zone.kitchen", "zone.home"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("ip_address", "mac_address", "hostname"),
|
||||
[("0.0.0.0", "ad:de:ef:be:ed:fe", "test.hostname.org")],
|
||||
|
||||
Reference in New Issue
Block a user