From 0559809eee7991c1abb6a743d0bd3103eb699fd0 Mon Sep 17 00:00:00 2001 From: Stackie Jia Date: Fri, 27 Dec 2024 18:15:43 +0800 Subject: [PATCH] fix: fix load_default_certs warning on startup --- .../deye_dehumidifier/__init__.py | 9 ++-- .../deye_dehumidifier/data_coordinator.py | 46 +++++++++---------- custom_components/deye_dehumidifier/fan.py | 4 +- .../deye_dehumidifier/humidifier.py | 32 ++++++------- .../deye_dehumidifier/manifest.json | 2 +- custom_components/deye_dehumidifier/switch.py | 2 +- setup.cfg | 2 +- 7 files changed, 46 insertions(+), 51 deletions(-) diff --git a/custom_components/deye_dehumidifier/__init__.py b/custom_components/deye_dehumidifier/__init__.py index 8fda444..db4d612 100644 --- a/custom_components/deye_dehumidifier/__init__.py +++ b/custom_components/deye_dehumidifier/__init__.py @@ -3,6 +3,7 @@ from __future__ import annotations import logging +from typing import Any from homeassistant.config_entries import ConfigEntry from homeassistant.const import Platform @@ -11,6 +12,7 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.entity import DeviceInfo, Entity from homeassistant.helpers.update_coordinator import CoordinatorEntity +from homeassistant.util import ssl from libdeye.cloud_api import ( DeyeCloudApi, DeyeCloudApiCannotConnectError, @@ -67,6 +69,7 @@ def on_auth_token_refreshed(auth_token: str) -> None: mqtt_info["loginname"], mqtt_info["password"], mqtt_info["endpoint"], + ssl.get_default_context(), ) mqtt_client.connect() device_list = list( @@ -110,7 +113,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: return unload_ok -class DeyeEntity(CoordinatorEntity, Entity): +class DeyeEntity(CoordinatorEntity[DeyeDataUpdateCoordinator], Entity): """Initiate Deye Base Class.""" def __init__( @@ -153,7 +156,7 @@ async def async_added_to_hass(self) -> None: self.async_on_remove(remove_handle) await super().async_added_to_hass() - async def publish_command_async(self, attribute, value): + async def publish_command_async(self, attribute: str, value: Any) -> None: """Push command to a queue and deal with them together.""" self.async_write_ha_state() self.hass.bus.fire( @@ -163,7 +166,7 @@ async def publish_command_async(self, attribute, value): self.coordinator.mute_subscription_for_a_while() @property - def available(self): + def available(self) -> bool: return self._device_available @callback diff --git a/custom_components/deye_dehumidifier/data_coordinator.py b/custom_components/deye_dehumidifier/data_coordinator.py index ae394be..2aa1125 100644 --- a/custom_components/deye_dehumidifier/data_coordinator.py +++ b/custom_components/deye_dehumidifier/data_coordinator.py @@ -1,18 +1,27 @@ -import asyncio import logging from datetime import datetime, timedelta +from typing import cast -from homeassistant.core import CALLBACK_TYPE, callback +from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback from homeassistant.helpers.event import async_call_later from homeassistant.helpers.update_coordinator import DataUpdateCoordinator +from libdeye.cloud_api import DeyeCloudApi from libdeye.const import QUERY_DEVICE_STATE_COMMAND from libdeye.device_state_command import DeyeDeviceState +from libdeye.mqtt_client import DeyeMqttClient +from libdeye.types import DeyeApiResponseDeviceInfo _LOGGER = logging.getLogger(__name__) -class DeyeDataUpdateCoordinator(DataUpdateCoordinator): - def __init__(self, hass, device, mqtt_client, cloud_api): +class DeyeDataUpdateCoordinator(DataUpdateCoordinator[DeyeDeviceState]): + def __init__( + self, + hass: HomeAssistant, + device: DeyeApiResponseDeviceInfo, + mqtt_client: DeyeMqttClient, + cloud_api: DeyeCloudApi, + ) -> None: super().__init__( hass, _LOGGER, @@ -31,20 +40,12 @@ def __init__(self, hass, device, mqtt_client, cloud_api): self.device_available = self._device["online"] """When entity is added to Home Assistant.""" if self._device["platform"] == 1: - # self._mqtt_client.subscribe_availability_change( - # self._device["product_id"], - # self._device["device_id"], - # self.update_device_availability, - # ) self._mqtt_client.subscribe_state_change( self._device["product_id"], self._device["device_id"], self.update_device_state, ) - self.receive_queue = asyncio.Queue() - self.device_available_queue = asyncio.Queue() - def mute_subscription_for_a_while(self) -> None: """Mute subscription for a while to avoid state bouncing.""" if self.subscription_muted: @@ -58,21 +59,17 @@ def unmute(now: datetime) -> None: def update_device_state(self, state: DeyeDeviceState) -> None: """Will be called when received new DeyeDeviceState.""" - self.receive_queue.put_nowait(state) - # self.async_set_updated_data(state) - - # async def async_request_refresh(self) -> None: - # self.mute_subscription_for_a_while() - # await super().async_request_refresh() + if self.subscription_muted: + return + self.async_set_updated_data(state) async def poll_device_state(self) -> DeyeDeviceState: """ Some Deye devices have a very long heartbeat period. So polling is still necessary to get the latest state as quickly as possible. """ - # _LOGGER.error("poll_device_state called: " + str(self._device["product_id"])) if self.subscription_muted: - return self.data + return cast(DeyeDeviceState, self.data) device_list = list( filter( @@ -91,13 +88,12 @@ async def poll_device_state(self) -> DeyeDeviceState: self._device["device_id"], QUERY_DEVICE_STATE_COMMAND, ) - response = await asyncio.wait_for(self.receive_queue.get(), timeout=10) - return response + return cast(DeyeDeviceState, self.data) elif self._device["platform"] == 2: - response = DeyeDeviceState( + return DeyeDeviceState( await self._cloud_api.get_fog_platform_device_properties( self._device["device_id"] ) ) - # _LOGGER.error(response.to_command().json()) - return response + else: + return cast(DeyeDeviceState, self.data) diff --git a/custom_components/deye_dehumidifier/fan.py b/custom_components/deye_dehumidifier/fan.py index c0d30e0..f859859 100644 --- a/custom_components/deye_dehumidifier/fan.py +++ b/custom_components/deye_dehumidifier/fan.py @@ -106,7 +106,7 @@ async def async_set_percentage(self, percentage: int) -> None: """Set the speed of the fan, as a percentage.""" if percentage == 0: await self.async_turn_off() - fan_speed = int( + fan_speed = DeyeFanSpeed( percentage_to_ordered_list_item(self._named_fan_speeds, percentage) ) self.device_state.fan_speed = fan_speed @@ -122,7 +122,7 @@ async def async_turn_on( self.device_state.power_switch = True await self.publish_command_async("power_switch", True) if percentage is not None: - fan_speed = int( + fan_speed = DeyeFanSpeed( percentage_to_ordered_list_item(self._named_fan_speeds, percentage) ) self.device_state.fan_speed = fan_speed diff --git a/custom_components/deye_dehumidifier/humidifier.py b/custom_components/deye_dehumidifier/humidifier.py index 02fa2b0..5713ae9 100644 --- a/custom_components/deye_dehumidifier/humidifier.py +++ b/custom_components/deye_dehumidifier/humidifier.py @@ -10,9 +10,13 @@ HumidifierEntity, HumidifierEntityFeature, ) -from homeassistant.components.humidifier.const import MODE_AUTO, MODE_SLEEP +from homeassistant.components.humidifier.const import ( + MODE_AUTO, + MODE_SLEEP, + HumidifierAction, +) from homeassistant.config_entries import ConfigEntry -from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback +from homeassistant.core import CALLBACK_TYPE, Event, HomeAssistant, callback from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.event import async_track_time_interval from libdeye.cloud_api import DeyeCloudApi @@ -82,9 +86,9 @@ def __init__( self._attr_min_humidity = feature_config["min_target_humidity"] self._attr_max_humidity = feature_config["max_target_humidity"] self._attr_entity_picture = device["product_icon"] - self.data_change_list: dict = dict() + self.data_change_list: dict[str, Any] = dict() - async def call_method(self, event): + async def call_method(self, event: Event) -> None: if event.data.get("device_id") == self._device["device_id"]: prop = event.data.get("prop") value = event.data.get("value") @@ -119,7 +123,7 @@ async def put_device_state(self, now: datetime | None = None) -> None: self.async_write_ha_state() - async def publish_command(self, prop, value) -> None: + async def publish_command(self, prop: str, value: Any) -> None: self.data_change_list[prop] = value @property @@ -147,21 +151,13 @@ def mode(self) -> str: return deye_mode_to_hass_mode(self.device_state.mode) @property - def action(self) -> str: - """ - Return the current action. - - off/drying/idle are from `homeassistant.components.humidifier.const.HumidifierAction` - - For backward compatibility, we cannot directly import them from homeassistant (which requires - homeassistant >= 2023.7) - """ + def action(self) -> HumidifierAction: if not self.device_state.power_switch: - return "off" + return HumidifierAction.OFF elif self.device_state.fan_running: - return "drying" + return HumidifierAction.DRYING else: - return "idle" + return HumidifierAction.IDLE async def async_set_mode(self, mode: str) -> None: """Set new working mode.""" @@ -184,7 +180,7 @@ async def async_turn_off(self, **kwargs: Any) -> None: await self.publish_command_async("power_switch", False) -def set_class_variable(obj, var_name, new_value): +def set_class_variable(obj, var_name, new_value) -> None: if hasattr(obj, var_name): setattr(obj, var_name, new_value) else: diff --git a/custom_components/deye_dehumidifier/manifest.json b/custom_components/deye_dehumidifier/manifest.json index f0feb90..7101bcb 100644 --- a/custom_components/deye_dehumidifier/manifest.json +++ b/custom_components/deye_dehumidifier/manifest.json @@ -6,6 +6,6 @@ "documentation": "https://github.com/stackia/ha-deye-dehumidifier", "iot_class": "cloud_push", "issue_tracker": "https://github.com/stackia/ha-deye-dehumidifier/issues", - "requirements": ["libdeye==1.3.1"], + "requirements": ["libdeye==1.3.2"], "version": "1.6.4" } diff --git a/custom_components/deye_dehumidifier/switch.py b/custom_components/deye_dehumidifier/switch.py index cfe4a30..fc2c6c3 100644 --- a/custom_components/deye_dehumidifier/switch.py +++ b/custom_components/deye_dehumidifier/switch.py @@ -207,7 +207,7 @@ def __init__( self.entity_id = f"switch.{self.entity_id_base}_continuous" @property - def available(self): + def available(self) -> bool: return ( super().available and self.device_state.mode == DeyeDeviceMode.MANUAL_MODE ) diff --git a/setup.cfg b/setup.cfg index 777810d..7d17190 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,7 +26,7 @@ package_dir = python_requires = >=3.10 install_requires = importlib-metadata; python_version<"3.8" - libdeye==1.3.1 + libdeye==1.3.2 [options.packages.find]