示例#1
0
    async def _async_control_heating(self, time=None, force=False):
        """Check if we need to turn heating on or off."""
        async with self._temp_lock:
            if not self._active and None not in (self._cur_temp,
                                                 self._target_temp):
                self._active = True
                _LOGGER.info("Obtained current and target temperature. "
                             "Generic thermostat active. %s, %s",
                             self._cur_temp, self._target_temp)

            if not self._active or self._hvac_mode == HVAC_MODE_OFF:
                return

            if not force and time is None:
                # If the `force` argument is True, we
                # ignore `min_cycle_duration`.
                # If the `time` argument is not none, we were invoked for
                # keep-alive purposes, and `min_cycle_duration` is irrelevant.
                if self.min_cycle_duration:
                    if self._is_device_active:
                        current_state = STATE_ON
                    else:
                        current_state = HVAC_MODE_OFF
                        if (self._hvac_mode == HVAC_MODE_COOL):
                            long_enough = condition.state(
                                self.hass, self.cooler_entity_id, current_state,
                                self.min_cycle_duration)
                        elif (self._hvac_mode == HVAC_MODE_HEAT):
                            long_enough = condition.state(
                                self.hass, self.heater_entity_id, current_state,
                                self.min_cycle_duration)
                    if not long_enough:
                        return

            too_cold = \
                self._target_temp - self._cur_temp >= self._tolerance
            too_hot = \
                self._cur_temp - self._target_temp >= self._tolerance
            if self._is_device_active:
                if (self._hvac_mode == HVAC_MODE_COOL and too_cold) or (self._hvac_mode == HVAC_MODE_HEAT and too_hot):
                    _LOGGER.info("Turning off HVAC")
                    await self._async_turn_off()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    if (self._hvac_mode == HVAC_MODE_COOL):
                        await self._async_cooler_turn_on()
                    elif (self._hvac_mode == HVAC_MODE_HEAT):
                        await self._async_heater_turn_on()
            else:
                if (self._hvac_mode == HVAC_MODE_COOL and too_hot):
                    _LOGGER.info("Turning on cooler %s", self.cooler_entity_id)
                    await self._async_cooler_turn_on()
                elif (self._hvac_mode == HVAC_MODE_HEAT and too_cold):
                    _LOGGER.info("Turning on heater %s", self.heater_entity_id)
                    await self._async_heater_turn_on()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    await self._async_turn_off()
示例#2
0
async def test_state_raises(hass):
    """Test that state raises ConditionError on errors."""
    # No entity
    with pytest.raises(ConditionError, match="no entity"):
        condition.state(hass, entity=None, req_state="missing")

    # Unknown entities
    test = await condition.async_from_config(
        hass,
        {
            "condition": "state",
            "entity_id": ["sensor.door_unknown", "sensor.window_unknown"],
            "state": "open",
        },
    )
    with pytest.raises(ConditionError, match="unknown entity.*door"):
        test(hass)
    with pytest.raises(ConditionError, match="unknown entity.*window"):
        test(hass)

    # Unknown attribute
    with pytest.raises(ConditionError, match=r"attribute .* does not exist"):
        test = await condition.async_from_config(
            hass,
            {
                "condition": "state",
                "entity_id": "sensor.door",
                "attribute": "model",
                "state": "acme",
            },
        )

        hass.states.async_set("sensor.door", "open")
        test(hass)

    # Unknown state entity
    with pytest.raises(ConditionError, match="input_text.missing"):
        test = await condition.async_from_config(
            hass,
            {
                "condition": "state",
                "entity_id": "sensor.door",
                "state": "input_text.missing",
            },
        )

        hass.states.async_set("sensor.door", "open")
        test(hass)
示例#3
0
 def test_is_state(hass: HomeAssistant,
                   variables: TemplateVarsType) -> bool:
     """Test if an entity is a certain state."""
     result = condition.state(hass, config[ATTR_ENTITY_ID], STATE_HOME)
     if reverse:
         result = not result
     return result
示例#4
0
    async def _async_control_humidification(self, time=None, force=False):
        """Check if we need to turn humidification on or off."""
        async with self._humidity_lock:
            if not self._active and None not in (self._cur_humidity,
                                                 self._target_humidity):
                self._active = True
                _LOGGER.info(
                    "Obtained current and target humidity. "
                    "Generic hygrostat active. %s, %s",
                    self._cur_humidity,
                    self._target_humidity,
                )

            if not self._active or self._hvac_mode == HVAC_MODE_FAN_ONLY or self._hvac_mode == HVAC_MODE_OFF:
                return

            if not force and time is None:
                # If the `force` argument is True, we
                # ignore `min_cycle_duration`.
                # If the `time` argument is not none, we were invoked for
                # keep-alive purposes, and `min_cycle_duration` is irrelevant.
                if self.min_cycle_duration:
                    if self._is_device_active:
                        current_state = STATE_ON
                    else:
                        current_state = HVAC_MODE_OFF
                    long_enough = condition.state(
                        self.hass,
                        self.dryer_entity_id,
                        current_state,
                        self.min_cycle_duration,
                    )
                    if not long_enough:
                        return

            too_dry = self._target_humidity >= self._cur_humidity + self._dry_tolerance
            too_moist = self._cur_humidity >= self._target_humidity + self._moist_tolerance
            if self._is_device_active:
                if (self.moist_mode and too_moist) or (not self.moist_mode
                                                       and too_dry):
                    _LOGGER.info("Turning off dryer %s", self.dryer_entity_id)
                    await self._async_dryer_turn_off()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    _LOGGER.info(
                        "Keep-alive - Turning on dryer %s",
                        self.dryer_entity_id,
                    )
                    await self._async_dryer_turn_on()
            else:
                if (self.moist_mode and too_dry) or (not self.moist_mode
                                                     and too_moist):
                    _LOGGER.info("Turning on dryer %s", self.dryer_entity_id)
                    await self._async_dryer_turn_on()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    _LOGGER.info("Keep-alive - Turning off dryer %s",
                                 self.dryer_entity_id)
                    await self._async_dryer_turn_off()
    def _process_state(self, entity_observation):
        """Add entity to current observations if state conditions are met."""
        entity = entity_observation['entity_id']

        should_trigger = condition.state(
            self.hass, entity, entity_observation.get('to_state'))

        self._update_current_obs(entity_observation, should_trigger)
 def is_active_long_enough(self, mode=None):
     """ This function is to check if the heater/cooler has been active long enough """
     if not self.min_cycle_duration:
         return True
     if self._is_device_active:
         current_state = STATE_ON
     else:
         current_state = STATE_OFF
     if mode == "heat":
         for entity in self.heaters_entity_ids:
             return condition.state(self.hass, entity, current_state, self.min_cycle_duration)
     elif mode == "cool":
         for entity in self.coolers_entity_ids:
             return condition.state(self.hass, entity, current_state, self.min_cycle_duration)
     else:
         _LOGGER.error("Wrong mode have been passed to function is_active_long_enough")
     return True
示例#7
0
    def _process_state(self, entity_observation):
        """Return True if state conditions are met."""
        entity = entity_observation["entity_id"]

        should_trigger = condition.state(self.hass, entity,
                                         entity_observation.get("to_state"))

        return should_trigger
示例#8
0
    def _process_state(self, entity_observation):
        """Add entity to current observations if state conditions are met."""
        entity = entity_observation["entity_id"]

        should_trigger = condition.state(self.hass, entity,
                                         entity_observation.get("to_state"))

        self._update_current_obs(entity_observation, should_trigger)
示例#9
0
    def _process_state(self, entity_observation):
        """Return True if state conditions are met."""
        entity = entity_observation["entity_id"]

        try:
            return condition.state(self.hass, entity,
                                   entity_observation.get("to_state"))
        except ConditionError:
            return False
    def _async_control_heating(self):
        """Check if we need to turn heating on or off."""
        if not self._active and None not in (self._cur_temp,
                                             self._target_temp):
            self._active = True
            _LOGGER.info(
                "Obtained current and target temperature. "
                "Generic thermostat active. %s, %s", self._cur_temp,
                self._target_temp)

        if not self._active:
            return

        if not self._enabled:
            return

        if self.min_cycle_duration:
            if self._is_device_active:
                current_state = STATE_ON
            else:
                current_state = STATE_OFF
            long_enough = condition.state(self.hass, self.heater_entity_id,
                                          current_state,
                                          self.min_cycle_duration)
            if not long_enough:
                return

        if self.ac_mode:
            is_cooling = self._is_device_active
            if is_cooling:
                too_cold = self._target_temp - self._cur_temp >= \
                    self._cold_tolerance
                if too_cold:
                    _LOGGER.info("Turning off AC %s", self.heater_entity_id)
                    self._heater_turn_off()
            else:
                too_hot = self._cur_temp - self._target_temp >= \
                    self._hot_tolerance
                if too_hot:
                    _LOGGER.info("Turning on AC %s", self.heater_entity_id)
                    self._heater_turn_on()
        else:
            is_heating = self._is_device_active
            if is_heating:
                too_hot = self._cur_temp - self._target_temp >= \
                    self._hot_tolerance
                if too_hot:
                    _LOGGER.info("Turning off heater %s",
                                 self.heater_entity_id)
                    self._heater_turn_off()
            else:
                too_cold = self._target_temp - self._cur_temp >= \
                    self._cold_tolerance
                if too_cold:
                    _LOGGER.info("Turning on heater %s", self.heater_entity_id)
                    self._heater_turn_on()
        def test_is_state(hass: HomeAssistant, variables: TemplateVarsType):
            """ Test thumbnail state """

            return condition.state(
                hass,
                entity_id,
                state,
                for_period,
                attribute,
            )
    def _async_control_heating(self):
        """Check if we need to turn heating on or off."""
        if not self._active and None not in (self._cur_temp,
                                             self._target_temp):
            self._active = True
            _LOGGER.info("Obtained current and target temperature. "
                         "Generic thermostat active. %s, %s",
                         self._cur_temp, self._target_temp)

        if not self._active:
            return

        if not self._enabled:
            return

        if self.min_cycle_duration:
            if self._is_device_active:
                current_state = STATE_ON
            else:
                current_state = STATE_OFF
            long_enough = condition.state(
                self.hass, self.heater_entity_id, current_state,
                self.min_cycle_duration)
            if not long_enough:
                return

        if self.ac_mode:
            is_cooling = self._is_device_active
            if is_cooling:
                too_cold = self._target_temp - self._cur_temp >= \
                    self._cold_tolerance
                if too_cold:
                    _LOGGER.info("Turning off AC %s", self.heater_entity_id)
                    self._heater_turn_off()
            else:
                too_hot = self._cur_temp - self._target_temp >= \
                    self._hot_tolerance
                if too_hot:
                    _LOGGER.info("Turning on AC %s", self.heater_entity_id)
                    self._heater_turn_on()
        else:
            is_heating = self._is_device_active
            if is_heating:
                too_hot = self._cur_temp - self._target_temp >= \
                    self._hot_tolerance
                if too_hot:
                    _LOGGER.info("Turning off heater %s",
                                 self.heater_entity_id)
                    self._heater_turn_off()
            else:
                too_cold = self._target_temp - self._cur_temp >= \
                    self._cold_tolerance
                if too_cold:
                    _LOGGER.info("Turning on heater %s", self.heater_entity_id)
                    self._heater_turn_on()
示例#13
0
 def test_is_state(hass: HomeAssistant,
                   variables: TemplateVarsType) -> bool:
     """Test if an entity is a certain state."""
     return condition.state(
         hass,
         config[ATTR_ENTITY_ID],
         "linked",
         attribute=config[CONF_TYPE][:-len(
             "_linked"
         )],  # Condition names are attribute + _linked. Bit hacky, TODO: replace with removesuffix in Python 3.9
     )
    async def _async_control_heat_cool(self, time=None, force=False):
        """Check if we need to turn heating on or off."""
        async with self._temp_lock:
            if not self._active and None not in (
                self._cur_temp,
                self._target_temp_high,
                self._target_temp_low,
            ):
                self._active = True
            if not self._active or self._hvac_mode == HVAC_MODE_OFF:
                return

            if not force and time is None:
                # If the `force` argument is True, we
                # ignore `min_cycle_duration`.
                # If the `time` argument is not none, we were invoked for
                # keep-alive purposes, and `min_cycle_duration` is irrelevant.
                if self.min_cycle_duration:
                    if self._is_device_active:
                        current_state = STATE_ON
                    else:
                        current_state = HVAC_MODE_OFF
                    long_enough = condition.state(
                        self.hass,
                        self.heater_entity_id,
                        self.cooler_entity_id,
                        current_state,
                        self.min_cycle_duration,
                    )
                    if not long_enough:
                        return

            too_cold = self._target_temp_low >= self._cur_temp + self._cold_tolerance
            too_hot = self._cur_temp >= self._target_temp_high + self._hot_tolerance

            if self._is_opening_open:
                await self._async_heater_turn_off()
                await self._async_cooler_turn_off()
            elif self._is_floor_hot:
                await self._async_heater_turn_off()
            else:
                await self.async_heater_cooler_toggle(too_cold, too_hot)

            if time is not None:
                # The time argument is passed only in keep-alive case
                _LOGGER.info(
                    "Keep-alive - Toggling on heater cooler %s, %s",
                    self.heater_entity_id,
                    self.cooler_entity_id,
                )
                await self.async_heater_cooler_toggle(too_cold, too_hot)
示例#15
0
    async def _async_control_heating(self, time=None, force=False):
        """Check if we need to turn heating on or off."""
        async with self._temp_lock:
            if not self._active and None not in (self._cur_temp,
                                                 self._target_temp):
                self._active = True
                _LOGGER.info("Obtained current and target temperature. "
                             "Generic thermostat active. %s, %s",
                             self._cur_temp, self._target_temp)

            if not self._active or not self._enabled:
                return

            if not force and time is None:
                # If the `force` argument is True, we
                # ignore `min_cycle_duration`.
                # If the `time` argument is not none, we were invoked for
                # keep-alive purposes, and `min_cycle_duration` is irrelevant.
                if self.min_cycle_duration:
                    if self._is_device_active:
                        current_state = STATE_ON
                    else:
                        current_state = STATE_OFF
                    long_enough = condition.state(
                        self.hass, self.heater_entity_id, current_state,
                        self.min_cycle_duration)
                    if not long_enough:
                        return

            too_cold = \
                self._target_temp - self._cur_temp >= self._cold_tolerance
            too_hot = \
                self._cur_temp - self._target_temp >= self._hot_tolerance
            if self._is_device_active:
                if (self.ac_mode and too_cold) or \
                   (not self.ac_mode and too_hot):
                    _LOGGER.info("Turning off heater %s",
                                 self.heater_entity_id)
                    await self._async_heater_turn_off()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    await self._async_heater_turn_on()
            else:
                if (self.ac_mode and too_hot) or \
                   (not self.ac_mode and too_cold):
                    _LOGGER.info("Turning on heater %s", self.heater_entity_id)
                    await self._async_heater_turn_on()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    await self._async_heater_turn_off()
    async def _async_control_heating(self, time=None):
        """Check if we need to turn heating on or off."""
        async with self._temp_lock:
            if not self._active and None not in (self._cur_temp,
                                                 self._target_temp):
                self._active = True
                _LOGGER.info(
                    "Obtained current and target temperature. "
                    "Generic thermostat active. %s, %s", self._cur_temp,
                    self._target_temp)

            if not self._active or not self._enabled:
                return

            if self.min_cycle_duration:
                if self._is_device_active:
                    current_state = STATE_ON
                else:
                    current_state = STATE_OFF
                long_enough = condition.state(self.hass, self.heater_entity_id,
                                              current_state,
                                              self.min_cycle_duration)
                if not long_enough:
                    return

            too_cold = \
                self._target_temp - self._cur_temp >= self._cold_tolerance
            too_hot = \
                self._cur_temp - self._target_temp >= self._hot_tolerance
            if self._is_device_active:
                if (self.ac_mode and too_cold) or \
                   (not self.ac_mode and too_hot):
                    _LOGGER.info("Turning off heater %s",
                                 self.heater_entity_id)
                    await self._async_heater_turn_off()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    await self._async_heater_turn_on()
            else:
                if (self.ac_mode and too_hot) or \
                   (not self.ac_mode and too_cold):
                    _LOGGER.info("Turning on heater %s", self.heater_entity_id)
                    await self._async_heater_turn_on()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    await self._async_heater_turn_off()
    def _control_heating(self):
        """Check if we need to turn heating on or off."""
        if not self._active and None not in (self._cur_temp,
                                             self._target_temp):
            self._active = True
            _LOGGER.info('Obtained current and target temperature. '
                         'Generic thermostat active.')

        if not self._active:
            return

        if self.min_cycle_duration:
            if self._is_device_active:
                current_state = STATE_ON
            else:
                current_state = STATE_OFF
            long_enough = condition.state(self.hass, self.heater_entity_id,
                                          current_state,
                                          self.min_cycle_duration)
            if not long_enough:
                return

        if self.ac_mode:
            too_hot = self._cur_temp - self._target_temp > self._tolerance
            is_cooling = self._is_device_active
            if too_hot and not is_cooling:
                _LOGGER.info('Turning on AC %s', self.heater_entity_id)
                switch.turn_on(self.hass, self.heater_entity_id)
            elif not too_hot and is_cooling:
                _LOGGER.info('Turning off AC %s', self.heater_entity_id)
                switch.turn_off(self.hass, self.heater_entity_id)
        else:
            too_cold = self._target_temp - self._cur_temp > self._tolerance
            is_heating = self._is_device_active

            if too_cold and not is_heating:
                _LOGGER.info('Turning on heater %s', self.heater_entity_id)
                switch.turn_on(self.hass, self.heater_entity_id)
            elif not too_cold and is_heating:
                _LOGGER.info('Turning off heater %s', self.heater_entity_id)
                switch.turn_off(self.hass, self.heater_entity_id)
示例#18
0
    def _control_heating(self):
        """Check if we need to turn heating on or off."""
        if not self._active and None not in (self._cur_temp,
                                             self._target_temp):
            self._active = True
            _LOGGER.info('Obtained current and target temperature. '
                         'Generic thermostat active.')

        if not self._active:
            return

        if self.min_cycle_duration:
            if self._is_device_active:
                current_state = STATE_ON
            else:
                current_state = STATE_OFF
            long_enough = condition.state(self.hass, self.heater_entity_id,
                                          current_state,
                                          self.min_cycle_duration)
            if not long_enough:
                return

        if self.ac_mode:
            too_hot = self._cur_temp - self._target_temp > TOL_TEMP
            is_cooling = self._is_device_active
            if too_hot and not is_cooling:
                _LOGGER.info('Turning on AC %s', self.heater_entity_id)
                switch.turn_on(self.hass, self.heater_entity_id)
            elif not too_hot and is_cooling:
                _LOGGER.info('Turning off AC %s', self.heater_entity_id)
                switch.turn_off(self.hass, self.heater_entity_id)
        else:
            too_cold = self._target_temp - self._cur_temp > TOL_TEMP
            is_heating = self._is_device_active

            if too_cold and not is_heating:
                _LOGGER.info('Turning on heater %s', self.heater_entity_id)
                switch.turn_on(self.hass, self.heater_entity_id)
            elif not too_cold and is_heating:
                _LOGGER.info('Turning off heater %s', self.heater_entity_id)
                switch.turn_off(self.hass, self.heater_entity_id)
示例#19
0
    async def _async_control_heating(self, time=None, force=False):
        """Check if we need to turn heating on or off."""
        async with self._temp_lock:
            if not self._active and None not in (self._cur_temp,
                                                 self._target_temp):
                self._active = True
                _LOGGER.info(
                    "Obtained current and target temperature. "
                    "Generic Dual-mode thermostat active. %s, %s",
                    self._cur_temp,
                    self._target_temp,
                )

            if not self._active or self._hvac_mode == HVAC_MODE_OFF:
                return

            # This variable is used for the long_enough condition and for the LOG Messages
            if not force and time is None:
                # If the `force` argument is True, we
                # ignore `min_cycle_duration`.
                # If the `time` argument is not none, we were invoked for
                # keep-alive purposes, and `min_cycle_duration` is irrelevant.
                if self.min_cycle_duration:
                    if self._hvac_mode == HVAC_MODE_COOL:
                        active_entity = self.cooler_entity_id
                    if self._hvac_mode == HVAC_MODE_HEAT:
                        active_entity = self.heater_entity_id
                    if self._hvac_mode == HVAC_MODE_FAN_ONLY:
                        active_entity = self.fan_entity_id
                    if self._hvac_mode == HVAC_MODE_DRY:
                        active_entity = self.dryer_entity_id

                    if self._is_device_active:
                        current_state = STATE_ON
                    else:
                        current_state = HVAC_MODE_OFF
                    long_enough = condition.state(
                        self.hass,
                        active_entity,
                        current_state,
                        self.min_cycle_duration,
                    )
                    if not long_enough:
                        return

            too_cold = self._target_temp >= self._cur_temp + self._cold_tolerance
            too_hot = self._cur_temp >= self._target_temp + self._hot_tolerance
            if self._is_device_active:  # when to turn off
                if too_cold and self._hvac_mode == HVAC_MODE_COOL:
                    _LOGGER.info("Turning off cooler %s",
                                 self.cooler_entity_id)
                    await self._async_cooler_turn_off()
                elif too_hot and self._hvac_mode == HVAC_MODE_HEAT:
                    _LOGGER.info("Turning off heater %s",
                                 self.heater_entity_id)
                    await self._async_heater_turn_off()
                elif self._hvac_mode == HVAC_MODE_FAN_ONLY:
                    if too_cold and self.fan_behavior == FAN_MODE_COOL:
                        _LOGGER.info("Turning off fan %s", self.fan_entity_id)
                        await self._async_fan_turn_off()
                    elif too_hot and self.fan_behavior == FAN_MODE_HEAT:
                        _LOGGER.info("Turning off fan %s", self.fan_entity_id)
                        await self._async_fan_turn_off()
                elif self._hvac_mode == HVAC_MODE_DRY:
                    if too_cold and self.dryer_behavior == DRYER_MODE_COOL:
                        _LOGGER.info("Turning off dehumidifier %s",
                                     self.dryer_entity_id)
                        await self._async_dryer_turn_off()
                    elif too_hot and self.dryer_behavior == DRYER_MODE_HEAT:
                        _LOGGER.info("Turning off dehumidifier %s",
                                     self.dryer_entity_id)
                        await self._async_dryer_turn_off()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    _LOGGER.info("Keep-alive - Turning on heater %s",
                                 active_entity)
                    if self._hvac_mode == HVAC_MODE_COOL:
                        await self._async_cooler_turn_on()
                    elif self._hvac_mode == HVAC_MODE_HEAT:
                        await self._async_heater_turn_on()
                    elif self._hvac_mode == HVAC_MODE_FAN_ONLY:
                        await self._async_fan_turn_on()
                    elif self._hvac_mode == HVAC_MODE_DRY:
                        await self._async_dryer_turn_on()
            else:  # when to turn on
                if too_hot and self._hvac_mode == HVAC_MODE_COOL:
                    _LOGGER.info("Turning on cooler %s", self.cooler_entity_id)
                    await self._async_cooler_turn_on()
                elif too_cold and self._hvac_mode == HVAC_MODE_HEAT:
                    _LOGGER.info("Turning on heater %s", self.heater_entity_id)
                    await self._async_heater_turn_on()
                elif self._hvac_mode == HVAC_MODE_FAN_ONLY:
                    if too_hot and self.fan_behavior == FAN_MODE_COOL:
                        _LOGGER.info("Turning on fan %s", self.fan_entity_id)
                        await self._async_fan_turn_on()
                    elif too_cold and self.fan_behavior == FAN_MODE_HEAT:
                        _LOGGER.info("Turning on fan %s", self.fan_entity_id)
                        await self._async_fan_turn_on()
                elif self._hvac_mode == HVAC_MODE_DRY:
                    if too_hot and self.dryer_behavior == DRYER_MODE_COOL:
                        _LOGGER.info("Turning on dehumidifier %s",
                                     self.dryer_entity_id)
                        await self._async_dryer_turn_on()
                    elif too_cold and self.dryer_behavior == DRYER_MODE_HEAT:
                        _LOGGER.info("Turning on dehumidifier %s",
                                     self.dryer_entity_id)
                        await self._async_dryer_turn_on()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    _LOGGER.info("Keep-alive - Turning off heater %s",
                                 active_entity)
                    if self._hvac_mode == HVAC_MODE_COOL:
                        await self._async_cooler_turn_off()
                    elif self._hvac_mode == HVAC_MODE_HEAT:
                        await self._async_heater_turn_off()
                    elif self._hvac_mode == HVAC_MODE_FAN_ONLY:
                        await self._async_fan_turn_off()
                    elif self._hvac_mode == HVAC_MODE_DRY:
                        await self._async_dryer_turn_off()

            if self.fan_behavior == FAN_MODE_NEUTRAL and self._hvac_mode == HVAC_MODE_FAN_ONLY:
                await self._async_fan_turn_on()
            if self.dryer_behavior == DRYER_MODE_NEUTRAL and self._hvac_mode == HVAC_MODE_DRY:
                await self._async_dryer_turn_on()
    def _async_control_heating(self):
        """Check if we need to turn heating on or off."""
        if not self._active and None not in (self._cur_temp,
                                             self._target_temp):
            self._active = True
            _LOGGER.info('Obtained current and target temperature. '
                         'Generic thermostat active.')

        if not self._active:
            return

        if not self._enabled:
            return

        if self.min_cycle_duration:
            if self._is_device_active:
                current_state = STATE_ON
            else:
                current_state = STATE_OFF
            long_enough = condition.state(self.hass, self.heater_entity_id,
                                          current_state,
                                          self.min_cycle_duration)
            if not long_enough:
                return

        if self.ac_mode:
            is_cooling = self._is_device_active
            #if is_cooling:
            #too_cold = self._target_temp - self._cur_temp >= \
            #self._cold_tolerance
            #if too_cold:
            #_LOGGER.info('Turning off AC %s', self.heater_entity_id)
            #self._heater_turn_off()
            #else:
            #too_hot = self._cur_temp - self._target_temp >= \
            #self._hot_tolerance
            #if too_hot:
            #_LOGGER.info('Turning on AC %s', self.heater_entity_id)
            #self._heater_turn_on()
        else:
            is_heating = self._is_device_active
            if self._target_temp < self._min_heating_temp:  # or operation mode is off
                if is_heating:
                    _LOGGER.info('Turning of heatpump {0}'.format(
                        self.heater_entity_id))
                    self._heatpump_set_mode('OFF')
                else:
                    return
            elif is_heating:
                too_hot = self._cur_temp - self._target_temp >= \
                    self._hot_tolerance
                if too_hot:
                    _LOGGER.info('Turning heatpump %s to FAN',
                                 self.heater_entity_id)
                    self._heatpump_set_mode('FAN')
            else:
                too_cold = self._target_temp - self._cur_temp >= \
                    self._cold_tolerance
                if too_cold:
                    _LOGGER.info('Turning heatpump %s to HEAT',
                                 self.heater_entity_id)
                    self._heatpump_set_mode('HEAT')
示例#21
0
    async def _async_control_heating(self, time=None, force=False):
        """Check if we need to turn heating on or off."""
        async with self._temp_lock:
            if not self._active and None not in (self._cur_temp,
                                                 self._target_temp):
                self._active = True
                _LOGGER.info(
                    "Obtained current and target temperature. "
                    "Generic Dual-mode thermostat active. %s, %s",
                    self._cur_temp,
                    self._target_temp,
                )

            if not self._active or self._hvac_mode == HVAC_MODE_OFF:
                return

            if not force and time is None:
                # If the `force` argument is True, we
                # ignore `min_cycle_duration`.
                # If the `time` argument is not none, we were invoked for
                # keep-alive purposes, and `min_cycle_duration` is irrelevant.
                if self.min_cycle_duration:
                    entity = (self.cooler_entity_id if self._hvac_mode
                              == HVAC_MODE_COOL else self.heater_entity_id)

                    if self._is_device_active:
                        current_state = STATE_ON
                    else:
                        current_state = HVAC_MODE_OFF
                    long_enough = condition.state(
                        self.hass,
                        entity,
                        current_state,
                        self.min_cycle_duration,
                    )
                    if not long_enough:
                        return

            # self._hvac_mode can only be HVAC_MODE_HEAT or HVAC_MODE_COOL at this point
            if self.sensor_mode == SENSOR_MODE_SMART:
                if self._hvac_mode == HVAC_MODE_HEAT:
                    too_cold = (self._fs_heat_min_temp >=
                                self._cur_floor_temp + self._cold_tolerance or
                                (self._target_temp >=
                                 self._cur_temp + self._cold_tolerance
                                 and self._fs_heat_max_temp >=
                                 self._cur_floor_temp + self._cold_tolerance))
                    too_hot = (self._cur_floor_temp >=
                               self._fs_heat_max_temp + self._hot_tolerance
                               or (self._cur_floor_temp >=
                                   self._fs_heat_min_temp + self._hot_tolerance
                                   and self._cur_temp >=
                                   self._target_temp + self._hot_tolerance))
                elif self._hvac_mode == HVAC_MODE_COOL:
                    too_cold = (self._cur_floor_temp + self._cold_tolerance <=
                                self._fs_cool_min_temp
                                or (self._fs_cool_max_temp >=
                                    self._cur_floor_temp + self._cold_tolerance
                                    and self._target_temp >=
                                    self._cur_temp + self._cold_tolerance))
                    too_hot = (self._cur_floor_temp >=
                               self._fs_cool_max_temp + self._hot_tolerance or
                               (self._cur_temp >= self._target_temp +
                                self._hot_tolerance and self._cur_floor_temp >=
                                self._fs_cool_min_temp + self._hot_tolerance))
                else:
                    too_cold = False
                    too_hot = False
                    _LOGGER.error("Smart mode, HVAC_MODE nor heat or cool")
            elif self.sensor_mode == SENSOR_MODE_FLOOR:
                if self._hvac_mode == HVAC_MODE_HEAT:
                    too_cold = (self._fs_heat_min_temp >=
                                self._cur_floor_temp + self._cold_tolerance or
                                (self._target_temp >=
                                 self._cur_floor_temp + self._cold_tolerance
                                 and self._fs_heat_max_temp >=
                                 self._cur_floor_temp + self._cold_tolerance))
                    too_hot = (self._cur_floor_temp >=
                               self._fs_heat_max_temp + self._hot_tolerance
                               or (self._cur_floor_temp >=
                                   self._fs_heat_min_temp + self._hot_tolerance
                                   and self._cur_floor_temp >=
                                   self._target_temp + self._hot_tolerance))
                elif self._hvac_mode == HVAC_MODE_COOL:
                    too_cold = (self._fs_cool_min_temp >=
                                self._cur_floor_temp + self._cold_tolerance or
                                (self._fs_cool_max_temp >=
                                 self._cur_floor_temp + self._cold_tolerance
                                 and self._target_temp >=
                                 self._cur_floor_temp + self._cold_tolerance))
                    too_hot = (self._cur_floor_temp >=
                               self._fs_cool_max_temp + self._hot_tolerance or
                               (self._cur_floor_temp >= self._target_temp +
                                self._hot_tolerance and self._target_temp >
                                self._fs_cool_min_temp + self._hot_tolerance))
                else:
                    too_cold = False
                    too_hot = False
                    _LOGGER.error("Floor mode, HVAC_MODE nor heat or cool")
            else:  # self.sensor_mode == SENSOR_MODE_AMBIENT:
                too_cold = self._target_temp >= self._cur_temp + self._cold_tolerance
                too_hot = self._cur_temp >= self._target_temp + self._hot_tolerance
            if self._is_device_active:  # when to turn off
                if too_cold and self._hvac_mode == HVAC_MODE_COOL:
                    _LOGGER.info("Turning off cooler %s",
                                 self.cooler_entity_id)
                    await self._async_cooler_turn_off()
                elif too_hot and self._hvac_mode == HVAC_MODE_HEAT:
                    _LOGGER.info("Turning off heater %s",
                                 self.heater_entity_id)
                    await self._async_heater_turn_off()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    _LOGGER.info(
                        "Keep-alive - Turning on heater heater %s",
                        self.heater_entity_id if self._hvac_mode
                        == HVAC_MODE_HEAT else self.cooler_entity_id,
                    )
                    if self._hvac_mode == HVAC_MODE_COOL:
                        await self._async_cooler_turn_on()
                    elif self._hvac_mode == HVAC_MODE_HEAT:
                        await self._async_heater_turn_on()
            else:  # when to turn on
                if too_hot and self._hvac_mode == HVAC_MODE_COOL:
                    _LOGGER.info("Turning on cooler %s", self.cooler_entity_id)
                    await self._async_cooler_turn_on()
                elif too_cold and self._hvac_mode == HVAC_MODE_HEAT:
                    _LOGGER.info("Turning on heater %s", self.heater_entity_id)
                    await self._async_heater_turn_on()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    _LOGGER.info(
                        "Keep-alive - Turning off heater %s",
                        self.heater_entity_id if self._hvac_mode
                        == HVAC_MODE_HEAT else self.cooler_entity_id,
                    )
                    if self._hvac_mode == HVAC_MODE_COOL:
                        await self._async_cooler_turn_off()
                    elif self._hvac_mode == HVAC_MODE_HEAT:
                        await self._async_heater_turn_off()
示例#22
0
    async def _async_control_heating(self, time=None, force=False):
        """Check if we need to turn heating on or off."""
        _LOGGER.debug("Check if we need to turn heating on or off")
        async with self._temp_lock:
            if not self._active and None not in (self._cur_temp,
                                                 self._target_temp):
                self._active = True
                _LOGGER.info("Obtained current and target temperature. "
                             "Generic thermostat active. %s, %s",
                             self._cur_temp, self._target_temp)

            if not self._active or not self._enabled:
                return

            next_state = self._current_operation
            is_heating = self._is_device_active
            if is_heating:
                too_hot = self._cur_temp - self._target_temp >= \
                    self._hot_tolerance
                if too_hot:
                    next_state = STATE_STANDBY
                else:
                    _LOGGER.debug("Evaluate regulation mode for heater %s",
                                    self.heater_entity_id)
                    regulation_mode = self._cur_temp >= \
                        self._target_temp - self._regulation_delta
                    if regulation_mode:
                        next_state = STATE_REGULATION
                    else:
                        next_state = STATE_HEAT
            else:
                too_cold = self._target_temp - self._cur_temp >= \
                    self._cold_tolerance
                if too_cold:
                    next_state = STATE_HEAT
                else:
                    next_state = STATE_STANDBY
            _LOGGER.debug("Next state for heater %s : %s", self.heater_entity_id, next_state)

            if not force and time is None:
                # If the `force` argument is True, we
                # ignore `min_cycle_duration`.
                # If the `time` argument is not none, we were invoked for
                # keep-alive purposes, and `min_cycle_duration` is irrelevant.
                if self.min_cycle_duration:
                    if self._is_device_active:
                        current_state = STATE_ON
                    else:
                        current_state = STATE_OFF
                    if next_state == STATE_STANDBY:
                        next_current_state = STATE_OFF
                    else:
                        next_current_state = STATE_ON
                    if current_state != next_current_state:
                        _LOGGER.debug("State : %s since %s", self.hass.states.get(self._heat_entity_id).state, self.hass.states.get(self._heat_entity_id).last_changed)
                        long_enough = condition.state(
                            self.hass, self._heat_entity_id, current_state,
                            self.min_cycle_duration)
                        if not long_enough:
                            _LOGGER.debug("Min cycle duration not reach for heater %s", self._heat_entity_id)
                            return

            await self._async_set_heating_mode(next_state, time)
示例#23
0
    async def _async_operate(self, time=None, force=False):
        """Check if we need to turn humidifying on or off."""
        async with self._humidity_lock:
            if not self._active and None not in (
                self._cur_humidity,
                self._target_humidity,
            ):
                self._active = True
                force = True
                _LOGGER.info(
                    "Obtained current and target humidity. "
                    "Generic hygrostat active. %s, %s",
                    self._cur_humidity,
                    self._target_humidity,
                )

            if not self._active or not self._state:
                return

            if not force and time is None:
                # If the `force` argument is True, we
                # ignore `min_cycle_duration`.
                # If the `time` argument is not none, we were invoked for
                # keep-alive purposes, and `min_cycle_duration` is irrelevant.
                if self._min_cycle_duration:
                    if self._is_device_active:
                        current_state = STATE_ON
                    else:
                        current_state = STATE_OFF
                    long_enough = condition.state(
                        self.hass,
                        self._switch_entity_id,
                        current_state,
                        self._min_cycle_duration,
                    )
                    if not long_enough:
                        return

            if force:
                # Ignore the tolerance when switched on manually
                dry_tolerance = 0
                wet_tolerance = 0
            else:
                dry_tolerance = self._dry_tolerance
                wet_tolerance = self._wet_tolerance

            too_dry = self._target_humidity - self._cur_humidity >= dry_tolerance
            too_wet = self._cur_humidity - self._target_humidity >= wet_tolerance
            if self._is_device_active:
                if (
                    self._device_class == HumidifierDeviceClass.HUMIDIFIER and too_wet
                ) or (
                    self._device_class == HumidifierDeviceClass.DEHUMIDIFIER and too_dry
                ):
                    _LOGGER.info("Turning off humidifier %s", self._switch_entity_id)
                    await self._async_device_turn_off()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    await self._async_device_turn_on()
            else:
                if (
                    self._device_class == HumidifierDeviceClass.HUMIDIFIER and too_dry
                ) or (
                    self._device_class == HumidifierDeviceClass.DEHUMIDIFIER and too_wet
                ):
                    _LOGGER.info("Turning on humidifier %s", self._switch_entity_id)
                    await self._async_device_turn_on()
                elif time is not None:
                    # The time argument is passed only in keep-alive case
                    await self._async_device_turn_off()
示例#24
0
    async def _async_control_heating(self, time=None, force=False):
        """Check if we need to turn heating on or off."""
        _LOGGER.debug("Check if we need to turn heating on or off")
        async with self._temp_lock:
            if not self._active and None not in (self._cur_temp,
                                                 self._target_temp):
                self._active = True
                _LOGGER.info(
                    "Obtained current and target temperature. "
                    "Generic thermostat active. %s, %s",
                    self._cur_temp,
                    self._target_temp,
                )

            if not self._active or self._hvac_mode == HVAC_MODE_OFF:
                return

            #CCL
            next_state = self._hvac_mode
            #End CCL

            if not force and time is None:
                # If the `force` argument is True, we
                # ignore `min_cycle_duration`.
                # If the `time` argument is not none, we were invoked for
                # keep-alive purposes, and `min_cycle_duration` is irrelevant.
                if self.min_cycle_duration:
                    if self._is_device_active:
                        current_state = STATE_ON
                    else:
                        current_state = HVAC_MODE_OFF
                    #CCL
                    if next_state == HVAC_MODE_IDLE:
                        next_current_state = HVAC_MODE_OFF
                    else:
                        next_current_state = STATE_ON

                    if current_state != next_current_state:
                        _LOGGER.debug(
                            "State : %s since %s",
                            self.hass.states.get(self._heat_entity_id).state,
                            self.hass.states.get(
                                self._heat_entity_id).last_changed)
                        #End CCL
                        long_enough = condition.state(
                            self.hass,
                            self.heater_entity_id,
                            current_state,
                            self.min_cycle_duration,
                        )
                        if not long_enough:
                            _LOGGER.debug(
                                "Min cycle duration not reach for heater %s",
                                self._heat_entity_id)
                            return

            too_cold = self._target_temp - self._cur_temp >= self._cold_tolerance
            too_hot = self._cur_temp - self._target_temp >= self._hot_tolerance

            # CCL : Replace fallowing by ...
            #if self._is_device_active:
            #    if (self.ac_mode and too_cold) or (not self.ac_mode and too_hot):
            #        _LOGGER.info("Turning off heater %s", self.heater_entity_id)
            #        await self._async_heater_turn_off()
            #    elif time is not None:
            #        # The time argument is passed only in keep-alive case
            #        await self._async_heater_turn_on()
            #else:
            #    if (self.ac_mode and too_hot) or (not self.ac_mode and too_cold):
            #        _LOGGER.info("Turning on heater %s", self.heater_entity_id)
            #        await self._async_heater_turn_on()
            #    elif time is not None:
            #        # The time argument is passed only in keep-alive case
            #        await self._async_heater_turn_off()
            if self._is_device_active:
                if too_hot:
                    next_state = HVAC_MODE_IDLE
                else:
                    _LOGGER.debug("Evaluate regulation mode for heater %s",
                                  self.heater_entity_id)
                    regulation_mode = self._cur_temp >= \
                        self._target_temp - self._regulation_delta
                    if regulation_mode:
                        next_state = HVAC_MODE_REGULATION
                    else:
                        next_state = HVAC_MODE_COOL
            else:
                if too_cold:
                    next_state = HVAC_MODE_COOL
                else:
                    next_state = HVAC_MODE_IDLE
            _LOGGER.debug(
                "Next state for heater %s : %s (force: %s, time: %s)",
                self.heater_entity_id, next_state, force, time)
            await self._async_set_heating_mode(next_state, time)
示例#25
0
 def test_is_state(hass: HomeAssistant,
                   variables: TemplateVarsType) -> bool:
     """Test if an entity is a certain state."""
     return condition.state(hass, config[CONF_ENTITY_ID],
                            config[CONF_OPTION], config.get(CONF_FOR))
示例#26
0
 def test_is_on(hass: HomeAssistant, variables: TemplateVarsType) -> bool:
     """Test if an entity is on."""
     return condition.state(hass, config[ATTR_ENTITY_ID], STATE_ON)
    async def _async_control_heating(self, time=None, force=False):
        """Check if we need to turn heating on or off."""
        async with self._temp_lock:
            if not self._active and None not in (self._cur_temp, self._target_temp):
                self._active = True
                _LOGGER.info(
                    "Obtained current and target temperature. "
                    "Dual smart thermostat active. %s, %s",
                    self._cur_temp,
                    self._target_temp,
                )

            if not self._active or self._hvac_mode == HVAC_MODE_OFF:
                return

            if not force and time is None:
                # If the `force` argument is True, we
                # ignore `min_cycle_duration`.
                # If the `time` argument is not none, we were invoked for
                # keep-alive purposes, and `min_cycle_duration` is irrelevant.
                if self.min_cycle_duration:
                    if self._is_device_active:
                        current_state = STATE_ON
                    else:
                        current_state = HVAC_MODE_OFF
                    long_enough = condition.state(
                        self.hass,
                        self.heater_entity_id,
                        current_state,
                        self.min_cycle_duration,
                    )
                    if not long_enough:
                        return

            too_cold = self._target_temp >= self._cur_temp + self._cold_tolerance
            too_hot = self._cur_temp >= self._target_temp + self._hot_tolerance

            if self._is_device_active:
                if (
                    (self.ac_mode and too_cold)
                    or (not self.ac_mode and too_hot)
                    or (not self.ac_mode and self._is_floor_hot)
                    or self._is_opening_open
                ):
                    _LOGGER.info("Turning off heater %s", self.heater_entity_id)
                    await self._async_heater_turn_off()
                elif (
                    time is not None
                    and not self._is_opening_open
                    and not self._is_floor_hot
                ):
                    # The time argument is passed only in keep-alive case
                    _LOGGER.info(
                        "Keep-alive - Turning on heater (from active) %s",
                        self.heater_entity_id,
                    )
                    await self._async_heater_turn_on()
            else:
                if (self.ac_mode and too_hot and not self._is_opening_open) or (
                    not self.ac_mode
                    and too_cold
                    and not self._is_opening_open
                    and not self._is_floor_hot
                ):
                    _LOGGER.info(
                        "Turning on heater (from inactive) %s", self.heater_entity_id
                    )
                    await self._async_heater_turn_on()
                elif time is not None or self._is_opening_open or self._is_floor_hot:
                    # The time argument is passed only in keep-alive case
                    _LOGGER.info(
                        "Keep-alive - Turning off heater %s", self.heater_entity_id
                    )
                    await self._async_heater_turn_off()
示例#28
0
 def test_is_state(hass: HomeAssistant,
                   variables: TemplateVarsType) -> bool:
     """Test if an entity is a certain state."""
     return condition.state(hass, config[ATTR_ENTITY_ID], state)
示例#29
0
    async def _async_control_heating(self, force=False):
        _LOGGER.debug("running _async_control_heating")
        """Check if we need to turn heating on or off."""
        async with self._temp_lock:
            if not self._active and None not in (self._cur_temp,
                                                 self._target_temp_high,
                                                 self._target_temp_low):
                self._active = True
                _LOGGER.info(
                    "Obtained current and target temperature. "
                    "Generic thermostat active. %s, %s, %s", self._cur_temp,
                    self._target_temp_low, self._target_temp_high)

            if not self._active:
                _LOGGER.debug("not active")
                return

            if self._hvac_mode == HVAC_MODE_OFF:
                _LOGGER.debug("Mode is off")
                return

            if not force:
                _LOGGER.debug("force = false")
                # If the `force` argument is True, we
                # ignore `min_cycle_duration`.
                if self.min_cycle_duration:
                    _LOGGER.debug("min_cycle_duration = false")
                    entity = self.cooler_entity_id if self._hvac_mode == HVAC_MODE_COOL else self.heater_entity_id

                    if self._is_device_active:
                        current_state = STATE_ON
                    else:
                        current_state = HVAC_MODE_OFF
                    long_enough = condition.state(
                        self.hass,
                        entity,
                        current_state,
                        self.min_cycle_duration,
                    )
                    if not long_enough:
                        _LOGGER.debug("not long enough")
                        return

            too_cold = self._target_temp_low - self._cur_temp >= self._cold_tolerance
            too_hot = self._cur_temp - self._target_temp_high >= self._hot_tolerance
            cool_enough = self._target_temp_high - self._cur_temp >= self._hot_tolerance
            warm_enough = self._cur_temp - self._target_temp_low >= self._cold_tolerance

            _LOGGER.debug(
                "States: too_cold=%s too_hot=%s cool_enough=%s warm_enough=%s",
                too_cold, too_hot, cool_enough, warm_enough)
            _LOGGER.debug("Mode: %s, %s", self._hvac_mode,
                          self._is_device_active)
            if self._is_device_active:  # when to turn off
                if cool_enough and (self._hvac_mode == HVAC_MODE_COOL
                                    or self._hvac_mode == HVAC_MODE_HEAT_COOL):
                    _LOGGER.info("Turning off cooler %s",
                                 self.cooler_entity_id)
                    await self._async_cooler_turn_off()
                elif warm_enough and (self._hvac_mode == HVAC_MODE_HEAT or
                                      self._hvac_mode == HVAC_MODE_HEAT_COOL):
                    _LOGGER.info("Turning off heater %s",
                                 self.heater_entity_id)
                    await self._async_heater_turn_off()
            else:  # when to turn on
                if too_hot and (self._hvac_mode == HVAC_MODE_COOL
                                or self._hvac_mode == HVAC_MODE_HEAT_COOL):
                    _LOGGER.info("Turning on cooler %s", self.cooler_entity_id)
                    await self._async_cooler_turn_on()
                elif too_cold and (self._hvac_mode == HVAC_MODE_HEAT
                                   or self._hvac_mode == HVAC_MODE_HEAT_COOL):
                    _LOGGER.info("Turning on heater %s", self.heater_entity_id)
                    await self._async_heater_turn_on()