Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PlayStation Network Integration #133850

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
1acc665
Add Playstation Network Support
JackJPowell Nov 17, 2024
0b67971
Add starline run sensor (#130444)
Anonym-tsk Nov 15, 2024
dff19a5
Allow reconnecting wireless omada clients (#128491)
reey Nov 15, 2024
2b461e6
Add two WiiM models to linkplay (#130707)
dnikles Nov 15, 2024
38db16a
Do not create ESPHome Dashboard update entity if no configuration fou…
jesserockz Nov 15, 2024
eb43141
Use shorthand attribute for extra state attributes in statistics (#12…
gjohansson-ST Nov 15, 2024
fd036db
Add action for using transformation items to Habitica (#129606)
tr4nt0r Nov 15, 2024
283033a
Add sensor platform to eq3btsmart (#130438)
EuleMitKeule Nov 15, 2024
c757fbc
Switcher add current current temperature sensor (#130653)
YogevBokobza Nov 15, 2024
f7879ed
KNX: Cache last telegram for each group address (#130566)
farmio Nov 15, 2024
c91f196
Bump ruff to 0.7.4 (#130716)
autinerd Nov 15, 2024
66aa875
Merge branch 'dev' into playstation-network2
tr4nt0r Nov 17, 2024
507a60a
further cleanup
JackJPowell Nov 26, 2024
80e03c5
Move coordinator logic to external library
JackJPowell Nov 29, 2024
cd9f242
Read directly from coordinator.data
JackJPowell Nov 29, 2024
5c35650
Misc. Fixes
JackJPowell Nov 30, 2024
cf62e3f
Minor fixes
JackJPowell Dec 13, 2024
9d7899e
npsso_link, entity_creation_callback, config_entry_type
JackJPowell Dec 13, 2024
03a4385
Add media player per console
JackJPowell Dec 14, 2024
36f6b10
final touches
JackJPowell Dec 22, 2024
34ad37c
Merge branch 'dev' into playstation_network
JackJPowell Dec 23, 2024
d1d5ae6
Add cover to the niko_home_control integration (#133801)
VandeurenGlenn Dec 23, 2024
19be434
Add AEMET Weather Radar images (#131386)
Noltari Dec 23, 2024
1ce5a04
Add Ecovacs station entities (#133876)
edenhaus Dec 23, 2024
65be59f
Set Fronius integration quality scale to gold (#133884)
farmio Dec 23, 2024
a24cd58
Update frontend to 20241223.1 (#133886)
bramkragten Dec 23, 2024
46f2303
Add two WiiM models to linkplay (#130707)
dnikles Nov 15, 2024
ca35381
Use shorthand attribute for extra state attributes in statistics (#12…
gjohansson-ST Nov 15, 2024
301567b
Bump ruff to 0.7.4 (#130716)
autinerd Nov 15, 2024
67c4738
Refactor npsso parsing and media player improvements
JackJPowell Dec 23, 2024
c2ebf4e
Merge branch 'home-assistant:dev' into playstation_network
JackJPowell Dec 23, 2024
ea9f38a
Merge branch 'home-assistant:dev' into playstation_network
JackJPowell Dec 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.3
rev: v0.7.4
hooks:
- id: ruff
args:
Expand Down
2 changes: 2 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,8 @@ build.json @home-assistant/supervisor
/tests/components/ping/ @jpbede
/homeassistant/components/plaato/ @JohNan
/tests/components/plaato/ @JohNan
/homeassistant/components/playstation_network/ @jackjpowell
/tests/components/playstation_network/ @jackjpowell
/homeassistant/components/plex/ @jjlawren
/tests/components/plex/ @jjlawren
/homeassistant/components/plugwise/ @CoMPaTech @bouwew @frenck
Expand Down
32 changes: 27 additions & 5 deletions homeassistant/components/linkplay/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
MANUFACTURER_ARYLIC: Final[str] = "Arylic"
MANUFACTURER_IEAST: Final[str] = "iEAST"
MANUFACTURER_WIIM: Final[str] = "WiiM"
MANUFACTURER_GGMM: Final[str] = "GGMM"
MANUFACTURER_MEDION: Final[str] = "Medion"
MANUFACTURER_GENERIC: Final[str] = "Generic"
MODELS_ARTSOUND_SMART_ZONE4: Final[str] = "Smart Zone 4 AMP"
MODELS_ARTSOUND_SMART_HYDE: Final[str] = "Smart Hyde"
Expand All @@ -33,8 +31,6 @@
MODELS_IEAST_AUDIOCAST_M5: Final[str] = "AudioCast M5"
MODELS_WIIM_AMP: Final[str] = "WiiM Amp"
MODELS_WIIM_MINI: Final[str] = "WiiM Mini"
MODELS_GGMM_GGMM_E2: Final[str] = "GGMM E2"
MODELS_MEDION_MD_43970: Final[str] = "Life P66970 (MD 43970)"
MODELS_GENERIC: Final[str] = "Generic"

PROJECTID_LOOKUP: Final[dict[str, tuple[str, str]]] = {
Expand Down Expand Up @@ -74,7 +70,33 @@

def get_info_from_project(project: str) -> tuple[str, str]:
"""Get manufacturer and model info based on given project."""
return PROJECTID_LOOKUP.get(project, (MANUFACTURER_GENERIC, MODELS_GENERIC))
match project:
case "SMART_ZONE4_AMP":
return MANUFACTURER_ARTSOUND, MODELS_ARTSOUND_SMART_ZONE4
case "SMART_HYDE":
return MANUFACTURER_ARTSOUND, MODELS_ARTSOUND_SMART_HYDE
case "ARYLIC_S50":
return MANUFACTURER_ARYLIC, MODELS_ARYLIC_S50
case "RP0016_S50PRO_S":
return MANUFACTURER_ARYLIC, MODELS_ARYLIC_S50_PRO
case "RP0011_WB60_S":
return MANUFACTURER_ARYLIC, MODELS_ARYLIC_A30
case "ARYLIC_A50S":
return MANUFACTURER_ARYLIC, MODELS_ARYLIC_A50S
case "UP2STREAM_AMP_V3":
return MANUFACTURER_ARYLIC, MODELS_ARYLIC_UP2STREAM_AMP_V3
case "UP2STREAM_AMP_V4":
return MANUFACTURER_ARYLIC, MODELS_ARYLIC_UP2STREAM_AMP_V4
case "UP2STREAM_PRO_V3":
return MANUFACTURER_ARYLIC, MODELS_ARYLIC_UP2STREAM_PRO_V3
case "iEAST-02":
return MANUFACTURER_IEAST, MODELS_IEAST_AUDIOCAST_M5
case "WiiM_Amp_4layer":
return MANUFACTURER_WIIM, MODELS_WIIM_AMP
case "Muzo_Mini":
return MANUFACTURER_WIIM, MODELS_WIIM_MINI
case _:
return MANUFACTURER_GENERIC, MODELS_GENERIC


async def async_get_client_session(hass: HomeAssistant) -> ClientSession:
Expand Down
36 changes: 36 additions & 0 deletions homeassistant/components/playstation_network/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""The PlayStation Network integration."""

from __future__ import annotations

from psnawp_api.psn import PlaystationNetwork

from homeassistant.const import Platform
from homeassistant.core import HomeAssistant

from .const import CONF_NPSSO
from .coordinator import PlaystationNetworkConfigEntry, PlaystationNetworkCoordinator

PLATFORMS: list[Platform] = [Platform.MEDIA_PLAYER]


async def async_setup_entry(
hass: HomeAssistant, entry: PlaystationNetworkConfigEntry
) -> bool:
"""Set up Playstation Network from a config entry."""

psn = PlaystationNetwork(entry.data[CONF_NPSSO])
user = await hass.async_add_executor_job(psn.get_user)

coordinator = PlaystationNetworkCoordinator(hass, psn, user)
await coordinator.async_config_entry_first_refresh()
entry.runtime_data = coordinator

await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
return True


async def async_unload_entry(
hass: HomeAssistant, entry: PlaystationNetworkConfigEntry
) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
58 changes: 58 additions & 0 deletions homeassistant/components/playstation_network/config_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""Config flow for the PlayStation Network integration."""

import logging
from typing import Any

from psnawp_api.core.psnawp_exceptions import PSNAWPAuthenticationError, PSNAWPException
from psnawp_api.models.user import User
from psnawp_api.psn import PlaystationNetwork
import voluptuous as vol

from homeassistant.config_entries import ConfigFlow, ConfigFlowResult

from .const import CONF_NPSSO, DOMAIN

_LOGGER = logging.getLogger(__name__)

STEP_USER_DATA_SCHEMA = vol.Schema({vol.Required(CONF_NPSSO): str})


class PlaystationNetworkConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Playstation Network."""

async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle the initial step."""
errors: dict[str, str] = {}
if user_input is not None:
try:
npsso = PlaystationNetwork.parse_npsso_token(
user_input.get(CONF_NPSSO, "")
)
psn = PlaystationNetwork(npsso)
user: User = await self.hass.async_add_executor_job(psn.get_user)
except PSNAWPAuthenticationError:
errors["base"] = "invalid_auth"
except PSNAWPException:
errors["base"] = "cannot_connect"
except Exception:
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else:
await self.async_set_unique_id(user.account_id)
self._abort_if_unique_id_configured()
return self.async_create_entry(
title=user.online_id,
data={CONF_NPSSO: npsso},
)

return self.async_show_form(
step_id="user",
data_schema=STEP_USER_DATA_SCHEMA,
errors=errors,
description_placeholders={
"npsso_link": "https://ca.account.sony.com/api/v1/ssocookie",
"psn_link": "https://playstation.com",
},
)
6 changes: 6 additions & 0 deletions homeassistant/components/playstation_network/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Constants for the Playstation Network integration."""

from typing import Final

DOMAIN = "playstation_network"
CONF_NPSSO: Final = "npsso"
61 changes: 61 additions & 0 deletions homeassistant/components/playstation_network/coordinator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""Coordinator for the PlayStation Network Integration."""

from __future__ import annotations

from datetime import timedelta
import logging

from psnawp_api.core.psnawp_exceptions import PSNAWPAuthenticationError
from psnawp_api.models.user import User
from psnawp_api.psn import PlaystationNetwork, PlaystationNetworkData

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)

type PlaystationNetworkConfigEntry = ConfigEntry[PlaystationNetworkCoordinator]


class PlaystationNetworkCoordinator(DataUpdateCoordinator[PlaystationNetworkData]):
"""Data update coordinator for PSN."""

config_entry: PlaystationNetworkConfigEntry

def __init__(
self, hass: HomeAssistant, psn: PlaystationNetwork, user: User
) -> None:
"""Initialize the Coordinator."""
super().__init__(
hass,
name=DOMAIN,
logger=_LOGGER,
update_interval=timedelta(seconds=30),
)

self.hass = hass
self.user: User = user
self.psn: PlaystationNetwork = psn

async def _async_update_data(self) -> PlaystationNetworkData:
"""Get the latest data from the PSN."""
try:
return await self.hass.async_add_executor_job(self.psn.get_data)
except PSNAWPAuthenticationError as error:
raise UpdateFailed(
DOMAIN,
"update_failed",
) from error

async def _async_setup(self) -> None:
try:
await self.hass.async_add_executor_job(self.psn.validate_connection)
except PSNAWPAuthenticationError as error:
raise ConfigEntryNotReady(
DOMAIN,
"not_ready",
) from error
9 changes: 9 additions & 0 deletions homeassistant/components/playstation_network/icons.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"entity": {
"media_player": {
"playstation": {
"default": "mdi:sony-playstation"
}
}
}
}
10 changes: 10 additions & 0 deletions homeassistant/components/playstation_network/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"domain": "playstation_network",
"name": "PlayStation Network",
"codeowners": ["@jackjpowell"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/playstation_network",
"integration_type": "service",
"iot_class": "cloud_polling",
"requirements": ["PSNAWP-HA==2.3.1"]
}
Loading