mirror of
https://github.com/esphome/esphome.git
synced 2026-06-24 15:10:51 +00:00
[core] Replace custom esphome::optional with std::optional (#14368)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -63,8 +63,9 @@ void Am43Component::control(const CoverCall &call) {
|
||||
ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status);
|
||||
}
|
||||
}
|
||||
if (call.get_position().has_value()) {
|
||||
auto pos = *call.get_position();
|
||||
auto opt_pos = call.get_position();
|
||||
if (opt_pos.has_value()) {
|
||||
auto pos = *opt_pos;
|
||||
|
||||
if (this->invert_position_)
|
||||
pos = 1 - pos;
|
||||
|
||||
@@ -24,8 +24,9 @@ void Anova::loop() {
|
||||
}
|
||||
|
||||
void Anova::control(const ClimateCall &call) {
|
||||
if (call.get_mode().has_value()) {
|
||||
ClimateMode mode = *call.get_mode();
|
||||
auto mode_val = call.get_mode();
|
||||
if (mode_val.has_value()) {
|
||||
ClimateMode mode = *mode_val;
|
||||
AnovaPacket *pkt;
|
||||
switch (mode) {
|
||||
case climate::CLIMATE_MODE_OFF:
|
||||
@@ -45,8 +46,9 @@ void Anova::control(const ClimateCall &call) {
|
||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str(), status);
|
||||
}
|
||||
}
|
||||
if (call.get_target_temperature().has_value()) {
|
||||
auto *pkt = this->codec_->get_set_target_temp_request(*call.get_target_temperature());
|
||||
auto target_temp = call.get_target_temperature();
|
||||
if (target_temp.has_value()) {
|
||||
auto *pkt = this->codec_->get_set_target_temp_request(*target_temp);
|
||||
auto status =
|
||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||
pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
|
||||
@@ -47,7 +47,7 @@ void BalluClimate::transmit_state() {
|
||||
remote_state[11] = 0x1e;
|
||||
|
||||
// Fan speed
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_HIGH:
|
||||
remote_state[4] |= BALLU_FAN_HIGH;
|
||||
break;
|
||||
|
||||
@@ -45,17 +45,21 @@ void BangBangClimate::setup() {
|
||||
}
|
||||
|
||||
void BangBangClimate::control(const climate::ClimateCall &call) {
|
||||
if (call.get_mode().has_value()) {
|
||||
this->mode = *call.get_mode();
|
||||
auto mode = call.get_mode();
|
||||
if (mode.has_value()) {
|
||||
this->mode = *mode;
|
||||
}
|
||||
if (call.get_target_temperature_low().has_value()) {
|
||||
this->target_temperature_low = *call.get_target_temperature_low();
|
||||
auto target_temperature_low = call.get_target_temperature_low();
|
||||
if (target_temperature_low.has_value()) {
|
||||
this->target_temperature_low = *target_temperature_low;
|
||||
}
|
||||
if (call.get_target_temperature_high().has_value()) {
|
||||
this->target_temperature_high = *call.get_target_temperature_high();
|
||||
auto target_temperature_high = call.get_target_temperature_high();
|
||||
if (target_temperature_high.has_value()) {
|
||||
this->target_temperature_high = *target_temperature_high;
|
||||
}
|
||||
if (call.get_preset().has_value()) {
|
||||
this->change_away_(*call.get_preset() == climate::CLIMATE_PRESET_AWAY);
|
||||
auto preset = call.get_preset();
|
||||
if (preset.has_value()) {
|
||||
this->change_away_(*preset == climate::CLIMATE_PRESET_AWAY);
|
||||
}
|
||||
|
||||
this->compute_state_();
|
||||
|
||||
@@ -96,8 +96,9 @@ void BedJetClimate::control(const ClimateCall &call) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (call.get_mode().has_value()) {
|
||||
ClimateMode mode = *call.get_mode();
|
||||
auto mode_opt = call.get_mode();
|
||||
if (mode_opt.has_value()) {
|
||||
ClimateMode mode = *mode_opt;
|
||||
bool button_result;
|
||||
switch (mode) {
|
||||
case CLIMATE_MODE_OFF:
|
||||
@@ -125,8 +126,9 @@ void BedJetClimate::control(const ClimateCall &call) {
|
||||
}
|
||||
}
|
||||
|
||||
if (call.get_target_temperature().has_value()) {
|
||||
auto target_temp = *call.get_target_temperature();
|
||||
auto target_temp_opt = call.get_target_temperature();
|
||||
if (target_temp_opt.has_value()) {
|
||||
auto target_temp = *target_temp_opt;
|
||||
auto result = this->parent_->set_target_temp(target_temp);
|
||||
|
||||
if (result) {
|
||||
@@ -134,8 +136,9 @@ void BedJetClimate::control(const ClimateCall &call) {
|
||||
}
|
||||
}
|
||||
|
||||
if (call.get_preset().has_value()) {
|
||||
ClimatePreset preset = *call.get_preset();
|
||||
auto preset_opt = call.get_preset();
|
||||
if (preset_opt.has_value()) {
|
||||
ClimatePreset preset = *preset_opt;
|
||||
bool result;
|
||||
|
||||
if (preset == CLIMATE_PRESET_BOOST) {
|
||||
@@ -187,10 +190,11 @@ void BedJetClimate::control(const ClimateCall &call) {
|
||||
}
|
||||
}
|
||||
|
||||
if (call.get_fan_mode().has_value()) {
|
||||
auto fan_mode_opt = call.get_fan_mode();
|
||||
if (fan_mode_opt.has_value()) {
|
||||
// Climate fan mode only supports low/med/high, but the BedJet supports 5-100% increments.
|
||||
// We can still support a ClimateCall that requests low/med/high, and just translate it to a step increment here.
|
||||
auto fan_mode = *call.get_fan_mode();
|
||||
auto fan_mode = *fan_mode_opt;
|
||||
bool result;
|
||||
if (fan_mode == CLIMATE_FAN_LOW) {
|
||||
result = this->parent_->set_fan_speed(20);
|
||||
|
||||
@@ -19,7 +19,8 @@ void BedJetFan::control(const fan::FanCall &call) {
|
||||
}
|
||||
bool did_change = false;
|
||||
|
||||
if (call.get_state().has_value() && this->state != *call.get_state()) {
|
||||
auto state_opt = call.get_state();
|
||||
if (state_opt.has_value() && this->state != *state_opt) {
|
||||
// Turning off is easy:
|
||||
if (this->state && this->parent_->button_off()) {
|
||||
this->state = false;
|
||||
@@ -36,8 +37,9 @@ void BedJetFan::control(const fan::FanCall &call) {
|
||||
}
|
||||
|
||||
// ignore speed changes if not on or turning on
|
||||
if (this->state && call.get_speed().has_value()) {
|
||||
auto speed = *call.get_speed();
|
||||
auto speed_opt = call.get_speed();
|
||||
if (this->state && speed_opt.has_value()) {
|
||||
auto speed = *speed_opt;
|
||||
if (speed >= 1) {
|
||||
this->speed = speed;
|
||||
// Fan.speed is 1-20, but Bedjet expects 0-19, so subtract 1
|
||||
|
||||
@@ -18,12 +18,15 @@ fan::FanTraits BinaryFan::get_traits() {
|
||||
return fan::FanTraits(this->oscillating_ != nullptr, false, this->direction_ != nullptr, 0);
|
||||
}
|
||||
void BinaryFan::control(const fan::FanCall &call) {
|
||||
if (call.get_state().has_value())
|
||||
this->state = *call.get_state();
|
||||
if (call.get_oscillating().has_value())
|
||||
this->oscillating = *call.get_oscillating();
|
||||
if (call.get_direction().has_value())
|
||||
this->direction = *call.get_direction();
|
||||
auto state = call.get_state();
|
||||
if (state.has_value())
|
||||
this->state = *state;
|
||||
auto oscillating = call.get_oscillating();
|
||||
if (oscillating.has_value())
|
||||
this->oscillating = *oscillating;
|
||||
auto direction = call.get_direction();
|
||||
if (direction.has_value())
|
||||
this->direction = *direction;
|
||||
|
||||
this->write_state_();
|
||||
this->publish_state();
|
||||
|
||||
@@ -76,11 +76,12 @@ class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff,
|
||||
}
|
||||
break;
|
||||
case MATCH_BY_IBEACON_UUID:
|
||||
if (!device.get_ibeacon().has_value()) {
|
||||
auto maybe_ibeacon = device.get_ibeacon();
|
||||
if (!maybe_ibeacon.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ibeacon = device.get_ibeacon().value();
|
||||
auto ibeacon = *maybe_ibeacon;
|
||||
|
||||
if (this->ibeacon_uuid_ != ibeacon.get_uuid()) {
|
||||
return false;
|
||||
|
||||
@@ -74,11 +74,12 @@ class BLERSSISensor : public sensor::Sensor, public esp32_ble_tracker::ESPBTDevi
|
||||
}
|
||||
break;
|
||||
case MATCH_BY_IBEACON_UUID:
|
||||
if (!device.get_ibeacon().has_value()) {
|
||||
auto maybe_ibeacon = device.get_ibeacon();
|
||||
if (!maybe_ibeacon.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ibeacon = device.get_ibeacon().value();
|
||||
auto ibeacon = *maybe_ibeacon;
|
||||
|
||||
if (this->ibeacon_uuid_ != ibeacon.get_uuid()) {
|
||||
return false;
|
||||
|
||||
@@ -71,16 +71,21 @@ void ClimateIR::setup() {
|
||||
}
|
||||
|
||||
void ClimateIR::control(const climate::ClimateCall &call) {
|
||||
if (call.get_mode().has_value())
|
||||
this->mode = *call.get_mode();
|
||||
if (call.get_target_temperature().has_value())
|
||||
this->target_temperature = *call.get_target_temperature();
|
||||
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_preset().has_value())
|
||||
this->preset = *call.get_preset();
|
||||
auto mode = call.get_mode();
|
||||
if (mode.has_value())
|
||||
this->mode = *mode;
|
||||
auto target_temperature = call.get_target_temperature();
|
||||
if (target_temperature.has_value())
|
||||
this->target_temperature = *target_temperature;
|
||||
auto fan_mode = call.get_fan_mode();
|
||||
if (fan_mode.has_value())
|
||||
this->fan_mode = fan_mode;
|
||||
auto swing_mode = call.get_swing_mode();
|
||||
if (swing_mode.has_value())
|
||||
this->swing_mode = *swing_mode;
|
||||
auto preset = call.get_preset();
|
||||
if (preset.has_value())
|
||||
this->preset = preset;
|
||||
this->transmit_state();
|
||||
this->publish_state();
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ void LgIrClimate::transmit_state() {
|
||||
if (this->mode == climate::CLIMATE_MODE_OFF) {
|
||||
remote_state |= FAN_AUTO;
|
||||
} else {
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_HIGH:
|
||||
remote_state |= FAN_MAX;
|
||||
break;
|
||||
|
||||
@@ -23,7 +23,8 @@ class LgIrClimate : public climate_ir::ClimateIR {
|
||||
void control(const climate::ClimateCall &call) override {
|
||||
this->send_swing_cmd_ = call.get_swing_mode().has_value();
|
||||
// swing resets after unit powered off
|
||||
if (call.get_mode().has_value() && *call.get_mode() == climate::CLIMATE_MODE_OFF)
|
||||
auto mode = call.get_mode();
|
||||
if (mode.has_value() && *mode == climate::CLIMATE_MODE_OFF)
|
||||
this->swing_mode = climate::CLIMATE_SWING_OFF;
|
||||
climate_ir::ClimateIR::control(call);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ void CoolixClimate::transmit_state() {
|
||||
this->fan_mode = climate::CLIMATE_FAN_AUTO;
|
||||
remote_state |= COOLIX_FAN_MODE_AUTO_DRY;
|
||||
} else {
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_HIGH:
|
||||
remote_state |= COOLIX_FAN_MAX;
|
||||
break;
|
||||
|
||||
@@ -23,7 +23,8 @@ class CoolixClimate : public climate_ir::ClimateIR {
|
||||
void control(const climate::ClimateCall &call) override {
|
||||
send_swing_cmd_ = call.get_swing_mode().has_value();
|
||||
// swing resets after unit powered off
|
||||
if (call.get_mode().has_value() && *call.get_mode() == climate::CLIMATE_MODE_OFF)
|
||||
auto mode = call.get_mode();
|
||||
if (mode.has_value() && *mode == climate::CLIMATE_MODE_OFF)
|
||||
this->swing_mode = climate::CLIMATE_SWING_OFF;
|
||||
climate_ir::ClimateIR::control(call);
|
||||
}
|
||||
|
||||
@@ -38,12 +38,15 @@ cover::CoverTraits CopyCover::get_traits() {
|
||||
void CopyCover::control(const cover::CoverCall &call) {
|
||||
auto call2 = source_->make_call();
|
||||
call2.set_stop(call.get_stop());
|
||||
if (call.get_tilt().has_value())
|
||||
call2.set_tilt(*call.get_tilt());
|
||||
if (call.get_position().has_value())
|
||||
call2.set_position(*call.get_position());
|
||||
if (call.get_tilt().has_value())
|
||||
call2.set_tilt(*call.get_tilt());
|
||||
auto tilt = call.get_tilt();
|
||||
if (tilt.has_value())
|
||||
call2.set_tilt(*tilt);
|
||||
auto position = call.get_position();
|
||||
if (position.has_value())
|
||||
call2.set_position(*position);
|
||||
auto tilt2 = call.get_tilt();
|
||||
if (tilt2.has_value())
|
||||
call2.set_tilt(*tilt2);
|
||||
call2.perform();
|
||||
}
|
||||
|
||||
|
||||
@@ -45,14 +45,18 @@ fan::FanTraits CopyFan::get_traits() {
|
||||
|
||||
void CopyFan::control(const fan::FanCall &call) {
|
||||
auto call2 = source_->make_call();
|
||||
if (call.get_state().has_value())
|
||||
call2.set_state(*call.get_state());
|
||||
if (call.get_oscillating().has_value())
|
||||
call2.set_oscillating(*call.get_oscillating());
|
||||
if (call.get_speed().has_value())
|
||||
call2.set_speed(*call.get_speed());
|
||||
if (call.get_direction().has_value())
|
||||
call2.set_direction(*call.get_direction());
|
||||
auto state = call.get_state();
|
||||
if (state.has_value())
|
||||
call2.set_state(*state);
|
||||
auto oscillating = call.get_oscillating();
|
||||
if (oscillating.has_value())
|
||||
call2.set_oscillating(*oscillating);
|
||||
auto speed = call.get_speed();
|
||||
if (speed.has_value())
|
||||
call2.set_speed(*speed);
|
||||
auto direction = call.get_direction();
|
||||
if (direction.has_value())
|
||||
call2.set_direction(*direction);
|
||||
if (call.has_preset_mode())
|
||||
call2.set_preset_mode(call.get_preset_mode());
|
||||
call2.perform();
|
||||
|
||||
@@ -11,8 +11,9 @@ void CopySelect::setup() {
|
||||
|
||||
traits.set_options(source_->traits.get_options());
|
||||
|
||||
if (source_->has_state())
|
||||
this->publish_state(source_->active_index().value());
|
||||
auto idx = this->source_->active_index();
|
||||
if (idx.has_value())
|
||||
this->publish_state(*idx);
|
||||
}
|
||||
|
||||
void CopySelect::dump_config() { LOG_SELECT("", "Copy Select", this); }
|
||||
|
||||
@@ -37,8 +37,9 @@ void CurrentBasedCover::control(const CoverCall &call) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (call.get_position().has_value()) {
|
||||
auto pos = *call.get_position();
|
||||
auto opt_pos = call.get_position();
|
||||
if (opt_pos.has_value()) {
|
||||
auto pos = *opt_pos;
|
||||
if (fabsf(this->position - pos) < 0.01) {
|
||||
// already at target
|
||||
} else {
|
||||
|
||||
@@ -94,7 +94,7 @@ uint8_t DaikinClimate::operation_mode_() const {
|
||||
|
||||
uint16_t DaikinClimate::fan_speed_() const {
|
||||
uint16_t fan_speed;
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_QUIET:
|
||||
fan_speed = DAIKIN_FAN_SILENT << 8;
|
||||
break;
|
||||
|
||||
@@ -176,7 +176,7 @@ uint8_t DaikinArcClimate::operation_mode_() {
|
||||
|
||||
uint16_t DaikinArcClimate::fan_speed_() {
|
||||
uint16_t fan_speed;
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
fan_speed = DAIKIN_FAN_1 << 8;
|
||||
break;
|
||||
@@ -485,8 +485,9 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) {
|
||||
}
|
||||
|
||||
void DaikinArcClimate::control(const climate::ClimateCall &call) {
|
||||
if (call.get_target_humidity().has_value()) {
|
||||
this->target_humidity = *call.get_target_humidity();
|
||||
auto target_humidity = call.get_target_humidity();
|
||||
if (target_humidity.has_value()) {
|
||||
this->target_humidity = *target_humidity;
|
||||
}
|
||||
climate_ir::ClimateIR::control(call);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ uint8_t DaikinBrcClimate::operation_mode_() {
|
||||
|
||||
uint8_t DaikinBrcClimate::fan_speed_swing_() {
|
||||
uint16_t fan_speed;
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
fan_speed = DAIKIN_BRC_FAN_1;
|
||||
break;
|
||||
|
||||
@@ -15,7 +15,7 @@ void DeepSleepComponent::dump_config_platform_() {}
|
||||
bool DeepSleepComponent::prepare_to_sleep_() { return true; }
|
||||
|
||||
void DeepSleepComponent::deep_sleep_() {
|
||||
ESP.deepSleep(*this->sleep_duration_); // NOLINT(readability-static-accessed-through-instance)
|
||||
ESP.deepSleep(this->sleep_duration_.value_or(0)); // NOLINT(readability-static-accessed-through-instance)
|
||||
}
|
||||
|
||||
} // namespace deep_sleep
|
||||
|
||||
@@ -64,7 +64,7 @@ uint8_t DelonghiClimate::operation_mode_() {
|
||||
|
||||
uint16_t DelonghiClimate::fan_speed_() {
|
||||
uint16_t fan_speed;
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
fan_speed = DELONGHI_FAN_LOW;
|
||||
break;
|
||||
|
||||
@@ -29,10 +29,11 @@ class DemoAlarmControlPanel : public AlarmControlPanel, public Component {
|
||||
protected:
|
||||
void control(const AlarmControlPanelCall &call) override {
|
||||
auto state = call.get_state().value_or(ACP_STATE_DISARMED);
|
||||
auto code = call.get_code();
|
||||
switch (state) {
|
||||
case ACP_STATE_ARMED_AWAY:
|
||||
if (this->get_requires_code_to_arm() && call.get_code().has_value()) {
|
||||
if (call.get_code().value() != "1234") {
|
||||
if (this->get_requires_code_to_arm() && code.has_value()) {
|
||||
if (*code != "1234") {
|
||||
this->status_momentary_error("invalid_code", 5000);
|
||||
return;
|
||||
}
|
||||
@@ -40,8 +41,8 @@ class DemoAlarmControlPanel : public AlarmControlPanel, public Component {
|
||||
this->publish_state(ACP_STATE_ARMED_AWAY);
|
||||
break;
|
||||
case ACP_STATE_DISARMED:
|
||||
if (this->get_requires_code() && call.get_code().has_value()) {
|
||||
if (call.get_code().value() != "1234") {
|
||||
if (this->get_requires_code() && code.has_value()) {
|
||||
if (*code != "1234") {
|
||||
this->status_momentary_error("invalid_code", 5000);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -45,33 +45,31 @@ class DemoClimate : public climate::Climate, public Component {
|
||||
|
||||
protected:
|
||||
void control(const climate::ClimateCall &call) override {
|
||||
if (call.get_mode().has_value()) {
|
||||
this->mode = *call.get_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_fan_mode().has_value()) {
|
||||
this->set_fan_mode_(*call.get_fan_mode());
|
||||
}
|
||||
if (call.get_swing_mode().has_value()) {
|
||||
this->swing_mode = *call.get_swing_mode();
|
||||
}
|
||||
if (call.has_custom_fan_mode()) {
|
||||
auto mode = call.get_mode();
|
||||
if (mode.has_value())
|
||||
this->mode = *mode;
|
||||
auto target_temperature = call.get_target_temperature();
|
||||
if (target_temperature.has_value())
|
||||
this->target_temperature = *target_temperature;
|
||||
auto target_temperature_low = call.get_target_temperature_low();
|
||||
if (target_temperature_low.has_value())
|
||||
this->target_temperature_low = *target_temperature_low;
|
||||
auto target_temperature_high = call.get_target_temperature_high();
|
||||
if (target_temperature_high.has_value())
|
||||
this->target_temperature_high = *target_temperature_high;
|
||||
auto fan_mode = call.get_fan_mode();
|
||||
if (fan_mode.has_value())
|
||||
this->set_fan_mode_(*fan_mode);
|
||||
auto swing_mode = call.get_swing_mode();
|
||||
if (swing_mode.has_value())
|
||||
this->swing_mode = *swing_mode;
|
||||
if (call.has_custom_fan_mode())
|
||||
this->set_custom_fan_mode_(call.get_custom_fan_mode());
|
||||
}
|
||||
if (call.get_preset().has_value()) {
|
||||
this->set_preset_(*call.get_preset());
|
||||
}
|
||||
if (call.has_custom_preset()) {
|
||||
auto preset = call.get_preset();
|
||||
if (preset.has_value())
|
||||
this->set_preset_(*preset);
|
||||
if (call.has_custom_preset())
|
||||
this->set_custom_preset_(call.get_custom_preset());
|
||||
}
|
||||
this->publish_state();
|
||||
}
|
||||
climate::ClimateTraits traits() override {
|
||||
|
||||
@@ -38,8 +38,9 @@ class DemoCover : public cover::Cover, public Component {
|
||||
|
||||
protected:
|
||||
void control(const cover::CoverCall &call) override {
|
||||
if (call.get_position().has_value()) {
|
||||
float target = *call.get_position();
|
||||
auto pos = call.get_position();
|
||||
if (pos.has_value()) {
|
||||
float target = *pos;
|
||||
this->current_operation =
|
||||
target > this->position ? cover::COVER_OPERATION_OPENING : cover::COVER_OPERATION_CLOSING;
|
||||
|
||||
@@ -49,8 +50,9 @@ class DemoCover : public cover::Cover, public Component {
|
||||
this->publish_state();
|
||||
});
|
||||
}
|
||||
if (call.get_tilt().has_value()) {
|
||||
this->tilt = *call.get_tilt();
|
||||
auto tilt = call.get_tilt();
|
||||
if (tilt.has_value()) {
|
||||
this->tilt = *tilt;
|
||||
}
|
||||
if (call.get_stop()) {
|
||||
this->cancel_timeout("move");
|
||||
|
||||
@@ -47,14 +47,18 @@ class DemoFan : public fan::Fan, public Component {
|
||||
|
||||
protected:
|
||||
void control(const fan::FanCall &call) override {
|
||||
if (call.get_state().has_value())
|
||||
this->state = *call.get_state();
|
||||
if (call.get_oscillating().has_value())
|
||||
this->oscillating = *call.get_oscillating();
|
||||
if (call.get_speed().has_value())
|
||||
this->speed = *call.get_speed();
|
||||
if (call.get_direction().has_value())
|
||||
this->direction = *call.get_direction();
|
||||
auto state = call.get_state();
|
||||
if (state.has_value())
|
||||
this->state = *state;
|
||||
auto oscillating = call.get_oscillating();
|
||||
if (oscillating.has_value())
|
||||
this->oscillating = *oscillating;
|
||||
auto speed = call.get_speed();
|
||||
if (speed.has_value())
|
||||
this->speed = *speed;
|
||||
auto direction = call.get_direction();
|
||||
if (direction.has_value())
|
||||
this->direction = *direction;
|
||||
|
||||
this->publish_state();
|
||||
}
|
||||
|
||||
@@ -8,8 +8,9 @@ namespace demo {
|
||||
class DemoLock : public lock::Lock {
|
||||
protected:
|
||||
void control(const lock::LockCall &call) override {
|
||||
auto state = *call.get_state();
|
||||
this->publish_state(state);
|
||||
auto state = call.get_state();
|
||||
if (state.has_value())
|
||||
this->publish_state(*state);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -26,12 +26,15 @@ class DemoValve : public valve::Valve {
|
||||
|
||||
protected:
|
||||
void control(const valve::ValveCall &call) override {
|
||||
if (call.get_position().has_value()) {
|
||||
this->position = *call.get_position();
|
||||
auto pos = call.get_position();
|
||||
if (pos.has_value()) {
|
||||
this->position = *pos;
|
||||
this->publish_state();
|
||||
return;
|
||||
} else if (call.get_toggle().has_value()) {
|
||||
if (call.get_toggle().value()) {
|
||||
}
|
||||
auto toggle = call.get_toggle();
|
||||
if (toggle.has_value()) {
|
||||
if (*toggle) {
|
||||
if (this->position == valve::VALVE_OPEN) {
|
||||
this->position = valve::VALVE_CLOSED;
|
||||
this->publish_state();
|
||||
|
||||
@@ -28,7 +28,7 @@ uint8_t EmmetiClimate::set_mode_() {
|
||||
}
|
||||
|
||||
uint8_t EmmetiClimate::set_fan_speed_() {
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
return EMMETI_FAN_1;
|
||||
case climate::CLIMATE_FAN_MEDIUM:
|
||||
|
||||
@@ -37,8 +37,9 @@ void EndstopCover::control(const CoverCall &call) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (call.get_position().has_value()) {
|
||||
auto pos = *call.get_position();
|
||||
auto opt_pos = call.get_position();
|
||||
if (opt_pos.has_value()) {
|
||||
auto pos = *opt_pos;
|
||||
if (pos == this->position) {
|
||||
// already at target
|
||||
} else {
|
||||
|
||||
@@ -107,7 +107,7 @@ class ESPBTDevice {
|
||||
for (auto &it : this->manufacturer_datas_) {
|
||||
auto res = ESPBLEiBeacon::from_manufacturer_data(it);
|
||||
if (res.has_value())
|
||||
return *res;
|
||||
return res;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -162,7 +162,8 @@ void ESP32RMTLEDStripLightOutput::set_led_params(uint32_t bit0_high, uint32_t bi
|
||||
void ESP32RMTLEDStripLightOutput::write_state(light::LightState *state) {
|
||||
// protect from refreshing too often
|
||||
uint32_t now = micros();
|
||||
if (*this->max_refresh_rate_ != 0 && (now - this->last_refresh_) < *this->max_refresh_rate_) {
|
||||
auto rate = this->max_refresh_rate_.value_or(0);
|
||||
if (rate != 0 && (now - this->last_refresh_) < rate) {
|
||||
// try again next loop iteration, so that this change won't get lost
|
||||
this->schedule_show();
|
||||
return;
|
||||
@@ -301,7 +302,7 @@ void ESP32RMTLEDStripLightOutput::dump_config() {
|
||||
" RGB Order: %s\n"
|
||||
" Max refresh rate: %" PRIu32 "\n"
|
||||
" Number of LEDs: %u",
|
||||
rgb_order, *this->max_refresh_rate_, this->num_leds_);
|
||||
rgb_order, this->max_refresh_rate_.value_or(0), this->num_leds_);
|
||||
}
|
||||
|
||||
float ESP32RMTLEDStripLightOutput::get_setup_priority() const { return setup_priority::HARDWARE; }
|
||||
|
||||
@@ -21,12 +21,13 @@ void FastLEDLightOutput::dump_config() {
|
||||
"FastLED light:\n"
|
||||
" Num LEDs: %u\n"
|
||||
" Max refresh rate: %u",
|
||||
this->num_leds_, *this->max_refresh_rate_);
|
||||
this->num_leds_, this->max_refresh_rate_.value_or(0));
|
||||
}
|
||||
void FastLEDLightOutput::write_state(light::LightState *state) {
|
||||
// protect from refreshing too often
|
||||
uint32_t now = micros();
|
||||
if (*this->max_refresh_rate_ != 0 && (now - this->last_refresh_) < *this->max_refresh_rate_) {
|
||||
uint32_t max_rate = this->max_refresh_rate_.value_or(0);
|
||||
if (max_rate != 0 && (now - this->last_refresh_) < max_rate) {
|
||||
// try again next loop iteration, so that this change won't get lost
|
||||
this->schedule_show();
|
||||
return;
|
||||
|
||||
@@ -269,9 +269,12 @@ void FeedbackCover::control(const CoverCall &call) {
|
||||
this->start_direction_(COVER_OPERATION_CLOSING);
|
||||
}
|
||||
}
|
||||
} else if (call.get_position().has_value()) {
|
||||
} else {
|
||||
auto pos_opt = call.get_position();
|
||||
if (!pos_opt.has_value())
|
||||
return;
|
||||
// go to position action
|
||||
auto pos = *call.get_position();
|
||||
auto pos = *pos_opt;
|
||||
if (pos == this->position) {
|
||||
// already at target,
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ void FujitsuGeneralClimate::transmit_state() {
|
||||
}
|
||||
|
||||
// Set fan
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_HIGH:
|
||||
SET_NIBBLE(remote_state, FUJITSU_GENERAL_FAN_NIBBLE, FUJITSU_GENERAL_FAN_HIGH);
|
||||
break;
|
||||
|
||||
@@ -180,7 +180,7 @@ uint8_t GreeClimate::operation_mode_() {
|
||||
uint8_t GreeClimate::fan_speed_() {
|
||||
// YX1FF has 4 fan speeds -- we treat low as quiet and turbo as high
|
||||
if (this->model_ == GREE_YX1FF) {
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_QUIET:
|
||||
return GREE_FAN_1;
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
@@ -195,7 +195,7 @@ uint8_t GreeClimate::fan_speed_() {
|
||||
}
|
||||
}
|
||||
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
return GREE_FAN_1;
|
||||
case climate::CLIMATE_FAN_MEDIUM:
|
||||
@@ -235,7 +235,7 @@ uint8_t GreeClimate::temperature_() {
|
||||
uint8_t GreeClimate::preset_() {
|
||||
// YX1FF has sleep preset
|
||||
if (this->model_ == GREE_YX1FF) {
|
||||
switch (this->preset.value()) {
|
||||
switch (this->preset.value_or(climate::CLIMATE_PRESET_NONE)) {
|
||||
case climate::CLIMATE_PRESET_NONE:
|
||||
return GREE_PRESET_NONE;
|
||||
case climate::CLIMATE_PRESET_SLEEP:
|
||||
|
||||
@@ -893,7 +893,8 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *
|
||||
} else {
|
||||
this->preset = CLIMATE_PRESET_NONE;
|
||||
}
|
||||
should_publish = should_publish || (!old_preset.has_value()) || (old_preset.value() != this->preset.value());
|
||||
should_publish = should_publish || (!old_preset.has_value()) ||
|
||||
(old_preset.value_or(CLIMATE_PRESET_NONE) != this->preset.value_or(CLIMATE_PRESET_NONE));
|
||||
}
|
||||
{
|
||||
// Target temperature
|
||||
@@ -936,7 +937,8 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *
|
||||
this->fan_mode = CLIMATE_FAN_HIGH;
|
||||
break;
|
||||
}
|
||||
should_publish = should_publish || (!old_fan_mode.has_value()) || (old_fan_mode.value() != fan_mode.value());
|
||||
should_publish = should_publish || (!old_fan_mode.has_value()) ||
|
||||
(old_fan_mode.value_or(CLIMATE_FAN_ON) != this->fan_mode.value_or(CLIMATE_FAN_ON));
|
||||
}
|
||||
// Display status
|
||||
// should be before "Climate mode" because it is changing this->mode
|
||||
@@ -1301,7 +1303,8 @@ void HonClimate::clear_control_messages_queue_() {
|
||||
}
|
||||
|
||||
bool HonClimate::prepare_pending_action() {
|
||||
switch (this->action_request_.value().action) {
|
||||
auto &action_request = this->action_request_.value(); // NOLINT(bugprone-unchecked-optional-access)
|
||||
switch (action_request.action) {
|
||||
case ActionRequest::START_SELF_CLEAN:
|
||||
if (this->control_method_ == HonControlMethod::SET_GROUP_PARAMETERS) {
|
||||
uint8_t control_out_buffer[haier_protocol::MAX_FRAME_SIZE];
|
||||
@@ -1315,12 +1318,12 @@ bool HonClimate::prepare_pending_action() {
|
||||
out_data->ac_power = 1;
|
||||
out_data->ac_mode = (uint8_t) hon_protocol::ConditioningMode::DRY;
|
||||
out_data->light_status = 0;
|
||||
this->action_request_.value().message = haier_protocol::HaierMessage(
|
||||
action_request.message = haier_protocol::HaierMessage(
|
||||
haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_GROUP_PARAMETERS,
|
||||
control_out_buffer, this->real_control_packet_size_);
|
||||
return true;
|
||||
} else if (this->control_method_ == HonControlMethod::SET_SINGLE_PARAMETER) {
|
||||
this->action_request_.value().message =
|
||||
action_request.message =
|
||||
haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL,
|
||||
(uint16_t) hon_protocol::SubcommandsControl::SET_SINGLE_PARAMETER +
|
||||
(uint8_t) hon_protocol::DataParameters::SELF_CLEANING,
|
||||
@@ -1343,7 +1346,7 @@ bool HonClimate::prepare_pending_action() {
|
||||
out_data->ac_power = 1;
|
||||
out_data->ac_mode = (uint8_t) hon_protocol::ConditioningMode::DRY;
|
||||
out_data->light_status = 0;
|
||||
this->action_request_.value().message = haier_protocol::HaierMessage(
|
||||
action_request.message = haier_protocol::HaierMessage(
|
||||
haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_GROUP_PARAMETERS,
|
||||
control_out_buffer, this->real_control_packet_size_);
|
||||
return true;
|
||||
|
||||
@@ -402,7 +402,8 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin
|
||||
} else {
|
||||
this->preset = CLIMATE_PRESET_NONE;
|
||||
}
|
||||
should_publish = should_publish || (!old_preset.has_value()) || (old_preset.value() != this->preset.value());
|
||||
should_publish = should_publish || (!old_preset.has_value()) ||
|
||||
(old_preset.value_or(CLIMATE_PRESET_NONE) != this->preset.value_or(CLIMATE_PRESET_NONE));
|
||||
}
|
||||
{
|
||||
// Target temperature
|
||||
@@ -446,7 +447,8 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin
|
||||
this->fan_mode = CLIMATE_FAN_HIGH;
|
||||
break;
|
||||
}
|
||||
should_publish = should_publish || (!old_fan_mode.has_value()) || (old_fan_mode.value() != fan_mode.value());
|
||||
should_publish = should_publish || (!old_fan_mode.has_value()) ||
|
||||
(old_fan_mode.value_or(CLIMATE_FAN_ON) != this->fan_mode.value_or(CLIMATE_FAN_ON));
|
||||
}
|
||||
// Display status
|
||||
// should be before "Climate mode" because it is changing this->mode
|
||||
|
||||
@@ -49,14 +49,18 @@ void HBridgeFan::dump_config() {
|
||||
}
|
||||
|
||||
void HBridgeFan::control(const fan::FanCall &call) {
|
||||
if (call.get_state().has_value())
|
||||
this->state = *call.get_state();
|
||||
if (call.get_speed().has_value())
|
||||
this->speed = *call.get_speed();
|
||||
if (call.get_oscillating().has_value())
|
||||
this->oscillating = *call.get_oscillating();
|
||||
if (call.get_direction().has_value())
|
||||
this->direction = *call.get_direction();
|
||||
auto call_state = call.get_state();
|
||||
if (call_state.has_value())
|
||||
this->state = *call_state;
|
||||
auto call_speed = call.get_speed();
|
||||
if (call_speed.has_value())
|
||||
this->speed = *call_speed;
|
||||
auto call_oscillating = call.get_oscillating();
|
||||
if (call_oscillating.has_value())
|
||||
this->oscillating = *call_oscillating;
|
||||
auto call_direction = call.get_direction();
|
||||
if (call_direction.has_value())
|
||||
this->direction = *call_direction;
|
||||
this->apply_preset_mode_(call);
|
||||
|
||||
this->write_state_();
|
||||
|
||||
@@ -171,9 +171,12 @@ void HE60rCover::control(const CoverCall &call) {
|
||||
} else {
|
||||
this->toggles_needed_++;
|
||||
}
|
||||
} else if (call.get_position().has_value()) {
|
||||
} else {
|
||||
auto pos_opt = call.get_position();
|
||||
if (!pos_opt.has_value())
|
||||
return;
|
||||
// go to position action
|
||||
auto pos = *call.get_position();
|
||||
auto pos = *pos_opt;
|
||||
// are we at the target?
|
||||
if (pos == this->position) {
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
|
||||
@@ -175,7 +175,7 @@ void HitachiClimate::transmit_state() {
|
||||
|
||||
set_temp_(static_cast<uint8_t>(this->target_temperature));
|
||||
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
set_fan_(HITACHI_AC344_FAN_LOW);
|
||||
break;
|
||||
|
||||
@@ -176,7 +176,7 @@ void HitachiClimate::transmit_state() {
|
||||
|
||||
set_temp_(static_cast<uint8_t>(this->target_temperature));
|
||||
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
set_fan_(HITACHI_AC424_FAN_LOW);
|
||||
break;
|
||||
|
||||
@@ -11,17 +11,18 @@ static const char *const TAG = "audio";
|
||||
|
||||
void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) {
|
||||
media_player::MediaPlayerState play_state = media_player::MEDIA_PLAYER_STATE_PLAYING;
|
||||
if (call.get_announcement().has_value()) {
|
||||
play_state = call.get_announcement().value() ? media_player::MEDIA_PLAYER_STATE_ANNOUNCING
|
||||
: media_player::MEDIA_PLAYER_STATE_PLAYING;
|
||||
auto announcement = call.get_announcement();
|
||||
if (announcement.has_value()) {
|
||||
play_state = *announcement ? media_player::MEDIA_PLAYER_STATE_ANNOUNCING : media_player::MEDIA_PLAYER_STATE_PLAYING;
|
||||
}
|
||||
if (call.get_media_url().has_value()) {
|
||||
this->current_url_ = call.get_media_url();
|
||||
auto media_url = call.get_media_url();
|
||||
if (media_url.has_value()) {
|
||||
this->current_url_ = media_url;
|
||||
if (this->i2s_state_ != I2S_STATE_STOPPED && this->audio_ != nullptr) {
|
||||
if (this->audio_->isRunning()) {
|
||||
this->audio_->stopSong();
|
||||
}
|
||||
this->audio_->connecttohost(this->current_url_.value().c_str());
|
||||
this->audio_->connecttohost(media_url->c_str());
|
||||
this->state = play_state;
|
||||
} else {
|
||||
this->start();
|
||||
@@ -32,13 +33,15 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) {
|
||||
this->is_announcement_ = true;
|
||||
}
|
||||
|
||||
if (call.get_volume().has_value()) {
|
||||
this->volume = call.get_volume().value();
|
||||
auto vol = call.get_volume();
|
||||
if (vol.has_value()) {
|
||||
this->volume = *vol;
|
||||
this->set_volume_(volume);
|
||||
this->unmute_();
|
||||
}
|
||||
if (call.get_command().has_value()) {
|
||||
switch (call.get_command().value()) {
|
||||
auto cmd = call.get_command();
|
||||
if (cmd.has_value()) {
|
||||
switch (*cmd) {
|
||||
case media_player::MEDIA_PLAYER_COMMAND_MUTE:
|
||||
this->mute_();
|
||||
break;
|
||||
@@ -67,7 +70,7 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) {
|
||||
if (this->i2s_state_ != I2S_STATE_RUNNING) {
|
||||
return;
|
||||
}
|
||||
switch (call.get_command().value()) {
|
||||
switch (*cmd) {
|
||||
case media_player::MEDIA_PLAYER_COMMAND_PLAY:
|
||||
if (!this->audio_->isRunning())
|
||||
this->audio_->pauseResume();
|
||||
|
||||
@@ -90,8 +90,9 @@ void Infrared::control(const InfraredCall &call) {
|
||||
auto *transmit_data = transmit_call.get_data();
|
||||
|
||||
// Set carrier frequency
|
||||
if (call.get_carrier_frequency().has_value()) {
|
||||
transmit_data->set_carrier_frequency(call.get_carrier_frequency().value());
|
||||
auto freq = call.get_carrier_frequency();
|
||||
if (freq.has_value()) {
|
||||
transmit_data->set_carrier_frequency(*freq);
|
||||
}
|
||||
|
||||
// Set timings based on format
|
||||
|
||||
@@ -56,7 +56,8 @@ optional<uint8_t> ledc_bit_depth_for_frequency(float frequency) {
|
||||
|
||||
esp_err_t configure_timer_frequency(ledc_mode_t speed_mode, ledc_timer_t timer_num, ledc_channel_t chan_num,
|
||||
uint8_t channel, uint8_t &bit_depth, float frequency) {
|
||||
bit_depth = *ledc_bit_depth_for_frequency(frequency);
|
||||
auto bit_depth_opt = ledc_bit_depth_for_frequency(frequency);
|
||||
bit_depth = bit_depth_opt.value_or(0);
|
||||
if (bit_depth < 1) {
|
||||
ESP_LOGE(TAG, "Frequency %f can't be achieved with any bit depth", frequency);
|
||||
}
|
||||
|
||||
@@ -19,8 +19,9 @@ void Mcp4461Component::setup() {
|
||||
// save WP/WL status
|
||||
this->update_write_protection_status_();
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (this->reg_[i].initial_value.has_value()) {
|
||||
uint16_t initial_state = static_cast<uint16_t>(*this->reg_[i].initial_value * 256.0f);
|
||||
auto init_val = this->reg_[i].initial_value;
|
||||
if (init_val.has_value()) {
|
||||
uint16_t initial_state = static_cast<uint16_t>(*init_val * 256.0f);
|
||||
this->write_wiper_level_(i, initial_state);
|
||||
}
|
||||
if (this->reg_[i].enabled) {
|
||||
|
||||
@@ -56,20 +56,25 @@ void AirConditioner::on_status_change() {
|
||||
|
||||
void AirConditioner::control(const ClimateCall &call) {
|
||||
dudanov::midea::ac::Control ctrl{};
|
||||
if (call.get_target_temperature().has_value())
|
||||
ctrl.targetTemp = call.get_target_temperature().value();
|
||||
if (call.get_swing_mode().has_value())
|
||||
ctrl.swingMode = Converters::to_midea_swing_mode(call.get_swing_mode().value());
|
||||
if (call.get_mode().has_value())
|
||||
ctrl.mode = Converters::to_midea_mode(call.get_mode().value());
|
||||
if (call.get_preset().has_value()) {
|
||||
ctrl.preset = Converters::to_midea_preset(call.get_preset().value());
|
||||
auto target_temp_val = call.get_target_temperature();
|
||||
if (target_temp_val.has_value())
|
||||
ctrl.targetTemp = *target_temp_val;
|
||||
auto swing_mode_val = call.get_swing_mode();
|
||||
if (swing_mode_val.has_value())
|
||||
ctrl.swingMode = Converters::to_midea_swing_mode(*swing_mode_val);
|
||||
auto mode_val = call.get_mode();
|
||||
if (mode_val.has_value())
|
||||
ctrl.mode = Converters::to_midea_mode(*mode_val);
|
||||
auto preset_val = call.get_preset();
|
||||
if (preset_val.has_value()) {
|
||||
ctrl.preset = Converters::to_midea_preset(*preset_val);
|
||||
} else if (call.has_custom_preset()) {
|
||||
// get_custom_preset() returns StringRef pointing to null-terminated string literals from codegen
|
||||
ctrl.preset = Converters::to_midea_preset(call.get_custom_preset().c_str());
|
||||
}
|
||||
if (call.get_fan_mode().has_value()) {
|
||||
ctrl.fanMode = Converters::to_midea_fan_mode(call.get_fan_mode().value());
|
||||
auto fan_mode_val = call.get_fan_mode();
|
||||
if (fan_mode_val.has_value()) {
|
||||
ctrl.fanMode = Converters::to_midea_fan_mode(*fan_mode_val);
|
||||
} else if (call.has_custom_fan_mode()) {
|
||||
// get_custom_fan_mode() returns StringRef pointing to null-terminated string literals from codegen
|
||||
ctrl.fanMode = Converters::to_midea_fan_mode(call.get_custom_fan_mode().c_str());
|
||||
|
||||
@@ -114,15 +114,20 @@ void MideaIR::control(const climate::ClimateCall &call) {
|
||||
if (call.get_mode() == climate::CLIMATE_MODE_OFF) {
|
||||
this->swing_mode = climate::CLIMATE_SWING_OFF;
|
||||
this->preset = climate::CLIMATE_PRESET_NONE;
|
||||
} else if (call.get_swing_mode().has_value() && ((*call.get_swing_mode() == climate::CLIMATE_SWING_OFF &&
|
||||
this->swing_mode == climate::CLIMATE_SWING_VERTICAL) ||
|
||||
(*call.get_swing_mode() == climate::CLIMATE_SWING_VERTICAL &&
|
||||
this->swing_mode == climate::CLIMATE_SWING_OFF))) {
|
||||
this->swing_ = true;
|
||||
} else if (call.get_preset().has_value() &&
|
||||
((*call.get_preset() == climate::CLIMATE_PRESET_NONE && this->preset == climate::CLIMATE_PRESET_BOOST) ||
|
||||
(*call.get_preset() == climate::CLIMATE_PRESET_BOOST && this->preset == climate::CLIMATE_PRESET_NONE))) {
|
||||
this->boost_ = true;
|
||||
} else {
|
||||
auto swing = call.get_swing_mode();
|
||||
if (swing.has_value() &&
|
||||
((*swing == climate::CLIMATE_SWING_OFF && this->swing_mode == climate::CLIMATE_SWING_VERTICAL) ||
|
||||
(*swing == climate::CLIMATE_SWING_VERTICAL && this->swing_mode == climate::CLIMATE_SWING_OFF))) {
|
||||
this->swing_ = true;
|
||||
} else {
|
||||
auto preset = call.get_preset();
|
||||
if (preset.has_value() &&
|
||||
((*preset == climate::CLIMATE_PRESET_NONE && this->preset == climate::CLIMATE_PRESET_BOOST) ||
|
||||
(*preset == climate::CLIMATE_PRESET_BOOST && this->preset == climate::CLIMATE_PRESET_NONE))) {
|
||||
this->boost_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
climate_ir::ClimateIR::control(call);
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ void MitsubishiClimate::transmit_state() {
|
||||
// For 5Level: Low = 1, Middle = 2, Medium = 3, High = 4
|
||||
// For 4Level + Quiet: Low = 1, Middle = 2, Medium = 3, High = 4, Quiet = 5
|
||||
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
remote_state[9] = 1;
|
||||
break;
|
||||
@@ -209,7 +209,8 @@ void MitsubishiClimate::transmit_state() {
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "fan: %02x state: %02x", this->fan_mode.value(), remote_state[9]);
|
||||
ESP_LOGD(TAG, "fan: %02x state: %02x", static_cast<uint8_t>(this->fan_mode.value_or(climate::CLIMATE_FAN_ON)),
|
||||
remote_state[9]);
|
||||
|
||||
// Vertical Vane
|
||||
switch (this->swing_mode) {
|
||||
@@ -227,7 +228,7 @@ void MitsubishiClimate::transmit_state() {
|
||||
ESP_LOGD(TAG, "default_vertical_direction_: %02X", this->default_vertical_direction_);
|
||||
|
||||
// Special modes
|
||||
switch (this->preset.value()) {
|
||||
switch (this->preset.value_or(climate::CLIMATE_PRESET_NONE)) {
|
||||
case climate::CLIMATE_PRESET_ECO:
|
||||
remote_state[6] = MITSUBISHI_MODE_COOL | MITSUBISHI_OTHERWISE;
|
||||
remote_state[8] = (remote_state[8] & ~7) | MITSUBISHI_MODE_A_COOL;
|
||||
|
||||
@@ -52,7 +52,7 @@ void ModbusSelect::control(size_t index) {
|
||||
// Transform func requires string parameter for backward compatibility
|
||||
auto val = (*this->write_transform_func_)(this, std::string(option), *mapval, data);
|
||||
if (val.has_value()) {
|
||||
mapval = *val;
|
||||
mapval = val;
|
||||
ESP_LOGV(TAG, "write_lambda returned mapping value %lld", *mapval);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Communication handled by write_lambda - exiting control");
|
||||
|
||||
@@ -71,7 +71,7 @@ void NoblexClimate::transmit_state() {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
remote_state[0] |= (IRNoblexFan::IR_NOBLEX_FAN_LOW << 2);
|
||||
break;
|
||||
|
||||
@@ -26,7 +26,8 @@ class NoblexClimate : public climate_ir::ClimateIR {
|
||||
void control(const climate::ClimateCall &call) override {
|
||||
send_swing_cmd_ = call.get_swing_mode().has_value();
|
||||
// swing resets after unit powered off
|
||||
if (call.get_mode().has_value() && *call.get_mode() == climate::CLIMATE_MODE_OFF)
|
||||
auto mode = call.get_mode();
|
||||
if (mode.has_value() && *mode == climate::CLIMATE_MODE_OFF)
|
||||
this->swing_mode = climate::CLIMATE_SWING_OFF;
|
||||
climate_ir::ClimateIR::control(call);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@ static const char *const TAG = "output.lock";
|
||||
void OutputLock::dump_config() { LOG_LOCK("", "Output Lock", this); }
|
||||
|
||||
void OutputLock::control(const lock::LockCall &call) {
|
||||
auto state = *call.get_state();
|
||||
auto state_val = call.get_state();
|
||||
if (!state_val.has_value())
|
||||
return;
|
||||
auto state = *state_val;
|
||||
if (state == lock::LOCK_STATE_LOCKED) {
|
||||
this->output_->turn_on();
|
||||
} else if (state == lock::LOCK_STATE_UNLOCKED) {
|
||||
|
||||
@@ -41,10 +41,12 @@ void PIDClimate::setup() {
|
||||
}
|
||||
}
|
||||
void PIDClimate::control(const climate::ClimateCall &call) {
|
||||
if (call.get_mode().has_value())
|
||||
this->mode = *call.get_mode();
|
||||
if (call.get_target_temperature().has_value())
|
||||
this->target_temperature = *call.get_target_temperature();
|
||||
auto call_mode = call.get_mode();
|
||||
if (call_mode.has_value())
|
||||
this->mode = *call_mode;
|
||||
auto call_target = call.get_target_temperature();
|
||||
if (call_target.has_value())
|
||||
this->target_temperature = *call_target;
|
||||
|
||||
// If switching to off mode, set output immediately
|
||||
if (this->mode == climate::CLIMATE_MODE_OFF)
|
||||
|
||||
@@ -26,7 +26,10 @@ void PZEM004T::loop() {
|
||||
|
||||
// PZEM004T packet size is 7 byte
|
||||
while (this->available() >= 7) {
|
||||
auto resp = *this->read_array<7>();
|
||||
auto resp_opt = this->read_array<7>();
|
||||
if (!resp_opt.has_value())
|
||||
break;
|
||||
auto resp = *resp_opt;
|
||||
// packet format:
|
||||
// 0: packet type
|
||||
// 1-5: data
|
||||
|
||||
@@ -69,7 +69,7 @@ optional<size_t> SelectCall::calculate_target_index_(const char *name) {
|
||||
ESP_LOGW(TAG, "'%s' - No option set", name);
|
||||
return {};
|
||||
}
|
||||
return this->index_.value();
|
||||
return this->index_;
|
||||
}
|
||||
|
||||
// SELECT_OP_NEXT or SELECT_OP_PREVIOUS
|
||||
|
||||
@@ -81,22 +81,16 @@ class SGP4xComponent : public PollingComponent, public sensor::Sensor, public se
|
||||
void set_voc_algorithm_tuning(uint16_t index_offset, uint16_t learning_time_offset_hours,
|
||||
uint16_t learning_time_gain_hours, uint16_t gating_max_duration_minutes,
|
||||
uint16_t std_initial, uint16_t gain_factor) {
|
||||
voc_tuning_params_.value().index_offset = index_offset;
|
||||
voc_tuning_params_.value().learning_time_offset_hours = learning_time_offset_hours;
|
||||
voc_tuning_params_.value().learning_time_gain_hours = learning_time_gain_hours;
|
||||
voc_tuning_params_.value().gating_max_duration_minutes = gating_max_duration_minutes;
|
||||
voc_tuning_params_.value().std_initial = std_initial;
|
||||
voc_tuning_params_.value().gain_factor = gain_factor;
|
||||
this->voc_tuning_params_ = GasTuning{
|
||||
index_offset, learning_time_offset_hours, learning_time_gain_hours, gating_max_duration_minutes, std_initial,
|
||||
gain_factor};
|
||||
}
|
||||
void set_nox_algorithm_tuning(uint16_t index_offset, uint16_t learning_time_offset_hours,
|
||||
uint16_t learning_time_gain_hours, uint16_t gating_max_duration_minutes,
|
||||
uint16_t gain_factor) {
|
||||
nox_tuning_params_.value().index_offset = index_offset;
|
||||
nox_tuning_params_.value().learning_time_offset_hours = learning_time_offset_hours;
|
||||
nox_tuning_params_.value().learning_time_gain_hours = learning_time_gain_hours;
|
||||
nox_tuning_params_.value().gating_max_duration_minutes = gating_max_duration_minutes;
|
||||
nox_tuning_params_.value().std_initial = 50;
|
||||
nox_tuning_params_.value().gain_factor = gain_factor;
|
||||
this->nox_tuning_params_ =
|
||||
GasTuning{index_offset, learning_time_offset_hours, learning_time_gain_hours, gating_max_duration_minutes, 50,
|
||||
gain_factor};
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -144,7 +144,7 @@ void SpeakerMediaPlayer::watch_media_commands_() {
|
||||
delete media_command.url.value();
|
||||
}
|
||||
if (media_command.file.has_value()) {
|
||||
playlist_item.file = media_command.file.value();
|
||||
playlist_item.file = media_command.file;
|
||||
}
|
||||
|
||||
if (this->single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value())) {
|
||||
@@ -495,18 +495,21 @@ void SpeakerMediaPlayer::control(const media_player::MediaPlayerCall &call) {
|
||||
|
||||
MediaCallCommand media_command;
|
||||
|
||||
if (this->single_pipeline_() || (call.get_announcement().has_value() && call.get_announcement().value())) {
|
||||
auto ann = call.get_announcement();
|
||||
if (this->single_pipeline_() || (ann.has_value() && *ann)) {
|
||||
media_command.announce = true;
|
||||
} else {
|
||||
media_command.announce = false;
|
||||
}
|
||||
|
||||
if (call.get_media_url().has_value()) {
|
||||
media_command.url = new std::string(
|
||||
call.get_media_url().value()); // Must be manually deleted after receiving media_command from a queue
|
||||
auto media_url = call.get_media_url();
|
||||
if (media_url.has_value()) {
|
||||
media_command.url =
|
||||
new std::string(*media_url); // Must be manually deleted after receiving media_command from a queue
|
||||
|
||||
if (call.get_command().has_value()) {
|
||||
if (call.get_command().value() == media_player::MEDIA_PLAYER_COMMAND_ENQUEUE) {
|
||||
auto cmd = call.get_command();
|
||||
if (cmd.has_value()) {
|
||||
if (*cmd == media_player::MEDIA_PLAYER_COMMAND_ENQUEUE) {
|
||||
media_command.enqueue = true;
|
||||
}
|
||||
}
|
||||
@@ -515,18 +518,20 @@ void SpeakerMediaPlayer::control(const media_player::MediaPlayerCall &call) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (call.get_volume().has_value()) {
|
||||
media_command.volume = call.get_volume().value();
|
||||
auto vol = call.get_volume();
|
||||
if (vol.has_value()) {
|
||||
media_command.volume = vol;
|
||||
// Wait 0 ticks for queue to be free, volume sets aren't that important!
|
||||
xQueueSend(this->media_control_command_queue_, &media_command, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (call.get_command().has_value()) {
|
||||
media_command.command = call.get_command().value();
|
||||
auto cmd = call.get_command();
|
||||
if (cmd.has_value()) {
|
||||
media_command.command = cmd;
|
||||
TickType_t ticks_to_wait = portMAX_DELAY;
|
||||
if ((call.get_command().value() == media_player::MEDIA_PLAYER_COMMAND_VOLUME_UP) ||
|
||||
(call.get_command().value() == media_player::MEDIA_PLAYER_COMMAND_VOLUME_DOWN)) {
|
||||
if ((*cmd == media_player::MEDIA_PLAYER_COMMAND_VOLUME_UP) ||
|
||||
(*cmd == media_player::MEDIA_PLAYER_COMMAND_VOLUME_DOWN)) {
|
||||
ticks_to_wait = 0; // Wait 0 ticks for queue to be free, volume sets aren't that important!
|
||||
}
|
||||
xQueueSend(this->media_control_command_queue_, &media_command, ticks_to_wait);
|
||||
|
||||
@@ -21,14 +21,18 @@ void SpeedFan::setup() {
|
||||
void SpeedFan::dump_config() { LOG_FAN("", "Speed Fan", this); }
|
||||
|
||||
void SpeedFan::control(const fan::FanCall &call) {
|
||||
if (call.get_state().has_value())
|
||||
this->state = *call.get_state();
|
||||
if (call.get_speed().has_value())
|
||||
this->speed = *call.get_speed();
|
||||
if (call.get_oscillating().has_value())
|
||||
this->oscillating = *call.get_oscillating();
|
||||
if (call.get_direction().has_value())
|
||||
this->direction = *call.get_direction();
|
||||
auto call_state = call.get_state();
|
||||
if (call_state.has_value())
|
||||
this->state = *call_state;
|
||||
auto call_speed = call.get_speed();
|
||||
if (call_speed.has_value())
|
||||
this->speed = *call_speed;
|
||||
auto call_oscillating = call.get_oscillating();
|
||||
if (call_oscillating.has_value())
|
||||
this->oscillating = *call_oscillating;
|
||||
auto call_direction = call.get_direction();
|
||||
if (call_direction.has_value())
|
||||
this->direction = *call_direction;
|
||||
this->apply_preset_mode_(call);
|
||||
|
||||
this->write_state_();
|
||||
|
||||
@@ -44,7 +44,7 @@ SprinklerControllerSwitch::SprinklerControllerSwitch() = default;
|
||||
|
||||
void SprinklerControllerSwitch::loop() {
|
||||
// Loop is only enabled when f_ has a value (see setup())
|
||||
auto s = (*this->f_)();
|
||||
auto s = (*this->f_)(); // NOLINT(bugprone-unchecked-optional-access)
|
||||
if (s.has_value()) {
|
||||
this->publish_state(*s);
|
||||
}
|
||||
@@ -89,20 +89,21 @@ void SprinklerValveOperator::loop() {
|
||||
uint32_t now = App.get_loop_component_start_time();
|
||||
switch (this->state_) {
|
||||
case STARTING:
|
||||
if ((now - *this->start_millis_) > this->start_delay_) {
|
||||
if ((now - *this->start_millis_) > this->start_delay_) { // NOLINT(bugprone-unchecked-optional-access)
|
||||
this->run_(); // start_delay_ has been exceeded, so ensure both valves are on and update the state
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTIVE:
|
||||
if ((now - *this->start_millis_) > (this->start_delay_ + this->run_duration_)) {
|
||||
if ((now - *this->start_millis_) > // NOLINT(bugprone-unchecked-optional-access)
|
||||
(this->start_delay_ + this->run_duration_)) {
|
||||
this->stop(); // start_delay_ + run_duration_ has been exceeded, start shutting down
|
||||
}
|
||||
break;
|
||||
|
||||
case STOPPING:
|
||||
if ((now - *this->stop_millis_) > this->stop_delay_) {
|
||||
this->kill_(); // stop_delay_has been exceeded, ensure all valves are off
|
||||
if ((now - *this->stop_millis_) > this->stop_delay_) { // NOLINT(bugprone-unchecked-optional-access)
|
||||
this->kill_(); // stop_delay_has been exceeded, ensure all valves are off
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1067,7 +1068,8 @@ uint32_t Sprinkler::total_cycle_time_enabled_incomplete_valves() {
|
||||
if (this->valve_is_enabled_(valve)) {
|
||||
enabled_valve_count++;
|
||||
if (!this->valve_cycle_complete_(valve)) {
|
||||
if (!this->active_valve().has_value() || (valve != this->active_valve().value())) {
|
||||
auto active = this->active_valve();
|
||||
if (!active.has_value() || (valve != *active)) {
|
||||
total_time_remaining += this->valve_run_duration_adjusted(valve);
|
||||
incomplete_valve_count++;
|
||||
} else {
|
||||
@@ -1190,8 +1192,11 @@ switch_::Switch *Sprinkler::valve_switch(const size_t valve_number) {
|
||||
}
|
||||
|
||||
switch_::Switch *Sprinkler::valve_pump_switch(const size_t valve_number) {
|
||||
if (this->is_a_valid_valve(valve_number) && this->valve_[valve_number].pump_switch_index.has_value()) {
|
||||
return this->pump_[this->valve_[valve_number].pump_switch_index.value()];
|
||||
if (this->is_a_valid_valve(valve_number)) {
|
||||
auto idx = this->valve_[valve_number].pump_switch_index;
|
||||
if (idx.has_value()) {
|
||||
return this->pump_[*idx];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ void Tcl112Climate::transmit_state() {
|
||||
|
||||
// Set fan
|
||||
uint8_t selected_fan;
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_HIGH:
|
||||
selected_fan = TCL112_FAN_HIGH;
|
||||
break;
|
||||
|
||||
@@ -257,14 +257,16 @@ void TemplateAlarmControlPanel::bypass_before_arming() {
|
||||
}
|
||||
|
||||
void TemplateAlarmControlPanel::control(const AlarmControlPanelCall &call) {
|
||||
if (call.get_state()) {
|
||||
if (call.get_state() == ACP_STATE_ARMED_AWAY) {
|
||||
auto opt_state = call.get_state();
|
||||
if (opt_state) {
|
||||
auto state = *opt_state;
|
||||
if (state == ACP_STATE_ARMED_AWAY) {
|
||||
this->arm_(call.get_code(), ACP_STATE_ARMED_AWAY, this->arming_away_time_);
|
||||
} else if (call.get_state() == ACP_STATE_ARMED_HOME) {
|
||||
} else if (state == ACP_STATE_ARMED_HOME) {
|
||||
this->arm_(call.get_code(), ACP_STATE_ARMED_HOME, this->arming_home_time_);
|
||||
} else if (call.get_state() == ACP_STATE_ARMED_NIGHT) {
|
||||
} else if (state == ACP_STATE_ARMED_NIGHT) {
|
||||
this->arm_(call.get_code(), ACP_STATE_ARMED_NIGHT, this->arming_night_time_);
|
||||
} else if (call.get_state() == ACP_STATE_DISARMED) {
|
||||
} else if (state == ACP_STATE_DISARMED) {
|
||||
if (!this->is_code_valid_(call.get_code())) {
|
||||
ESP_LOGW(TAG, "Not disarming code doesn't match");
|
||||
return;
|
||||
@@ -274,13 +276,12 @@ void TemplateAlarmControlPanel::control(const AlarmControlPanelCall &call) {
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
this->bypassed_sensor_indicies_.clear();
|
||||
#endif
|
||||
} else if (call.get_state() == ACP_STATE_TRIGGERED) {
|
||||
} else if (state == ACP_STATE_TRIGGERED) {
|
||||
this->publish_state(ACP_STATE_TRIGGERED);
|
||||
} else if (call.get_state() == ACP_STATE_PENDING) {
|
||||
} else if (state == ACP_STATE_PENDING) {
|
||||
this->publish_state(ACP_STATE_PENDING);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "State not yet implemented: %s",
|
||||
LOG_STR_ARG(alarm_control_panel_state_to_string(*call.get_state())));
|
||||
ESP_LOGE(TAG, "State not yet implemented: %s", LOG_STR_ARG(alarm_control_panel_state_to_string(state)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,8 +74,9 @@ void TemplateCover::control(const CoverCall &call) {
|
||||
this->prev_command_trigger_ = &this->toggle_trigger_;
|
||||
this->publish_state();
|
||||
}
|
||||
if (call.get_position().has_value()) {
|
||||
auto pos = *call.get_position();
|
||||
auto pos_val = call.get_position();
|
||||
if (pos_val.has_value()) {
|
||||
auto pos = *pos_val;
|
||||
this->stop_prev_trigger_();
|
||||
|
||||
if (pos == COVER_OPEN) {
|
||||
@@ -93,8 +94,9 @@ void TemplateCover::control(const CoverCall &call) {
|
||||
}
|
||||
}
|
||||
|
||||
if (call.get_tilt().has_value()) {
|
||||
auto tilt = *call.get_tilt();
|
||||
auto tilt_val = call.get_tilt();
|
||||
if (tilt_val.has_value()) {
|
||||
auto tilt = *tilt_val;
|
||||
this->tilt_trigger_.trigger(tilt);
|
||||
|
||||
if (this->optimistic_) {
|
||||
|
||||
@@ -48,46 +48,49 @@ void TemplateDate::update() {
|
||||
}
|
||||
|
||||
void TemplateDate::control(const datetime::DateCall &call) {
|
||||
bool has_year = call.get_year().has_value();
|
||||
bool has_month = call.get_month().has_value();
|
||||
bool has_day = call.get_day().has_value();
|
||||
auto opt_year = call.get_year();
|
||||
auto opt_month = call.get_month();
|
||||
auto opt_day = call.get_day();
|
||||
bool has_year = opt_year.has_value();
|
||||
bool has_month = opt_month.has_value();
|
||||
bool has_day = opt_day.has_value();
|
||||
|
||||
ESPTime value = {};
|
||||
if (has_year)
|
||||
value.year = *call.get_year();
|
||||
value.year = *opt_year;
|
||||
|
||||
if (has_month)
|
||||
value.month = *call.get_month();
|
||||
value.month = *opt_month;
|
||||
|
||||
if (has_day)
|
||||
value.day_of_month = *call.get_day();
|
||||
value.day_of_month = *opt_day;
|
||||
|
||||
this->set_trigger_.trigger(value);
|
||||
|
||||
if (this->optimistic_) {
|
||||
if (has_year)
|
||||
this->year_ = *call.get_year();
|
||||
this->year_ = *opt_year;
|
||||
if (has_month)
|
||||
this->month_ = *call.get_month();
|
||||
this->month_ = *opt_month;
|
||||
if (has_day)
|
||||
this->day_ = *call.get_day();
|
||||
this->day_ = *opt_day;
|
||||
this->publish_state();
|
||||
}
|
||||
|
||||
if (this->restore_value_) {
|
||||
datetime::DateEntityRestoreState temp = {};
|
||||
if (has_year) {
|
||||
temp.year = *call.get_year();
|
||||
temp.year = *opt_year;
|
||||
} else {
|
||||
temp.year = this->year_;
|
||||
}
|
||||
if (has_month) {
|
||||
temp.month = *call.get_month();
|
||||
temp.month = *opt_month;
|
||||
} else {
|
||||
temp.month = this->month_;
|
||||
}
|
||||
if (has_day) {
|
||||
temp.day = *call.get_day();
|
||||
temp.day = *opt_day;
|
||||
} else {
|
||||
temp.day = this->day_;
|
||||
}
|
||||
|
||||
@@ -54,79 +54,85 @@ void TemplateDateTime::update() {
|
||||
}
|
||||
|
||||
void TemplateDateTime::control(const datetime::DateTimeCall &call) {
|
||||
bool has_year = call.get_year().has_value();
|
||||
bool has_month = call.get_month().has_value();
|
||||
bool has_day = call.get_day().has_value();
|
||||
bool has_hour = call.get_hour().has_value();
|
||||
bool has_minute = call.get_minute().has_value();
|
||||
bool has_second = call.get_second().has_value();
|
||||
auto opt_year = call.get_year();
|
||||
auto opt_month = call.get_month();
|
||||
auto opt_day = call.get_day();
|
||||
auto opt_hour = call.get_hour();
|
||||
auto opt_minute = call.get_minute();
|
||||
auto opt_second = call.get_second();
|
||||
bool has_year = opt_year.has_value();
|
||||
bool has_month = opt_month.has_value();
|
||||
bool has_day = opt_day.has_value();
|
||||
bool has_hour = opt_hour.has_value();
|
||||
bool has_minute = opt_minute.has_value();
|
||||
bool has_second = opt_second.has_value();
|
||||
|
||||
ESPTime value = {};
|
||||
if (has_year)
|
||||
value.year = *call.get_year();
|
||||
value.year = *opt_year;
|
||||
|
||||
if (has_month)
|
||||
value.month = *call.get_month();
|
||||
value.month = *opt_month;
|
||||
|
||||
if (has_day)
|
||||
value.day_of_month = *call.get_day();
|
||||
value.day_of_month = *opt_day;
|
||||
|
||||
if (has_hour)
|
||||
value.hour = *call.get_hour();
|
||||
value.hour = *opt_hour;
|
||||
|
||||
if (has_minute)
|
||||
value.minute = *call.get_minute();
|
||||
value.minute = *opt_minute;
|
||||
|
||||
if (has_second)
|
||||
value.second = *call.get_second();
|
||||
value.second = *opt_second;
|
||||
|
||||
this->set_trigger_.trigger(value);
|
||||
|
||||
if (this->optimistic_) {
|
||||
if (has_year)
|
||||
this->year_ = *call.get_year();
|
||||
this->year_ = *opt_year;
|
||||
if (has_month)
|
||||
this->month_ = *call.get_month();
|
||||
this->month_ = *opt_month;
|
||||
if (has_day)
|
||||
this->day_ = *call.get_day();
|
||||
this->day_ = *opt_day;
|
||||
if (has_hour)
|
||||
this->hour_ = *call.get_hour();
|
||||
this->hour_ = *opt_hour;
|
||||
if (has_minute)
|
||||
this->minute_ = *call.get_minute();
|
||||
this->minute_ = *opt_minute;
|
||||
if (has_second)
|
||||
this->second_ = *call.get_second();
|
||||
this->second_ = *opt_second;
|
||||
this->publish_state();
|
||||
}
|
||||
|
||||
if (this->restore_value_) {
|
||||
datetime::DateTimeEntityRestoreState temp = {};
|
||||
if (has_year) {
|
||||
temp.year = *call.get_year();
|
||||
temp.year = *opt_year;
|
||||
} else {
|
||||
temp.year = this->year_;
|
||||
}
|
||||
if (has_month) {
|
||||
temp.month = *call.get_month();
|
||||
temp.month = *opt_month;
|
||||
} else {
|
||||
temp.month = this->month_;
|
||||
}
|
||||
if (has_day) {
|
||||
temp.day = *call.get_day();
|
||||
temp.day = *opt_day;
|
||||
} else {
|
||||
temp.day = this->day_;
|
||||
}
|
||||
if (has_hour) {
|
||||
temp.hour = *call.get_hour();
|
||||
temp.hour = *opt_hour;
|
||||
} else {
|
||||
temp.hour = this->hour_;
|
||||
}
|
||||
if (has_minute) {
|
||||
temp.minute = *call.get_minute();
|
||||
temp.minute = *opt_minute;
|
||||
} else {
|
||||
temp.minute = this->minute_;
|
||||
}
|
||||
if (has_second) {
|
||||
temp.second = *call.get_second();
|
||||
temp.second = *opt_second;
|
||||
} else {
|
||||
temp.second = this->second_;
|
||||
}
|
||||
|
||||
@@ -48,46 +48,49 @@ void TemplateTime::update() {
|
||||
}
|
||||
|
||||
void TemplateTime::control(const datetime::TimeCall &call) {
|
||||
bool has_hour = call.get_hour().has_value();
|
||||
bool has_minute = call.get_minute().has_value();
|
||||
bool has_second = call.get_second().has_value();
|
||||
auto opt_hour = call.get_hour();
|
||||
auto opt_minute = call.get_minute();
|
||||
auto opt_second = call.get_second();
|
||||
bool has_hour = opt_hour.has_value();
|
||||
bool has_minute = opt_minute.has_value();
|
||||
bool has_second = opt_second.has_value();
|
||||
|
||||
ESPTime value = {};
|
||||
if (has_hour)
|
||||
value.hour = *call.get_hour();
|
||||
value.hour = *opt_hour;
|
||||
|
||||
if (has_minute)
|
||||
value.minute = *call.get_minute();
|
||||
value.minute = *opt_minute;
|
||||
|
||||
if (has_second)
|
||||
value.second = *call.get_second();
|
||||
value.second = *opt_second;
|
||||
|
||||
this->set_trigger_.trigger(value);
|
||||
|
||||
if (this->optimistic_) {
|
||||
if (has_hour)
|
||||
this->hour_ = *call.get_hour();
|
||||
this->hour_ = *opt_hour;
|
||||
if (has_minute)
|
||||
this->minute_ = *call.get_minute();
|
||||
this->minute_ = *opt_minute;
|
||||
if (has_second)
|
||||
this->second_ = *call.get_second();
|
||||
this->second_ = *opt_second;
|
||||
this->publish_state();
|
||||
}
|
||||
|
||||
if (this->restore_value_) {
|
||||
datetime::TimeEntityRestoreState temp = {};
|
||||
if (has_hour) {
|
||||
temp.hour = *call.get_hour();
|
||||
temp.hour = *opt_hour;
|
||||
} else {
|
||||
temp.hour = this->hour_;
|
||||
}
|
||||
if (has_minute) {
|
||||
temp.minute = *call.get_minute();
|
||||
temp.minute = *opt_minute;
|
||||
} else {
|
||||
temp.minute = this->minute_;
|
||||
}
|
||||
if (has_second) {
|
||||
temp.second = *call.get_second();
|
||||
temp.second = *opt_second;
|
||||
} else {
|
||||
temp.second = this->second_;
|
||||
}
|
||||
|
||||
@@ -20,14 +20,18 @@ void TemplateFan::setup() {
|
||||
void TemplateFan::dump_config() { LOG_FAN("", "Template Fan", this); }
|
||||
|
||||
void TemplateFan::control(const fan::FanCall &call) {
|
||||
if (call.get_state().has_value())
|
||||
this->state = *call.get_state();
|
||||
if (call.get_speed().has_value() && (this->speed_count_ > 0))
|
||||
this->speed = *call.get_speed();
|
||||
if (call.get_oscillating().has_value() && this->has_oscillating_)
|
||||
this->oscillating = *call.get_oscillating();
|
||||
if (call.get_direction().has_value() && this->has_direction_)
|
||||
this->direction = *call.get_direction();
|
||||
auto call_state = call.get_state();
|
||||
if (call_state.has_value())
|
||||
this->state = *call_state;
|
||||
auto call_speed = call.get_speed();
|
||||
if (call_speed.has_value() && (this->speed_count_ > 0))
|
||||
this->speed = *call_speed;
|
||||
auto call_oscillating = call.get_oscillating();
|
||||
if (call_oscillating.has_value() && this->has_oscillating_)
|
||||
this->oscillating = *call_oscillating;
|
||||
auto call_direction = call.get_direction();
|
||||
if (call_direction.has_value() && this->has_direction_)
|
||||
this->direction = *call_direction;
|
||||
this->apply_preset_mode_(call);
|
||||
|
||||
this->publish_state();
|
||||
|
||||
@@ -25,7 +25,10 @@ void TemplateLock::control(const lock::LockCall &call) {
|
||||
this->prev_trigger_->stop_action();
|
||||
}
|
||||
|
||||
auto state = *call.get_state();
|
||||
auto opt_state = call.get_state();
|
||||
if (!opt_state.has_value())
|
||||
return;
|
||||
auto state = *opt_state;
|
||||
if (state == LOCK_STATE_LOCKED) {
|
||||
this->prev_trigger_ = &this->lock_trigger_;
|
||||
this->lock_trigger_.trigger();
|
||||
|
||||
@@ -77,8 +77,9 @@ void TemplateValve::control(const ValveCall &call) {
|
||||
this->prev_command_trigger_ = &this->toggle_trigger_;
|
||||
this->publish_state();
|
||||
}
|
||||
if (call.get_position().has_value()) {
|
||||
auto pos = *call.get_position();
|
||||
auto pos_val = call.get_position();
|
||||
if (pos_val.has_value()) {
|
||||
auto pos = *pos_val;
|
||||
this->stop_prev_trigger_();
|
||||
|
||||
if (pos == VALVE_OPEN) {
|
||||
|
||||
@@ -101,9 +101,10 @@ water_heater::WaterHeaterCallInternal TemplateWaterHeater::make_call() {
|
||||
}
|
||||
|
||||
void TemplateWaterHeater::control(const water_heater::WaterHeaterCall &call) {
|
||||
if (call.get_mode().has_value()) {
|
||||
auto mode_val = call.get_mode();
|
||||
if (mode_val.has_value()) {
|
||||
if (this->optimistic_) {
|
||||
this->mode_ = *call.get_mode();
|
||||
this->mode_ = *mode_val;
|
||||
}
|
||||
}
|
||||
if (!std::isnan(call.get_target_temperature())) {
|
||||
@@ -112,14 +113,16 @@ void TemplateWaterHeater::control(const water_heater::WaterHeaterCall &call) {
|
||||
}
|
||||
}
|
||||
|
||||
if (call.get_away().has_value()) {
|
||||
auto away_val = call.get_away();
|
||||
if (away_val.has_value()) {
|
||||
if (this->optimistic_) {
|
||||
this->set_state_flag_(water_heater::WATER_HEATER_STATE_AWAY, *call.get_away());
|
||||
this->set_state_flag_(water_heater::WATER_HEATER_STATE_AWAY, *away_val);
|
||||
}
|
||||
}
|
||||
if (call.get_on().has_value()) {
|
||||
auto on_val = call.get_on();
|
||||
if (on_val.has_value()) {
|
||||
if (this->optimistic_) {
|
||||
this->set_state_flag_(water_heater::WATER_HEATER_STATE_ON, *call.get_on());
|
||||
this->set_state_flag_(water_heater::WATER_HEATER_STATE_ON, *on_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ void ThermostatClimate::refresh() {
|
||||
this->switch_to_mode_(this->mode, false);
|
||||
this->switch_to_action_(this->compute_action_(), false);
|
||||
this->switch_to_supplemental_action_(this->compute_supplemental_action_());
|
||||
this->switch_to_fan_mode_(this->fan_mode.value(), false);
|
||||
this->switch_to_fan_mode_(this->fan_mode.value_or(climate::CLIMATE_FAN_ON), false);
|
||||
this->switch_to_swing_mode_(this->swing_mode, false);
|
||||
this->switch_to_humidity_control_action_(this->compute_humidity_control_action_());
|
||||
this->check_humidity_change_trigger_();
|
||||
@@ -211,12 +211,13 @@ void ThermostatClimate::validate_target_humidity() {
|
||||
void ThermostatClimate::control(const climate::ClimateCall &call) {
|
||||
bool target_temperature_high_changed = false;
|
||||
|
||||
if (call.get_preset().has_value()) {
|
||||
auto preset = call.get_preset();
|
||||
if (preset.has_value()) {
|
||||
// setup_complete_ blocks modifying/resetting the temps immediately after boot
|
||||
if (this->setup_complete_) {
|
||||
this->change_preset_(call.get_preset().value());
|
||||
this->change_preset_(*preset);
|
||||
} else {
|
||||
this->preset = call.get_preset().value();
|
||||
this->preset = preset;
|
||||
}
|
||||
}
|
||||
if (call.has_custom_preset()) {
|
||||
@@ -229,34 +230,41 @@ void ThermostatClimate::control(const climate::ClimateCall &call) {
|
||||
}
|
||||
}
|
||||
|
||||
if (call.get_mode().has_value()) {
|
||||
this->mode = call.get_mode().value();
|
||||
auto mode = call.get_mode();
|
||||
if (mode.has_value()) {
|
||||
this->mode = *mode;
|
||||
}
|
||||
if (call.get_fan_mode().has_value()) {
|
||||
this->fan_mode = call.get_fan_mode().value();
|
||||
auto fan_mode = call.get_fan_mode();
|
||||
if (fan_mode.has_value()) {
|
||||
this->fan_mode = fan_mode;
|
||||
}
|
||||
if (call.get_swing_mode().has_value()) {
|
||||
this->swing_mode = call.get_swing_mode().value();
|
||||
auto swing_mode = call.get_swing_mode();
|
||||
if (swing_mode.has_value()) {
|
||||
this->swing_mode = *swing_mode;
|
||||
}
|
||||
if (this->supports_two_points_) {
|
||||
if (call.get_target_temperature_low().has_value()) {
|
||||
this->target_temperature_low = call.get_target_temperature_low().value();
|
||||
auto target_temp_low = call.get_target_temperature_low();
|
||||
if (target_temp_low.has_value()) {
|
||||
this->target_temperature_low = *target_temp_low;
|
||||
}
|
||||
if (call.get_target_temperature_high().has_value()) {
|
||||
target_temperature_high_changed = this->target_temperature_high != call.get_target_temperature_high().value();
|
||||
this->target_temperature_high = call.get_target_temperature_high().value();
|
||||
auto target_temp_high = call.get_target_temperature_high();
|
||||
if (target_temp_high.has_value()) {
|
||||
target_temperature_high_changed = this->target_temperature_high != *target_temp_high;
|
||||
this->target_temperature_high = *target_temp_high;
|
||||
}
|
||||
// ensure the two set points are valid and adjust one of them if necessary
|
||||
this->validate_target_temperatures(target_temperature_high_changed ||
|
||||
(this->prev_mode_ == climate::CLIMATE_MODE_COOL));
|
||||
} else {
|
||||
if (call.get_target_temperature().has_value()) {
|
||||
this->target_temperature = call.get_target_temperature().value();
|
||||
auto target_temp = call.get_target_temperature();
|
||||
if (target_temp.has_value()) {
|
||||
this->target_temperature = *target_temp;
|
||||
this->validate_target_temperature();
|
||||
}
|
||||
}
|
||||
if (call.get_target_humidity().has_value()) {
|
||||
this->target_humidity = call.get_target_humidity().value();
|
||||
auto target_humidity = call.get_target_humidity();
|
||||
if (target_humidity.has_value()) {
|
||||
this->target_humidity = *target_humidity;
|
||||
this->validate_target_humidity();
|
||||
}
|
||||
// make any changes happen
|
||||
@@ -1264,9 +1272,9 @@ bool ThermostatClimate::change_preset_internal_(const ThermostatClimateTargetTem
|
||||
something_changed = true;
|
||||
}
|
||||
|
||||
if (config.fan_mode_.has_value() && (this->fan_mode != config.fan_mode_.value())) {
|
||||
if (config.fan_mode_.has_value() && (this->fan_mode != config.fan_mode_)) {
|
||||
ESP_LOGV(TAG, "Setting fan mode to %s", LOG_STR_ARG(climate::climate_fan_mode_to_string(*config.fan_mode_)));
|
||||
this->fan_mode = *config.fan_mode_;
|
||||
this->fan_mode = config.fan_mode_;
|
||||
something_changed = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,8 +79,9 @@ void TimeBasedCover::control(const CoverCall &call) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (call.get_position().has_value()) {
|
||||
auto pos = *call.get_position();
|
||||
auto pos_val = call.get_position();
|
||||
if (pos_val.has_value()) {
|
||||
auto pos = *pos_val;
|
||||
if (pos == this->position) {
|
||||
// already at target
|
||||
if (this->manual_control_ && (pos == COVER_OPEN || pos == COVER_CLOSED)) {
|
||||
|
||||
@@ -66,8 +66,9 @@ void Tormatic::control(const cover::CoverCall &call) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (call.get_position().has_value()) {
|
||||
auto pos = call.get_position().value();
|
||||
auto pos_val = call.get_position();
|
||||
if (pos_val.has_value()) {
|
||||
auto pos = *pos_val;
|
||||
this->control_position_(pos);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -502,7 +502,7 @@ void ToshibaClimate::transmit_generic_() {
|
||||
}
|
||||
|
||||
uint8_t fan;
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_QUIET:
|
||||
fan = TOSHIBA_FAN_SPEED_QUIET;
|
||||
break;
|
||||
@@ -567,7 +567,7 @@ void ToshibaClimate::transmit_rac_pt1411hwru_() {
|
||||
message[2] = RAC_PT1411HWRU_NO_FAN.code1;
|
||||
message[7] = RAC_PT1411HWRU_NO_FAN.code2;
|
||||
} else {
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
message[2] = RAC_PT1411HWRU_FAN_LOW.code1;
|
||||
message[7] = RAC_PT1411HWRU_FAN_LOW.code2;
|
||||
@@ -811,12 +811,12 @@ void ToshibaClimate::transmit_ras_2819t_() {
|
||||
uint8_t temp_code = get_ras_2819t_temp_code(temperature);
|
||||
|
||||
// Get fan speed encoding for rc_code_1
|
||||
climate::ClimateFanMode effective_fan_mode = this->fan_mode.value();
|
||||
climate::ClimateFanMode effective_fan_mode = this->fan_mode.value_or(climate::CLIMATE_FAN_ON);
|
||||
|
||||
// Dry mode only supports AUTO fan speed
|
||||
if (this->mode == climate::CLIMATE_MODE_DRY) {
|
||||
effective_fan_mode = climate::CLIMATE_FAN_AUTO;
|
||||
if (this->fan_mode.value() != climate::CLIMATE_FAN_AUTO) {
|
||||
if (this->fan_mode.value_or(climate::CLIMATE_FAN_ON) != climate::CLIMATE_FAN_AUTO) {
|
||||
ESP_LOGW(TAG, "Dry mode only supports AUTO fan speed, forcing AUTO");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,9 @@ namespace tuya {
|
||||
static const char *const TAG = "tuya.climate";
|
||||
|
||||
void TuyaClimate::setup() {
|
||||
if (this->switch_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->switch_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto switch_id = this->switch_id_;
|
||||
if (switch_id.has_value()) {
|
||||
this->parent_->register_listener(*switch_id, [this](const TuyaDatapoint &datapoint) {
|
||||
ESP_LOGV(TAG, "MCU reported switch is: %s", ONOFF(datapoint.value_bool));
|
||||
this->mode = climate::CLIMATE_MODE_OFF;
|
||||
if (datapoint.value_bool) {
|
||||
@@ -32,16 +33,18 @@ void TuyaClimate::setup() {
|
||||
this->cooling_state_pin_->setup();
|
||||
this->cooling_state_ = this->cooling_state_pin_->digital_read();
|
||||
}
|
||||
if (this->active_state_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->active_state_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto active_state_id = this->active_state_id_;
|
||||
if (active_state_id.has_value()) {
|
||||
this->parent_->register_listener(*active_state_id, [this](const TuyaDatapoint &datapoint) {
|
||||
ESP_LOGV(TAG, "MCU reported active state is: %u", datapoint.value_enum);
|
||||
this->active_state_ = datapoint.value_enum;
|
||||
this->compute_state_();
|
||||
this->publish_state();
|
||||
});
|
||||
}
|
||||
if (this->target_temperature_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->target_temperature_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto target_temp_id = this->target_temperature_id_;
|
||||
if (target_temp_id.has_value()) {
|
||||
this->parent_->register_listener(*target_temp_id, [this](const TuyaDatapoint &datapoint) {
|
||||
this->manual_temperature_ = datapoint.value_int * this->target_temperature_multiplier_;
|
||||
if (this->reports_fahrenheit_) {
|
||||
this->manual_temperature_ = (this->manual_temperature_ - 32) * 5 / 9;
|
||||
@@ -53,8 +56,9 @@ void TuyaClimate::setup() {
|
||||
this->publish_state();
|
||||
});
|
||||
}
|
||||
if (this->current_temperature_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->current_temperature_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto current_temp_id = this->current_temperature_id_;
|
||||
if (current_temp_id.has_value()) {
|
||||
this->parent_->register_listener(*current_temp_id, [this](const TuyaDatapoint &datapoint) {
|
||||
this->current_temperature = datapoint.value_int * this->current_temperature_multiplier_;
|
||||
if (this->reports_fahrenheit_) {
|
||||
this->current_temperature = (this->current_temperature - 32) * 5 / 9;
|
||||
@@ -65,8 +69,9 @@ void TuyaClimate::setup() {
|
||||
this->publish_state();
|
||||
});
|
||||
}
|
||||
if (this->eco_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->eco_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto eco_id = this->eco_id_;
|
||||
if (eco_id.has_value()) {
|
||||
this->parent_->register_listener(*eco_id, [this](const TuyaDatapoint &datapoint) {
|
||||
// Whether data type is BOOL or ENUM, it will still be a 1 or a 0, so the functions below are valid in both cases
|
||||
this->eco_ = datapoint.value_bool;
|
||||
this->eco_type_ = datapoint.type;
|
||||
@@ -76,8 +81,9 @@ void TuyaClimate::setup() {
|
||||
this->publish_state();
|
||||
});
|
||||
}
|
||||
if (this->sleep_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->sleep_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto sleep_id = this->sleep_id_;
|
||||
if (sleep_id.has_value()) {
|
||||
this->parent_->register_listener(*sleep_id, [this](const TuyaDatapoint &datapoint) {
|
||||
this->sleep_ = datapoint.value_bool;
|
||||
ESP_LOGV(TAG, "MCU reported sleep is: %s", ONOFF(this->sleep_));
|
||||
this->compute_preset_();
|
||||
@@ -85,8 +91,9 @@ void TuyaClimate::setup() {
|
||||
this->publish_state();
|
||||
});
|
||||
}
|
||||
if (this->swing_vertical_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->swing_vertical_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto swing_vert_id = this->swing_vertical_id_;
|
||||
if (swing_vert_id.has_value()) {
|
||||
this->parent_->register_listener(*swing_vert_id, [this](const TuyaDatapoint &datapoint) {
|
||||
this->swing_vertical_ = datapoint.value_bool;
|
||||
ESP_LOGV(TAG, "MCU reported vertical swing is: %s", ONOFF(datapoint.value_bool));
|
||||
this->compute_swingmode_();
|
||||
@@ -94,8 +101,9 @@ void TuyaClimate::setup() {
|
||||
});
|
||||
}
|
||||
|
||||
if (this->swing_horizontal_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->swing_horizontal_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto swing_horiz_id = this->swing_horizontal_id_;
|
||||
if (swing_horiz_id.has_value()) {
|
||||
this->parent_->register_listener(*swing_horiz_id, [this](const TuyaDatapoint &datapoint) {
|
||||
this->swing_horizontal_ = datapoint.value_bool;
|
||||
ESP_LOGV(TAG, "MCU reported horizontal swing is: %s", ONOFF(datapoint.value_bool));
|
||||
this->compute_swingmode_();
|
||||
@@ -103,8 +111,9 @@ void TuyaClimate::setup() {
|
||||
});
|
||||
}
|
||||
|
||||
if (this->fan_speed_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->fan_speed_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto fan_speed_id = this->fan_speed_id_;
|
||||
if (fan_speed_id.has_value()) {
|
||||
this->parent_->register_listener(*fan_speed_id, [this](const TuyaDatapoint &datapoint) {
|
||||
ESP_LOGV(TAG, "MCU reported Fan Speed Mode is: %u", datapoint.value_enum);
|
||||
this->fan_state_ = datapoint.value_enum;
|
||||
this->compute_fanmode_();
|
||||
@@ -139,21 +148,34 @@ void TuyaClimate::loop() {
|
||||
}
|
||||
|
||||
void TuyaClimate::control(const climate::ClimateCall &call) {
|
||||
if (call.get_mode().has_value()) {
|
||||
const bool switch_state = *call.get_mode() != climate::CLIMATE_MODE_OFF;
|
||||
auto mode = call.get_mode();
|
||||
if (mode.has_value()) {
|
||||
const bool switch_state = *mode != climate::CLIMATE_MODE_OFF;
|
||||
ESP_LOGV(TAG, "Setting switch: %s", ONOFF(switch_state));
|
||||
this->parent_->set_boolean_datapoint_value(*this->switch_id_, switch_state);
|
||||
const climate::ClimateMode new_mode = *call.get_mode();
|
||||
auto switch_dp_id = this->switch_id_;
|
||||
if (switch_dp_id.has_value()) {
|
||||
this->parent_->set_boolean_datapoint_value(*switch_dp_id, switch_state);
|
||||
}
|
||||
const climate::ClimateMode new_mode = *mode;
|
||||
|
||||
if (this->active_state_id_.has_value()) {
|
||||
auto active_state_dp_id = this->active_state_id_;
|
||||
if (active_state_dp_id.has_value()) {
|
||||
if (new_mode == climate::CLIMATE_MODE_HEAT && this->supports_heat_) {
|
||||
this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_heating_value_);
|
||||
auto heating_val = this->active_state_heating_value_;
|
||||
if (heating_val.has_value())
|
||||
this->parent_->set_enum_datapoint_value(*active_state_dp_id, *heating_val);
|
||||
} else if (new_mode == climate::CLIMATE_MODE_COOL && this->supports_cool_) {
|
||||
this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_cooling_value_);
|
||||
} else if (new_mode == climate::CLIMATE_MODE_DRY && this->active_state_drying_value_.has_value()) {
|
||||
this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_drying_value_);
|
||||
} else if (new_mode == climate::CLIMATE_MODE_FAN_ONLY && this->active_state_fanonly_value_.has_value()) {
|
||||
this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_fanonly_value_);
|
||||
auto cooling_val = this->active_state_cooling_value_;
|
||||
if (cooling_val.has_value())
|
||||
this->parent_->set_enum_datapoint_value(*active_state_dp_id, *cooling_val);
|
||||
} else if (new_mode == climate::CLIMATE_MODE_DRY) {
|
||||
auto drying_val = this->active_state_drying_value_;
|
||||
if (drying_val.has_value())
|
||||
this->parent_->set_enum_datapoint_value(*active_state_dp_id, *drying_val);
|
||||
} else if (new_mode == climate::CLIMATE_MODE_FAN_ONLY) {
|
||||
auto fanonly_val = this->active_state_fanonly_value_;
|
||||
if (fanonly_val.has_value())
|
||||
this->parent_->set_enum_datapoint_value(*active_state_dp_id, *fanonly_val);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Active state (mode) datapoint not configured");
|
||||
@@ -163,31 +185,38 @@ void TuyaClimate::control(const climate::ClimateCall &call) {
|
||||
control_swing_mode_(call);
|
||||
control_fan_mode_(call);
|
||||
|
||||
if (call.get_target_temperature().has_value()) {
|
||||
float target_temperature = *call.get_target_temperature();
|
||||
auto target_temp = call.get_target_temperature();
|
||||
if (target_temp.has_value()) {
|
||||
float target_temperature = *target_temp;
|
||||
if (this->reports_fahrenheit_)
|
||||
target_temperature = (target_temperature * 9 / 5) + 32;
|
||||
|
||||
ESP_LOGV(TAG, "Setting target temperature: %.1f", target_temperature);
|
||||
this->parent_->set_integer_datapoint_value(*this->target_temperature_id_,
|
||||
(int) (target_temperature / this->target_temperature_multiplier_));
|
||||
auto target_temp_dp_id = this->target_temperature_id_;
|
||||
if (target_temp_dp_id.has_value()) {
|
||||
this->parent_->set_integer_datapoint_value(*target_temp_dp_id,
|
||||
(int) (target_temperature / this->target_temperature_multiplier_));
|
||||
}
|
||||
}
|
||||
|
||||
if (call.get_preset().has_value()) {
|
||||
const climate::ClimatePreset preset = *call.get_preset();
|
||||
if (this->eco_id_.has_value()) {
|
||||
auto preset_val = call.get_preset();
|
||||
if (preset_val.has_value()) {
|
||||
const climate::ClimatePreset preset = *preset_val;
|
||||
auto eco_dp_id = this->eco_id_;
|
||||
if (eco_dp_id.has_value()) {
|
||||
const bool eco = preset == climate::CLIMATE_PRESET_ECO;
|
||||
ESP_LOGV(TAG, "Setting eco: %s", ONOFF(eco));
|
||||
if (this->eco_type_ == TuyaDatapointType::ENUM) {
|
||||
this->parent_->set_enum_datapoint_value(*this->eco_id_, eco);
|
||||
this->parent_->set_enum_datapoint_value(*eco_dp_id, eco);
|
||||
} else {
|
||||
this->parent_->set_boolean_datapoint_value(*this->eco_id_, eco);
|
||||
this->parent_->set_boolean_datapoint_value(*eco_dp_id, eco);
|
||||
}
|
||||
}
|
||||
if (this->sleep_id_.has_value()) {
|
||||
auto sleep_dp_id = this->sleep_id_;
|
||||
if (sleep_dp_id.has_value()) {
|
||||
const bool sleep = preset == climate::CLIMATE_PRESET_SLEEP;
|
||||
ESP_LOGV(TAG, "Setting sleep: %s", ONOFF(sleep));
|
||||
this->parent_->set_boolean_datapoint_value(*this->sleep_id_, sleep);
|
||||
this->parent_->set_boolean_datapoint_value(*sleep_dp_id, sleep);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,8 +225,9 @@ void TuyaClimate::control_swing_mode_(const climate::ClimateCall &call) {
|
||||
bool vertical_swing_changed = false;
|
||||
bool horizontal_swing_changed = false;
|
||||
|
||||
if (call.get_swing_mode().has_value()) {
|
||||
const auto swing_mode = *call.get_swing_mode();
|
||||
auto swing_mode_val = call.get_swing_mode();
|
||||
if (swing_mode_val.has_value()) {
|
||||
const auto swing_mode = *swing_mode_val;
|
||||
|
||||
switch (swing_mode) {
|
||||
case climate::CLIMATE_SWING_OFF:
|
||||
@@ -241,14 +271,16 @@ void TuyaClimate::control_swing_mode_(const climate::ClimateCall &call) {
|
||||
}
|
||||
}
|
||||
|
||||
if (vertical_swing_changed && this->swing_vertical_id_.has_value()) {
|
||||
auto vert_dp_id = this->swing_vertical_id_;
|
||||
if (vertical_swing_changed && vert_dp_id.has_value()) {
|
||||
ESP_LOGV(TAG, "Setting vertical swing: %s", ONOFF(swing_vertical_));
|
||||
this->parent_->set_boolean_datapoint_value(*this->swing_vertical_id_, swing_vertical_);
|
||||
this->parent_->set_boolean_datapoint_value(*vert_dp_id, swing_vertical_);
|
||||
}
|
||||
|
||||
if (horizontal_swing_changed && this->swing_horizontal_id_.has_value()) {
|
||||
auto horiz_dp_id = this->swing_horizontal_id_;
|
||||
if (horizontal_swing_changed && horiz_dp_id.has_value()) {
|
||||
ESP_LOGV(TAG, "Setting horizontal swing: %s", ONOFF(swing_horizontal_));
|
||||
this->parent_->set_boolean_datapoint_value(*this->swing_horizontal_id_, swing_horizontal_);
|
||||
this->parent_->set_boolean_datapoint_value(*horiz_dp_id, swing_horizontal_);
|
||||
}
|
||||
|
||||
// Publish the state after updating the swing mode
|
||||
@@ -256,33 +288,35 @@ void TuyaClimate::control_swing_mode_(const climate::ClimateCall &call) {
|
||||
}
|
||||
|
||||
void TuyaClimate::control_fan_mode_(const climate::ClimateCall &call) {
|
||||
if (call.get_fan_mode().has_value()) {
|
||||
climate::ClimateFanMode fan_mode = *call.get_fan_mode();
|
||||
auto fan_mode_val = call.get_fan_mode();
|
||||
if (fan_mode_val.has_value()) {
|
||||
climate::ClimateFanMode fan_mode = *fan_mode_val;
|
||||
|
||||
uint8_t tuya_fan_speed;
|
||||
switch (fan_mode) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
tuya_fan_speed = *fan_speed_low_value_;
|
||||
tuya_fan_speed = this->fan_speed_low_value_.value_or(0);
|
||||
break;
|
||||
case climate::CLIMATE_FAN_MEDIUM:
|
||||
tuya_fan_speed = *fan_speed_medium_value_;
|
||||
tuya_fan_speed = this->fan_speed_medium_value_.value_or(0);
|
||||
break;
|
||||
case climate::CLIMATE_FAN_MIDDLE:
|
||||
tuya_fan_speed = *fan_speed_middle_value_;
|
||||
tuya_fan_speed = this->fan_speed_middle_value_.value_or(0);
|
||||
break;
|
||||
case climate::CLIMATE_FAN_HIGH:
|
||||
tuya_fan_speed = *fan_speed_high_value_;
|
||||
tuya_fan_speed = this->fan_speed_high_value_.value_or(0);
|
||||
break;
|
||||
case climate::CLIMATE_FAN_AUTO:
|
||||
tuya_fan_speed = *fan_speed_auto_value_;
|
||||
tuya_fan_speed = this->fan_speed_auto_value_.value_or(0);
|
||||
break;
|
||||
default:
|
||||
tuya_fan_speed = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (this->fan_speed_id_.has_value()) {
|
||||
this->parent_->set_enum_datapoint_value(*this->fan_speed_id_, tuya_fan_speed);
|
||||
auto fan_speed_dp_id = this->fan_speed_id_;
|
||||
if (fan_speed_dp_id.has_value()) {
|
||||
this->parent_->set_enum_datapoint_value(*fan_speed_dp_id, tuya_fan_speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -337,31 +371,39 @@ climate::ClimateTraits TuyaClimate::traits() {
|
||||
|
||||
void TuyaClimate::dump_config() {
|
||||
LOG_CLIMATE("", "Tuya Climate", this);
|
||||
if (this->switch_id_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Switch has datapoint ID %u", *this->switch_id_);
|
||||
auto switch_dp_id = this->switch_id_;
|
||||
if (switch_dp_id.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Switch has datapoint ID %u", *switch_dp_id);
|
||||
}
|
||||
if (this->active_state_id_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Active state has datapoint ID %u", *this->active_state_id_);
|
||||
auto active_state_dp_id = this->active_state_id_;
|
||||
if (active_state_dp_id.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Active state has datapoint ID %u", *active_state_dp_id);
|
||||
}
|
||||
if (this->target_temperature_id_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Target Temperature has datapoint ID %u", *this->target_temperature_id_);
|
||||
auto target_temp_dp_id = this->target_temperature_id_;
|
||||
if (target_temp_dp_id.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Target Temperature has datapoint ID %u", *target_temp_dp_id);
|
||||
}
|
||||
if (this->current_temperature_id_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Current Temperature has datapoint ID %u", *this->current_temperature_id_);
|
||||
auto current_temp_dp_id = this->current_temperature_id_;
|
||||
if (current_temp_dp_id.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Current Temperature has datapoint ID %u", *current_temp_dp_id);
|
||||
}
|
||||
LOG_PIN(" Heating State Pin: ", this->heating_state_pin_);
|
||||
LOG_PIN(" Cooling State Pin: ", this->cooling_state_pin_);
|
||||
if (this->eco_id_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Eco has datapoint ID %u", *this->eco_id_);
|
||||
auto eco_dp_id = this->eco_id_;
|
||||
if (eco_dp_id.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Eco has datapoint ID %u", *eco_dp_id);
|
||||
}
|
||||
if (this->sleep_id_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Sleep has datapoint ID %u", *this->sleep_id_);
|
||||
auto sleep_dp_id = this->sleep_id_;
|
||||
if (sleep_dp_id.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Sleep has datapoint ID %u", *sleep_dp_id);
|
||||
}
|
||||
if (this->swing_vertical_id_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Swing Vertical has datapoint ID %u", *this->swing_vertical_id_);
|
||||
auto swing_vert_dp_id = this->swing_vertical_id_;
|
||||
if (swing_vert_dp_id.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Swing Vertical has datapoint ID %u", *swing_vert_dp_id);
|
||||
}
|
||||
if (this->swing_horizontal_id_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Swing Horizontal has datapoint ID %u", *this->swing_horizontal_id_);
|
||||
auto swing_horiz_dp_id = this->swing_horizontal_id_;
|
||||
if (swing_horiz_dp_id.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Swing Horizontal has datapoint ID %u", *swing_horiz_dp_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,9 @@ void TuyaCover::setup() {
|
||||
}
|
||||
});
|
||||
|
||||
if (!this->position_id_.has_value()) {
|
||||
return;
|
||||
}
|
||||
uint8_t report_id = *this->position_id_;
|
||||
if (this->position_report_id_.has_value()) {
|
||||
// A position report datapoint is configured; listen to that instead.
|
||||
@@ -60,29 +63,30 @@ void TuyaCover::control(const cover::CoverCall &call) {
|
||||
if (call.get_stop()) {
|
||||
if (this->control_id_.has_value()) {
|
||||
this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_STOP);
|
||||
} else {
|
||||
} else if (this->position_id_.has_value()) {
|
||||
auto pos = this->position;
|
||||
pos = this->invert_position_report_ ? pos : 1.0f - pos;
|
||||
auto position_int = static_cast<uint32_t>(pos * this->value_range_);
|
||||
position_int = position_int + this->min_value_;
|
||||
|
||||
parent_->force_set_integer_datapoint_value(*this->position_id_, position_int);
|
||||
this->parent_->force_set_integer_datapoint_value(*this->position_id_, position_int);
|
||||
}
|
||||
}
|
||||
if (call.get_position().has_value()) {
|
||||
auto pos = *call.get_position();
|
||||
auto pos_opt = call.get_position();
|
||||
if (pos_opt.has_value()) {
|
||||
auto pos = *pos_opt;
|
||||
if (this->control_id_.has_value() && (pos == COVER_OPEN || pos == COVER_CLOSED)) {
|
||||
if (pos == COVER_OPEN) {
|
||||
this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_OPEN);
|
||||
} else {
|
||||
this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_CLOSE);
|
||||
}
|
||||
} else {
|
||||
} else if (this->position_id_.has_value()) {
|
||||
pos = this->invert_position_report_ ? pos : 1.0f - pos;
|
||||
auto position_int = static_cast<uint32_t>(pos * this->value_range_);
|
||||
position_int = position_int + this->min_value_;
|
||||
|
||||
parent_->force_set_integer_datapoint_value(*this->position_id_, position_int);
|
||||
this->parent_->force_set_integer_datapoint_value(*this->position_id_, position_int);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@ namespace tuya {
|
||||
static const char *const TAG = "tuya.fan";
|
||||
|
||||
void TuyaFan::setup() {
|
||||
if (this->speed_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->speed_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto speed_id = this->speed_id_;
|
||||
if (speed_id.has_value()) {
|
||||
this->parent_->register_listener(*speed_id, [this](const TuyaDatapoint &datapoint) {
|
||||
if (datapoint.type == TuyaDatapointType::ENUM) {
|
||||
ESP_LOGV(TAG, "MCU reported speed of: %d", datapoint.value_enum);
|
||||
if (datapoint.value_enum >= this->speed_count_) {
|
||||
@@ -25,15 +26,17 @@ void TuyaFan::setup() {
|
||||
this->speed_type_ = datapoint.type;
|
||||
});
|
||||
}
|
||||
if (this->switch_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->switch_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto switch_id = this->switch_id_;
|
||||
if (switch_id.has_value()) {
|
||||
this->parent_->register_listener(*switch_id, [this](const TuyaDatapoint &datapoint) {
|
||||
ESP_LOGV(TAG, "MCU reported switch is: %s", ONOFF(datapoint.value_bool));
|
||||
this->state = datapoint.value_bool;
|
||||
this->publish_state();
|
||||
});
|
||||
}
|
||||
if (this->oscillation_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->oscillation_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto oscillation_id = this->oscillation_id_;
|
||||
if (oscillation_id.has_value()) {
|
||||
this->parent_->register_listener(*oscillation_id, [this](const TuyaDatapoint &datapoint) {
|
||||
// Whether data type is BOOL or ENUM, it will still be a 1 or a 0, so the functions below are valid in both
|
||||
// scenarios
|
||||
ESP_LOGV(TAG, "MCU reported oscillation is: %s", ONOFF(datapoint.value_bool));
|
||||
@@ -43,8 +46,9 @@ void TuyaFan::setup() {
|
||||
this->oscillation_type_ = datapoint.type;
|
||||
});
|
||||
}
|
||||
if (this->direction_id_.has_value()) {
|
||||
this->parent_->register_listener(*this->direction_id_, [this](const TuyaDatapoint &datapoint) {
|
||||
auto direction_id = this->direction_id_;
|
||||
if (direction_id.has_value()) {
|
||||
this->parent_->register_listener(*direction_id, [this](const TuyaDatapoint &datapoint) {
|
||||
ESP_LOGD(TAG, "MCU reported reverse direction is: %s", ONOFF(datapoint.value_bool));
|
||||
this->direction = datapoint.value_bool ? fan::FanDirection::REVERSE : fan::FanDirection::FORWARD;
|
||||
this->publish_state();
|
||||
@@ -60,17 +64,21 @@ void TuyaFan::setup() {
|
||||
|
||||
void TuyaFan::dump_config() {
|
||||
LOG_FAN("", "Tuya Fan", this);
|
||||
if (this->speed_id_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Speed has datapoint ID %u", *this->speed_id_);
|
||||
auto speed_dp_id = this->speed_id_;
|
||||
if (speed_dp_id.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Speed has datapoint ID %u", *speed_dp_id);
|
||||
}
|
||||
if (this->switch_id_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Switch has datapoint ID %u", *this->switch_id_);
|
||||
auto switch_dp_id = this->switch_id_;
|
||||
if (switch_dp_id.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Switch has datapoint ID %u", *switch_dp_id);
|
||||
}
|
||||
if (this->oscillation_id_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Oscillation has datapoint ID %u", *this->oscillation_id_);
|
||||
auto oscillation_dp_id = this->oscillation_id_;
|
||||
if (oscillation_dp_id.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Oscillation has datapoint ID %u", *oscillation_dp_id);
|
||||
}
|
||||
if (this->direction_id_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Direction has datapoint ID %u", *this->direction_id_);
|
||||
auto direction_dp_id = this->direction_id_;
|
||||
if (direction_dp_id.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Direction has datapoint ID %u", *direction_dp_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,25 +88,41 @@ fan::FanTraits TuyaFan::get_traits() {
|
||||
}
|
||||
|
||||
void TuyaFan::control(const fan::FanCall &call) {
|
||||
if (this->switch_id_.has_value() && call.get_state().has_value()) {
|
||||
this->parent_->set_boolean_datapoint_value(*this->switch_id_, *call.get_state());
|
||||
}
|
||||
if (this->oscillation_id_.has_value() && call.get_oscillating().has_value()) {
|
||||
if (this->oscillation_type_ == TuyaDatapointType::ENUM) {
|
||||
this->parent_->set_enum_datapoint_value(*this->oscillation_id_, *call.get_oscillating());
|
||||
} else if (this->oscillation_type_ == TuyaDatapointType::BOOLEAN) {
|
||||
this->parent_->set_boolean_datapoint_value(*this->oscillation_id_, *call.get_oscillating());
|
||||
auto switch_id = this->switch_id_;
|
||||
if (switch_id.has_value()) {
|
||||
auto state = call.get_state();
|
||||
if (state.has_value()) {
|
||||
this->parent_->set_boolean_datapoint_value(*switch_id, *state);
|
||||
}
|
||||
}
|
||||
if (this->direction_id_.has_value() && call.get_direction().has_value()) {
|
||||
bool enable = *call.get_direction() == fan::FanDirection::REVERSE;
|
||||
this->parent_->set_enum_datapoint_value(*this->direction_id_, enable);
|
||||
auto osc_id = this->oscillation_id_;
|
||||
if (osc_id.has_value()) {
|
||||
auto oscillating = call.get_oscillating();
|
||||
if (oscillating.has_value()) {
|
||||
if (this->oscillation_type_ == TuyaDatapointType::ENUM) {
|
||||
this->parent_->set_enum_datapoint_value(*osc_id, *oscillating);
|
||||
} else if (this->oscillation_type_ == TuyaDatapointType::BOOLEAN) {
|
||||
this->parent_->set_boolean_datapoint_value(*osc_id, *oscillating);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this->speed_id_.has_value() && call.get_speed().has_value()) {
|
||||
if (this->speed_type_ == TuyaDatapointType::ENUM) {
|
||||
this->parent_->set_enum_datapoint_value(*this->speed_id_, *call.get_speed() - 1);
|
||||
} else if (this->speed_type_ == TuyaDatapointType::INTEGER) {
|
||||
this->parent_->set_integer_datapoint_value(*this->speed_id_, *call.get_speed());
|
||||
auto dir_id = this->direction_id_;
|
||||
if (dir_id.has_value()) {
|
||||
auto direction = call.get_direction();
|
||||
if (direction.has_value()) {
|
||||
bool enable = *direction == fan::FanDirection::REVERSE;
|
||||
this->parent_->set_enum_datapoint_value(*dir_id, enable);
|
||||
}
|
||||
}
|
||||
auto spd_id = this->speed_id_;
|
||||
if (spd_id.has_value()) {
|
||||
auto speed = call.get_speed();
|
||||
if (speed.has_value()) {
|
||||
if (this->speed_type_ == TuyaDatapointType::ENUM) {
|
||||
this->parent_->set_enum_datapoint_value(*spd_id, *speed - 1);
|
||||
} else if (this->speed_type_ == TuyaDatapointType::INTEGER) {
|
||||
this->parent_->set_integer_datapoint_value(*spd_id, *speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@ void TuyaLight::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->color_type_.has_value())
|
||||
return;
|
||||
|
||||
float red, green, blue;
|
||||
switch (*this->color_type_) {
|
||||
case TuyaColorType::RGBHSV:
|
||||
@@ -185,7 +188,7 @@ void TuyaLight::write_state(light::LightState *state) {
|
||||
}
|
||||
}
|
||||
|
||||
if (this->color_id_.has_value() && (brightness == 0.0f || !color_interlock_)) {
|
||||
if (this->color_id_.has_value() && this->color_type_.has_value() && (brightness == 0.0f || !color_interlock_)) {
|
||||
std::string color_value;
|
||||
switch (*this->color_type_) {
|
||||
case TuyaColorType::RGB: {
|
||||
|
||||
@@ -42,8 +42,9 @@ climate::ClimateTraits UponorSmatrixClimate::traits() {
|
||||
}
|
||||
|
||||
void UponorSmatrixClimate::control(const climate::ClimateCall &call) {
|
||||
if (call.get_target_temperature().has_value()) {
|
||||
uint16_t temp = celsius_to_raw(*call.get_target_temperature());
|
||||
auto val = call.get_target_temperature();
|
||||
if (val.has_value()) {
|
||||
uint16_t temp = celsius_to_raw(*val);
|
||||
if (this->preset == climate::CLIMATE_PRESET_ECO) {
|
||||
// During ECO mode, the thermostat automatically substracts the setback value from the setpoint,
|
||||
// so we need to add it here first
|
||||
|
||||
@@ -82,7 +82,7 @@ void WhirlpoolClimate::transmit_state() {
|
||||
remote_state[3] |= (uint8_t) (temp - this->temperature_min_()) << 4;
|
||||
|
||||
// Fan speed
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_HIGH:
|
||||
remote_state[2] |= WHIRLPOOL_FAN_HIGH;
|
||||
break;
|
||||
|
||||
@@ -69,7 +69,7 @@ void Whynter::transmit_state() {
|
||||
}
|
||||
mode_before_ = this->mode;
|
||||
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
remote_state |= FAN_LOW;
|
||||
break;
|
||||
|
||||
@@ -1094,8 +1094,9 @@ void WiFiComponent::start_connecting(const WiFiAP &ap) {
|
||||
}
|
||||
|
||||
#ifdef USE_WIFI_WPA2_EAP
|
||||
if (ap.get_eap().has_value()) {
|
||||
EAPAuth eap_config = ap.get_eap().value();
|
||||
auto eap_opt = ap.get_eap();
|
||||
if (eap_opt.has_value()) {
|
||||
EAPAuth eap_config = *eap_opt;
|
||||
// clang-format off
|
||||
ESP_LOGV(
|
||||
TAG,
|
||||
@@ -1129,8 +1130,9 @@ void WiFiComponent::start_connecting(const WiFiAP &ap) {
|
||||
ESP_LOGV(TAG, " Channel not set");
|
||||
}
|
||||
#ifdef USE_WIFI_MANUAL_IP
|
||||
if (ap.get_manual_ip().has_value()) {
|
||||
ManualIP m = *ap.get_manual_ip();
|
||||
auto manual_ip = ap.get_manual_ip();
|
||||
if (manual_ip.has_value()) {
|
||||
ManualIP m = *manual_ip;
|
||||
char static_ip_buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||
char gateway_buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||
char subnet_buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||
|
||||
@@ -298,9 +298,10 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
|
||||
|
||||
// setup enterprise authentication if required
|
||||
#ifdef USE_WIFI_WPA2_EAP
|
||||
if (ap.get_eap().has_value()) {
|
||||
auto eap_opt = ap.get_eap();
|
||||
if (eap_opt.has_value()) {
|
||||
// note: all certificates and keys have to be null terminated. Lengths are appended by +1 to include \0.
|
||||
EAPAuth eap = ap.get_eap().value();
|
||||
EAPAuth eap = *eap_opt;
|
||||
ret = wifi_station_set_enterprise_identity((uint8_t *) eap.identity.c_str(), eap.identity.length());
|
||||
if (ret) {
|
||||
ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_identity failed: %d", ret);
|
||||
|
||||
@@ -403,9 +403,10 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
|
||||
|
||||
// setup enterprise authentication if required
|
||||
#ifdef USE_WIFI_WPA2_EAP
|
||||
if (ap.get_eap().has_value()) {
|
||||
auto eap_opt = ap.get_eap();
|
||||
if (eap_opt.has_value()) {
|
||||
// note: all certificates and keys have to be null terminated. Lengths are appended by +1 to include \0.
|
||||
EAPAuth eap = ap.get_eap().value();
|
||||
EAPAuth eap = *eap_opt;
|
||||
#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1)
|
||||
err = esp_eap_client_set_identity((uint8_t *) eap.identity.c_str(), eap.identity.length());
|
||||
#else
|
||||
|
||||
@@ -120,10 +120,12 @@ void YashimaClimate::setup() {
|
||||
}
|
||||
|
||||
void YashimaClimate::control(const climate::ClimateCall &call) {
|
||||
if (call.get_mode().has_value())
|
||||
this->mode = *call.get_mode();
|
||||
if (call.get_target_temperature().has_value())
|
||||
this->target_temperature = *call.get_target_temperature();
|
||||
auto call_mode = call.get_mode();
|
||||
if (call_mode.has_value())
|
||||
this->mode = *call_mode;
|
||||
auto call_target = call.get_target_temperature();
|
||||
if (call_target.has_value())
|
||||
this->target_temperature = *call_target;
|
||||
|
||||
this->transmit_state_();
|
||||
this->publish_state();
|
||||
|
||||
@@ -13,7 +13,7 @@ void ZHLT01Climate::transmit_state() {
|
||||
ir_message[1] = 0x00; // Timer off
|
||||
|
||||
// Byte 3 : Turbo mode
|
||||
if (this->preset.value() == climate::CLIMATE_PRESET_BOOST) {
|
||||
if (this->preset.value_or(climate::CLIMATE_PRESET_NONE) == climate::CLIMATE_PRESET_BOOST) {
|
||||
ir_message[3] = AC1_FAN_TURBO;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ void ZHLT01Climate::transmit_state() {
|
||||
}
|
||||
|
||||
// -- Fan
|
||||
switch (this->preset.value()) {
|
||||
switch (this->preset.value_or(climate::CLIMATE_PRESET_NONE)) {
|
||||
case climate::CLIMATE_PRESET_BOOST:
|
||||
ir_message[7] |= AC1_FAN3;
|
||||
break;
|
||||
@@ -55,7 +55,7 @@ void ZHLT01Climate::transmit_state() {
|
||||
ir_message[7] |= AC1_FAN_SILENT;
|
||||
break;
|
||||
default:
|
||||
switch (this->fan_mode.value()) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
ir_message[7] |= AC1_FAN1;
|
||||
break;
|
||||
|
||||
@@ -248,7 +248,7 @@ void log_entity_unit_of_measurement(const char *tag, const char *prefix, const E
|
||||
template<typename T> class StatefulEntityBase : public EntityBase {
|
||||
public:
|
||||
virtual bool has_state() const { return this->state_.has_value(); }
|
||||
virtual const T &get_state() const { return this->state_.value(); }
|
||||
virtual const T &get_state() const { return this->state_.value(); } // NOLINT(bugprone-unchecked-optional-access)
|
||||
virtual T get_state_default(T default_value) const { return this->state_.value_or(default_value); }
|
||||
void invalidate_state() { this->set_new_state({}); }
|
||||
|
||||
|
||||
@@ -1,220 +1,12 @@
|
||||
#pragma once
|
||||
//
|
||||
// Copyright (c) 2017 Martin Moene
|
||||
//
|
||||
// https://github.com/martinmoene/optional-bare
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// Modified by Otto Winter on 18.05.18
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
|
||||
namespace esphome {
|
||||
|
||||
// type for nullopt
|
||||
|
||||
struct nullopt_t { // NOLINT
|
||||
struct init {}; // NOLINT
|
||||
nullopt_t(init /*unused*/) {}
|
||||
};
|
||||
|
||||
// extra parenthesis to prevent the most vexing parse:
|
||||
|
||||
const nullopt_t nullopt((nullopt_t::init())); // NOLINT
|
||||
|
||||
// Simplistic optional: requires T to be default constructible, copyable.
|
||||
|
||||
template<typename T> class optional { // NOLINT
|
||||
private:
|
||||
using safe_bool = void (optional::*)() const;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
optional() {}
|
||||
|
||||
optional(nullopt_t /*unused*/) {}
|
||||
|
||||
optional(T const &arg) : has_value_(true), value_(arg) {} // NOLINT
|
||||
|
||||
template<class U> optional(optional<U> const &other) : has_value_(other.has_value()), value_(other.value()) {}
|
||||
|
||||
optional &operator=(nullopt_t /*unused*/) {
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
bool operator==(optional<T> const &rhs) const {
|
||||
if (has_value() && rhs.has_value())
|
||||
return value() == rhs.value();
|
||||
return !has_value() && !rhs.has_value();
|
||||
}
|
||||
|
||||
template<class U> optional &operator=(optional<U> const &other) {
|
||||
has_value_ = other.has_value();
|
||||
value_ = other.value();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(optional &rhs) noexcept {
|
||||
using std::swap;
|
||||
if (has_value() && rhs.has_value()) {
|
||||
swap(**this, *rhs);
|
||||
} else if (!has_value() && rhs.has_value()) {
|
||||
initialize(*rhs);
|
||||
rhs.reset();
|
||||
} else if (has_value() && !rhs.has_value()) {
|
||||
rhs.initialize(**this);
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
// observers
|
||||
|
||||
value_type const *operator->() const { return &value_; }
|
||||
|
||||
value_type *operator->() { return &value_; }
|
||||
|
||||
value_type const &operator*() const { return value_; }
|
||||
|
||||
value_type &operator*() { return value_; }
|
||||
|
||||
operator safe_bool() const { return has_value() ? &optional::this_type_does_not_support_comparisons : nullptr; }
|
||||
|
||||
bool has_value() const { return has_value_; }
|
||||
|
||||
value_type const &value() const { return value_; }
|
||||
|
||||
value_type &value() { return value_; }
|
||||
|
||||
template<class U> value_type value_or(U const &v) const { return has_value() ? value() : static_cast<value_type>(v); }
|
||||
|
||||
// modifiers
|
||||
|
||||
void reset() { has_value_ = false; }
|
||||
|
||||
private:
|
||||
void this_type_does_not_support_comparisons() const {} // NOLINT
|
||||
|
||||
template<typename V> void initialize(V const &value) { // NOLINT
|
||||
value_ = value;
|
||||
has_value_ = true;
|
||||
}
|
||||
|
||||
bool has_value_{false}; // NOLINT
|
||||
value_type value_; // NOLINT
|
||||
};
|
||||
|
||||
// Relational operators
|
||||
|
||||
template<typename T, typename U> inline bool operator==(optional<T> const &x, optional<U> const &y) {
|
||||
return bool(x) != bool(y) ? false : !bool(x) ? true : *x == *y;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator!=(optional<T> const &x, optional<U> const &y) {
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator<(optional<T> const &x, optional<U> const &y) {
|
||||
return (!y) ? false : (!x) ? true : *x < *y;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator>(optional<T> const &x, optional<U> const &y) { return (y < x); }
|
||||
|
||||
template<typename T, typename U> inline bool operator<=(optional<T> const &x, optional<U> const &y) { return !(y < x); }
|
||||
|
||||
template<typename T, typename U> inline bool operator>=(optional<T> const &x, optional<U> const &y) { return !(x < y); }
|
||||
|
||||
// Comparison with nullopt
|
||||
|
||||
template<typename T> inline bool operator==(optional<T> const &x, nullopt_t /*unused*/) { return (!x); }
|
||||
|
||||
template<typename T> inline bool operator==(nullopt_t /*unused*/, optional<T> const &x) { return (!x); }
|
||||
|
||||
template<typename T> inline bool operator!=(optional<T> const &x, nullopt_t /*unused*/) { return bool(x); }
|
||||
|
||||
template<typename T> inline bool operator!=(nullopt_t /*unused*/, optional<T> const &x) { return bool(x); }
|
||||
|
||||
template<typename T> inline bool operator<(optional<T> const & /*unused*/, nullopt_t /*unused*/) { return false; }
|
||||
|
||||
template<typename T> inline bool operator<(nullopt_t /*unused*/, optional<T> const &x) { return bool(x); }
|
||||
|
||||
template<typename T> inline bool operator<=(optional<T> const &x, nullopt_t /*unused*/) { return (!x); }
|
||||
|
||||
template<typename T> inline bool operator<=(nullopt_t /*unused*/, optional<T> const & /*unused*/) { return true; }
|
||||
|
||||
template<typename T> inline bool operator>(optional<T> const &x, nullopt_t /*unused*/) { return bool(x); }
|
||||
|
||||
template<typename T> inline bool operator>(nullopt_t /*unused*/, optional<T> const & /*unused*/) { return false; }
|
||||
|
||||
template<typename T> inline bool operator>=(optional<T> const & /*unused*/, nullopt_t /*unused*/) { return true; }
|
||||
|
||||
template<typename T> inline bool operator>=(nullopt_t /*unused*/, optional<T> const &x) { return (!x); }
|
||||
|
||||
// Comparison with T
|
||||
|
||||
template<typename T, typename U> inline bool operator==(optional<T> const &x, U const &v) {
|
||||
return bool(x) ? *x == v : false;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator==(U const &v, optional<T> const &x) {
|
||||
return bool(x) ? v == *x : false;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator!=(optional<T> const &x, U const &v) {
|
||||
return bool(x) ? *x != v : true;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator!=(U const &v, optional<T> const &x) {
|
||||
return bool(x) ? v != *x : true;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator<(optional<T> const &x, U const &v) {
|
||||
return bool(x) ? *x < v : true;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator<(U const &v, optional<T> const &x) {
|
||||
return bool(x) ? v < *x : false;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator<=(optional<T> const &x, U const &v) {
|
||||
return bool(x) ? *x <= v : true;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator<=(U const &v, optional<T> const &x) {
|
||||
return bool(x) ? v <= *x : false;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator>(optional<T> const &x, U const &v) {
|
||||
return bool(x) ? *x > v : false;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator>(U const &v, optional<T> const &x) {
|
||||
return bool(x) ? v > *x : true;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator>=(optional<T> const &x, U const &v) {
|
||||
return bool(x) ? *x >= v : false;
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator>=(U const &v, optional<T> const &x) {
|
||||
return bool(x) ? v >= *x : true;
|
||||
}
|
||||
|
||||
// Specialized algorithms
|
||||
|
||||
template<typename T> void swap(optional<T> &x, optional<T> &y) noexcept { x.swap(y); }
|
||||
|
||||
// Convenience function to create an optional.
|
||||
|
||||
template<typename T> inline optional<T> make_optional(T const &v) { return optional<T>(v); }
|
||||
using std::make_optional;
|
||||
using std::nullopt;
|
||||
using std::nullopt_t;
|
||||
using std::optional;
|
||||
|
||||
} // namespace esphome
|
||||
|
||||
@@ -31,9 +31,7 @@ Component = esphome_ns.class_("Component")
|
||||
ComponentPtr = Component.operator("ptr")
|
||||
PollingComponent = esphome_ns.class_("PollingComponent", Component)
|
||||
Application = esphome_ns.class_("Application")
|
||||
# Create optional with explicit namespace to avoid ambiguity with std::optional
|
||||
# The generated code will use esphome::optional instead of just optional
|
||||
optional = global_ns.namespace("esphome").class_("optional")
|
||||
optional = global_ns.namespace("std").class_("optional")
|
||||
arduino_json_ns = global_ns.namespace("ArduinoJson")
|
||||
JsonObject = arduino_json_ns.class_("JsonObject")
|
||||
JsonObjectConst = arduino_json_ns.class_("JsonObjectConst")
|
||||
|
||||
@@ -66,5 +66,20 @@ def test_text_config_lamda_is_set(generate_main):
|
||||
main_cpp = generate_main("tests/component_tests/text/test_text.yaml")
|
||||
|
||||
# Then
|
||||
assert "it_4->set_template([]() -> esphome::optional<std::string> {" in main_cpp
|
||||
assert "it_4->set_template([]() -> std::optional<std::string> {" in main_cpp
|
||||
assert 'return std::string{"Hello"};' in main_cpp
|
||||
|
||||
|
||||
def test_esphome_optional_alias_works(generate_main):
|
||||
"""
|
||||
Test that esphome::optional alias compiles (backward compatibility)
|
||||
"""
|
||||
# Given
|
||||
|
||||
# When
|
||||
main_cpp = generate_main("tests/component_tests/text/test_text.yaml")
|
||||
|
||||
# Then
|
||||
# Codegen emits std::optional, but esphome::optional must also work
|
||||
# via the using alias in esphome/core/optional.h
|
||||
assert "std::optional<std::string>" in main_cpp
|
||||
|
||||
@@ -28,9 +28,14 @@ esphome:
|
||||
# Test C++ API: set_template() with stateless lambda (no captures)
|
||||
# NOTE: set_template() is not intended to be a public API, but we test it to ensure it doesn't break.
|
||||
- lambda: |-
|
||||
id(template_sens).set_template([]() -> esphome::optional<float> {
|
||||
id(template_sens).set_template([]() -> std::optional<float> {
|
||||
return 123.0f;
|
||||
});
|
||||
# Test that esphome::optional alias still works for backward compatibility
|
||||
- lambda: |-
|
||||
id(template_sens).set_template([]() -> esphome::optional<float> {
|
||||
return 42.0f;
|
||||
});
|
||||
|
||||
- datetime.date.set:
|
||||
id: test_date
|
||||
|
||||
Reference in New Issue
Block a user