From a8114b7e4f67dbcba188ad1fb8c080322a740229 Mon Sep 17 00:00:00 2001 From: Jordan Harvey Date: Mon, 29 Dec 2025 13:00:37 +0000 Subject: [PATCH] Add time extended sensor for Nintendo Switch parental controls (#159227) --- .../nintendo_parental_controls/sensor.py | 21 +++++- .../nintendo_parental_controls/strings.json | 3 + .../nintendo_parental_controls/conftest.py | 1 + .../snapshots/test_sensor.ambr | 64 +++++++++++++++++-- .../nintendo_parental_controls/test_sensor.py | 4 +- 5 files changed, 85 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/nintendo_parental_controls/sensor.py b/homeassistant/components/nintendo_parental_controls/sensor.py index 129c7280e53..99282317e3a 100644 --- a/homeassistant/components/nintendo_parental_controls/sensor.py +++ b/homeassistant/components/nintendo_parental_controls/sensor.py @@ -4,6 +4,7 @@ from __future__ import annotations from collections.abc import Callable from dataclasses import dataclass +from datetime import datetime from enum import StrEnum from homeassistant.components.sensor import ( @@ -28,13 +29,15 @@ class NintendoParentalControlsSensor(StrEnum): PLAYING_TIME = "playing_time" TIME_REMAINING = "time_remaining" + TIME_EXTENDED = "time_extended" @dataclass(kw_only=True, frozen=True) class NintendoParentalControlsSensorEntityDescription(SensorEntityDescription): """Description for Nintendo parental controls sensor entities.""" - value_fn: Callable[[Device], int | float | None] + value_fn: Callable[[Device], datetime | int | float | None] + available_fn: Callable[[Device], bool] = lambda device: True SENSOR_DESCRIPTIONS: tuple[NintendoParentalControlsSensorEntityDescription, ...] = ( @@ -54,6 +57,15 @@ SENSOR_DESCRIPTIONS: tuple[NintendoParentalControlsSensorEntityDescription, ...] state_class=SensorStateClass.MEASUREMENT, value_fn=lambda device: device.today_time_remaining, ), + NintendoParentalControlsSensorEntityDescription( + key=NintendoParentalControlsSensor.TIME_EXTENDED, + translation_key=NintendoParentalControlsSensor.TIME_EXTENDED, + native_unit_of_measurement=UnitOfTime.MINUTES, + device_class=SensorDeviceClass.DURATION, + state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda device: device.extra_playing_time, + available_fn=lambda device: device.extra_playing_time is not None, + ), ) @@ -86,6 +98,11 @@ class NintendoParentalControlsSensorEntity(NintendoDevice, SensorEntity): self.entity_description = description @property - def native_value(self) -> int | float | None: + def native_value(self) -> datetime | int | float | None: """Return the native value.""" return self.entity_description.value_fn(self._device) + + @property + def available(self) -> bool: + """Return if the sensor is available.""" + return super().available and self.entity_description.available_fn(self._device) diff --git a/homeassistant/components/nintendo_parental_controls/strings.json b/homeassistant/components/nintendo_parental_controls/strings.json index dfd2fd94dfa..8b671d4b099 100644 --- a/homeassistant/components/nintendo_parental_controls/strings.json +++ b/homeassistant/components/nintendo_parental_controls/strings.json @@ -50,6 +50,9 @@ "playing_time": { "name": "Used screen time" }, + "time_extended": { + "name": "Extended screen time" + }, "time_remaining": { "name": "Screen time remaining" } diff --git a/tests/components/nintendo_parental_controls/conftest.py b/tests/components/nintendo_parental_controls/conftest.py index bd018a17cfd..3b7ccf0f4b0 100644 --- a/tests/components/nintendo_parental_controls/conftest.py +++ b/tests/components/nintendo_parental_controls/conftest.py @@ -41,6 +41,7 @@ def mock_nintendo_device() -> Device: mock.today_time_remaining = 10 mock.bedtime_alarm = time(hour=19) mock.timer_mode = DeviceTimerMode.DAILY + mock.extra_playing_time = 30 mock.add_extra_time.return_value = None mock.set_bedtime_alarm.return_value = None mock.update_max_daily_playtime.return_value = None diff --git a/tests/components/nintendo_parental_controls/snapshots/test_sensor.ambr b/tests/components/nintendo_parental_controls/snapshots/test_sensor.ambr index 784ea269b0c..25afbf4442e 100644 --- a/tests/components/nintendo_parental_controls/snapshots/test_sensor.ambr +++ b/tests/components/nintendo_parental_controls/snapshots/test_sensor.ambr @@ -1,5 +1,61 @@ # serializer version: 1 -# name: test_number[sensor.home_assistant_test_screen_time_remaining-entry] +# name: test_sensor[sensor.home_assistant_test_extended_screen_time-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.home_assistant_test_extended_screen_time', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Extended screen time', + 'platform': 'nintendo_parental_controls', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': , + 'unique_id': 'testdevid_time_extended', + 'unit_of_measurement': , + }) +# --- +# name: test_sensor[sensor.home_assistant_test_extended_screen_time-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'duration', + 'friendly_name': 'Home Assistant Test Extended screen time', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.home_assistant_test_extended_screen_time', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '30', + }) +# --- +# name: test_sensor[sensor.home_assistant_test_screen_time_remaining-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ }), @@ -39,7 +95,7 @@ 'unit_of_measurement': , }) # --- -# name: test_number[sensor.home_assistant_test_screen_time_remaining-state] +# name: test_sensor[sensor.home_assistant_test_screen_time_remaining-state] StateSnapshot({ 'attributes': ReadOnlyDict({ 'device_class': 'duration', @@ -55,7 +111,7 @@ 'state': '10', }) # --- -# name: test_number[sensor.home_assistant_test_used_screen_time-entry] +# name: test_sensor[sensor.home_assistant_test_used_screen_time-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ }), @@ -95,7 +151,7 @@ 'unit_of_measurement': , }) # --- -# name: test_number[sensor.home_assistant_test_used_screen_time-state] +# name: test_sensor[sensor.home_assistant_test_used_screen_time-state] StateSnapshot({ 'attributes': ReadOnlyDict({ 'device_class': 'duration', diff --git a/tests/components/nintendo_parental_controls/test_sensor.py b/tests/components/nintendo_parental_controls/test_sensor.py index 79890df4ba4..0d958488828 100644 --- a/tests/components/nintendo_parental_controls/test_sensor.py +++ b/tests/components/nintendo_parental_controls/test_sensor.py @@ -13,14 +13,14 @@ from . import setup_integration from tests.common import MockConfigEntry, snapshot_platform -async def test_number( +async def test_sensor( hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_nintendo_client: AsyncMock, entity_registry: er.EntityRegistry, snapshot: SnapshotAssertion, ) -> None: - """Test number platform.""" + """Test sensor platform.""" with patch( "homeassistant.components.nintendo_parental_controls._PLATFORMS", [Platform.SENSOR],