mirror of
https://github.com/Electric-Special/ha-core.git
synced 2026-03-21 07:05:48 +01:00
Add actions for Nintendo Parental Controls (#154886)
This commit is contained in:
@@ -11,10 +11,13 @@ from pynintendoparental.exceptions import (
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryAuthFailed
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import CONF_SESSION_TOKEN, DOMAIN
|
||||
from .coordinator import NintendoParentalControlsConfigEntry, NintendoUpdateCoordinator
|
||||
from .services import async_setup_services
|
||||
|
||||
_PLATFORMS: list[Platform] = [
|
||||
Platform.SENSOR,
|
||||
@@ -23,6 +26,14 @@ _PLATFORMS: list[Platform] = [
|
||||
Platform.NUMBER,
|
||||
]
|
||||
|
||||
PLATFORM_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the Nintendo Switch Parental Controls integration."""
|
||||
async_setup_services(hass)
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant, entry: NintendoParentalControlsConfigEntry
|
||||
|
||||
@@ -7,3 +7,5 @@ CONF_SESSION_TOKEN = "session_token"
|
||||
BEDTIME_ALARM_MIN = "16:00"
|
||||
BEDTIME_ALARM_MAX = "23:00"
|
||||
BEDTIME_ALARM_DISABLE = "00:00"
|
||||
|
||||
ATTR_BONUS_TIME = "bonus_time"
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"services": {
|
||||
"add_bonus_time": {
|
||||
"service": "mdi:timer-plus-outline"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,13 @@
|
||||
rules:
|
||||
# Bronze
|
||||
action-setup:
|
||||
status: exempt
|
||||
comment: |
|
||||
No custom actions are defined.
|
||||
action-setup: done
|
||||
appropriate-polling: done
|
||||
brands: done
|
||||
common-modules: done
|
||||
config-flow-test-coverage: done
|
||||
config-flow: done
|
||||
dependency-transparency: done
|
||||
docs-actions:
|
||||
status: exempt
|
||||
comment: |
|
||||
No custom actions are defined.
|
||||
docs-actions: done
|
||||
docs-high-level-description: done
|
||||
docs-installation-instructions: done
|
||||
docs-removal-instructions: done
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
"""Services for Nintendo Parental integration."""
|
||||
|
||||
from enum import StrEnum
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import ATTR_DEVICE_ID
|
||||
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import config_validation as cv, device_registry as dr
|
||||
|
||||
from .const import ATTR_BONUS_TIME, DOMAIN
|
||||
from .coordinator import NintendoParentalControlsConfigEntry
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NintendoParentalServices(StrEnum):
|
||||
"""Store keys for Nintendo Parental services."""
|
||||
|
||||
ADD_BONUS_TIME = "add_bonus_time"
|
||||
|
||||
|
||||
@callback
|
||||
def async_setup_services(
|
||||
hass: HomeAssistant,
|
||||
):
|
||||
"""Set up the Nintendo Parental services."""
|
||||
hass.services.async_register(
|
||||
domain=DOMAIN,
|
||||
service=NintendoParentalServices.ADD_BONUS_TIME,
|
||||
service_func=async_add_bonus_time,
|
||||
schema=vol.Schema(
|
||||
{
|
||||
vol.Required(ATTR_DEVICE_ID): cv.string,
|
||||
vol.Required(ATTR_BONUS_TIME): vol.All(int, vol.Range(min=5, max=30)),
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def _get_nintendo_device_id(dev: dr.DeviceEntry) -> str | None:
|
||||
"""Get the Nintendo device ID from a device entry."""
|
||||
for identifier in dev.identifiers:
|
||||
if identifier[0] == DOMAIN:
|
||||
return identifier[1].split("_")[-1]
|
||||
return None
|
||||
|
||||
|
||||
async def async_add_bonus_time(call: ServiceCall) -> None:
|
||||
"""Add bonus time to a device."""
|
||||
config_entry: NintendoParentalControlsConfigEntry | None
|
||||
data = call.data
|
||||
device_id: str = data[ATTR_DEVICE_ID]
|
||||
bonus_time: int = data[ATTR_BONUS_TIME]
|
||||
device = dr.async_get(call.hass).async_get(device_id)
|
||||
if device is None:
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="device_not_found",
|
||||
)
|
||||
for entry_id in device.config_entries:
|
||||
config_entry = call.hass.config_entries.async_get_entry(entry_id)
|
||||
if config_entry is not None and config_entry.domain == DOMAIN:
|
||||
break
|
||||
nintendo_device_id = _get_nintendo_device_id(device)
|
||||
if config_entry and nintendo_device_id:
|
||||
await config_entry.runtime_data.api.devices[nintendo_device_id].add_extra_time(
|
||||
bonus_time
|
||||
)
|
||||
@@ -0,0 +1,17 @@
|
||||
add_bonus_time:
|
||||
fields:
|
||||
bonus_time:
|
||||
required: true
|
||||
example: 30
|
||||
selector:
|
||||
number:
|
||||
min: -1
|
||||
max: 1440
|
||||
unit_of_measurement: minutes
|
||||
mode: box
|
||||
device_id:
|
||||
required: true
|
||||
example: 1234567890abcdef1234567890abcdef
|
||||
selector:
|
||||
device:
|
||||
integration: nintendo_parental_controls
|
||||
@@ -61,6 +61,29 @@
|
||||
},
|
||||
"bedtime_alarm_out_of_range": {
|
||||
"message": "{value} not accepted. Bedtime Alarm must be between {bedtime_alarm_min} and {bedtime_alarm_max}. To disable, set to {bedtime_alarm_disable}."
|
||||
},
|
||||
"config_entry_not_found": {
|
||||
"message": "Config entry not found."
|
||||
},
|
||||
"device_not_found": {
|
||||
"message": "Device not found."
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"add_bonus_time": {
|
||||
"description": "Add bonus screen time to the selected Nintendo Switch.",
|
||||
"fields": {
|
||||
"bonus_time": {
|
||||
"description": "The amount of bonus time to add in minutes. Maximum is 30 minutes, minimum is 5.",
|
||||
"name": "Bonus Time"
|
||||
},
|
||||
"device_id": {
|
||||
"description": "The ID of the device to add bonus time to.",
|
||||
"example": "1234567890abcdef",
|
||||
"name": "Device"
|
||||
}
|
||||
},
|
||||
"name": "Add Bonus Time"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ def mock_nintendo_device() -> Device:
|
||||
mock.today_playing_time = 110
|
||||
mock.today_time_remaining = 10
|
||||
mock.bedtime_alarm = time(hour=19)
|
||||
mock.add_extra_time.return_value = None
|
||||
mock.set_bedtime_alarm.return_value = None
|
||||
mock.update_max_daily_playtime.return_value = None
|
||||
mock.forced_termination_mode = True
|
||||
|
||||
65
tests/components/nintendo_parental_controls/test_services.py
Normal file
65
tests/components/nintendo_parental_controls/test_services.py
Normal file
@@ -0,0 +1,65 @@
|
||||
"""Test Nintendo Parental Controls service calls."""
|
||||
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.nintendo_parental_controls.const import (
|
||||
ATTR_BONUS_TIME,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.components.nintendo_parental_controls.services import (
|
||||
NintendoParentalServices,
|
||||
)
|
||||
from homeassistant.const import ATTR_DEVICE_ID
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
|
||||
from . import setup_integration
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_add_bonus_time(
|
||||
hass: HomeAssistant,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_nintendo_client: AsyncMock,
|
||||
mock_nintendo_device: AsyncMock,
|
||||
) -> None:
|
||||
"""Test add bonus time service."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
device_entry = device_registry.async_get_device(identifiers={(DOMAIN, "testdevid")})
|
||||
assert device_entry
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
NintendoParentalServices.ADD_BONUS_TIME,
|
||||
{
|
||||
ATTR_DEVICE_ID: device_entry.id,
|
||||
ATTR_BONUS_TIME: 15,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(mock_nintendo_device.add_extra_time.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_add_bonus_time_invalid_device(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_nintendo_client: AsyncMock,
|
||||
) -> None:
|
||||
"""Test add bonus time service."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
with pytest.raises(HomeAssistantError) as err:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
NintendoParentalServices.ADD_BONUS_TIME,
|
||||
{
|
||||
ATTR_DEVICE_ID: "invalid_device_id",
|
||||
ATTR_BONUS_TIME: 15,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert err.value.translation_domain == DOMAIN
|
||||
assert err.value.translation_key == "device_not_found"
|
||||
Reference in New Issue
Block a user