Add sensor last online to PlayStation Network integration (#147796)

This commit is contained in:
Manu 2025-06-30 19:52:11 +02:00 committed by GitHub
parent f03af213d4
commit 5e3fc858d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 77 additions and 3 deletions

View File

@ -26,6 +26,9 @@
}, },
"online_id": { "online_id": {
"default": "mdi:account" "default": "mdi:account"
},
"last_online": {
"default": "mdi:account-clock"
} }
} }
} }

View File

@ -4,16 +4,22 @@ from __future__ import annotations
from collections.abc import Callable from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime
from enum import StrEnum from enum import StrEnum
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from homeassistant.components.sensor import SensorEntity, SensorEntityDescription from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
)
from homeassistant.const import PERCENTAGE from homeassistant.const import PERCENTAGE
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType from homeassistant.helpers.typing import StateType
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.util import dt as dt_util
from .const import DOMAIN from .const import DOMAIN
from .coordinator import ( from .coordinator import (
@ -29,7 +35,7 @@ PARALLEL_UPDATES = 0
class PlaystationNetworkSensorEntityDescription(SensorEntityDescription): class PlaystationNetworkSensorEntityDescription(SensorEntityDescription):
"""PlayStation Network sensor description.""" """PlayStation Network sensor description."""
value_fn: Callable[[PlaystationNetworkData], StateType] value_fn: Callable[[PlaystationNetworkData], StateType | datetime]
entity_picture: str | None = None entity_picture: str | None = None
@ -43,6 +49,7 @@ class PlaystationNetworkSensor(StrEnum):
EARNED_TROPHIES_SILVER = "earned_trophies_silver" EARNED_TROPHIES_SILVER = "earned_trophies_silver"
EARNED_TROPHIES_BRONZE = "earned_trophies_bronze" EARNED_TROPHIES_BRONZE = "earned_trophies_bronze"
ONLINE_ID = "online_id" ONLINE_ID = "online_id"
LAST_ONLINE = "last_online"
SENSOR_DESCRIPTIONS: tuple[PlaystationNetworkSensorEntityDescription, ...] = ( SENSOR_DESCRIPTIONS: tuple[PlaystationNetworkSensorEntityDescription, ...] = (
@ -102,6 +109,16 @@ SENSOR_DESCRIPTIONS: tuple[PlaystationNetworkSensorEntityDescription, ...] = (
translation_key=PlaystationNetworkSensor.ONLINE_ID, translation_key=PlaystationNetworkSensor.ONLINE_ID,
value_fn=lambda psn: psn.username, value_fn=lambda psn: psn.username,
), ),
PlaystationNetworkSensorEntityDescription(
key=PlaystationNetworkSensor.LAST_ONLINE,
translation_key=PlaystationNetworkSensor.LAST_ONLINE,
value_fn=(
lambda psn: dt_util.parse_datetime(
psn.presence["basicPresence"]["lastAvailableDate"]
)
),
device_class=SensorDeviceClass.TIMESTAMP,
),
) )
@ -147,7 +164,7 @@ class PlaystationNetworkSensorEntity(
) )
@property @property
def native_value(self) -> StateType: def native_value(self) -> StateType | datetime:
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self.entity_description.value_fn(self.coordinator.data) return self.entity_description.value_fn(self.coordinator.data)

View File

@ -78,6 +78,9 @@
}, },
"online_id": { "online_id": {
"name": "Online-ID" "name": "Online-ID"
},
"last_online": {
"name": "Last online"
} }
} }
} }

View File

@ -64,6 +64,7 @@ def mock_user() -> Generator[MagicMock]:
"conceptIconUrl": "https://image.api.playstation.com/vulcan/ap/rnd/202211/2222/l8QTN7ThQK3lRBHhB3nX1s7h.png", "conceptIconUrl": "https://image.api.playstation.com/vulcan/ap/rnd/202211/2222/l8QTN7ThQK3lRBHhB3nX1s7h.png",
} }
], ],
"lastAvailableDate": "2025-06-30T01:42:15.391Z",
} }
} }

View File

@ -26,6 +26,7 @@
'titleName': 'STAR WARS Jedi: Survivor™', 'titleName': 'STAR WARS Jedi: Survivor™',
}), }),
]), ]),
'lastAvailableDate': '2025-06-30T01:42:15.391Z',
'primaryPlatformInfo': dict({ 'primaryPlatformInfo': dict({
'onlineStatus': 'online', 'onlineStatus': 'online',
'platform': 'PS5', 'platform': 'PS5',

View File

@ -97,6 +97,55 @@
'state': '11754', 'state': '11754',
}) })
# --- # ---
# name: test_sensors[sensor.testuser_last_online-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.testuser_last_online',
'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': 'Last online',
'platform': 'playstation_network',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': <PlaystationNetworkSensor.LAST_ONLINE: 'last_online'>,
'unique_id': 'my-psn-id_last_online',
'unit_of_measurement': None,
})
# ---
# name: test_sensors[sensor.testuser_last_online-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'timestamp',
'friendly_name': 'testuser Last online',
}),
'context': <ANY>,
'entity_id': 'sensor.testuser_last_online',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2025-06-30T01:42:15+00:00',
})
# ---
# name: test_sensors[sensor.testuser_next_level-entry] # name: test_sensors[sensor.testuser_next_level-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({