Example #1
0
class SomfyClimate(SomfyEntity, ClimateEntity):
    """Representation of a Somfy thermostat device."""
    def __init__(self, coordinator, device_id, api):
        """Initialize the Somfy device."""
        super().__init__(coordinator, device_id, api)
        self._climate = None
        self._create_device()

    def _create_device(self):
        """Update the device with the latest data."""
        self._climate = Thermostat(self.device, self.api)

    @property
    def supported_features(self) -> int:
        """Return the list of supported features."""
        return SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE

    @property
    def temperature_unit(self):
        """Return the unit of measurement used by the platform."""
        return TEMP_CELSIUS

    @property
    def current_temperature(self):
        """Return the current temperature."""
        return self._climate.get_ambient_temperature()

    @property
    def target_temperature(self):
        """Return the temperature we try to reach."""
        return self._climate.get_target_temperature()

    def set_temperature(self, **kwargs) -> None:
        """Set new target temperature."""
        temperature = kwargs.get(ATTR_TEMPERATURE)
        if temperature is None:
            return

        self._climate.set_target(TargetMode.MANUAL, temperature,
                                 DurationType.NEXT_MODE)

    @property
    def max_temp(self) -> float:
        """Return the maximum temperature."""
        return 26.0

    @property
    def min_temp(self) -> float:
        """Return the minimum temperature."""
        return 15.0

    @property
    def current_humidity(self):
        """Return the current humidity."""
        return self._climate.get_humidity()

    @property
    def hvac_mode(self) -> str:
        """Return hvac operation ie. heat, cool mode."""
        if self._climate.get_regulation_state() == RegulationState.TIMETABLE:
            return HVAC_MODE_AUTO
        return HVAC_MODES_MAPPING.get(self._climate.get_hvac_state())

    @property
    def hvac_modes(self) -> list[str]:
        """Return the list of available hvac operation modes.

        HEAT and COOL mode are exclusive. End user has to enable a mode manually within the Somfy application.
        So only one mode can be displayed. Auto mode is a scheduler.
        """
        hvac_state = HVAC_MODES_MAPPING[self._climate.get_hvac_state()]
        return [HVAC_MODE_AUTO, hvac_state]

    def set_hvac_mode(self, hvac_mode: str) -> None:
        """Set new target hvac mode."""
        if hvac_mode == HVAC_MODE_AUTO:
            self._climate.cancel_target()
        else:
            self._climate.set_target(TargetMode.MANUAL,
                                     self.target_temperature,
                                     DurationType.FURTHER_NOTICE)

    @property
    def preset_mode(self) -> str | None:
        """Return the current preset mode."""
        mode = self._climate.get_target_mode()
        return PRESETS_MAPPING.get(mode)

    @property
    def preset_modes(self) -> list[str] | None:
        """Return a list of available preset modes."""
        return list(PRESETS_MAPPING.values())

    def set_preset_mode(self, preset_mode: str) -> None:
        """Set new preset mode."""
        if self.preset_mode == preset_mode:
            return

        if preset_mode == PRESET_HOME:
            temperature = self._climate.get_at_home_temperature()
        elif preset_mode == PRESET_AWAY:
            temperature = self._climate.get_away_temperature()
        elif preset_mode == PRESET_SLEEP:
            temperature = self._climate.get_night_temperature()
        elif preset_mode == PRESET_FROST_GUARD:
            temperature = self._climate.get_frost_protection_temperature()
        elif preset_mode in [PRESET_MANUAL, PRESET_GEOFENCING]:
            temperature = self.target_temperature
        else:
            raise ValueError(f"Preset mode not supported: {preset_mode}")

        self._climate.set_target(REVERSE_PRESET_MAPPING[preset_mode],
                                 temperature, DurationType.NEXT_MODE)
class SomfyClimate(SomfyEntity, ClimateEntity):
    """Representation of a Somfy thermostat device."""
    def __init__(self, coordinator, device_id, api):
        """Initialize the Somfy device."""
        super().__init__(coordinator, device_id, api)
        self.climate = None
        self._create_device()

    def _create_device(self):
        """Update the device with the latest data."""
        self.climate = Thermostat(self.device, self.api)

    @property
    def supported_features(self) -> int:
        """Return the list of supported features."""
        supported_features = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE
        return supported_features

    @property
    def device_state_attributes(self) -> Dict[str, Any]:
        """Return the state attributes of the device."""
        return {ATTR_BATTERY_LEVEL: self.climate.get_battery()}

    @property
    def temperature_unit(self):
        """Return the unit of measurement used by the platform."""
        return TEMP_CELSIUS

    @property
    def current_temperature(self):
        """Return the current temperature."""
        return self.climate.get_ambient_temperature()

    @property
    def target_temperature(self):
        """Return the temperature we try to reach."""
        return self.climate.get_target_temperature()

    def set_temperature(self, **kwargs) -> None:
        """Set new target temperature."""
        temperature = kwargs.get(ATTR_TEMPERATURE)
        if temperature is None:
            return

        self.climate.set_target(TargetMode.MANUAL, temperature,
                                DurationType.NEXT_MODE)

    @property
    def max_temp(self) -> float:
        """Return the maximum temperature."""
        return 26.0

    @property
    def min_temp(self) -> float:
        """Return the minimum temperature."""
        return 15.0

    @property
    def current_humidity(self):
        """Return the current humidity."""
        return self.climate.get_humidity()

    @property
    def hvac_mode(self) -> str:
        """Return hvac operation ie. heat, cool mode."""
        if self.climate.get_regulation_state() == RegulationState.TIMETABLE:
            return HVAC_MODE_AUTO
        else:
            return HVAC_MODES_MAPPING.get(self.climate.get_hvac_state())

    @property
    def hvac_modes(self) -> List[str]:
        """Return the list of available hvac operation modes."""
        hvac_state = HVAC_MODES_MAPPING.get(self.climate.get_hvac_state())
        return [HVAC_MODE_AUTO, hvac_state]

    def set_hvac_mode(self, hvac_mode: str) -> None:
        """Set new target hvac mode."""
        if hvac_mode == self.hvac_mode:
            return
        if hvac_mode == HVAC_MODE_AUTO:
            self.climate.cancel_target()
        else:
            self.climate.set_target(TargetMode.MANUAL, self.target_temperature,
                                    DurationType.FURTHER_NOTICE)

    @property
    def hvac_action(self) -> str:
        """Return the current running hvac operation if supported."""
        if not self.current_temperature or not self.target_temperature:
            return CURRENT_HVAC_IDLE

        if (self.hvac_mode == HVAC_MODE_HEAT
                and self.current_temperature < self.target_temperature):
            return CURRENT_HVAC_HEAT

        if (self.hvac_mode == HVAC_MODE_COOL
                and self.current_temperature > self.target_temperature):
            return CURRENT_HVAC_HEAT

        return CURRENT_HVAC_IDLE

    @property
    def preset_mode(self) -> Optional[str]:
        """Return the current preset mode."""
        mode = self.climate.get_target_mode()
        return PRESETS_MAPPING.get(mode)

    @property
    def preset_modes(self) -> Optional[List[str]]:
        """Return a list of available preset modes."""
        return list(PRESETS_MAPPING.values())

    def set_preset_mode(self, preset_mode: str) -> None:
        """Set new preset mode."""
        if self.preset_mode == preset_mode:
            return

        if preset_mode == PRESET_HOME:
            temperature = self.climate.get_at_home_temperature()
        elif preset_mode == PRESET_AWAY:
            temperature = self.climate.get_away_temperature()
        elif preset_mode == PRESET_SLEEP:
            temperature = self.climate.get_night_temperature()
        elif preset_mode == PRESET_FROST_GUARD:
            temperature = self.climate.get_frost_protection_temperature()
        elif preset_mode == PRESET_MANUAL or preset_mode == PRESET_GEOFENCING:
            temperature = self.target_temperature
        else:
            _LOGGER.error("Preset mode not supported: %s", preset_mode)
            return

        self.climate.set_target(REVERSE_PRESET_MAPPING[preset_mode],
                                temperature, DurationType.NEXT_MODE)