diff --git a/homeassistant/components/directv/media_player.py b/homeassistant/components/directv/media_player.py index cd4f910c707..603d0127fe6 100644 --- a/homeassistant/components/directv/media_player.py +++ b/homeassistant/components/directv/media_player.py @@ -77,23 +77,24 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the DirecTV platform.""" known_devices = hass.data.get(DATA_DIRECTV, set()) - hosts = [] + entities = [] if CONF_HOST in config: + name = config[CONF_NAME] + host = config[CONF_HOST] + port = config[CONF_PORT] + device = config[CONF_DEVICE] + _LOGGER.debug( - "Adding configured device %s with client address %s ", - config.get(CONF_NAME), - config.get(CONF_DEVICE), - ) - hosts.append( - [ - config.get(CONF_NAME), - config.get(CONF_HOST), - config.get(CONF_PORT), - config.get(CONF_DEVICE), - ] + "Adding configured device %s with client address %s", name, device, ) + dtv = DIRECTV(host, port, device) + dtv_version = _get_receiver_version(dtv) + + entities.append(DirecTvDevice(name, device, dtv, dtv_version,)) + known_devices.add((host, device)) + elif discovery_info: host = discovery_info.get("host") name = "DirecTV_{}".format(discovery_info.get("serial", "")) @@ -102,7 +103,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None): _LOGGER.debug("Doing discovery of DirecTV devices on %s", host) dtv = DIRECTV(host, DEFAULT_PORT) + try: + dtv_version = _get_receiver_version(dtv) resp = dtv.get_locations() except requests.exceptions.RequestException as ex: # Bail out and just go forward with uPnP data @@ -116,6 +119,8 @@ def setup_platform(hass, config, add_entities, discovery_info=None): if "locationName" not in loc or "clientAddr" not in loc: continue + loc_name = str.title(loc["locationName"]) + # Make sure that this device is not already configured # Comparing based on host (IP) and clientAddr. if (host, loc["clientAddr"]) in known_devices: @@ -123,42 +128,47 @@ def setup_platform(hass, config, add_entities, discovery_info=None): "Discovered device %s on host %s with " "client address %s is already " "configured", - str.title(loc["locationName"]), + loc_name, host, loc["clientAddr"], ) else: _LOGGER.debug( "Adding discovered device %s with client address %s", - str.title(loc["locationName"]), + loc_name, loc["clientAddr"], ) - hosts.append( - [ - str.title(loc["locationName"]), - host, - DEFAULT_PORT, + + entities.append( + DirecTvDevice( + loc_name, loc["clientAddr"], - ] + DIRECTV(host, DEFAULT_PORT, loc["clientAddr"]), + dtv_version, + ) ) + known_devices.add((host, loc["clientAddr"])) - dtvs = [] + add_entities(entities) - for host in hosts: - dtvs.append(DirecTvDevice(*host)) - hass.data.setdefault(DATA_DIRECTV, set()).add((host[1], host[3])) - add_entities(dtvs) +def _get_receiver_version(client): + """Return the version of the DirectTV receiver.""" + try: + return client.get_version() + except requests.exceptions.RequestException as ex: + _LOGGER.debug("Request exception %s trying to get receiver version", ex) + return None class DirecTvDevice(MediaPlayerDevice): """Representation of a DirecTV receiver on the network.""" - def __init__(self, name, host, port, device): + def __init__(self, name, device, dtv, version_info=None): """Initialize the device.""" - - self.dtv = DIRECTV(host, port, device) + self.dtv = dtv self._name = name + self._unique_id = None self._is_standby = True self._current = None self._last_update = None @@ -170,6 +180,11 @@ class DirecTvDevice(MediaPlayerDevice): self._available = False self._first_error_timestamp = None + if device != "0": + self._unique_id = device + elif version_info: + self._unique_id = "".join(version_info.get("receiverId").split()) + if self._is_client: _LOGGER.debug("Created DirecTV client %s for device %s", self._name, device) else: @@ -257,6 +272,11 @@ class DirecTvDevice(MediaPlayerDevice): """Return the name of the device.""" return self._name + @property + def unique_id(self): + """Return a unique ID to use for this media player.""" + return self._unique_id + # MediaPlayerDevice properties and methods @property def state(self): diff --git a/tests/components/directv/test_media_player.py b/tests/components/directv/test_media_player.py index 449147c3648..be805d837f5 100644 --- a/tests/components/directv/test_media_player.py +++ b/tests/components/directv/test_media_player.py @@ -60,6 +60,7 @@ import homeassistant.util.dt as dt_util from tests.common import async_fire_time_changed +ATTR_UNIQUE_ID = "unique_id" CLIENT_ENTITY_ID = "media_player.client_dvr" MAIN_ENTITY_ID = "media_player.main_dvr" IP_ADDRESS = "127.0.0.1" @@ -138,7 +139,7 @@ def main_dtv(): def dtv_side_effect(client_dtv, main_dtv): """Fixture to create DIRECTV instance for main and client.""" - def mock_dtv(ip, port, client_addr): + def mock_dtv(ip, port, client_addr="0"): if client_addr != "0": mocked_dtv = client_dtv else: @@ -174,7 +175,7 @@ def platforms(hass, dtv_side_effect, mock_now): "name": "Client DVR", "host": IP_ADDRESS, "port": DEFAULT_PORT, - "device": "1", + "device": "2CA17D1CD30X", }, ] } @@ -272,6 +273,20 @@ class MockDirectvClass: return test_locations + def get_serial_num(self): + """Mock for get_serial_num method.""" + test_serial_num = { + "serialNum": "9999999999", + "status": { + "code": 200, + "commandResult": 0, + "msg": "OK.", + "query": "/info/getSerialNum", + }, + } + + return test_serial_num + def get_standby(self): """Mock for get_standby method.""" return self._standby @@ -290,6 +305,24 @@ class MockDirectvClass: } return test_attributes + def get_version(self): + """Mock for get_version method.""" + test_version = { + "accessCardId": "0021-1495-6572", + "receiverId": "0288 7745 5858", + "status": { + "code": 200, + "commandResult": 0, + "msg": "OK.", + "query": "/info/getVersion", + }, + "stbSoftwareVersion": "0x4ed7", + "systemTime": 1281625203, + "version": "1.2", + } + + return test_version + def key_press(self, keypress): """Mock for key_press method.""" if keypress == "poweron": @@ -391,6 +424,17 @@ async def test_setup_platform_discover_client(hass): assert len(hass.states.async_entity_ids("media_player")) == 3 +async def test_unique_id(hass, platforms): + """Test unique id.""" + entity_registry = await hass.helpers.entity_registry.async_get_registry() + + main = entity_registry.async_get(MAIN_ENTITY_ID) + assert main.unique_id == "028877455858" + + client = entity_registry.async_get(CLIENT_ENTITY_ID) + assert client.unique_id == "2CA17D1CD30X" + + async def test_supported_features(hass, platforms): """Test supported features.""" # Features supported for main DVR