Add timer support to mobile app (#121469)

* Add timer support to mobile app

* Fix tests

* Make it time-sensitive
This commit is contained in:
Paulus Schoutsen 2024-07-18 01:40:05 +02:00 committed by GitHub
parent 4ae6e38800
commit 454ca0ce95
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 139 additions and 3 deletions

View file

@ -1,9 +1,10 @@
"""Integrates Native Apps to Home Assistant.""" """Integrates Native Apps to Home Assistant."""
from contextlib import suppress from contextlib import suppress
from functools import partial
from typing import Any from typing import Any
from homeassistant.components import cloud, notify as hass_notify from homeassistant.components import cloud, intent, notify as hass_notify
from homeassistant.components.webhook import ( from homeassistant.components.webhook import (
async_register as webhook_register, async_register as webhook_register,
async_unregister as webhook_unregister, async_unregister as webhook_unregister,
@ -46,7 +47,8 @@ from .const import (
) )
from .helpers import savable_state from .helpers import savable_state
from .http_api import RegistrationsView from .http_api import RegistrationsView
from .util import async_create_cloud_hook from .timers import async_handle_timer_event
from .util import async_create_cloud_hook, supports_push
from .webhook import handle_webhook from .webhook import handle_webhook
PLATFORMS = [Platform.BINARY_SENSOR, Platform.DEVICE_TRACKER, Platform.SENSOR] PLATFORMS = [Platform.BINARY_SENSOR, Platform.DEVICE_TRACKER, Platform.SENSOR]
@ -133,6 +135,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
if supports_push(hass, webhook_id):
entry.async_on_unload(
intent.async_register_timer_handler(
hass, device.id, partial(async_handle_timer_event, hass, entry)
)
)
await hass_notify.async_reload(hass, DOMAIN) await hass_notify.async_reload(hass, DOMAIN)
return True return True

View file

@ -4,7 +4,14 @@
"after_dependencies": ["cloud", "camera", "conversation", "notify"], "after_dependencies": ["cloud", "camera", "conversation", "notify"],
"codeowners": ["@home-assistant/core"], "codeowners": ["@home-assistant/core"],
"config_flow": true, "config_flow": true,
"dependencies": ["http", "webhook", "person", "tag", "websocket_api"], "dependencies": [
"http",
"intent",
"person",
"tag",
"webhook",
"websocket_api"
],
"documentation": "https://www.home-assistant.io/integrations/mobile_app", "documentation": "https://www.home-assistant.io/integrations/mobile_app",
"iot_class": "local_push", "iot_class": "local_push",
"loggers": ["nacl"], "loggers": ["nacl"],

View file

@ -0,0 +1,52 @@
"""Timers for the mobile app."""
from datetime import timedelta
from homeassistant.components import notify
from homeassistant.components.intent.timers import TimerEventType, TimerInfo
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICE_ID
from homeassistant.core import HomeAssistant, callback
from . import device_action
@callback
def async_handle_timer_event(
hass: HomeAssistant,
entry: ConfigEntry,
event_type: TimerEventType,
timer_info: TimerInfo,
) -> None:
"""Handle timer events."""
if event_type != TimerEventType.FINISHED:
return
if timer_info.name:
message = f"{timer_info.name} finished"
else:
message = f"{timedelta(seconds=timer_info.created_seconds)} timer finished"
entry.async_create_task(
hass,
device_action.async_call_action_from_config(
hass,
{
CONF_DEVICE_ID: timer_info.device_id,
notify.ATTR_MESSAGE: message,
notify.ATTR_DATA: {
"group": "timers",
# Android
"channel": "Timers",
"importance": "high",
# iOS
"push": {
"interruption-level": "time-sensitive",
},
},
},
{},
None,
),
"mobile_app_timer_notification",
)

View file

@ -0,0 +1,68 @@
"""Test mobile app timers."""
from unittest.mock import patch
import pytest
from homeassistant.components.mobile_app import DATA_DEVICES, DOMAIN
from homeassistant.core import HomeAssistant
from homeassistant.helpers import intent as intent_helper
@pytest.mark.parametrize(
("intent_args", "message"),
[
(
{},
"0:02:00 timer finished",
),
(
{"name": {"value": "pizza"}},
"pizza finished",
),
],
)
async def test_timer_events(
hass: HomeAssistant, push_registration, intent_args: dict, message: str
) -> None:
"""Test for timer events."""
webhook_id = push_registration["webhook_id"]
device_id = hass.data[DOMAIN][DATA_DEVICES][webhook_id].id
await intent_helper.async_handle(
hass,
"test",
intent_helper.INTENT_START_TIMER,
{
"minutes": {"value": 2},
}
| intent_args,
device_id=device_id,
)
with patch(
"homeassistant.components.mobile_app.notify.MobileAppNotificationService.async_send_message"
) as mock_send_message:
await intent_helper.async_handle(
hass,
"test",
intent_helper.INTENT_DECREASE_TIMER,
{
"minutes": {"value": 2},
},
device_id=device_id,
)
await hass.async_block_till_done()
assert mock_send_message.mock_calls[0][2] == {
"target": [webhook_id],
"message": message,
"data": {
"channel": "Timers",
"group": "timers",
"importance": "high",
"push": {
"interruption-level": "time-sensitive",
},
},
}