diff --git a/README.md b/README.md index b9d83c6..d354258 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ Many more Xiaomi and Redmi routers supported by MiWiFi | ![](images/RB03.png) | **Redmi Router AX6S** | RB03 | 🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢 | | ![](images/RB01.png) | **Xiaomi Router AX3200** | RB01 | 🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢 | | ![](images/RA81.png) | **Redmi Router AX3000** | RA81 | 🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢 | +| ![](images/CR6606.png) | **Xiaomi China Unicom WiFi 6 Router** | CR6606 | 🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢 | | ![](images/RA71.png) | **Redmi Router AX1800** | RA71 | 🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢 | | ![](images/RA69.png) | **Redmi Router AX6** | RA69 | 🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢 | | ![](images/RA67.png) | **Redmi Router AX5** | RA67 | 🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢 | 🟢🟢🟢🟢🟢 | diff --git a/custom_components/miwifi/config_flow.py b/custom_components/miwifi/config_flow.py index 3f9b91d..3ad5cf7 100644 --- a/custom_components/miwifi/config_flow.py +++ b/custom_components/miwifi/config_flow.py @@ -21,6 +21,7 @@ from .const import ( CONF_ACTIVITY_DAYS, + CONF_IS_TRACK_DEVICES, CONF_IS_FORCE_LOAD, CONF_STAY_ONLINE, CONF_ENCRYPTION_ALGORITHM, @@ -136,6 +137,7 @@ async def async_step_user( EncryptionAlgorithm.SHA256, ] ), + vol.Required(CONF_IS_TRACK_DEVICES, default=True): cv.boolean, vol.Required( CONF_STAY_ONLINE, default=DEFAULT_STAY_ONLINE ): cv.positive_int, @@ -223,6 +225,7 @@ async def async_step_discovery_confirm( EncryptionAlgorithm.SHA256, ] ), + vol.Required(CONF_IS_TRACK_DEVICES, default=True): cv.boolean, vol.Required( CONF_STAY_ONLINE, default=DEFAULT_STAY_ONLINE ): cv.positive_int, @@ -337,6 +340,12 @@ def _get_options_schema(self) -> vol.Schema: EncryptionAlgorithm.SHA256, ] ), + vol.Required( + CONF_IS_TRACK_DEVICES, + default=get_config_value( + self._config_entry, CONF_IS_TRACK_DEVICES, True + ), + ): cv.boolean, vol.Required( CONF_STAY_ONLINE, default=get_config_value( diff --git a/custom_components/miwifi/const.py b/custom_components/miwifi/const.py index 599fc78..5c9bcb1 100644 --- a/custom_components/miwifi/const.py +++ b/custom_components/miwifi/const.py @@ -41,6 +41,7 @@ """Custom conf""" CONF_STAY_ONLINE: Final = "stay_online" +CONF_IS_TRACK_DEVICES: Final = "is_track_devices" CONF_IS_FORCE_LOAD: Final = "is_force_load" CONF_ACTIVITY_DAYS: Final = "activity_days" CONF_ENCRYPTION_ALGORITHM: Final = "encryption_algorithm" diff --git a/custom_components/miwifi/device_tracker.py b/custom_components/miwifi/device_tracker.py index 78856d4..47906ce 100644 --- a/custom_components/miwifi/device_tracker.py +++ b/custom_components/miwifi/device_tracker.py @@ -41,6 +41,7 @@ ATTR_TRACKER_UP_SPEED, ATTR_TRACKER_UPDATER_ENTRY_ID, ATTRIBUTION, + CONF_IS_TRACK_DEVICES, CONF_STAY_ONLINE, DEFAULT_CALL_DELAY, DEFAULT_STAY_ONLINE, @@ -98,7 +99,10 @@ def add_device(new_device: dict) -> None: :param new_device: dict: Device object """ - if new_device[ATTR_TRACKER_UPDATER_ENTRY_ID] != config_entry.entry_id: + if ( + not get_config_value(config_entry, CONF_IS_TRACK_DEVICES, True) + or new_device[ATTR_TRACKER_UPDATER_ENTRY_ID] != config_entry.entry_id + ): return # pragma: no cover entity_id: str = generate_entity_id( diff --git a/custom_components/miwifi/enum.py b/custom_components/miwifi/enum.py index c3da5d9..5e07e14 100644 --- a/custom_components/miwifi/enum.py +++ b/custom_components/miwifi/enum.py @@ -238,3 +238,4 @@ def __str__(self) -> str: RA72 = "ra72" RA70 = "ra70" RB04 = "rb04" + CR6606 = "cr6606" diff --git a/custom_components/miwifi/manifest.json b/custom_components/miwifi/manifest.json index 225ce59..89bcdfb 100644 --- a/custom_components/miwifi/manifest.json +++ b/custom_components/miwifi/manifest.json @@ -1,7 +1,7 @@ { "domain": "miwifi", "name": "MiWiFi", - "version": "2.7.5", + "version": "2.8.0", "documentation": "https://github.com/dmamontov/hass-miwifi/wiki", "issue_tracker": "https://github.com/dmamontov/hass-miwifi/issues", "config_flow": true, diff --git a/custom_components/miwifi/strings.json b/custom_components/miwifi/strings.json index 998e51a..a773230 100644 --- a/custom_components/miwifi/strings.json +++ b/custom_components/miwifi/strings.json @@ -13,6 +13,8 @@ "data": { "ip_address": "[%key:common::config_flow::data::ip_address%]", "password": "[%key:common::config_flow::data::password%]", + "encryption_algorithm": "Password encryption algorithm", + "is_track_devices": "Track devices", "stay_online": "Minimum stay online in seconds", "scan_interval": "Scan interval in seconds [PRO]", "timeout": "Timeout of requests in seconds [PRO]" @@ -34,6 +36,8 @@ "data": { "ip_address": "[%key:common::config_flow::data::ip_address%]", "password": "[%key:common::config_flow::data::password%]", + "encryption_algorithm": "Password encryption algorithm", + "is_track_devices": "Track devices", "stay_online": "Minimum stay online in seconds", "scan_interval": "Scan interval in seconds [PRO]", "activity_days": "Allowed number of days to wait after the last activity [PRO]", diff --git a/custom_components/miwifi/switch.py b/custom_components/miwifi/switch.py index d36ed93..c79cd98 100644 --- a/custom_components/miwifi/switch.py +++ b/custom_components/miwifi/switch.py @@ -326,7 +326,7 @@ def _additional_prepare(self) -> bool: self._attr_entity_registry_enabled_default = False is_available = False - return is_available + return is_available and self.entity_description.key in self._updater.data def _change_icon(self, is_on: bool) -> None: """Change icon diff --git a/custom_components/miwifi/translations/de.json b/custom_components/miwifi/translations/de.json index da8d40f..2e4db7b 100644 --- a/custom_components/miwifi/translations/de.json +++ b/custom_components/miwifi/translations/de.json @@ -15,6 +15,7 @@ "ip_address": "IP Adresse", "password": "Passwort", "encryption_algorithm": "Passwort Verschlüsselungsalgorithmus", + "is_track_devices": "Geräte verfolgen", "stay_online": "Mindestaufenthalt in Sekunden online", "scan_interval": "Scanintervall in Sekunden [PRO]", "timeout": "Timeout von Anfragen in Sekunden [PRO]" @@ -37,6 +38,7 @@ "ip_address": "IP Adresse", "password": "Passwort", "encryption_algorithm": "Passwort Verschlüsselungsalgorithmus", + "is_track_devices": "Geräte verfolgen", "stay_online": "Mindestaufenthalt in Sekunden online", "scan_interval": "Scanintervall in Sekunden [PRO]", "activity_days": "Anzahl an Tagen, die nach der letzten Aktivität gewartet werden soll [PRO]", diff --git a/custom_components/miwifi/translations/en.json b/custom_components/miwifi/translations/en.json index 1c66667..1712fb9 100644 --- a/custom_components/miwifi/translations/en.json +++ b/custom_components/miwifi/translations/en.json @@ -15,6 +15,7 @@ "ip_address": "IP address", "password": "Password", "encryption_algorithm": "Password encryption algorithm", + "is_track_devices": "Track devices", "stay_online": "Minimum stay online in seconds", "scan_interval": "Scan interval in seconds [PRO]", "timeout": "Timeout of requests in seconds [PRO]" @@ -37,6 +38,7 @@ "ip_address": "IP address", "password": "Password", "encryption_algorithm": "Password encryption algorithm", + "is_track_devices": "Track devices", "stay_online": "Minimum stay online in seconds", "scan_interval": "Scan interval in seconds [PRO]", "activity_days": "Allowed number of days to wait after the last activity [PRO]", diff --git a/custom_components/miwifi/translations/fr.json b/custom_components/miwifi/translations/fr.json index 3a8f96d..9ae41c6 100644 --- a/custom_components/miwifi/translations/fr.json +++ b/custom_components/miwifi/translations/fr.json @@ -15,6 +15,7 @@ "ip_address": "Adresse IP", "password": "Mot de passe", "encryption_algorithm": "Algorithme de cryptage du mot de passe", + "is_track_devices": "Suivre les appareils", "stay_online": "Reste en ligne minimum en secondes", "scan_interval": "Intervalle d'analyse en secondes [PRO]", "timeout": "Délai d'expiration des requêtes en secondes [PRO]" @@ -37,6 +38,7 @@ "ip_address": "Adresse IP", "password": "Mot de passe", "encryption_algorithm": "Algorithme de cryptage du mot de passe", + "is_track_devices": "Suivre les appareils", "stay_online": "Reste en ligne minimum en secondes", "scan_interval": "Intervalle d'analyse en secondes [PRO]", "activity_days": "Nombre de jours d'attente autorisés après la dernière activité [PRO]", diff --git a/custom_components/miwifi/translations/pt-BR.json b/custom_components/miwifi/translations/pt-BR.json index ea87db2..f768286 100644 --- a/custom_components/miwifi/translations/pt-BR.json +++ b/custom_components/miwifi/translations/pt-BR.json @@ -15,6 +15,7 @@ "ip_address": "Endereço IP", "password": "Senha", "encryption_algorithm": "Algoritmo de criptografia de senha", + "is_track_devices": "Dispositivos de rastreamento", "stay_online": "Estadia mínima online em segundos", "scan_interval": "Intervalo de varredura em segundos [PRO]", "timeout": "Tempo limite de solicitações em segundos [PRO]" @@ -40,6 +41,7 @@ "ip_address": "Endereço IP", "password": "Senha", "encryption_algorithm": "Algoritmo de criptografia de senha", + "is_track_devices": "Dispositivos de rastreamento", "stay_online": "Estadia mínima online em segundos", "scan_interval": "Intervalo de varredura em segundos [PRO]", "activity_days": "Número permitido de dias de espera após a última atividade [PRO]", diff --git a/custom_components/miwifi/translations/ru.json b/custom_components/miwifi/translations/ru.json index d3d5d76..870f046 100644 --- a/custom_components/miwifi/translations/ru.json +++ b/custom_components/miwifi/translations/ru.json @@ -15,6 +15,7 @@ "ip_address": "IP адрес", "password": "Пароль", "encryption_algorithm": "Алгоритм шифрования пароля", + "is_track_devices": "Отслеживать устройства", "stay_online": "Минимальное пребывание онлайн в секундах", "scan_interval": "Интервал сканирования в секундах [PRO]", "timeout": "Тайм-аут запросов в секундах [PRO]" @@ -38,6 +39,7 @@ "password": "Пароль", "encryption_algorithm": "Алгоритм шифрования пароля", "stay_online": "Минимальное пребывание онлайн в секундах", + "is_track_devices": "Отслеживать устройства", "scan_interval": "Интервал сканирования в секундах [PRO]", "activity_days": "Допустимое количество дней ожидания после последней активности [PRO]", "timeout": "Тайм-аут запросов в секундах [PRO]", diff --git a/custom_components/miwifi/translations/tr.json b/custom_components/miwifi/translations/tr.json index df7d45d..6fc1917 100644 --- a/custom_components/miwifi/translations/tr.json +++ b/custom_components/miwifi/translations/tr.json @@ -15,6 +15,7 @@ "ip_address": "IP adresi", "password": "Parola", "encryption_algorithm": "Şifreleme algoritması", + "is_track_devices": "Cihazları takip edin", "stay_online": "En az çevrimiçi kalma süresi (saniye)", "scan_interval": "Tarama aralığı (saniye) [PRO]", "timeout": "İstek zaman aşımı (saniye) [PRO]" @@ -37,6 +38,7 @@ "ip_address": "IP adresi", "password": "Parola", "encryption_algorithm": "Şifreleme algoritması", + "is_track_devices": "Cihazları takip edin", "stay_online": "En az çevrimiçi kalma süresi (saniye)", "scan_interval": "Tarama aralığı (saniye) [PRO]", "activity_days": "Son aktiviteden sonra beklenmesi gereken süre (gün) [PRO]", diff --git a/custom_components/miwifi/updater.py b/custom_components/miwifi/updater.py index a7abb07..8c33006 100644 --- a/custom_components/miwifi/updater.py +++ b/custom_components/miwifi/updater.py @@ -623,7 +623,10 @@ async def _async_prepare_wifi(self, data: dict) -> None: :param data: dict """ - response: dict = await self.luci.wifi_detail_all() + try: + response: dict = await self.luci.wifi_detail_all() + except LuciError: + return if "bsd" in response: data[ATTR_BINARY_SENSOR_DUAL_BAND] = int(response["bsd"]) == 1 diff --git a/images/CR6606.png b/images/CR6606.png new file mode 100644 index 0000000..d6ecf11 Binary files /dev/null and b/images/CR6606.png differ diff --git a/tests/test_switch.py b/tests/test_switch.py index 6769b25..a5c98c7 100644 --- a/tests/test_switch.py +++ b/tests/test_switch.py @@ -39,7 +39,7 @@ DOMAIN, UPDATER, ) -from custom_components.miwifi.exceptions import LuciRequestError +from custom_components.miwifi.exceptions import LuciConnectionError, LuciRequestError from custom_components.miwifi.helper import generate_entity_id from custom_components.miwifi.updater import LuciUpdater from tests.setup import MultipleSideEffect, async_mock_luci_client, async_setup @@ -218,6 +218,56 @@ async def test_init_without_guest(hass: HomeAssistant) -> None: assert registry.async_get(unique_id) is None +async def test_init_with_error(hass: HomeAssistant) -> None: + """Test init. + + :param hass: HomeAssistant + """ + + with patch( + "custom_components.miwifi.updater.LuciClient" + ) as mock_luci_client, patch( + "custom_components.miwifi.updater.async_dispatcher_send" + ), patch( + "custom_components.miwifi.async_start_discovery", return_value=None + ), patch( + "custom_components.miwifi.device_tracker.socket.socket" + ) as mock_socket, patch( + "custom_components.miwifi.updater.asyncio.sleep", return_value=None + ): + mock_socket.return_value.recv.return_value = AsyncMock(return_value=None) + + await async_mock_luci_client(mock_luci_client) + + mock_luci_client.return_value.wifi_detail_all = AsyncMock( + side_effect=LuciConnectionError + ) + + setup_data: list = await async_setup(hass) + + config_entry: MockConfigEntry = setup_data[1] + + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + updater: LuciUpdater = hass.data[DOMAIN][config_entry.entry_id][UPDATER] + registry = er.async_get(hass) + + assert updater.last_update_success + + unique_id: str = _generate_id(ATTR_SWITCH_WIFI_2_4_NAME, updater) + states: State | None = hass.states.get(unique_id) + assert states is not None + assert states.state == STATE_UNAVAILABLE + assert registry.async_get(unique_id) is not None + + unique_id = _generate_id(ATTR_SWITCH_WIFI_5_0_NAME, updater) + states = hass.states.get(unique_id) + assert states is not None + assert states.state == STATE_UNAVAILABLE + assert registry.async_get(unique_id) is not None + + async def test_init_bsd( hass: HomeAssistant, ) -> None: