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
CLIMATE_ACTION_COOLING = 2;
CLIMATE_ACTION_HEATING = 3;
CLIMATE_ACTION_IDLE = 4;
CLIMATE_ACTION_DRYING = 5;
CLIMATE_ACTION_FAN = 6;
}
message ListEntitiesClimateResponse {
option (id) = 46;

View file

@ -158,6 +158,12 @@ template<> const char *proto_enum_to_string<enums::ClimateAction>(enums::Climate
return "CLIMATE_ACTION_COOLING";
case enums::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:
return "UNKNOWN";
}

View file

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

View file

@ -51,12 +51,15 @@ climate::ClimateTraits BangBangClimate::traits() {
}
void BangBangClimate::compute_state_() {
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));
return;
}
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);
return;
}
@ -69,18 +72,18 @@ void BangBangClimate::compute_state_() {
if (this->supports_heat_)
target_action = climate::CLIMATE_ACTION_HEATING;
else
target_action = climate::CLIMATE_ACTION_OFF;
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_OFF;
target_action = climate::CLIMATE_ACTION_IDLE;
} else {
// neither too hot nor too cold -> in range
if (this->supports_cool_ && this->supports_heat_) {
// if supports both ends, go to idle mode
target_action = climate::CLIMATE_ACTION_OFF;
// if supports both ends, go to idle action
target_action = climate::CLIMATE_ACTION_IDLE;
} else {
// else use current mode and don't change (hysteresis)
target_action = this->action;
@ -94,6 +97,16 @@ void BangBangClimate::switch_to_action_(climate::ClimateAction 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)) {
// 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) {
this->prev_trigger_->stop();
this->prev_trigger_ = nullptr;
@ -101,6 +114,7 @@ void BangBangClimate::switch_to_action_(climate::ClimateAction action) {
Trigger<> *trig;
switch (action) {
case climate::CLIMATE_ACTION_OFF:
case climate::CLIMATE_ACTION_IDLE:
trig = this->idle_trigger_;
break;
case climate::CLIMATE_ACTION_COOLING:
@ -112,13 +126,11 @@ void BangBangClimate::switch_to_action_(climate::ClimateAction action) {
default:
trig = nullptr;
}
if (trig != nullptr) {
// trig should never be null, but still check so that we don't crash
trig->trigger();
this->action = action;
this->prev_trigger_ = trig;
this->publish_state();
}
assert(trig != nullptr);
trig->trigger();
this->action = action;
this->prev_trigger_ = trig;
this->publish_state();
}
void BangBangClimate::change_away_(bool away) {
if (!away) {

View file

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

View file

@ -29,6 +29,12 @@ enum ClimateAction : uint8_t {
CLIMATE_ACTION_COOLING = 2,
/// The climate device is actively heating (usually in heat or auto mode)
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