mirror of
https://github.com/home-assistant/core.git
synced 2025-07-15 01:07:10 +00:00
Correct range for nibe_heatpump numbers (#102553)
This commit is contained in:
parent
e936ca0cb1
commit
7d2fa5bf60
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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})
|
||||
|
@ -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
|
||||
|
135
tests/components/nibe_heatpump/snapshots/test_number.ambr
Normal file
135
tests/components/nibe_heatpump/snapshots/test_number.ambr
Normal 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',
|
||||
})
|
||||
# ---
|
@ -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
|
||||
|
109
tests/components/nibe_heatpump/test_number.py
Normal file
109
tests/components/nibe_heatpump/test_number.py
Normal 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
|
Loading…
x
Reference in New Issue
Block a user