From 2025afe14b18d35b186003057edbd44eec8bf47a Mon Sep 17 00:00:00 2001 From: Simone Chemelli <simone.chemelli@gmail.com> Date: Mon, 26 Jul 2021 16:43:05 +0200 Subject: [PATCH] Add MAC to SamsungTV when missing (#53479) * Add MAC when missing * Fix I/O * Add test for missing MAC address --- .../components/samsungtv/__init__.py | 14 ++++-- .../components/samsungtv/config_flow.py | 3 ++ .../components/samsungtv/manifest.json | 1 + requirements_all.txt | 1 + requirements_test_all.txt | 1 + .../components/samsungtv/test_config_flow.py | 49 +++++++++++++++++++ 6 files changed, 66 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/samsungtv/__init__.py b/homeassistant/components/samsungtv/__init__.py index 09b513c3830..773c340d7b9 100644 --- a/homeassistant/components/samsungtv/__init__.py +++ b/homeassistant/components/samsungtv/__init__.py @@ -1,6 +1,8 @@ """The Samsung TV integration.""" +from functools import partial import socket +import getmac import voluptuous as vol from homeassistant import config_entries @@ -140,13 +142,19 @@ async def _async_create_bridge_with_updated_data(hass, entry): bridge = _async_get_device_bridge({**entry.data, **updated_data}) - if not entry.data.get(CONF_MAC) and bridge.method == METHOD_WEBSOCKET: + mac = entry.data.get(CONF_MAC) + if not mac and bridge.method == METHOD_WEBSOCKET: if info: mac = mac_from_device_info(info) else: mac = await hass.async_add_executor_job(bridge.mac_from_device) - if mac: - updated_data[CONF_MAC] = mac + + if not mac: + mac = await hass.async_add_executor_job( + partial(getmac.get_mac_address, ip=host) + ) + if mac: + updated_data[CONF_MAC] = mac if updated_data: data = {**entry.data, **updated_data} diff --git a/homeassistant/components/samsungtv/config_flow.py b/homeassistant/components/samsungtv/config_flow.py index 392beda6ac5..da13d0fe70c 100644 --- a/homeassistant/components/samsungtv/config_flow.py +++ b/homeassistant/components/samsungtv/config_flow.py @@ -2,6 +2,7 @@ import socket from urllib.parse import urlparse +import getmac import voluptuous as vol from homeassistant import config_entries, data_entry_flow @@ -154,6 +155,8 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): self._udn = _strip_uuid(dev_info.get("udn", info["id"])) if mac := mac_from_device_info(info): self._mac = mac + elif mac := getmac.get_mac_address(ip=self._host): + self._mac = mac self._device_info = info return True diff --git a/homeassistant/components/samsungtv/manifest.json b/homeassistant/components/samsungtv/manifest.json index 133baccf4fb..36481b43756 100644 --- a/homeassistant/components/samsungtv/manifest.json +++ b/homeassistant/components/samsungtv/manifest.json @@ -3,6 +3,7 @@ "name": "Samsung Smart TV", "documentation": "https://www.home-assistant.io/integrations/samsungtv", "requirements": [ + "getmac==0.8.2", "samsungctl[websocket]==0.7.1", "samsungtvws==1.6.0", "wakeonlan==2.0.1" diff --git a/requirements_all.txt b/requirements_all.txt index 523bca15f47..47bc55074be 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -679,6 +679,7 @@ georss_qld_bushfire_alert_client==0.5 # homeassistant.components.kef # homeassistant.components.minecraft_server # homeassistant.components.nmap_tracker +# homeassistant.components.samsungtv getmac==0.8.2 # homeassistant.components.gios diff --git a/requirements_test_all.txt b/requirements_test_all.txt index e2fd0df2fe0..f05af08862e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -388,6 +388,7 @@ georss_qld_bushfire_alert_client==0.5 # homeassistant.components.kef # homeassistant.components.minecraft_server # homeassistant.components.nmap_tracker +# homeassistant.components.samsungtv getmac==0.8.2 # homeassistant.components.gios diff --git a/tests/components/samsungtv/test_config_flow.py b/tests/components/samsungtv/test_config_flow.py index 4fe8ddc2b5e..64d0c95c084 100644 --- a/tests/components/samsungtv/test_config_flow.py +++ b/tests/components/samsungtv/test_config_flow.py @@ -797,6 +797,55 @@ async def test_autodetect_websocket(hass: HomeAssistant, remote: Mock, remotews: assert entries[0].data[CONF_MAC] == "aa:bb:cc:dd:ee:ff" +async def test_websocket_no_mac(hass: HomeAssistant, remote: Mock, remotews: Mock): + """Test for send key with autodetection of protocol.""" + with patch( + "homeassistant.components.samsungtv.bridge.Remote", + side_effect=OSError("Boom"), + ), patch( + "homeassistant.components.samsungtv.config_flow.socket.gethostbyname", + return_value="fake_host", + ), patch( + "homeassistant.components.samsungtv.bridge.SamsungTVWS" + ) as remotews, patch( + "getmac.get_mac_address", return_value="gg:hh:ii:ll:mm:nn" + ): + enter = Mock() + type(enter).token = PropertyMock(return_value="123456789") + remote = Mock() + remote.__enter__ = Mock(return_value=enter) + remote.__exit__ = Mock(return_value=False) + remote.rest_device_info.return_value = { + "id": "uuid:be9554b9-c9fb-41f4-8920-22da015376a4", + "device": { + "modelName": "82GXARRS", + "networkType": "lan", + "udn": "uuid:be9554b9-c9fb-41f4-8920-22da015376a4", + "name": "[TV] Living Room", + "type": "Samsung SmartTV", + }, + } + remotews.return_value = remote + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER}, data=MOCK_USER_DATA + ) + assert result["type"] == "create_entry" + assert result["data"][CONF_METHOD] == "websocket" + assert result["data"][CONF_TOKEN] == "123456789" + assert result["data"][CONF_MAC] == "gg:hh:ii:ll:mm:nn" + assert remotews.call_count == 2 + assert remotews.call_args_list == [ + call(**AUTODETECT_WEBSOCKET_SSL), + call(**DEVICEINFO_WEBSOCKET_SSL), + ] + await hass.async_block_till_done() + + entries = hass.config_entries.async_entries(DOMAIN) + assert len(entries) == 1 + assert entries[0].data[CONF_MAC] == "gg:hh:ii:ll:mm:nn" + + async def test_autodetect_auth_missing(hass: HomeAssistant, remote: Mock): """Test for send key with autodetection of protocol.""" with patch( -- GitLab