1
0
mirror of https://github.com/esphome/esphome.git synced 2025-01-31 18:20:53 +00:00

added idle action for climate (#859)

* added idle

* more clear state description

* Also add drying/fan

Putting it in this PR because it will be put in the same aioesphomeapi release anyway.

* Update bang_bang for idle action


Co-authored-by: root <root@mail.danman.eu>
Co-authored-by: Otto Winter <otto@otto-winter.com>
This commit is contained in:
Daniel Kucera 2019-11-26 16:56:04 +00:00 committed by Otto Winter
parent be36eef939
commit fe89dcdc08
6 changed files with 49 additions and 13 deletions

View File

@ -678,6 +678,9 @@ enum ClimateAction {
// values same as mode for readability // values same as mode for readability
CLIMATE_ACTION_COOLING = 2; CLIMATE_ACTION_COOLING = 2;
CLIMATE_ACTION_HEATING = 3; CLIMATE_ACTION_HEATING = 3;
CLIMATE_ACTION_IDLE = 4;
CLIMATE_ACTION_DRYING = 5;
CLIMATE_ACTION_FAN = 6;
} }
message ListEntitiesClimateResponse { message ListEntitiesClimateResponse {
option (id) = 46; option (id) = 46;

View File

@ -158,6 +158,12 @@ template<> const char *proto_enum_to_string<enums::ClimateAction>(enums::Climate
return "CLIMATE_ACTION_COOLING"; return "CLIMATE_ACTION_COOLING";
case enums::CLIMATE_ACTION_HEATING: case enums::CLIMATE_ACTION_HEATING:
return "CLIMATE_ACTION_HEATING"; return "CLIMATE_ACTION_HEATING";
case enums::CLIMATE_ACTION_IDLE:
return "CLIMATE_ACTION_IDLE";
case enums::CLIMATE_ACTION_DRYING:
return "CLIMATE_ACTION_DRYING";
case enums::CLIMATE_ACTION_FAN:
return "CLIMATE_ACTION_FAN";
default: default:
return "UNKNOWN"; return "UNKNOWN";
} }

View File

@ -76,6 +76,9 @@ enum ClimateAction : uint32_t {
CLIMATE_ACTION_OFF = 0, CLIMATE_ACTION_OFF = 0,
CLIMATE_ACTION_COOLING = 2, CLIMATE_ACTION_COOLING = 2,
CLIMATE_ACTION_HEATING = 3, CLIMATE_ACTION_HEATING = 3,
CLIMATE_ACTION_IDLE = 4,
CLIMATE_ACTION_DRYING = 5,
CLIMATE_ACTION_FAN = 6,
}; };
} // namespace enums } // namespace enums

View File

@ -51,12 +51,15 @@ climate::ClimateTraits BangBangClimate::traits() {
} }
void BangBangClimate::compute_state_() { void BangBangClimate::compute_state_() {
if (this->mode != climate::CLIMATE_MODE_AUTO) { if (this->mode != climate::CLIMATE_MODE_AUTO) {
// in non-auto mode // 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<climate::ClimateAction>(this->mode)); this->switch_to_action_(static_cast<climate::ClimateAction>(this->mode));
return; return;
} }
if (isnan(this->current_temperature) || isnan(this->target_temperature_low) || isnan(this->target_temperature_high)) { if (isnan(this->current_temperature) || isnan(this->target_temperature_low) || isnan(this->target_temperature_high)) {
// if any control values are nan, go to OFF (idle) mode // if any control parameters are nan, go to OFF action (not IDLE!)
this->switch_to_action_(climate::CLIMATE_ACTION_OFF); this->switch_to_action_(climate::CLIMATE_ACTION_OFF);
return; return;
} }
@ -69,18 +72,18 @@ void BangBangClimate::compute_state_() {
if (this->supports_heat_) if (this->supports_heat_)
target_action = climate::CLIMATE_ACTION_HEATING; target_action = climate::CLIMATE_ACTION_HEATING;
else else
target_action = climate::CLIMATE_ACTION_OFF; target_action = climate::CLIMATE_ACTION_IDLE;
} else if (too_hot) { } else if (too_hot) {
// too hot -> enable cooling if possible, else idle // too hot -> enable cooling if possible, else idle
if (this->supports_cool_) if (this->supports_cool_)
target_action = climate::CLIMATE_ACTION_COOLING; target_action = climate::CLIMATE_ACTION_COOLING;
else else
target_action = climate::CLIMATE_ACTION_OFF; target_action = climate::CLIMATE_ACTION_IDLE;
} else { } else {
// neither too hot nor too cold -> in range // neither too hot nor too cold -> in range
if (this->supports_cool_ && this->supports_heat_) { if (this->supports_cool_ && this->supports_heat_) {
// if supports both ends, go to idle mode // if supports both ends, go to idle action
target_action = climate::CLIMATE_ACTION_OFF; target_action = climate::CLIMATE_ACTION_IDLE;
} else { } else {
// else use current mode and don't change (hysteresis) // else use current mode and don't change (hysteresis)
target_action = this->action; target_action = this->action;
@ -94,6 +97,16 @@ void BangBangClimate::switch_to_action_(climate::ClimateAction action) {
// already in target mode // already in target mode
return; return;
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_trigger_ != nullptr) { if (this->prev_trigger_ != nullptr) {
this->prev_trigger_->stop(); this->prev_trigger_->stop();
this->prev_trigger_ = nullptr; this->prev_trigger_ = nullptr;
@ -101,6 +114,7 @@ void BangBangClimate::switch_to_action_(climate::ClimateAction action) {
Trigger<> *trig; Trigger<> *trig;
switch (action) { switch (action) {
case climate::CLIMATE_ACTION_OFF: case climate::CLIMATE_ACTION_OFF:
case climate::CLIMATE_ACTION_IDLE:
trig = this->idle_trigger_; trig = this->idle_trigger_;
break; break;
case climate::CLIMATE_ACTION_COOLING: case climate::CLIMATE_ACTION_COOLING:
@ -112,14 +126,12 @@ void BangBangClimate::switch_to_action_(climate::ClimateAction action) {
default: default:
trig = nullptr; trig = nullptr;
} }
if (trig != nullptr) { assert(trig != nullptr);
// trig should never be null, but still check so that we don't crash
trig->trigger(); trig->trigger();
this->action = action; this->action = action;
this->prev_trigger_ = trig; this->prev_trigger_ = trig;
this->publish_state(); this->publish_state();
} }
}
void BangBangClimate::change_away_(bool away) { void BangBangClimate::change_away_(bool away) {
if (!away) { if (!away) {
this->target_temperature_low = this->normal_config_.default_temperature_low; this->target_temperature_low = this->normal_config_.default_temperature_low;

View File

@ -29,6 +29,12 @@ const char *climate_action_to_string(ClimateAction action) {
return "COOLING"; return "COOLING";
case CLIMATE_ACTION_HEATING: case CLIMATE_ACTION_HEATING:
return "HEATING"; return "HEATING";
case CLIMATE_ACTION_IDLE:
return "IDLE";
case CLIMATE_ACTION_DRYING:
return "DRYING";
case CLIMATE_ACTION_FAN:
return "FAN";
default: default:
return "UNKNOWN"; return "UNKNOWN";
} }

View File

@ -29,6 +29,12 @@ enum ClimateAction : uint8_t {
CLIMATE_ACTION_COOLING = 2, CLIMATE_ACTION_COOLING = 2,
/// The climate device is actively heating (usually in heat or auto mode) /// The climate device is actively heating (usually in heat or auto mode)
CLIMATE_ACTION_HEATING = 3, CLIMATE_ACTION_HEATING = 3,
/// The climate device is idle (monitoring climate but no action needed)
CLIMATE_ACTION_IDLE = 4,
/// The climate device is drying (either mode DRY or AUTO)
CLIMATE_ACTION_DRYING = 5,
/// The climate device is in fan only mode (either mode FAN_ONLY or AUTO)
CLIMATE_ACTION_FAN = 6,
}; };
/// Enum for all modes a climate fan can be in /// Enum for all modes a climate fan can be in