Fix more unchecked optional access errors found by clang-tidy

Store optional results in local variables before checking
and dereferencing to satisfy bugprone-unchecked-optional-access.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
J. Nick Koston
2026-02-27 17:58:13 -10:00
co-authored by Claude Opus 4.6
parent 529293b5be
commit e535c51847
26 changed files with 118 additions and 115 deletions
+2 -2
View File
@@ -63,8 +63,8 @@ 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();
if (auto opt_pos = call.get_position(); opt_pos.has_value()) {
auto pos = *opt_pos;
if (this->invert_position_)
pos = 1 - pos;
+4 -4
View File
@@ -24,8 +24,8 @@ void Anova::loop() {
}
void Anova::control(const ClimateCall &call) {
if (call.get_mode().has_value()) {
ClimateMode mode = *call.get_mode();
if (auto val = call.get_mode(); val.has_value()) {
ClimateMode mode = *val;
AnovaPacket *pkt;
switch (mode) {
case climate::CLIMATE_MODE_OFF:
@@ -45,8 +45,8 @@ 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());
if (auto val = call.get_target_temperature(); val.has_value()) {
auto *pkt = this->codec_->get_set_target_temp_request(*val);
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);
@@ -45,17 +45,17 @@ void BangBangClimate::setup() {
}
void BangBangClimate::control(const climate::ClimateCall &call) {
if (call.get_mode().has_value()) {
this->mode = *call.get_mode();
if (auto val = call.get_mode(); val.has_value()) {
this->mode = *val;
}
if (call.get_target_temperature_low().has_value()) {
this->target_temperature_low = *call.get_target_temperature_low();
if (auto val = call.get_target_temperature_low(); val.has_value()) {
this->target_temperature_low = *val;
}
if (call.get_target_temperature_high().has_value()) {
this->target_temperature_high = *call.get_target_temperature_high();
if (auto val = call.get_target_temperature_high(); val.has_value()) {
this->target_temperature_high = *val;
}
if (call.get_preset().has_value()) {
this->change_away_(*call.get_preset() == climate::CLIMATE_PRESET_AWAY);
if (auto val = call.get_preset(); val.has_value()) {
this->change_away_(*val == climate::CLIMATE_PRESET_AWAY);
}
this->compute_state_();
@@ -96,8 +96,8 @@ void BedJetClimate::control(const ClimateCall &call) {
return;
}
if (call.get_mode().has_value()) {
ClimateMode mode = *call.get_mode();
if (auto val = call.get_mode(); val.has_value()) {
ClimateMode mode = *val;
bool button_result;
switch (mode) {
case CLIMATE_MODE_OFF:
@@ -125,8 +125,8 @@ void BedJetClimate::control(const ClimateCall &call) {
}
}
if (call.get_target_temperature().has_value()) {
auto target_temp = *call.get_target_temperature();
if (auto val = call.get_target_temperature(); val.has_value()) {
auto target_temp = *val;
auto result = this->parent_->set_target_temp(target_temp);
if (result) {
@@ -134,8 +134,8 @@ void BedJetClimate::control(const ClimateCall &call) {
}
}
if (call.get_preset().has_value()) {
ClimatePreset preset = *call.get_preset();
if (auto val = call.get_preset(); val.has_value()) {
ClimatePreset preset = *val;
bool result;
if (preset == CLIMATE_PRESET_BOOST) {
@@ -187,10 +187,10 @@ void BedJetClimate::control(const ClimateCall &call) {
}
}
if (call.get_fan_mode().has_value()) {
if (auto val = call.get_fan_mode(); val.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 = *val;
bool result;
if (fan_mode == CLIMATE_FAN_LOW) {
result = this->parent_->set_fan_speed(20);
+3 -3
View File
@@ -19,7 +19,7 @@ void BedJetFan::control(const fan::FanCall &call) {
}
bool did_change = false;
if (call.get_state().has_value() && this->state != *call.get_state()) {
if (auto val = call.get_state(); val.has_value() && this->state != *val) {
// Turning off is easy:
if (this->state && this->parent_->button_off()) {
this->state = false;
@@ -36,8 +36,8 @@ 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();
if (auto val = call.get_speed(); this->state && val.has_value()) {
auto speed = *val;
if (speed >= 1) {
this->speed = speed;
// Fan.speed is 1-20, but Bedjet expects 0-19, so subtract 1
+6 -6
View File
@@ -18,12 +18,12 @@ 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();
if (auto val = call.get_state(); val.has_value())
this->state = *val;
if (auto val = call.get_oscillating(); val.has_value())
this->oscillating = *val;
if (auto val = call.get_direction(); val.has_value())
this->direction = *val;
this->write_state_();
this->publish_state();
+8 -8
View File
@@ -71,16 +71,16 @@ 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 (auto val = call.get_mode(); val.has_value())
this->mode = *val;
if (auto val = call.get_target_temperature(); val.has_value())
this->target_temperature = *val;
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();
this->fan_mode = call.get_fan_mode();
if (auto val = call.get_swing_mode(); val.has_value())
this->swing_mode = *val;
if (call.get_preset().has_value())
this->preset = *call.get_preset();
this->preset = call.get_preset();
this->transmit_state();
this->publish_state();
}
+6 -6
View File
@@ -38,12 +38,12 @@ 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());
if (auto val = call.get_tilt(); val.has_value())
call2.set_tilt(*val);
if (auto val = call.get_position(); val.has_value())
call2.set_position(*val);
if (auto val = call.get_tilt(); val.has_value())
call2.set_tilt(*val);
call2.perform();
}
+8 -8
View File
@@ -45,14 +45,14 @@ 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());
if (auto val = call.get_state(); val.has_value())
call2.set_state(*val);
if (auto val = call.get_oscillating(); val.has_value())
call2.set_oscillating(*val);
if (auto val = call.get_speed(); val.has_value())
call2.set_speed(*val);
if (auto val = call.get_direction(); val.has_value())
call2.set_direction(*val);
if (call.has_preset_mode())
call2.set_preset_mode(call.get_preset_mode());
call2.perform();
@@ -11,8 +11,8 @@ void CopySelect::setup() {
traits.set_options(source_->traits.get_options());
if (source_->has_state())
this->publish_state(source_->active_index().value());
if (auto idx = this->source_->active_index(); idx.has_value())
this->publish_state(*idx);
}
void CopySelect::dump_config() { LOG_SELECT("", "Copy Select", this); }
@@ -37,8 +37,8 @@ void CurrentBasedCover::control(const CoverCall &call) {
}
}
}
if (call.get_position().has_value()) {
auto pos = *call.get_position();
if (auto opt_pos = call.get_position(); opt_pos.has_value()) {
auto pos = *opt_pos;
if (fabsf(this->position - pos) < 0.01) {
// already at target
} else {
+2 -2
View File
@@ -485,8 +485,8 @@ 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();
if (auto val = call.get_target_humidity(); val.has_value()) {
this->target_humidity = *val;
}
climate_ir::ClimateIR::control(call);
}
+2 -2
View File
@@ -37,8 +37,8 @@ void EndstopCover::control(const CoverCall &call) {
}
}
}
if (call.get_position().has_value()) {
auto pos = *call.get_position();
if (auto opt_pos = call.get_position(); opt_pos.has_value()) {
auto pos = *opt_pos;
if (pos == this->position) {
// already at target
} else {
@@ -162,7 +162,7 @@ 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_) {
if (this->max_refresh_rate_.value_or(0) != 0 && (now - this->last_refresh_) < this->max_refresh_rate_.value_or(0)) {
// try again next loop iteration, so that this change won't get lost
this->schedule_show();
return;
@@ -301,7 +301,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,9 @@ void FeedbackCover::control(const CoverCall &call) {
this->start_direction_(COVER_OPERATION_CLOSING);
}
}
} else if (call.get_position().has_value()) {
} else if (auto pos_opt = call.get_position(); pos_opt.has_value()) {
// go to position action
auto pos = *call.get_position();
auto pos = *pos_opt;
if (pos == this->position) {
// already at target,
+5 -4
View File
@@ -1303,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];
@@ -1317,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,
@@ -1345,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;
@@ -49,14 +49,14 @@ 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();
if (auto val = call.get_state(); val.has_value())
this->state = *val;
if (auto val = call.get_speed(); val.has_value())
this->speed = *val;
if (auto val = call.get_oscillating(); val.has_value())
this->oscillating = *val;
if (auto val = call.get_direction(); val.has_value())
this->direction = *val;
this->apply_preset_mode_(call);
this->write_state_();
+2 -2
View File
@@ -171,9 +171,9 @@ void HE60rCover::control(const CoverCall &call) {
} else {
this->toggles_needed_++;
}
} else if (call.get_position().has_value()) {
} else if (auto pos_opt = call.get_position(); pos_opt.has_value()) {
// 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);
@@ -11,17 +11,16 @@ 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;
if (auto announcement = call.get_announcement(); 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();
if (auto media_url = call.get_media_url(); 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 +31,13 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) {
this->is_announcement_ = true;
}
if (call.get_volume().has_value()) {
this->volume = call.get_volume().value();
if (auto vol = call.get_volume(); vol.has_value()) {
this->volume = *vol;
this->set_volume_(volume);
this->unmute_();
}
if (call.get_command().has_value()) {
switch (call.get_command().value()) {
if (auto cmd = call.get_command(); cmd.has_value()) {
switch (*cmd) {
case media_player::MEDIA_PLAYER_COMMAND_MUTE:
this->mute_();
break;
@@ -67,7 +66,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();
+2 -2
View File
@@ -90,8 +90,8 @@ 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());
if (auto freq = call.get_carrier_frequency(); freq.has_value()) {
transmit_data->set_carrier_frequency(*freq);
}
// Set timings based on format
+2 -1
View File
@@ -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);
}
+2 -2
View File
@@ -19,8 +19,8 @@ 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);
if (auto init_val = this->reg_[i].initial_value; 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) {
+10 -10
View File
@@ -56,20 +56,20 @@ 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());
if (auto val = call.get_target_temperature(); val.has_value())
ctrl.targetTemp = *val;
if (auto val = call.get_swing_mode(); val.has_value())
ctrl.swingMode = Converters::to_midea_swing_mode(*val);
if (auto val = call.get_mode(); val.has_value())
ctrl.mode = Converters::to_midea_mode(*val);
if (auto val = call.get_preset(); val.has_value()) {
ctrl.preset = Converters::to_midea_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());
if (auto val = call.get_fan_mode(); val.has_value()) {
ctrl.fanMode = Converters::to_midea_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());
+8 -7
View File
@@ -114,14 +114,15 @@ 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))) {
} else if (auto swing = call.get_swing_mode();
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 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))) {
} else if (auto preset = call.get_preset();
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);
@@ -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");