mirror of
https://github.com/esphome/esphome.git
synced 2025-01-31 10:10:56 +00:00
Thermostat remove deprecated config (#3643)
* Raise errors for all the now deprecated options * Fix CONF_DEFAULT_PRESET detection * Stop attempting to set the non-existent normal_config * Add support for default presets * Fix correct detection of Two Point temperature mode * Fix lint issues * Fix tests * Generate correct yaml for equivalent configurations * Remove debug code * Only set default preset if the thermostat does not have state to restore * Add restore_default_preset_on_boot option If set to True then the default_preset will be applied on every boot. If False (Default) state will be restored from memory as per prior versions * Apply lint suggestions * Switch from restore_default_preset_on_boot to an enum for startup_behavior This gives better self-documentation as well as the option for extending to other options down the track * Lint fixes * Rename startup_behavior to on_boot_restore_from This removes any issues with different English locales * Fix comparable_preset yaml output alignment * Add dump of on_boot_restore_from setting Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
This commit is contained in:
parent
ce2e161b08
commit
8095db6715
@ -69,6 +69,8 @@ from esphome.const import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
CONF_PRESET_CHANGE = "preset_change"
|
CONF_PRESET_CHANGE = "preset_change"
|
||||||
|
CONF_DEFAULT_PRESET = "default_preset"
|
||||||
|
CONF_ON_BOOT_RESTORE_FROM = "on_boot_restore_from"
|
||||||
|
|
||||||
CODEOWNERS = ["@kbx81"]
|
CODEOWNERS = ["@kbx81"]
|
||||||
|
|
||||||
@ -80,6 +82,13 @@ ThermostatClimate = thermostat_ns.class_(
|
|||||||
ThermostatClimateTargetTempConfig = thermostat_ns.struct(
|
ThermostatClimateTargetTempConfig = thermostat_ns.struct(
|
||||||
"ThermostatClimateTargetTempConfig"
|
"ThermostatClimateTargetTempConfig"
|
||||||
)
|
)
|
||||||
|
OnBootRestoreFrom = thermostat_ns.enum("OnBootRestoreFrom")
|
||||||
|
ON_BOOT_RESTORE_FROM = {
|
||||||
|
"MEMORY": OnBootRestoreFrom.MEMORY,
|
||||||
|
"DEFAULT_PRESET": OnBootRestoreFrom.DEFAULT_PRESET,
|
||||||
|
}
|
||||||
|
validate_on_boot_restore_from = cv.enum(ON_BOOT_RESTORE_FROM, upper=True)
|
||||||
|
|
||||||
ClimateMode = climate_ns.enum("ClimateMode")
|
ClimateMode = climate_ns.enum("ClimateMode")
|
||||||
CLIMATE_MODES = {
|
CLIMATE_MODES = {
|
||||||
"OFF": ClimateMode.CLIMATE_MODE_OFF,
|
"OFF": ClimateMode.CLIMATE_MODE_OFF,
|
||||||
@ -125,6 +134,17 @@ def validate_temperature_preset(preset, root_config, name, requirements):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_comparable_preset(config, name):
|
||||||
|
comparable_preset = f"{CONF_PRESET}:\n" f" - {CONF_NAME}: {name}\n"
|
||||||
|
|
||||||
|
if CONF_DEFAULT_TARGET_TEMPERATURE_LOW in config:
|
||||||
|
comparable_preset += f" {CONF_DEFAULT_TARGET_TEMPERATURE_LOW}: {config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW]}\n"
|
||||||
|
if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in config:
|
||||||
|
comparable_preset += f" {CONF_DEFAULT_TARGET_TEMPERATURE_HIGH}: {config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH]}\n"
|
||||||
|
|
||||||
|
return comparable_preset
|
||||||
|
|
||||||
|
|
||||||
def validate_thermostat(config):
|
def validate_thermostat(config):
|
||||||
# verify corresponding action(s) exist(s) for any defined climate mode or action
|
# verify corresponding action(s) exist(s) for any defined climate mode or action
|
||||||
requirements = {
|
requirements = {
|
||||||
@ -277,13 +297,32 @@ def validate_thermostat(config):
|
|||||||
CONF_DEFAULT_TARGET_TEMPERATURE_LOW: [CONF_HEAT_ACTION],
|
CONF_DEFAULT_TARGET_TEMPERATURE_LOW: [CONF_HEAT_ACTION],
|
||||||
}
|
}
|
||||||
|
|
||||||
# Validate temperature requirements for default configuraation
|
# Legacy high/low configs
|
||||||
validate_temperature_preset(config, config, "default", requirements)
|
if CONF_DEFAULT_TARGET_TEMPERATURE_LOW in config:
|
||||||
|
comparable_preset = generate_comparable_preset(config, "Your new preset")
|
||||||
|
|
||||||
# Validate temperature requirements for away configuration
|
raise cv.Invalid(
|
||||||
|
f"{CONF_DEFAULT_TARGET_TEMPERATURE_LOW} is no longer valid. Please switch to using a preset for an equivalent experience.\nEquivalent configuration:\n\n"
|
||||||
|
f"{comparable_preset}"
|
||||||
|
)
|
||||||
|
if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in config:
|
||||||
|
comparable_preset = generate_comparable_preset(config, "Your new preset")
|
||||||
|
|
||||||
|
raise cv.Invalid(
|
||||||
|
f"{CONF_DEFAULT_TARGET_TEMPERATURE_HIGH} is no longer valid. Please switch to using a preset for an equivalent experience.\nEquivalent configuration:\n\n"
|
||||||
|
f"{comparable_preset}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Legacy away mode - raise an error instructing the user to switch to presets
|
||||||
if CONF_AWAY_CONFIG in config:
|
if CONF_AWAY_CONFIG in config:
|
||||||
away = config[CONF_AWAY_CONFIG]
|
comparable_preset = generate_comparable_preset(config[CONF_AWAY_CONFIG], "Away")
|
||||||
validate_temperature_preset(away, config, "away", requirements)
|
|
||||||
|
raise cv.Invalid(
|
||||||
|
f"{CONF_AWAY_CONFIG} is no longer valid. Please switch to using a preset named "
|
||||||
|
"Away"
|
||||||
|
" for an equivalent experience.\nEquivalent configuration:\n\n"
|
||||||
|
f"{comparable_preset}"
|
||||||
|
)
|
||||||
|
|
||||||
# Validate temperature requirements for presets
|
# Validate temperature requirements for presets
|
||||||
if CONF_PRESET in config:
|
if CONF_PRESET in config:
|
||||||
@ -292,7 +331,12 @@ def validate_thermostat(config):
|
|||||||
preset_config, config, preset_config[CONF_NAME], requirements
|
preset_config, config, preset_config[CONF_NAME], requirements
|
||||||
)
|
)
|
||||||
|
|
||||||
# Verify default climate mode is valid given above configuration
|
# Warn about using the removed CONF_DEFAULT_MODE and advise users
|
||||||
|
if CONF_DEFAULT_MODE in config and config[CONF_DEFAULT_MODE] is not None:
|
||||||
|
raise cv.Invalid(
|
||||||
|
f"{CONF_DEFAULT_MODE} is no longer valid. Please switch to using presets and specify a {CONF_DEFAULT_PRESET}."
|
||||||
|
)
|
||||||
|
|
||||||
default_mode = config[CONF_DEFAULT_MODE]
|
default_mode = config[CONF_DEFAULT_MODE]
|
||||||
requirements = {
|
requirements = {
|
||||||
"HEAT_COOL": [CONF_COOL_ACTION, CONF_HEAT_ACTION],
|
"HEAT_COOL": [CONF_COOL_ACTION, CONF_HEAT_ACTION],
|
||||||
@ -403,6 +447,38 @@ def validate_thermostat(config):
|
|||||||
f"{CONF_SWING_MODE} is set to {swing_mode} for {preset_config[CONF_NAME]} but {req} is not present in the configuration"
|
f"{CONF_SWING_MODE} is set to {swing_mode} for {preset_config[CONF_NAME]} but {req} is not present in the configuration"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# If a default preset is requested then ensure that preset is defined
|
||||||
|
if CONF_DEFAULT_PRESET in config:
|
||||||
|
default_preset = config[CONF_DEFAULT_PRESET]
|
||||||
|
|
||||||
|
if CONF_PRESET not in config:
|
||||||
|
raise cv.Invalid(
|
||||||
|
f"{CONF_DEFAULT_PRESET} is specified but no presets are defined"
|
||||||
|
)
|
||||||
|
|
||||||
|
presets = config[CONF_PRESET]
|
||||||
|
found_preset = False
|
||||||
|
|
||||||
|
for preset in presets:
|
||||||
|
if preset[CONF_NAME] == default_preset:
|
||||||
|
found_preset = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if found_preset is False:
|
||||||
|
raise cv.Invalid(
|
||||||
|
f"{CONF_DEFAULT_PRESET} set to '{default_preset}' but no such preset has been defined. Available presets: {[preset[CONF_NAME] for preset in presets]}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# If restoring default preset on boot is true then ensure we have a default preset
|
||||||
|
if (
|
||||||
|
CONF_ON_BOOT_RESTORE_FROM in config
|
||||||
|
and config[CONF_ON_BOOT_RESTORE_FROM] is OnBootRestoreFrom.DEFAULT_PRESET
|
||||||
|
):
|
||||||
|
if CONF_DEFAULT_PRESET not in config:
|
||||||
|
raise cv.Invalid(
|
||||||
|
f"{CONF_DEFAULT_PRESET} must be defined to use {CONF_ON_BOOT_RESTORE_FROM} in DEFAULT_PRESET mode"
|
||||||
|
)
|
||||||
|
|
||||||
if config[CONF_FAN_WITH_COOLING] is True and CONF_FAN_ONLY_ACTION not in config:
|
if config[CONF_FAN_WITH_COOLING] is True and CONF_FAN_ONLY_ACTION not in config:
|
||||||
raise cv.Invalid(
|
raise cv.Invalid(
|
||||||
f"{CONF_FAN_ONLY_ACTION} must be defined to use {CONF_FAN_WITH_COOLING}"
|
f"{CONF_FAN_ONLY_ACTION} must be defined to use {CONF_FAN_WITH_COOLING}"
|
||||||
@ -502,9 +578,8 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
cv.Optional(
|
cv.Optional(
|
||||||
CONF_TARGET_TEMPERATURE_CHANGE_ACTION
|
CONF_TARGET_TEMPERATURE_CHANGE_ACTION
|
||||||
): automation.validate_automation(single=True),
|
): automation.validate_automation(single=True),
|
||||||
cv.Optional(CONF_DEFAULT_MODE, default="OFF"): cv.templatable(
|
cv.Optional(CONF_DEFAULT_MODE, default=None): cv.valid,
|
||||||
validate_climate_mode
|
cv.Optional(CONF_DEFAULT_PRESET): cv.templatable(cv.string),
|
||||||
),
|
|
||||||
cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature,
|
cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature,
|
||||||
cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature,
|
cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature,
|
||||||
cv.Optional(
|
cv.Optional(
|
||||||
@ -542,6 +617,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_PRESET): cv.ensure_list(PRESET_CONFIG_SCHEMA),
|
cv.Optional(CONF_PRESET): cv.ensure_list(PRESET_CONFIG_SCHEMA),
|
||||||
|
cv.Optional(CONF_ON_BOOT_RESTORE_FROM): validate_on_boot_restore_from,
|
||||||
cv.Optional(CONF_PRESET_CHANGE): automation.validate_automation(
|
cv.Optional(CONF_PRESET_CHANGE): automation.validate_automation(
|
||||||
single=True
|
single=True
|
||||||
),
|
),
|
||||||
@ -564,9 +640,10 @@ async def to_code(config):
|
|||||||
CONF_COOL_ACTION in config
|
CONF_COOL_ACTION in config
|
||||||
or (config[CONF_FAN_ONLY_COOLING] and CONF_FAN_ONLY_ACTION in config)
|
or (config[CONF_FAN_ONLY_COOLING] and CONF_FAN_ONLY_ACTION in config)
|
||||||
)
|
)
|
||||||
|
if two_points_available:
|
||||||
|
cg.add(var.set_supports_two_points(True))
|
||||||
|
|
||||||
sens = await cg.get_variable(config[CONF_SENSOR])
|
sens = await cg.get_variable(config[CONF_SENSOR])
|
||||||
cg.add(var.set_default_mode(config[CONF_DEFAULT_MODE]))
|
|
||||||
cg.add(
|
cg.add(
|
||||||
var.set_set_point_minimum_differential(
|
var.set_set_point_minimum_differential(
|
||||||
config[CONF_SET_POINT_MINIMUM_DIFFERENTIAL]
|
config[CONF_SET_POINT_MINIMUM_DIFFERENTIAL]
|
||||||
@ -579,23 +656,6 @@ async def to_code(config):
|
|||||||
cg.add(var.set_heat_deadband(config[CONF_HEAT_DEADBAND]))
|
cg.add(var.set_heat_deadband(config[CONF_HEAT_DEADBAND]))
|
||||||
cg.add(var.set_heat_overrun(config[CONF_HEAT_OVERRUN]))
|
cg.add(var.set_heat_overrun(config[CONF_HEAT_OVERRUN]))
|
||||||
|
|
||||||
if two_points_available is True:
|
|
||||||
cg.add(var.set_supports_two_points(True))
|
|
||||||
normal_config = ThermostatClimateTargetTempConfig(
|
|
||||||
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 = ThermostatClimateTargetTempConfig(
|
|
||||||
config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH]
|
|
||||||
)
|
|
||||||
elif CONF_DEFAULT_TARGET_TEMPERATURE_LOW in config:
|
|
||||||
cg.add(var.set_supports_two_points(False))
|
|
||||||
normal_config = ThermostatClimateTargetTempConfig(
|
|
||||||
config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW]
|
|
||||||
)
|
|
||||||
|
|
||||||
if CONF_MAX_COOLING_RUN_TIME in config:
|
if CONF_MAX_COOLING_RUN_TIME in config:
|
||||||
cg.add(
|
cg.add(
|
||||||
var.set_cooling_maximum_run_time_in_sec(config[CONF_MAX_COOLING_RUN_TIME])
|
var.set_cooling_maximum_run_time_in_sec(config[CONF_MAX_COOLING_RUN_TIME])
|
||||||
@ -661,7 +721,6 @@ async def to_code(config):
|
|||||||
cg.add(var.set_supports_fan_with_heating(config[CONF_FAN_WITH_HEATING]))
|
cg.add(var.set_supports_fan_with_heating(config[CONF_FAN_WITH_HEATING]))
|
||||||
|
|
||||||
cg.add(var.set_use_startup_delay(config[CONF_STARTUP_DELAY]))
|
cg.add(var.set_use_startup_delay(config[CONF_STARTUP_DELAY]))
|
||||||
cg.add(var.set_preset_config(ClimatePreset.CLIMATE_PRESET_HOME, normal_config))
|
|
||||||
|
|
||||||
await automation.build_automation(
|
await automation.build_automation(
|
||||||
var.get_idle_action_trigger(), [], config[CONF_IDLE_ACTION]
|
var.get_idle_action_trigger(), [], config[CONF_IDLE_ACTION]
|
||||||
@ -808,27 +867,8 @@ async def to_code(config):
|
|||||||
config[CONF_TARGET_TEMPERATURE_CHANGE_ACTION],
|
config[CONF_TARGET_TEMPERATURE_CHANGE_ACTION],
|
||||||
)
|
)
|
||||||
|
|
||||||
if CONF_AWAY_CONFIG in config:
|
|
||||||
away = config[CONF_AWAY_CONFIG]
|
|
||||||
|
|
||||||
if two_points_available is True:
|
|
||||||
away_config = ThermostatClimateTargetTempConfig(
|
|
||||||
away[CONF_DEFAULT_TARGET_TEMPERATURE_LOW],
|
|
||||||
away[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH],
|
|
||||||
)
|
|
||||||
elif CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in away:
|
|
||||||
away_config = ThermostatClimateTargetTempConfig(
|
|
||||||
away[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH]
|
|
||||||
)
|
|
||||||
elif CONF_DEFAULT_TARGET_TEMPERATURE_LOW in away:
|
|
||||||
away_config = ThermostatClimateTargetTempConfig(
|
|
||||||
away[CONF_DEFAULT_TARGET_TEMPERATURE_LOW]
|
|
||||||
)
|
|
||||||
cg.add(var.set_preset_config(ClimatePreset.CLIMATE_PRESET_AWAY, away_config))
|
|
||||||
|
|
||||||
if CONF_PRESET in config:
|
if CONF_PRESET in config:
|
||||||
for preset_config in config[CONF_PRESET]:
|
for preset_config in config[CONF_PRESET]:
|
||||||
|
|
||||||
name = preset_config[CONF_NAME]
|
name = preset_config[CONF_NAME]
|
||||||
standard_preset = None
|
standard_preset = None
|
||||||
if name.upper() in climate.CLIMATE_PRESETS:
|
if name.upper() in climate.CLIMATE_PRESETS:
|
||||||
@ -872,6 +912,19 @@ async def to_code(config):
|
|||||||
else:
|
else:
|
||||||
cg.add(var.set_custom_preset_config(name, preset_target_variable))
|
cg.add(var.set_custom_preset_config(name, preset_target_variable))
|
||||||
|
|
||||||
|
if CONF_DEFAULT_PRESET in config:
|
||||||
|
default_preset_name = config[CONF_DEFAULT_PRESET]
|
||||||
|
|
||||||
|
# if the name is a built in preset use the appropriate naming format
|
||||||
|
if default_preset_name.upper() in climate.CLIMATE_PRESETS:
|
||||||
|
climate_preset = climate.CLIMATE_PRESETS[default_preset_name.upper()]
|
||||||
|
cg.add(var.set_default_preset(climate_preset))
|
||||||
|
else:
|
||||||
|
cg.add(var.set_default_preset(default_preset_name))
|
||||||
|
|
||||||
|
if CONF_ON_BOOT_RESTORE_FROM in config:
|
||||||
|
cg.add(var.set_on_boot_restore_from(config[CONF_ON_BOOT_RESTORE_FROM]))
|
||||||
|
|
||||||
if CONF_PRESET_CHANGE in config:
|
if CONF_PRESET_CHANGE in config:
|
||||||
await automation.build_automation(
|
await automation.build_automation(
|
||||||
var.get_preset_change_trigger(), [], config[CONF_PRESET_CHANGE]
|
var.get_preset_change_trigger(), [], config[CONF_PRESET_CHANGE]
|
||||||
|
@ -25,15 +25,27 @@ void ThermostatClimate::setup() {
|
|||||||
this->publish_state();
|
this->publish_state();
|
||||||
});
|
});
|
||||||
this->current_temperature = this->sensor_->state;
|
this->current_temperature = this->sensor_->state;
|
||||||
// restore all climate data, if possible
|
|
||||||
auto restore = this->restore_state_();
|
auto use_default_preset = true;
|
||||||
if (restore.has_value()) {
|
|
||||||
restore->to_call(this).perform();
|
if (this->on_boot_restore_from_ == thermostat::OnBootRestoreFrom::MEMORY) {
|
||||||
} else {
|
// restore all climate data, if possible
|
||||||
// restore from defaults, change_away handles temps for us
|
auto restore = this->restore_state_();
|
||||||
this->mode = this->default_mode_;
|
if (restore.has_value()) {
|
||||||
this->change_preset_(climate::CLIMATE_PRESET_HOME);
|
use_default_preset = false;
|
||||||
|
restore->to_call(this).perform();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Either we failed to restore state or the user has requested we always apply the default preset
|
||||||
|
if (use_default_preset) {
|
||||||
|
if (this->default_preset_ != climate::ClimatePreset::CLIMATE_PRESET_NONE) {
|
||||||
|
this->change_preset_(this->default_preset_);
|
||||||
|
} else if (!this->default_custom_preset_.empty()) {
|
||||||
|
this->change_custom_preset_(this->default_custom_preset_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// refresh the climate action based on the restored settings, we'll publish_state() later
|
// refresh the climate action based on the restored settings, we'll publish_state() later
|
||||||
this->switch_to_action_(this->compute_action_(), false);
|
this->switch_to_action_(this->compute_action_(), false);
|
||||||
this->switch_to_supplemental_action_(this->compute_supplemental_action_());
|
this->switch_to_supplemental_action_(this->compute_supplemental_action_());
|
||||||
@ -923,10 +935,12 @@ bool ThermostatClimate::supplemental_heating_required_() {
|
|||||||
(this->supplemental_action_ == climate::CLIMATE_ACTION_HEATING));
|
(this->supplemental_action_ == climate::CLIMATE_ACTION_HEATING));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThermostatClimate::dump_preset_config_(const std::string &preset,
|
void ThermostatClimate::dump_preset_config_(const std::string &preset, const ThermostatClimateTargetTempConfig &config,
|
||||||
const ThermostatClimateTargetTempConfig &config) {
|
bool is_default_preset) {
|
||||||
const auto *preset_name = preset.c_str();
|
const auto *preset_name = preset.c_str();
|
||||||
|
|
||||||
|
ESP_LOGCONFIG(TAG, " %s Is Default: %s", preset_name, YESNO(is_default_preset));
|
||||||
|
|
||||||
if (this->supports_heat_) {
|
if (this->supports_heat_) {
|
||||||
if (this->supports_two_points_) {
|
if (this->supports_two_points_) {
|
||||||
ESP_LOGCONFIG(TAG, " %s Default Target Temperature Low: %.1f°C", preset_name,
|
ESP_LOGCONFIG(TAG, " %s Default Target Temperature Low: %.1f°C", preset_name,
|
||||||
@ -1061,7 +1075,15 @@ ThermostatClimate::ThermostatClimate()
|
|||||||
temperature_change_trigger_(new Trigger<>()),
|
temperature_change_trigger_(new Trigger<>()),
|
||||||
preset_change_trigger_(new Trigger<>()) {}
|
preset_change_trigger_(new Trigger<>()) {}
|
||||||
|
|
||||||
void ThermostatClimate::set_default_mode(climate::ClimateMode default_mode) { this->default_mode_ = default_mode; }
|
void ThermostatClimate::set_default_preset(const std::string &custom_preset) {
|
||||||
|
this->default_custom_preset_ = custom_preset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThermostatClimate::set_default_preset(climate::ClimatePreset preset) { this->default_preset_ = preset; }
|
||||||
|
|
||||||
|
void ThermostatClimate::set_on_boot_restore_from(thermostat::OnBootRestoreFrom on_boot_restore_from) {
|
||||||
|
this->on_boot_restore_from_ = on_boot_restore_from;
|
||||||
|
}
|
||||||
void ThermostatClimate::set_set_point_minimum_differential(float differential) {
|
void ThermostatClimate::set_set_point_minimum_differential(float differential) {
|
||||||
this->set_point_minimum_differential_ = differential;
|
this->set_point_minimum_differential_ = differential;
|
||||||
}
|
}
|
||||||
@ -1213,8 +1235,9 @@ Trigger<> *ThermostatClimate::get_preset_change_trigger() const { return this->p
|
|||||||
void ThermostatClimate::dump_config() {
|
void ThermostatClimate::dump_config() {
|
||||||
LOG_CLIMATE("", "Thermostat", this);
|
LOG_CLIMATE("", "Thermostat", this);
|
||||||
|
|
||||||
if (this->supports_two_points_)
|
if (this->supports_two_points_) {
|
||||||
ESP_LOGCONFIG(TAG, " Minimum Set Point Differential: %.1f°C", this->set_point_minimum_differential_);
|
ESP_LOGCONFIG(TAG, " Minimum Set Point Differential: %.1f°C", this->set_point_minimum_differential_);
|
||||||
|
}
|
||||||
ESP_LOGCONFIG(TAG, " Start-up Delay Enabled: %s", YESNO(this->use_startup_delay_));
|
ESP_LOGCONFIG(TAG, " Start-up Delay Enabled: %s", YESNO(this->use_startup_delay_));
|
||||||
if (this->supports_cool_) {
|
if (this->supports_cool_) {
|
||||||
ESP_LOGCONFIG(TAG, " Cooling Parameters:");
|
ESP_LOGCONFIG(TAG, " Cooling Parameters:");
|
||||||
@ -1284,7 +1307,7 @@ void ThermostatClimate::dump_config() {
|
|||||||
const auto *preset_name = LOG_STR_ARG(climate::climate_preset_to_string(it.first));
|
const auto *preset_name = LOG_STR_ARG(climate::climate_preset_to_string(it.first));
|
||||||
|
|
||||||
ESP_LOGCONFIG(TAG, " Supports %s: %s", preset_name, YESNO(true));
|
ESP_LOGCONFIG(TAG, " Supports %s: %s", preset_name, YESNO(true));
|
||||||
this->dump_preset_config_(preset_name, it.second);
|
this->dump_preset_config_(preset_name, it.second, it.first == this->default_preset_);
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGCONFIG(TAG, " Supported CUSTOM PRESETS: ");
|
ESP_LOGCONFIG(TAG, " Supported CUSTOM PRESETS: ");
|
||||||
@ -1292,8 +1315,10 @@ void ThermostatClimate::dump_config() {
|
|||||||
const auto *preset_name = it.first.c_str();
|
const auto *preset_name = it.first.c_str();
|
||||||
|
|
||||||
ESP_LOGCONFIG(TAG, " Supports %s: %s", preset_name, YESNO(true));
|
ESP_LOGCONFIG(TAG, " Supports %s: %s", preset_name, YESNO(true));
|
||||||
this->dump_preset_config_(preset_name, it.second);
|
this->dump_preset_config_(preset_name, it.second, it.first == this->default_custom_preset_);
|
||||||
}
|
}
|
||||||
|
ESP_LOGCONFIG(TAG, " On boot, restore from: %s",
|
||||||
|
this->on_boot_restore_from_ == thermostat::DEFAULT_PRESET ? "DEFAULT_PRESET" : "MEMORY");
|
||||||
}
|
}
|
||||||
|
|
||||||
ThermostatClimateTargetTempConfig::ThermostatClimateTargetTempConfig() = default;
|
ThermostatClimateTargetTempConfig::ThermostatClimateTargetTempConfig() = default;
|
||||||
|
@ -22,6 +22,7 @@ enum ThermostatClimateTimerIndex : size_t {
|
|||||||
TIMER_IDLE_ON = 9,
|
TIMER_IDLE_ON = 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum OnBootRestoreFrom : size_t { MEMORY = 0, DEFAULT_PRESET = 1 };
|
||||||
struct ThermostatClimateTimer {
|
struct ThermostatClimateTimer {
|
||||||
const std::string name;
|
const std::string name;
|
||||||
bool active;
|
bool active;
|
||||||
@ -57,7 +58,9 @@ class ThermostatClimate : public climate::Climate, public Component {
|
|||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
|
|
||||||
void set_default_mode(climate::ClimateMode default_mode);
|
void set_default_preset(const std::string &custom_preset);
|
||||||
|
void set_default_preset(climate::ClimatePreset preset);
|
||||||
|
void set_on_boot_restore_from(thermostat::OnBootRestoreFrom on_boot_restore_from);
|
||||||
void set_set_point_minimum_differential(float differential);
|
void set_set_point_minimum_differential(float differential);
|
||||||
void set_cool_deadband(float deadband);
|
void set_cool_deadband(float deadband);
|
||||||
void set_cool_overrun(float overrun);
|
void set_cool_overrun(float overrun);
|
||||||
@ -225,7 +228,8 @@ class ThermostatClimate : public climate::Climate, public Component {
|
|||||||
bool supplemental_cooling_required_();
|
bool supplemental_cooling_required_();
|
||||||
bool supplemental_heating_required_();
|
bool supplemental_heating_required_();
|
||||||
|
|
||||||
void dump_preset_config_(const std::string &preset_name, const ThermostatClimateTargetTempConfig &config);
|
void dump_preset_config_(const std::string &preset_name, const ThermostatClimateTargetTempConfig &config,
|
||||||
|
bool is_default_preset);
|
||||||
|
|
||||||
/// The sensor used for getting the current temperature
|
/// The sensor used for getting the current temperature
|
||||||
sensor::Sensor *sensor_{nullptr};
|
sensor::Sensor *sensor_{nullptr};
|
||||||
@ -397,7 +401,6 @@ class ThermostatClimate : public climate::Climate, public Component {
|
|||||||
/// These are used to determine when a trigger/action needs to be called
|
/// These are used to determine when a trigger/action needs to be called
|
||||||
climate::ClimateAction supplemental_action_{climate::CLIMATE_ACTION_OFF};
|
climate::ClimateAction supplemental_action_{climate::CLIMATE_ACTION_OFF};
|
||||||
climate::ClimateFanMode prev_fan_mode_{climate::CLIMATE_FAN_ON};
|
climate::ClimateFanMode prev_fan_mode_{climate::CLIMATE_FAN_ON};
|
||||||
climate::ClimateMode default_mode_{climate::CLIMATE_MODE_OFF};
|
|
||||||
climate::ClimateMode prev_mode_{climate::CLIMATE_MODE_OFF};
|
climate::ClimateMode prev_mode_{climate::CLIMATE_MODE_OFF};
|
||||||
climate::ClimateSwingMode prev_swing_mode_{climate::CLIMATE_SWING_OFF};
|
climate::ClimateSwingMode prev_swing_mode_{climate::CLIMATE_SWING_OFF};
|
||||||
|
|
||||||
@ -441,6 +444,15 @@ class ThermostatClimate : public climate::Climate, public Component {
|
|||||||
std::map<climate::ClimatePreset, ThermostatClimateTargetTempConfig> preset_config_{};
|
std::map<climate::ClimatePreset, ThermostatClimateTargetTempConfig> preset_config_{};
|
||||||
/// The set of custom preset configurations this thermostat supports (eg. "My Custom Preset")
|
/// The set of custom preset configurations this thermostat supports (eg. "My Custom Preset")
|
||||||
std::map<std::string, ThermostatClimateTargetTempConfig> custom_preset_config_{};
|
std::map<std::string, ThermostatClimateTargetTempConfig> custom_preset_config_{};
|
||||||
|
|
||||||
|
/// Default standard preset to use on start up
|
||||||
|
climate::ClimatePreset default_preset_{};
|
||||||
|
/// Default custom preset to use on start up
|
||||||
|
std::string default_custom_preset_{};
|
||||||
|
|
||||||
|
/// If set to DEFAULT_PRESET then the default preset is always used. When MEMORY prior
|
||||||
|
/// state will attempt to be restored if possible
|
||||||
|
thermostat::OnBootRestoreFrom on_boot_restore_from_{thermostat::OnBootRestoreFrom::MEMORY};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace thermostat
|
} // namespace thermostat
|
||||||
|
@ -1061,8 +1061,13 @@ climate:
|
|||||||
- platform: thermostat
|
- platform: thermostat
|
||||||
name: Thermostat Climate
|
name: Thermostat Climate
|
||||||
sensor: ha_hello_world
|
sensor: ha_hello_world
|
||||||
default_target_temperature_low: 18°C
|
preset:
|
||||||
default_target_temperature_high: 24°C
|
- name: Default Preset
|
||||||
|
default_target_temperature_low: 18°C
|
||||||
|
default_target_temperature_high: 24°C
|
||||||
|
- name: Away
|
||||||
|
default_target_temperature_low: 16°C
|
||||||
|
default_target_temperature_high: 20°C
|
||||||
idle_action:
|
idle_action:
|
||||||
- switch.turn_on: gpio_switch1
|
- switch.turn_on: gpio_switch1
|
||||||
cool_action:
|
cool_action:
|
||||||
@ -1137,9 +1142,6 @@ climate:
|
|||||||
fan_only_cooling: true
|
fan_only_cooling: true
|
||||||
fan_with_cooling: true
|
fan_with_cooling: true
|
||||||
fan_with_heating: true
|
fan_with_heating: true
|
||||||
away_config:
|
|
||||||
default_target_temperature_low: 16°C
|
|
||||||
default_target_temperature_high: 20°C
|
|
||||||
- platform: pid
|
- platform: pid
|
||||||
id: pid_climate
|
id: pid_climate
|
||||||
name: PID Climate Controller
|
name: PID Climate Controller
|
||||||
|
Loading…
x
Reference in New Issue
Block a user