From 897942a1c2f76f5d3ddcf459e472a80cd24a1201 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 8 May 2021 09:59:30 +0200 Subject: [PATCH 01/10] Add zhimi.airpurifier.za1 support (Closes: #181) --- README.md | 1 + custom_components/xiaomi_miio_airpurifier/fan.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 31a6adb..94383d0 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ This custom component is more or less the beta version of the [official componen | Air Purifier Super 2 | zhimi.airpurifier.sa2 | | | | Air Purifier 3 (2019) | zhimi.airpurifier.ma4 | | | | Air Purifier 3H (2019) | zhimi.airpurifier.mb3 | FJY4031GL(?), XM200017 | 45m2, 380m3/h CADR, 64dB, 38W (max) | +| Air Purifier ZA1 | zhimi.airpurifier.za1 | | | | Air Dog X3 | airdog.airpurifier.x3 | | | | Air Dog X5 | airdog.airpurifier.x5 | | | | Air Dog X7SM | airdog.airpurifier.x7sm | | | diff --git a/custom_components/xiaomi_miio_airpurifier/fan.py b/custom_components/xiaomi_miio_airpurifier/fan.py index 44120ee..1c4b432 100644 --- a/custom_components/xiaomi_miio_airpurifier/fan.py +++ b/custom_components/xiaomi_miio_airpurifier/fan.py @@ -120,6 +120,7 @@ MODEL_AIRPURIFIER_2H = "zhimi.airpurifier.mc2" MODEL_AIRPURIFIER_3 = "zhimi.airpurifier.ma4" MODEL_AIRPURIFIER_3H = "zhimi.airpurifier.mb3" +MODEL_AIRPURIFIER_ZA1 = "zhimi.airpurifier.za1" MODEL_AIRPURIFIER_AIRDOG_X3 = "airdog.airpurifier.x3" MODEL_AIRPURIFIER_AIRDOG_X5 = "airdog.airpurifier.x5" MODEL_AIRPURIFIER_AIRDOG_X7SM = "airdog.airpurifier.x7sm" @@ -175,6 +176,7 @@ MODEL_AIRPURIFIER_2H, MODEL_AIRPURIFIER_3, MODEL_AIRPURIFIER_3H, + MODEL_AIRPURIFIER_ZA1, MODEL_AIRPURIFIER_AIRDOG_X3, MODEL_AIRPURIFIER_AIRDOG_X5, MODEL_AIRPURIFIER_AIRDOG_X7SM, @@ -305,7 +307,7 @@ # Fan Leshow SS4 ATTR_ERROR_DETECTED = "error_detected" -PURIFIER_MIOT = [MODEL_AIRPURIFIER_3, MODEL_AIRPURIFIER_3H] +PURIFIER_MIOT = [MODEL_AIRPURIFIER_3, MODEL_AIRPURIFIER_3H, MODEL_AIRPURIFIER_ZA1] HUMIDIFIER_MIOT = [MODEL_AIRHUMIDIFIER_CA4] # AirDogX7SM From acafb93f2268e0e2eb120da76477d5a14527dd8b Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 8 May 2021 11:19:26 +0200 Subject: [PATCH 02/10] Add set_percentage support to the fan.dmaker.c1 --- .../xiaomi_miio_airpurifier/fan.py | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/custom_components/xiaomi_miio_airpurifier/fan.py b/custom_components/xiaomi_miio_airpurifier/fan.py index 1c4b432..71284ad 100644 --- a/custom_components/xiaomi_miio_airpurifier/fan.py +++ b/custom_components/xiaomi_miio_airpurifier/fan.py @@ -2,6 +2,7 @@ import asyncio from enum import Enum from functools import partial +from typing import Optional import logging from miio import ( # pylint: disable=import-error @@ -93,6 +94,7 @@ ) from homeassistant.exceptions import PlatformNotReady import homeassistant.helpers.config_validation as cv +from homeassistant.util.percentage import ordered_list_item_to_percentage, percentage_to_ordered_list_item _LOGGER = logging.getLogger(__name__) @@ -669,6 +671,9 @@ FAN_SPEED_LEVEL3: 3, } +FAN_SPEEDS_1C = list(FAN_PRESET_MODES_1C) +FAN_SPEEDS_1C.remove(SPEED_OFF) + OPERATION_MODES_AIRPURIFIER = ["Auto", "Silent", "Favorite", "Idle"] OPERATION_MODES_AIRPURIFIER_PRO = ["Auto", "Silent", "Favorite"] OPERATION_MODES_AIRPURIFIER_PRO_V7 = OPERATION_MODES_AIRPURIFIER_PRO @@ -2741,7 +2746,7 @@ def __init__(self, name, device, model, unique_id, retries): @property def supported_features(self) -> int: """Supported features.""" - return SUPPORT_PRESET_MODE | SUPPORT_OSCILLATE + return SUPPORT_SET_SPEED | SUPPORT_PRESET_MODE | SUPPORT_OSCILLATE async def async_update(self): """Fetch state from the device.""" @@ -2786,6 +2791,16 @@ async def async_update(self): self._retry, ) + @property + def percentage(self) -> Optional[int]: + """Return the current speed percentage.""" + return ordered_list_item_to_percentage(FAN_SPEEDS_1C, self._preset_mode) + + @property + def speed_count(self) -> int: + """Return the number of speeds the fan supports.""" + return len(FAN_SPEEDS_1C) + @property def preset_modes(self): """Get the list of available preset modes.""" @@ -2809,6 +2824,22 @@ async def async_set_preset_mode(self, preset_mode: str) -> None: FAN_PRESET_MODES_1C[preset_mode], ) + async def async_set_percentage(self, percentage: int) -> None: + """Set the speed percentage of the fan.""" + _LOGGER.debug("Setting the fan speed percentage to: %s", percentage) + + if percentage == 0: + await self.async_turn_off() + return + + await self._try_command( + "Setting preset mode of the miio device failed.", + self._device.set_speed, + FAN_PRESET_MODES_1C[ + percentage_to_ordered_list_item(FAN_SPEEDS_1C, percentage) + ], + ) + @property def oscillating(self): """Return the oscillation state.""" From 775caa1b1367f1afd26020cd44a2a4bb66d69de6 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 8 May 2021 11:19:26 +0200 Subject: [PATCH 03/10] Add set_percentage support to the fan.dmaker.c1 --- .../xiaomi_miio_airpurifier/fan.py | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/custom_components/xiaomi_miio_airpurifier/fan.py b/custom_components/xiaomi_miio_airpurifier/fan.py index 1c4b432..7942e0c 100644 --- a/custom_components/xiaomi_miio_airpurifier/fan.py +++ b/custom_components/xiaomi_miio_airpurifier/fan.py @@ -3,6 +3,7 @@ from enum import Enum from functools import partial import logging +from typing import Optional from miio import ( # pylint: disable=import-error AirDogX3, @@ -93,6 +94,10 @@ ) from homeassistant.exceptions import PlatformNotReady import homeassistant.helpers.config_validation as cv +from homeassistant.util.percentage import ( + ordered_list_item_to_percentage, + percentage_to_ordered_list_item, +) _LOGGER = logging.getLogger(__name__) @@ -669,6 +674,9 @@ FAN_SPEED_LEVEL3: 3, } +FAN_SPEEDS_1C = list(FAN_PRESET_MODES_1C) +FAN_SPEEDS_1C.remove(SPEED_OFF) + OPERATION_MODES_AIRPURIFIER = ["Auto", "Silent", "Favorite", "Idle"] OPERATION_MODES_AIRPURIFIER_PRO = ["Auto", "Silent", "Favorite"] OPERATION_MODES_AIRPURIFIER_PRO_V7 = OPERATION_MODES_AIRPURIFIER_PRO @@ -2373,11 +2381,11 @@ async def async_set_percentage(self, percentage: int) -> None: async def async_set_direction(self, direction: str) -> None: """Set the direction of the fan.""" - if direction == 'forward': - direction = 'right' + if direction == "forward": + direction = "right" - if direction == 'reverse': - direction = 'left' + if direction == "reverse": + direction = "left" if self._oscillate: await self._try_command( @@ -2741,7 +2749,7 @@ def __init__(self, name, device, model, unique_id, retries): @property def supported_features(self) -> int: """Supported features.""" - return SUPPORT_PRESET_MODE | SUPPORT_OSCILLATE + return SUPPORT_SET_SPEED | SUPPORT_PRESET_MODE | SUPPORT_OSCILLATE async def async_update(self): """Fetch state from the device.""" @@ -2786,6 +2794,16 @@ async def async_update(self): self._retry, ) + @property + def percentage(self) -> Optional[int]: + """Return the current speed percentage.""" + return ordered_list_item_to_percentage(FAN_SPEEDS_1C, self._preset_mode) + + @property + def speed_count(self) -> int: + """Return the number of speeds the fan supports.""" + return len(FAN_SPEEDS_1C) + @property def preset_modes(self): """Get the list of available preset modes.""" @@ -2809,6 +2827,22 @@ async def async_set_preset_mode(self, preset_mode: str) -> None: FAN_PRESET_MODES_1C[preset_mode], ) + async def async_set_percentage(self, percentage: int) -> None: + """Set the speed percentage of the fan.""" + _LOGGER.debug("Setting the fan speed percentage to: %s", percentage) + + if percentage == 0: + await self.async_turn_off() + return + + await self._try_command( + "Setting preset mode of the miio device failed.", + self._device.set_speed, + FAN_PRESET_MODES_1C[ + percentage_to_ordered_list_item(FAN_SPEEDS_1C, percentage) + ], + ) + @property def oscillating(self): """Return the oscillation state.""" From d34254ef24b06e6dfb778be32a32defff99d7ff3 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 8 May 2021 12:17:39 +0200 Subject: [PATCH 04/10] Turn the fan.dmaker.1c on in front of every set_percentage and set_preset_mode call --- custom_components/xiaomi_miio_airpurifier/fan.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/custom_components/xiaomi_miio_airpurifier/fan.py b/custom_components/xiaomi_miio_airpurifier/fan.py index 71284ad..31ae6ce 100644 --- a/custom_components/xiaomi_miio_airpurifier/fan.py +++ b/custom_components/xiaomi_miio_airpurifier/fan.py @@ -2818,6 +2818,10 @@ async def async_set_preset_mode(self, preset_mode: str) -> None: """Set the preset mode of the fan.""" _LOGGER.debug("Setting the preset mode to: %s", preset_mode) + if not self._state: + await self._try_command( + "Turning the miio device on failed.", self._device.on + ) await self._try_command( "Setting preset mode of the miio device failed.", self._device.set_speed, @@ -2832,6 +2836,10 @@ async def async_set_percentage(self, percentage: int) -> None: await self.async_turn_off() return + if not self._state: + await self._try_command( + "Turning the miio device on failed.", self._device.on + ) await self._try_command( "Setting preset mode of the miio device failed.", self._device.set_speed, From 3781d85ab591eceb7387e4e240de54f36523a750 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Tue, 11 May 2021 21:36:22 +0200 Subject: [PATCH 05/10] Fix yamllint issue --- custom_components/xiaomi_miio_airpurifier/services.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/custom_components/xiaomi_miio_airpurifier/services.yaml b/custom_components/xiaomi_miio_airpurifier/services.yaml index bd93de8..a7af806 100644 --- a/custom_components/xiaomi_miio_airpurifier/services.yaml +++ b/custom_components/xiaomi_miio_airpurifier/services.yaml @@ -155,5 +155,3 @@ fan_set_filters_cleaned: entity_id: description: Name of the xiaomi miio entity. example: "xiaomi_miio_airpurifier.xiaomi_miio_device" - - From 41303bbd2716476aafde8a476905fc7c1e8c0c3e Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sun, 20 Jun 2021 20:09:18 +0200 Subject: [PATCH 06/10] Simplify CI pipeline --- .github/workflows/ci.yaml | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7e7784f..062529f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,4 +1,4 @@ -name: "Validation And Formatting" +name: "Hassfest and hacs validation" on: push: pull_request: @@ -10,23 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Download repo - with: - fetch-depth: 0 - - uses: actions/setup-python@v2 - name: Setup Python - with: - python-version: '3.8.x' - - uses: actions/cache@v2 - name: Cache - with: - path: | - ~/.cache/pip - key: custom-component-ci + - uses: home-assistant/actions/hassfest@master - uses: hacs/action@main with: - CATEGORY: integration - - uses: KTibow/ha-blueprint@stable - name: CI - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + category: integration From e1cddf5a2f08a6cdd7daf64584faef9375f16b43 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Fri, 25 Jun 2021 07:12:44 +0200 Subject: [PATCH 07/10] Improve install instructions --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 94383d0..3922643 100644 --- a/README.md +++ b/README.md @@ -550,7 +550,10 @@ This paragraph was moved to [docs/dmaker-airfresh-t2017.md](docs/dmaker-airfresh ## Install -You can install this custom component by adding this repository ([https://github.com/syssi/xiaomi_airpurifier](https://github.com/syssi/xiaomi_airpurifier/)) to [HACS](https://hacs.xyz/) in the settings menu of HACS first. You will find the custom component in the integration menu afterwards, look for 'Xiaomi Mi Air Purifier and Xiaomi Mi Air Humidifier Integration'. Alternatively, you can install it manually by copying the custom_component folder to your Home Assistant configuration folder. +You can install this custom component via [HACS](https://hacs.xyz/). Search for for 'Xiaomi Mi Air Purifier and Xiaomi Mi Air Humidifier Integration' at the integration page of HACS. Alternatively, you can install it manually by copying the custom_compon +ent folder to your Home Assistant configuration folder. + +As next step you have to setup the custom component at your `configuration.yaml`. This custom component doesn't provide a `config-flow` right now. A restart of Home Assistant is required afterwards. ## Setup From f61c876a64922a6f93ed64aef216833113ce5a17 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sun, 29 Aug 2021 12:41:26 +0200 Subject: [PATCH 08/10] Add badges --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 3922643..7b8dbf3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # Xiaomi Mi Air Purifier & Xiaomi Mi Air Humidifier +![GitHub actions](https://github.com/syssi/xiaomi_airpurifier/actions/workflows/ci.yaml/badge.svg) +![GitHub stars](https://img.shields.io/github/stars/syssi/xiaomi_airpurifier) +![GitHub forks](https://img.shields.io/github/forks/syssi/xiaomi_airpurifier) +![GitHub watchers](https://img.shields.io/github/watchers/syssi/xiaomi_airpurifier) +[!["Buy Me A Coffee"](https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg)](https://www.buymeacoffee.com/syssi) + This is a custom component for home assistant to integrate the Xiaomi Mi Air Purifier 2, Air Purifier 2S, Air Purifier Pro, Air Humidifier, Air Fresh and Pedestal Fan. Please follow the instructions on [Retrieving the Access Token](https://home-assistant.io/components/xiaomi/#retrieving-the-access-token) to get the API token to use in the configuration.yaml file. From af86be72271dcc4b448f7590664a92896290d02d Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sun, 29 Aug 2021 13:42:52 +0200 Subject: [PATCH 09/10] Bump python-miio and component version --- custom_components/xiaomi_miio_airpurifier/manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/xiaomi_miio_airpurifier/manifest.json b/custom_components/xiaomi_miio_airpurifier/manifest.json index 0b27439..09a6fd8 100644 --- a/custom_components/xiaomi_miio_airpurifier/manifest.json +++ b/custom_components/xiaomi_miio_airpurifier/manifest.json @@ -1,14 +1,14 @@ { "domain": "xiaomi_miio_airpurifier", "name": "Xiaomi Mi Air Purifier, Air Humidifier, Air Fresh and Pedestal Fan Integration", - "version": "0.6.9", + "version": "0.6.10", "iot_class": "local_polling", "config_flow": false, "documentation": "https://github.com/syssi/xiaomi_airpurifier", "issue_tracker": "https://github.com/syssi/xiaomi_airpurifier/issues", "requirements": [ "construct==2.10.56", - "python-miio>=0.5.6" + "python-miio>=0.5.7" ], "dependencies": [], "codeowners": [ From ad273d454e1ac49803b77d6d7021851d2e2ac9c0 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sun, 29 Aug 2021 13:43:24 +0200 Subject: [PATCH 10/10] Bump component version --- custom_components/xiaomi_miio_airpurifier/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/xiaomi_miio_airpurifier/manifest.json b/custom_components/xiaomi_miio_airpurifier/manifest.json index 09a6fd8..cf7377a 100644 --- a/custom_components/xiaomi_miio_airpurifier/manifest.json +++ b/custom_components/xiaomi_miio_airpurifier/manifest.json @@ -1,7 +1,7 @@ { "domain": "xiaomi_miio_airpurifier", "name": "Xiaomi Mi Air Purifier, Air Humidifier, Air Fresh and Pedestal Fan Integration", - "version": "0.6.10", + "version": "0.6.12", "iot_class": "local_polling", "config_flow": false, "documentation": "https://github.com/syssi/xiaomi_airpurifier",