mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Add support for buttons in gardena bluetooth (#96871)
* Add button to gardena * Add tests for button * Bump gardena bluetooth to 1.0.2 --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
67e3203d00
commit
80a7447030
@ -22,6 +22,7 @@ from .coordinator import Coordinator, DeviceUnavailable
|
|||||||
|
|
||||||
PLATFORMS: list[Platform] = [
|
PLATFORMS: list[Platform] = [
|
||||||
Platform.BINARY_SENSOR,
|
Platform.BINARY_SENSOR,
|
||||||
|
Platform.BUTTON,
|
||||||
Platform.NUMBER,
|
Platform.NUMBER,
|
||||||
Platform.SENSOR,
|
Platform.SENSOR,
|
||||||
Platform.SWITCH,
|
Platform.SWITCH,
|
||||||
|
60
homeassistant/components/gardena_bluetooth/button.py
Normal file
60
homeassistant/components/gardena_bluetooth/button.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
"""Support for button entities."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
from gardena_bluetooth.const import Reset
|
||||||
|
from gardena_bluetooth.parse import CharacteristicBool
|
||||||
|
|
||||||
|
from homeassistant.components.button import (
|
||||||
|
ButtonEntity,
|
||||||
|
ButtonEntityDescription,
|
||||||
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import EntityCategory
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .coordinator import Coordinator, GardenaBluetoothDescriptorEntity
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class GardenaBluetoothButtonEntityDescription(ButtonEntityDescription):
|
||||||
|
"""Description of entity."""
|
||||||
|
|
||||||
|
char: CharacteristicBool = field(default_factory=lambda: CharacteristicBool(""))
|
||||||
|
|
||||||
|
|
||||||
|
DESCRIPTIONS = (
|
||||||
|
GardenaBluetoothButtonEntityDescription(
|
||||||
|
key=Reset.factory_reset.uuid,
|
||||||
|
translation_key="factory_reset",
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
char=Reset.factory_reset,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||||
|
) -> None:
|
||||||
|
"""Set up binary sensor based on a config entry."""
|
||||||
|
coordinator: Coordinator = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
entities = [
|
||||||
|
GardenaBluetoothButton(coordinator, description)
|
||||||
|
for description in DESCRIPTIONS
|
||||||
|
if description.key in coordinator.characteristics
|
||||||
|
]
|
||||||
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
|
||||||
|
class GardenaBluetoothButton(GardenaBluetoothDescriptorEntity, ButtonEntity):
|
||||||
|
"""Representation of a binary sensor."""
|
||||||
|
|
||||||
|
entity_description: GardenaBluetoothButtonEntityDescription
|
||||||
|
|
||||||
|
async def async_press(self) -> None:
|
||||||
|
"""Trigger button action."""
|
||||||
|
await self.coordinator.write(self.entity_description.char, True)
|
@ -13,5 +13,5 @@
|
|||||||
"dependencies": ["bluetooth_adapters"],
|
"dependencies": ["bluetooth_adapters"],
|
||||||
"documentation": "https://www.home-assistant.io/integrations/gardena_bluetooth",
|
"documentation": "https://www.home-assistant.io/integrations/gardena_bluetooth",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"requirements": ["gardena_bluetooth==1.0.1"]
|
"requirements": ["gardena_bluetooth==1.0.2"]
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,11 @@
|
|||||||
"name": "Valve connection"
|
"name": "Valve connection"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"button": {
|
||||||
|
"factory_reset": {
|
||||||
|
"name": "Factory reset"
|
||||||
|
}
|
||||||
|
},
|
||||||
"number": {
|
"number": {
|
||||||
"remaining_open_time": {
|
"remaining_open_time": {
|
||||||
"name": "Remaining open time"
|
"name": "Remaining open time"
|
||||||
|
@ -820,7 +820,7 @@ fritzconnection[qr]==1.12.2
|
|||||||
gTTS==2.2.4
|
gTTS==2.2.4
|
||||||
|
|
||||||
# homeassistant.components.gardena_bluetooth
|
# homeassistant.components.gardena_bluetooth
|
||||||
gardena_bluetooth==1.0.1
|
gardena_bluetooth==1.0.2
|
||||||
|
|
||||||
# homeassistant.components.google_assistant_sdk
|
# homeassistant.components.google_assistant_sdk
|
||||||
gassist-text==0.0.10
|
gassist-text==0.0.10
|
||||||
|
@ -642,7 +642,7 @@ fritzconnection[qr]==1.12.2
|
|||||||
gTTS==2.2.4
|
gTTS==2.2.4
|
||||||
|
|
||||||
# homeassistant.components.gardena_bluetooth
|
# homeassistant.components.gardena_bluetooth
|
||||||
gardena_bluetooth==1.0.1
|
gardena_bluetooth==1.0.2
|
||||||
|
|
||||||
# homeassistant.components.google_assistant_sdk
|
# homeassistant.components.google_assistant_sdk
|
||||||
gassist-text==0.0.10
|
gassist-text==0.0.10
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
# serializer version: 1
|
||||||
|
# name: test_setup
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'friendly_name': 'Mock Title Factory reset',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'button.mock_title_factory_reset',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'unknown',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_setup.1
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'friendly_name': 'Mock Title Factory reset',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'button.mock_title_factory_reset',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'unknown',
|
||||||
|
})
|
||||||
|
# ---
|
67
tests/components/gardena_bluetooth/test_button.py
Normal file
67
tests/components/gardena_bluetooth/test_button.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
"""Test Gardena Bluetooth sensor."""
|
||||||
|
|
||||||
|
|
||||||
|
from unittest.mock import Mock, call
|
||||||
|
|
||||||
|
from gardena_bluetooth.const import Reset
|
||||||
|
import pytest
|
||||||
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
|
||||||
|
from homeassistant.const import (
|
||||||
|
ATTR_ENTITY_ID,
|
||||||
|
Platform,
|
||||||
|
)
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from . import setup_entry
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_switch_chars(mock_read_char_raw):
|
||||||
|
"""Mock data on device."""
|
||||||
|
mock_read_char_raw[Reset.factory_reset.uuid] = b"\x00"
|
||||||
|
return mock_read_char_raw
|
||||||
|
|
||||||
|
|
||||||
|
async def test_setup(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
mock_entry: MockConfigEntry,
|
||||||
|
mock_switch_chars: dict[str, bytes],
|
||||||
|
) -> None:
|
||||||
|
"""Test setup creates expected entities."""
|
||||||
|
|
||||||
|
entity_id = "button.mock_title_factory_reset"
|
||||||
|
coordinator = await setup_entry(hass, mock_entry, [Platform.BUTTON])
|
||||||
|
assert hass.states.get(entity_id) == snapshot
|
||||||
|
|
||||||
|
mock_switch_chars[Reset.factory_reset.uuid] = b"\x01"
|
||||||
|
await coordinator.async_refresh()
|
||||||
|
assert hass.states.get(entity_id) == snapshot
|
||||||
|
|
||||||
|
|
||||||
|
async def test_switching(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_entry: MockConfigEntry,
|
||||||
|
mock_client: Mock,
|
||||||
|
mock_switch_chars: dict[str, bytes],
|
||||||
|
) -> None:
|
||||||
|
"""Test switching makes correct calls."""
|
||||||
|
|
||||||
|
entity_id = "button.mock_title_factory_reset"
|
||||||
|
await setup_entry(hass, mock_entry, [Platform.BUTTON])
|
||||||
|
assert hass.states.get(entity_id)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
BUTTON_DOMAIN,
|
||||||
|
SERVICE_PRESS,
|
||||||
|
{ATTR_ENTITY_ID: entity_id},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert mock_client.write_char.mock_calls == [
|
||||||
|
call(Reset.factory_reset, True),
|
||||||
|
]
|
Loading…
x
Reference in New Issue
Block a user