mirror of
https://github.com/esphome/esphome.git
synced 2025-09-01 10:52:19 +01:00
Merge branch 'fix_string_lifetime_fill_and_encode_entity_info' into integration
This commit is contained in:
@@ -303,11 +303,13 @@ class APIConnection final : public APIServerConnection {
|
||||
msg.key = entity->get_object_id_hash();
|
||||
// Try to use static reference first to avoid allocation
|
||||
StringRef static_ref = entity->get_object_id_ref_for_api_();
|
||||
// Store dynamic string outside the if-else to maintain lifetime
|
||||
std::string object_id;
|
||||
if (!static_ref.empty()) {
|
||||
msg.set_object_id(static_ref);
|
||||
} else {
|
||||
// Dynamic case - need to allocate
|
||||
std::string object_id = entity->get_object_id();
|
||||
object_id = entity->get_object_id();
|
||||
msg.set_object_id(StringRef(object_id));
|
||||
}
|
||||
|
||||
|
@@ -138,11 +138,37 @@ void Rtttl::stop() {
|
||||
this->set_state_(STATE_STOPPING);
|
||||
}
|
||||
#endif
|
||||
this->position_ = this->rtttl_.length();
|
||||
this->note_duration_ = 0;
|
||||
}
|
||||
|
||||
void Rtttl::finish_() {
|
||||
ESP_LOGV(TAG, "Rtttl::finish_()");
|
||||
#ifdef USE_OUTPUT
|
||||
if (this->output_ != nullptr) {
|
||||
this->output_->set_level(0.0);
|
||||
this->set_state_(State::STATE_STOPPED);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SPEAKER
|
||||
if (this->speaker_ != nullptr) {
|
||||
SpeakerSample sample[2];
|
||||
sample[0].left = 0;
|
||||
sample[0].right = 0;
|
||||
sample[1].left = 0;
|
||||
sample[1].right = 0;
|
||||
this->speaker_->play((uint8_t *) (&sample), 8);
|
||||
this->speaker_->finish();
|
||||
this->set_state_(State::STATE_STOPPING);
|
||||
}
|
||||
#endif
|
||||
// Ensure no more notes are played in case finish_() is called for an error.
|
||||
this->position_ = this->rtttl_.length();
|
||||
this->note_duration_ = 0;
|
||||
}
|
||||
|
||||
void Rtttl::loop() {
|
||||
if (this->note_duration_ == 0 || this->state_ == State::STATE_STOPPED) {
|
||||
if (this->state_ == State::STATE_STOPPED) {
|
||||
this->disable_loop();
|
||||
return;
|
||||
}
|
||||
@@ -152,6 +178,8 @@ void Rtttl::loop() {
|
||||
if (this->state_ == State::STATE_STOPPING) {
|
||||
if (this->speaker_->is_stopped()) {
|
||||
this->set_state_(State::STATE_STOPPED);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (this->state_ == State::STATE_INIT) {
|
||||
if (this->speaker_->is_stopped()) {
|
||||
@@ -207,7 +235,7 @@ void Rtttl::loop() {
|
||||
if (this->output_ != nullptr && millis() - this->last_note_ < this->note_duration_)
|
||||
return;
|
||||
#endif
|
||||
if (!this->rtttl_[this->position_]) {
|
||||
if (this->position_ >= this->rtttl_.length()) {
|
||||
this->finish_();
|
||||
return;
|
||||
}
|
||||
@@ -346,31 +374,6 @@ void Rtttl::loop() {
|
||||
this->last_note_ = millis();
|
||||
}
|
||||
|
||||
void Rtttl::finish_() {
|
||||
#ifdef USE_OUTPUT
|
||||
if (this->output_ != nullptr) {
|
||||
this->output_->set_level(0.0);
|
||||
this->set_state_(State::STATE_STOPPED);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SPEAKER
|
||||
if (this->speaker_ != nullptr) {
|
||||
SpeakerSample sample[2];
|
||||
sample[0].left = 0;
|
||||
sample[0].right = 0;
|
||||
sample[1].left = 0;
|
||||
sample[1].right = 0;
|
||||
this->speaker_->play((uint8_t *) (&sample), 8);
|
||||
|
||||
this->speaker_->finish();
|
||||
this->set_state_(State::STATE_STOPPING);
|
||||
}
|
||||
#endif
|
||||
this->note_duration_ = 0;
|
||||
this->on_finished_playback_callback_.call();
|
||||
ESP_LOGD(TAG, "Playback finished");
|
||||
}
|
||||
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG
|
||||
static const LogString *state_to_string(State state) {
|
||||
switch (state) {
|
||||
@@ -397,7 +400,11 @@ void Rtttl::set_state_(State state) {
|
||||
LOG_STR_ARG(state_to_string(state)));
|
||||
|
||||
// Clear loop_done when transitioning from STOPPED to any other state
|
||||
if (old_state == State::STATE_STOPPED && state != State::STATE_STOPPED) {
|
||||
if (state == State::STATE_STOPPED) {
|
||||
this->disable_loop();
|
||||
this->on_finished_playback_callback_.call();
|
||||
ESP_LOGD(TAG, "Playback finished");
|
||||
} else if (old_state == State::STATE_STOPPED) {
|
||||
this->enable_loop();
|
||||
}
|
||||
}
|
||||
|
@@ -60,35 +60,60 @@ class Rtttl : public Component {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief Finalizes the playback of the RTTTL string.
|
||||
*
|
||||
* This method is called internally when the end of the RTTTL string is reached
|
||||
* or when a parsing error occurs. It stops the output, sets the component state,
|
||||
* and triggers the on_finished_playback_callback_.
|
||||
*/
|
||||
void finish_();
|
||||
void set_state_(State state);
|
||||
|
||||
/// The RTTTL string to play.
|
||||
std::string rtttl_{""};
|
||||
/// The current position in the RTTTL string.
|
||||
size_t position_{0};
|
||||
/// The duration of a whole note in milliseconds.
|
||||
uint16_t wholenote_;
|
||||
/// The default duration of a note (e.g. 4 for a quarter note).
|
||||
uint16_t default_duration_;
|
||||
/// The default octave for a note.
|
||||
uint16_t default_octave_;
|
||||
/// The time the last note was started.
|
||||
uint32_t last_note_;
|
||||
/// The duration of the current note in milliseconds.
|
||||
uint16_t note_duration_;
|
||||
|
||||
/// The frequency of the current note in Hz.
|
||||
uint32_t output_freq_;
|
||||
/// The gain of the output.
|
||||
float gain_{0.6f};
|
||||
/// The current state of the RTTTL player.
|
||||
State state_{State::STATE_STOPPED};
|
||||
|
||||
#ifdef USE_OUTPUT
|
||||
/// The output to write the sound to.
|
||||
output::FloatOutput *output_;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SPEAKER
|
||||
/// The speaker to write the sound to.
|
||||
speaker::Speaker *speaker_{nullptr};
|
||||
/// The sample rate of the speaker.
|
||||
int sample_rate_{16000};
|
||||
/// The number of samples for one full cycle of a note's waveform, in Q10 fixed-point format.
|
||||
int samples_per_wave_{0};
|
||||
/// The number of samples sent.
|
||||
int samples_sent_{0};
|
||||
/// The total number of samples to send.
|
||||
int samples_count_{0};
|
||||
/// The number of samples for the gap between notes.
|
||||
int samples_gap_{0};
|
||||
|
||||
#endif
|
||||
|
||||
/// The callback to call when playback is finished.
|
||||
CallbackManager<void()> on_finished_playback_callback_;
|
||||
};
|
||||
|
||||
|
@@ -151,6 +151,8 @@ void WiFiComponent::loop() {
|
||||
this->status_set_warning("waiting to reconnect");
|
||||
if (millis() - this->action_started_ > 5000) {
|
||||
if (this->fast_connect_ || this->retry_hidden_) {
|
||||
if (!this->selected_ap_.get_bssid().has_value())
|
||||
this->selected_ap_ = this->sta_[0];
|
||||
this->start_connecting(this->selected_ap_, false);
|
||||
} else {
|
||||
this->start_scanning();
|
||||
@@ -670,10 +672,12 @@ void WiFiComponent::check_connecting_finished() {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Connected");
|
||||
// We won't retry hidden networks unless a reconnect fails more than three times again
|
||||
if (this->retry_hidden_ && !this->selected_ap_.get_hidden())
|
||||
ESP_LOGW(TAG, "Network '%s' should be marked as hidden", this->selected_ap_.get_ssid().c_str());
|
||||
this->retry_hidden_ = false;
|
||||
|
||||
ESP_LOGI(TAG, "Connected");
|
||||
this->print_connect_params_();
|
||||
|
||||
if (this->has_ap()) {
|
||||
|
Reference in New Issue
Block a user