mirror of
https://github.com/esphome/esphome.git
synced 2026-09-17 18:18:43 +00:00
Merge branch 'mopeka_stack_format' into integration
This commit is contained in:
@@ -88,6 +88,77 @@ SYMBOL_PATTERNS = {
|
||||
"sys_mbox_new",
|
||||
"sys_arch_mbox_tryfetch",
|
||||
],
|
||||
# LibreTiny/Beken BK7231 radio calibration
|
||||
"bk_radio_cal": [
|
||||
"bk7011_",
|
||||
"calibration_main",
|
||||
"gcali_",
|
||||
"rwnx_cal",
|
||||
],
|
||||
# LibreTiny/Beken WiFi MAC layer
|
||||
"bk_wifi_mac": [
|
||||
"rxu_", # RX upper layer
|
||||
"txu_", # TX upper layer
|
||||
"txl_", # TX lower layer
|
||||
"rxl_", # RX lower layer
|
||||
"scanu_", # Scan unit
|
||||
"mm_hw_", # MAC management hardware
|
||||
"mm_bcn", # MAC management beacon
|
||||
"mm_tim", # MAC management TIM
|
||||
"mm_check", # MAC management checks
|
||||
"sm_connect", # Station management
|
||||
"me_beacon", # Management entity beacon
|
||||
"me_build", # Management entity build
|
||||
"hapd_", # Host AP daemon
|
||||
"chan_pre_", # Channel management
|
||||
"handle_probe_", # Probe handling
|
||||
],
|
||||
# LibreTiny/Beken system control
|
||||
"bk_system": [
|
||||
"sctrl_", # System control
|
||||
"icu_ctrl", # Interrupt control unit
|
||||
"gdma_ctrl", # DMA control
|
||||
"mpb_ctrl", # MPB control
|
||||
"uf2_", # UF2 OTA
|
||||
"bkreg_", # Beken registers
|
||||
],
|
||||
# LibreTiny/Beken BLE stack
|
||||
"bk_ble": [
|
||||
"gapc_", # GAP client
|
||||
"gattc_", # GATT client
|
||||
"attc_", # ATT client
|
||||
"attmdb_", # ATT database
|
||||
"atts_", # ATT server
|
||||
"l2cc_", # L2CAP
|
||||
"prf_env", # Profile environment
|
||||
],
|
||||
# LibreTiny/Beken scheduler
|
||||
"bk_scheduler": [
|
||||
"sch_plan_", # Scheduler plan
|
||||
"sch_prog_", # Scheduler program
|
||||
"sch_arb_", # Scheduler arbiter
|
||||
],
|
||||
# LibreTiny/Beken DMA descriptors
|
||||
"bk_dma": [
|
||||
"rx_payload_desc",
|
||||
"rx_dma_hdrdesc",
|
||||
"tx_hw_desc",
|
||||
"host_event_data",
|
||||
"host_cmd_data",
|
||||
],
|
||||
# ARM EABI compiler runtime (LibreTiny uses ARM Cortex-M)
|
||||
"arm_runtime": [
|
||||
"__aeabi_",
|
||||
"__adddf3",
|
||||
"__subdf3",
|
||||
"__muldf3",
|
||||
"__divdf3",
|
||||
"__addsf3",
|
||||
"__subsf3",
|
||||
"__mulsf3",
|
||||
"__divsf3",
|
||||
"__gnu_unwind",
|
||||
],
|
||||
"xtensa": ["xt_", "_xt_", "xPortEnterCriticalTimeout"],
|
||||
"heap": ["heap_", "multi_heap"],
|
||||
"spi_flash": ["spi_flash"],
|
||||
@@ -782,7 +853,22 @@ SYMBOL_PATTERNS = {
|
||||
"math_internal": ["__mdiff", "__lshift", "__mprec_tens", "quorem"],
|
||||
"character_class": ["__chclass"],
|
||||
"camellia": ["camellia_", "camellia_feistel"],
|
||||
"crypto_tables": ["FSb", "FSb2", "FSb3", "FSb4"],
|
||||
"crypto_tables": [
|
||||
"FSb",
|
||||
"FSb2",
|
||||
"FSb3",
|
||||
"FSb4",
|
||||
"Te0", # AES encryption table
|
||||
"Td0", # AES decryption table
|
||||
"crc32_table", # CRC32 lookup table
|
||||
"crc_tab", # CRC lookup table
|
||||
],
|
||||
"crypto_hash": [
|
||||
"SHA1Transform", # SHA1 hash function
|
||||
"MD5Transform", # MD5 hash function
|
||||
"SHA256",
|
||||
"SHA512",
|
||||
],
|
||||
"event_buffer": ["g_eb_list_desc", "eb_space"],
|
||||
"base_node": ["base_node_", "base_node_add_handler"],
|
||||
"file_descriptor": ["s_fd_table"],
|
||||
|
||||
@@ -15,10 +15,8 @@ namespace alpha3 {
|
||||
namespace espbt = esphome::esp32_ble_tracker;
|
||||
|
||||
static const espbt::ESPBTUUID ALPHA3_GENI_SERVICE_UUID = espbt::ESPBTUUID::from_uint16(0xfe5d);
|
||||
static const espbt::ESPBTUUID ALPHA3_GENI_CHARACTERISTIC_UUID =
|
||||
espbt::ESPBTUUID::from_raw({static_cast<char>(0xa9), 0x7b, static_cast<char>(0xb8), static_cast<char>(0x85), 0x0,
|
||||
0x1a, 0x28, static_cast<char>(0xaa), 0x2a, 0x43, 0x6e, 0x3, static_cast<char>(0xd1),
|
||||
static_cast<char>(0xff), static_cast<char>(0x9c), static_cast<char>(0x85)});
|
||||
static const espbt::ESPBTUUID ALPHA3_GENI_CHARACTERISTIC_UUID = espbt::ESPBTUUID::from_raw(
|
||||
{0xa9, 0x7b, 0xb8, 0x85, 0x00, 0x1a, 0x28, 0xaa, 0x2a, 0x43, 0x6e, 0x03, 0xd1, 0xff, 0x9c, 0x85});
|
||||
static const int16_t GENI_RESPONSE_HEADER_LENGTH = 13;
|
||||
static const size_t GENI_RESPONSE_TYPE_LENGTH = 8;
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ class ESPBTUUID {
|
||||
static ESPBTUUID from_raw(const char *data, size_t length);
|
||||
static ESPBTUUID from_raw(const char *data) { return from_raw(data, strlen(data)); }
|
||||
static ESPBTUUID from_raw(const std::string &data) { return from_raw(data.c_str(), data.length()); }
|
||||
static ESPBTUUID from_raw(std::initializer_list<char> data) { return from_raw(data.begin(), data.size()); }
|
||||
static ESPBTUUID from_raw(std::initializer_list<uint8_t> data) {
|
||||
return from_raw(reinterpret_cast<const char *>(data.begin()), data.size());
|
||||
}
|
||||
|
||||
static ESPBTUUID from_uuid(esp_bt_uuid_t uuid);
|
||||
|
||||
|
||||
@@ -62,7 +62,8 @@ bool MopekaListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
||||
const bool sync_button_pressed = (manu_data.data[3] & 0x80) != 0;
|
||||
|
||||
if (this->show_sensors_without_sync_ || sync_button_pressed) {
|
||||
ESP_LOGI(TAG, "MOPEKA STD (CC2540) SENSOR FOUND: %s", device.address_str().c_str());
|
||||
char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
|
||||
ESP_LOGI(TAG, "MOPEKA STD (CC2540) SENSOR FOUND: %s", device.address_str_to(addr_buf));
|
||||
}
|
||||
|
||||
// Is the device maybe a Mopeka Pro (NRF52) sensor.
|
||||
@@ -78,7 +79,8 @@ bool MopekaListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
||||
const bool sync_button_pressed = (manu_data.data[2] & 0x80) != 0;
|
||||
|
||||
if (this->show_sensors_without_sync_ || sync_button_pressed) {
|
||||
ESP_LOGI(TAG, "MOPEKA PRO (NRF52) SENSOR FOUND: %s", device.address_str().c_str());
|
||||
char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
|
||||
ESP_LOGI(TAG, "MOPEKA PRO (NRF52) SENSOR FOUND: %s", device.address_str_to(addr_buf));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ bool MopekaProCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_LOGVV(TAG, "parse_device(): MAC address %s found.", device.address_str().c_str());
|
||||
char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
|
||||
ESP_LOGVV(TAG, "parse_device(): MAC address %s found.", device.address_str_to(addr_buf));
|
||||
|
||||
const auto &manu_datas = device.get_manufacturer_datas();
|
||||
|
||||
|
||||
@@ -35,15 +35,17 @@ void MopekaStdCheck::dump_config() {
|
||||
* update the sensor state data.
|
||||
*/
|
||||
bool MopekaStdCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
|
||||
{
|
||||
// Validate address.
|
||||
if (device.address_uint64() != this->address_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_LOGVV(TAG, "parse_device(): MAC address %s found.", device.address_str().c_str());
|
||||
// Validate address.
|
||||
if (device.address_uint64() != this->address_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stack buffer for MAC address formatting - reused throughout function
|
||||
char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
|
||||
const char *addr_str = device.address_str_to(addr_buf);
|
||||
|
||||
ESP_LOGVV(TAG, "parse_device(): MAC address %s found.", addr_str);
|
||||
|
||||
{
|
||||
// Validate service uuid
|
||||
const auto &service_uuids = device.get_service_uuids();
|
||||
@@ -59,7 +61,7 @@ bool MopekaStdCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
||||
const auto &manu_datas = device.get_manufacturer_datas();
|
||||
|
||||
if (manu_datas.size() != 1) {
|
||||
ESP_LOGE(TAG, "[%s] Unexpected manu_datas size (%d)", device.address_str().c_str(), manu_datas.size());
|
||||
ESP_LOGE(TAG, "[%s] Unexpected manu_datas size (%d)", addr_str, manu_datas.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -68,11 +70,11 @@ bool MopekaStdCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
|
||||
char hex_buf[format_hex_pretty_size(MOPEKA_MAX_LOG_BYTES)];
|
||||
#endif
|
||||
ESP_LOGVV(TAG, "[%s] Manufacturer data: %s", device.address_str().c_str(),
|
||||
ESP_LOGVV(TAG, "[%s] Manufacturer data: %s", addr_str,
|
||||
format_hex_pretty_to(hex_buf, manu_data.data.data(), manu_data.data.size()));
|
||||
|
||||
if (manu_data.data.size() != MANUFACTURER_DATA_LENGTH) {
|
||||
ESP_LOGE(TAG, "[%s] Unexpected manu_data size (%d)", device.address_str().c_str(), manu_data.data.size());
|
||||
ESP_LOGE(TAG, "[%s] Unexpected manu_data size (%d)", addr_str, manu_data.data.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -82,21 +84,21 @@ bool MopekaStdCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
||||
const u_int8_t hardware_id = mopeka_data->data_1 & 0xCF;
|
||||
if (static_cast<SensorType>(hardware_id) != STANDARD && static_cast<SensorType>(hardware_id) != XL &&
|
||||
static_cast<SensorType>(hardware_id) != ETRAILER && static_cast<SensorType>(hardware_id) != STANDARD_ALT) {
|
||||
ESP_LOGE(TAG, "[%s] Unsupported Sensor Type (0x%X)", device.address_str().c_str(), hardware_id);
|
||||
ESP_LOGE(TAG, "[%s] Unsupported Sensor Type (0x%X)", addr_str, hardware_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_LOGVV(TAG, "[%s] Sensor slow update rate: %d", device.address_str().c_str(), mopeka_data->slow_update_rate);
|
||||
ESP_LOGVV(TAG, "[%s] Sensor sync pressed: %d", device.address_str().c_str(), mopeka_data->sync_pressed);
|
||||
ESP_LOGVV(TAG, "[%s] Sensor slow update rate: %d", addr_str, mopeka_data->slow_update_rate);
|
||||
ESP_LOGVV(TAG, "[%s] Sensor sync pressed: %d", addr_str, mopeka_data->sync_pressed);
|
||||
for (u_int8_t i = 0; i < 3; i++) {
|
||||
ESP_LOGVV(TAG, "[%s] %u. Sensor data %u time %u.", device.address_str().c_str(), (i * 4) + 1,
|
||||
mopeka_data->val[i].value_0, mopeka_data->val[i].time_0);
|
||||
ESP_LOGVV(TAG, "[%s] %u. Sensor data %u time %u.", device.address_str().c_str(), (i * 4) + 2,
|
||||
mopeka_data->val[i].value_1, mopeka_data->val[i].time_1);
|
||||
ESP_LOGVV(TAG, "[%s] %u. Sensor data %u time %u.", device.address_str().c_str(), (i * 4) + 3,
|
||||
mopeka_data->val[i].value_2, mopeka_data->val[i].time_2);
|
||||
ESP_LOGVV(TAG, "[%s] %u. Sensor data %u time %u.", device.address_str().c_str(), (i * 4) + 4,
|
||||
mopeka_data->val[i].value_3, mopeka_data->val[i].time_3);
|
||||
ESP_LOGVV(TAG, "[%s] %u. Sensor data %u time %u.", addr_str, (i * 4) + 1, mopeka_data->val[i].value_0,
|
||||
mopeka_data->val[i].time_0);
|
||||
ESP_LOGVV(TAG, "[%s] %u. Sensor data %u time %u.", addr_str, (i * 4) + 2, mopeka_data->val[i].value_1,
|
||||
mopeka_data->val[i].time_1);
|
||||
ESP_LOGVV(TAG, "[%s] %u. Sensor data %u time %u.", addr_str, (i * 4) + 3, mopeka_data->val[i].value_2,
|
||||
mopeka_data->val[i].time_2);
|
||||
ESP_LOGVV(TAG, "[%s] %u. Sensor data %u time %u.", addr_str, (i * 4) + 4, mopeka_data->val[i].value_3,
|
||||
mopeka_data->val[i].time_3);
|
||||
}
|
||||
|
||||
// Get battery level first
|
||||
@@ -163,12 +165,12 @@ bool MopekaStdCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "[%s] Found %u values with best data %u time %u.", device.address_str().c_str(),
|
||||
number_of_usable_values, best_value, best_time);
|
||||
ESP_LOGV(TAG, "[%s] Found %u values with best data %u time %u.", addr_str, number_of_usable_values, best_value,
|
||||
best_time);
|
||||
|
||||
if (number_of_usable_values < 1 || best_value < 2 || best_time < 2) {
|
||||
// At least two measurement values must be present.
|
||||
ESP_LOGW(TAG, "[%s] Poor read quality. Setting distance to 0.", device.address_str().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Poor read quality. Setting distance to 0.", addr_str);
|
||||
if (this->distance_ != nullptr) {
|
||||
this->distance_->publish_state(0);
|
||||
}
|
||||
@@ -177,7 +179,7 @@ bool MopekaStdCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
||||
}
|
||||
} else {
|
||||
float lpg_speed_of_sound = this->get_lpg_speed_of_sound_(temp_in_c);
|
||||
ESP_LOGV(TAG, "[%s] Speed of sound in current fluid %f m/s", device.address_str().c_str(), lpg_speed_of_sound);
|
||||
ESP_LOGV(TAG, "[%s] Speed of sound in current fluid %f m/s", addr_str, lpg_speed_of_sound);
|
||||
|
||||
uint32_t distance_value = lpg_speed_of_sound * best_time / 100.0f;
|
||||
|
||||
|
||||
@@ -163,6 +163,7 @@ bool WhirlpoolClimate::on_receive(remote_base::RemoteReceiveData data) {
|
||||
}
|
||||
|
||||
uint8_t remote_state[WHIRLPOOL_STATE_LENGTH] = {0};
|
||||
bool skip_footer = false;
|
||||
// Read all bytes.
|
||||
for (int i = 0; i < WHIRLPOOL_STATE_LENGTH; i++) {
|
||||
// Read bit
|
||||
@@ -170,6 +171,13 @@ bool WhirlpoolClimate::on_receive(remote_base::RemoteReceiveData data) {
|
||||
if (!data.expect_item(WHIRLPOOL_BIT_MARK, WHIRLPOOL_GAP))
|
||||
return false;
|
||||
}
|
||||
if (i == 14 && !data.is_valid()) {
|
||||
// Remote control only sent 14 bytes, nothing more to read, not even the footer
|
||||
ESP_LOGV(TAG, "Remote control only sent %d bytes", i);
|
||||
skip_footer = true;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (data.expect_item(WHIRLPOOL_BIT_MARK, WHIRLPOOL_ONE_SPACE)) {
|
||||
remote_state[i] |= 1 << j;
|
||||
@@ -183,7 +191,7 @@ bool WhirlpoolClimate::on_receive(remote_base::RemoteReceiveData data) {
|
||||
ESP_LOGVV(TAG, "Byte %d %02X", i, remote_state[i]);
|
||||
}
|
||||
// Validate footer
|
||||
if (!data.expect_mark(WHIRLPOOL_BIT_MARK)) {
|
||||
if (!data.expect_mark(WHIRLPOOL_BIT_MARK) && !skip_footer) {
|
||||
ESP_LOGV(TAG, "Footer fail");
|
||||
return false;
|
||||
}
|
||||
@@ -196,7 +204,7 @@ bool WhirlpoolClimate::on_receive(remote_base::RemoteReceiveData data) {
|
||||
for (uint8_t i = 14; i < 20; i++)
|
||||
checksum20 ^= remote_state[i];
|
||||
|
||||
if (checksum13 != remote_state[13] || checksum20 != remote_state[20]) {
|
||||
if (checksum13 != remote_state[13] || (!skip_footer && checksum20 != remote_state[20])) {
|
||||
ESP_LOGVV(TAG, "Checksum fail");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -92,18 +92,23 @@ def run_detailed_analysis(build_dir: str) -> dict | None:
|
||||
print(f"Build directory not found: {build_dir}", file=sys.stderr)
|
||||
return None
|
||||
|
||||
# Find firmware.elf
|
||||
# Find firmware.elf (or raw_firmware.elf for LibreTiny)
|
||||
elf_path = None
|
||||
for elf_candidate in [
|
||||
build_path / "firmware.elf",
|
||||
build_path / ".pioenvs" / build_path.name / "firmware.elf",
|
||||
# LibreTiny uses raw_firmware.elf
|
||||
build_path / "raw_firmware.elf",
|
||||
build_path / ".pioenvs" / build_path.name / "raw_firmware.elf",
|
||||
]:
|
||||
if elf_candidate.exists():
|
||||
elf_path = str(elf_candidate)
|
||||
break
|
||||
|
||||
if not elf_path:
|
||||
print(f"firmware.elf not found in {build_dir}", file=sys.stderr)
|
||||
print(
|
||||
f"firmware.elf/raw_firmware.elf not found in {build_dir}", file=sys.stderr
|
||||
)
|
||||
return None
|
||||
|
||||
# Find idedata.json - check multiple locations
|
||||
|
||||
@@ -89,6 +89,7 @@ class Platform(StrEnum):
|
||||
ESP32_C6_IDF = "esp32-c6-idf"
|
||||
ESP32_S2_IDF = "esp32-s2-idf"
|
||||
ESP32_S3_IDF = "esp32-s3-idf"
|
||||
BK72XX_ARD = "bk72xx-ard" # LibreTiny BK7231N
|
||||
|
||||
|
||||
# Memory impact analysis constants
|
||||
@@ -120,6 +121,7 @@ PLATFORM_SPECIFIC_COMPONENTS = frozenset(
|
||||
# fastest build times, most sensitive to code size changes
|
||||
# 3. ESP32 IDF - Primary ESP32 platform, most representative of modern ESPHome
|
||||
# 4-6. Other ESP32 variants - Less commonly used but still supported
|
||||
# 7. BK72XX - LibreTiny platform (good for detecting LibreTiny-specific changes)
|
||||
MEMORY_IMPACT_PLATFORM_PREFERENCE = [
|
||||
Platform.ESP32_C6_IDF, # ESP32-C6 IDF (newest, supports Thread/Zigbee)
|
||||
Platform.ESP8266_ARD, # ESP8266 Arduino (most memory constrained, fastest builds)
|
||||
@@ -127,6 +129,7 @@ MEMORY_IMPACT_PLATFORM_PREFERENCE = [
|
||||
Platform.ESP32_C3_IDF, # ESP32-C3 IDF
|
||||
Platform.ESP32_S2_IDF, # ESP32-S2 IDF
|
||||
Platform.ESP32_S3_IDF, # ESP32-S3 IDF
|
||||
Platform.BK72XX_ARD, # LibreTiny BK7231N
|
||||
]
|
||||
|
||||
|
||||
@@ -404,7 +407,7 @@ def _detect_platform_hint_from_filename(filename: str) -> Platform | None:
|
||||
- wifi_component_esp_idf.cpp, *_idf.h -> ESP32 IDF variants
|
||||
- wifi_component_esp8266.cpp, *_esp8266.h -> ESP8266_ARD
|
||||
- *_esp32*.cpp -> ESP32 IDF (generic)
|
||||
- *_libretiny.cpp, *_retiny.* -> LibreTiny (not in preference list)
|
||||
- *_libretiny.cpp, *_bk72*.* -> BK72XX (LibreTiny)
|
||||
- *_pico.cpp, *_rp2040.* -> RP2040 (not in preference list)
|
||||
|
||||
Args:
|
||||
@@ -438,10 +441,11 @@ def _detect_platform_hint_from_filename(filename: str) -> Platform | None:
|
||||
if "esp32" in filename_lower:
|
||||
return Platform.ESP32_IDF
|
||||
|
||||
# LibreTiny and RP2040 are not in MEMORY_IMPACT_PLATFORM_PREFERENCE
|
||||
# so we don't return them as hints
|
||||
# if "retiny" in filename_lower or "libretiny" in filename_lower:
|
||||
# return None # No specific LibreTiny platform preference
|
||||
# LibreTiny (via 'libretiny' pattern or BK72xx-specific files)
|
||||
if "libretiny" in filename_lower or "bk72" in filename_lower:
|
||||
return Platform.BK72XX_ARD
|
||||
|
||||
# RP2040 is not in MEMORY_IMPACT_PLATFORM_PREFERENCE
|
||||
# if "pico" in filename_lower or "rp2040" in filename_lower:
|
||||
# return None # No RP2040 platform preference
|
||||
|
||||
|
||||
Reference in New Issue
Block a user