Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweak available handling #30

Merged
merged 1 commit into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 30 additions & 7 deletions tests/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1154,9 +1154,7 @@ async def test_last_feeding_size_sensor_v2(


@pytest.mark.looptime
async def test_device_counter_sensors(
zha_gateway: Gateway, caplog: pytest.LogCaptureFixture
) -> None:
async def test_device_counter_sensors(zha_gateway: Gateway) -> None:
"""Test quirks defined sensor."""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""Test quirks defined sensor."""
"""Test coordinator counter sensor."""


coordinator = zha_gateway.coordinator_zha_device
Expand All @@ -1179,11 +1177,36 @@ async def test_device_counter_sensors(

assert entity.state["state"] == 2

coordinator.available = False
await asyncio.sleep(120)

@pytest.mark.looptime
async def test_device_unavailable_skips_entity_polling(
zha_gateway: Gateway,
elec_measurement_zha_dev: Device, # pylint: disable=redefined-outer-name
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test quirks defined sensor."""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""Test quirks defined sensor."""
"""Test polling is skipped for unavailable device."""


assert not elec_measurement_zha_dev.is_coordinator
assert not elec_measurement_zha_dev.is_active_coordinator
entity_id = "sensor.fakemanufacturer_fakemodel_e769900a_basic_rssi"
entity = get_entity(elec_measurement_zha_dev, entity_id)
assert entity is not None

assert entity.state["state"] is None

# simulate counter increment on application
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# simulate counter increment on application

elec_measurement_zha_dev.device.rssi = 60

await asyncio.sleep(zha_gateway.global_updater.__polling_interval + 2)
await zha_gateway.async_block_till_done(wait_background_tasks=True)

assert entity.state["state"] == 60

elec_measurement_zha_dev.on_network = False
await asyncio.sleep(zha_gateway.global_updater.__polling_interval * 2)
await zha_gateway.async_block_till_done(wait_background_tasks=True)

assert (
"counter_1: skipping polling for updated state, available: False, allow polled requests: True"
in caplog.text
"00:0d:6f:00:0a:90:69:e7-1-0-rssi: skipping polling for updated state, "
"available: False, allow polled requests: True" in caplog.text
)
10 changes: 5 additions & 5 deletions zha/zigbee/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def __init__(
CONF_CONSIDER_UNAVAILABLE_BATTERY,
CONF_DEFAULT_CONSIDER_UNAVAILABLE_BATTERY,
)
self._available: bool = self.is_coordinator or (
self._available: bool = self.is_active_coordinator or (
self.last_seen is not None
and time.time() - self.last_seen < self.consider_unavailable_time
)
Expand Down Expand Up @@ -370,14 +370,14 @@ def is_end_device(self) -> bool | None:
@property
def is_groupable(self) -> bool:
"""Return true if this device has a group cluster."""
return self.is_coordinator or (
return self.is_active_coordinator or (
self.available and bool(self.async_get_groupable_endpoints())
)

@cached_property
def skip_configuration(self) -> bool:
"""Return true if the device should not issue configuration related commands."""
return self._zigpy_device.skip_configuration or bool(self.is_coordinator)
return self._zigpy_device.skip_configuration or bool(self.is_active_coordinator)

@cached_property
def gateway(self):
Expand All @@ -401,7 +401,7 @@ def device_automation_triggers(self) -> dict[tuple[str, str], dict[str, str]]:
@property
def available(self):
"""Return True if device is available."""
return self._available and self.on_network
return self.is_active_coordinator or (self._available and self.on_network)

@available.setter
def available(self, new_availability: bool) -> None:
Expand Down Expand Up @@ -521,7 +521,7 @@ def async_update_sw_build_id(self, sw_version: int) -> None:

async def _check_available(self, *_: Any) -> None:
# don't flip the availability state of the coordinator
if self.is_coordinator:
if self.is_active_coordinator:
return
if not self._on_network:
self.debug("Device is not on the network, marking unavailable")
Expand Down
Loading