mirror of
https://github.com/home-assistant/core.git
synced 2025-07-29 16:17:20 +00:00
Add "Albums" sensor to Lidarr (#125631)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
c1f612dce1
commit
50161670ce
@ -16,6 +16,7 @@ from homeassistant.helpers.device_registry import DeviceEntryType
|
||||
|
||||
from .const import DEFAULT_NAME, DOMAIN
|
||||
from .coordinator import (
|
||||
AlbumsDataUpdateCoordinator,
|
||||
DiskSpaceDataUpdateCoordinator,
|
||||
QueueDataUpdateCoordinator,
|
||||
StatusDataUpdateCoordinator,
|
||||
@ -35,6 +36,7 @@ class LidarrData:
|
||||
queue: QueueDataUpdateCoordinator
|
||||
status: StatusDataUpdateCoordinator
|
||||
wanted: WantedDataUpdateCoordinator
|
||||
albums: AlbumsDataUpdateCoordinator
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: LidarrConfigEntry) -> bool:
|
||||
@ -54,6 +56,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: LidarrConfigEntry) -> bo
|
||||
queue=QueueDataUpdateCoordinator(hass, host_configuration, lidarr),
|
||||
status=StatusDataUpdateCoordinator(hass, host_configuration, lidarr),
|
||||
wanted=WantedDataUpdateCoordinator(hass, host_configuration, lidarr),
|
||||
albums=AlbumsDataUpdateCoordinator(hass, host_configuration, lidarr),
|
||||
)
|
||||
for field in fields(data):
|
||||
coordinator = getattr(data, field.name)
|
||||
|
@ -17,7 +17,7 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, Upda
|
||||
|
||||
from .const import DEFAULT_MAX_RECORDS, DOMAIN, LOGGER
|
||||
|
||||
T = TypeVar("T", bound=list[LidarrRootFolder] | LidarrQueue | str | LidarrAlbum)
|
||||
T = TypeVar("T", bound=list[LidarrRootFolder] | LidarrQueue | str | LidarrAlbum | int)
|
||||
|
||||
|
||||
class LidarrDataUpdateCoordinator(DataUpdateCoordinator[T], Generic[T], ABC):
|
||||
@ -96,3 +96,11 @@ class WantedDataUpdateCoordinator(LidarrDataUpdateCoordinator[LidarrAlbum]):
|
||||
LidarrAlbum,
|
||||
await self.api_client.async_get_wanted(page_size=DEFAULT_MAX_RECORDS),
|
||||
)
|
||||
|
||||
|
||||
class AlbumsDataUpdateCoordinator(LidarrDataUpdateCoordinator[int]):
|
||||
"""Albums update coordinator."""
|
||||
|
||||
async def _fetch_data(self) -> int:
|
||||
"""Fetch the album data."""
|
||||
return len(cast(list[LidarrAlbum], await self.api_client.async_get_albums()))
|
||||
|
@ -85,7 +85,7 @@ SENSOR_TYPES: dict[str, LidarrSensorEntityDescription[Any]] = {
|
||||
"queue": LidarrSensorEntityDescription[LidarrQueue](
|
||||
key="queue",
|
||||
translation_key="queue",
|
||||
native_unit_of_measurement="Albums",
|
||||
native_unit_of_measurement="albums",
|
||||
value_fn=lambda data, _: data.totalRecords,
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
attributes_fn=lambda data: {i.title: queue_str(i) for i in data.records},
|
||||
@ -93,7 +93,7 @@ SENSOR_TYPES: dict[str, LidarrSensorEntityDescription[Any]] = {
|
||||
"wanted": LidarrSensorEntityDescription[LidarrQueue](
|
||||
key="wanted",
|
||||
translation_key="wanted",
|
||||
native_unit_of_measurement="Albums",
|
||||
native_unit_of_measurement="albums",
|
||||
value_fn=lambda data, _: data.totalRecords,
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
entity_registry_enabled_default=False,
|
||||
@ -101,6 +101,14 @@ SENSOR_TYPES: dict[str, LidarrSensorEntityDescription[Any]] = {
|
||||
album.title: album.artist.artistName for album in data.records
|
||||
},
|
||||
),
|
||||
"albums": LidarrSensorEntityDescription[int](
|
||||
key="albums",
|
||||
translation_key="albums",
|
||||
native_unit_of_measurement="albums",
|
||||
value_fn=lambda data, _: data,
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,6 +39,9 @@
|
||||
},
|
||||
"wanted": {
|
||||
"name": "Wanted"
|
||||
},
|
||||
"albums": {
|
||||
"name": "Albums"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,10 +44,12 @@ def mock_error(
|
||||
aioclient_mock.get(f"{API_URL}/rootfolder", status=status)
|
||||
aioclient_mock.get(f"{API_URL}/system/status", status=status)
|
||||
aioclient_mock.get(f"{API_URL}/wanted/missing", status=status)
|
||||
aioclient_mock.get(f"{API_URL}/album", status=status)
|
||||
aioclient_mock.get(f"{API_URL}/queue", exc=ClientError)
|
||||
aioclient_mock.get(f"{API_URL}/rootfolder", exc=ClientError)
|
||||
aioclient_mock.get(f"{API_URL}/system/status", exc=ClientError)
|
||||
aioclient_mock.get(f"{API_URL}/wanted/missing", exc=ClientError)
|
||||
aioclient_mock.get(f"{API_URL}/album", exc=ClientError)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -115,6 +117,11 @@ def mock_connection(aioclient_mock: AiohttpClientMocker) -> None:
|
||||
text=load_fixture("lidarr/wanted-missing.json"),
|
||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
f"{API_URL}/album",
|
||||
text=load_fixture("lidarr/album.json"),
|
||||
headers={"Content-Type": CONTENT_TYPE_JSON},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
f"{API_URL}/rootfolder",
|
||||
text=load_fixture("lidarr/rootfolder-linux.json"),
|
||||
|
155
tests/components/lidarr/fixtures/album.json
Normal file
155
tests/components/lidarr/fixtures/album.json
Normal file
@ -0,0 +1,155 @@
|
||||
[
|
||||
{
|
||||
"id": 0,
|
||||
"title": "string",
|
||||
"disambiguation": "string",
|
||||
"overview": "string",
|
||||
"artistId": 0,
|
||||
"foreignAlbumId": "string",
|
||||
"monitored": true,
|
||||
"anyReleaseOk": true,
|
||||
"profileId": 0,
|
||||
"duration": 0,
|
||||
"albumType": "string",
|
||||
"secondaryTypes": ["string"],
|
||||
"mediumCount": 0,
|
||||
"ratings": {
|
||||
"votes": 0,
|
||||
"value": 0
|
||||
},
|
||||
"releaseDate": "2024-09-09T20:16:28.493Z",
|
||||
"releases": [
|
||||
{
|
||||
"id": 0,
|
||||
"albumId": 0,
|
||||
"foreignReleaseId": "string",
|
||||
"title": "string",
|
||||
"status": "string",
|
||||
"duration": 0,
|
||||
"trackCount": 0,
|
||||
"media": [
|
||||
{
|
||||
"mediumNumber": 0,
|
||||
"mediumName": "string",
|
||||
"mediumFormat": "string"
|
||||
}
|
||||
],
|
||||
"mediumCount": 0,
|
||||
"disambiguation": "string",
|
||||
"country": ["string"],
|
||||
"label": ["string"],
|
||||
"format": "string",
|
||||
"monitored": true
|
||||
}
|
||||
],
|
||||
"genres": ["string"],
|
||||
"media": [
|
||||
{
|
||||
"mediumNumber": 0,
|
||||
"mediumName": "string",
|
||||
"mediumFormat": "string"
|
||||
}
|
||||
],
|
||||
"artist": {
|
||||
"id": 0,
|
||||
"status": "continuing",
|
||||
"ended": true,
|
||||
"artistName": "string",
|
||||
"foreignArtistId": "string",
|
||||
"mbId": "string",
|
||||
"tadbId": 0,
|
||||
"discogsId": 0,
|
||||
"allMusicId": "string",
|
||||
"overview": "string",
|
||||
"artistType": "string",
|
||||
"disambiguation": "string",
|
||||
"links": [
|
||||
{
|
||||
"url": "string",
|
||||
"name": "string"
|
||||
}
|
||||
],
|
||||
"nextAlbum": "string",
|
||||
"lastAlbum": "string",
|
||||
"images": [
|
||||
{
|
||||
"url": "string",
|
||||
"coverType": "unknown",
|
||||
"extension": "string",
|
||||
"remoteUrl": "string"
|
||||
}
|
||||
],
|
||||
"members": [
|
||||
{
|
||||
"name": "string",
|
||||
"instrument": "string",
|
||||
"images": [
|
||||
{
|
||||
"url": "string",
|
||||
"coverType": "unknown",
|
||||
"extension": "string",
|
||||
"remoteUrl": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"remotePoster": "string",
|
||||
"path": "string",
|
||||
"qualityProfileId": 0,
|
||||
"metadataProfileId": 0,
|
||||
"monitored": true,
|
||||
"monitorNewItems": "all",
|
||||
"rootFolderPath": "string",
|
||||
"folder": "string",
|
||||
"genres": ["string"],
|
||||
"cleanName": "string",
|
||||
"sortName": "string",
|
||||
"tags": [0],
|
||||
"added": "2024-09-09T20:16:28.493Z",
|
||||
"addOptions": {
|
||||
"monitor": "all",
|
||||
"albumsToMonitor": ["string"],
|
||||
"monitored": true,
|
||||
"searchForMissingAlbums": true
|
||||
},
|
||||
"ratings": {
|
||||
"votes": 0,
|
||||
"value": 0
|
||||
},
|
||||
"statistics": {
|
||||
"albumCount": 0,
|
||||
"trackFileCount": 0,
|
||||
"trackCount": 0,
|
||||
"totalTrackCount": 0,
|
||||
"sizeOnDisk": 0,
|
||||
"percentOfTracks": 0
|
||||
}
|
||||
},
|
||||
"images": [
|
||||
{
|
||||
"url": "string",
|
||||
"coverType": "unknown",
|
||||
"extension": "string",
|
||||
"remoteUrl": "string"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"url": "string",
|
||||
"name": "string"
|
||||
}
|
||||
],
|
||||
"statistics": {
|
||||
"trackFileCount": 0,
|
||||
"trackCount": 0,
|
||||
"totalTrackCount": 0,
|
||||
"sizeOnDisk": 0,
|
||||
"percentOfTracks": 0
|
||||
},
|
||||
"addOptions": {
|
||||
"addType": "automatic",
|
||||
"searchForNewAlbum": true
|
||||
},
|
||||
"remoteCover": "string"
|
||||
}
|
||||
]
|
@ -25,10 +25,14 @@ async def test_sensors(
|
||||
assert state.state == "2"
|
||||
assert state.attributes.get("string") == "stopped"
|
||||
assert state.attributes.get("string2") == "downloading"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "Albums"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "albums"
|
||||
assert state.attributes.get(CONF_STATE_CLASS) == SensorStateClass.TOTAL
|
||||
state = hass.states.get("sensor.mock_title_wanted")
|
||||
assert state.state == "1"
|
||||
assert state.attributes.get("test") == "test"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "Albums"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "albums"
|
||||
assert state.attributes.get(CONF_STATE_CLASS) == SensorStateClass.TOTAL
|
||||
state = hass.states.get("sensor.mock_title_albums")
|
||||
assert state.state == "1"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "albums"
|
||||
assert state.attributes.get(CONF_STATE_CLASS) == SensorStateClass.TOTAL
|
||||
|
Loading…
x
Reference in New Issue
Block a user