mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Add blebox tvLiftBox support (#74395)
* Added tvLiftBox support. * Changes after @epenet code review. * After @epenet code review, dictionaries moved to relevant modules. * Import path changed to full path. * Removed redundant code in BLEBOX_TO_<platform>_DEVICE_CLASSES for switch and button platforms. * Post isort on covers. * Added tests, required version bump. As property was added inside dependency.
This commit is contained in:
parent
c80066072c
commit
ca93aacc57
@ -17,12 +17,13 @@ from .const import DEFAULT_SETUP_TIMEOUT, DOMAIN, PRODUCT
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
PLATFORMS = [
|
PLATFORMS = [
|
||||||
|
Platform.AIR_QUALITY,
|
||||||
|
Platform.BUTTON,
|
||||||
|
Platform.CLIMATE,
|
||||||
Platform.COVER,
|
Platform.COVER,
|
||||||
|
Platform.LIGHT,
|
||||||
Platform.SENSOR,
|
Platform.SENSOR,
|
||||||
Platform.SWITCH,
|
Platform.SWITCH,
|
||||||
Platform.AIR_QUALITY,
|
|
||||||
Platform.LIGHT,
|
|
||||||
Platform.CLIMATE,
|
|
||||||
]
|
]
|
||||||
|
|
||||||
PARALLEL_UPDATES = 0
|
PARALLEL_UPDATES = 0
|
||||||
|
48
homeassistant/components/blebox/button.py
Normal file
48
homeassistant/components/blebox/button.py
Normal file
@ -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()
|
@ -1,9 +1,5 @@
|
|||||||
"""Constants for the BleBox devices integration."""
|
"""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"
|
DOMAIN = "blebox"
|
||||||
PRODUCT = "product"
|
PRODUCT = "product"
|
||||||
@ -16,16 +12,6 @@ CANNOT_CONNECT = "cannot_connect"
|
|||||||
UNSUPPORTED_VERSION = "unsupported_version"
|
UNSUPPORTED_VERSION = "unsupported_version"
|
||||||
UNKNOWN = "unknown"
|
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_HOST = "192.168.0.2"
|
||||||
DEFAULT_PORT = 80
|
DEFAULT_PORT = 80
|
||||||
|
@ -5,6 +5,7 @@ from typing import Any
|
|||||||
|
|
||||||
from homeassistant.components.cover import (
|
from homeassistant.components.cover import (
|
||||||
ATTR_POSITION,
|
ATTR_POSITION,
|
||||||
|
CoverDeviceClass,
|
||||||
CoverEntity,
|
CoverEntity,
|
||||||
CoverEntityFeature,
|
CoverEntityFeature,
|
||||||
)
|
)
|
||||||
@ -14,7 +15,13 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import BleBoxEntity, create_blebox_entities
|
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 = {
|
BLEBOX_TO_HASS_COVER_STATES = {
|
||||||
None: None,
|
None: None,
|
||||||
@ -49,7 +56,7 @@ class BleBoxCoverEntity(BleBoxEntity, CoverEntity):
|
|||||||
def __init__(self, feature):
|
def __init__(self, feature):
|
||||||
"""Initialize a BleBox cover feature."""
|
"""Initialize a BleBox cover feature."""
|
||||||
super().__init__(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
|
position = CoverEntityFeature.SET_POSITION if feature.is_slider else 0
|
||||||
stop = CoverEntityFeature.STOP if feature.has_stop else 0
|
stop = CoverEntityFeature.STOP if feature.has_stop else 0
|
||||||
self._attr_supported_features = (
|
self._attr_supported_features = (
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "BleBox devices",
|
"name": "BleBox devices",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/blebox",
|
"documentation": "https://www.home-assistant.io/integrations/blebox",
|
||||||
"requirements": ["blebox_uniapi==2.0.1"],
|
"requirements": ["blebox_uniapi==2.0.2"],
|
||||||
"codeowners": ["@bbx-a", "@riokuu"],
|
"codeowners": ["@bbx-a", "@riokuu"],
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"loggers": ["blebox_uniapi"]
|
"loggers": ["blebox_uniapi"]
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
"""BleBox sensor entities."""
|
"""BleBox sensor entities."""
|
||||||
from homeassistant.components.sensor import SensorEntity
|
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import TEMP_CELSIUS
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import BleBoxEntity, create_blebox_entities
|
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(
|
async def async_setup_entry(
|
||||||
@ -27,7 +31,7 @@ class BleBoxSensorEntity(BleBoxEntity, SensorEntity):
|
|||||||
"""Initialize a BleBox sensor feature."""
|
"""Initialize a BleBox sensor feature."""
|
||||||
super().__init__(feature)
|
super().__init__(feature)
|
||||||
self._attr_native_unit_of_measurement = BLEBOX_TO_UNIT_MAP[feature.unit]
|
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
|
@property
|
||||||
def native_value(self):
|
def native_value(self):
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
"""BleBox switch implementation."""
|
"""BleBox switch implementation."""
|
||||||
from datetime import timedelta
|
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.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import BleBoxEntity, create_blebox_entities
|
from . import BleBoxEntity, create_blebox_entities
|
||||||
from .const import BLEBOX_TO_HASS_DEVICE_CLASSES
|
|
||||||
|
|
||||||
SCAN_INTERVAL = timedelta(seconds=5)
|
SCAN_INTERVAL = timedelta(seconds=5)
|
||||||
|
|
||||||
@ -29,7 +28,7 @@ class BleBoxSwitchEntity(BleBoxEntity, SwitchEntity):
|
|||||||
def __init__(self, feature):
|
def __init__(self, feature):
|
||||||
"""Initialize a BleBox switch feature."""
|
"""Initialize a BleBox switch feature."""
|
||||||
super().__init__(feature)
|
super().__init__(feature)
|
||||||
self._attr_device_class = BLEBOX_TO_HASS_DEVICE_CLASSES[feature.device_class]
|
self._attr_device_class = SwitchDeviceClass.SWITCH
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self):
|
||||||
|
@ -405,7 +405,7 @@ bizkaibus==0.1.1
|
|||||||
bleak==0.14.3
|
bleak==0.14.3
|
||||||
|
|
||||||
# homeassistant.components.blebox
|
# homeassistant.components.blebox
|
||||||
blebox_uniapi==2.0.1
|
blebox_uniapi==2.0.2
|
||||||
|
|
||||||
# homeassistant.components.blink
|
# homeassistant.components.blink
|
||||||
blinkpy==0.19.0
|
blinkpy==0.19.0
|
||||||
|
@ -320,7 +320,7 @@ bimmer_connected==0.9.6
|
|||||||
bleak==0.14.3
|
bleak==0.14.3
|
||||||
|
|
||||||
# homeassistant.components.blebox
|
# homeassistant.components.blebox
|
||||||
blebox_uniapi==2.0.1
|
blebox_uniapi==2.0.2
|
||||||
|
|
||||||
# homeassistant.components.blink
|
# homeassistant.components.blink
|
||||||
blinkpy==0.19.0
|
blinkpy==0.19.0
|
||||||
|
68
tests/components/blebox/test_button.py
Normal file
68
tests/components/blebox/test_button.py
Normal file
@ -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]
|
Loading…
x
Reference in New Issue
Block a user