Restore SmartThings button event (#140044)

* Restore SmartThings button event

* Fix
This commit is contained in:
Joost Lekkerkerker 2025-03-07 15:46:00 +01:00 committed by GitHub
parent cd2ce5e11b
commit e51154ae69
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 141 additions and 4 deletions

View File

@ -12,6 +12,7 @@ from pysmartthings import (
Attribute, Attribute,
Capability, Capability,
Device, Device,
DeviceEvent,
Scene, Scene,
SmartThings, SmartThings,
SmartThingsAuthenticationFailedError, SmartThingsAuthenticationFailedError,
@ -29,7 +30,14 @@ from homeassistant.helpers.config_entry_oauth2_flow import (
async_get_config_entry_implementation, async_get_config_entry_implementation,
) )
from .const import CONF_INSTALLED_APP_ID, CONF_LOCATION_ID, DOMAIN, MAIN, OLD_DATA from .const import (
CONF_INSTALLED_APP_ID,
CONF_LOCATION_ID,
DOMAIN,
EVENT_BUTTON,
MAIN,
OLD_DATA,
)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -141,6 +149,28 @@ async def async_setup_entry(hass: HomeAssistant, entry: SmartThingsConfigEntry)
rooms=rooms, rooms=rooms,
) )
def handle_button_press(event: DeviceEvent) -> None:
"""Handle a button press."""
if (
event.capability is Capability.BUTTON
and event.attribute is Attribute.BUTTON
):
hass.bus.async_fire(
EVENT_BUTTON,
{
"component_id": event.component_id,
"device_id": event.device_id,
"location_id": event.location_id,
"value": event.value,
"name": entry.runtime_data.devices[event.device_id].device.label,
"data": event.data,
},
)
entry.async_on_unload(
client.add_unspecified_device_event_listener(handle_button_press)
)
entry.async_create_background_task( entry.async_create_background_task(
hass, hass,
client.subscribe( client.subscribe(

View File

@ -32,3 +32,5 @@ CONF_REFRESH_TOKEN = "refresh_token"
MAIN = "main" MAIN = "main"
OLD_DATA = "old_data" OLD_DATA = "old_data"
EVENT_BUTTON = "smartthings.button"

View File

@ -68,6 +68,8 @@ async def trigger_update(
value, value,
data, data,
) )
for call in mock.add_unspecified_device_event_listener.call_args_list:
call[0][0](event)
for call in mock.add_device_event_listener.call_args_list: for call in mock.add_device_event_listener.call_args_list:
if call[0][0] == device_id: if call[0][0] == device_id:
call[0][3](event) call[0][3](event)

View File

@ -0,0 +1,21 @@
{
"components": {
"main": {
"button": {
"button": {
"value": "pushed",
"timestamp": "2025-03-07T12:20:43.363Z"
},
"numberOfButtons": {
"value": 1,
"timestamp": "2025-03-07T12:20:43.363Z"
},
"supportedButtonValues": {
"value": ["pushed", "held", "pushed_2x"],
"timestamp": "2025-03-07T12:20:43.363Z"
}
},
"refresh": {}
}
}
}

View File

@ -0,0 +1,49 @@
{
"items": [
{
"deviceId": "c4bdd19f-85d1-4d58-8f9c-e75ac3cf113b",
"name": "button",
"label": "button",
"manufacturerName": "SmartThingsCommunity",
"presentationId": "238c483a-10e8-359b-b032-1be2b2fcdee7",
"locationId": "88a3a314-f0c8-40b4-bb44-44ba06c9c42f",
"ownerId": "12d4af93-cb68-b108-87f5-625437d7371f",
"components": [
{
"id": "main",
"label": "main",
"capabilities": [
{
"id": "button",
"version": 1
},
{
"id": "refresh",
"version": 1
}
],
"categories": [
{
"name": "Other",
"categoryType": "manufacturer"
}
]
}
],
"createTime": "2025-03-07T12:20:43.273Z",
"profile": {
"id": "b045d731-4d01-35bc-8018-b3da711d8904"
},
"virtual": {
"name": "button",
"executingLocally": false
},
"type": "VIRTUAL",
"restrictionTier": 0,
"allowed": null,
"executionContext": "CLOUD",
"relationships": []
}
],
"_links": {}
}

View File

@ -1,4 +1,7 @@
# serializer version: 1 # serializer version: 1
# name: test_button_event[button]
<Event smartthings.button[L]: component_id=main, device_id=c4bdd19f-85d1-4d58-8f9c-e75ac3cf113b, location_id=abc, value=pushed, name=button, data=None>
# ---
# name: test_devices[aeotec_home_energy_meter_gen5] # name: test_devices[aeotec_home_energy_meter_gen5]
DeviceRegistryEntrySnapshot({ DeviceRegistryEntrySnapshot({
'area_id': 'toilet', 'area_id': 'toilet',

View File

@ -2,15 +2,16 @@
from unittest.mock import AsyncMock from unittest.mock import AsyncMock
from pysmartthings import DeviceResponse, DeviceStatus from pysmartthings import Attribute, Capability, DeviceResponse, DeviceStatus
import pytest import pytest
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
from homeassistant.components.smartthings import EVENT_BUTTON
from homeassistant.components.smartthings.const import DOMAIN from homeassistant.components.smartthings.const import DOMAIN
from homeassistant.core import HomeAssistant from homeassistant.core import Event, HomeAssistant
from homeassistant.helpers import device_registry as dr from homeassistant.helpers import device_registry as dr
from . import setup_integration from . import setup_integration, trigger_update
from tests.common import MockConfigEntry, load_fixture from tests.common import MockConfigEntry, load_fixture
@ -33,6 +34,35 @@ async def test_devices(
assert device == snapshot assert device == snapshot
@pytest.mark.parametrize("device_fixture", ["button"])
async def test_button_event(
hass: HomeAssistant,
devices: AsyncMock,
mock_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test button event."""
await setup_integration(hass, mock_config_entry)
events = []
def capture_event(event: Event) -> None:
events.append(event)
hass.bus.async_listen_once(EVENT_BUTTON, capture_event)
await trigger_update(
hass,
devices,
"c4bdd19f-85d1-4d58-8f9c-e75ac3cf113b",
Capability.BUTTON,
Attribute.BUTTON,
"pushed",
)
assert len(events) == 1
assert events[0] == snapshot
@pytest.mark.parametrize("device_fixture", ["da_ac_rac_000001"]) @pytest.mark.parametrize("device_fixture", ["da_ac_rac_000001"])
async def test_removing_stale_devices( async def test_removing_stale_devices(
hass: HomeAssistant, hass: HomeAssistant,