Add select platform to jvc_projector component (#111638)
* Initial commit of jvc_projector select platform * Move icon to icons.json * Apply suggestions from code review * Update tests/components/jvc_projector/test_select.py --------- Co-authored-by: Erik Montnemery <erik@montnemery.com> Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
41a86d2404
commit
d565c1a84b
5 changed files with 136 additions and 1 deletions
|
@ -18,7 +18,7 @@ from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .coordinator import JvcProjectorDataUpdateCoordinator
|
from .coordinator import JvcProjectorDataUpdateCoordinator
|
||||||
|
|
||||||
PLATFORMS = [Platform.BINARY_SENSOR, Platform.REMOTE, Platform.SENSOR]
|
PLATFORMS = [Platform.BINARY_SENSOR, Platform.REMOTE, Platform.SELECT, Platform.SENSOR]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"select": {
|
||||||
|
"input": {
|
||||||
|
"default": "mdi:hdmi-port"
|
||||||
|
}
|
||||||
|
},
|
||||||
"sensor": {
|
"sensor": {
|
||||||
"jvc_power_status": {
|
"jvc_power_status": {
|
||||||
"default": "mdi:power-plug-off",
|
"default": "mdi:power-plug-off",
|
||||||
|
|
77
homeassistant/components/jvc_projector/select.py
Normal file
77
homeassistant/components/jvc_projector/select.py
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
"""Select platform for the jvc_projector integration."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Awaitable, Callable
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Final
|
||||||
|
|
||||||
|
from jvcprojector import JvcProjector, const
|
||||||
|
|
||||||
|
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
from . import JvcProjectorDataUpdateCoordinator
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .entity import JvcProjectorEntity
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True, kw_only=True)
|
||||||
|
class JvcProjectorSelectDescription(SelectEntityDescription):
|
||||||
|
"""Describes JVC Projector select entities."""
|
||||||
|
|
||||||
|
command: Callable[[JvcProjector, str], Awaitable[None]]
|
||||||
|
|
||||||
|
|
||||||
|
OPTIONS: Final[dict[str, dict[str, str]]] = {
|
||||||
|
"input": {const.HDMI1: const.REMOTE_HDMI_1, const.HDMI2: const.REMOTE_HDMI_2}
|
||||||
|
}
|
||||||
|
|
||||||
|
SELECTS: Final[list[JvcProjectorSelectDescription]] = [
|
||||||
|
JvcProjectorSelectDescription(
|
||||||
|
key="input",
|
||||||
|
translation_key="input",
|
||||||
|
options=list(OPTIONS["input"]),
|
||||||
|
command=lambda device, option: device.remote(OPTIONS["input"][option]),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Set up the JVC Projector platform from a config entry."""
|
||||||
|
coordinator: JvcProjectorDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
|
||||||
|
async_add_entities(
|
||||||
|
JvcProjectorSelectEntity(coordinator, description) for description in SELECTS
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class JvcProjectorSelectEntity(JvcProjectorEntity, SelectEntity):
|
||||||
|
"""Representation of a JVC Projector select entity."""
|
||||||
|
|
||||||
|
entity_description: JvcProjectorSelectDescription
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
coordinator: JvcProjectorDataUpdateCoordinator,
|
||||||
|
description: JvcProjectorSelectDescription,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the entity."""
|
||||||
|
super().__init__(coordinator)
|
||||||
|
self.entity_description = description
|
||||||
|
self._attr_unique_id = f"{coordinator.unique_id}_{description.key}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_option(self) -> str | None:
|
||||||
|
"""Return the selected entity option to represent the entity state."""
|
||||||
|
return self.coordinator.data[self.entity_description.key]
|
||||||
|
|
||||||
|
async def async_select_option(self, option: str) -> None:
|
||||||
|
"""Change the selected option."""
|
||||||
|
await self.entity_description.command(self.coordinator.device, option)
|
|
@ -38,6 +38,15 @@
|
||||||
"name": "[%key:component::sensor::entity_component::power::name%]"
|
"name": "[%key:component::sensor::entity_component::power::name%]"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"select": {
|
||||||
|
"input": {
|
||||||
|
"name": "Input",
|
||||||
|
"state": {
|
||||||
|
"hdmi1": "HDMI 1",
|
||||||
|
"hdmi2": "HDMI 2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"sensor": {
|
"sensor": {
|
||||||
"jvc_power_status": {
|
"jvc_power_status": {
|
||||||
"name": "Power status",
|
"name": "Power status",
|
||||||
|
|
44
tests/components/jvc_projector/test_select.py
Normal file
44
tests/components/jvc_projector/test_select.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
"""Tests for JVC Projector select platform."""
|
||||||
|
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
from jvcprojector import const
|
||||||
|
|
||||||
|
from homeassistant.components.select import (
|
||||||
|
ATTR_OPTIONS,
|
||||||
|
DOMAIN as SELECT_DOMAIN,
|
||||||
|
SERVICE_SELECT_OPTION,
|
||||||
|
)
|
||||||
|
from homeassistant.const import ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME, ATTR_OPTION
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
INPUT_ENTITY_ID = "select.jvc_projector_input"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_input_select(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
mock_device: MagicMock,
|
||||||
|
mock_integration: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test input select."""
|
||||||
|
entity = hass.states.get(INPUT_ENTITY_ID)
|
||||||
|
assert entity
|
||||||
|
assert entity.attributes.get(ATTR_FRIENDLY_NAME) == "JVC Projector Input"
|
||||||
|
assert entity.attributes.get(ATTR_OPTIONS) == [const.HDMI1, const.HDMI2]
|
||||||
|
assert entity.state == const.HDMI1
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
SELECT_DOMAIN,
|
||||||
|
SERVICE_SELECT_OPTION,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: INPUT_ENTITY_ID,
|
||||||
|
ATTR_OPTION: const.HDMI2,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_device.remote.assert_called_once_with(const.REMOTE_HDMI_2)
|
Loading…
Add table
Reference in a new issue