diff --git a/homeassistant/components/fully_kiosk/__init__.py b/homeassistant/components/fully_kiosk/__init__.py index 95d7d59ecbf..582ae23aea4 100644 --- a/homeassistant/components/fully_kiosk/__init__.py +++ b/homeassistant/components/fully_kiosk/__init__.py @@ -15,6 +15,7 @@ PLATFORMS = [ Platform.BUTTON, Platform.CAMERA, Platform.MEDIA_PLAYER, + Platform.NOTIFY, Platform.NUMBER, Platform.SENSOR, Platform.SWITCH, diff --git a/homeassistant/components/fully_kiosk/notify.py b/homeassistant/components/fully_kiosk/notify.py new file mode 100644 index 00000000000..aa47c178f03 --- /dev/null +++ b/homeassistant/components/fully_kiosk/notify.py @@ -0,0 +1,74 @@ +"""Support for Fully Kiosk Browser notifications.""" + +from __future__ import annotations + +from dataclasses import dataclass + +from fullykiosk import FullyKioskError + +from homeassistant.components.notify import NotifyEntity, NotifyEntityDescription +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import DOMAIN +from .coordinator import FullyKioskDataUpdateCoordinator +from .entity import FullyKioskEntity + + +@dataclass(frozen=True, kw_only=True) +class FullyNotifyEntityDescription(NotifyEntityDescription): + """Fully Kiosk Browser notify entity description.""" + + cmd: str + + +NOTIFIERS: tuple[FullyNotifyEntityDescription, ...] = ( + FullyNotifyEntityDescription( + key="overlay_message", + translation_key="overlay_message", + cmd="setOverlayMessage", + ), + FullyNotifyEntityDescription( + key="tts", + translation_key="tts", + cmd="textToSpeech", + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Set up the Fully Kiosk Browser notify entities.""" + coordinator: FullyKioskDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] + async_add_entities( + FullyNotifyEntity(coordinator, description) for description in NOTIFIERS + ) + + +class FullyNotifyEntity(FullyKioskEntity, NotifyEntity): + """Implement the notify entity for Fully Kiosk Browser.""" + + entity_description: FullyNotifyEntityDescription + + def __init__( + self, + coordinator: FullyKioskDataUpdateCoordinator, + description: FullyNotifyEntityDescription, + ) -> None: + """Initialize the entity.""" + FullyKioskEntity.__init__(self, coordinator) + NotifyEntity.__init__(self) + self.entity_description = description + self._attr_unique_id = f"{coordinator.data['deviceID']}-{description.key}" + + async def async_send_message(self, message: str, title: str | None = None) -> None: + """Send a message.""" + try: + await self.coordinator.fully.sendCommand( + self.entity_description.cmd, text=message + ) + except FullyKioskError as err: + raise HomeAssistantError(err) from err diff --git a/homeassistant/components/fully_kiosk/strings.json b/homeassistant/components/fully_kiosk/strings.json index c1a1ef1fcf0..c6fe65b8383 100644 --- a/homeassistant/components/fully_kiosk/strings.json +++ b/homeassistant/components/fully_kiosk/strings.json @@ -56,6 +56,14 @@ "name": "Load start URL" } }, + "notify": { + "overlay_message": { + "name": "Overlay message" + }, + "tts": { + "name": "Text to speech" + } + }, "number": { "screensaver_time": { "name": "Screensaver timer" diff --git a/tests/components/fully_kiosk/test_notify.py b/tests/components/fully_kiosk/test_notify.py new file mode 100644 index 00000000000..727457f1b84 --- /dev/null +++ b/tests/components/fully_kiosk/test_notify.py @@ -0,0 +1,70 @@ +"""Test the Fully Kiosk Browser notify platform.""" + +from unittest.mock import MagicMock + +from fullykiosk import FullyKioskError +import pytest + +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError + +from tests.common import MockConfigEntry + + +async def test_notify_text_to_speech( + hass: HomeAssistant, + mock_fully_kiosk: MagicMock, + init_integration: MockConfigEntry, +) -> None: + """Test notify text to speech entity.""" + message = "one, two, testing, testing" + await hass.services.async_call( + "notify", + "send_message", + { + "entity_id": "notify.amazon_fire_text_to_speech", + "message": message, + }, + blocking=True, + ) + mock_fully_kiosk.sendCommand.assert_called_with("textToSpeech", text=message) + + +async def test_notify_text_to_speech_raises( + hass: HomeAssistant, + mock_fully_kiosk: MagicMock, + init_integration: MockConfigEntry, +) -> None: + """Test notify text to speech entity raises.""" + mock_fully_kiosk.sendCommand.side_effect = FullyKioskError("error", "status") + message = "one, two, testing, testing" + with pytest.raises(HomeAssistantError): + await hass.services.async_call( + "notify", + "send_message", + { + "entity_id": "notify.amazon_fire_text_to_speech", + "message": message, + }, + blocking=True, + ) + mock_fully_kiosk.sendCommand.assert_called_with("textToSpeech", text=message) + + +async def test_notify_overlay_message( + hass: HomeAssistant, + mock_fully_kiosk: MagicMock, + init_integration: MockConfigEntry, +) -> None: + """Test notify overlay message entity.""" + message = "one, two, testing, testing" + await hass.services.async_call( + "notify", + "send_message", + { + "entity_id": "notify.amazon_fire_overlay_message", + "message": message, + }, + blocking=True, + ) + mock_fully_kiosk.sendCommand.assert_called_with("setOverlayMessage", text=message)