Procházet zdrojové kódy

Entities: call super().__init__ from __init__

Most entity base classes only do static initialisation, but Camera
defines __init__ and depends on its contents internally.

In case others change in future, all of them are changed.

- Reformatted to eliminate most overly long lines.
- use old style format strings for logging. As well as helping with
  the long lines, it also apparently makes the non-logging case more
  efficient.
- fix some issues where logging was done without defining the _LOGGER.

Issue #759
Jason Rumney před 2 roky
rodič
revize
10a26639b5

+ 3 - 1
custom_components/tuya_local/binary_sensor.py

@@ -36,6 +36,7 @@ class TuyaLocalBinarySensor(TuyaLocalEntity, BinarySensorEntity):
             device (TuyaLocalDevice): the device API instance.
             config (TuyaEntityConfig): the configuration for this entity
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._sensor_dps = dps_map.pop("sensor")
         if self._sensor_dps is None:
@@ -51,7 +52,8 @@ class TuyaLocalBinarySensor(TuyaLocalEntity, BinarySensorEntity):
         except ValueError:
             if dclass:
                 _LOGGER.warning(
-                    f"Unrecognised binary_sensor device class of {dclass} ignored"
+                    "Unrecognised binary_sensor device class of %s ignored",
+                    dclass,
                 )
             return None
 

+ 9 - 1
custom_components/tuya_local/button.py

@@ -1,6 +1,8 @@
 """
 Setup for different kinds of Tuya button devices
 """
+import logging
+
 from homeassistant.components.button import ButtonEntity, ButtonDeviceClass
 
 from .device import TuyaLocalDevice
@@ -8,6 +10,8 @@ from .helpers.config import async_tuya_setup_platform
 from .helpers.device_config import TuyaEntityConfig
 from .helpers.mixin import TuyaLocalEntity
 
+_LOGGER = logging.getLogger(__name__)
+
 
 async def async_setup_entry(hass, config_entry, async_add_entities):
     config = {**config_entry.data, **config_entry.options}
@@ -30,6 +34,7 @@ class TuyaLocalButton(TuyaLocalEntity, ButtonEntity):
             device (TuyaLocalDevice): The device API instance.
             config (TuyaEntityConfig): The config portion for this entity.
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._button_dp = dps_map.pop("button")
         self._init_end(dps_map)
@@ -42,7 +47,10 @@ class TuyaLocalButton(TuyaLocalEntity, ButtonEntity):
             return ButtonDeviceClass(dclass)
         except ValueError:
             if dclass:
-                _LOGGER.warning(f"Unrecognized button device class of {dclass} ignored")
+                _LOGGER.warning(
+                    "Unrecognized button device class of %s ignored",
+                    dclass,
+                )
 
     async def async_press(self):
         """Press the button"""

+ 1 - 0
custom_components/tuya_local/camera.py

@@ -37,6 +37,7 @@ class TuyaLocalCamera(TuyaLocalEntity, CameraEntity):
             device (TuyaLocalDevice): the device API instance
             config (TuyaEntityConfig): the configuration for this entity
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._switch_dp = dps_map.pop("switch", None)
         self._snapshot_dp = dps_map.pop("snapshot", None)

+ 24 - 8
custom_components/tuya_local/climate.py

@@ -70,10 +70,14 @@ class TuyaLocalClimate(TuyaLocalEntity, ClimateEntity):
            device (TuyaLocalDevice): The device API instance.
            config (TuyaEntityConfig): The entity config.
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
 
         self._aux_heat_dps = dps_map.pop(ATTR_AUX_HEAT, None)
-        self._current_temperature_dps = dps_map.pop(ATTR_CURRENT_TEMPERATURE, None)
+        self._current_temperature_dps = dps_map.pop(
+            ATTR_CURRENT_TEMPERATURE,
+            None,
+        )
         self._current_humidity_dps = dps_map.pop(ATTR_CURRENT_HUMIDITY, None)
         self._fan_mode_dps = dps_map.pop(ATTR_FAN_MODE, None)
         self._humidity_dps = dps_map.pop(ATTR_HUMIDITY, None)
@@ -213,7 +217,9 @@ class TuyaLocalClimate(TuyaLocalEntity, ClimateEntity):
         if kwargs.get(ATTR_PRESET_MODE) is not None:
             await self.async_set_preset_mode(kwargs.get(ATTR_PRESET_MODE))
         if kwargs.get(ATTR_TEMPERATURE) is not None:
-            await self.async_set_target_temperature(kwargs.get(ATTR_TEMPERATURE))
+            await self.async_set_target_temperature(
+                kwargs.get(ATTR_TEMPERATURE),
+            )
         high = kwargs.get(ATTR_TARGET_TEMP_HIGH)
         low = kwargs.get(ATTR_TARGET_TEMP_LOW)
         if high is not None or low is not None:
@@ -223,15 +229,22 @@ class TuyaLocalClimate(TuyaLocalEntity, ClimateEntity):
         if self._temperature_dps is None:
             raise NotImplementedError()
 
-        await self._temperature_dps.async_set_value(self._device, target_temperature)
+        await self._temperature_dps.async_set_value(
+            self._device,
+            target_temperature,
+        )
 
     async def async_set_target_temperature_range(self, low, high):
         """Set the target temperature range."""
         dps_map = {}
         if low is not None and self._temp_low_dps is not None:
-            dps_map.update(self._temp_low_dps.get_values_to_set(self._device, low))
+            dps_map.update(
+                self._temp_low_dps.get_values_to_set(self._device, low),
+            )
         if high is not None and self._temp_high_dps is not None:
-            dps_map.update(self._temp_high_dps.get_values_to_set(self._device, high))
+            dps_map.update(
+                self._temp_high_dps.get_values_to_set(self._device, high),
+            )
         if dps_map:
             await self._device.async_set_properties(dps_map)
 
@@ -287,7 +300,7 @@ class TuyaLocalClimate(TuyaLocalEntity, ClimateEntity):
         try:
             return HVACAction(action) if action else None
         except ValueError:
-            _LOGGER.warning(f"_Unrecognised HVAC Action {action} ignored")
+            _LOGGER.warning("Unrecognised HVAC Action %s ignored", action)
             return None
 
     @property
@@ -299,7 +312,7 @@ class TuyaLocalClimate(TuyaLocalEntity, ClimateEntity):
         try:
             return HVACMode(hvac_mode) if hvac_mode else None
         except ValueError:
-            _LOGGER.warning(f"Unrecognised HVAC Mode of {hvac_mode} ignored")
+            _LOGGER.warning("Unrecognised HVAC Mode of %s ignored", hvac_mode)
             return None
 
     @property
@@ -330,7 +343,10 @@ class TuyaLocalClimate(TuyaLocalEntity, ClimateEntity):
         # Bypass the usual dps mapping to switch the power dp directly
         # this way the hvac_mode will be kept when toggling off and on.
         if self._hvac_mode_dps and self._hvac_mode_dps.type is bool:
-            await self._device.async_set_property(self._hvac_mode_dps.id, False)
+            await self._device.async_set_property(
+                self._hvac_mode_dps.id,
+                False,
+            )
         else:
             await super().async_turn_off()
 

+ 5 - 1
custom_components/tuya_local/cover.py

@@ -37,6 +37,7 @@ class TuyaLocalCover(TuyaLocalEntity, CoverEntity):
           device (TuyaLocalDevice): The device API instance
           config (TuyaEntityConfig): The entity config
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._position_dp = dps_map.pop("position", None)
         self._currentpos_dp = dps_map.pop("current_position", None)
@@ -65,7 +66,10 @@ class TuyaLocalCover(TuyaLocalEntity, CoverEntity):
             return CoverDeviceClass(dclass)
         except ValueError:
             if dclass:
-                _LOGGER.warning(f"Unrecognised cover device class of {dclass} ignored")
+                _LOGGER.warning(
+                    "Unrecognised cover device class of %s ignored",
+                    dclass,
+                )
             return None
 
     @property

+ 3 - 1
custom_components/tuya_local/fan.py

@@ -37,6 +37,7 @@ class TuyaLocalFan(TuyaLocalEntity, FanEntity):
            device (TuyaLocalDevice): The device API instance.
            config (TuyaEntityConfig): The entity config.
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._switch_dps = dps_map.pop("switch", None)
         self._preset_dps = dps_map.pop("preset_mode", None)
@@ -112,7 +113,8 @@ class TuyaLocalFan(TuyaLocalEntity, FanEntity):
         # If there is a fixed list of values, snap to the closest one
         if self._speed_dps.values(self._device):
             percentage = min(
-                self._speed_dps.values(self._device), key=lambda x: abs(x - percentage)
+                self._speed_dps.values(self._device),
+                key=lambda x: abs(x - percentage),
             )
 
         await self._speed_dps.async_set_value(self._device, percentage)

+ 1 - 0
custom_components/tuya_local/humidifier.py

@@ -42,6 +42,7 @@ class TuyaLocalHumidifier(TuyaLocalEntity, HumidifierEntity):
            device (TuyaLocalDevice): The device API instance.
            config (TuyaEntityConfig): The entity config.
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._humidity_dps = dps_map.pop("humidity", None)
         self._mode_dps = dps_map.pop("mode", None)

+ 36 - 13
custom_components/tuya_local/light.py

@@ -3,7 +3,6 @@ Setup for different kinds of Tuya light devices
 """
 from homeassistant.components.light import (
     ATTR_BRIGHTNESS,
-    ATTR_COLOR_MODE,
     ATTR_COLOR_TEMP,
     ATTR_EFFECT,
     ATTR_HS_COLOR,
@@ -46,6 +45,7 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
             device (TuyaLocalDevice): The device API instance.
             config (TuyaEntityConfig): The configuration for this entity.
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._switch_dps = dps_map.pop("switch", None)
         self._brightness_dps = dps_map.pop("brightness", None)
@@ -70,7 +70,10 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
                 if mode and mode != ColorMode.UNKNOWN:
                     return [mode]
             except ValueError:
-                _LOGGER.warning(f"Unrecognised color mode {self.color_mode} ignored")
+                _LOGGER.warning(
+                    "Unrecognised color mode %s ignored",
+                    self.color_mode,
+                )
         return []
 
     @property
@@ -114,7 +117,9 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
             unscaled = self._color_temp_dps.get_value(self._device)
             r = self._color_temp_dps.range(self._device)
             if r and isinstance(unscaled, (int, float)):
-                return round(unscaled * 347 / (r["max"] - r["min"]) + 153 - r["min"])
+                return round(
+                    unscaled * 347 / (r["max"] - r["min"]) + 153 - r["min"],
+                )
             else:
                 return unscaled
 
@@ -154,7 +159,7 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
                 idx = 0
                 rgbhsv = {}
                 for v in vals:
-                    # Range in HA is 0-100 for s, 0-255 for rgb and v, 0-360 for h
+                    # HA range: s = 0-100, rgbv = 0-255, h = 0-360
                     n = fmt["names"][idx]
                     r = fmt["ranges"][idx]
                     mx = r["max"]
@@ -224,7 +229,10 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
                 color_mode = ColorMode.WHITE
             if ATTR_BRIGHTNESS not in params and self._brightness_dps:
                 bright = params.get(ATTR_WHITE)
-                _LOGGER.debug(f"Setting brightness via WHITE parameter to {bright}")
+                _LOGGER.debug(
+                    "Setting brightness via WHITE parameter to %d",
+                    bright,
+                )
                 settings = {
                     **settings,
                     **self._brightness_dps.get_values_to_set(
@@ -244,10 +252,13 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
                     (color_temp - 153 + r["min"]) * (r["max"] - r["min"]) / 347
                 )
 
-            _LOGGER.debug(f"Setting color temp to {color_temp}")
+            _LOGGER.debug("Setting color temp to %d", color_temp)
             settings = {
                 **settings,
-                **self._color_temp_dps.get_values_to_set(self._device, color_temp),
+                **self._color_temp_dps.get_values_to_set(
+                    self._device,
+                    color_temp,
+                ),
             }
         elif self._rgbhsv_dps and (
             ATTR_HS_COLOR in params
@@ -270,7 +281,13 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
                     "v": brightness,
                 }
                 _LOGGER.debug(
-                    f"Setting color as {rgb[0]},{rgb[1]},{rgb[2]},{hs[0]},{hs[1]},{brightness}"
+                    "Setting color as R:%d,G:%d,B:%d,H:%d,S:%d,V:%d",
+                    rgb[0],
+                    rgb[1],
+                    rgb[2],
+                    hs[0],
+                    hs[1],
+                    brightness,
                 )
                 ordered = []
                 idx = 0
@@ -304,15 +321,21 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
                 }
         if self._color_mode_dps:
             if color_mode:
-                _LOGGER.debug(f"Auto setting color mode to {color_mode}")
+                _LOGGER.debug("Auto setting color mode to %s", color_mode)
                 settings = {
                     **settings,
-                    **self._color_mode_dps.get_values_to_set(self._device, color_mode),
+                    **self._color_mode_dps.get_values_to_set(
+                        self._device,
+                        color_mode,
+                    ),
                 }
             elif not self._effect_dps:
                 effect = params.get(ATTR_EFFECT)
                 if effect:
-                    _LOGGER.debug(f"Emulating effect using color mode of {effect}")
+                    _LOGGER.debug(
+                        "Emulating effect using color mode of %s",
+                        effect,
+                    )
                     settings = {
                         **settings,
                         **self._color_mode_dps.get_values_to_set(
@@ -327,7 +350,7 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
             and self._brightness_dps
         ):
             bright = params.get(ATTR_BRIGHTNESS)
-            _LOGGER.debug(f"Setting brightness to {bright}")
+            _LOGGER.debug("Setting brightness to %s", bright)
             settings = {
                 **settings,
                 **self._brightness_dps.get_values_to_set(
@@ -339,7 +362,7 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
         if self._effect_dps:
             effect = params.get(ATTR_EFFECT, None)
             if effect:
-                _LOGGER.debug(f"Setting effect to {effect}")
+                _LOGGER.debug("Setting effect to %s", effect)
                 settings = {
                     **settings,
                     **self._effect_dps.get_values_to_set(

+ 1 - 0
custom_components/tuya_local/lock.py

@@ -30,6 +30,7 @@ class TuyaLocalLock(TuyaLocalEntity, LockEntity):
           device (TuyaLocalDevice): The device API instance.
           config (TuyaEntityConfig): The configuration for this entity.
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._lock_dp = dps_map.pop("lock", None)
         self._unlock_fp_dp = dps_map.pop("unlock_fingerprint", None)

+ 5 - 0
custom_components/tuya_local/number.py

@@ -1,6 +1,8 @@
 """
 Setup for different kinds of Tuya numbers
 """
+import logging
+
 from homeassistant.components.number import NumberEntity
 from homeassistant.components.number.const import (
     DEFAULT_MIN_VALUE,
@@ -13,6 +15,8 @@ from .helpers.config import async_tuya_setup_platform
 from .helpers.device_config import TuyaEntityConfig
 from .helpers.mixin import TuyaLocalEntity, unit_from_ascii
 
+_LOGGER = logging.getLogger(__name__)
+
 MODE_AUTO = "auto"
 
 
@@ -37,6 +41,7 @@ class TuyaLocalNumber(TuyaLocalEntity, NumberEntity):
             device (TuyaLocalDevice): the device API instance
             config (TuyaEntityConfig): the configuration for this entity
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._value_dps = dps_map.pop("value")
         if self._value_dps is None:

+ 1 - 0
custom_components/tuya_local/select.py

@@ -30,6 +30,7 @@ class TuyaLocalSelect(TuyaLocalEntity, SelectEntity):
             device (TuyaLocalDevice): the device API instance
             config (TuyaEntityConfig): the configuration for this entity
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._option_dps = dps_map.pop("option")
         if self._option_dps is None:

+ 1 - 0
custom_components/tuya_local/sensor.py

@@ -37,6 +37,7 @@ class TuyaLocalSensor(TuyaLocalEntity, SensorEntity):
             device (TuyaLocalDevice): the device API instance.
             config (TuyaEntityConfig): the configuration for this entity
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._sensor_dps = dps_map.pop("sensor", None)
         if self._sensor_dps is None:

+ 3 - 1
custom_components/tuya_local/siren.py

@@ -33,6 +33,7 @@ class TuyaLocalSiren(TuyaLocalEntity, SirenEntity):
            device (TuyaLocalDevice): The device API instance.
            config (TuyaEntityConfig): The config for this entity.
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._tone_dp = dps_map.get("tone", None)
         self._volume_dp = dps_map.get("volume_level", None)
@@ -94,7 +95,8 @@ class TuyaLocalSiren(TuyaLocalEntity, SirenEntity):
             # for fixed values, we need to snap to closest value.
             if self._volume_dp.values(self._device) is not None:
                 volume = min(
-                    self._volume_dp.values(self._device), key=lambda x: abs(x - volume)
+                    self._volume_dp.values(self._device),
+                    key=lambda x: abs(x - volume),
                 )
 
             set_dps = {

+ 1 - 0
custom_components/tuya_local/switch.py

@@ -29,6 +29,7 @@ class TuyaLocalSwitch(TuyaLocalEntity, SwitchEntity):
         Args:
             device (TuyaLocalDevice): The device API instance.
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._switch_dps = dps_map.pop("switch")
         self._init_end(dps_map)

+ 1 - 0
custom_components/tuya_local/vacuum.py

@@ -41,6 +41,7 @@ class TuyaLocalVacuum(TuyaLocalEntity, StateVacuumEntity):
             device (TuyaLocalDevice): the device API instance.
             config (TuyaEntityConfig): the configuration for this entity
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
         self._status_dps = dps_map.get("status")
         self._command_dps = dps_map.get("command")

+ 21 - 10
custom_components/tuya_local/water_heater.py

@@ -48,9 +48,13 @@ class TuyaLocalWaterHeater(TuyaLocalEntity, WaterHeaterEntity):
            device (TuyaLocalDevice): The device API instance.
            config (TuyaEntityConfig): The entity config.
         """
+        super().__init__()
         dps_map = self._init_begin(device, config)
 
-        self._current_temperature_dps = dps_map.pop(ATTR_CURRENT_TEMPERATURE, None)
+        self._current_temperature_dps = dps_map.pop(
+            ATTR_CURRENT_TEMPERATURE,
+            None,
+        )
         self._temperature_dps = dps_map.pop(ATTR_TEMPERATURE, None)
         self._unit_dps = dps_map.pop("temperature_unit", None)
         self._mintemp_dps = dps_map.pop("min_temperature", None)
@@ -119,8 +123,8 @@ class TuyaLocalWaterHeater(TuyaLocalEntity, WaterHeaterEntity):
     def is_away_mode_on(self):
         if self._away_mode_dps:
             return self._away_mode_dps.get_value(self._device)
-        elif self._operation_mode_dps and "away" in self._operation_mode_dps.values(
-            self._device
+        elif self._operation_mode_dps and (
+            "away" in self._operation_mode_dps.values(self._device)
         ):
             return self.current_operation == "away"
 
@@ -151,7 +155,9 @@ class TuyaLocalWaterHeater(TuyaLocalEntity, WaterHeaterEntity):
         if kwargs.get(ATTR_OPERATION_MODE) is not None:
             if self._operation_mode_dps is None:
                 raise NotImplementedError()
-            await self.async_set_operation_mode(kwargs.get(ATTR_OPERATION_MODE))
+            await self.async_set_operation_mode(
+                kwargs.get(ATTR_OPERATION_MODE),
+            )
 
         if kwargs.get(ATTR_TEMPERATURE) is not None:
             if self._temperature_dps is None:
@@ -164,14 +170,17 @@ class TuyaLocalWaterHeater(TuyaLocalEntity, WaterHeaterEntity):
         """Set new target operation mode."""
         if self._operation_mode_dps is None:
             raise NotImplementedError()
-        await self._operation_mode_dps.async_set_value(self._device, operation_mode)
+        await self._operation_mode_dps.async_set_value(
+            self._device,
+            operation_mode,
+        )
 
     async def async_turn_away_mode_on(self):
         """Turn away mode on"""
         if self._away_mode_dps:
             await self._away_mode_dps.async_set_value(self._device, True)
-        elif self._operation_mode_dps and "away" in self._operation_mode_dps.values(
-            self._device
+        elif self._operation_mode_dps and (
+            "away" in self._operation_mode_dps.values(self._device)
         ):
             await self.async_set_operation_mode("away")
         else:
@@ -181,11 +190,13 @@ class TuyaLocalWaterHeater(TuyaLocalEntity, WaterHeaterEntity):
         """Turn away mode off"""
         if self._away_mode_dps:
             await self._away_mode_dps.async_set_value(self._device, False)
-        elif self._operation_mode_dps and "away" in self._operation_mode_dps.values(
-            self._device
+        elif self._operation_mode_dps and (
+            "away" in self._operation_mode_dps.values(self._device)
         ):
             # switch to the default mode
-            await self.async_set_operation_mode(self._operation_mode_dps.default)
+            await self.async_set_operation_mode(
+                self._operation_mode_dps.default,
+            )
         else:
             raise NotImplementedError()