Use device supplied ranges in LaMetric (#135590)

This commit is contained in:
Joost Lekkerkerker 2025-01-14 14:02:17 +01:00 committed by Franck Nijhof
parent c6cde13615
commit 0bd03346e8
No known key found for this signature in database
GPG Key ID: D62583BA8AB11CA3
3 changed files with 100 additions and 6 deletions

View File

@ -6,7 +6,7 @@ from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from typing import Any
from demetriek import Device, LaMetricDevice
from demetriek import Device, LaMetricDevice, Range
from homeassistant.components.number import NumberEntity, NumberEntityDescription
from homeassistant.config_entries import ConfigEntry
@ -25,6 +25,7 @@ class LaMetricNumberEntityDescription(NumberEntityDescription):
"""Class describing LaMetric number entities."""
value_fn: Callable[[Device], int | None]
range_fn: Callable[[Device], Range | None]
has_fn: Callable[[Device], bool] = lambda device: True
set_value_fn: Callable[[LaMetricDevice, float], Awaitable[Any]]
@ -35,8 +36,7 @@ NUMBERS = [
translation_key="brightness",
entity_category=EntityCategory.CONFIG,
native_step=1,
native_min_value=0,
native_max_value=100,
range_fn=lambda device: device.display.brightness_limit,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda device: device.display.brightness,
set_value_fn=lambda device, bri: device.display(brightness=int(bri)),
@ -46,8 +46,7 @@ NUMBERS = [
translation_key="volume",
entity_category=EntityCategory.CONFIG,
native_step=1,
native_min_value=0,
native_max_value=100,
range_fn=lambda device: device.audio.volume_range if device.audio else None,
native_unit_of_measurement=PERCENTAGE,
has_fn=lambda device: bool(device.audio and device.audio.available),
value_fn=lambda device: device.audio.volume if device.audio else 0,
@ -92,6 +91,20 @@ class LaMetricNumberEntity(LaMetricEntity, NumberEntity):
"""Return the number value."""
return self.entity_description.value_fn(self.coordinator.data)
@property
def native_min_value(self) -> int:
"""Return the min range."""
if limits := self.entity_description.range_fn(self.coordinator.data):
return limits.range_min
return 0
@property
def native_max_value(self) -> int:
"""Return the max range."""
if limits := self.entity_description.range_fn(self.coordinator.data):
return limits.range_max
return 100
@lametric_exception_handler
async def async_set_native_value(self, value: float) -> None:
"""Change to new number value."""

View File

@ -0,0 +1,68 @@
{
"audio": {
"available": true,
"volume": 53,
"volume_limit": {
"max": 100,
"min": 0
},
"volume_range": {
"max": 100,
"min": 0
}
},
"bluetooth": {
"active": false,
"address": "40:F4:C9:AA:AA:AA",
"available": true,
"discoverable": true,
"mac": "40:F4:C9:AA:AA:AA",
"name": "LM8367",
"pairable": false
},
"display": {
"brightness": 75,
"brightness_limit": {
"max": 76,
"min": 2
},
"brightness_mode": "manual",
"brightness_range": {
"max": 100,
"min": 0
},
"height": 8,
"on": true,
"screensaver": {
"enabled": true,
"modes": {
"time_based": {
"enabled": false
},
"when_dark": {
"enabled": true
}
},
"widget": "1_com.lametric.clock"
},
"type": "mixed",
"width": 37
},
"id": "67790",
"mode": "manual",
"model": "sa8",
"name": "TIME",
"os_version": "3.1.3",
"serial_number": "SA840700836700W00BAA",
"wifi": {
"active": true,
"mac": "40:F4:C9:AA:AA:AA",
"available": true,
"encryption": "WPA",
"ssid": "My wifi",
"ip": "10.0.0.99",
"mode": "dhcp",
"netmask": "255.255.255.0",
"rssi": 78
}
}

View File

@ -42,7 +42,7 @@ async def test_brightness(
assert state.attributes.get(ATTR_DEVICE_CLASS) is None
assert state.attributes.get(ATTR_FRIENDLY_NAME) == "Frenck's LaMetric Brightness"
assert state.attributes.get(ATTR_MAX) == 100
assert state.attributes.get(ATTR_MIN) == 0
assert state.attributes.get(ATTR_MIN) == 2
assert state.attributes.get(ATTR_STEP) == 1
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == PERCENTAGE
assert state.state == "100"
@ -183,3 +183,16 @@ async def test_number_connection_error(
state = hass.states.get("number.frenck_s_lametric_volume")
assert state
assert state.state == STATE_UNAVAILABLE
@pytest.mark.parametrize("device_fixture", ["computer_powered"])
async def test_computer_powered_devices(
hass: HomeAssistant,
mock_lametric: MagicMock,
) -> None:
"""Test Brightness is properly limited for computer powered devices."""
state = hass.states.get("number.time_brightness")
assert state
assert state.state == "75"
assert state.attributes[ATTR_MIN] == 2
assert state.attributes[ATTR_MAX] == 76