Skip to content

Commit

Permalink
Merge pull request #24 from JackJPowell/additional-platforms
Browse files Browse the repository at this point in the history
Include Profile Data
  • Loading branch information
JackJPowell authored Nov 16, 2024
2 parents f516159 + 1003a5f commit 78d3021
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 55 deletions.
23 changes: 7 additions & 16 deletions custom_components/playstation_network/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
PLATFORMS: list[Platform] = [
Platform.MEDIA_PLAYER,
Platform.SENSOR,
Platform.BINARY_SENSOR,
Platform.IMAGE,
]

_LOGGER: logging.Logger = logging.getLogger(__package__)
Expand Down Expand Up @@ -73,26 +75,14 @@ def async_migrate_entity_entry(entry: er.RegistryEntry) -> dict[str, Any] | None
"""
if entry.domain == Platform.SENSOR and entry.unique_id == "psn_psn_status":
new = f"{coordinator.data.get("username").lower()}_psn_status"
return {
"new_unique_id": entry.unique_id.replace(
"psn_psn_status", new
)
}
return {"new_unique_id": entry.unique_id.replace("psn_psn_status", new)}

if entry.domain == Platform.SENSOR and entry.unique_id == "psn_psn_trophies":
new = f"{coordinator.data.get("username").lower()}_psn_trophy_level"
return {
"new_unique_id": entry.unique_id.replace(
"psn_psn_trophies", new
)
}
return {"new_unique_id": entry.unique_id.replace("psn_psn_trophies", new)}
if entry.domain == Platform.MEDIA_PLAYER and entry.unique_id == "PS5_console":
new = f"{coordinator.data.get('username').lower()}_{coordinator.data.get('platform').get('platform').lower()}_console"
return {
"new_unique_id": entry.unique_id.replace(
"PS5_console", new
)
}
return {"new_unique_id": entry.unique_id.replace("PS5_console", new)}

# No migration needed
return None
Expand All @@ -105,7 +95,6 @@ def async_migrate_entity_entry(entry: er.RegistryEntry) -> dict[str, Any] | None
_migrate_device_identifiers(hass, entry.entry_id, coordinator)
hass.config_entries.async_update_entry(entry, version=2)


await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
entry.async_on_unload(entry.add_update_listener(update_listener))
return True
Expand All @@ -123,10 +112,12 @@ async def update_listener(hass: HomeAssistant, entry: ConfigEntry):
"""Update Listener."""
await hass.config_entries.async_reload(entry.entry_id)


async def async_migrate_entry(hass: HomeAssistant, self):
"""Migrate Entry Support"""
return True


def _migrate_device_identifiers(
hass: HomeAssistant, entry_id: str, coordinator
) -> None:
Expand Down
43 changes: 43 additions & 0 deletions custom_components/playstation_network/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Binary sensor platform for Unfolded Circle."""

from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.core import HomeAssistant, callback

from .const import DOMAIN, PSN_COORDINATOR
from .entity import PSNEntity


async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entities):
"""Add sensors for passed config_entry in HA."""
coordinator = hass.data[DOMAIN][config_entry.entry_id][PSN_COORDINATOR]

async_add_entities([PlaystationPlusBinarySensor(coordinator)])


class PlaystationPlusBinarySensor(PSNEntity, BinarySensorEntity):
"""Sensor indicating if user is subscribed to PlayStation Plus"""

def __init__(self, coordinator) -> None:
"""Initialize Binary Sensor."""
super().__init__(coordinator)
self.coordinator = coordinator

# As per the sensor, this must be a unique value within this domain.
self._attr_unique_id = (
f"{coordinator.data.get("username").lower()}_has_playstation_plus"
)

# The name of the entity
self._attr_has_entity_name = True
self._attr_name = "Playstation Plus"
self._attr_native_value = self.coordinator.data.get("profile").get("isPlus")
self._attr_icon = "mdi:gamepad-outline"

@property
def is_on(self):
"""Return the state of the binary sensor."""
return self.coordinator.data.get("profile", {}).get("isPlus")

@callback
def _handle_coordinator_update(self) -> None:
self.async_write_ha_state()
2 changes: 1 addition & 1 deletion custom_components/playstation_network/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ async def _async_update_data(self) -> dict[str, Any]:
try:
self.data["username"] = self.user.online_id
self.data["profile"] = await self.hass.async_add_executor_job(
self.user.profile
lambda: self.user.profile()
)
self.data["presence"] = await self.hass.async_add_executor_job(
self.user.get_presence
Expand Down
55 changes: 55 additions & 0 deletions custom_components/playstation_network/image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""Image sensor platform for the PlayStation Network."""

from homeassistant.components.image import ImageEntity
from homeassistant.core import HomeAssistant, callback
from homeassistant.util import dt as dt_util

from .const import DOMAIN, PSN_COORDINATOR
from .entity import PSNEntity


async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entities):
"""Add sensors for passed config_entry in HA."""
coordinator = hass.data[DOMAIN][config_entry.entry_id][PSN_COORDINATOR]

async_add_entities([PlaystationProfileImage(coordinator)])


class PlaystationProfileImage(PSNEntity, ImageEntity):
"""Image representing your PlayStation Avatar"""

def __init__(self, coordinator) -> None:
"""Initialize Image."""
super().__init__(coordinator)
self._attr_extra_state_attributes = {}
self.coordinator = coordinator

self._attr_unique_id = (
f"{self.coordinator.data.get("username").lower()}_playstation_avatar"
)

ImageEntity.__init__(self, coordinator.hass)
self._attr_has_entity_name = True
self._attr_name = "Playstation Avatar"
self._attr_icon = "mdi:face-man-profile"
self._attr_image_url = self.get_avatar()
self._attr_image_last_updated = dt_util.utcnow()

def get_avatar(self) -> str:
"""Return Avatar URL"""
previous_image = self._attr_image_url
current_image = None
for avatar in self.coordinator.data.get("profile", {}).get("avatars", []):
if avatar.get("size") == "xl":
current_image = avatar.get("url", None)

if previous_image != current_image:
self._cached_image = None
self._attr_image_last_updated = dt_util.utcnow()

return current_image

@callback
def _handle_coordinator_update(self) -> None:
self._attr_image_url = self.get_avatar()
self.async_write_ha_state()
50 changes: 12 additions & 38 deletions custom_components/playstation_network/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,6 @@ def get_status(coordinator_data: any) -> str:
return "Offline"


def get_avatar(data: any) -> str:
"""Return Avatar URL"""
for avatar in data.get("profile").get("avatars"):
if avatar.get("size") == "l":
return avatar.get("url")


def get_status_attr(coordinator_data: any) -> dict[str, str]:
"""Parses status attributes"""
attrs: dict[str, str] = {
Expand All @@ -64,8 +57,6 @@ def get_status_attr(coordinator_data: any) -> dict[str, str]:
"play_duration": None,
"star_rating": None,
"about_me": None,
"avatar": None,
"playstation_plus": None,
"trophies": {
"platinum": None,
"gold": None,
Expand All @@ -82,15 +73,23 @@ def get_status_attr(coordinator_data: any) -> dict[str, str]:
}

attrs["next_level_progress"] = coordinator_data.get("trophy_summary").progress
attrs["about_me"] = coordinator_data.get("profile").get("aboutMe")

if coordinator_data.get("title_metadata", {}).get("npTitleId"):
title = coordinator_data.get("title_details", [{}])[0]
title_trophies = coordinator_data.get("title_trophies", {})

attrs["name"] = title.get("name", "").title()
attrs["description"] = (
title.get("descriptions", [""])[0].get("desc", "").title()
)

description = ""
for desc in title.get("descriptions", [""]):
if desc.get("type") == "SHORT":
description = desc.get("desc", "").title()

if len(description) >= 252:
description = f"{description[0:252]}..."
attrs["description"] = description

attrs["platform"] = (
coordinator_data.get("presence", {})
.get("basicPresence", {})
Expand All @@ -103,11 +102,6 @@ def get_status_attr(coordinator_data: any) -> dict[str, str]:
attrs["earned_trophies"] = title_trophies.earned_trophies
attrs["trophy_progress"] = title_trophies.progress

attrs["about_me"] = coordinator_data.get("profile").get("aboutMe")
attrs["playstation_plus"] = coordinator_data.get("profile").get("isPlus")

attrs["avatar"] = get_avatar(coordinator_data)

for t in coordinator_data["recent_titles"]:
if t.title_id == coordinator_data.get("title_metadata").get("npTitleId"):
title_stats = t
Expand Down Expand Up @@ -195,27 +189,7 @@ def get_trophy_attr(coordinator_data: any) -> dict[str, str]:
entity_registry_enabled_default=True,
has_entity_name=True,
unique_id="psn_about_me_attr",
value_fn=lambda data: data.get("profile").get("aboutMe"),
),
PsnSensorEntityDescription(
key="has_playstation_plus",
native_unit_of_measurement=None,
name="Playstation Plus",
icon="mdi:gamepad-outline",
entity_registry_enabled_default=True,
has_entity_name=True,
unique_id="psn_playstation_plus_attr",
value_fn=lambda data: data.get("profile").get("isPlus"),
),
PsnSensorEntityDescription(
key="avatar",
native_unit_of_measurement=None,
name="Avatar",
icon="mdi:face-man-profile",
entity_registry_enabled_default=True,
has_entity_name=True,
unique_id="psn_avatar_attr",
value_fn=get_avatar,
value_fn=lambda data: data.get("about_me"),
),
PsnSensorEntityDescription(
key="platform",
Expand Down

0 comments on commit 78d3021

Please sign in to comment.