mirror of
https://github.com/esphome/esphome.git
synced 2025-09-27 15:42:22 +01:00
Merge branch 'integration' into memory_api
This commit is contained in:
@@ -35,7 +35,7 @@ void Syslog::log_(const int level, const char *tag, const char *message, size_t
|
|||||||
severity = LOG_LEVEL_TO_SYSLOG_SEVERITY[level];
|
severity = LOG_LEVEL_TO_SYSLOG_SEVERITY[level];
|
||||||
}
|
}
|
||||||
int pri = this->facility_ * 8 + severity;
|
int pri = this->facility_ * 8 + severity;
|
||||||
auto timestamp = this->time_->now().strftime("%b %d %H:%M:%S");
|
auto timestamp = this->time_->now().strftime("%b %e %H:%M:%S");
|
||||||
size_t len = message_len;
|
size_t len = message_len;
|
||||||
// remove color formatting
|
// remove color formatting
|
||||||
if (this->strip_ && message[0] == 0x1B && len > 11) {
|
if (this->strip_ && message[0] == 0x1B && len > 11) {
|
||||||
|
@@ -505,6 +505,54 @@ void WiFiComponent::start_scanning() {
|
|||||||
this->state_ = WIFI_COMPONENT_STATE_STA_SCANNING;
|
this->state_ = WIFI_COMPONENT_STATE_STA_SCANNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function for WiFi scan result comparison
|
||||||
|
// Returns true if 'a' should be placed before 'b' in the sorted order
|
||||||
|
static bool wifi_scan_result_is_better(const WiFiScanResult &a, const WiFiScanResult &b) {
|
||||||
|
// Matching networks always come before non-matching
|
||||||
|
if (a.get_matches() && !b.get_matches())
|
||||||
|
return true;
|
||||||
|
if (!a.get_matches() && b.get_matches())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (a.get_matches() && b.get_matches()) {
|
||||||
|
// For APs with the same SSID, always prefer stronger signal
|
||||||
|
// This helps with mesh networks and multiple APs
|
||||||
|
if (a.get_ssid() == b.get_ssid()) {
|
||||||
|
return a.get_rssi() > b.get_rssi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// For different SSIDs, check priority first
|
||||||
|
if (a.get_priority() != b.get_priority())
|
||||||
|
return a.get_priority() > b.get_priority();
|
||||||
|
// If priorities are equal, prefer stronger signal
|
||||||
|
return a.get_rssi() > b.get_rssi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both don't match - sort by signal strength
|
||||||
|
return a.get_rssi() > b.get_rssi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function for insertion sort of WiFi scan results
|
||||||
|
// Using insertion sort instead of std::stable_sort saves flash memory
|
||||||
|
// by avoiding template instantiations (std::rotate, std::stable_sort, lambdas)
|
||||||
|
// IMPORTANT: This sort is stable (preserves relative order of equal elements)
|
||||||
|
static void insertion_sort_scan_results(std::vector<WiFiScanResult> &results) {
|
||||||
|
const size_t size = results.size();
|
||||||
|
for (size_t i = 1; i < size; i++) {
|
||||||
|
// Make a copy to avoid issues with move semantics during comparison
|
||||||
|
WiFiScanResult key = results[i];
|
||||||
|
int32_t j = i - 1;
|
||||||
|
|
||||||
|
// Move elements that are worse than key to the right
|
||||||
|
// For stability, we only move if key is strictly better than results[j]
|
||||||
|
while (j >= 0 && wifi_scan_result_is_better(key, results[j])) {
|
||||||
|
results[j + 1] = results[j];
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
results[j + 1] = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void WiFiComponent::check_scanning_finished() {
|
void WiFiComponent::check_scanning_finished() {
|
||||||
if (!this->scan_done_) {
|
if (!this->scan_done_) {
|
||||||
if (millis() - this->action_started_ > 30000) {
|
if (millis() - this->action_started_ > 30000) {
|
||||||
@@ -535,30 +583,8 @@ void WiFiComponent::check_scanning_finished() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stable_sort(this->scan_result_.begin(), this->scan_result_.end(),
|
// Sort scan results using insertion sort for better memory efficiency
|
||||||
[](const WiFiScanResult &a, const WiFiScanResult &b) {
|
insertion_sort_scan_results(this->scan_result_);
|
||||||
// return true if a is better than b
|
|
||||||
if (a.get_matches() && !b.get_matches())
|
|
||||||
return true;
|
|
||||||
if (!a.get_matches() && b.get_matches())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (a.get_matches() && b.get_matches()) {
|
|
||||||
// For APs with the same SSID, always prefer stronger signal
|
|
||||||
// This helps with mesh networks and multiple APs
|
|
||||||
if (a.get_ssid() == b.get_ssid()) {
|
|
||||||
return a.get_rssi() > b.get_rssi();
|
|
||||||
}
|
|
||||||
|
|
||||||
// For different SSIDs, check priority first
|
|
||||||
if (a.get_priority() != b.get_priority())
|
|
||||||
return a.get_priority() > b.get_priority();
|
|
||||||
// If priorities are equal, prefer stronger signal
|
|
||||||
return a.get_rssi() > b.get_rssi();
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.get_rssi() > b.get_rssi();
|
|
||||||
});
|
|
||||||
|
|
||||||
for (auto &res : this->scan_result_) {
|
for (auto &res : this->scan_result_) {
|
||||||
char bssid_s[18];
|
char bssid_s[18];
|
||||||
|
@@ -34,6 +34,44 @@ namespace esphome {
|
|||||||
|
|
||||||
static const char *const TAG = "app";
|
static const char *const TAG = "app";
|
||||||
|
|
||||||
|
// Helper function for insertion sort of components by setup priority
|
||||||
|
// Using insertion sort instead of std::stable_sort saves ~1.3KB of flash
|
||||||
|
// by avoiding template instantiations (std::rotate, std::stable_sort, lambdas)
|
||||||
|
// IMPORTANT: This sort is stable (preserves relative order of equal elements),
|
||||||
|
// which is necessary to maintain user-defined component order for same priority
|
||||||
|
static void insertion_sort_by_setup_priority(Component **components, size_t size) {
|
||||||
|
for (size_t i = 1; i < size; i++) {
|
||||||
|
Component *key = components[i];
|
||||||
|
float key_priority = key->get_actual_setup_priority();
|
||||||
|
int32_t j = i - 1;
|
||||||
|
|
||||||
|
// Using '<' (not '<=') ensures stability - equal priority components keep their order
|
||||||
|
while (j >= 0 && components[j]->get_actual_setup_priority() < key_priority) {
|
||||||
|
components[j + 1] = components[j];
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
components[j + 1] = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function for insertion sort of components by loop priority
|
||||||
|
// IMPORTANT: This sort is stable (preserves relative order of equal elements),
|
||||||
|
// which is required when components are re-sorted during setup() if they block
|
||||||
|
static void insertion_sort_by_loop_priority(Component **components, size_t size) {
|
||||||
|
for (size_t i = 1; i < size; i++) {
|
||||||
|
Component *key = components[i];
|
||||||
|
float key_priority = key->get_loop_priority();
|
||||||
|
int32_t j = i - 1;
|
||||||
|
|
||||||
|
// Using '<' (not '<=') ensures stability - equal priority components keep their order
|
||||||
|
while (j >= 0 && components[j]->get_loop_priority() < key_priority) {
|
||||||
|
components[j + 1] = components[j];
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
components[j + 1] = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Application::register_component_(Component *comp) {
|
void Application::register_component_(Component *comp) {
|
||||||
if (comp == nullptr) {
|
if (comp == nullptr) {
|
||||||
ESP_LOGW(TAG, "Tried to register null component!");
|
ESP_LOGW(TAG, "Tried to register null component!");
|
||||||
@@ -51,9 +89,9 @@ void Application::register_component_(Component *comp) {
|
|||||||
void Application::setup() {
|
void Application::setup() {
|
||||||
ESP_LOGI(TAG, "Running through setup()");
|
ESP_LOGI(TAG, "Running through setup()");
|
||||||
ESP_LOGV(TAG, "Sorting components by setup priority");
|
ESP_LOGV(TAG, "Sorting components by setup priority");
|
||||||
std::stable_sort(this->components_.begin(), this->components_.end(), [](const Component *a, const Component *b) {
|
|
||||||
return a->get_actual_setup_priority() > b->get_actual_setup_priority();
|
// Sort by setup priority using our helper function
|
||||||
});
|
insertion_sort_by_setup_priority(this->components_.data(), this->components_.size());
|
||||||
|
|
||||||
// Initialize looping_components_ early so enable_pending_loops_() works during setup
|
// Initialize looping_components_ early so enable_pending_loops_() works during setup
|
||||||
this->calculate_looping_components_();
|
this->calculate_looping_components_();
|
||||||
@@ -69,20 +107,8 @@ void Application::setup() {
|
|||||||
if (component->can_proceed())
|
if (component->can_proceed())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Using insertion sort instead of std::stable_sort saves ~1.3KB of flash
|
// Sort components 0 through i by loop priority
|
||||||
// by avoiding std::rotate, std::stable_sort, and lambda template instantiations.
|
insertion_sort_by_loop_priority(this->components_.data(), i + 1);
|
||||||
// Insertion sort is efficient for small arrays and maintains stability
|
|
||||||
for (int32_t j = 1; j <= static_cast<int32_t>(i); j++) {
|
|
||||||
Component *key = this->components_[j];
|
|
||||||
float key_priority = key->get_loop_priority();
|
|
||||||
int32_t k = j - 1;
|
|
||||||
|
|
||||||
while (k >= 0 && this->components_[k]->get_loop_priority() < key_priority) {
|
|
||||||
this->components_[k + 1] = this->components_[k];
|
|
||||||
k--;
|
|
||||||
}
|
|
||||||
this->components_[k + 1] = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
uint8_t new_app_state = STATUS_LED_WARNING;
|
uint8_t new_app_state = STATUS_LED_WARNING;
|
||||||
|
Reference in New Issue
Block a user