[improv_ble] Rename from esp32_improv and decouple from ESP32 (#19264)

This commit is contained in:
Jesse Hills
2026-09-16 20:49:56 +12:00
committed by GitHub
parent 9b21b64836
commit 4c7aee1a77
33 changed files with 303 additions and 140 deletions
@@ -9,5 +9,5 @@ wifi:
password: password1
# esp32_ble_server is only auto-loaded here, so it has no services of its own.
esp32_improv:
improv_ble:
authorizer: none
@@ -55,7 +55,7 @@ def test_uuid_is_matches_descriptor_short_strings(uuid16) -> None:
@pytest.mark.parametrize(
("config_file", "required"),
[
# Auto-loaded by esp32_improv only: nothing to find until Improv asks for it
# Auto-loaded by improv_ble only: nothing to find until Improv asks for it
("improv_only.yaml", False),
# The configuration defines a service clients are meant to connect to
("own_service.yaml", True),
@@ -0,0 +1,31 @@
esphome:
name: improv-ble-automations
esp32:
variant: esp32
framework:
type: esp-idf
logger:
wifi:
ssid: MySSID
password: password1
binary_sensor:
- platform: gpio
pin: 0
id: io0_button
output:
- platform: gpio
pin: 2
id: built_in_led
improv_ble:
authorizer: io0_button
status_indicator: built_in_led
on_provisioned:
- logger.log: provisioned
on_provisioning:
- logger.log: provisioning
on_start:
- logger.log: start
on_state:
- logger.log: state
on_stop:
- logger.log: stop
@@ -0,0 +1,12 @@
esphome:
name: improv-ble-esp32
esp32:
variant: esp32
framework:
type: esp-idf
logger:
wifi:
ssid: MySSID
password: password1
improv_ble:
authorizer: none
@@ -0,0 +1,10 @@
esphome:
name: improv-ble-esp8266
esp8266:
board: nodemcuv2
logger:
wifi:
ssid: MySSID
password: password1
improv_ble:
authorizer: none
@@ -0,0 +1,12 @@
esphome:
name: improv-ble-legacy-key
esp32:
variant: esp32
framework:
type: esp-idf
logger:
wifi:
ssid: MySSID
password: password1
esp32_improv:
authorizer: none
@@ -0,0 +1,59 @@
"""improv_ble is platform neutral; only its BLE server backends are not.
Covers the platform gate (BLE_SERVER_BACKENDS) and the esp32_improv alias that
keeps pre-rename configurations working.
"""
from collections.abc import Callable
from pathlib import Path
import pytest
from esphome.config import read_config
from esphome.core import CORE
def test_esp32_generates_component(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
main_cpp = generate_main(component_config_path("esp32.yaml"))
assert "improv_ble::ImprovBLEComponent" in main_cpp
def test_legacy_key_routes_to_improv_ble(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
caplog: pytest.LogCaptureFixture,
) -> None:
main_cpp = generate_main(component_config_path("legacy_key.yaml"))
assert "improv_ble::ImprovBLEComponent" in main_cpp
assert "'esp32_improv:' top-level key is deprecated" in caplog.text
def test_platform_without_ble_server_rejected(
component_config_path: Callable[[str], Path],
capsys: pytest.CaptureFixture[str],
) -> None:
# AUTO_LOAD finds no backend for esp8266 and pulls in improv_base only, so
# the platform gate in CONFIG_SCHEMA is what has to reject the config.
CORE.config_path = component_config_path("esp8266.yaml")
assert read_config({}) is None
assert "only available on" in capsys.readouterr().out
def test_automations_emit_renamed_triggers(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
main_cpp = generate_main(component_config_path("automations.yaml"))
for trigger in (
"ImprovBLEProvisionedTrigger",
"ImprovBLEProvisioningTrigger",
"ImprovBLEStartTrigger",
"ImprovBLEStateTrigger",
"ImprovBLEStoppedTrigger",
):
assert f"improv_ble::{trigger}" in main_cpp
assert "set_authorizer" in main_cpp
assert "set_status_indicator" in main_cpp
@@ -52,7 +52,7 @@ TEST(RpcResponseBuilder, GoldenBytes) {
(std::vector<uint8_t>{0x04, 0x03, 0x02, 'a', 'b', 0xCC}));
}
// esp32_improv calls finish() and build_rpc_response() with no checksum flag,
// improv_ble calls finish() and build_rpc_response() with no checksum flag,
// so the two defaults must agree
TEST(RpcResponseBuilder, DefaultChecksumFlagMatches) {
const std::vector<std::string> urls = {"https://example.com"};
@@ -12,7 +12,7 @@ output:
pin: 2
id: built_in_led
esp32_improv:
improv_ble:
authorizer: io0_button
authorized_duration: 1min
status_indicator: built_in_led
@@ -5,6 +5,6 @@ wifi:
logger:
hardware_uart: UART0
# next_url compiles the USE_IMPROV_SERIAL_NEXT_URL branch and add_next_url_
# next_url compiles the USE_IMPROV_NEXT_URL branch and add_next_url_
improv_serial:
next_url: https://example.com/?device_name={{device_name}}&ip_address={{ip_address}}
@@ -1,6 +1,6 @@
# Exercises the provisioning window: api registers as a provisioning source
# (encryption enabled, no key), the on_timeout automation, and the wifi (AP +
# captive portal) and esp32_improv cross-component guards. improv_serial is
# captive portal) and improv_ble cross-component guards. improv_serial is
# intentionally NOT gated.
provisioning:
timeout: 1min
@@ -26,5 +26,5 @@ binary_sensor:
pin: 0
id: io0_button
esp32_improv:
improv_ble:
authorizer: io0_button