mirror of
https://github.com/esphome/esphome.git
synced 2026-02-08 00:31:58 +00:00
[esp32_ble] include sdkconfig.h before ESP-Hosted preprocessor guards (#13787)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,20 +10,11 @@
|
|||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
#ifdef USE_ESP32_BLE_ADVERTISING
|
#ifdef USE_ESP32_BLE_ADVERTISING
|
||||||
|
|
||||||
#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID
|
|
||||||
#include <esp_bt.h>
|
|
||||||
#endif
|
|
||||||
#include <esp_gap_ble_api.h>
|
#include <esp_gap_ble_api.h>
|
||||||
#include <esp_gatts_api.h>
|
#include <esp_gatts_api.h>
|
||||||
|
|
||||||
namespace esphome::esp32_ble {
|
namespace esphome::esp32_ble {
|
||||||
|
|
||||||
using raw_adv_data_t = struct {
|
|
||||||
uint8_t *data;
|
|
||||||
size_t length;
|
|
||||||
esp_power_level_t power_level;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ESPBTUUID;
|
class ESPBTUUID;
|
||||||
|
|
||||||
class BLEAdvertising {
|
class BLEAdvertising {
|
||||||
|
|||||||
@@ -53,8 +53,10 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
cv.Optional(CONF_MEASURED_POWER, default=-59): cv.int_range(
|
cv.Optional(CONF_MEASURED_POWER, default=-59): cv.int_range(
|
||||||
min=-128, max=0
|
min=-128, max=0
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_TX_POWER, default="3dBm"): cv.All(
|
cv.OnlyWithout(CONF_TX_POWER, "esp32_hosted", default="3dBm"): cv.All(
|
||||||
cv.decibel, cv.enum(esp32_ble.TX_POWER_LEVELS, int=True)
|
cv.conflicts_with_component("esp32_hosted"),
|
||||||
|
cv.decibel,
|
||||||
|
cv.enum(esp32_ble.TX_POWER_LEVELS, int=True),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA),
|
).extend(cv.COMPONENT_SCHEMA),
|
||||||
@@ -82,7 +84,10 @@ async def to_code(config):
|
|||||||
cg.add(var.set_min_interval(config[CONF_MIN_INTERVAL]))
|
cg.add(var.set_min_interval(config[CONF_MIN_INTERVAL]))
|
||||||
cg.add(var.set_max_interval(config[CONF_MAX_INTERVAL]))
|
cg.add(var.set_max_interval(config[CONF_MAX_INTERVAL]))
|
||||||
cg.add(var.set_measured_power(config[CONF_MEASURED_POWER]))
|
cg.add(var.set_measured_power(config[CONF_MEASURED_POWER]))
|
||||||
cg.add(var.set_tx_power(config[CONF_TX_POWER]))
|
|
||||||
|
# TX power control only available on native Bluetooth (not ESP-Hosted)
|
||||||
|
if CONF_TX_POWER in config:
|
||||||
|
cg.add(var.set_tx_power(config[CONF_TX_POWER]))
|
||||||
|
|
||||||
cg.add_define("USE_ESP32_BLE_ADVERTISING")
|
cg.add_define("USE_ESP32_BLE_ADVERTISING")
|
||||||
|
|
||||||
|
|||||||
@@ -36,11 +36,16 @@ void ESP32BLEBeacon::dump_config() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*bpos = '\0';
|
*bpos = '\0';
|
||||||
|
#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID
|
||||||
ESP_LOGCONFIG(TAG,
|
ESP_LOGCONFIG(TAG,
|
||||||
" UUID: %s, Major: %u, Minor: %u, Min Interval: %ums, Max Interval: %ums, Measured Power: %d"
|
" UUID: %s, Major: %u, Minor: %u, Min Interval: %ums, Max Interval: %ums, Measured Power: %d"
|
||||||
", TX Power: %ddBm",
|
", TX Power: %ddBm",
|
||||||
uuid, this->major_, this->minor_, this->min_interval_, this->max_interval_, this->measured_power_,
|
uuid, this->major_, this->minor_, this->min_interval_, this->max_interval_, this->measured_power_,
|
||||||
(this->tx_power_ * 3) - 12);
|
(this->tx_power_ * 3) - 12);
|
||||||
|
#else
|
||||||
|
ESP_LOGCONFIG(TAG, " UUID: %s, Major: %u, Minor: %u, Min Interval: %ums, Max Interval: %ums, Measured Power: %d",
|
||||||
|
uuid, this->major_, this->minor_, this->min_interval_, this->max_interval_, this->measured_power_);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
float ESP32BLEBeacon::get_setup_priority() const { return setup_priority::AFTER_BLUETOOTH; }
|
float ESP32BLEBeacon::get_setup_priority() const { return setup_priority::AFTER_BLUETOOTH; }
|
||||||
@@ -74,11 +79,14 @@ void ESP32BLEBeacon::on_advertise_() {
|
|||||||
ibeacon_adv_data.ibeacon_vendor.major = byteswap(this->major_);
|
ibeacon_adv_data.ibeacon_vendor.major = byteswap(this->major_);
|
||||||
ibeacon_adv_data.ibeacon_vendor.measured_power = static_cast<uint8_t>(this->measured_power_);
|
ibeacon_adv_data.ibeacon_vendor.measured_power = static_cast<uint8_t>(this->measured_power_);
|
||||||
|
|
||||||
|
esp_err_t err;
|
||||||
|
#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID
|
||||||
ESP_LOGD(TAG, "Setting BLE TX power");
|
ESP_LOGD(TAG, "Setting BLE TX power");
|
||||||
esp_err_t err = esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, this->tx_power_);
|
err = esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, this->tx_power_);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGW(TAG, "esp_ble_tx_power_set failed: %s", esp_err_to_name(err));
|
ESP_LOGW(TAG, "esp_ble_tx_power_set failed: %s", esp_err_to_name(err));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
err = esp_ble_gap_config_adv_data_raw((uint8_t *) &ibeacon_adv_data, sizeof(ibeacon_adv_data));
|
err = esp_ble_gap_config_adv_data_raw((uint8_t *) &ibeacon_adv_data, sizeof(ibeacon_adv_data));
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "esp_ble_gap_config_adv_data_raw failed: %s", esp_err_to_name(err));
|
ESP_LOGE(TAG, "esp_ble_gap_config_adv_data_raw failed: %s", esp_err_to_name(err));
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ class ESP32BLEBeacon : public Component, public GAPEventHandler, public Parented
|
|||||||
void set_min_interval(uint16_t val) { this->min_interval_ = val; }
|
void set_min_interval(uint16_t val) { this->min_interval_ = val; }
|
||||||
void set_max_interval(uint16_t val) { this->max_interval_ = val; }
|
void set_max_interval(uint16_t val) { this->max_interval_ = val; }
|
||||||
void set_measured_power(int8_t val) { this->measured_power_ = val; }
|
void set_measured_power(int8_t val) { this->measured_power_ = val; }
|
||||||
|
#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID
|
||||||
void set_tx_power(esp_power_level_t val) { this->tx_power_ = val; }
|
void set_tx_power(esp_power_level_t val) { this->tx_power_ = val; }
|
||||||
|
#endif
|
||||||
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override;
|
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -60,7 +62,9 @@ class ESP32BLEBeacon : public Component, public GAPEventHandler, public Parented
|
|||||||
uint16_t min_interval_{};
|
uint16_t min_interval_{};
|
||||||
uint16_t max_interval_{};
|
uint16_t max_interval_{};
|
||||||
int8_t measured_power_{};
|
int8_t measured_power_{};
|
||||||
|
#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID
|
||||||
esp_power_level_t tx_power_{};
|
esp_power_level_t tx_power_{};
|
||||||
|
#endif
|
||||||
esp_ble_adv_params_t ble_adv_params_;
|
esp_ble_adv_params_t ble_adv_params_;
|
||||||
bool advertising_{false};
|
bool advertising_{false};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1403,6 +1403,17 @@ def requires_component(comp):
|
|||||||
return validator
|
return validator
|
||||||
|
|
||||||
|
|
||||||
|
def conflicts_with_component(comp):
|
||||||
|
"""Validate that this option cannot be specified when the component `comp` is loaded."""
|
||||||
|
|
||||||
|
def validator(value):
|
||||||
|
if comp in CORE.loaded_integrations:
|
||||||
|
raise Invalid(f"This option is not compatible with component {comp}")
|
||||||
|
return value
|
||||||
|
|
||||||
|
return validator
|
||||||
|
|
||||||
|
|
||||||
uint8_t = int_range(min=0, max=255)
|
uint8_t = int_range(min=0, max=255)
|
||||||
uint16_t = int_range(min=0, max=65535)
|
uint16_t = int_range(min=0, max=65535)
|
||||||
uint32_t = int_range(min=0, max=4294967295)
|
uint32_t = int_range(min=0, max=4294967295)
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
"""
|
"""
|
||||||
Test schema.extend functionality in esphome.config_validation.
|
Test config_validation functionality in esphome.config_validation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from voluptuous import Invalid
|
||||||
|
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
|
from esphome.core import CORE
|
||||||
|
|
||||||
|
|
||||||
def test_config_extend() -> None:
|
def test_config_extend() -> None:
|
||||||
@@ -49,3 +53,37 @@ def test_config_extend() -> None:
|
|||||||
assert validated["key2"] == "initial_value2"
|
assert validated["key2"] == "initial_value2"
|
||||||
assert validated["extra_1"] == "value1"
|
assert validated["extra_1"] == "value1"
|
||||||
assert validated["extra_2"] == "value2"
|
assert validated["extra_2"] == "value2"
|
||||||
|
|
||||||
|
|
||||||
|
def test_requires_component_passes_when_loaded() -> None:
|
||||||
|
"""Test requires_component passes when the required component is loaded."""
|
||||||
|
CORE.loaded_integrations.update({"wifi", "logger"})
|
||||||
|
validator = cv.requires_component("wifi")
|
||||||
|
result = validator("test_value")
|
||||||
|
assert result == "test_value"
|
||||||
|
|
||||||
|
|
||||||
|
def test_requires_component_fails_when_not_loaded() -> None:
|
||||||
|
"""Test requires_component raises Invalid when the required component is not loaded."""
|
||||||
|
CORE.loaded_integrations.add("logger")
|
||||||
|
validator = cv.requires_component("wifi")
|
||||||
|
with pytest.raises(Invalid) as exc_info:
|
||||||
|
validator("test_value")
|
||||||
|
assert "requires component wifi" in str(exc_info.value)
|
||||||
|
|
||||||
|
|
||||||
|
def test_conflicts_with_component_passes_when_not_loaded() -> None:
|
||||||
|
"""Test conflicts_with_component passes when the conflicting component is not loaded."""
|
||||||
|
CORE.loaded_integrations.update({"wifi", "logger"})
|
||||||
|
validator = cv.conflicts_with_component("esp32_hosted")
|
||||||
|
result = validator("test_value")
|
||||||
|
assert result == "test_value"
|
||||||
|
|
||||||
|
|
||||||
|
def test_conflicts_with_component_fails_when_loaded() -> None:
|
||||||
|
"""Test conflicts_with_component raises Invalid when the conflicting component is loaded."""
|
||||||
|
CORE.loaded_integrations.update({"wifi", "esp32_hosted"})
|
||||||
|
validator = cv.conflicts_with_component("esp32_hosted")
|
||||||
|
with pytest.raises(Invalid) as exc_info:
|
||||||
|
validator("test_value")
|
||||||
|
assert "not compatible with component esp32_hosted" in str(exc_info.value)
|
||||||
|
|||||||
8
tests/components/esp32_ble/test.esp32-p4-idf.yaml
Normal file
8
tests/components/esp32_ble/test.esp32-p4-idf.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
packages:
|
||||||
|
ble: !include ../../test_build_components/common/ble/esp32-p4-idf.yaml
|
||||||
|
|
||||||
|
<<: !include common.yaml
|
||||||
|
|
||||||
|
esp32_ble:
|
||||||
|
io_capability: keyboard_only
|
||||||
|
disable_bt_logs: false
|
||||||
7
tests/components/esp32_ble_beacon/test.esp32-p4-idf.yaml
Normal file
7
tests/components/esp32_ble_beacon/test.esp32-p4-idf.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
packages:
|
||||||
|
ble: !include ../../test_build_components/common/ble/esp32-p4-idf.yaml
|
||||||
|
|
||||||
|
# tx_power is not supported on ESP-Hosted platforms
|
||||||
|
esp32_ble_beacon:
|
||||||
|
type: iBeacon
|
||||||
|
uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98'
|
||||||
6
tests/components/esp32_ble_client/test.esp32-p4-idf.yaml
Normal file
6
tests/components/esp32_ble_client/test.esp32-p4-idf.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
packages:
|
||||||
|
ble: !include ../../test_build_components/common/ble/esp32-p4-idf.yaml
|
||||||
|
|
||||||
|
ble_client:
|
||||||
|
- mac_address: 01:02:03:04:05:06
|
||||||
|
id: blec
|
||||||
4
tests/components/esp32_ble_server/test.esp32-p4-idf.yaml
Normal file
4
tests/components/esp32_ble_server/test.esp32-p4-idf.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
packages:
|
||||||
|
ble: !include ../../test_build_components/common/ble/esp32-p4-idf.yaml
|
||||||
|
|
||||||
|
<<: !include common.yaml
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
packages:
|
||||||
|
ble: !include ../../test_build_components/common/ble/esp32-p4-idf.yaml
|
||||||
|
|
||||||
|
<<: !include common.yaml
|
||||||
|
|
||||||
|
esp32_ble_tracker:
|
||||||
|
max_connections: 9
|
||||||
21
tests/test_build_components/common/ble/esp32-p4-idf.yaml
Normal file
21
tests/test_build_components/common/ble/esp32-p4-idf.yaml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Common BLE tracker configuration for ESP32-P4 IDF tests
|
||||||
|
# ESP32-P4 requires ESP-Hosted for Bluetooth via external coprocessor
|
||||||
|
# BLE client components share this tracker infrastructure
|
||||||
|
# Each component defines its own ble_client with unique MAC address
|
||||||
|
|
||||||
|
esp32_hosted:
|
||||||
|
active_high: true
|
||||||
|
variant: ESP32C6
|
||||||
|
reset_pin: GPIO54
|
||||||
|
cmd_pin: GPIO19
|
||||||
|
clk_pin: GPIO18
|
||||||
|
d0_pin: GPIO14
|
||||||
|
d1_pin: GPIO15
|
||||||
|
d2_pin: GPIO16
|
||||||
|
d3_pin: GPIO17
|
||||||
|
|
||||||
|
esp32_ble_tracker:
|
||||||
|
scan_parameters:
|
||||||
|
interval: 1100ms
|
||||||
|
window: 1100ms
|
||||||
|
active: true
|
||||||
Reference in New Issue
Block a user