mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Add select platform to myuplink (#118661)
This commit is contained in:
parent
f5f9480b5a
commit
172778053c
@ -25,6 +25,7 @@ from .coordinator import MyUplinkDataCoordinator
|
||||
PLATFORMS: list[Platform] = [
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.NUMBER,
|
||||
Platform.SELECT,
|
||||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
Platform.UPDATE,
|
||||
|
@ -21,6 +21,9 @@ def find_matching_platform(
|
||||
return Platform.SWITCH
|
||||
return Platform.BINARY_SENSOR
|
||||
|
||||
if len(device_point.enum_values) > 0 and device_point.writable:
|
||||
return Platform.SELECT
|
||||
|
||||
if (
|
||||
description
|
||||
and description.native_unit_of_measurement == "DM"
|
||||
|
95
homeassistant/components/myuplink/select.py
Normal file
95
homeassistant/components/myuplink/select.py
Normal file
@ -0,0 +1,95 @@
|
||||
"""Select entity for myUplink."""
|
||||
|
||||
from typing import cast
|
||||
|
||||
from aiohttp import ClientError
|
||||
from myuplink import DevicePoint
|
||||
|
||||
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import MyUplinkConfigEntry, MyUplinkDataCoordinator
|
||||
from .entity import MyUplinkEntity
|
||||
from .helpers import find_matching_platform, skip_entity
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MyUplinkConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up myUplink select."""
|
||||
entities: list[SelectEntity] = []
|
||||
coordinator: MyUplinkDataCoordinator = config_entry.runtime_data
|
||||
|
||||
# Setup device point select entities
|
||||
for device_id, point_data in coordinator.data.points.items():
|
||||
for point_id, device_point in point_data.items():
|
||||
if skip_entity(device_point.category, device_point):
|
||||
continue
|
||||
description = None
|
||||
if find_matching_platform(device_point, description) == Platform.SELECT:
|
||||
entities.append(
|
||||
MyUplinkSelect(
|
||||
coordinator=coordinator,
|
||||
device_id=device_id,
|
||||
device_point=device_point,
|
||||
entity_description=description,
|
||||
unique_id_suffix=point_id,
|
||||
)
|
||||
)
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
class MyUplinkSelect(MyUplinkEntity, SelectEntity):
|
||||
"""Representation of a myUplink select entity."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: MyUplinkDataCoordinator,
|
||||
device_id: str,
|
||||
device_point: DevicePoint,
|
||||
entity_description: SelectEntityDescription | None,
|
||||
unique_id_suffix: str,
|
||||
) -> None:
|
||||
"""Initialize the select."""
|
||||
super().__init__(
|
||||
coordinator=coordinator,
|
||||
device_id=device_id,
|
||||
unique_id_suffix=unique_id_suffix,
|
||||
)
|
||||
|
||||
# Internal properties
|
||||
self.point_id = device_point.parameter_id
|
||||
self._attr_name = device_point.parameter_name
|
||||
|
||||
self._attr_options = [x["text"].capitalize() for x in device_point.enum_values]
|
||||
self.options_map = {
|
||||
str(int(x["value"])): x["text"].capitalize()
|
||||
for x in device_point.enum_values
|
||||
}
|
||||
self.options_rev = {value: key for key, value in self.options_map.items()}
|
||||
|
||||
@property
|
||||
def current_option(self) -> str | None:
|
||||
"""Retrieve currently selected option."""
|
||||
device_point = self.coordinator.data.points[self.device_id][self.point_id]
|
||||
value = int(cast(int, device_point.value_t))
|
||||
return self.options_map.get(str(value))
|
||||
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Set the current option."""
|
||||
try:
|
||||
await self.coordinator.api.async_set_device_points(
|
||||
self.device_id, data={self.point_id: str(self.options_rev[option])}
|
||||
)
|
||||
except ClientError as err:
|
||||
raise HomeAssistantError(
|
||||
f"Failed to set new option {self.options_rev[option]} for {self.point_id}/{self.entity_id}"
|
||||
) from err
|
||||
|
||||
await self.coordinator.async_request_refresh()
|
@ -951,5 +951,43 @@
|
||||
],
|
||||
"scaleValue": "1",
|
||||
"zoneId": null
|
||||
},
|
||||
{
|
||||
"category": "NIBEF F730 CU 3x400V",
|
||||
"parameterId": "47041",
|
||||
"parameterName": "comfort mode",
|
||||
"parameterUnit": "",
|
||||
"writable": true,
|
||||
"timestamp": "2024-05-22T15:02:03+00:00",
|
||||
"value": 0,
|
||||
"strVal": "economy",
|
||||
"smartHomeCategories": [],
|
||||
"minValue": null,
|
||||
"maxValue": null,
|
||||
"stepValue": 1,
|
||||
"enumValues": [
|
||||
{
|
||||
"value": "4",
|
||||
"text": "smart control",
|
||||
"icon": ""
|
||||
},
|
||||
{
|
||||
"value": "0",
|
||||
"text": "economy",
|
||||
"icon": ""
|
||||
},
|
||||
{
|
||||
"value": "1",
|
||||
"text": "normal",
|
||||
"icon": ""
|
||||
},
|
||||
{
|
||||
"value": "2",
|
||||
"text": "luxury",
|
||||
"icon": ""
|
||||
}
|
||||
],
|
||||
"scaleValue": "1",
|
||||
"zoneId": null
|
||||
}
|
||||
]
|
||||
|
@ -3996,9 +3996,9 @@
|
||||
"parameterUnit": "",
|
||||
"writable": true,
|
||||
"timestamp": "2024-02-14T08:36:05+00:00",
|
||||
"value": 0,
|
||||
"value": 0.0,
|
||||
"strVal": "economy",
|
||||
"smartHomeCategories": [],
|
||||
"smartHomeCategories": ["test"],
|
||||
"minValue": null,
|
||||
"maxValue": null,
|
||||
"stepValue": 1,
|
||||
|
@ -1012,6 +1012,44 @@
|
||||
],
|
||||
"scaleValue": "1",
|
||||
"zoneId": null
|
||||
},
|
||||
{
|
||||
"category": "NIBEF F730 CU 3x400V",
|
||||
"parameterId": "47041",
|
||||
"parameterName": "comfort mode",
|
||||
"parameterUnit": "",
|
||||
"writable": true,
|
||||
"timestamp": "2024-05-22T15:02:03+00:00",
|
||||
"value": 0,
|
||||
"strVal": "economy",
|
||||
"smartHomeCategories": [],
|
||||
"minValue": null,
|
||||
"maxValue": null,
|
||||
"stepValue": 1,
|
||||
"enumValues": [
|
||||
{
|
||||
"value": "4",
|
||||
"text": "smart control",
|
||||
"icon": ""
|
||||
},
|
||||
{
|
||||
"value": "0",
|
||||
"text": "economy",
|
||||
"icon": ""
|
||||
},
|
||||
{
|
||||
"value": "1",
|
||||
"text": "normal",
|
||||
"icon": ""
|
||||
},
|
||||
{
|
||||
"value": "2",
|
||||
"text": "luxury",
|
||||
"icon": ""
|
||||
}
|
||||
],
|
||||
"scaleValue": "1",
|
||||
"zoneId": null
|
||||
}
|
||||
]
|
||||
|
||||
@ -2017,6 +2055,44 @@
|
||||
],
|
||||
"scaleValue": "1",
|
||||
"zoneId": null
|
||||
},
|
||||
{
|
||||
"category": "NIBEF F730 CU 3x400V",
|
||||
"parameterId": "47041",
|
||||
"parameterName": "comfort mode",
|
||||
"parameterUnit": "",
|
||||
"writable": true,
|
||||
"timestamp": "2024-05-22T15:02:03+00:00",
|
||||
"value": 0,
|
||||
"strVal": "economy",
|
||||
"smartHomeCategories": [],
|
||||
"minValue": null,
|
||||
"maxValue": null,
|
||||
"stepValue": 1,
|
||||
"enumValues": [
|
||||
{
|
||||
"value": "4",
|
||||
"text": "smart control",
|
||||
"icon": ""
|
||||
},
|
||||
{
|
||||
"value": "0",
|
||||
"text": "economy",
|
||||
"icon": ""
|
||||
},
|
||||
{
|
||||
"value": "1",
|
||||
"text": "normal",
|
||||
"icon": ""
|
||||
},
|
||||
{
|
||||
"value": "2",
|
||||
"text": "luxury",
|
||||
"icon": ""
|
||||
}
|
||||
],
|
||||
"scaleValue": "1",
|
||||
"zoneId": null
|
||||
}
|
||||
]
|
||||
|
||||
|
89
tests/components/myuplink/test_select.py
Normal file
89
tests/components/myuplink/test_select.py
Normal file
@ -0,0 +1,89 @@
|
||||
"""Tests for myuplink select module."""
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from aiohttp import ClientError
|
||||
import pytest
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_OPTION,
|
||||
SERVICE_SELECT_OPTION,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
TEST_PLATFORM = Platform.SELECT
|
||||
pytestmark = pytest.mark.parametrize("platforms", [(TEST_PLATFORM,)])
|
||||
|
||||
ENTITY_ID = "select.gotham_city_comfort_mode"
|
||||
ENTITY_FRIENDLY_NAME = "Gotham City comfort mode"
|
||||
ENTITY_UID = "robin-r-1234-20240201-123456-aa-bb-cc-dd-ee-ff-47041"
|
||||
|
||||
|
||||
async def test_select_entity(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
mock_myuplink_client: MagicMock,
|
||||
setup_platform: None,
|
||||
) -> None:
|
||||
"""Test that the entities are registered in the entity registry."""
|
||||
|
||||
entry = entity_registry.async_get(ENTITY_ID)
|
||||
assert entry.unique_id == ENTITY_UID
|
||||
|
||||
# Test the select attributes are correct.
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
assert state.state == "Economy"
|
||||
assert state.attributes == {
|
||||
"options": ["Smart control", "Economy", "Normal", "Luxury"],
|
||||
"friendly_name": ENTITY_FRIENDLY_NAME,
|
||||
}
|
||||
|
||||
|
||||
async def test_selecting(
|
||||
hass: HomeAssistant,
|
||||
mock_myuplink_client: MagicMock,
|
||||
setup_platform: None,
|
||||
) -> None:
|
||||
"""Test select option service."""
|
||||
|
||||
await hass.services.async_call(
|
||||
TEST_PLATFORM,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_OPTION: "Economy"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
mock_myuplink_client.async_set_device_points.assert_called_once()
|
||||
|
||||
# Test handling of exception from API.
|
||||
|
||||
mock_myuplink_client.async_set_device_points.side_effect = ClientError
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.services.async_call(
|
||||
TEST_PLATFORM,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_OPTION: "Economy"},
|
||||
blocking=True,
|
||||
)
|
||||
assert mock_myuplink_client.async_set_device_points.call_count == 2
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"load_device_points_file",
|
||||
["device_points_nibe_smo20.json"],
|
||||
)
|
||||
async def test_entity_registry_smo20(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
mock_myuplink_client: MagicMock,
|
||||
setup_platform: None,
|
||||
) -> None:
|
||||
"""Test that the entities are registered in the entity registry."""
|
||||
|
||||
entry = entity_registry.async_get("select.gotham_city_all")
|
||||
assert entry.unique_id == "robin-r-1234-20240201-123456-aa-bb-cc-dd-ee-ff-47660"
|
Loading…
x
Reference in New Issue
Block a user