-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add diagnostic sensors for the active subscription of Cookidoo (#136485)
* add diagnostics for the active subcription * fix mapping between api and ha states for subscription * multiline lambda
- Loading branch information
Showing
10 changed files
with
317 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,9 @@ | ||
"""Constants for the Cookidoo integration.""" | ||
|
||
DOMAIN = "cookidoo" | ||
|
||
SUBSCRIPTION_MAP = { | ||
"NONE": "free", | ||
"TRIAL": "trial", | ||
"REGULAR": "premium", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
"""Sensor platform for the Cookidoo integration.""" | ||
|
||
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 ( | ||
SensorDeviceClass, | ||
SensorEntity, | ||
SensorEntityDescription, | ||
) | ||
from homeassistant.const import EntityCategory | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers.entity_platform import AddEntitiesCallback | ||
from homeassistant.helpers.typing import StateType | ||
from homeassistant.util import dt as dt_util | ||
|
||
from .const import SUBSCRIPTION_MAP | ||
from .coordinator import ( | ||
CookidooConfigEntry, | ||
CookidooData, | ||
CookidooDataUpdateCoordinator, | ||
) | ||
from .entity import CookidooBaseEntity | ||
|
||
PARALLEL_UPDATES = 0 | ||
|
||
|
||
@dataclass(kw_only=True, frozen=True) | ||
class CookidooSensorEntityDescription(SensorEntityDescription): | ||
"""Cookidoo Sensor Description.""" | ||
|
||
value_fn: Callable[[CookidooData], StateType | datetime] | ||
|
||
|
||
class CookidooSensor(StrEnum): | ||
"""Cookidoo sensors.""" | ||
|
||
SUBSCRIPTION = "subscription" | ||
EXPIRES = "expires" | ||
|
||
|
||
SENSOR_DESCRIPTIONS: tuple[CookidooSensorEntityDescription, ...] = ( | ||
CookidooSensorEntityDescription( | ||
key=CookidooSensor.SUBSCRIPTION, | ||
translation_key=CookidooSensor.SUBSCRIPTION, | ||
value_fn=( | ||
lambda data: SUBSCRIPTION_MAP[data.subscription.type] | ||
if data.subscription | ||
else SUBSCRIPTION_MAP["NONE"] | ||
), | ||
entity_category=EntityCategory.DIAGNOSTIC, | ||
options=list(SUBSCRIPTION_MAP.values()), | ||
device_class=SensorDeviceClass.ENUM, | ||
), | ||
CookidooSensorEntityDescription( | ||
key=CookidooSensor.EXPIRES, | ||
translation_key=CookidooSensor.EXPIRES, | ||
value_fn=( | ||
lambda data: dt_util.parse_datetime(data.subscription.expires) | ||
if data.subscription | ||
else None | ||
), | ||
entity_category=EntityCategory.DIAGNOSTIC, | ||
device_class=SensorDeviceClass.TIMESTAMP, | ||
), | ||
) | ||
|
||
|
||
async def async_setup_entry( | ||
hass: HomeAssistant, | ||
config_entry: CookidooConfigEntry, | ||
async_add_entities: AddEntitiesCallback, | ||
) -> None: | ||
"""Set up the sensor platform.""" | ||
coordinator = config_entry.runtime_data | ||
|
||
async_add_entities( | ||
CookidooSensorEntity( | ||
coordinator, | ||
description, | ||
) | ||
for description in SENSOR_DESCRIPTIONS | ||
) | ||
|
||
|
||
class CookidooSensorEntity(CookidooBaseEntity, SensorEntity): | ||
"""A sensor entity.""" | ||
|
||
entity_description: CookidooSensorEntityDescription | ||
|
||
def __init__( | ||
self, | ||
coordinator: CookidooDataUpdateCoordinator, | ||
entity_description: CookidooSensorEntityDescription, | ||
) -> None: | ||
"""Initialize the entity.""" | ||
super().__init__(coordinator) | ||
self.entity_description = entity_description | ||
self._attr_unique_id = ( | ||
f"{coordinator.config_entry.unique_id}_{self.entity_description.key}" | ||
) | ||
|
||
@property | ||
def native_value(self) -> StateType | datetime: | ||
"""Return the state of the sensor.""" | ||
|
||
return self.entity_description.value_fn(self.coordinator.data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"data": { | ||
"active": true, | ||
"start_date": "2024-12-16T00:00:00Z", | ||
"expires": "2025-12-16T23:59:00Z", | ||
"type": "REGULAR", | ||
"extended_type": "REGULAR", | ||
"subscription_level": "FULL", | ||
"subscription_source": "COMMERCE", | ||
"status": "ACTIVE" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# serializer version: 1 | ||
# name: test_setup[sensor.cookidoo_subscription-entry] | ||
EntityRegistryEntrySnapshot({ | ||
'aliases': set({ | ||
}), | ||
'area_id': None, | ||
'capabilities': dict({ | ||
'options': list([ | ||
'free', | ||
'trial', | ||
'premium', | ||
]), | ||
}), | ||
'config_entry_id': <ANY>, | ||
'device_class': None, | ||
'device_id': <ANY>, | ||
'disabled_by': None, | ||
'domain': 'sensor', | ||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>, | ||
'entity_id': 'sensor.cookidoo_subscription', | ||
'has_entity_name': True, | ||
'hidden_by': None, | ||
'icon': None, | ||
'id': <ANY>, | ||
'labels': set({ | ||
}), | ||
'name': None, | ||
'options': dict({ | ||
}), | ||
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>, | ||
'original_icon': None, | ||
'original_name': 'Subscription', | ||
'platform': 'cookidoo', | ||
'previous_unique_id': None, | ||
'supported_features': 0, | ||
'translation_key': <CookidooSensor.SUBSCRIPTION: 'subscription'>, | ||
'unique_id': 'sub_uuid_subscription', | ||
'unit_of_measurement': None, | ||
}) | ||
# --- | ||
# name: test_setup[sensor.cookidoo_subscription-state] | ||
StateSnapshot({ | ||
'attributes': ReadOnlyDict({ | ||
'device_class': 'enum', | ||
'friendly_name': 'Cookidoo Subscription', | ||
'options': list([ | ||
'free', | ||
'trial', | ||
'premium', | ||
]), | ||
}), | ||
'context': <ANY>, | ||
'entity_id': 'sensor.cookidoo_subscription', | ||
'last_changed': <ANY>, | ||
'last_reported': <ANY>, | ||
'last_updated': <ANY>, | ||
'state': 'premium', | ||
}) | ||
# --- | ||
# name: test_setup[sensor.cookidoo_subscription_expiration_date-entry] | ||
EntityRegistryEntrySnapshot({ | ||
'aliases': set({ | ||
}), | ||
'area_id': None, | ||
'capabilities': None, | ||
'config_entry_id': <ANY>, | ||
'device_class': None, | ||
'device_id': <ANY>, | ||
'disabled_by': None, | ||
'domain': 'sensor', | ||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>, | ||
'entity_id': 'sensor.cookidoo_subscription_expiration_date', | ||
'has_entity_name': True, | ||
'hidden_by': None, | ||
'icon': None, | ||
'id': <ANY>, | ||
'labels': set({ | ||
}), | ||
'name': None, | ||
'options': dict({ | ||
}), | ||
'original_device_class': <SensorDeviceClass.TIMESTAMP: 'timestamp'>, | ||
'original_icon': None, | ||
'original_name': 'Subscription expiration date', | ||
'platform': 'cookidoo', | ||
'previous_unique_id': None, | ||
'supported_features': 0, | ||
'translation_key': <CookidooSensor.EXPIRES: 'expires'>, | ||
'unique_id': 'sub_uuid_expires', | ||
'unit_of_measurement': None, | ||
}) | ||
# --- | ||
# name: test_setup[sensor.cookidoo_subscription_expiration_date-state] | ||
StateSnapshot({ | ||
'attributes': ReadOnlyDict({ | ||
'device_class': 'timestamp', | ||
'friendly_name': 'Cookidoo Subscription expiration date', | ||
}), | ||
'context': <ANY>, | ||
'entity_id': 'sensor.cookidoo_subscription_expiration_date', | ||
'last_changed': <ANY>, | ||
'last_reported': <ANY>, | ||
'last_updated': <ANY>, | ||
'state': '2025-12-16T23:59:00+00:00', | ||
}) | ||
# --- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
"""Test for sensor platform of the Cookidoo integration.""" | ||
|
||
from collections.abc import Generator | ||
from unittest.mock import patch | ||
|
||
import pytest | ||
from syrupy.assertion import SnapshotAssertion | ||
|
||
from homeassistant.config_entries import ConfigEntryState | ||
from homeassistant.const import Platform | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers import entity_registry as er | ||
|
||
from tests.common import MockConfigEntry, snapshot_platform | ||
|
||
|
||
@pytest.fixture(autouse=True) | ||
def sensor_only() -> Generator[None]: | ||
"""Enable only the sensor platform.""" | ||
with patch( | ||
"homeassistant.components.cookidoo.PLATFORMS", | ||
[Platform.SENSOR], | ||
): | ||
yield | ||
|
||
|
||
@pytest.mark.usefixtures("mock_cookidoo_client") | ||
async def test_setup( | ||
hass: HomeAssistant, | ||
cookidoo_config_entry: MockConfigEntry, | ||
snapshot: SnapshotAssertion, | ||
entity_registry: er.EntityRegistry, | ||
) -> None: | ||
"""Snapshot test states of sensor platform.""" | ||
|
||
cookidoo_config_entry.add_to_hass(hass) | ||
await hass.config_entries.async_setup(cookidoo_config_entry.entry_id) | ||
await hass.async_block_till_done() | ||
|
||
assert cookidoo_config_entry.state is ConfigEntryState.LOADED | ||
|
||
await snapshot_platform( | ||
hass, entity_registry, snapshot, cookidoo_config_entry.entry_id | ||
) |