Skip to content

Commit

Permalink
fix: selection of osram lightify plugs
Browse files Browse the repository at this point in the history
  • Loading branch information
bramstroker committed Jan 3, 2025
1 parent 7822827 commit 3cdd9a2
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 21 deletions.
8 changes: 3 additions & 5 deletions custom_components/powercalc/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
from .group_include.include import find_entities
from .power_profile.factory import get_power_profile
from .power_profile.library import ModelInfo, ProfileLibrary
from .power_profile.power_profile import DEVICE_TYPE_DOMAIN, DeviceType, PowerProfile
from .power_profile.power_profile import DEVICE_TYPE_DOMAIN, DeviceType, PowerProfile, get_entity_device_types
from .sensors.daily_energy import DEFAULT_DAILY_UPDATE_FREQUENCY
from .sensors.power import PowerSensor
from .strategy.factory import PowerCalculatorStrategyFactory
Expand Down Expand Up @@ -987,10 +987,8 @@ async def _create_schema() -> vol.Schema:
"""Create model schema."""
manufacturer = str(self.sensor_config.get(CONF_MANUFACTURER))
library = await ProfileLibrary.factory(self.hass)
models = [
selector.SelectOptionDict(value=model, label=model)
for model in await library.get_model_listing(manufacturer, self.source_entity.domain) # type: ignore
]
device_types = get_entity_device_types(self.source_entity.domain, self.source_entity.entity_entry) if self.source_entity else None

Check notice on line 990 in custom_components/powercalc/config_flow.py

View workflow job for this annotation

GitHub Actions / Qodana Community for Python

PEP 8 coding style violation

PEP 8: E501 line too long (142 \> 120 characters)
models = [selector.SelectOptionDict(value=model, label=model) for model in await library.get_model_listing(manufacturer, device_types)]

Check notice on line 991 in custom_components/powercalc/config_flow.py

View workflow job for this annotation

GitHub Actions / Qodana Community for Python

PEP 8 coding style violation

PEP 8: E501 line too long (147 \> 120 characters)
return vol.Schema(
{
vol.Required(CONF_MODEL, default=self.sensor_config.get(CONF_MODEL)): selector.SelectSelector(
Expand Down
5 changes: 2 additions & 3 deletions custom_components/powercalc/power_profile/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from .loader.local import LocalLoader
from .loader.protocol import Loader
from .loader.remote import RemoteLoader
from .power_profile import PowerProfile, get_device_types_from_domain
from .power_profile import DeviceType, PowerProfile, get_device_types_from_domain

LEGACY_CUSTOM_DATA_DIRECTORY = "powercalc-custom-models"
CUSTOM_DATA_DIRECTORY = "powercalc/profiles"
Expand Down Expand Up @@ -73,13 +73,12 @@ async def get_manufacturer_listing(self, entity_domain: str | None = None) -> li
manufacturers = await self._loader.get_manufacturer_listing(device_types)
return sorted(manufacturers)

async def get_model_listing(self, manufacturer: str, entity_domain: str | None = None) -> list[str]:
async def get_model_listing(self, manufacturer: str, device_types: set[DeviceType] | None = None) -> list[str]:
"""Get listing of available models for a given manufacturer."""

resolved_manufacturers = await self._loader.find_manufacturers(manufacturer)
if not resolved_manufacturers:
return []
device_types = get_device_types_from_domain(entity_domain) if entity_domain else None
all_models: list[str] = []
for manufacturer in resolved_manufacturers:
cache_key = f"{manufacturer}/{device_types}"
Expand Down
14 changes: 9 additions & 5 deletions custom_components/powercalc/power_profile/power_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ def get_device_types_from_domain(search_domain: str) -> set[DeviceType]:
return set(DOMAIN_TO_DEVICE_TYPES.get(search_domain, {}))


def get_entity_device_types(domain: str, entity_entry: RegistryEntry | None) -> set[DeviceType]:
device_types = get_device_types_from_domain(domain)
# see https://github.com/bramstroker/homeassistant-powercalc/issues/1491
if entity_entry and entity_entry.platform in ["hue", "osramlightify"] and entity_entry.domain == LIGHT_DOMAIN:
device_types.add(DeviceType.SMART_SWITCH)
return device_types


class PowerProfile:
def __init__(
self,
Expand Down Expand Up @@ -373,11 +381,7 @@ def is_entity_domain_supported(self, entity_entry: RegistryEntry) -> bool:
if self.device_type == DeviceType.PRINTER and entity_entry.unit_of_measurement:
return False

# see https://github.com/bramstroker/homeassistant-powercalc/issues/1491
if self.device_type == DeviceType.SMART_SWITCH and entity_entry.platform in ["hue", "osramlightify"] and domain == LIGHT_DOMAIN:
return True

return DEVICE_TYPE_DOMAIN.get(self.device_type) == domain
return self.device_type in get_entity_device_types(domain, entity_entry)


class SubProfileSelector:
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def _mock_entity_with_model_information(

platform = "foo"
if "platform" in entity_reg_kwargs:
unique_id = entity_reg_kwargs["platform"]
platform = entity_reg_kwargs["platform"]
del entity_reg_kwargs["platform"]

mock_registry(
Expand Down
2 changes: 1 addition & 1 deletion tests/power_profile/loader/test_remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ async def test_multiple_manufacturer_aliases(hass: HomeAssistant, mock_aiorespon
manufacturers = await library.find_manufacturers("my-alias")
assert manufacturers == {"manufacturer1", "manufacturer2"}

model_listing = await library.get_model_listing("my-alias", "light")
model_listing = await library.get_model_listing("my-alias", {DeviceType.LIGHT})
assert len(model_listing) == 2

models = await library.find_models(ModelInfo("my-alias", "model1"))
Expand Down
6 changes: 5 additions & 1 deletion tests/power_profile/test_power_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ async def test_vacuum_entity_domain_supported(hass: HomeAssistant) -> None:
get_test_profile_dir("vacuum"),
)
assert power_profile.is_entity_domain_supported(
SourceEntity("vacuum.test", "test", "vacuum"),
RegistryEntry(
entity_id="vacuum.test",
unique_id="1234",
platform="xiaomi_miio",
),
)


Expand Down
48 changes: 48 additions & 0 deletions tests/power_profile/user_scenarios/test_lightify_plug.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from selectors import SelectSelector

from homeassistant import data_entry_flow
from homeassistant.const import CONF_ENTITY_ID
from homeassistant.core import HomeAssistant

from custom_components.powercalc.config_flow import CONF_CONFIRM_AUTODISCOVERED_MODEL, Step
from custom_components.powercalc.const import (
CONF_MANUFACTURER,
)
from tests.config_flow.common import select_menu_item
from tests.conftest import MockEntityWithModel


async def test_lightify_plug_selectable(
hass: HomeAssistant,
mock_entity_with_model_information: MockEntityWithModel,
) -> None:
"""
See https://github.com/bramstroker/homeassistant-powercalc/issues/2858
"""
mock_entity_with_model_information(
"light.test",
"osram",
"LIGHTIFY Plug 01",
platform="osramlightify",
)

result = await select_menu_item(hass, Step.MENU_LIBRARY)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_ENTITY_ID: "light.test"},
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_CONFIRM_AUTODISCOVERED_MODEL: False},
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_MANUFACTURER: "osram",
},
)
assert result["type"] == data_entry_flow.FlowResultType.FORM
data_schema = result["data_schema"]
model_select: SelectSelector = data_schema.schema["model"]
model_options = model_select.config["options"]
assert {"value": "LIGHTIFY Plug 01", "label": "LIGHTIFY Plug 01"} in model_options
6 changes: 1 addition & 5 deletions tests/power_profile/user_scenarios/test_nintendo_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,9 @@
CONF_STANDBY_POWER,
)
from tests.common import run_powercalc_setup
from tests.conftest import MockEntityWithModel


async def test_nintendo_switch(
hass: HomeAssistant,
mock_entity_with_model_information: MockEntityWithModel,
) -> None:
async def test_nintendo_switch(hass: HomeAssistant) -> None:
"""
See https://community.home-assistant.io/t/powercalc-virtual-power-sensors/318515/840?u=bramski
"""
Expand Down

0 comments on commit 3cdd9a2

Please sign in to comment.