diff --git a/homeassistant/components/blebox/__init__.py b/homeassistant/components/blebox/__init__.py index 383e5a95f4e..ff907d728b7 100644 --- a/homeassistant/components/blebox/__init__.py +++ b/homeassistant/components/blebox/__init__.py @@ -17,12 +17,13 @@ from .const import DEFAULT_SETUP_TIMEOUT, DOMAIN, PRODUCT _LOGGER = logging.getLogger(__name__) PLATFORMS = [ + Platform.AIR_QUALITY, + Platform.BUTTON, + Platform.CLIMATE, Platform.COVER, + Platform.LIGHT, Platform.SENSOR, Platform.SWITCH, - Platform.AIR_QUALITY, - Platform.LIGHT, - Platform.CLIMATE, ] PARALLEL_UPDATES = 0 diff --git a/homeassistant/components/blebox/button.py b/homeassistant/components/blebox/button.py new file mode 100644 index 00000000000..01de5fa56b7 --- /dev/null +++ b/homeassistant/components/blebox/button.py @@ -0,0 +1,48 @@ +"""BleBox button entities implementation.""" +from __future__ import annotations + +from homeassistant.components.button import ButtonDeviceClass, ButtonEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import BleBoxEntity, create_blebox_entities + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up a BleBox button entry.""" + create_blebox_entities( + hass, config_entry, async_add_entities, BleBoxButtonEntity, "buttons" + ) + + +class BleBoxButtonEntity(BleBoxEntity, ButtonEntity): + """Representation of BleBox buttons.""" + + def __init__(self, feature): + """Initialize a BleBox button feature.""" + super().__init__(feature) + self._attr_device_class = ButtonDeviceClass.UPDATE + self._attr_icon = self.get_icon() + + def get_icon(self): + """Return icon for endpoint.""" + if "up" in self._feature.query_string: + return "mdi:arrow-up-circle" + if "down" in self._feature.query_string: + return "mdi:arrow-down-circle" + if "fav" in self._feature.query_string: + return "mdi:heart-circle" + if "open" in self._feature.query_string: + return "mdi:arrow-up-circle" + if "close" in self._feature.query_string: + return "mdi:arrow-down-circle" + return "" + + async def async_press(self) -> None: + """Handle the button press.""" + await self._feature.set() diff --git a/homeassistant/components/blebox/const.py b/homeassistant/components/blebox/const.py index 013a6501068..533c33f37bb 100644 --- a/homeassistant/components/blebox/const.py +++ b/homeassistant/components/blebox/const.py @@ -1,9 +1,5 @@ """Constants for the BleBox devices integration.""" -from homeassistant.components.cover import CoverDeviceClass -from homeassistant.components.sensor import SensorDeviceClass -from homeassistant.components.switch import SwitchDeviceClass -from homeassistant.const import TEMP_CELSIUS DOMAIN = "blebox" PRODUCT = "product" @@ -16,16 +12,6 @@ CANNOT_CONNECT = "cannot_connect" UNSUPPORTED_VERSION = "unsupported_version" UNKNOWN = "unknown" -BLEBOX_TO_HASS_DEVICE_CLASSES = { - "shutter": CoverDeviceClass.SHUTTER, - "gatebox": CoverDeviceClass.DOOR, - "gate": CoverDeviceClass.GATE, - "relay": SwitchDeviceClass.SWITCH, - "temperature": SensorDeviceClass.TEMPERATURE, -} - - -BLEBOX_TO_UNIT_MAP = {"celsius": TEMP_CELSIUS} DEFAULT_HOST = "192.168.0.2" DEFAULT_PORT = 80 diff --git a/homeassistant/components/blebox/cover.py b/homeassistant/components/blebox/cover.py index 8763ec34d34..882356f1a77 100644 --- a/homeassistant/components/blebox/cover.py +++ b/homeassistant/components/blebox/cover.py @@ -5,6 +5,7 @@ from typing import Any from homeassistant.components.cover import ( ATTR_POSITION, + CoverDeviceClass, CoverEntity, CoverEntityFeature, ) @@ -14,7 +15,13 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import BleBoxEntity, create_blebox_entities -from .const import BLEBOX_TO_HASS_DEVICE_CLASSES + +BLEBOX_TO_COVER_DEVICE_CLASSES = { + "gate": CoverDeviceClass.GATE, + "gatebox": CoverDeviceClass.DOOR, + "shutter": CoverDeviceClass.SHUTTER, +} + BLEBOX_TO_HASS_COVER_STATES = { None: None, @@ -49,7 +56,7 @@ class BleBoxCoverEntity(BleBoxEntity, CoverEntity): def __init__(self, feature): """Initialize a BleBox cover feature.""" super().__init__(feature) - self._attr_device_class = BLEBOX_TO_HASS_DEVICE_CLASSES[feature.device_class] + self._attr_device_class = BLEBOX_TO_COVER_DEVICE_CLASSES[feature.device_class] position = CoverEntityFeature.SET_POSITION if feature.is_slider else 0 stop = CoverEntityFeature.STOP if feature.has_stop else 0 self._attr_supported_features = ( diff --git a/homeassistant/components/blebox/manifest.json b/homeassistant/components/blebox/manifest.json index 08554695316..49d44db8f01 100644 --- a/homeassistant/components/blebox/manifest.json +++ b/homeassistant/components/blebox/manifest.json @@ -3,7 +3,7 @@ "name": "BleBox devices", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/blebox", - "requirements": ["blebox_uniapi==2.0.1"], + "requirements": ["blebox_uniapi==2.0.2"], "codeowners": ["@bbx-a", "@riokuu"], "iot_class": "local_polling", "loggers": ["blebox_uniapi"] diff --git a/homeassistant/components/blebox/sensor.py b/homeassistant/components/blebox/sensor.py index 2c317acada8..663af970e3e 100644 --- a/homeassistant/components/blebox/sensor.py +++ b/homeassistant/components/blebox/sensor.py @@ -1,11 +1,15 @@ """BleBox sensor entities.""" -from homeassistant.components.sensor import SensorEntity +from homeassistant.components.sensor import SensorDeviceClass, SensorEntity from homeassistant.config_entries import ConfigEntry +from homeassistant.const import TEMP_CELSIUS from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import BleBoxEntity, create_blebox_entities -from .const import BLEBOX_TO_HASS_DEVICE_CLASSES, BLEBOX_TO_UNIT_MAP + +BLEBOX_TO_UNIT_MAP = {"celsius": TEMP_CELSIUS} + +BLEBOX_TO_SENSOR_DEVICE_CLASS = {"temperature": SensorDeviceClass.TEMPERATURE} async def async_setup_entry( @@ -27,7 +31,7 @@ class BleBoxSensorEntity(BleBoxEntity, SensorEntity): """Initialize a BleBox sensor feature.""" super().__init__(feature) self._attr_native_unit_of_measurement = BLEBOX_TO_UNIT_MAP[feature.unit] - self._attr_device_class = BLEBOX_TO_HASS_DEVICE_CLASSES[feature.device_class] + self._attr_device_class = BLEBOX_TO_SENSOR_DEVICE_CLASS[feature.device_class] @property def native_value(self): diff --git a/homeassistant/components/blebox/switch.py b/homeassistant/components/blebox/switch.py index 50eba1d2c4a..f9c866244c7 100644 --- a/homeassistant/components/blebox/switch.py +++ b/homeassistant/components/blebox/switch.py @@ -1,13 +1,12 @@ """BleBox switch implementation.""" from datetime import timedelta -from homeassistant.components.switch import SwitchEntity +from homeassistant.components.switch import SwitchDeviceClass, SwitchEntity from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import BleBoxEntity, create_blebox_entities -from .const import BLEBOX_TO_HASS_DEVICE_CLASSES SCAN_INTERVAL = timedelta(seconds=5) @@ -29,7 +28,7 @@ class BleBoxSwitchEntity(BleBoxEntity, SwitchEntity): def __init__(self, feature): """Initialize a BleBox switch feature.""" super().__init__(feature) - self._attr_device_class = BLEBOX_TO_HASS_DEVICE_CLASSES[feature.device_class] + self._attr_device_class = SwitchDeviceClass.SWITCH @property def is_on(self): diff --git a/requirements_all.txt b/requirements_all.txt index 75da41fcdb9..7a9c482ea84 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -405,7 +405,7 @@ bizkaibus==0.1.1 bleak==0.14.3 # homeassistant.components.blebox -blebox_uniapi==2.0.1 +blebox_uniapi==2.0.2 # homeassistant.components.blink blinkpy==0.19.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index d95ea62c203..5b7077c8ebd 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -320,7 +320,7 @@ bimmer_connected==0.9.6 bleak==0.14.3 # homeassistant.components.blebox -blebox_uniapi==2.0.1 +blebox_uniapi==2.0.2 # homeassistant.components.blink blinkpy==0.19.0 diff --git a/tests/components/blebox/test_button.py b/tests/components/blebox/test_button.py new file mode 100644 index 00000000000..22e1b8cb734 --- /dev/null +++ b/tests/components/blebox/test_button.py @@ -0,0 +1,68 @@ +"""Blebox button entities tests.""" +import logging +from unittest.mock import PropertyMock + +import blebox_uniapi +import pytest + +from homeassistant.components.button import ButtonDeviceClass +from homeassistant.const import ATTR_ICON + +from .conftest import async_setup_entity, mock_feature + +query_icon_matching = [ + ("up", "mdi:arrow-up-circle"), + ("down", "mdi:arrow-down-circle"), + ("fav", "mdi:heart-circle"), + ("open", "mdi:arrow-up-circle"), + ("close", "mdi:arrow-down-circle"), +] + + +@pytest.fixture(name="tvliftbox") +def tv_lift_box_fixture(caplog): + """Return simple button entity mock.""" + caplog.set_level(logging.ERROR) + + feature = mock_feature( + "buttons", + blebox_uniapi.button.Button, + unique_id="BleBox-tvLiftBox-4a3fdaad90aa-open_or_stop", + full_name="tvLiftBox-open_or_stop", + control_type=blebox_uniapi.button.ControlType.OPEN, + ) + + product = feature.product + type(product).name = PropertyMock(return_value="My tvLiftBox") + type(product).model = PropertyMock(return_value="tvLiftBox") + type(product)._query_string = PropertyMock(return_value="open_or_stop") + + return (feature, "button.tvliftbox_open_or_stop") + + +async def test_tvliftbox_init(tvliftbox, hass, config, caplog): + """Test tvLiftBox initialisation.""" + caplog.set_level(logging.ERROR) + + _, entity_id = tvliftbox + entry = await async_setup_entity(hass, config, entity_id) + state = hass.states.get(entity_id) + + assert entry.unique_id == "BleBox-tvLiftBox-4a3fdaad90aa-open_or_stop" + + assert state.attributes["device_class"] == ButtonDeviceClass.UPDATE + + assert state.name == "tvLiftBox-open_or_stop" + + +@pytest.mark.parametrize("input", query_icon_matching) +async def test_get_icon(input, tvliftbox, hass, config, caplog): + """Test if proper icon is returned.""" + caplog.set_level(logging.ERROR) + + feature_mock, entity_id = tvliftbox + feature_mock.query_string = input[0] + _ = await async_setup_entity(hass, config, entity_id) + state = hass.states.get(entity_id) + + assert state.attributes[ATTR_ICON] == input[1]