Correct range for nibe_heatpump numbers (#102553)

This commit is contained in:
Joakim Plate 2023-10-22 22:39:40 +02:00 committed by GitHub
parent e936ca0cb1
commit 7d2fa5bf60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 277 additions and 14 deletions

View File

@ -827,7 +827,6 @@ omit =
homeassistant/components/nibe_heatpump/__init__.py
homeassistant/components/nibe_heatpump/climate.py
homeassistant/components/nibe_heatpump/binary_sensor.py
homeassistant/components/nibe_heatpump/number.py
homeassistant/components/nibe_heatpump/select.py
homeassistant/components/nibe_heatpump/sensor.py
homeassistant/components/nibe_heatpump/switch.py

View File

@ -50,6 +50,8 @@ class Number(CoilEntity, NumberEntity):
self._attr_native_min_value,
self._attr_native_max_value,
) = _get_numeric_limits(coil.size)
self._attr_native_min_value /= coil.factor
self._attr_native_max_value /= coil.factor
else:
self._attr_native_min_value = float(coil.min)
self._attr_native_max_value = float(coil.max)

View File

@ -2,12 +2,24 @@
from typing import Any
from nibe.heatpump import Model
from homeassistant.components.nibe_heatpump import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
MOCK_ENTRY_DATA = {
"model": None,
"ip_address": "127.0.0.1",
"listening_port": 9999,
"remote_read_port": 10000,
"remote_write_port": 10001,
"word_swap": True,
"connection_type": "nibegw",
}
async def async_add_entry(hass: HomeAssistant, data: dict[str, Any]) -> None:
"""Add entry and get the coordinator."""
@ -17,3 +29,8 @@ async def async_add_entry(hass: HomeAssistant, data: dict[str, Any]) -> None:
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert entry.state == ConfigEntryState.LOADED
async def async_add_model(hass: HomeAssistant, model: Model):
"""Add entry of specific model."""
await async_add_entry(hass, {**MOCK_ENTRY_DATA, "model": model.name})

View File

@ -62,4 +62,15 @@ async def fixture_coils(mock_connection):
mock_connection.read_coil = read_coil
mock_connection.read_coils = read_coils
return coils
# pylint: disable-next=import-outside-toplevel
from homeassistant.components.nibe_heatpump import HeatPump
get_coils_original = HeatPump.get_coils
def get_coils(x):
coils_data = get_coils_original(x)
return [coil for coil in coils_data if coil.address in coils]
with patch.object(HeatPump, "get_coils", new=get_coils):
yield coils

View File

@ -0,0 +1,135 @@
# serializer version: 1
# name: test_update[Model.F1155-47011-number.heat_offset_s1_47011--10]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'F1155 Heat Offset S1',
'max': 10.0,
'min': -10.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'context': <ANY>,
'entity_id': 'number.heat_offset_s1_47011',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '-10.0',
})
# ---
# name: test_update[Model.F1155-47011-number.heat_offset_s1_47011-10]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'F1155 Heat Offset S1',
'max': 10.0,
'min': -10.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'context': <ANY>,
'entity_id': 'number.heat_offset_s1_47011',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '10.0',
})
# ---
# name: test_update[Model.F1155-47062-number.heat_offset_s1_47011-None]
None
# ---
# name: test_update[Model.F750-47062-number.hw_charge_offset_47062--10]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'F750 HW charge offset',
'max': 12.7,
'min': -12.8,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': '°C',
}),
'context': <ANY>,
'entity_id': 'number.hw_charge_offset_47062',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '-10.0',
})
# ---
# name: test_update[Model.F750-47062-number.hw_charge_offset_47062-10]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'F750 HW charge offset',
'max': 12.7,
'min': -12.8,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': '°C',
}),
'context': <ANY>,
'entity_id': 'number.hw_charge_offset_47062',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '10.0',
})
# ---
# name: test_update[Model.F750-47062-number.hw_charge_offset_47062-None]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'F750 HW charge offset',
'max': 12.7,
'min': -12.8,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': '°C',
}),
'context': <ANY>,
'entity_id': 'number.hw_charge_offset_47062',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_update[Model.S320-40031-number.heating_offset_climate_system_1_40031--10]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'S320 Heating offset climate system 1',
'max': 10.0,
'min': -10.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'context': <ANY>,
'entity_id': 'number.heating_offset_climate_system_1_40031',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '-10.0',
})
# ---
# name: test_update[Model.S320-40031-number.heating_offset_climate_system_1_40031-10]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'S320 Heating offset climate system 1',
'max': 10.0,
'min': -10.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'context': <ANY>,
'entity_id': 'number.heating_offset_climate_system_1_40031',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '10.0',
})
# ---
# name: test_update[Model.S320-40031-number.heating_offset_climate_system_1_40031-None]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'S320 Heating offset climate system 1',
'max': 10.0,
'min': -10.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'context': <ANY>,
'entity_id': 'number.heating_offset_climate_system_1_40031',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---

View File

@ -17,20 +17,10 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant
from . import async_add_entry
from . import async_add_model
from tests.common import async_fire_time_changed
MOCK_ENTRY_DATA = {
"model": None,
"ip_address": "127.0.0.1",
"listening_port": 9999,
"remote_read_port": 10000,
"remote_write_port": 10001,
"word_swap": True,
"connection_type": "nibegw",
}
@pytest.fixture(autouse=True)
async def fixture_single_platform():
@ -62,7 +52,7 @@ async def test_reset_button(
coils[unit.alarm_reset] = 0
coils[unit.alarm] = 0
await async_add_entry(hass, {**MOCK_ENTRY_DATA, "model": model.name})
await async_add_model(hass, model)
state = hass.states.get(entity_id)
assert state

View File

@ -0,0 +1,109 @@
"""Test the Nibe Heat Pump config flow."""
from typing import Any
from unittest.mock import AsyncMock, patch
from nibe.coil import CoilData
from nibe.heatpump import Model
import pytest
from syrupy import SnapshotAssertion
from homeassistant.components.number import (
ATTR_VALUE,
DOMAIN as PLATFORM_DOMAIN,
SERVICE_SET_VALUE,
)
from homeassistant.const import ATTR_ENTITY_ID, Platform
from homeassistant.core import HomeAssistant
from . import async_add_model
@pytest.fixture(autouse=True)
async def fixture_single_platform():
"""Only allow this platform to load."""
with patch("homeassistant.components.nibe_heatpump.PLATFORMS", [Platform.NUMBER]):
yield
@pytest.mark.parametrize(
("model", "address", "entity_id", "value"),
[
# Tests for S series coils with min/max
(Model.S320, 40031, "number.heating_offset_climate_system_1_40031", 10),
(Model.S320, 40031, "number.heating_offset_climate_system_1_40031", -10),
(Model.S320, 40031, "number.heating_offset_climate_system_1_40031", None),
# Tests for F series coils with min/max
(Model.F1155, 47011, "number.heat_offset_s1_47011", 10),
(Model.F1155, 47011, "number.heat_offset_s1_47011", -10),
(Model.F1155, 47062, "number.heat_offset_s1_47011", None),
# Tests for F series coils without min/max
(Model.F750, 47062, "number.hw_charge_offset_47062", 10),
(Model.F750, 47062, "number.hw_charge_offset_47062", -10),
(Model.F750, 47062, "number.hw_charge_offset_47062", None),
],
)
async def test_update(
hass: HomeAssistant,
model: Model,
entity_id: str,
address: int,
value: Any,
coils: dict[int, Any],
entity_registry_enabled_by_default: None,
snapshot: SnapshotAssertion,
) -> None:
"""Test setting of value."""
coils[address] = value
await async_add_model(hass, model)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state == snapshot
@pytest.mark.parametrize(
("model", "address", "entity_id", "value"),
[
(Model.S320, 40031, "number.heating_offset_climate_system_1_40031", 10),
(Model.S320, 40031, "number.heating_offset_climate_system_1_40031", -10),
(Model.F1155, 47011, "number.heat_offset_s1_47011", 10),
(Model.F1155, 47011, "number.heat_offset_s1_47011", -10),
(Model.F750, 47062, "number.hw_charge_offset_47062", 10),
],
)
async def test_set_value(
hass: HomeAssistant,
mock_connection: AsyncMock,
model: Model,
entity_id: str,
address: int,
value: Any,
coils: dict[int, Any],
entity_registry_enabled_by_default: None,
) -> None:
"""Test setting of value."""
coils[address] = 0
await async_add_model(hass, model)
await hass.async_block_till_done()
assert hass.states.get(entity_id)
# Write value
await hass.services.async_call(
PLATFORM_DOMAIN,
SERVICE_SET_VALUE,
{ATTR_ENTITY_ID: entity_id, ATTR_VALUE: value},
blocking=True,
)
await hass.async_block_till_done()
# Verify written
args = mock_connection.write_coil.call_args
assert args
coil = args.args[0]
assert isinstance(coil, CoilData)
assert coil.coil.address == address
assert coil.value == value