1 """Support for PlayStation 4 consoles."""
6 from pyps4_2ndscreen.ddp
import async_create_ddp_endpoint
7 from pyps4_2ndscreen.media_art
import COUNTRIES
8 import voluptuous
as vol
12 ATTR_MEDIA_CONTENT_TYPE,
34 from .config_flow
import PlayStation4FlowHandler
44 _LOGGER = logging.getLogger(__name__)
46 SERVICE_COMMAND =
"send_command"
48 PS4_COMMAND_SCHEMA = vol.Schema(
50 vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
51 vol.Required(ATTR_COMMAND): vol.In(
list(COMMANDS)),
55 PLATFORMS = [Platform.MEDIA_PLAYER]
57 CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
61 """Init Data Class."""
69 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
70 """Set up the PS4 Component."""
73 transport, protocol = await async_create_ddp_endpoint()
74 hass.data[PS4_DATA].protocol = protocol
75 _LOGGER.debug(
"PS4 DDP endpoint created: %s, %s", transport, protocol)
81 """Set up PS4 from a config entry."""
82 await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
87 """Unload a PS4 config entry."""
88 return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
92 """Migrate old entry."""
93 config_entries = hass.config_entries
95 version = entry.version
97 _LOGGER.debug(
"Migrating PS4 entry from Version %s", version)
100 1:
"Region codes have changed",
101 2:
"Format for Unique ID for entity registry has changed",
108 country = COUNTRYCODE_NAMES.get(loc.country_code)
109 if country
in COUNTRIES:
110 for device
in data[
"devices"]:
111 device[CONF_REGION] = country
113 config_entries.async_update_entry(entry, data=data, version=2)
115 "PlayStation 4 Config Updated: Region changed to: %s",
122 registry = er.async_get(hass)
124 for e_entry
in registry.entities.get_entries_for_config_entry_id(
127 unique_id = e_entry.unique_id
128 entity_id = e_entry.entity_id
131 registry.async_remove(entity_id)
138 registry.async_get_or_create(
142 suggested_object_id=new_id,
144 device_id=e_entry.device_id,
147 "PlayStation 4 identifier for entity: %s has changed",
150 config_entries.async_update_entry(entry, version=3)
153 msg = f
"""{reason[version]} for the PlayStation 4 Integration.
154 Please remove the PS4 Integration and re-configure
155 [here](/config/integrations)."""
157 persistent_notification.async_create(
159 title=
"PlayStation 4 Integration Configuration Requires Update",
161 notification_id=
"config_entry_migration",
167 """Use last 4 Chars of credential as suffix. Unique ID per PSN user."""
169 return f
"{mac_address}_{suffix}"
172 def load_games(hass: HomeAssistant, unique_id: str) -> JsonObjectType:
173 """Load games for sources."""
174 g_file = hass.config.path(GAMES_FILE.format(unique_id))
177 except HomeAssistantError
as error:
179 _LOGGER.error(
"Failed to load games file: %s", error)
182 if os.path.isfile(g_file):
187 def save_games(hass: HomeAssistant, games: dict, unique_id: str):
188 """Save games to file."""
189 g_file = hass.config.path(GAMES_FILE.format(unique_id))
192 except OSError
as error:
193 _LOGGER.error(
"Could not save game list, %s", error)
197 """Reformat data to correct format."""
198 data_reformatted =
False
200 for game, data
in games.items():
202 if not isinstance(data, dict):
206 ATTR_MEDIA_TITLE: data,
207 ATTR_MEDIA_IMAGE_URL:
None,
208 ATTR_MEDIA_CONTENT_TYPE: MediaType.GAME,
210 data_reformatted =
True
212 _LOGGER.debug(
"Reformatting media data for item: %s, %s", game, data)
220 """Handle for services."""
222 async
def async_service_command(call: ServiceCall) ->
None:
223 """Service for sending commands."""
224 entity_ids = call.data[ATTR_ENTITY_ID]
225 command = call.data[ATTR_COMMAND]
226 for device
in hass.data[PS4_DATA].devices:
227 if device.entity_id
in entity_ids:
228 await device.async_send_command(command)
230 hass.services.async_register(
231 DOMAIN, SERVICE_COMMAND, async_service_command, schema=PS4_COMMAND_SCHEMA
bool async_migrate_entry(HomeAssistant hass, ConfigEntry entry)
bool async_setup(HomeAssistant hass, ConfigType config)
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
dict _reformat_data(HomeAssistant hass, dict games, str unique_id)
JsonObjectType load_games(HomeAssistant hass, str unique_id)
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
def format_unique_id(creds, mac_address)
def save_games(HomeAssistant hass, dict games, str unique_id)
def service_handle(HomeAssistant hass)
tuple[str, str] split_entity_id(str entity_id)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)
None save_json(str filename, list|dict data, bool private=False, *type[json.JSONEncoder]|None encoder=None, bool atomic_writes=False)
JsonObjectType load_json_object(str|PathLike[str] filename, JsonObjectType default=_SENTINEL)