mirror of
https://github.com/esphome/esphome.git
synced 2026-10-14 02:02:51 +00:00
[core] Add a name truncation helper and keep the MAC suffix in the nRF52 BLE name (#19768)
This commit is contained in:
@@ -350,19 +350,8 @@ bool ESP32BLE::ble_setup_() {
|
||||
}
|
||||
} else {
|
||||
const auto &app_name = App.get_name();
|
||||
size_t name_len = app_name.length();
|
||||
if (name_len > 20) {
|
||||
if (App.is_name_add_mac_suffix_enabled()) {
|
||||
// Keep first 13 chars and last 7 chars (MAC suffix), remove middle
|
||||
memcpy(name_buffer, app_name.c_str(), 13);
|
||||
memcpy(name_buffer + 13, app_name.c_str() + name_len - 7, 7);
|
||||
} else {
|
||||
memcpy(name_buffer, app_name.c_str(), 20);
|
||||
}
|
||||
name_buffer[20] = '\0';
|
||||
} else {
|
||||
memcpy(name_buffer, app_name.c_str(), name_len + 1); // Include null terminator
|
||||
}
|
||||
truncate_name_to(name_buffer, sizeof(name_buffer), app_name.c_str(), app_name.length(),
|
||||
App.is_name_add_mac_suffix_enabled() ? MAC_ADDRESS_SUFFIX_WITH_SEPARATOR_LEN : 0);
|
||||
device_name = name_buffer;
|
||||
}
|
||||
|
||||
|
||||
@@ -1048,30 +1048,17 @@ void WiFiComponent::setup_ap_config_() {
|
||||
return;
|
||||
|
||||
if (this->ap_.ssid_.empty()) {
|
||||
// Build AP SSID from app name without heap allocation
|
||||
// WiFi SSID max is 32 bytes, with MAC suffix we keep first 25 + last 7
|
||||
// Build AP SSID from app name without heap allocation; WiFi SSID max is 32 bytes
|
||||
static constexpr size_t AP_SSID_MAX_LEN = 32;
|
||||
static constexpr size_t AP_SSID_PREFIX_LEN = 25;
|
||||
static constexpr size_t AP_SSID_SUFFIX_LEN = 7;
|
||||
|
||||
const auto &app_name = App.get_name();
|
||||
const char *name_ptr = app_name.c_str();
|
||||
size_t name_len = app_name.length();
|
||||
|
||||
if (name_len <= AP_SSID_MAX_LEN) {
|
||||
if (app_name.length() <= AP_SSID_MAX_LEN) {
|
||||
// Name fits, use directly
|
||||
this->ap_.set_ssid(name_ptr);
|
||||
this->ap_.set_ssid(app_name.c_str());
|
||||
} else {
|
||||
// Name too long, need to truncate into stack buffer
|
||||
char ssid_buf[AP_SSID_MAX_LEN + 1];
|
||||
if (App.is_name_add_mac_suffix_enabled()) {
|
||||
// Keep first 25 chars and last 7 chars (MAC suffix), remove middle
|
||||
memcpy(ssid_buf, name_ptr, AP_SSID_PREFIX_LEN);
|
||||
memcpy(ssid_buf + AP_SSID_PREFIX_LEN, name_ptr + name_len - AP_SSID_SUFFIX_LEN, AP_SSID_SUFFIX_LEN);
|
||||
} else {
|
||||
memcpy(ssid_buf, name_ptr, AP_SSID_MAX_LEN);
|
||||
}
|
||||
ssid_buf[AP_SSID_MAX_LEN] = '\0';
|
||||
truncate_name_to(ssid_buf, sizeof(ssid_buf), app_name.c_str(), app_name.length(),
|
||||
App.is_name_add_mac_suffix_enabled() ? MAC_ADDRESS_SUFFIX_WITH_SEPARATOR_LEN : 0);
|
||||
this->ap_.set_ssid(ssid_buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifdef USE_ZEPHYR
|
||||
#include "ble_server.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/settings/settings.h>
|
||||
@@ -13,13 +15,8 @@ static k_work advertise_work; // NOLINT(cppcoreguidelines-avoid-non-const-globa
|
||||
|
||||
BLEServer *global_ble_server; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
|
||||
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
|
||||
|
||||
static const bt_data AD[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
|
||||
};
|
||||
// What the advertisement has left for the name: the flags take 3 bytes and the name header 2
|
||||
static constexpr size_t MAX_ADV_NAME_LEN = BT_GAP_ADV_MAX_ADV_DATA_LEN - 3 - 2;
|
||||
|
||||
static const bt_data SD[] = {
|
||||
#ifdef USE_OTA
|
||||
@@ -36,7 +33,19 @@ static void advertise(k_work *work) {
|
||||
ESP_LOGE(TAG, "Advertising failed to stop (rc %d)", rc);
|
||||
}
|
||||
|
||||
rc = bt_le_adv_start(ADV_PARAM, AD, ARRAY_SIZE(AD), SD, ARRAY_SIZE(SD));
|
||||
// Zephyr would cut the end of a long name, which is where the MAC suffix is
|
||||
char name[MAX_ADV_NAME_LEN + 1];
|
||||
const auto &app_name = App.get_name();
|
||||
const size_t name_len =
|
||||
truncate_name_to(name, sizeof(name), app_name.c_str(), app_name.length(),
|
||||
App.is_name_add_mac_suffix_enabled() ? MAC_ADDRESS_SUFFIX_WITH_SEPARATOR_LEN : 0);
|
||||
const uint8_t name_type = name_len < app_name.length() ? BT_DATA_NAME_SHORTENED : BT_DATA_NAME_COMPLETE;
|
||||
const bt_data ad[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||
BT_DATA(name_type, name, static_cast<uint8_t>(name_len)),
|
||||
};
|
||||
|
||||
rc = bt_le_adv_start(ADV_PARAM, ad, ARRAY_SIZE(ad), SD, ARRAY_SIZE(SD));
|
||||
if (rc) {
|
||||
ESP_LOGE(TAG, "Advertising failed to start (rc %d)", rc);
|
||||
return;
|
||||
|
||||
@@ -293,6 +293,26 @@ size_t make_name_with_suffix_to(char *buffer, size_t buffer_size, const char *na
|
||||
return total_len;
|
||||
}
|
||||
|
||||
size_t truncate_name_to(char *buffer, size_t buffer_size, const char *name, size_t name_len, size_t keep_suffix_len) {
|
||||
if (buffer_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
const size_t max_len = buffer_size - 1;
|
||||
if (name_len <= max_len) {
|
||||
memcpy(buffer, name, name_len);
|
||||
buffer[name_len] = '\0';
|
||||
return name_len;
|
||||
}
|
||||
if (keep_suffix_len > max_len) {
|
||||
keep_suffix_len = max_len;
|
||||
}
|
||||
const size_t head_len = max_len - keep_suffix_len;
|
||||
memcpy(buffer, name, head_len);
|
||||
memcpy(buffer + head_len, name + name_len - keep_suffix_len, keep_suffix_len);
|
||||
buffer[max_len] = '\0';
|
||||
return max_len;
|
||||
}
|
||||
|
||||
// Parsing & formatting
|
||||
|
||||
size_t parse_hex(const char *str, size_t length, uint8_t *data, size_t count) {
|
||||
|
||||
@@ -1256,6 +1256,16 @@ static constexpr size_t MAX_NAME_WITH_SUFFIX_SIZE = 128;
|
||||
size_t make_name_with_suffix_to(char *buffer, size_t buffer_size, const char *name, size_t name_len, char sep,
|
||||
const char *suffix_ptr, size_t suffix_len);
|
||||
|
||||
/// Length of the suffix name_add_mac_suffix appends: "-" plus 6 characters of the MAC address
|
||||
static constexpr size_t MAC_ADDRESS_SUFFIX_WITH_SEPARATOR_LEN = 7;
|
||||
|
||||
/// Copy a name into a buffer, cutting it when it does not fit.
|
||||
/// A name that is cut keeps its last keep_suffix_len characters (for example a MAC suffix) and loses
|
||||
/// the middle instead; pass 0 to cut the end.
|
||||
/// @param buffer Output buffer; holds at most buffer_size - 1 characters plus the null terminator
|
||||
/// @return Length written (excluding null terminator)
|
||||
size_t truncate_name_to(char *buffer, size_t buffer_size, const char *name, size_t name_len, size_t keep_suffix_len);
|
||||
|
||||
///@}
|
||||
|
||||
/// @name Parsing & formatting
|
||||
|
||||
@@ -7,6 +7,47 @@
|
||||
|
||||
namespace esphome::core::testing {
|
||||
|
||||
// --- truncate_name_to() ---
|
||||
|
||||
TEST(TruncateNameTo, NameThatFitsIsCopied) {
|
||||
char buffer[21];
|
||||
EXPECT_EQ(truncate_name_to(buffer, sizeof(buffer), "kitchen", 7, 7), 7u);
|
||||
EXPECT_STREQ(buffer, "kitchen");
|
||||
}
|
||||
|
||||
TEST(TruncateNameTo, NameOfExactlyTheLimitIsCopied) {
|
||||
char buffer[8];
|
||||
EXPECT_EQ(truncate_name_to(buffer, sizeof(buffer), "kitchen", 7, 0), 7u);
|
||||
EXPECT_STREQ(buffer, "kitchen");
|
||||
}
|
||||
|
||||
TEST(TruncateNameTo, CutsTheEndWithoutASuffix) {
|
||||
char buffer[21];
|
||||
const char *name = "a-very-long-device-name-here";
|
||||
EXPECT_EQ(truncate_name_to(buffer, sizeof(buffer), name, strlen(name), 0), 20u);
|
||||
EXPECT_STREQ(buffer, "a-very-long-device-n");
|
||||
}
|
||||
|
||||
TEST(TruncateNameTo, KeepsTheSuffixAndRemovesTheMiddle) {
|
||||
char buffer[21];
|
||||
const char *name = "a-very-long-device-name-a1b2c3";
|
||||
EXPECT_EQ(truncate_name_to(buffer, sizeof(buffer), name, strlen(name), 7), 20u);
|
||||
EXPECT_STREQ(buffer, "a-very-long-d-a1b2c3");
|
||||
}
|
||||
|
||||
TEST(TruncateNameTo, SuffixLongerThanTheBufferIsCut) {
|
||||
char buffer[5];
|
||||
const char *name = "name-a1b2c3";
|
||||
EXPECT_EQ(truncate_name_to(buffer, sizeof(buffer), name, strlen(name), 7), 4u);
|
||||
EXPECT_STREQ(buffer, "b2c3");
|
||||
}
|
||||
|
||||
TEST(TruncateNameTo, ZeroBufferSize) {
|
||||
char buffer[1] = {'x'};
|
||||
EXPECT_EQ(truncate_name_to(buffer, 0, "name", 4, 0), 0u);
|
||||
EXPECT_EQ(buffer[0], 'x');
|
||||
}
|
||||
|
||||
// --- format_hex_to() ---
|
||||
|
||||
TEST(FormatHexTo, Basic) {
|
||||
|
||||
Reference in New Issue
Block a user