mirror of
https://github.com/Threnklyn/esphome-dev.git
synced 2026-06-04 03:48:29 +02:00
add support for climate action (#720)
* add support for climate action: Following hass implementation of climate, action represents the current action the climate device is perfoming, e.g. cooling or heating fix bang_bang climate: make sure that the thresholds are always respected. fixes the issue where the component would just keep on heating, regardless of the temperature range * Updates - Use dedicated enum for action (otherwise it gets confusing because "auto" is not a valid action) - Add field to tell HA that action is supported - Revert semantic changes in bang_bang * Conditional print Co-authored-by: Otto Winter <otto@otto-winter.com>
This commit is contained in:
committed by
Otto Winter
parent
22aecdfc6f
commit
72d6471ab8
@@ -46,52 +46,51 @@ climate::ClimateTraits BangBangClimate::traits() {
|
||||
traits.set_supports_heat_mode(this->supports_heat_);
|
||||
traits.set_supports_two_point_target_temperature(true);
|
||||
traits.set_supports_away(this->supports_away_);
|
||||
traits.set_supports_action(true);
|
||||
return traits;
|
||||
}
|
||||
void BangBangClimate::compute_state_() {
|
||||
if (this->mode != climate::CLIMATE_MODE_AUTO) {
|
||||
// in non-auto mode
|
||||
this->switch_to_mode_(this->mode);
|
||||
this->switch_to_action_(static_cast<climate::ClimateAction>(this->mode));
|
||||
return;
|
||||
}
|
||||
|
||||
// auto mode, compute target mode
|
||||
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
|
||||
this->switch_to_mode_(climate::CLIMATE_MODE_OFF);
|
||||
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;
|
||||
|
||||
climate::ClimateMode target_mode;
|
||||
climate::ClimateAction target_action;
|
||||
if (too_cold) {
|
||||
// too cold -> enable heating if possible, else idle
|
||||
if (this->supports_heat_)
|
||||
target_mode = climate::CLIMATE_MODE_HEAT;
|
||||
target_action = climate::CLIMATE_ACTION_HEATING;
|
||||
else
|
||||
target_mode = climate::CLIMATE_MODE_OFF;
|
||||
target_action = climate::CLIMATE_ACTION_OFF;
|
||||
} else if (too_hot) {
|
||||
// too hot -> enable cooling if possible, else idle
|
||||
if (this->supports_cool_)
|
||||
target_mode = climate::CLIMATE_MODE_COOL;
|
||||
target_action = climate::CLIMATE_ACTION_COOLING;
|
||||
else
|
||||
target_mode = climate::CLIMATE_MODE_OFF;
|
||||
target_action = climate::CLIMATE_ACTION_OFF;
|
||||
} 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_mode = climate::CLIMATE_MODE_OFF;
|
||||
target_action = climate::CLIMATE_ACTION_OFF;
|
||||
} else {
|
||||
// else use current mode and don't change (hysteresis)
|
||||
target_mode = this->internal_mode_;
|
||||
target_action = this->action;
|
||||
}
|
||||
}
|
||||
|
||||
this->switch_to_mode_(target_mode);
|
||||
this->switch_to_action_(target_action);
|
||||
}
|
||||
void BangBangClimate::switch_to_mode_(climate::ClimateMode mode) {
|
||||
if (mode == this->internal_mode_)
|
||||
void BangBangClimate::switch_to_action_(climate::ClimateAction action) {
|
||||
if (action == this->action)
|
||||
// already in target mode
|
||||
return;
|
||||
|
||||
@@ -100,14 +99,14 @@ void BangBangClimate::switch_to_mode_(climate::ClimateMode mode) {
|
||||
this->prev_trigger_ = nullptr;
|
||||
}
|
||||
Trigger<> *trig;
|
||||
switch (mode) {
|
||||
case climate::CLIMATE_MODE_OFF:
|
||||
switch (action) {
|
||||
case climate::CLIMATE_ACTION_OFF:
|
||||
trig = this->idle_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_COOL:
|
||||
case climate::CLIMATE_ACTION_COOLING:
|
||||
trig = this->cool_trigger_;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_HEAT:
|
||||
case climate::CLIMATE_ACTION_HEATING:
|
||||
trig = this->heat_trigger_;
|
||||
break;
|
||||
default:
|
||||
@@ -116,7 +115,7 @@ void BangBangClimate::switch_to_mode_(climate::ClimateMode mode) {
|
||||
if (trig != nullptr) {
|
||||
// trig should never be null, but still check so that we don't crash
|
||||
trig->trigger();
|
||||
this->internal_mode_ = mode;
|
||||
this->action = action;
|
||||
this->prev_trigger_ = trig;
|
||||
this->publish_state();
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ class BangBangClimate : public climate::Climate, public Component {
|
||||
void compute_state_();
|
||||
|
||||
/// Switch the climate device to the given climate mode.
|
||||
void switch_to_mode_(climate::ClimateMode mode);
|
||||
void switch_to_action_(climate::ClimateAction action);
|
||||
|
||||
/// The sensor used for getting the current temperature
|
||||
sensor::Sensor *sensor_{nullptr};
|
||||
@@ -74,11 +74,6 @@ class BangBangClimate : public climate::Climate, public Component {
|
||||
* This is so that the previous trigger can be stopped before enabling a new one.
|
||||
*/
|
||||
Trigger<> *prev_trigger_{nullptr};
|
||||
/** The climate mode that is currently active - for a `.mode = AUTO` this will
|
||||
* contain the actual mode the device
|
||||
*
|
||||
*/
|
||||
climate::ClimateMode internal_mode_{climate::CLIMATE_MODE_OFF};
|
||||
|
||||
BangBangClimateTargetTempConfig normal_config_{};
|
||||
bool supports_away_{false};
|
||||
|
||||
Reference in New Issue
Block a user