From 4209d7733b3983cc45f61b4eb6c758f5edb314b0 Mon Sep 17 00:00:00 2001 From: Antonino Piazza Date: Fri, 8 Jul 2022 22:09:03 +0200 Subject: [PATCH] Add huawei_lte wifi guest network switch (#71035) --- .../components/huawei_lte/__init__.py | 13 ++ homeassistant/components/huawei_lte/const.py | 3 +- homeassistant/components/huawei_lte/switch.py | 47 +++++- tests/components/huawei_lte/test_switches.py | 138 ++++++++++++++++++ 4 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 tests/components/huawei_lte/test_switches.py diff --git a/homeassistant/components/huawei_lte/__init__.py b/homeassistant/components/huawei_lte/__init__.py index f4e2cb209db..c0337095a9c 100644 --- a/homeassistant/components/huawei_lte/__init__.py +++ b/homeassistant/components/huawei_lte/__init__.py @@ -74,6 +74,7 @@ from .const import ( KEY_SMS_SMS_COUNT, KEY_WLAN_HOST_LIST, KEY_WLAN_WIFI_FEATURE_SWITCH, + KEY_WLAN_WIFI_GUEST_NETWORK_SWITCH, NOTIFY_SUPPRESS_TIMEOUT, SERVICE_CLEAR_TRAFFIC_STATISTICS, SERVICE_REBOOT, @@ -275,6 +276,18 @@ class Router: self._get_data( KEY_WLAN_WIFI_FEATURE_SWITCH, self.client.wlan.wifi_feature_switch ) + self._get_data( + KEY_WLAN_WIFI_GUEST_NETWORK_SWITCH, + lambda: next( + filter( + lambda ssid: ssid.get("wifiisguestnetwork") == "1", + self.client.wlan.multi_basic_settings() + .get("Ssids", {}) + .get("Ssid", []), + ), + {}, + ), + ) dispatcher_send(self.hass, UPDATE_SIGNAL, self.config_entry.unique_id) diff --git a/homeassistant/components/huawei_lte/const.py b/homeassistant/components/huawei_lte/const.py index b9cbf546087..754be6bf2f3 100644 --- a/homeassistant/components/huawei_lte/const.py +++ b/homeassistant/components/huawei_lte/const.py @@ -43,6 +43,7 @@ KEY_NET_NET_MODE = "net_net_mode" KEY_SMS_SMS_COUNT = "sms_sms_count" KEY_WLAN_HOST_LIST = "wlan_host_list" KEY_WLAN_WIFI_FEATURE_SWITCH = "wlan_wifi_feature_switch" +KEY_WLAN_WIFI_GUEST_NETWORK_SWITCH = "wlan_wifi_guest_network_switch" BINARY_SENSOR_KEYS = { KEY_MONITORING_CHECK_NOTIFICATIONS, @@ -67,7 +68,7 @@ SENSOR_KEYS = { KEY_SMS_SMS_COUNT, } -SWITCH_KEYS = {KEY_DIALUP_MOBILE_DATASWITCH} +SWITCH_KEYS = {KEY_DIALUP_MOBILE_DATASWITCH, KEY_WLAN_WIFI_GUEST_NETWORK_SWITCH} ALL_KEYS = ( BINARY_SENSOR_KEYS diff --git a/homeassistant/components/huawei_lte/switch.py b/homeassistant/components/huawei_lte/switch.py index cc5e8e446c5..611f7212d9a 100644 --- a/homeassistant/components/huawei_lte/switch.py +++ b/homeassistant/components/huawei_lte/switch.py @@ -16,7 +16,11 @@ from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import HuaweiLteBaseEntityWithDevice -from .const import DOMAIN, KEY_DIALUP_MOBILE_DATASWITCH +from .const import ( + DOMAIN, + KEY_DIALUP_MOBILE_DATASWITCH, + KEY_WLAN_WIFI_GUEST_NETWORK_SWITCH, +) _LOGGER = logging.getLogger(__name__) @@ -33,6 +37,9 @@ async def async_setup_entry( if router.data.get(KEY_DIALUP_MOBILE_DATASWITCH): switches.append(HuaweiLteMobileDataSwitch(router)) + if router.data.get(KEY_WLAN_WIFI_GUEST_NETWORK_SWITCH).get("WifiEnable"): + switches.append(HuaweiLteWifiGuestNetworkSwitch(router)) + async_add_entities(switches, True) @@ -113,3 +120,41 @@ class HuaweiLteMobileDataSwitch(HuaweiLteBaseSwitch): def icon(self) -> str: """Return switch icon.""" return "mdi:signal" if self.is_on else "mdi:signal-off" + + +@dataclass +class HuaweiLteWifiGuestNetworkSwitch(HuaweiLteBaseSwitch): + """Huawei LTE WiFi guest network switch device.""" + + def __post_init__(self) -> None: + """Initialize identifiers.""" + self.key = KEY_WLAN_WIFI_GUEST_NETWORK_SWITCH + self.item = "WifiEnable" + + @property + def _entity_name(self) -> str: + return "WiFi guest network" + + @property + def _device_unique_id(self) -> str: + return f"{self.key}.{self.item}" + + @property + def is_on(self) -> bool: + """Return whether the switch is on.""" + return self._raw_state == "1" + + def _turn(self, state: bool) -> None: + self.router.client.wlan.wifi_guest_network_switch(state) + self._raw_state = "1" if state else "0" + self.schedule_update_ha_state() + + @property + def icon(self) -> str: + """Return switch icon.""" + return "mdi:wifi" if self.is_on else "mdi:wifi-off" + + @property + def extra_state_attributes(self) -> dict[str, str]: + """Return the state attributes.""" + return {"ssid": self.router.data[self.key].get("WifiSsid")} diff --git a/tests/components/huawei_lte/test_switches.py b/tests/components/huawei_lte/test_switches.py new file mode 100644 index 00000000000..c5006add923 --- /dev/null +++ b/tests/components/huawei_lte/test_switches.py @@ -0,0 +1,138 @@ +"""Tests for the Huawei LTE switches.""" +from unittest.mock import MagicMock, patch + +from huawei_lte_api.enums.cradle import ConnectionStatusEnum +from pytest import fixture + +from homeassistant.components.huawei_lte.const import DOMAIN +from homeassistant.components.switch import ( + DOMAIN as SWITCH_DOMAIN, + SERVICE_TURN_OFF, + SERVICE_TURN_ON, +) +from homeassistant.const import ATTR_ENTITY_ID, CONF_URL, STATE_OFF, STATE_ON +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er +from homeassistant.helpers.entity_registry import EntityRegistry + +from tests.common import MockConfigEntry + +SWITCH_WIFI_GUEST_NETWORK = "switch.huawei_lte_wifi_guest_network" + + +@fixture +@patch("homeassistant.components.huawei_lte.Connection", MagicMock()) +@patch( + "homeassistant.components.huawei_lte.Client", + return_value=MagicMock( + device=MagicMock( + information=MagicMock(return_value={"SerialNumber": "test-serial-number"}) + ), + monitoring=MagicMock( + check_notifications=MagicMock(return_value={"SmsStorageFull": 0}), + status=MagicMock( + return_value={"ConnectionStatus": ConnectionStatusEnum.CONNECTED.value} + ), + ), + wlan=MagicMock( + multi_basic_settings=MagicMock( + return_value={ + "Ssids": {"Ssid": [{"wifiisguestnetwork": "1", "WifiEnable": "0"}]} + } + ), + wifi_feature_switch=MagicMock(return_value={"wifi24g_switch_enable": 1}), + ), + ), +) +async def setup_component_with_wifi_guest_network( + client: MagicMock, hass: HomeAssistant +) -> None: + """Initialize huawei_lte components.""" + assert client + huawei_lte = MockConfigEntry(domain=DOMAIN, data={CONF_URL: "http://huawei-lte"}) + huawei_lte.add_to_hass(hass) + assert await hass.config_entries.async_setup(huawei_lte.entry_id) + await hass.async_block_till_done() + + +@fixture +@patch("homeassistant.components.huawei_lte.Connection", MagicMock()) +@patch( + "homeassistant.components.huawei_lte.Client", + return_value=MagicMock( + device=MagicMock( + information=MagicMock(return_value={"SerialNumber": "test-serial-number"}) + ), + monitoring=MagicMock( + check_notifications=MagicMock(return_value={"SmsStorageFull": 0}), + status=MagicMock( + return_value={"ConnectionStatus": ConnectionStatusEnum.CONNECTED.value} + ), + ), + wlan=MagicMock( + multi_basic_settings=MagicMock(return_value={}), + wifi_feature_switch=MagicMock(return_value={"wifi24g_switch_enable": 1}), + ), + ), +) +async def setup_component_without_wifi_guest_network( + client: MagicMock, hass: HomeAssistant +) -> None: + """Initialize huawei_lte components.""" + assert client + huawei_lte = MockConfigEntry(domain=DOMAIN, data={CONF_URL: "http://huawei-lte"}) + huawei_lte.add_to_hass(hass) + assert await hass.config_entries.async_setup(huawei_lte.entry_id) + await hass.async_block_till_done() + + +def test_huawei_lte_wifi_guest_network_config_entry_when_network_is_not_present( + hass: HomeAssistant, + setup_component_without_wifi_guest_network, +) -> None: + """Test switch wifi guest network config entry when network is not present.""" + entity_registry: EntityRegistry = er.async_get(hass) + assert not entity_registry.async_is_registered(SWITCH_WIFI_GUEST_NETWORK) + + +def test_huawei_lte_wifi_guest_network_config_entry_when_network_is_present( + hass: HomeAssistant, + setup_component_with_wifi_guest_network, +) -> None: + """Test switch wifi guest network config entry when network is present.""" + entity_registry: EntityRegistry = er.async_get(hass) + assert entity_registry.async_is_registered(SWITCH_WIFI_GUEST_NETWORK) + + +async def test_turn_on_switch_wifi_guest_network( + hass: HomeAssistant, setup_component_with_wifi_guest_network +) -> None: + """Test switch wifi guest network turn on method.""" + await hass.services.async_call( + SWITCH_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: SWITCH_WIFI_GUEST_NETWORK}, + blocking=True, + ) + await hass.async_block_till_done() + assert hass.states.is_state(SWITCH_WIFI_GUEST_NETWORK, STATE_ON) + hass.data[DOMAIN].routers[ + "test-serial-number" + ].client.wlan.wifi_guest_network_switch.assert_called_once_with(True) + + +async def test_turn_off_switch_wifi_guest_network( + hass: HomeAssistant, setup_component_with_wifi_guest_network +) -> None: + """Test switch wifi guest network turn off method.""" + await hass.services.async_call( + SWITCH_DOMAIN, + SERVICE_TURN_OFF, + {ATTR_ENTITY_ID: SWITCH_WIFI_GUEST_NETWORK}, + blocking=True, + ) + await hass.async_block_till_done() + assert hass.states.is_state(SWITCH_WIFI_GUEST_NETWORK, STATE_OFF) + hass.data[DOMAIN].routers[ + "test-serial-number" + ].client.wlan.wifi_guest_network_switch.assert_called_with(False)