diff --git a/homeassistant/components/sensor/__init__.py b/homeassistant/components/sensor/__init__.py index 929af262cdb..9480c5fe464 100644 --- a/homeassistant/components/sensor/__init__.py +++ b/homeassistant/components/sensor/__init__.py @@ -77,6 +77,7 @@ from .const import ( # noqa: F401 SensorDeviceClass, SensorStateClass, ) +from .websocket_api import async_setup as async_setup_ws_api _LOGGER: Final = logging.getLogger(__name__) @@ -109,6 +110,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: _LOGGER, DOMAIN, hass, SCAN_INTERVAL ) + async_setup_ws_api(hass) await component.async_setup(config) return True diff --git a/homeassistant/components/sensor/websocket_api.py b/homeassistant/components/sensor/websocket_api.py new file mode 100644 index 00000000000..10699b8c1c6 --- /dev/null +++ b/homeassistant/components/sensor/websocket_api.py @@ -0,0 +1,35 @@ +"""The sensor websocket API.""" +from __future__ import annotations + +from typing import Any + +import voluptuous as vol + +from homeassistant.components import websocket_api +from homeassistant.core import HomeAssistant, callback + +from .const import DEVICE_CLASS_UNITS, UNIT_CONVERTERS + + +@callback +def async_setup(hass: HomeAssistant) -> None: + """Set up the sensor websocket API.""" + websocket_api.async_register_command(hass, ws_device_class_units) + + +@callback +@websocket_api.websocket_command( + { + vol.Required("type"): "sensor/device_class_convertible_units", + vol.Required("device_class"): str, + } +) +def ws_device_class_units( + hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict[str, Any] +) -> None: + """Return supported units for a device class.""" + device_class = msg["device_class"] + convertible_units = set() + if device_class in UNIT_CONVERTERS and device_class in DEVICE_CLASS_UNITS: + convertible_units = DEVICE_CLASS_UNITS[device_class] + connection.send_result(msg["id"], {"units": convertible_units}) diff --git a/tests/components/sensor/test_websocket_api.py b/tests/components/sensor/test_websocket_api.py new file mode 100644 index 00000000000..50945956d6f --- /dev/null +++ b/tests/components/sensor/test_websocket_api.py @@ -0,0 +1,53 @@ +"""Test the sensor websocket API.""" +from pytest_unordered import unordered + +from homeassistant.components.sensor.const import DOMAIN +from homeassistant.core import HomeAssistant +from homeassistant.setup import async_setup_component + + +async def test_device_class_units(hass: HomeAssistant, hass_ws_client) -> None: + """Test we can get supported units.""" + assert await async_setup_component(hass, DOMAIN, {}) + + client = await hass_ws_client(hass) + + # Device class with units which sensor allows customizing & converting + await client.send_json( + { + "id": 1, + "type": "sensor/device_class_convertible_units", + "device_class": "speed", + } + ) + msg = await client.receive_json() + assert msg["success"] + assert msg["result"] == { + "units": unordered( + ["km/h", "kn", "mph", "in/h", "in/d", "ft/s", "mm/d", "mm/h", "m/s"] + ) + } + + # Device class with units which sensor doesn't allow customizing & converting + await client.send_json( + { + "id": 2, + "type": "sensor/device_class_convertible_units", + "device_class": "energy", + } + ) + msg = await client.receive_json() + assert msg["success"] + assert msg["result"] == {"units": []} + + # Unknown device class + await client.send_json( + { + "id": 3, + "type": "sensor/device_class_convertible_units", + "device_class": "kebabsås", + } + ) + msg = await client.receive_json() + assert msg["success"] + assert msg["result"] == {"units": unordered([])}