diff --git a/homeassistant/components/samsungtv/__init__.py b/homeassistant/components/samsungtv/__init__.py index 09b513c38303f375b186d5b5819ae6c9521deed5..773c340d7b9c45c277188c577538cccddc5d9f64 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 392beda6ac542a3bff064abf343ef3a60732a923..da13d0fe70c6b41b30d359a14ac11c05b22bcd88 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 133baccf4fb4cfcef0c11fd8f007aaab87a11c6d..36481b43756e0f2a11acfcb92340bc80ca577e2b 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 523bca15f4775e5c605106002178d34f14b81cb8..47bc55074be4aff7ed85f02c19533dc0d8e9382c 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 e2fd0df2fe00787282dae381ce16dfee69c0b7fe..f05af08862ea205d5da767ac5b75a4709756f0fd 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 4fe8ddc2b5e088265eaf02f31841671ec7e88df2..64d0c95c084416f6d1920bfc28fa7de850a16323 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(