From f479eae714f54e38eae943ea0ed355312600dabb Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino Date: Wed, 1 Jul 2020 14:08:55 -0300 Subject: [PATCH] Revert "Climate bang bang enhancements (#1061)" (#1106) This reverts commit 0082c5b4597dbbe75237a14f471beefc6ee86352. --- .../bang_bang/bang_bang_climate.cpp | 520 +++--------------- .../components/bang_bang/bang_bang_climate.h | 248 ++------- esphome/components/bang_bang/climate.py | 235 +------- esphome/const.py | 22 - tests/test3.yaml | 43 -- 5 files changed, 123 insertions(+), 945 deletions(-) diff --git a/esphome/components/bang_bang/bang_bang_climate.cpp b/esphome/components/bang_bang/bang_bang_climate.cpp index 29f08fbd89..cf527988fe 100644 --- a/esphome/components/bang_bang/bang_bang_climate.cpp +++ b/esphome/components/bang_bang/bang_bang_climate.cpp @@ -9,393 +9,136 @@ static const char *TAG = "bang_bang.climate"; void BangBangClimate::setup() { this->sensor_->add_on_state_callback([this](float state) { this->current_temperature = state; - // required action may have changed, recompute, refresh - this->switch_to_action_(compute_action_()); - // current temperature and possibly action changed, so publish the new state + // control may have changed, recompute + this->compute_state_(); + // current temperature changed, publish state this->publish_state(); }); this->current_temperature = this->sensor_->state; - // restore all climate data, if possible + // restore set points auto restore = this->restore_state_(); if (restore.has_value()) { restore->to_call(this).perform(); } else { - // restore from defaults, change_away handles temps for us + // restore from defaults, change_away handles those for us this->mode = climate::CLIMATE_MODE_AUTO; this->change_away_(false); } - // refresh the climate action based on the restored settings - this->switch_to_action_(compute_action_()); - this->setup_complete_ = true; - this->publish_state(); -} -void BangBangClimate::refresh() { - this->switch_to_mode_(this->mode); - this->switch_to_action_(compute_action_()); - this->switch_to_fan_mode_(this->fan_mode); - this->switch_to_swing_mode_(this->swing_mode); - this->publish_state(); } void BangBangClimate::control(const climate::ClimateCall &call) { if (call.get_mode().has_value()) this->mode = *call.get_mode(); - if (call.get_fan_mode().has_value()) - this->fan_mode = *call.get_fan_mode(); - if (call.get_swing_mode().has_value()) - this->swing_mode = *call.get_swing_mode(); - if (call.get_target_temperature().has_value()) - this->target_temperature = *call.get_target_temperature(); if (call.get_target_temperature_low().has_value()) this->target_temperature_low = *call.get_target_temperature_low(); if (call.get_target_temperature_high().has_value()) this->target_temperature_high = *call.get_target_temperature_high(); - if (call.get_away().has_value()) { - // setup_complete_ blocks modifying/resetting the temps immediately after boot - if (this->setup_complete_) { - this->change_away_(*call.get_away()); - } else { - this->away = *call.get_away(); - } - } - // set point validation - if (this->supports_two_points_) { - if (this->target_temperature_low < this->get_traits().get_visual_min_temperature()) - this->target_temperature_low = this->get_traits().get_visual_min_temperature(); - if (this->target_temperature_high > this->get_traits().get_visual_max_temperature()) - this->target_temperature_high = this->get_traits().get_visual_max_temperature(); - if (this->target_temperature_high < this->target_temperature_low) - this->target_temperature_high = this->target_temperature_low; - } else { - if (this->target_temperature < this->get_traits().get_visual_min_temperature()) - this->target_temperature = this->get_traits().get_visual_min_temperature(); - if (this->target_temperature > this->get_traits().get_visual_max_temperature()) - this->target_temperature = this->get_traits().get_visual_max_temperature(); - } - // make any changes happen - refresh(); + if (call.get_away().has_value()) + this->change_away_(*call.get_away()); + + this->compute_state_(); + this->publish_state(); } climate::ClimateTraits BangBangClimate::traits() { auto traits = climate::ClimateTraits(); traits.set_supports_current_temperature(true); - traits.set_supports_auto_mode(this->supports_auto_); + traits.set_supports_auto_mode(true); traits.set_supports_cool_mode(this->supports_cool_); - traits.set_supports_dry_mode(this->supports_dry_); - traits.set_supports_fan_only_mode(this->supports_fan_only_); traits.set_supports_heat_mode(this->supports_heat_); - traits.set_supports_fan_mode_on(this->supports_fan_mode_on_); - traits.set_supports_fan_mode_off(this->supports_fan_mode_off_); - traits.set_supports_fan_mode_auto(this->supports_fan_mode_auto_); - traits.set_supports_fan_mode_low(this->supports_fan_mode_low_); - traits.set_supports_fan_mode_medium(this->supports_fan_mode_medium_); - traits.set_supports_fan_mode_high(this->supports_fan_mode_high_); - traits.set_supports_fan_mode_middle(this->supports_fan_mode_middle_); - traits.set_supports_fan_mode_focus(this->supports_fan_mode_focus_); - traits.set_supports_fan_mode_diffuse(this->supports_fan_mode_diffuse_); - traits.set_supports_swing_mode_both(this->supports_swing_mode_both_); - traits.set_supports_swing_mode_horizontal(this->supports_swing_mode_horizontal_); - traits.set_supports_swing_mode_off(this->supports_swing_mode_off_); - traits.set_supports_swing_mode_vertical(this->supports_swing_mode_vertical_); - traits.set_supports_two_point_target_temperature(this->supports_two_points_); + traits.set_supports_two_point_target_temperature(true); traits.set_supports_away(this->supports_away_); traits.set_supports_action(true); return traits; } -climate::ClimateAction BangBangClimate::compute_action_() { - climate::ClimateAction target_action = this->action; - if (this->supports_two_points_) { - if (isnan(this->current_temperature) || isnan(this->target_temperature_low) || - isnan(this->target_temperature_high) || isnan(this->hysteresis_)) - // if any control parameters are nan, go to OFF action (not IDLE!) - return climate::CLIMATE_ACTION_OFF; +void BangBangClimate::compute_state_() { + if (this->mode != climate::CLIMATE_MODE_AUTO) { + // in non-auto mode, switch directly to appropriate action + // - HEAT mode -> HEATING action + // - COOL mode -> COOLING action + // - OFF mode -> OFF action (not IDLE!) + this->switch_to_action_(static_cast(this->mode)); + return; + } + if (isnan(this->current_temperature) || isnan(this->target_temperature_low) || isnan(this->target_temperature_high)) { + // if any control parameters are nan, go to OFF action (not IDLE!) + this->switch_to_action_(climate::CLIMATE_ACTION_OFF); + return; + } + const bool too_cold = this->current_temperature < this->target_temperature_low; + const bool too_hot = this->current_temperature > this->target_temperature_high; - if (((this->action == climate::CLIMATE_ACTION_FAN) && (this->mode != climate::CLIMATE_MODE_FAN_ONLY)) || - ((this->action == climate::CLIMATE_ACTION_DRYING) && (this->mode != climate::CLIMATE_MODE_DRY))) { + climate::ClimateAction target_action; + if (too_cold) { + // too cold -> enable heating if possible, else idle + if (this->supports_heat_) + target_action = climate::CLIMATE_ACTION_HEATING; + else + target_action = climate::CLIMATE_ACTION_IDLE; + } else if (too_hot) { + // too hot -> enable cooling if possible, else idle + if (this->supports_cool_) + target_action = climate::CLIMATE_ACTION_COOLING; + else target_action = climate::CLIMATE_ACTION_IDLE; - } - - switch (this->mode) { - case climate::CLIMATE_MODE_FAN_ONLY: - if (this->supports_fan_only_) { - if (this->current_temperature > this->target_temperature_high + this->hysteresis_) - target_action = climate::CLIMATE_ACTION_FAN; - else if (this->current_temperature < this->target_temperature_high - this->hysteresis_) - if (this->action == climate::CLIMATE_ACTION_FAN) - target_action = climate::CLIMATE_ACTION_IDLE; - } - break; - case climate::CLIMATE_MODE_DRY: - target_action = climate::CLIMATE_ACTION_DRYING; - break; - case climate::CLIMATE_MODE_OFF: - target_action = climate::CLIMATE_ACTION_OFF; - break; - case climate::CLIMATE_MODE_AUTO: - case climate::CLIMATE_MODE_COOL: - case climate::CLIMATE_MODE_HEAT: - if (this->supports_cool_) { - if (this->current_temperature > this->target_temperature_high + this->hysteresis_) - target_action = climate::CLIMATE_ACTION_COOLING; - else if (this->current_temperature < this->target_temperature_high - this->hysteresis_) - if (this->action == climate::CLIMATE_ACTION_COOLING) - target_action = climate::CLIMATE_ACTION_IDLE; - } - if (this->supports_heat_) { - if (this->current_temperature < this->target_temperature_low - this->hysteresis_) - target_action = climate::CLIMATE_ACTION_HEATING; - else if (this->current_temperature > this->target_temperature_low + this->hysteresis_) - if (this->action == climate::CLIMATE_ACTION_HEATING) - target_action = climate::CLIMATE_ACTION_IDLE; - } - break; - default: - break; - } } else { - if (isnan(this->current_temperature) || isnan(this->target_temperature) || isnan(this->hysteresis_)) - // if any control parameters are nan, go to OFF action (not IDLE!) - return climate::CLIMATE_ACTION_OFF; - - if (((this->action == climate::CLIMATE_ACTION_FAN) && (this->mode != climate::CLIMATE_MODE_FAN_ONLY)) || - ((this->action == climate::CLIMATE_ACTION_DRYING) && (this->mode != climate::CLIMATE_MODE_DRY))) { + // neither too hot nor too cold -> in range + if (this->supports_cool_ && this->supports_heat_) { + // if supports both ends, go to idle action target_action = climate::CLIMATE_ACTION_IDLE; - } - - switch (this->mode) { - case climate::CLIMATE_MODE_FAN_ONLY: - if (this->supports_fan_only_) { - if (this->current_temperature > this->target_temperature + this->hysteresis_) - target_action = climate::CLIMATE_ACTION_FAN; - else if (this->current_temperature < this->target_temperature - this->hysteresis_) - if (this->action == climate::CLIMATE_ACTION_FAN) - target_action = climate::CLIMATE_ACTION_IDLE; - } - break; - case climate::CLIMATE_MODE_DRY: - target_action = climate::CLIMATE_ACTION_DRYING; - break; - case climate::CLIMATE_MODE_OFF: - target_action = climate::CLIMATE_ACTION_OFF; - break; - case climate::CLIMATE_MODE_COOL: - if (this->supports_cool_) { - if (this->current_temperature > this->target_temperature + this->hysteresis_) - target_action = climate::CLIMATE_ACTION_COOLING; - else if (this->current_temperature < this->target_temperature - this->hysteresis_) - if (this->action == climate::CLIMATE_ACTION_COOLING) - target_action = climate::CLIMATE_ACTION_IDLE; - } - case climate::CLIMATE_MODE_HEAT: - if (this->supports_heat_) { - if (this->current_temperature < this->target_temperature - this->hysteresis_) - target_action = climate::CLIMATE_ACTION_HEATING; - else if (this->current_temperature > this->target_temperature + this->hysteresis_) - if (this->action == climate::CLIMATE_ACTION_HEATING) - target_action = climate::CLIMATE_ACTION_IDLE; - } - break; - default: - break; + } else { + // else use current mode and don't change (hysteresis) + target_action = this->action; } } - // do not switch to an action that isn't enabled per the active climate mode - if ((this->mode == climate::CLIMATE_MODE_COOL) && (target_action == climate::CLIMATE_ACTION_HEATING)) - target_action = climate::CLIMATE_ACTION_IDLE; - if ((this->mode == climate::CLIMATE_MODE_HEAT) && (target_action == climate::CLIMATE_ACTION_COOLING)) - target_action = climate::CLIMATE_ACTION_IDLE; - return target_action; + this->switch_to_action_(target_action); } void BangBangClimate::switch_to_action_(climate::ClimateAction action) { - // setup_complete_ helps us ensure an action is called immediately after boot - if ((action == this->action) && this->setup_complete_) + if (action == this->action) // already in target mode return; - if (((action == climate::CLIMATE_ACTION_OFF && this->action == climate::CLIMATE_ACTION_IDLE) || - (action == climate::CLIMATE_ACTION_IDLE && this->action == climate::CLIMATE_ACTION_OFF)) && - this->setup_complete_) { + if ((action == climate::CLIMATE_ACTION_OFF && this->action == climate::CLIMATE_ACTION_IDLE) || + (action == climate::CLIMATE_ACTION_IDLE && this->action == climate::CLIMATE_ACTION_OFF)) { // switching from OFF to IDLE or vice-versa // these only have visual difference. OFF means user manually disabled, // IDLE means it's in auto mode but value is in target range. this->action = action; + this->publish_state(); return; } - if (this->prev_action_trigger_ != nullptr) { - this->prev_action_trigger_->stop(); - this->prev_action_trigger_ = nullptr; + if (this->prev_trigger_ != nullptr) { + this->prev_trigger_->stop(); + this->prev_trigger_ = nullptr; } - Trigger<> *trig = this->idle_action_trigger_; + Trigger<> *trig; switch (action) { case climate::CLIMATE_ACTION_OFF: case climate::CLIMATE_ACTION_IDLE: - // trig = this->idle_action_trigger_; + trig = this->idle_trigger_; break; case climate::CLIMATE_ACTION_COOLING: - trig = this->cool_action_trigger_; + trig = this->cool_trigger_; break; case climate::CLIMATE_ACTION_HEATING: - trig = this->heat_action_trigger_; - break; - case climate::CLIMATE_ACTION_FAN: - trig = this->fan_only_action_trigger_; - break; - case climate::CLIMATE_ACTION_DRYING: - trig = this->dry_action_trigger_; + trig = this->heat_trigger_; break; default: - // we cannot report an invalid mode back to HA (even if it asked for one) - // and must assume some valid value - action = climate::CLIMATE_ACTION_OFF; - // trig = this->idle_action_trigger_; + trig = nullptr; } assert(trig != nullptr); trig->trigger(); this->action = action; - this->prev_action_trigger_ = trig; -} -void BangBangClimate::switch_to_fan_mode_(climate::ClimateFanMode fan_mode) { - // setup_complete_ helps us ensure an action is called immediately after boot - if ((fan_mode == this->prev_fan_mode_) && this->setup_complete_) - // already in target mode - return; - - if (this->prev_fan_mode_trigger_ != nullptr) { - this->prev_fan_mode_trigger_->stop(); - this->prev_fan_mode_trigger_ = nullptr; - } - Trigger<> *trig = this->fan_mode_auto_trigger_; - switch (fan_mode) { - case climate::CLIMATE_FAN_ON: - trig = this->fan_mode_on_trigger_; - break; - case climate::CLIMATE_FAN_OFF: - trig = this->fan_mode_off_trigger_; - break; - case climate::CLIMATE_FAN_AUTO: - // trig = this->fan_mode_auto_trigger_; - break; - case climate::CLIMATE_FAN_LOW: - trig = this->fan_mode_low_trigger_; - break; - case climate::CLIMATE_FAN_MEDIUM: - trig = this->fan_mode_medium_trigger_; - break; - case climate::CLIMATE_FAN_HIGH: - trig = this->fan_mode_high_trigger_; - break; - case climate::CLIMATE_FAN_MIDDLE: - trig = this->fan_mode_middle_trigger_; - break; - case climate::CLIMATE_FAN_FOCUS: - trig = this->fan_mode_focus_trigger_; - break; - case climate::CLIMATE_FAN_DIFFUSE: - trig = this->fan_mode_diffuse_trigger_; - break; - default: - // we cannot report an invalid mode back to HA (even if it asked for one) - // and must assume some valid value - fan_mode = climate::CLIMATE_FAN_AUTO; - // trig = this->fan_mode_auto_trigger_; - } - assert(trig != nullptr); - trig->trigger(); - this->fan_mode = fan_mode; - this->prev_fan_mode_ = fan_mode; - this->prev_fan_mode_trigger_ = trig; -} -void BangBangClimate::switch_to_mode_(climate::ClimateMode mode) { - // setup_complete_ helps us ensure an action is called immediately after boot - if ((mode == this->prev_mode_) && this->setup_complete_) - // already in target mode - return; - - if (this->prev_mode_trigger_ != nullptr) { - this->prev_mode_trigger_->stop(); - this->prev_mode_trigger_ = nullptr; - } - Trigger<> *trig = this->auto_mode_trigger_; - switch (mode) { - case climate::CLIMATE_MODE_OFF: - trig = this->off_mode_trigger_; - break; - case climate::CLIMATE_MODE_AUTO: - // trig = this->auto_mode_trigger_; - break; - case climate::CLIMATE_MODE_COOL: - trig = this->cool_mode_trigger_; - break; - case climate::CLIMATE_MODE_HEAT: - trig = this->heat_mode_trigger_; - break; - case climate::CLIMATE_MODE_FAN_ONLY: - trig = this->fan_only_mode_trigger_; - break; - case climate::CLIMATE_MODE_DRY: - trig = this->dry_mode_trigger_; - break; - default: - // we cannot report an invalid mode back to HA (even if it asked for one) - // and must assume some valid value - mode = climate::CLIMATE_MODE_AUTO; - // trig = this->auto_mode_trigger_; - } - assert(trig != nullptr); - trig->trigger(); - this->mode = mode; - this->prev_mode_ = mode; - this->prev_mode_trigger_ = trig; -} -void BangBangClimate::switch_to_swing_mode_(climate::ClimateSwingMode swing_mode) { - // setup_complete_ helps us ensure an action is called immediately after boot - if ((swing_mode == this->prev_swing_mode_) && this->setup_complete_) - // already in target mode - return; - - if (this->prev_swing_mode_trigger_ != nullptr) { - this->prev_swing_mode_trigger_->stop(); - this->prev_swing_mode_trigger_ = nullptr; - } - Trigger<> *trig = this->swing_mode_off_trigger_; - switch (swing_mode) { - case climate::CLIMATE_SWING_BOTH: - trig = this->swing_mode_both_trigger_; - break; - case climate::CLIMATE_SWING_HORIZONTAL: - trig = this->swing_mode_horizontal_trigger_; - break; - case climate::CLIMATE_SWING_OFF: - // trig = this->swing_mode_off_trigger_; - break; - case climate::CLIMATE_SWING_VERTICAL: - trig = this->swing_mode_vertical_trigger_; - break; - default: - // we cannot report an invalid mode back to HA (even if it asked for one) - // and must assume some valid value - swing_mode = climate::CLIMATE_SWING_OFF; - // trig = this->swing_mode_off_trigger_; - } - assert(trig != nullptr); - trig->trigger(); - this->swing_mode = swing_mode; - this->prev_swing_mode_ = swing_mode; - this->prev_swing_mode_trigger_ = trig; + this->prev_trigger_ = trig; + this->publish_state(); } void BangBangClimate::change_away_(bool away) { if (!away) { - if (this->supports_two_points_) { - this->target_temperature_low = this->normal_config_.default_temperature_low; - this->target_temperature_high = this->normal_config_.default_temperature_high; - } else - this->target_temperature = this->normal_config_.default_temperature; + this->target_temperature_low = this->normal_config_.default_temperature_low; + this->target_temperature_high = this->normal_config_.default_temperature_high; } else { - if (this->supports_two_points_) { - this->target_temperature_low = this->away_config_.default_temperature_low; - this->target_temperature_high = this->away_config_.default_temperature_high; - } else - this->target_temperature = this->away_config_.default_temperature; + this->target_temperature_low = this->away_config_.default_temperature_low; + this->target_temperature_high = this->away_config_.default_temperature_high; } this->away = away; } @@ -407,142 +150,23 @@ void BangBangClimate::set_away_config(const BangBangClimateTargetTempConfig &awa this->away_config_ = away_config; } BangBangClimate::BangBangClimate() - : cool_action_trigger_(new Trigger<>()), - cool_mode_trigger_(new Trigger<>()), - dry_action_trigger_(new Trigger<>()), - dry_mode_trigger_(new Trigger<>()), - heat_action_trigger_(new Trigger<>()), - heat_mode_trigger_(new Trigger<>()), - auto_mode_trigger_(new Trigger<>()), - idle_action_trigger_(new Trigger<>()), - off_mode_trigger_(new Trigger<>()), - fan_only_action_trigger_(new Trigger<>()), - fan_only_mode_trigger_(new Trigger<>()), - fan_mode_on_trigger_(new Trigger<>()), - fan_mode_off_trigger_(new Trigger<>()), - fan_mode_auto_trigger_(new Trigger<>()), - fan_mode_low_trigger_(new Trigger<>()), - fan_mode_medium_trigger_(new Trigger<>()), - fan_mode_high_trigger_(new Trigger<>()), - fan_mode_middle_trigger_(new Trigger<>()), - fan_mode_focus_trigger_(new Trigger<>()), - fan_mode_diffuse_trigger_(new Trigger<>()), - swing_mode_both_trigger_(new Trigger<>()), - swing_mode_off_trigger_(new Trigger<>()), - swing_mode_horizontal_trigger_(new Trigger<>()), - swing_mode_vertical_trigger_(new Trigger<>()) {} -void BangBangClimate::set_hysteresis(float hysteresis) { this->hysteresis_ = hysteresis; } + : idle_trigger_(new Trigger<>()), cool_trigger_(new Trigger<>()), heat_trigger_(new Trigger<>()) {} void BangBangClimate::set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; } -void BangBangClimate::set_supports_auto(bool supports_auto) { this->supports_auto_ = supports_auto; } +Trigger<> *BangBangClimate::get_idle_trigger() const { return this->idle_trigger_; } +Trigger<> *BangBangClimate::get_cool_trigger() const { return this->cool_trigger_; } void BangBangClimate::set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; } -void BangBangClimate::set_supports_dry(bool supports_dry) { this->supports_dry_ = supports_dry; } -void BangBangClimate::set_supports_fan_only(bool supports_fan_only) { this->supports_fan_only_ = supports_fan_only; } +Trigger<> *BangBangClimate::get_heat_trigger() const { return this->heat_trigger_; } void BangBangClimate::set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; } -void BangBangClimate::set_supports_fan_mode_on(bool supports_fan_mode_on) { - this->supports_fan_mode_on_ = supports_fan_mode_on; -} -void BangBangClimate::set_supports_fan_mode_off(bool supports_fan_mode_off) { - this->supports_fan_mode_off_ = supports_fan_mode_off; -} -void BangBangClimate::set_supports_fan_mode_auto(bool supports_fan_mode_auto) { - this->supports_fan_mode_auto_ = supports_fan_mode_auto; -} -void BangBangClimate::set_supports_fan_mode_low(bool supports_fan_mode_low) { - this->supports_fan_mode_low_ = supports_fan_mode_low; -} -void BangBangClimate::set_supports_fan_mode_medium(bool supports_fan_mode_medium) { - this->supports_fan_mode_medium_ = supports_fan_mode_medium; -} -void BangBangClimate::set_supports_fan_mode_high(bool supports_fan_mode_high) { - this->supports_fan_mode_high_ = supports_fan_mode_high; -} -void BangBangClimate::set_supports_fan_mode_middle(bool supports_fan_mode_middle) { - this->supports_fan_mode_middle_ = supports_fan_mode_middle; -} -void BangBangClimate::set_supports_fan_mode_focus(bool supports_fan_mode_focus) { - this->supports_fan_mode_focus_ = supports_fan_mode_focus; -} -void BangBangClimate::set_supports_fan_mode_diffuse(bool supports_fan_mode_diffuse) { - this->supports_fan_mode_diffuse_ = supports_fan_mode_diffuse; -} -void BangBangClimate::set_supports_swing_mode_both(bool supports_swing_mode_both) { - this->supports_swing_mode_both_ = supports_swing_mode_both; -} -void BangBangClimate::set_supports_swing_mode_off(bool supports_swing_mode_off) { - this->supports_swing_mode_off_ = supports_swing_mode_off; -} -void BangBangClimate::set_supports_swing_mode_horizontal(bool supports_swing_mode_horizontal) { - this->supports_swing_mode_horizontal_ = supports_swing_mode_horizontal; -} -void BangBangClimate::set_supports_swing_mode_vertical(bool supports_swing_mode_vertical) { - this->supports_swing_mode_vertical_ = supports_swing_mode_vertical; -} -void BangBangClimate::set_supports_two_points(bool supports_two_points) { - this->supports_two_points_ = supports_two_points; -} -Trigger<> *BangBangClimate::get_cool_action_trigger() const { return this->cool_action_trigger_; } -Trigger<> *BangBangClimate::get_dry_action_trigger() const { return this->dry_action_trigger_; } -Trigger<> *BangBangClimate::get_fan_only_action_trigger() const { return this->fan_only_action_trigger_; } -Trigger<> *BangBangClimate::get_heat_action_trigger() const { return this->heat_action_trigger_; } -Trigger<> *BangBangClimate::get_idle_action_trigger() const { return this->idle_action_trigger_; } -Trigger<> *BangBangClimate::get_auto_mode_trigger() const { return this->auto_mode_trigger_; } -Trigger<> *BangBangClimate::get_cool_mode_trigger() const { return this->cool_mode_trigger_; } -Trigger<> *BangBangClimate::get_dry_mode_trigger() const { return this->dry_mode_trigger_; } -Trigger<> *BangBangClimate::get_fan_only_mode_trigger() const { return this->fan_only_mode_trigger_; } -Trigger<> *BangBangClimate::get_heat_mode_trigger() const { return this->heat_mode_trigger_; } -Trigger<> *BangBangClimate::get_off_mode_trigger() const { return this->off_mode_trigger_; } -Trigger<> *BangBangClimate::get_fan_mode_on_trigger() const { return this->fan_mode_on_trigger_; } -Trigger<> *BangBangClimate::get_fan_mode_off_trigger() const { return this->fan_mode_off_trigger_; } -Trigger<> *BangBangClimate::get_fan_mode_auto_trigger() const { return this->fan_mode_auto_trigger_; } -Trigger<> *BangBangClimate::get_fan_mode_low_trigger() const { return this->fan_mode_low_trigger_; } -Trigger<> *BangBangClimate::get_fan_mode_medium_trigger() const { return this->fan_mode_medium_trigger_; } -Trigger<> *BangBangClimate::get_fan_mode_high_trigger() const { return this->fan_mode_high_trigger_; } -Trigger<> *BangBangClimate::get_fan_mode_middle_trigger() const { return this->fan_mode_middle_trigger_; } -Trigger<> *BangBangClimate::get_fan_mode_focus_trigger() const { return this->fan_mode_focus_trigger_; } -Trigger<> *BangBangClimate::get_fan_mode_diffuse_trigger() const { return this->fan_mode_diffuse_trigger_; } -Trigger<> *BangBangClimate::get_swing_mode_both_trigger() const { return this->swing_mode_both_trigger_; } -Trigger<> *BangBangClimate::get_swing_mode_off_trigger() const { return this->swing_mode_off_trigger_; } -Trigger<> *BangBangClimate::get_swing_mode_horizontal_trigger() const { return this->swing_mode_horizontal_trigger_; } -Trigger<> *BangBangClimate::get_swing_mode_vertical_trigger() const { return this->swing_mode_vertical_trigger_; } void BangBangClimate::dump_config() { LOG_CLIMATE("", "Bang Bang Climate", this); - if (this->supports_heat_) - ESP_LOGCONFIG(TAG, " Default Target Temperature Low: %.1f°C", this->normal_config_.default_temperature_low); - if ((this->supports_cool_) || (this->supports_fan_only_)) - ESP_LOGCONFIG(TAG, " Default Target Temperature High: %.1f°C", this->normal_config_.default_temperature_high); - ESP_LOGCONFIG(TAG, " Hysteresis: %.1f°C", this->hysteresis_); - ESP_LOGCONFIG(TAG, " Supports AUTO: %s", YESNO(this->supports_auto_)); - ESP_LOGCONFIG(TAG, " Supports COOL: %s", YESNO(this->supports_cool_)); - ESP_LOGCONFIG(TAG, " Supports DRY: %s", YESNO(this->supports_dry_)); - ESP_LOGCONFIG(TAG, " Supports FAN_ONLY: %s", YESNO(this->supports_fan_only_)); ESP_LOGCONFIG(TAG, " Supports HEAT: %s", YESNO(this->supports_heat_)); - ESP_LOGCONFIG(TAG, " Supports FAN MODE ON: %s", YESNO(this->supports_fan_mode_on_)); - ESP_LOGCONFIG(TAG, " Supports FAN MODE OFF: %s", YESNO(this->supports_fan_mode_off_)); - ESP_LOGCONFIG(TAG, " Supports FAN MODE AUTO: %s", YESNO(this->supports_fan_mode_auto_)); - ESP_LOGCONFIG(TAG, " Supports FAN MODE LOW: %s", YESNO(this->supports_fan_mode_low_)); - ESP_LOGCONFIG(TAG, " Supports FAN MODE MEDIUM: %s", YESNO(this->supports_fan_mode_medium_)); - ESP_LOGCONFIG(TAG, " Supports FAN MODE HIGH: %s", YESNO(this->supports_fan_mode_high_)); - ESP_LOGCONFIG(TAG, " Supports FAN MODE MIDDLE: %s", YESNO(this->supports_fan_mode_middle_)); - ESP_LOGCONFIG(TAG, " Supports FAN MODE FOCUS: %s", YESNO(this->supports_fan_mode_focus_)); - ESP_LOGCONFIG(TAG, " Supports FAN MODE DIFFUSE: %s", YESNO(this->supports_fan_mode_diffuse_)); - ESP_LOGCONFIG(TAG, " Supports SWING MODE BOTH: %s", YESNO(this->supports_swing_mode_both_)); - ESP_LOGCONFIG(TAG, " Supports SWING MODE OFF: %s", YESNO(this->supports_swing_mode_off_)); - ESP_LOGCONFIG(TAG, " Supports SWING MODE HORIZONTAL: %s", YESNO(this->supports_swing_mode_horizontal_)); - ESP_LOGCONFIG(TAG, " Supports SWING MODE VERTICAL: %s", YESNO(this->supports_swing_mode_vertical_)); - ESP_LOGCONFIG(TAG, " Supports TWO SET POINTS: %s", YESNO(this->supports_two_points_)); + ESP_LOGCONFIG(TAG, " Supports COOL: %s", YESNO(this->supports_cool_)); ESP_LOGCONFIG(TAG, " Supports AWAY mode: %s", YESNO(this->supports_away_)); - if (this->supports_away_) { - if (this->supports_heat_) - ESP_LOGCONFIG(TAG, " Away Default Target Temperature Low: %.1f°C", this->away_config_.default_temperature_low); - if ((this->supports_cool_) || (this->supports_fan_only_)) - ESP_LOGCONFIG(TAG, " Away Default Target Temperature High: %.1f°C", - this->away_config_.default_temperature_high); - } + ESP_LOGCONFIG(TAG, " Default Target Temperature Low: %.1f°C", this->normal_config_.default_temperature_low); + ESP_LOGCONFIG(TAG, " Default Target Temperature High: %.1f°C", this->normal_config_.default_temperature_high); } BangBangClimateTargetTempConfig::BangBangClimateTargetTempConfig() = default; -BangBangClimateTargetTempConfig::BangBangClimateTargetTempConfig(float default_temperature) - : default_temperature(default_temperature) {} BangBangClimateTargetTempConfig::BangBangClimateTargetTempConfig(float default_temperature_low, float default_temperature_high) : default_temperature_low(default_temperature_low), default_temperature_high(default_temperature_high) {} diff --git a/esphome/components/bang_bang/bang_bang_climate.h b/esphome/components/bang_bang/bang_bang_climate.h index fd2b0ce43a..84bcd51f34 100644 --- a/esphome/components/bang_bang/bang_bang_climate.h +++ b/esphome/components/bang_bang/bang_bang_climate.h @@ -11,13 +11,10 @@ namespace bang_bang { struct BangBangClimateTargetTempConfig { public: BangBangClimateTargetTempConfig(); - BangBangClimateTargetTempConfig(float default_temperature); BangBangClimateTargetTempConfig(float default_temperature_low, float default_temperature_high); - float default_temperature{NAN}; float default_temperature_low{NAN}; float default_temperature_high{NAN}; - float hysteresis{NAN}; }; class BangBangClimate : public climate::Climate, public Component { @@ -26,243 +23,62 @@ class BangBangClimate : public climate::Climate, public Component { void setup() override; void dump_config() override; - void set_hysteresis(float hysteresis); void set_sensor(sensor::Sensor *sensor); - void set_supports_auto(bool supports_auto); + Trigger<> *get_idle_trigger() const; + Trigger<> *get_cool_trigger() const; void set_supports_cool(bool supports_cool); - void set_supports_dry(bool supports_dry); - void set_supports_fan_only(bool supports_fan_only); + Trigger<> *get_heat_trigger() const; void set_supports_heat(bool supports_heat); - void set_supports_fan_mode_on(bool supports_fan_mode_on); - void set_supports_fan_mode_off(bool supports_fan_mode_off); - void set_supports_fan_mode_auto(bool supports_fan_mode_auto); - void set_supports_fan_mode_low(bool supports_fan_mode_low); - void set_supports_fan_mode_medium(bool supports_fan_mode_medium); - void set_supports_fan_mode_high(bool supports_fan_mode_high); - void set_supports_fan_mode_middle(bool supports_fan_mode_middle); - void set_supports_fan_mode_focus(bool supports_fan_mode_focus); - void set_supports_fan_mode_diffuse(bool supports_fan_mode_diffuse); - void set_supports_swing_mode_both(bool supports_swing_mode_both); - void set_supports_swing_mode_horizontal(bool supports_swing_mode_horizontal); - void set_supports_swing_mode_off(bool supports_swing_mode_off); - void set_supports_swing_mode_vertical(bool supports_swing_mode_vertical); - void set_supports_two_points(bool supports_two_points); - void set_normal_config(const BangBangClimateTargetTempConfig &normal_config); void set_away_config(const BangBangClimateTargetTempConfig &away_config); - Trigger<> *get_cool_action_trigger() const; - Trigger<> *get_dry_action_trigger() const; - Trigger<> *get_fan_only_action_trigger() const; - Trigger<> *get_heat_action_trigger() const; - Trigger<> *get_idle_action_trigger() const; - Trigger<> *get_auto_mode_trigger() const; - Trigger<> *get_cool_mode_trigger() const; - Trigger<> *get_dry_mode_trigger() const; - Trigger<> *get_fan_only_mode_trigger() const; - Trigger<> *get_heat_mode_trigger() const; - Trigger<> *get_off_mode_trigger() const; - Trigger<> *get_fan_mode_on_trigger() const; - Trigger<> *get_fan_mode_off_trigger() const; - Trigger<> *get_fan_mode_auto_trigger() const; - Trigger<> *get_fan_mode_low_trigger() const; - Trigger<> *get_fan_mode_medium_trigger() const; - Trigger<> *get_fan_mode_high_trigger() const; - Trigger<> *get_fan_mode_middle_trigger() const; - Trigger<> *get_fan_mode_focus_trigger() const; - Trigger<> *get_fan_mode_diffuse_trigger() const; - Trigger<> *get_swing_mode_both_trigger() const; - Trigger<> *get_swing_mode_horizontal_trigger() const; - Trigger<> *get_swing_mode_off_trigger() const; - Trigger<> *get_swing_mode_vertical_trigger() const; - /// Call triggers based on updated climate states (modes/actions) - void refresh(); - protected: /// Override control to change settings of the climate device. void control(const climate::ClimateCall &call) override; - /// Change the away setting, will reset target temperatures to defaults. void change_away_(bool away); - /// Return the traits of this controller. climate::ClimateTraits traits() override; - /// Re-compute the required action of this climate controller. - climate::ClimateAction compute_action_(); - - /// Switch the climate device to the given climate action. - void switch_to_action_(climate::ClimateAction action); - - /// Switch the climate device to the given climate fan mode. - void switch_to_fan_mode_(climate::ClimateFanMode fan_mode); + /// Re-compute the state of this climate controller. + void compute_state_(); /// Switch the climate device to the given climate mode. - void switch_to_mode_(climate::ClimateMode mode); - - /// Switch the climate device to the given climate swing mode. - void switch_to_swing_mode_(climate::ClimateSwingMode swing_mode); + void switch_to_action_(climate::ClimateAction action); /// The sensor used for getting the current temperature sensor::Sensor *sensor_{nullptr}; - - /// Whether the controller supports auto/cooling/drying/fanning/heating. - /// - /// A false value for any given attribute means that the controller has no such action - /// (for example a thermostat, where only heating and not-heating is possible). - bool supports_auto_{false}; + /** The trigger to call when the controller should switch to idle mode. + * + * In idle mode, the controller is assumed to have both heating and cooling disabled. + */ + Trigger<> *idle_trigger_; + /** The trigger to call when the controller should switch to cooling mode. + */ + Trigger<> *cool_trigger_; + /** Whether the controller supports cooling. + * + * A false value for this attribute means that the controller has no cooling action + * (for example a thermostat, where only heating and not-heating is possible). + */ bool supports_cool_{false}; - bool supports_dry_{false}; - bool supports_fan_only_{false}; + /** The trigger to call when the controller should switch to heating mode. + * + * A null value for this attribute means that the controller has no heating action + * For example window blinds, where only cooling (blinds closed) and not-cooling + * (blinds open) is possible. + */ + Trigger<> *heat_trigger_{nullptr}; bool supports_heat_{false}; + /** A reference to the trigger that was previously active. + * + * This is so that the previous trigger can be stopped before enabling a new one. + */ + Trigger<> *prev_trigger_{nullptr}; - /// Whether the controller supports turning on or off just the fan. - /// - /// A false value for either attribute means that the controller has no fan on/off action - /// (for example a thermostat, where independent control of the fan is not possible). - bool supports_fan_mode_on_{false}; - bool supports_fan_mode_off_{false}; - - /// Whether the controller supports fan auto mode. - /// - /// A false value for this attribute means that the controller has no fan-auto action - /// (for example a thermostat, where independent control of the fan is not possible). - bool supports_fan_mode_auto_{false}; - - /// Whether the controller supports various fan speeds and/or positions. - /// - /// A false value for any given attribute means that the controller has no such fan action. - bool supports_fan_mode_low_{false}; - bool supports_fan_mode_medium_{false}; - bool supports_fan_mode_high_{false}; - bool supports_fan_mode_middle_{false}; - bool supports_fan_mode_focus_{false}; - bool supports_fan_mode_diffuse_{false}; - - /// Whether the controller supports various swing modes. - /// - /// A false value for any given attribute means that the controller has no such swing mode. - bool supports_swing_mode_both_{false}; - bool supports_swing_mode_off_{false}; - bool supports_swing_mode_horizontal_{false}; - bool supports_swing_mode_vertical_{false}; - - /// Whether the controller supports two set points - /// - /// A false value means that the controller has no such support. - bool supports_two_points_{false}; - - /// Whether the controller supports an "away" mode - /// - /// A false value means that the controller has no such mode. - bool supports_away_{false}; - - /// The trigger to call when the controller should switch to cooling action/mode. - /// - /// A null value for this attribute means that the controller has no cooling action - /// For example electric heat, where only heating (power on) and not-heating - /// (power off) is possible. - Trigger<> *cool_action_trigger_{nullptr}; - Trigger<> *cool_mode_trigger_{nullptr}; - - /// The trigger to call when the controller should switch to dry (dehumidification) mode. - /// - /// In dry mode, the controller is assumed to have both heating and cooling disabled, - /// although the system may use its cooling mechanism to achieve drying. - Trigger<> *dry_action_trigger_{nullptr}; - Trigger<> *dry_mode_trigger_{nullptr}; - - /// The trigger to call when the controller should switch to heating action/mode. - /// - /// A null value for this attribute means that the controller has no heating action - /// For example window blinds, where only cooling (blinds closed) and not-cooling - /// (blinds open) is possible. - Trigger<> *heat_action_trigger_{nullptr}; - Trigger<> *heat_mode_trigger_{nullptr}; - - /// The trigger to call when the controller should switch to auto mode. - /// - /// In auto mode, the controller will enable heating/cooling as necessary and switch - /// to idle when the temperature is within the thresholds/set points. - Trigger<> *auto_mode_trigger_{nullptr}; - - /// The trigger to call when the controller should switch to idle action/off mode. - /// - /// In these actions/modes, the controller is assumed to have both heating and cooling disabled. - Trigger<> *idle_action_trigger_{nullptr}; - Trigger<> *off_mode_trigger_{nullptr}; - - /// The trigger to call when the controller should switch to fan-only action/mode. - /// - /// In fan-only mode, the controller is assumed to have both heating and cooling disabled. - /// The system should activate the fan only. - Trigger<> *fan_only_action_trigger_{nullptr}; - Trigger<> *fan_only_mode_trigger_{nullptr}; - - /// The trigger to call when the controller should switch on the fan. - Trigger<> *fan_mode_on_trigger_{nullptr}; - - /// The trigger to call when the controller should switch off the fan. - Trigger<> *fan_mode_off_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "auto" mode. - Trigger<> *fan_mode_auto_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "low" speed. - Trigger<> *fan_mode_low_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "medium" speed. - Trigger<> *fan_mode_medium_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "high" speed. - Trigger<> *fan_mode_high_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "middle" position. - Trigger<> *fan_mode_middle_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "focus" position. - Trigger<> *fan_mode_focus_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "diffuse" position. - Trigger<> *fan_mode_diffuse_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the swing mode to "both". - Trigger<> *swing_mode_both_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the swing mode to "off". - Trigger<> *swing_mode_off_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the swing mode to "horizontal". - Trigger<> *swing_mode_horizontal_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the swing mode to "vertical". - Trigger<> *swing_mode_vertical_trigger_{nullptr}; - - /// A reference to the trigger that was previously active. - /// - /// This is so that the previous trigger can be stopped before enabling a new one - /// for each climate category (mode, action, fan_mode, swing_mode). - Trigger<> *prev_action_trigger_{nullptr}; - Trigger<> *prev_fan_mode_trigger_{nullptr}; - Trigger<> *prev_mode_trigger_{nullptr}; - Trigger<> *prev_swing_mode_trigger_{nullptr}; - - /// Store previously-known states - /// - /// These are used to determine when a trigger/action needs to be called - climate::ClimateFanMode prev_fan_mode_{climate::CLIMATE_FAN_ON}; - climate::ClimateMode prev_mode_{climate::CLIMATE_MODE_OFF}; - climate::ClimateSwingMode prev_swing_mode_{climate::CLIMATE_SWING_OFF}; - - /// Temperature data for normal/home and away modes BangBangClimateTargetTempConfig normal_config_{}; + bool supports_away_{false}; BangBangClimateTargetTempConfig away_config_{}; - - /// Hysteresis value used for computing climate actions - float hysteresis_{0}; - - /// setup_complete_ blocks modifying/resetting the temps immediately after boot - bool setup_complete_{false}; }; } // namespace bang_bang diff --git a/esphome/components/bang_bang/climate.py b/esphome/components/bang_bang/climate.py index 75ec58404b..4ef811c55d 100644 --- a/esphome/components/bang_bang/climate.py +++ b/esphome/components/bang_bang/climate.py @@ -2,107 +2,27 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.components import climate, sensor -from esphome.const import CONF_AUTO_MODE, CONF_AWAY_CONFIG, CONF_COOL_ACTION, CONF_COOL_MODE, \ - CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_DRY_ACTION, \ - CONF_DRY_MODE, CONF_FAN_MODE_ON_ACTION, CONF_FAN_MODE_OFF_ACTION, CONF_FAN_MODE_AUTO_ACTION, \ - CONF_FAN_MODE_LOW_ACTION, CONF_FAN_MODE_MEDIUM_ACTION, CONF_FAN_MODE_HIGH_ACTION, \ - CONF_FAN_MODE_MIDDLE_ACTION, CONF_FAN_MODE_FOCUS_ACTION, CONF_FAN_MODE_DIFFUSE_ACTION, \ - CONF_FAN_ONLY_ACTION, CONF_FAN_ONLY_MODE, CONF_HEAT_ACTION, CONF_HEAT_MODE, CONF_HYSTERESIS, \ - CONF_ID, CONF_IDLE_ACTION, CONF_OFF_MODE, CONF_SENSOR, CONF_SWING_BOTH_ACTION, \ - CONF_SWING_HORIZONTAL_ACTION, CONF_SWING_OFF_ACTION, CONF_SWING_VERTICAL_ACTION +from esphome.const import CONF_AWAY_CONFIG, CONF_COOL_ACTION, \ + CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION, \ + CONF_ID, CONF_IDLE_ACTION, CONF_SENSOR bang_bang_ns = cg.esphome_ns.namespace('bang_bang') BangBangClimate = bang_bang_ns.class_('BangBangClimate', climate.Climate, cg.Component) BangBangClimateTargetTempConfig = bang_bang_ns.struct('BangBangClimateTargetTempConfig') - -def validate_bangbang(config): - # verify corresponding climate action action exists for any defined climate mode action - if CONF_COOL_MODE in config and CONF_COOL_ACTION not in config: - raise cv.Invalid("{} must be defined to use {}".format(CONF_COOL_ACTION, CONF_COOL_MODE)) - if CONF_DRY_MODE in config and CONF_DRY_ACTION not in config: - raise cv.Invalid("{} must be defined to use {}".format(CONF_DRY_ACTION, CONF_DRY_MODE)) - if CONF_FAN_ONLY_MODE in config and CONF_FAN_ONLY_ACTION not in config: - raise cv.Invalid("{} must be defined to use {}".format(CONF_FAN_ONLY_ACTION, - CONF_FAN_ONLY_MODE)) - if CONF_HEAT_MODE in config and CONF_HEAT_ACTION not in config: - raise cv.Invalid("{} must be defined to use {}".format(CONF_HEAT_ACTION, CONF_HEAT_MODE)) - # verify corresponding default target temperature exists when a given climate action exists - if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH not in config and (CONF_COOL_ACTION in config - or CONF_FAN_ONLY_ACTION in config): - raise cv.Invalid("{} must be defined when using {} or {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_COOL_ACTION, CONF_FAN_ONLY_ACTION)) - if CONF_DEFAULT_TARGET_TEMPERATURE_LOW not in config and CONF_HEAT_ACTION in config: - raise cv.Invalid("{} must be defined when using {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION)) - # if a given climate action is NOT defined, it should not have a default target temperature - if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in config and (CONF_COOL_ACTION not in config - and CONF_FAN_ONLY_ACTION not in config): - raise cv.Invalid("{} is defined with no {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_COOL_ACTION)) - if CONF_DEFAULT_TARGET_TEMPERATURE_LOW in config and CONF_HEAT_ACTION not in config: - raise cv.Invalid("{} is defined with no {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION)) - - if CONF_AWAY_CONFIG in config: - away = config[CONF_AWAY_CONFIG] - # verify corresponding default target temperature exists when a given climate action exists - if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH not in away and (CONF_COOL_ACTION in config or - CONF_FAN_ONLY_ACTION in config): - raise cv.Invalid("{} must be defined in away configuration when using {} or {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_COOL_ACTION, CONF_FAN_ONLY_ACTION)) - if CONF_DEFAULT_TARGET_TEMPERATURE_LOW not in away and CONF_HEAT_ACTION in config: - raise cv.Invalid("{} must be defined in away configuration when using {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION)) - # if a given climate action is NOT defined, it should not have a default target temperature - if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in away and (CONF_COOL_ACTION not in config and - CONF_FAN_ONLY_ACTION not in config): - raise cv.Invalid("{} is defined in away configuration with no {} or {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_COOL_ACTION, CONF_FAN_ONLY_ACTION)) - if CONF_DEFAULT_TARGET_TEMPERATURE_LOW in away and CONF_HEAT_ACTION not in config: - raise cv.Invalid("{} is defined in away configuration with no {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION)) - - return config - - CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(BangBangClimate), cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), + cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, + cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, cv.Required(CONF_IDLE_ACTION): automation.validate_automation(single=True), cv.Optional(CONF_COOL_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_DRY_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_ONLY_ACTION): automation.validate_automation(single=True), cv.Optional(CONF_HEAT_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_AUTO_MODE): automation.validate_automation(single=True), - cv.Optional(CONF_COOL_MODE): automation.validate_automation(single=True), - cv.Optional(CONF_DRY_MODE): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_ONLY_MODE): automation.validate_automation(single=True), - cv.Optional(CONF_HEAT_MODE): automation.validate_automation(single=True), - cv.Optional(CONF_OFF_MODE): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_ON_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_OFF_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_AUTO_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_LOW_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_MEDIUM_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_HIGH_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_MIDDLE_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_FOCUS_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_DIFFUSE_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_SWING_BOTH_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_SWING_HORIZONTAL_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_SWING_OFF_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_SWING_VERTICAL_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, - cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, - cv.Optional(CONF_HYSTERESIS, default=0.5): cv.temperature, cv.Optional(CONF_AWAY_CONFIG): cv.Schema({ - cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, - cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, + cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, + cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, }), -}).extend(cv.COMPONENT_SCHEMA), cv.has_at_least_one_key(CONF_COOL_ACTION, CONF_DRY_ACTION, - CONF_FAN_ONLY_ACTION, CONF_HEAT_ACTION), - validate_bangbang) +}).extend(cv.COMPONENT_SCHEMA), cv.has_at_least_one_key(CONF_COOL_ACTION, CONF_HEAT_ACTION)) def to_code(config): @@ -110,145 +30,28 @@ def to_code(config): yield cg.register_component(var, config) yield climate.register_climate(var, config) - auto_mode_available = CONF_HEAT_ACTION in config and CONF_COOL_ACTION in config - two_points_available = CONF_HEAT_ACTION in config and (CONF_COOL_ACTION in config or - CONF_FAN_ONLY_ACTION in config) - sens = yield cg.get_variable(config[CONF_SENSOR]) cg.add(var.set_sensor(sens)) - cg.add(var.set_hysteresis(config[CONF_HYSTERESIS])) - if two_points_available is True: - cg.add(var.set_supports_two_points(True)) - normal_config = BangBangClimateTargetTempConfig( - config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW], - config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH] - ) - elif CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in config: - cg.add(var.set_supports_two_points(False)) - normal_config = BangBangClimateTargetTempConfig( - config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH] - ) - elif CONF_DEFAULT_TARGET_TEMPERATURE_LOW in config: - cg.add(var.set_supports_two_points(False)) - normal_config = BangBangClimateTargetTempConfig( - config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW] - ) + normal_config = BangBangClimateTargetTempConfig( + config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW], + config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH] + ) cg.add(var.set_normal_config(normal_config)) - yield automation.build_automation(var.get_idle_action_trigger(), [], - config[CONF_IDLE_ACTION]) - - if auto_mode_available is True: - cg.add(var.set_supports_auto(True)) - else: - cg.add(var.set_supports_auto(False)) + yield automation.build_automation(var.get_idle_trigger(), [], config[CONF_IDLE_ACTION]) if CONF_COOL_ACTION in config: - yield automation.build_automation(var.get_cool_action_trigger(), [], - config[CONF_COOL_ACTION]) + yield automation.build_automation(var.get_cool_trigger(), [], config[CONF_COOL_ACTION]) cg.add(var.set_supports_cool(True)) - if CONF_DRY_ACTION in config: - yield automation.build_automation(var.get_dry_action_trigger(), [], - config[CONF_DRY_ACTION]) - cg.add(var.set_supports_dry(True)) - if CONF_FAN_ONLY_ACTION in config: - yield automation.build_automation(var.get_fan_only_action_trigger(), [], - config[CONF_FAN_ONLY_ACTION]) - cg.add(var.set_supports_fan_only(True)) if CONF_HEAT_ACTION in config: - yield automation.build_automation(var.get_heat_action_trigger(), [], - config[CONF_HEAT_ACTION]) + yield automation.build_automation(var.get_heat_trigger(), [], config[CONF_HEAT_ACTION]) cg.add(var.set_supports_heat(True)) - if CONF_AUTO_MODE in config: - yield automation.build_automation(var.get_auto_mode_trigger(), [], - config[CONF_AUTO_MODE]) - if CONF_COOL_MODE in config: - yield automation.build_automation(var.get_cool_mode_trigger(), [], - config[CONF_COOL_MODE]) - cg.add(var.set_supports_cool(True)) - if CONF_DRY_MODE in config: - yield automation.build_automation(var.get_dry_mode_trigger(), [], - config[CONF_DRY_MODE]) - cg.add(var.set_supports_dry(True)) - if CONF_FAN_ONLY_MODE in config: - yield automation.build_automation(var.get_fan_only_mode_trigger(), [], - config[CONF_FAN_ONLY_MODE]) - cg.add(var.set_supports_fan_only(True)) - if CONF_HEAT_MODE in config: - yield automation.build_automation(var.get_heat_mode_trigger(), [], - config[CONF_HEAT_MODE]) - cg.add(var.set_supports_heat(True)) - if CONF_OFF_MODE in config: - yield automation.build_automation(var.get_off_mode_trigger(), [], - config[CONF_OFF_MODE]) - if CONF_FAN_MODE_ON_ACTION in config: - yield automation.build_automation(var.get_fan_mode_on_trigger(), [], - config[CONF_FAN_MODE_ON_ACTION]) - cg.add(var.set_supports_fan_mode_on(True)) - if CONF_FAN_MODE_OFF_ACTION in config: - yield automation.build_automation(var.get_fan_mode_off_trigger(), [], - config[CONF_FAN_MODE_OFF_ACTION]) - cg.add(var.set_supports_fan_mode_off(True)) - if CONF_FAN_MODE_AUTO_ACTION in config: - yield automation.build_automation(var.get_fan_mode_auto_trigger(), [], - config[CONF_FAN_MODE_AUTO_ACTION]) - cg.add(var.set_supports_fan_mode_auto(True)) - if CONF_FAN_MODE_LOW_ACTION in config: - yield automation.build_automation(var.get_fan_mode_low_trigger(), [], - config[CONF_FAN_MODE_LOW_ACTION]) - cg.add(var.set_supports_fan_mode_low(True)) - if CONF_FAN_MODE_MEDIUM_ACTION in config: - yield automation.build_automation(var.get_fan_mode_medium_trigger(), [], - config[CONF_FAN_MODE_MEDIUM_ACTION]) - cg.add(var.set_supports_fan_mode_medium(True)) - if CONF_FAN_MODE_HIGH_ACTION in config: - yield automation.build_automation(var.get_fan_mode_high_trigger(), [], - config[CONF_FAN_MODE_HIGH_ACTION]) - cg.add(var.set_supports_fan_mode_high(True)) - if CONF_FAN_MODE_MIDDLE_ACTION in config: - yield automation.build_automation(var.get_fan_mode_middle_trigger(), [], - config[CONF_FAN_MODE_MIDDLE_ACTION]) - cg.add(var.set_supports_fan_mode_middle(True)) - if CONF_FAN_MODE_FOCUS_ACTION in config: - yield automation.build_automation(var.get_fan_mode_focus_trigger(), [], - config[CONF_FAN_MODE_FOCUS_ACTION]) - cg.add(var.set_supports_fan_mode_focus(True)) - if CONF_FAN_MODE_DIFFUSE_ACTION in config: - yield automation.build_automation(var.get_fan_mode_diffuse_trigger(), [], - config[CONF_FAN_MODE_DIFFUSE_ACTION]) - cg.add(var.set_supports_fan_mode_diffuse(True)) - if CONF_SWING_BOTH_ACTION in config: - yield automation.build_automation(var.get_swing_mode_both_trigger(), [], - config[CONF_SWING_BOTH_ACTION]) - cg.add(var.set_supports_swing_mode_both(True)) - if CONF_SWING_HORIZONTAL_ACTION in config: - yield automation.build_automation(var.get_swing_mode_horizontal_trigger(), [], - config[CONF_SWING_HORIZONTAL_ACTION]) - cg.add(var.set_supports_swing_mode_horizontal(True)) - if CONF_SWING_OFF_ACTION in config: - yield automation.build_automation(var.get_swing_mode_off_trigger(), [], - config[CONF_SWING_OFF_ACTION]) - cg.add(var.set_supports_swing_mode_off(True)) - if CONF_SWING_VERTICAL_ACTION in config: - yield automation.build_automation(var.get_swing_mode_vertical_trigger(), [], - config[CONF_SWING_VERTICAL_ACTION]) - cg.add(var.set_supports_swing_mode_vertical(True)) if CONF_AWAY_CONFIG in config: away = config[CONF_AWAY_CONFIG] - - if two_points_available is True: - away_config = BangBangClimateTargetTempConfig( - away[CONF_DEFAULT_TARGET_TEMPERATURE_LOW], - away[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH] - ) - elif CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in away: - away_config = BangBangClimateTargetTempConfig( - away[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH] - ) - elif CONF_DEFAULT_TARGET_TEMPERATURE_LOW in away: - away_config = BangBangClimateTargetTempConfig( - away[CONF_DEFAULT_TARGET_TEMPERATURE_LOW] - ) + away_config = BangBangClimateTargetTempConfig( + away[CONF_DEFAULT_TARGET_TEMPERATURE_LOW], + away[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH] + ) cg.add(var.set_away_config(away_config)) diff --git a/esphome/const.py b/esphome/const.py index 8b727b615c..4cdf48fc76 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -44,7 +44,6 @@ CONF_ASSUMED_STATE = 'assumed_state' CONF_AT = 'at' CONF_ATTENUATION = 'attenuation' CONF_AUTH = 'auth' -CONF_AUTO_MODE = 'auto_mode' CONF_AUTOMATION_ID = 'automation_id' CONF_AVAILABILITY = 'availability' CONF_AWAY = 'away' @@ -103,7 +102,6 @@ CONF_CONDITION = 'condition' CONF_CONDITION_ID = 'condition_id' CONF_CONDUCTIVITY = 'conductivity' CONF_COOL_ACTION = 'cool_action' -CONF_COOL_MODE = 'cool_mode' CONF_COUNT_MODE = 'count_mode' CONF_CRON = 'cron' CONF_CS_PIN = 'cs_pin' @@ -142,8 +140,6 @@ CONF_DIV_RATIO = 'div_ratio' CONF_DNS1 = 'dns1' CONF_DNS2 = 'dns2' CONF_DOMAIN = 'domain' -CONF_DRY_ACTION = 'dry_action' -CONF_DRY_MODE = 'dry_mode' CONF_DUMP = 'dump' CONF_DURATION = 'duration' CONF_ECHO_PIN = 'echo_pin' @@ -163,17 +159,6 @@ CONF_EXTERNAL_VCC = 'external_vcc' CONF_FALLING_EDGE = 'falling_edge' CONF_FAMILY = 'family' CONF_FAN_MODE = 'fan_mode' -CONF_FAN_MODE_AUTO_ACTION = 'fan_mode_auto_action' -CONF_FAN_MODE_DIFFUSE_ACTION = 'fan_mode_diffuse_action' -CONF_FAN_MODE_FOCUS_ACTION = 'fan_mode_focus_action' -CONF_FAN_MODE_HIGH_ACTION = 'fan_mode_high_action' -CONF_FAN_MODE_LOW_ACTION = 'fan_mode_low_action' -CONF_FAN_MODE_MEDIUM_ACTION = 'fan_mode_medium_action' -CONF_FAN_MODE_MIDDLE_ACTION = 'fan_mode_middle_action' -CONF_FAN_MODE_OFF_ACTION = 'fan_mode_off_action' -CONF_FAN_MODE_ON_ACTION = 'fan_mode_on_action' -CONF_FAN_ONLY_ACTION = 'fan_only_action' -CONF_FAN_ONLY_MODE = 'fan_only_mode' CONF_FAST_CONNECT = 'fast_connect' CONF_FILE = 'file' CONF_FILTER = 'filter' @@ -198,7 +183,6 @@ CONF_GROUP = 'group' CONF_HARDWARE_UART = 'hardware_uart' CONF_HEARTBEAT = 'heartbeat' CONF_HEAT_ACTION = 'heat_action' -CONF_HEAT_MODE = 'heat_mode' CONF_HEATER = 'heater' CONF_HIDDEN = 'hidden' CONF_HIGH = 'high' @@ -206,7 +190,6 @@ CONF_HIGH_VOLTAGE_REFERENCE = 'high_voltage_reference' CONF_HOUR = 'hour' CONF_HOURS = 'hours' CONF_HUMIDITY = 'humidity' -CONF_HYSTERESIS = "hysteresis" CONF_I2C = 'i2c' CONF_I2C_ID = 'i2c_id' CONF_ICON = 'icon' @@ -302,7 +285,6 @@ CONF_NUM_CHANNELS = 'num_channels' CONF_NUM_CHIPS = 'num_chips' CONF_NUM_LEDS = 'num_leds' CONF_NUMBER = 'number' -CONF_OFF_MODE = 'off_mode' CONF_OFFSET = 'offset' CONF_ON = 'on' CONF_ON_BLE_ADVERTISE = 'on_ble_advertise' @@ -467,11 +449,7 @@ CONF_STOP_ACTION = 'stop_action' CONF_SUBNET = 'subnet' CONF_SUPPORTS_COOL = 'supports_cool' CONF_SUPPORTS_HEAT = 'supports_heat' -CONF_SWING_BOTH_ACTION = 'swing_both_action' -CONF_SWING_HORIZONTAL_ACTION = 'swing_horizontal_action' CONF_SWING_MODE = 'swing_mode' -CONF_SWING_OFF_ACTION = 'swing_off_action' -CONF_SWING_VERTICAL_ACTION = 'swing_vertical_action' CONF_SWITCHES = 'switches' CONF_SYNC = 'sync' CONF_TABLET = 'tablet' diff --git a/tests/test3.yaml b/tests/test3.yaml index 9c51894e12..72dde13055 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -621,49 +621,6 @@ climate: - switch.turn_on: gpio_switch2 heat_action: - switch.turn_on: gpio_switch1 - dry_action: - - switch.turn_on: gpio_switch2 - fan_only_action: - - switch.turn_on: gpio_switch1 - auto_mode: - - switch.turn_on: gpio_switch2 - off_mode: - - switch.turn_on: gpio_switch1 - heat_mode: - - switch.turn_on: gpio_switch2 - cool_mode: - - switch.turn_on: gpio_switch1 - dry_mode: - - switch.turn_on: gpio_switch2 - fan_only_mode: - - switch.turn_on: gpio_switch1 - fan_mode_auto_action: - - switch.turn_on: gpio_switch2 - fan_mode_on_action: - - switch.turn_on: gpio_switch1 - fan_mode_off_action: - - switch.turn_on: gpio_switch2 - fan_mode_low_action: - - switch.turn_on: gpio_switch1 - fan_mode_medium_action: - - switch.turn_on: gpio_switch2 - fan_mode_high_action: - - switch.turn_on: gpio_switch1 - fan_mode_middle_action: - - switch.turn_on: gpio_switch2 - fan_mode_focus_action: - - switch.turn_on: gpio_switch1 - fan_mode_diffuse_action: - - switch.turn_on: gpio_switch2 - swing_off_action: - - switch.turn_on: gpio_switch1 - swing_horizontal_action: - - switch.turn_on: gpio_switch2 - swing_vertical_action: - - switch.turn_on: gpio_switch1 - swing_both_action: - - switch.turn_on: gpio_switch2 - hysteresis: 0.2 away_config: default_target_temperature_low: 16°C default_target_temperature_high: 20°C