Add Plugwise number platform (#74655)

pull/75110/head
Bouwe Westerdijk 2022-07-13 09:21:58 +02:00 committed by GitHub
parent b7a6f4e220
commit 34f1d5e094
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 163 additions and 4 deletions

View File

@ -25,8 +25,9 @@ UNIT_LUMEN: Final = "lm"
PLATFORMS_GATEWAY: Final[list[str]] = [
Platform.BINARY_SENSOR,
Platform.CLIMATE,
Platform.SENSOR,
Platform.NUMBER,
Platform.SELECT,
Platform.SENSOR,
Platform.SWITCH,
]
ZEROCONF_MAP: Final[dict[str, str]] = {

View File

@ -2,7 +2,7 @@
"domain": "plugwise",
"name": "Plugwise",
"documentation": "https://www.home-assistant.io/integrations/plugwise",
"requirements": ["plugwise==0.18.5"],
"requirements": ["plugwise==0.18.6"],
"codeowners": ["@CoMPaTech", "@bouwew", "@brefra", "@frenck"],
"zeroconf": ["_plugwise._tcp.local."],
"config_flow": true,

View File

@ -0,0 +1,115 @@
"""Number platform for Plugwise integration."""
from __future__ import annotations
from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from plugwise import Smile
from homeassistant.components.number import (
NumberDeviceClass,
NumberEntity,
NumberEntityDescription,
NumberMode,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import TEMP_CELSIUS
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .coordinator import PlugwiseDataUpdateCoordinator
from .entity import PlugwiseEntity
@dataclass
class PlugwiseEntityDescriptionMixin:
"""Mixin values for Plugwse entities."""
command: Callable[[Smile, float], Awaitable[None]]
@dataclass
class PlugwiseNumberEntityDescription(
NumberEntityDescription, PlugwiseEntityDescriptionMixin
):
"""Class describing Plugwise Number entities."""
NUMBER_TYPES = (
PlugwiseNumberEntityDescription(
key="maximum_boiler_temperature",
command=lambda api, value: api.set_max_boiler_temperature(value),
device_class=NumberDeviceClass.TEMPERATURE,
name="Maximum Boiler Temperature Setpoint",
entity_category=EntityCategory.CONFIG,
native_unit_of_measurement=TEMP_CELSIUS,
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Plugwise number platform."""
coordinator: PlugwiseDataUpdateCoordinator = hass.data[DOMAIN][
config_entry.entry_id
]
entities: list[PlugwiseNumberEntity] = []
for device_id, device in coordinator.data.devices.items():
for description in NUMBER_TYPES:
if description.key in device:
entities.append(
PlugwiseNumberEntity(coordinator, device_id, description)
)
async_add_entities(entities)
class PlugwiseNumberEntity(PlugwiseEntity, NumberEntity):
"""Representation of a Plugwise number."""
entity_description: PlugwiseNumberEntityDescription
def __init__(
self,
coordinator: PlugwiseDataUpdateCoordinator,
device_id: str,
description: PlugwiseNumberEntityDescription,
) -> None:
"""Initiate Plugwise Number."""
super().__init__(coordinator, device_id)
self.entity_description = description
self._attr_unique_id = f"{device_id}-{description.key}"
self._attr_name = (f"{self.device['name']} {description.name}").lstrip()
self._attr_mode = NumberMode.BOX
@property
def native_step(self) -> float:
"""Return the setpoint step value."""
return max(self.device["resolution"], 1)
@property
def native_value(self) -> float:
"""Return the present setpoint value."""
return self.device[self.entity_description.key]
@property
def native_min_value(self) -> float:
"""Return the setpoint min. value."""
return self.device["lower_bound"]
@property
def native_max_value(self) -> float:
"""Return the setpoint max. value."""
return self.device["upper_bound"]
async def async_set_native_value(self, value: float) -> None:
"""Change to the new setpoint value."""
await self.entity_description.command(self.coordinator.api, value)
await self.coordinator.async_request_refresh()

View File

@ -1254,7 +1254,7 @@ plexauth==0.0.6
plexwebsocket==0.0.13
# homeassistant.components.plugwise
plugwise==0.18.5
plugwise==0.18.6
# homeassistant.components.plum_lightpad
plumlightpad==0.0.11

View File

@ -862,7 +862,7 @@ plexauth==0.0.6
plexwebsocket==0.0.13
# homeassistant.components.plugwise
plugwise==0.18.5
plugwise==0.18.6
# homeassistant.components.plum_lightpad
plumlightpad==0.0.11

View File

@ -13,6 +13,9 @@
"model": "Generic heater",
"name": "OpenTherm",
"vendor": "Techneco",
"lower_bound": 0.0,
"upper_bound": 100.0,
"resolution": 1.0,
"maximum_boiler_temperature": 60.0,
"binary_sensors": {
"dhw_state": false,

View File

@ -0,0 +1,40 @@
"""Tests for the Plugwise Number integration."""
from unittest.mock import MagicMock
from homeassistant.components.number import (
ATTR_VALUE,
DOMAIN as NUMBER_DOMAIN,
SERVICE_SET_VALUE,
)
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
async def test_anna_number_entities(
hass: HomeAssistant, mock_smile_anna: MagicMock, init_integration: MockConfigEntry
) -> None:
"""Test creation of a number."""
state = hass.states.get("number.opentherm_maximum_boiler_temperature_setpoint")
assert state
assert float(state.state) == 60.0
async def test_anna_max_boiler_temp_change(
hass: HomeAssistant, mock_smile_anna: MagicMock, init_integration: MockConfigEntry
) -> None:
"""Test changing of number entities."""
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: "number.opentherm_maximum_boiler_temperature_setpoint",
ATTR_VALUE: 65,
},
blocking=True,
)
assert mock_smile_anna.set_max_boiler_temperature.call_count == 1
mock_smile_anna.set_max_boiler_temperature.assert_called_with(65)