Skip to content
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
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,7 @@ omit =
homeassistant/components/overkiz/entity.py
homeassistant/components/overkiz/executor.py
homeassistant/components/overkiz/lock.py
homeassistant/components/overkiz/number.py
homeassistant/components/overkiz/sensor.py
homeassistant/components/ovo_energy/__init__.py
homeassistant/components/ovo_energy/const.py
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/overkiz/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
PLATFORMS: list[Platform] = [
Platform.BUTTON,
Platform.LOCK,
Platform.NUMBER,
Platform.SENSOR,
]

Expand Down
5 changes: 2 additions & 3 deletions homeassistant/components/overkiz/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
from pyoverkiz.enums import OverkizAttribute, OverkizState
from pyoverkiz.models import Device

from homeassistant.components.button import ButtonEntityDescription
from homeassistant.components.sensor import SensorEntityDescription
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity import DeviceInfo, EntityDescription
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DOMAIN
Expand Down Expand Up @@ -100,7 +99,7 @@ def __init__(
self,
device_url: str,
coordinator: OverkizDataUpdateCoordinator,
description: OverkizSensorDescription | ButtonEntityDescription,
description: EntityDescription,
) -> None:
"""Initialize the device."""
super().__init__(device_url, coordinator)
Expand Down
103 changes: 103 additions & 0 deletions homeassistant/components/overkiz/number.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"""Support for Overkiz (virtual) numbers."""
from __future__ import annotations

from dataclasses import dataclass

from pyoverkiz.enums import OverkizCommand, OverkizState

from homeassistant.components.number import NumberEntity, NumberEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import HomeAssistantOverkizData
from .const import DOMAIN, IGNORED_OVERKIZ_DEVICES
from .entity import OverkizDescriptiveEntity


@dataclass
class OverkizNumberDescriptionMixin:
"""Define an entity description mixin for number entities."""

command: str


@dataclass
class OverkizNumberDescription(NumberEntityDescription, OverkizNumberDescriptionMixin):
"""Class to describe an Overkiz number."""


NUMBER_DESCRIPTIONS: list[OverkizNumberDescription] = [
# Cover: My Position (0 - 100)
OverkizNumberDescription(
key=OverkizState.CORE_MEMORIZED_1_POSITION,
name="My Position",
icon="mdi:content-save-cog",
command=OverkizCommand.SET_MEMORIZED_1_POSITION,
entity_category=EntityCategory.CONFIG,
),
# WaterHeater: Expected Number Of Shower (2 - 4)
OverkizNumberDescription(
key=OverkizState.CORE_EXPECTED_NUMBER_OF_SHOWER,
name="Expected Number Of Shower",
icon="mdi:shower-head",
command=OverkizCommand.SET_EXPECTED_NUMBER_OF_SHOWER,
min_value=2,
max_value=4,
entity_category=EntityCategory.CONFIG,
),
]


async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Missing return value typing.

) -> None:

"""Set up the Overkiz number from a config entry."""
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
entities: list[OverkizNumber] = []

key_supported_states = {
description.key: description for description in NUMBER_DESCRIPTIONS
}

for device in data.coordinator.data.values():
if (
device.widget in IGNORED_OVERKIZ_DEVICES
or device.ui_class in IGNORED_OVERKIZ_DEVICES
):
continue

for state in device.definition.states:
if description := key_supported_states.get(state.qualified_name):
entities.append(
OverkizNumber(
device.device_url,
data.coordinator,
description,
)
)

async_add_entities(entities)


class OverkizNumber(OverkizDescriptiveEntity, NumberEntity):
"""Representation of an Overkiz Number."""

entity_description: OverkizNumberDescription

@property
def value(self) -> float:
"""Return the entity value to represent the entity state."""
if state := self.device.states.get(self.entity_description.key):
return state.value

return 0

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do we default to 0 instead of None?


async def async_set_value(self, value: float) -> None:
"""Set new value."""
await self.executor.async_execute_command(
self.entity_description.command, value
Comment thread
iMicknl marked this conversation as resolved.
)