Skip to content

Commit

Permalink
Fix Shelly Gen1 entity description restore
Browse files Browse the repository at this point in the history
  • Loading branch information
thecode committed Jan 14, 2024
1 parent 7a6dca0 commit 42efba6
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 74 deletions.
13 changes: 0 additions & 13 deletions homeassistant/components/shelly/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from homeassistant.const import STATE_ON, EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.entity_registry import RegistryEntry
from homeassistant.helpers.restore_state import RestoreEntity

from .const import CONF_SLEEP_PERIOD
Expand Down Expand Up @@ -210,16 +209,6 @@ class RestBinarySensorDescription(RestEntityDescription, BinarySensorEntityDescr
}


def _build_block_description(entry: RegistryEntry) -> BlockBinarySensorDescription:
"""Build description when restoring block attribute entities."""
return BlockBinarySensorDescription(
key="",
name="",
icon=entry.original_icon,
device_class=entry.original_device_class,
)


async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
Expand Down Expand Up @@ -248,7 +237,6 @@ async def async_setup_entry(
async_add_entities,
SENSORS,
BlockSleepingBinarySensor,
_build_block_description,
)
else:
async_setup_entry_attribute_entities(
Expand All @@ -257,7 +245,6 @@ async def async_setup_entry(
async_add_entities,
SENSORS,
BlockBinarySensor,
_build_block_description,
)
async_setup_entry_rest(
hass,
Expand Down
28 changes: 7 additions & 21 deletions homeassistant/components/shelly/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ def async_setup_entry_attribute_entities(
async_add_entities: AddEntitiesCallback,
sensors: Mapping[tuple[str, str], BlockEntityDescription],
sensor_class: Callable,
description_class: Callable[[RegistryEntry], BlockEntityDescription],
) -> None:
"""Set up entities for attributes."""
coordinator = get_entry_data(hass)[config_entry.entry_id].block
Expand All @@ -56,7 +55,6 @@ def async_setup_entry_attribute_entities(
coordinator,
sensors,
sensor_class,
description_class,
)


Expand Down Expand Up @@ -113,7 +111,6 @@ def async_restore_block_attribute_entities(
coordinator: ShellyBlockCoordinator,
sensors: Mapping[tuple[str, str], BlockEntityDescription],
sensor_class: Callable,
description_class: Callable[[RegistryEntry], BlockEntityDescription],
) -> None:
"""Restore block attributes entities."""
entities = []
Expand All @@ -128,11 +125,12 @@ def async_restore_block_attribute_entities(
continue

attribute = entry.unique_id.split("-")[-1]
description = description_class(entry)
block_type = entry.unique_id.split("-")[-2].split("_")[0]

entities.append(
sensor_class(coordinator, None, attribute, description, entry, sensors)
)
if description := sensors.get((block_type, attribute)):
entities.append(
sensor_class(coordinator, None, attribute, description, entry)
)

if not entities:
return
Expand Down Expand Up @@ -444,7 +442,7 @@ def available(self) -> bool:
"""Available."""
available = super().available

if not available or not self.entity_description.available:
if not available or not self.entity_description.available or self.block is None:
return available

return self.entity_description.available(self.block)
Expand Down Expand Up @@ -559,10 +557,8 @@ def __init__(
attribute: str,
description: BlockEntityDescription,
entry: RegistryEntry | None = None,
sensors: Mapping[tuple[str, str], BlockEntityDescription] | None = None,
) -> None:
"""Initialize the sleeping sensor."""
self.sensors = sensors
self.last_state: State | None = None
self.coordinator = coordinator
self.attribute = attribute
Expand All @@ -587,11 +583,7 @@ def __init__(
@callback
def _update_callback(self) -> None:
"""Handle device update."""
if (
self.block is not None
or not self.coordinator.device.initialized
or self.sensors is None
):
if self.block is not None or not self.coordinator.device.initialized:
super()._update_callback()
return

Expand All @@ -607,13 +599,7 @@ def _update_callback(self) -> None:
if sensor_id != entity_sensor:
continue

description = self.sensors.get((block.type, sensor_id))
if description is None:
continue

self.block = block
self.entity_description = description

LOGGER.debug("Entity %s attached to block", self.name)
super()._update_callback()
return
Expand Down
21 changes: 1 addition & 20 deletions homeassistant/components/shelly/number.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Number for Shelly."""
from __future__ import annotations

from collections.abc import Mapping
from dataclasses import dataclass
from typing import Any, Final, cast

Expand Down Expand Up @@ -56,22 +55,6 @@ class BlockNumberDescription(BlockEntityDescription, NumberEntityDescription):
}


def _build_block_description(entry: RegistryEntry) -> BlockNumberDescription:
"""Build description when restoring block attribute entities."""
assert entry.capabilities
return BlockNumberDescription(
key="",
name="",
icon=entry.original_icon,
native_unit_of_measurement=entry.unit_of_measurement,
device_class=entry.original_device_class,
native_min_value=cast(float, entry.capabilities.get("min")),
native_max_value=cast(float, entry.capabilities.get("max")),
native_step=cast(float, entry.capabilities.get("step")),
mode=cast(NumberMode, entry.capabilities.get("mode")),
)


async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
Expand All @@ -85,7 +68,6 @@ async def async_setup_entry(
async_add_entities,
NUMBERS,
BlockSleepingNumber,
_build_block_description,
)


Expand All @@ -101,11 +83,10 @@ def __init__(
attribute: str,
description: BlockNumberDescription,
entry: RegistryEntry | None = None,
sensors: Mapping[tuple[str, str], BlockNumberDescription] | None = None,
) -> None:
"""Initialize the sleeping sensor."""
self.restored_data: NumberExtraStoredData | None = None
super().__init__(coordinator, block, attribute, description, entry, sensors)
super().__init__(coordinator, block, attribute, description, entry)

async def async_added_to_hass(self) -> None:
"""Handle entity which will be added."""
Expand Down
18 changes: 1 addition & 17 deletions homeassistant/components/shelly/sensor.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Sensor for Shelly."""
from __future__ import annotations

from collections.abc import Mapping
from dataclasses import dataclass
from typing import Final, cast

Expand Down Expand Up @@ -36,7 +35,6 @@
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.entity_registry import RegistryEntry
from homeassistant.helpers.typing import StateType
from homeassistant.util.enum import try_parse_enum

from .const import CONF_SLEEP_PERIOD, SHAIR_MAX_WORK_HOURS
from .coordinator import ShellyBlockCoordinator, ShellyRpcCoordinator
Expand Down Expand Up @@ -963,17 +961,6 @@ class RestSensorDescription(RestEntityDescription, SensorEntityDescription):
}


def _build_block_description(entry: RegistryEntry) -> BlockSensorDescription:
"""Build description when restoring block attribute entities."""
return BlockSensorDescription(
key="",
name="",
icon=entry.original_icon,
native_unit_of_measurement=entry.unit_of_measurement,
device_class=try_parse_enum(SensorDeviceClass, entry.original_device_class),
)


async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
Expand Down Expand Up @@ -1002,7 +989,6 @@ async def async_setup_entry(
async_add_entities,
SENSORS,
BlockSleepingSensor,
_build_block_description,
)
else:
async_setup_entry_attribute_entities(
Expand All @@ -1011,7 +997,6 @@ async def async_setup_entry(
async_add_entities,
SENSORS,
BlockSensor,
_build_block_description,
)
async_setup_entry_rest(
hass, config_entry, async_add_entities, REST_SENSORS, RestSensor
Expand Down Expand Up @@ -1075,10 +1060,9 @@ def __init__(
attribute: str,
description: BlockSensorDescription,
entry: RegistryEntry | None = None,
sensors: Mapping[tuple[str, str], BlockSensorDescription] | None = None,
) -> None:
"""Initialize the sleeping sensor."""
super().__init__(coordinator, block, attribute, description, entry, sensors)
super().__init__(coordinator, block, attribute, description, entry)
self.restored_data: SensorExtraStoredData | None = None

async def async_added_to_hass(self) -> None:
Expand Down
18 changes: 15 additions & 3 deletions tests/components/shelly/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@
DOMAIN as HA_DOMAIN,
SERVICE_UPDATE_ENTITY,
)
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.components.sensor import (
ATTR_STATE_CLASS,
DOMAIN as SENSOR_DOMAIN,
SensorDeviceClass,
SensorStateClass,
)
from homeassistant.components.shelly.const import DOMAIN
from homeassistant.const import (
ATTR_DEVICE_CLASS,
ATTR_ENTITY_ID,
ATTR_UNIT_OF_MEASUREMENT,
PERCENTAGE,
Expand Down Expand Up @@ -153,7 +159,11 @@ async def test_block_restored_sleeping_sensor(
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()

assert hass.states.get(entity_id).state == "20.4"
state = hass.states.get(entity_id)
assert state
assert state.state == "20.4"
assert state.attributes.get(ATTR_STATE_CLASS) == SensorStateClass.MEASUREMENT
assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.TEMPERATURE

# Make device online
monkeypatch.setattr(mock_block_device, "initialized", True)
Expand Down Expand Up @@ -237,7 +247,9 @@ async def test_block_not_matched_restored_sleeping_sensor(
assert hass.states.get(entity_id).state == "20.4"

# Make device online
monkeypatch.setattr(mock_block_device.blocks[SENSOR_BLOCK_ID], "type", "other_type")
monkeypatch.setattr(
mock_block_device.blocks[SENSOR_BLOCK_ID], "description", "other_desc"
)
monkeypatch.setattr(mock_block_device, "initialized", True)
mock_block_device.mock_update()
await hass.async_block_till_done()
Expand Down

0 comments on commit 42efba6

Please sign in to comment.