XBOX ONE and PS4 components do not work with Hassio 0.88

Hi All,

I have just upgraded to Hassio and I noticed that the XBOX ONE and PS4 components do not work anymore:

This is what the log tells me about the PS4 component:

Error loading custom_components.media_player.ps4. Make sure all dependencies are installed

Traceback (most recent call last): File "/usr/local/lib/python3.7/site-packages/homeassistant/loader.py", line 147, in _load_file module = importlib.import_module(path) File "/usr/local/lib/python3.7/importlib/__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1006, in _gcd_import File "<frozen importlib._bootstrap>", line 983, in _find_and_load File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 677, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 728, in exec_module File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed File "/config/custom_components/media_player/ps4.py", line 11, in <module> from homeassistant.components.media_player import ( ImportError: cannot import name 'MEDIA_TYPE_CHANNEL' from 'homeassistant.components.media_player' (/usr/local/lib/python3.7/site-packages/homeassistant/components/media_player/__init__.py)

And this about the XBOX ONE component:

Error loading custom_components.media_player.xboxone. Make sure all dependencies are installed

Traceback (most recent call last): File "/usr/local/lib/python3.7/site-packages/homeassistant/loader.py", line 147, in _load_file module = importlib.import_module(path) File "/usr/local/lib/python3.7/importlib/__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1006, in _gcd_import File "<frozen importlib._bootstrap>", line 983, in _find_and_load File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 677, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 728, in exec_module File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed File "/config/custom_components/media_player/xboxone.py", line 17, in <module> from homeassistant.components.media_player import ( ImportError: cannot import name 'SUPPORT_TURN_OFF' from 'homeassistant.components.media_player' (/usr/local/lib/python3.7/site-packages/homeassistant/components/media_player/__init__.py)

I am getting the same error with the xbox component on 0.88, hopefully this can be fixed soon.

I had the same error after the update, it way due to the fact that some constants were moved to components.media_player.const. If you make the following change to xboxone.py it will work again:

  • Old code row 17:

from homeassistant.components.media_player.const import (
SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, PLATFORM_SCHEMA,
SUPPORT_SELECT_SOURCE, SUPPORT_TURN_OFF, SUPPORT_TURN_ON,
SUPPORT_VOLUME_STEP, SUPPORT_VOLUME_MUTE, SUPPORT_PLAY, MediaPlayerDevice,
MEDIA_TYPE_MUSIC, MEDIA_TYPE_VIDEO, MEDIA_TYPE_TVSHOW, MEDIA_TYPE_CHANNEL)

  • New code:
from homeassistant.components.media_player import (
    MediaPlayerDevice, MEDIA_PLAYER_SCHEMA, PLATFORM_SCHEMA)

from homeassistant.components.media_player.const import (
    SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK,
    SUPPORT_SELECT_SOURCE, SUPPORT_TURN_OFF, SUPPORT_TURN_ON,
    SUPPORT_VOLUME_STEP, SUPPORT_VOLUME_MUTE, SUPPORT_PLAY,
    MEDIA_TYPE_MUSIC, MEDIA_TYPE_VIDEO, MEDIA_TYPE_TVSHOW, MEDIA_TYPE_CHANNEL)

Hereafter you get a warning that the folder stucture has to change, to be safe for the future make the following folder structure:

  • /custom_components/xboxone/media_player.py ← this was xboxone.py

Let me know if it worked :slight_smile:

I have changed the code as you suggested.

Renamed the xboxone.py to media_player.py and placed that in xboxone folder in custom_components.

And it works again! Thanks @Onandon.

Do you also know how PS4 needs to be refactored?

I dont’t have an PS4 but is seems like the same problem. Can you send me a link or the ps4.py file itself? I will take a look for you…

Nice, thanks!

"""Playstation 4 media_player using ps4-waker."""
import json
import logging
import urllib.request
from datetime import timedelta
from urllib.parse import urlparse
import requests
import voluptuous as vol

import homeassistant.util as util
from homeassistant.components.media_player import (
    PLATFORM_SCHEMA,
    MEDIA_TYPE_CHANNEL,
    SUPPORT_TURN_ON,
    SUPPORT_TURN_OFF,
    SUPPORT_STOP,
    SUPPORT_SELECT_SOURCE,
    ENTITY_IMAGE_URL,
    MediaPlayerDevice
)
from homeassistant.const import (
    STATE_IDLE,
    STATE_UNKNOWN,
    STATE_OFF,
    STATE_PLAYING,
    CONF_NAME,
    CONF_HOST
)
from homeassistant.helpers import config_validation as cv

REQUIREMENTS = []

_LOGGER = logging.getLogger(__name__)

SUPPORT_PS4 = SUPPORT_TURN_OFF | SUPPORT_TURN_ON | \
              SUPPORT_STOP | SUPPORT_SELECT_SOURCE

DEFAULT_NAME = 'Playstation 4'
DEFAULT_PORT = ''
ICON = 'mdi:playstation'
CONF_GAMES_FILENAME = 'games_filename'
CONF_IMAGEMAP_JSON = 'imagemap_json'
CONF_CMD = 'cmd'
CONF_LOCAL_STORE = "local_store"
CONF_PS4_IP = "ps4_ip"

PS4_GAMES_FILE = 'ps4-games.json'
MEDIA_IMAGE_DEFAULT = ''
MEDIA_IMAGEMAP_JSON = 'https://github.com/hmn/ps4-imagemap/raw/master/games.json'
LOCAL_STORE = ''

MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1)

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Required(CONF_HOST): cv.string,
    vol.Optional(CONF_PS4_IP): cv.string,
    vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
    vol.Optional(CONF_GAMES_FILENAME, default=PS4_GAMES_FILE): cv.string,
    vol.Optional(CONF_IMAGEMAP_JSON, default=MEDIA_IMAGEMAP_JSON): cv.string,
    vol.Optional(CONF_LOCAL_STORE, default=LOCAL_STORE): cv.string,
})


def setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup PS4 platform."""
    if discovery_info is not None:
        ip = urlparse(discovery_info[1]).hostname
    else:
        ip = config.get(CONF_PS4_IP)

    if ip is None:
        _LOGGER.error("No PS4 found in configuration file or with discovery")
        return False

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    games_filename = hass.config.path(config.get(CONF_GAMES_FILENAME))
    games_map_json = config.get(CONF_IMAGEMAP_JSON)
    local_store = config.get(CONF_LOCAL_STORE)

    ps4 = PS4Waker(host, ip, games_filename)
    add_devices([PS4Device(name, ps4, games_map_json, local_store)], True)


class PS4Device(MediaPlayerDevice):
    """Representation of a PS4."""

    def __init__(self, name, ps4, gamesmap_json, local_store):
        """Initialize the ps4 device."""
        self.ps4 = ps4
        self._name = name
        self._state = STATE_UNKNOWN
        self._media_content_id = None
        self._media_title = None
        self._current_source = None
        self._current_source_id = None
        self._media_image = None
        self._games_map_json = gamesmap_json
        self._games_map = {}
        self._local_store = local_store
        if self._local_store == '':
            self.load_games_map()
        self.update()

    @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS)
    def update(self):
        """Retrieve the latest data."""
        data = self.ps4.search()
        self._media_title = data.get('running-app-name')
        self._media_content_id = data.get('running-app-titleid')
        self._current_source = data.get('running-app-name')
        self._current_source_id = data.get('running-app-titleid')

        if data.get('status') == 'Ok':
            if self._media_content_id is not None:
                self._state = STATE_PLAYING
            else:
                self._state = STATE_IDLE
        else:
            self._state = STATE_OFF
            self._media_title = None
            self._media_content_id = None
            self._current_source = None
            self._current_source_id = None
            self._media_image = None

    def load_games_map(self):
        import urllib.request, json

        try:
            with urllib.request.urlopen(self._games_map_json) as url:
                self._games_map = json.loads(url.read().decode())
            #self._games_map = json.loads(requests.get(self._games_map_json, verify=False))
        except Exception as e:
            _LOGGER.error("gamesmap json file could not be loaded, %s" % e)

    @property
    def entity_picture(self):
        if self.state == STATE_OFF:
            return None

        if self._local_store == '':
            image_hash = self.media_image_hash

            if image_hash is None:
                return None

            return ENTITY_IMAGE_URL.format(
                self.entity_id, self.access_token, image_hash)

        if self._media_content_id is None:
            return None

        filename = "/local/%s/%s.jpg" % (self._local_store, self._media_content_id)
        self._media_image = filename
        return filename

    @property
    def name(self):
        """Return the name of the device."""
        return self._name

    @property
    def state(self):
        """Return the state of the device."""
        return self._state

    @property
    def icon(self):
        """Icon."""
        return ICON

    @property
    def media_content_id(self):
        """Content ID of current playing media."""
        return self._media_content_id

    @property
    def media_content_type(self):
        """Content type of current playing media."""
        return MEDIA_TYPE_CHANNEL

    @property
    def media_image_url(self):
        """Image url of current playing media."""
        if self._media_content_id == '':
            return MEDIA_IMAGE_DEFAULT
            
        if self._local_store == '':
            try:
                return self._games_map[self._media_content_id]
            except KeyError:
                return MEDIA_IMAGE_DEFAULT 

        try:
            return self._media_image
        except KeyError:
            return MEDIA_IMAGE_DEFAULT 

    @property
    def media_title(self):
        """Title of current playing media."""
        return self._media_title

    @property
    def supported_features(self):
        """Media player features that are supported."""
        return SUPPORT_PS4

    @property
    def source(self):
        """Return the current input source."""
        return self._current_source

    @property
    def source_list(self):
        """List of available input sources."""
        return sorted(self.ps4.games.values())

    def turn_off(self):
        """Turn off media player."""
        self.ps4.standby()

    def turn_on(self):
        """Turn on the media player."""
        self.ps4.wake()
        self.update()

    def media_pause(self):
        """Send keypress ps to return to menu."""
        self.ps4.remote('ps')
        self.update()

    def media_stop(self):
        """Send keypress ps to return to menu."""
        self.ps4.remote('ps')
        self.update()

    def select_source(self, source):
        """Select input source."""
        for titleid, game in self.ps4.games.items():
            if source == game:
                self.ps4.start(titleid)
                self._current_source_id = titleid
                self._current_source = game
                self._media_content_id = titleid
                self._media_title = game
                self._media_image = self.entity_picture()
                self.update()


class PS4Waker(object):
    """Rest client for handling the data retrieval."""

    def __init__(self, url, ip, games_filename):
        """Initialize the data object."""
        self._url = url
        self._ip = ip
        self._games_filename = games_filename
        self.games = {}
        self._load_games()

    def __call(self, command, param=None):
        url = '{0}/ps4/{1}/{2}'.format(self._url, self._ip, command)
        if param is not None:
            url += '/{0}'.format(param)

        try:
            response = requests.get(url, verify=False)
            if 200 != response.status_code:
                raise Exception(response.text)
            return response.text
        except Exception as e:
            _LOGGER.error('Failed to call %s: %s', command, e)
            return None

    def _load_games(self):
        try:
            with open(self._games_filename, 'r') as f:
                self.games = json.load(f)
                f.close()
        except FileNotFoundError:
            self._save_games()
        except ValueError as e:
            _LOGGER.error('Games json file wrong: %s', e)

    def _save_games(self):
        try:
            with open(self._games_filename, 'w') as f:
                json.dump(self.games, f)
                f.close()
        except FileNotFoundError:
            pass

    def wake(self):
        """Wake PS4 up."""
        return self.__call('on')

    def standby(self):
        """Set PS4 into standby mode."""
        return self.__call('off')

    def start(self, title_id):
        """Start game using titleId."""
        return self.__call('start', title_id)

    def remote(self, key):
        """Send remote key press."""
        return self.__call('key', key)

    def search(self):
        """List current info."""
        value = self.__call('info')

        if value is None:
            return {}

        try:
            data = json.loads(value)
        except json.decoder.JSONDecodeError as e:
            _LOGGER.error("Error decoding ps4 json : %s", e)
            data = {}

        """Save current game"""
        if data.get('running-app-titleid'):
            if data.get('running-app-titleid') not in self.games.keys():
                game = {data.get('running-app-titleid'):
                            data.get('running-app-name')}
                self.games.update(game)
                self._save_games()

        return data

I don’t know which custom component you use, but by guessing I think it is this one:

They are already busy with a beta fix but you could also just try it:

  • Old code line 9:
import homeassistant.util as util
from homeassistant.components.media_player import (
    ENTITY_IMAGE_URL, MEDIA_TYPE_CHANNEL, MediaPlayerDevice, PLATFORM_SCHEMA,
    SUPPORT_SELECT_SOURCE, SUPPORT_STOP, SUPPORT_TURN_OFF, SUPPORT_TURN_ON,	
)
  • New code line 9:
import homeassistant.util as util
from homeassistant.components.media_player import (
    PLATFORM_SCHEMA,
    MediaPlayerDevice,
    ENTITY_IMAGE_URL
)
from homeassistant.components.media_player.const import (
    MEDIA_TYPE_CHANNEL, SUPPORT_TURN_ON,
    SUPPORT_TURN_OFF,
    SUPPORT_STOP,
    SUPPORT_SELECT_SOURCE
)

Good luck :slight_smile:

PS.: And ofcourse the same with the file naming. So:

  • /custom_components/ps4/media_player.py ← this is your ps4.py
2 Likes

And the PS4 also works again, thanks @Onandon, much appreciated!

Good to see my bandaid fix working for others. There is an update that’s under review.

and here is the fix for the PS4

It is all working for me now, thanks!

Hey Onandon, any chance you can take a look at the HEOS media component, the dev is not responding. I tried manually tweaking based on how you did it but i am still getting an error on “state_puased” declaration. Here is what i tried

from homeassistant.components.media_player import ( MediaPlayerDevice, PLATFORM_SCHEMA)
    
from homeassistant.components.media_player.const import ( MEDIA_TYPE_MUSIC,
        SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, # SUPPORT_VOLUME_STEP,
        SUPPORT_STOP, SUPPORT_PAUSE, SUPPORT_PLAY_MEDIA,
        SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK, SUPPORT_SEEK,
        SUPPORT_PLAY, STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN, STATE_OFF, MediaPlayerDevice, CONF_HOST, CONF_NAME)

The original file is here:https://github.com/Lampy09/hass.aioheos.media_player/blob/master/heos.py

Hi @skynet01, I don’t have a device to test it on but with the following changes it should work:

  • Old code (line 9):

from homeassistant.components.media_player import ( # pylint: disable=no-name-in-module
PLATFORM_SCHEMA, MEDIA_TYPE_MUSIC,
SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, # SUPPORT_VOLUME_STEP,
SUPPORT_STOP, SUPPORT_PAUSE, SUPPORT_PLAY_MEDIA,
SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK, SUPPORT_SEEK,
SUPPORT_PLAY, MediaPlayerDevice)
from homeassistant.const import (
CONF_HOST, CONF_NAME, CONF_USERNAME, CONF_PASSWORD, STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN, STATE_OFF)
import homeassistant.helpers.config_validation as cv

  • New code (line9):

from homeassistant.components.media_player.const import ( # pylint: disable=no-name-in-module
MEDIA_TYPE_MUSIC,
SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_VOLUME_STEP,
SUPPORT_STOP, SUPPORT_PAUSE, SUPPORT_PLAY_MEDIA,
SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK, SUPPORT_SEEK,
SUPPORT_PLAY)
from homeassistant.components.media_player import (MediaPlayerDevice, PLATFORM_SCHEMA)
from homeassistant.const import (CONF_HOST, CONF_NAME, CONF_USERNAME, CONF_PASSWORD, STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN, STATE_OFF)
import homeassistant.helpers.config_validation as cv

I hope it works now :slight_smile: please let me know!

Hahaha yesssss, it works! !!! you are a Magician Onandon!

PS4 had been working great for ages untill 0.88 update. I am confused as to what to change.
Here is my /config/custom_components/media_player/ps4.py

[details=“Summary”]
“”“Playstation 4 media_player using ps4-waker.”""
import json
import logging
from datetime import timedelta
from urllib.parse import urlparse
import requests
import voluptuous as vol

import homeassistant.util as util
from homeassistant.components.media_player import (
    PLATFORM_SCHEMA,
    MediaPlayerDevice,
    ENTITY_IMAGE_URL
)
from homeassistant.components.media_player import (
    PLATFORM_SCHEMA,
    MEDIA_TYPE_CHANNEL,
    SUPPORT_TURN_ON,
    SUPPORT_TURN_OFF,
    SUPPORT_STOP,
    SUPPORT_SELECT_SOURCE,
    ENTITY_IMAGE_URL,
    MediaPlayerDevice
)
from homeassistant.const import (
    STATE_IDLE,
    STATE_UNKNOWN,
    STATE_OFF,
    STATE_PLAYING,
    CONF_NAME,
    CONF_HOST
)
from homeassistant.helpers import config_validation as cv

REQUIREMENTS = []

_LOGGER = logging.getLogger(__name__)

SUPPORT_PS4 = SUPPORT_TURN_OFF | SUPPORT_TURN_ON | \
              SUPPORT_STOP | SUPPORT_SELECT_SOURCE

DEFAULT_NAME = 'Playstation 4'
DEFAULT_PORT = ''
ICON = 'mdi:playstation'
CONF_GAMES_FILENAME = 'games_filename'
CONF_IMAGEMAP_JSON = 'imagemap_json'
CONF_CMD = 'cmd'
CONF_LOCAL_STORE = "local_store"
CONF_PS4_IP = "ps4_ip"

PS4_GAMES_FILE = 'ps4-games.json'
MEDIA_IMAGE_DEFAULT = None
MEDIA_IMAGEMAP_JSON = 'https://github.com/hmn/ps4-imagemap/raw/master/games.json'
LOCAL_STORE = None

MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1)

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Required(CONF_HOST): cv.string,
    vol.Optional(CONF_PS4_IP): cv.string,
    vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
    vol.Optional(CONF_GAMES_FILENAME, default=PS4_GAMES_FILE): cv.string,
    vol.Optional(CONF_IMAGEMAP_JSON, default=MEDIA_IMAGEMAP_JSON): cv.string,
    vol.Optional(CONF_LOCAL_STORE, default=LOCAL_STORE): cv.string,
})


def setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup PS4 platform."""
    if discovery_info is not None:
        ip = urlparse(discovery_info[1]).hostname
    else:
        ip = config.get(CONF_PS4_IP)

    if ip is None:
        _LOGGER.error("No PS4 found in configuration file or with discovery")
        return False

    host = config.get(CONF_HOST)
    name = config.get(CONF_NAME)
    games_filename = hass.config.path(config.get(CONF_GAMES_FILENAME))
    games_map_json = config.get(CONF_IMAGEMAP_JSON)
    local_store = config.get(CONF_LOCAL_STORE)

    ps4 = PS4Waker(host, ip, games_filename)
    add_devices([PS4Device(name, ps4, games_map_json, local_store)], True)


class PS4Device(MediaPlayerDevice):
    """Representation of a PS4."""

    def __init__(self, name, ps4, gamesmap_json, local_store):
        """Initialize the ps4 device."""
        self.ps4 = ps4
        self._name = name
        self._state = STATE_UNKNOWN
        self._media_content_id = None
        self._media_title = None
        self._current_source = None
        self._current_source_id = None
        self._games_map_json = gamesmap_json
        self._games_map = {}
        self._local_store = local_store
        if self._local_store is None:
            self.load_games_map()
        self.update()

    @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS)
    def update(self):
        """Retrieve the latest data."""
        data = self.ps4.search()
        self._media_title = data.get('running-app-name')
        self._media_content_id = data.get('running-app-titleid')
        self._current_source = data.get('running-app-name')
        self._current_source_id = data.get('running-app-titleid')

        if data.get('status') == 'Ok':
            if self._media_content_id is not None:
                self._state = STATE_PLAYING
            else:
                self._state = STATE_IDLE
        else:
            self._state = STATE_OFF
            self._media_title = None
            self._media_content_id = None
            self._current_source = None
            self._current_source_id = None

    def load_games_map(self):
        try:
            self._games_map = json.loads(requests.get(self._games_map_json, verify=False))
        except Exception as e:
            _LOGGER.error("gamesmap json file could not be loaded, %s" % e)

    @property
    def entity_picture(self):
        if self.state == STATE_OFF:
            return None

        if self._local_store is None:
            image_hash = self.media_image_hash

            if image_hash is None:
                return None

            return ENTITY_IMAGE_URL.format(
                self.entity_id, self.access_token, image_hash)

        if self._media_content_id is None:
            return None

        filename = "/local/%s/%s.jpg" % (self._local_store, self._media_content_id)
        return filename

    @property
    def name(self):
        """Return the name of the device."""
        return self._name

    @property
    def state(self):
        """Return the state of the device."""
        return self._state

    @property
    def icon(self):
        """Icon."""
        return ICON

    @property
    def media_content_id(self):
        """Content ID of current playing media."""
        return self._media_content_id

    @property
    def media_content_type(self):
        """Content type of current playing media."""
        return MEDIA_TYPE_CHANNEL

    @property
    def media_image_url(self):
        """Image url of current playing media."""
        if self._media_content_id is None:
            return MEDIA_IMAGE_DEFAULT
        try:
            return self._games_map[self._media_content_id]
        except KeyError:
            return MEDIA_IMAGE_DEFAULT

    @property
    def media_title(self):
        """Title of current playing media."""
        return self._media_title

    @property
    def supported_features(self):
        """Media player features that are supported."""
        return SUPPORT_PS4

    @property
    def source(self):
        """Return the current input source."""
        return self._current_source

    @property
    def source_list(self):
        """List of available input sources."""
        return sorted(self.ps4.games.values())

    def turn_off(self):
        """Turn off media player."""
        self.ps4.standby()

    def turn_on(self):
        """Turn on the media player."""
        self.ps4.wake()
        self.update()

    def media_pause(self):
        """Send keypress ps to return to menu."""
        self.ps4.remote('ps')
        self.update()

    def media_stop(self):
        """Send keypress ps to return to menu."""
        self.ps4.remote('ps')
        self.update()

    def select_source(self, source):
        """Select input source."""
        for titleid, game in self.ps4.games.items():
            if source == game:
                self.ps4.start(titleid)
                self._current_source_id = titleid
                self._current_source = game
                self._media_content_id = titleid
                self._media_title = game
                self.update()


class PS4Waker(object):
    """Rest client for handling the data retrieval."""

    def __init__(self, url, ip, games_filename):
        """Initialize the data object."""
        self._url = url
        self._ip = ip
        self._games_filename = games_filename
        self.games = {}
        self._load_games()

    def __call(self, command, param=None):
        url = '{0}/ps4/{1}/{2}'.format(self._url, self._ip, command)
        if param is not None:
            url += '/{0}'.format(param)

        try:
            response = requests.get(url, verify=False)
            if 200 != response.status_code:
                raise Exception(response.text)
            return response.text
        except Exception as e:
            _LOGGER.error('Failed to call %s: %s', command, e)
            return None

    def _load_games(self):
        try:
            with open(self._games_filename, 'r') as f:
                self.games = json.load(f)
                f.close()
        except FileNotFoundError:
            self._save_games()
        except ValueError as e:
            _LOGGER.error('Games json file wrong: %s', e)

    def _save_games(self):
        try:
            with open(self._games_filename, 'w') as f:
                json.dump(self.games, f)
                f.close()
        except FileNotFoundError:
            pass

    def wake(self):
        """Wake PS4 up."""
        return self.__call('on')

    def standby(self):
        """Set PS4 into standby mode."""
        return self.__call('off')

    def start(self, title_id):
        """Start game using titleId."""
        return self.__call('start', title_id)

    def remote(self, key):
        """Send remote key press."""
        return self.__call('key', key)

    def search(self):
        """List current info."""
        value = self.__call('info')

        if value is None:
            return {}

        try:
            data = json.loads(value)
        except json.decoder.JSONDecodeError as e:
            _LOGGER.error("Error decoding ps4 json : %s", e)
            data = {}

        """Save current game"""
        if data.get('running-app-titleid'):
            if data.get('running-app-titleid') not in self.games.keys():
                game = {data.get('running-app-titleid'):
                            data.get('running-app-name')}
                self.games.update(game)
                self._save_games()

        return data
[/details]

and her is my /config/mediaplayer.yaml
- platform: ps4
host: http://10.1.1.42:3031
ps4_ip: 10.1.1.207
name: PlayStation 4
local_store: games

 - platform: vizio
   host: 10.1.1.37
   access_token: Zml5ui0gxc

PS4 seems to be supported with the 0.89 version now:

It works like a charm, I removed all the customisations and PS4 integration works perfectly! XBOX One next? :wink:

1 Like

Same here. 0.89 did the trick.

1 Like