mirror of
https://github.com/esphome/esphome.git
synced 2026-09-17 18:18:43 +00:00
[improv_ble] Rename from esp32_improv and decouple from ESP32 (#19264)
This commit is contained in:
+1
-1
@@ -182,7 +182,6 @@ esphome/components/esp32_camera_web_server/* @ayufan
|
||||
esphome/components/esp32_can/* @Sympatron
|
||||
esphome/components/esp32_hosted/* @swoboda1337
|
||||
esphome/components/esp32_hosted/update/* @swoboda1337
|
||||
esphome/components/esp32_improv/* @jesserockz
|
||||
esphome/components/esp32_rmt/* @jesserockz
|
||||
esphome/components/esp32_rmt_led_strip/* @jesserockz
|
||||
esphome/components/esp8266/* @esphome/core
|
||||
@@ -268,6 +267,7 @@ esphome/components/i2s_audio/speaker/* @jesserockz @kahrendt
|
||||
esphome/components/iaqcore/* @yozik04
|
||||
esphome/components/ili9xxx/* @clydebarrow @nielsnl68
|
||||
esphome/components/improv_base/* @esphome/core
|
||||
esphome/components/improv_ble/* @jesserockz
|
||||
esphome/components/improv_serial/* @esphome/core
|
||||
esphome/components/ina226/* @latonita @Sergio303
|
||||
esphome/components/ina260/* @mreditor97
|
||||
|
||||
@@ -6,5 +6,6 @@ See the component-alias section of esphome/loader.py.
|
||||
|
||||
# alias -> (canonical component, removal version or None)
|
||||
COMPONENT_ALIASES: dict[str, tuple[str, str | None]] = {
|
||||
"esp32_improv": ("improv_ble", "2027.4.0"),
|
||||
"rp2040": ("rp2", "2027.7.0"),
|
||||
}
|
||||
|
||||
@@ -597,7 +597,7 @@ async def to_code(config):
|
||||
cg.add(parent.advertising_set_appearance(config[CONF_APPEARANCE]))
|
||||
cg.add(var.set_max_clients(config[CONF_MAX_CLIENTS]))
|
||||
# Only advertise for the server itself when the configuration gives clients something to
|
||||
# find. A server that is auto-loaded purely to host a runtime service (esp32_improv) stays
|
||||
# find. A server that is auto-loaded purely to host a runtime service (improv_ble) stays
|
||||
# silent until that service asks for advertising.
|
||||
cg.add(
|
||||
var.set_advertising_required(
|
||||
|
||||
@@ -40,7 +40,7 @@ class BLEServer final : public Component, public Parented<ESP32BLE> {
|
||||
|
||||
/** Whether this server needs the device to advertise so clients can find and connect to it.
|
||||
*
|
||||
* False for a server that only hosts services created at runtime (e.g. esp32_improv), which
|
||||
* False for a server that only hosts services created at runtime (e.g. improv_ble), which
|
||||
* request advertising themselves for as long as they need it.
|
||||
*/
|
||||
void set_advertising_required(bool required) { this->advertising_required_ = required; }
|
||||
|
||||
@@ -38,9 +38,11 @@ def _process_next_url(url: str) -> str:
|
||||
return url
|
||||
|
||||
|
||||
async def setup_improv_core(var: MockObj, config: ConfigType, component: str) -> None:
|
||||
async def setup_improv_core(var: MockObj, config: ConfigType) -> None:
|
||||
if next_url := config.get(CONF_NEXT_URL):
|
||||
cg.add(var.set_next_url(_process_next_url(next_url)))
|
||||
cg.add_define(f"USE_{component.upper()}_NEXT_URL")
|
||||
# One define for all transports: next_url_ is per object, so a transport
|
||||
# configured without next_url: calls add_next_url_ and appends nothing.
|
||||
cg.add_define("USE_IMPROV_NEXT_URL")
|
||||
|
||||
cg.add_library("improv/Improv", "1.2.7")
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace esphome::improv_base {
|
||||
|
||||
#if defined(USE_ESP32_IMPROV_NEXT_URL) || defined(USE_IMPROV_SERIAL_NEXT_URL)
|
||||
#ifdef USE_IMPROV_NEXT_URL
|
||||
static const char *const TAG = "improv_base";
|
||||
|
||||
static constexpr const char DEVICE_NAME_PLACEHOLDER[] = "{{device_name}}";
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <cstddef>
|
||||
#include "esphome/core/defines.h"
|
||||
|
||||
#if defined(USE_ESP32_IMPROV_NEXT_URL) || defined(USE_IMPROV_SERIAL_NEXT_URL)
|
||||
#ifdef USE_IMPROV_NEXT_URL
|
||||
#include <improv.h>
|
||||
#endif
|
||||
|
||||
@@ -11,12 +11,12 @@ namespace esphome::improv_base {
|
||||
|
||||
class ImprovBase {
|
||||
public:
|
||||
#if defined(USE_ESP32_IMPROV_NEXT_URL) || defined(USE_IMPROV_SERIAL_NEXT_URL)
|
||||
#ifdef USE_IMPROV_NEXT_URL
|
||||
void set_next_url(const char *next_url) { this->next_url_ = next_url; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
#if defined(USE_ESP32_IMPROV_NEXT_URL) || defined(USE_IMPROV_SERIAL_NEXT_URL)
|
||||
#ifdef USE_IMPROV_NEXT_URL
|
||||
/// Format next_url_ into buffer, replacing placeholders. Returns length written.
|
||||
size_t get_formatted_next_url_(char *buffer, size_t buffer_size);
|
||||
/// Append the formatted next_url to the RPC response, warning if it does not fit.
|
||||
|
||||
+61
-29
@@ -1,14 +1,41 @@
|
||||
from esphome import automation
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import binary_sensor, esp32_ble, improv_base, output
|
||||
from esphome.components.esp32_ble import BTLoggers
|
||||
from esphome.components import binary_sensor, improv_base, output
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID, CONF_ON_START, CONF_ON_STATE, CONF_TRIGGER_ID
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_ON_START,
|
||||
CONF_ON_STATE,
|
||||
CONF_TRIGGER_ID,
|
||||
PLATFORM_ESP32,
|
||||
)
|
||||
from esphome.core import CORE
|
||||
from esphome.types import ConfigType
|
||||
|
||||
AUTO_LOAD = ["esp32_ble_server", "improv_base"]
|
||||
# The BLE GATT server component that hosts the Improv service, per target
|
||||
# platform. improv_ble itself is platform neutral; supporting another chip
|
||||
# means adding its BLE server component here and the matching backend in
|
||||
# improv_ble_component.cpp. Doubles as the platform gate below, so an
|
||||
# unsupported chip is rejected in validation rather than at link time.
|
||||
BLE_SERVER_BACKENDS: dict[str, str] = {
|
||||
PLATFORM_ESP32: "esp32_ble_server",
|
||||
}
|
||||
|
||||
|
||||
def AUTO_LOAD() -> list[str]:
|
||||
auto_load = ["improv_base"]
|
||||
if backend := BLE_SERVER_BACKENDS.get(CORE.target_platform):
|
||||
auto_load.append(backend)
|
||||
return auto_load
|
||||
|
||||
|
||||
CODEOWNERS = ["@jesserockz"]
|
||||
DEPENDENCIES = ["wifi", "esp32"]
|
||||
DEPENDENCIES = ["wifi"]
|
||||
|
||||
# Legacy top-level YAML key that routes here; esphome/loader.py and
|
||||
# esphome/config.py handle the warning and the key rename.
|
||||
ALIASES = ["esp32_improv"]
|
||||
ALIAS_REMOVAL_VERSION = "2027.4.0"
|
||||
|
||||
CONF_AUTHORIZED_DURATION = "authorized_duration"
|
||||
CONF_AUTHORIZER = "authorizer"
|
||||
@@ -29,29 +56,29 @@ improv_ns = cg.esphome_ns.namespace("improv")
|
||||
Error = improv_ns.enum("Error")
|
||||
State = improv_ns.enum("State")
|
||||
|
||||
esp32_improv_ns = cg.esphome_ns.namespace("esp32_improv")
|
||||
ESP32ImprovComponent = esp32_improv_ns.class_("ESP32ImprovComponent", cg.Component)
|
||||
ESP32ImprovProvisionedTrigger = esp32_improv_ns.class_(
|
||||
"ESP32ImprovProvisionedTrigger", automation.Trigger.template()
|
||||
improv_ble_ns = cg.esphome_ns.namespace("improv_ble")
|
||||
ImprovBLEComponent = improv_ble_ns.class_("ImprovBLEComponent", cg.Component)
|
||||
ImprovBLEProvisionedTrigger = improv_ble_ns.class_(
|
||||
"ImprovBLEProvisionedTrigger", automation.Trigger.template()
|
||||
)
|
||||
ESP32ImprovProvisioningTrigger = esp32_improv_ns.class_(
|
||||
"ESP32ImprovProvisioningTrigger", automation.Trigger.template()
|
||||
ImprovBLEProvisioningTrigger = improv_ble_ns.class_(
|
||||
"ImprovBLEProvisioningTrigger", automation.Trigger.template()
|
||||
)
|
||||
ESP32ImprovStartTrigger = esp32_improv_ns.class_(
|
||||
"ESP32ImprovStartTrigger", automation.Trigger.template()
|
||||
ImprovBLEStartTrigger = improv_ble_ns.class_(
|
||||
"ImprovBLEStartTrigger", automation.Trigger.template()
|
||||
)
|
||||
ESP32ImprovStateTrigger = esp32_improv_ns.class_(
|
||||
"ESP32ImprovStateTrigger", automation.Trigger.template()
|
||||
ImprovBLEStateTrigger = improv_ble_ns.class_(
|
||||
"ImprovBLEStateTrigger", automation.Trigger.template()
|
||||
)
|
||||
ESP32ImprovStoppedTrigger = esp32_improv_ns.class_(
|
||||
"ESP32ImprovStoppedTrigger", automation.Trigger.template()
|
||||
ImprovBLEStoppedTrigger = improv_ble_ns.class_(
|
||||
"ImprovBLEStoppedTrigger", automation.Trigger.template()
|
||||
)
|
||||
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(ESP32ImprovComponent),
|
||||
cv.GenerateID(): cv.declare_id(ImprovBLEComponent),
|
||||
cv.Required(CONF_AUTHORIZER): cv.Any(
|
||||
cv.none, cv.use_id(binary_sensor.BinarySensor)
|
||||
),
|
||||
@@ -68,55 +95,60 @@ CONFIG_SCHEMA = (
|
||||
cv.Optional(CONF_ON_PROVISIONED): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||
ESP32ImprovProvisionedTrigger
|
||||
ImprovBLEProvisionedTrigger
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_PROVISIONING): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||
ESP32ImprovProvisioningTrigger
|
||||
ImprovBLEProvisioningTrigger
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_START): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||
ESP32ImprovStartTrigger
|
||||
ImprovBLEStartTrigger
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_STATE): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||
ESP32ImprovStateTrigger
|
||||
ImprovBLEStateTrigger
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_STOP): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||
ESP32ImprovStoppedTrigger
|
||||
ImprovBLEStoppedTrigger
|
||||
),
|
||||
}
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(improv_base.IMPROV_SCHEMA)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(cv.COMPONENT_SCHEMA),
|
||||
cv.only_on(list(BLE_SERVER_BACKENDS)),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
# ESP32 backend setup: the platform gate above means this is the only backend
|
||||
# that can reach to_code. Make it conditional when a second one is added.
|
||||
from esphome.components import esp32_ble
|
||||
|
||||
# Register the loggers this component needs
|
||||
esp32_ble.register_bt_logger(BTLoggers.GATT, BTLoggers.SMP)
|
||||
esp32_ble.register_bt_logger(esp32_ble.BTLoggers.GATT, esp32_ble.BTLoggers.SMP)
|
||||
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
|
||||
cg.add_define("USE_IMPROV")
|
||||
cg.add_define("USE_IMPROV_BLE")
|
||||
|
||||
await improv_base.setup_improv_core(var, config, "esp32_improv")
|
||||
await improv_base.setup_improv_core(var, config)
|
||||
|
||||
cg.add(var.set_identify_duration(config[CONF_IDENTIFY_DURATION]))
|
||||
cg.add(var.set_authorized_duration(config[CONF_AUTHORIZED_DURATION]))
|
||||
@@ -155,4 +187,4 @@ async def to_code(config: ConfigType) -> None:
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
use_state_callback = True
|
||||
if use_state_callback:
|
||||
cg.add_define("USE_ESP32_IMPROV_STATE_CALLBACK")
|
||||
cg.add_define("USE_IMPROV_BLE_STATE_CALLBACK")
|
||||
+19
-19
@@ -1,17 +1,17 @@
|
||||
#pragma once
|
||||
#ifdef USE_ESP32
|
||||
#ifdef USE_ESP32_IMPROV_STATE_CALLBACK
|
||||
#include "esp32_improv_component.h"
|
||||
#ifdef USE_IMPROV_BLE_STATE_CALLBACK
|
||||
#include "improv_ble_component.h"
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
|
||||
#include <improv.h>
|
||||
|
||||
namespace esphome::esp32_improv {
|
||||
namespace esphome::improv_ble {
|
||||
|
||||
class ESP32ImprovProvisionedTrigger final : public Trigger<> {
|
||||
class ImprovBLEProvisionedTrigger final : public Trigger<> {
|
||||
public:
|
||||
explicit ESP32ImprovProvisionedTrigger(ESP32ImprovComponent *parent) : parent_(parent) {
|
||||
explicit ImprovBLEProvisionedTrigger(ImprovBLEComponent *parent) : parent_(parent) {
|
||||
parent->add_on_state_callback([this](improv::State state, improv::Error error) {
|
||||
if (state == improv::STATE_PROVISIONED && !this->parent_->is_failed()) {
|
||||
this->trigger();
|
||||
@@ -20,12 +20,12 @@ class ESP32ImprovProvisionedTrigger final : public Trigger<> {
|
||||
}
|
||||
|
||||
protected:
|
||||
ESP32ImprovComponent *parent_;
|
||||
ImprovBLEComponent *parent_;
|
||||
};
|
||||
|
||||
class ESP32ImprovProvisioningTrigger final : public Trigger<> {
|
||||
class ImprovBLEProvisioningTrigger final : public Trigger<> {
|
||||
public:
|
||||
explicit ESP32ImprovProvisioningTrigger(ESP32ImprovComponent *parent) : parent_(parent) {
|
||||
explicit ImprovBLEProvisioningTrigger(ImprovBLEComponent *parent) : parent_(parent) {
|
||||
parent->add_on_state_callback([this](improv::State state, improv::Error error) {
|
||||
if (state == improv::STATE_PROVISIONING && !this->parent_->is_failed()) {
|
||||
this->trigger();
|
||||
@@ -34,12 +34,12 @@ class ESP32ImprovProvisioningTrigger final : public Trigger<> {
|
||||
}
|
||||
|
||||
protected:
|
||||
ESP32ImprovComponent *parent_;
|
||||
ImprovBLEComponent *parent_;
|
||||
};
|
||||
|
||||
class ESP32ImprovStartTrigger final : public Trigger<> {
|
||||
class ImprovBLEStartTrigger final : public Trigger<> {
|
||||
public:
|
||||
explicit ESP32ImprovStartTrigger(ESP32ImprovComponent *parent) : parent_(parent) {
|
||||
explicit ImprovBLEStartTrigger(ImprovBLEComponent *parent) : parent_(parent) {
|
||||
parent->add_on_state_callback([this](improv::State state, improv::Error error) {
|
||||
if ((state == improv::STATE_AUTHORIZED || state == improv::STATE_AWAITING_AUTHORIZATION) &&
|
||||
!this->parent_->is_failed()) {
|
||||
@@ -49,12 +49,12 @@ class ESP32ImprovStartTrigger final : public Trigger<> {
|
||||
}
|
||||
|
||||
protected:
|
||||
ESP32ImprovComponent *parent_;
|
||||
ImprovBLEComponent *parent_;
|
||||
};
|
||||
|
||||
class ESP32ImprovStateTrigger final : public Trigger<improv::State, improv::Error> {
|
||||
class ImprovBLEStateTrigger final : public Trigger<improv::State, improv::Error> {
|
||||
public:
|
||||
explicit ESP32ImprovStateTrigger(ESP32ImprovComponent *parent) : parent_(parent) {
|
||||
explicit ImprovBLEStateTrigger(ImprovBLEComponent *parent) : parent_(parent) {
|
||||
parent->add_on_state_callback([this](improv::State state, improv::Error error) {
|
||||
if (!this->parent_->is_failed()) {
|
||||
this->trigger(state, error);
|
||||
@@ -63,12 +63,12 @@ class ESP32ImprovStateTrigger final : public Trigger<improv::State, improv::Erro
|
||||
}
|
||||
|
||||
protected:
|
||||
ESP32ImprovComponent *parent_;
|
||||
ImprovBLEComponent *parent_;
|
||||
};
|
||||
|
||||
class ESP32ImprovStoppedTrigger final : public Trigger<> {
|
||||
class ImprovBLEStoppedTrigger final : public Trigger<> {
|
||||
public:
|
||||
explicit ESP32ImprovStoppedTrigger(ESP32ImprovComponent *parent) : parent_(parent) {
|
||||
explicit ImprovBLEStoppedTrigger(ImprovBLEComponent *parent) : parent_(parent) {
|
||||
parent->add_on_state_callback([this](improv::State state, improv::Error error) {
|
||||
if (state == improv::STATE_STOPPED && !this->parent_->is_failed()) {
|
||||
this->trigger();
|
||||
@@ -77,10 +77,10 @@ class ESP32ImprovStoppedTrigger final : public Trigger<> {
|
||||
}
|
||||
|
||||
protected:
|
||||
ESP32ImprovComponent *parent_;
|
||||
ImprovBLEComponent *parent_;
|
||||
};
|
||||
|
||||
} // namespace esphome::esp32_improv
|
||||
} // namespace esphome::improv_ble
|
||||
|
||||
#endif
|
||||
#endif
|
||||
+35
-34
@@ -1,10 +1,7 @@
|
||||
#include "esp32_improv_component.h"
|
||||
#include "improv_ble_component.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "esphome/components/bytebuffer/bytebuffer.h"
|
||||
#include "esphome/components/esp32_ble/ble.h"
|
||||
#include "esphome/components/esp32_ble_server/ble_2902.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
@@ -15,11 +12,15 @@
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
namespace esphome::esp32_improv {
|
||||
#include "esphome/components/bytebuffer/bytebuffer.h"
|
||||
#include "esphome/components/esp32_ble/ble.h"
|
||||
#include "esphome/components/esp32_ble_server/ble_2902.h"
|
||||
|
||||
namespace esphome::improv_ble {
|
||||
|
||||
using namespace bytebuffer;
|
||||
|
||||
static const char *const TAG = "esp32_improv.component";
|
||||
static const char *const TAG = "improv_ble.component";
|
||||
static constexpr size_t IMPROV_MAX_LOG_BYTES = 128;
|
||||
static constexpr char ESPHOME_MY_LINK[] = "https://my.home-assistant.io/redirect/config_flow_start?domain=esphome";
|
||||
// command + data length + trailing byte
|
||||
@@ -38,9 +39,9 @@ static constexpr uint8_t IMPROV_SERVICE_DATA_SIZE = 8;
|
||||
static constexpr uint8_t IMPROV_PROTOCOL_ID_1 = 0x77; // 'P' << 1 | 'R' >> 7
|
||||
static constexpr uint8_t IMPROV_PROTOCOL_ID_2 = 0x46; // 'I' << 1 | 'M' >> 7
|
||||
|
||||
ESP32ImprovComponent::ESP32ImprovComponent() { global_improv_component = this; }
|
||||
ImprovBLEComponent::ImprovBLEComponent() { global_improv_component = this; }
|
||||
|
||||
void ESP32ImprovComponent::setup() {
|
||||
void ImprovBLEComponent::setup() {
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
if (this->authorizer_ != nullptr) {
|
||||
this->authorizer_->add_on_state_callback([this](bool state) {
|
||||
@@ -66,7 +67,7 @@ void ESP32ImprovComponent::setup() {
|
||||
this->disable_loop();
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::setup_characteristics() {
|
||||
void ImprovBLEComponent::setup_characteristics() {
|
||||
this->status_ = this->service_->create_characteristic(
|
||||
improv::STATUS_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
|
||||
BLEDescriptor *status_descriptor = new BLE2902();
|
||||
@@ -104,11 +105,11 @@ void ESP32ImprovComponent::setup_characteristics() {
|
||||
this->setup_complete_ = true;
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::loop() {
|
||||
void ImprovBLEComponent::loop() {
|
||||
if (!global_ble_server->is_running()) {
|
||||
if (this->state_ != improv::STATE_STOPPED) {
|
||||
this->state_ = improv::STATE_STOPPED;
|
||||
#ifdef USE_ESP32_IMPROV_STATE_CALLBACK
|
||||
#ifdef USE_IMPROV_BLE_STATE_CALLBACK
|
||||
this->state_callback_.call(this->state_, this->error_state_);
|
||||
#endif
|
||||
}
|
||||
@@ -200,7 +201,7 @@ void ESP32ImprovComponent::loop() {
|
||||
}
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::set_status_indicator_state_(bool state) {
|
||||
void ImprovBLEComponent::set_status_indicator_state_(bool state) {
|
||||
#ifdef USE_OUTPUT
|
||||
if (this->status_indicator_ == nullptr)
|
||||
return;
|
||||
@@ -216,7 +217,7 @@ void ESP32ImprovComponent::set_status_indicator_state_(bool state) {
|
||||
}
|
||||
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG
|
||||
const char *ESP32ImprovComponent::state_to_string_(improv::State state) {
|
||||
const char *ImprovBLEComponent::state_to_string_(improv::State state) {
|
||||
switch (state) {
|
||||
case improv::STATE_STOPPED:
|
||||
return "STOPPED";
|
||||
@@ -234,7 +235,7 @@ const char *ESP32ImprovComponent::state_to_string_(improv::State state) {
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ESP32ImprovComponent::check_identify_() {
|
||||
bool ImprovBLEComponent::check_identify_() {
|
||||
uint32_t now = millis();
|
||||
|
||||
bool identify = this->identify_start_ != 0 && now - this->identify_start_ <= this->identify_duration_;
|
||||
@@ -246,7 +247,7 @@ bool ESP32ImprovComponent::check_identify_() {
|
||||
return identify;
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::set_state_(improv::State state, bool update_advertising) {
|
||||
void ImprovBLEComponent::set_state_(improv::State state, bool update_advertising) {
|
||||
// Skip if state hasn't changed
|
||||
if (this->state_ == state) {
|
||||
return;
|
||||
@@ -274,12 +275,12 @@ void ESP32ImprovComponent::set_state_(improv::State state, bool update_advertisi
|
||||
// Advertise the new state via service data
|
||||
this->advertise_service_data_();
|
||||
}
|
||||
#ifdef USE_ESP32_IMPROV_STATE_CALLBACK
|
||||
#ifdef USE_IMPROV_BLE_STATE_CALLBACK
|
||||
this->state_callback_.call(this->state_, this->error_state_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::set_error_(improv::Error error) {
|
||||
void ImprovBLEComponent::set_error_(improv::Error error) {
|
||||
if (error != improv::ERROR_NONE) {
|
||||
ESP_LOGE(TAG, "Error: %d", error);
|
||||
}
|
||||
@@ -295,14 +296,14 @@ void ESP32ImprovComponent::set_error_(improv::Error error) {
|
||||
}
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::send_response_(std::span<const uint8_t> response) {
|
||||
void ImprovBLEComponent::send_response_(std::span<const uint8_t> response) {
|
||||
// The BLE characteristic owns its value, so one exact-size copy is required here
|
||||
this->rpc_response_->set_value(std::vector<uint8_t>(response.begin(), response.end()));
|
||||
if (this->state_ != improv::STATE_STOPPED)
|
||||
this->rpc_response_->notify();
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::start() {
|
||||
void ImprovBLEComponent::start() {
|
||||
if (this->should_start_ || this->state_ != improv::STATE_STOPPED)
|
||||
return;
|
||||
|
||||
@@ -320,7 +321,7 @@ void ESP32ImprovComponent::start() {
|
||||
this->enable_loop();
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::stop() {
|
||||
void ImprovBLEComponent::stop() {
|
||||
this->should_start_ = false;
|
||||
// Wait before stopping the service to ensure all BLE clients see the state change.
|
||||
// This prevents clients from repeatedly reconnecting and wasting resources by allowing
|
||||
@@ -335,10 +336,10 @@ void ESP32ImprovComponent::stop() {
|
||||
});
|
||||
}
|
||||
|
||||
float ESP32ImprovComponent::get_setup_priority() const { return setup_priority::AFTER_BLUETOOTH; }
|
||||
float ImprovBLEComponent::get_setup_priority() const { return setup_priority::AFTER_BLUETOOTH; }
|
||||
|
||||
void ESP32ImprovComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "ESP32 Improv:");
|
||||
void ImprovBLEComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "Improv BLE:");
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
LOG_BINARY_SENSOR(" ", "Authorizer", this->authorizer_);
|
||||
#endif
|
||||
@@ -347,7 +348,7 @@ void ESP32ImprovComponent::dump_config() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::process_incoming_data_() {
|
||||
void ImprovBLEComponent::process_incoming_data_() {
|
||||
if (this->incoming_data_.size() < 3)
|
||||
return;
|
||||
uint8_t length = this->incoming_data_[1];
|
||||
@@ -422,7 +423,7 @@ void ESP32ImprovComponent::process_incoming_data_() {
|
||||
}
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::on_wifi_connect_timeout_() {
|
||||
void ImprovBLEComponent::on_wifi_connect_timeout_() {
|
||||
this->set_error_(improv::ERROR_UNABLE_TO_CONNECT);
|
||||
this->set_state_(improv::STATE_AUTHORIZED);
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
@@ -433,7 +434,7 @@ void ESP32ImprovComponent::on_wifi_connect_timeout_() {
|
||||
wifi::global_wifi_component->clear_sta();
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::check_wifi_connection_() {
|
||||
void ImprovBLEComponent::check_wifi_connection_() {
|
||||
if (!wifi::global_wifi_component->is_connected()) {
|
||||
return;
|
||||
}
|
||||
@@ -447,7 +448,7 @@ void ESP32ImprovComponent::check_wifi_connection_() {
|
||||
std::array<uint8_t, improv::RPC_RESPONSE_MAX_SIZE> buf;
|
||||
improv::RpcResponseBuilder builder(buf, improv::WIFI_SETTINGS);
|
||||
|
||||
#ifdef USE_ESP32_IMPROV_NEXT_URL
|
||||
#ifdef USE_IMPROV_NEXT_URL
|
||||
// Add next_url if configured (should be first per Improv BLE spec)
|
||||
this->add_next_url_(builder, MAX_NEXT_URL_LEN);
|
||||
#endif
|
||||
@@ -480,7 +481,7 @@ void ESP32ImprovComponent::check_wifi_connection_() {
|
||||
this->stop();
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::advertise_service_data_() {
|
||||
void ImprovBLEComponent::advertise_service_data_() {
|
||||
uint8_t service_data[IMPROV_SERVICE_DATA_SIZE] = {};
|
||||
service_data[0] = IMPROV_PROTOCOL_ID_1; // PR
|
||||
service_data[1] = IMPROV_PROTOCOL_ID_2; // IM
|
||||
@@ -499,7 +500,7 @@ void ESP32ImprovComponent::advertise_service_data_() {
|
||||
esp32_ble::global_ble->advertising_set_service_data_and_name(std::span<const uint8_t>(service_data), false);
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::update_advertising_type_() {
|
||||
void ImprovBLEComponent::update_advertising_type_() {
|
||||
uint32_t now = App.get_loop_component_start_time();
|
||||
|
||||
// If we're advertising the device name and it's been more than NAME_ADVERTISING_DURATION, switch back to service data
|
||||
@@ -524,21 +525,21 @@ void ESP32ImprovComponent::update_advertising_type_() {
|
||||
}
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::request_advertising_() {
|
||||
void ImprovBLEComponent::request_advertising_() {
|
||||
if (this->advertising_requested_)
|
||||
return;
|
||||
this->advertising_requested_ = true;
|
||||
esp32_ble::global_ble->advertising_start();
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::release_advertising_() {
|
||||
void ImprovBLEComponent::release_advertising_() {
|
||||
if (!this->advertising_requested_)
|
||||
return;
|
||||
this->advertising_requested_ = false;
|
||||
esp32_ble::global_ble->advertising_stop();
|
||||
}
|
||||
|
||||
improv::State ESP32ImprovComponent::get_initial_state_() const {
|
||||
improv::State ImprovBLEComponent::get_initial_state_() const {
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
// If we have an authorizer, start in awaiting authorization state
|
||||
return this->authorizer_ == nullptr ? improv::STATE_AUTHORIZED : improv::STATE_AWAITING_AUTHORIZATION;
|
||||
@@ -548,8 +549,8 @@ improv::State ESP32ImprovComponent::get_initial_state_() const {
|
||||
#endif
|
||||
}
|
||||
|
||||
ESP32ImprovComponent *global_improv_component = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
ImprovBLEComponent *global_improv_component = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
} // namespace esphome::esp32_improv
|
||||
} // namespace esphome::improv_ble
|
||||
|
||||
#endif
|
||||
+14
-10
@@ -5,12 +5,10 @@
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/preferences.h"
|
||||
|
||||
#include "esphome/components/esp32_ble_server/ble_characteristic.h"
|
||||
#include "esphome/components/esp32_ble_server/ble_server.h"
|
||||
#include "esphome/components/improv_base/improv_base.h"
|
||||
#include "esphome/components/wifi/wifi_component.h"
|
||||
|
||||
#ifdef USE_ESP32_IMPROV_STATE_CALLBACK
|
||||
#ifdef USE_IMPROV_BLE_STATE_CALLBACK
|
||||
#include "esphome/core/automation.h"
|
||||
#endif
|
||||
|
||||
@@ -25,17 +23,23 @@
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
// ESP-IDF is currently the only target platform with a BLE GATT server, so it is
|
||||
// the only backend this component has. The Python side keeps the platform table
|
||||
// (BLE_SERVER_BACKENDS in __init__.py); a second backend adds another arm here.
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#include "esphome/components/esp32_ble_server/ble_characteristic.h"
|
||||
#include "esphome/components/esp32_ble_server/ble_server.h"
|
||||
|
||||
#include <improv.h>
|
||||
|
||||
namespace esphome::esp32_improv {
|
||||
namespace esphome::improv_ble {
|
||||
|
||||
using namespace esp32_ble_server;
|
||||
|
||||
class ESP32ImprovComponent final : public Component, public improv_base::ImprovBase {
|
||||
class ImprovBLEComponent final : public Component, public improv_base::ImprovBase {
|
||||
public:
|
||||
ESP32ImprovComponent();
|
||||
ImprovBLEComponent();
|
||||
void dump_config() override;
|
||||
void loop() override;
|
||||
void setup() override;
|
||||
@@ -47,7 +51,7 @@ class ESP32ImprovComponent final : public Component, public improv_base::ImprovB
|
||||
bool is_active() const { return this->state_ != improv::STATE_STOPPED; }
|
||||
bool should_start() const { return this->should_start_; }
|
||||
|
||||
#ifdef USE_ESP32_IMPROV_STATE_CALLBACK
|
||||
#ifdef USE_IMPROV_BLE_STATE_CALLBACK
|
||||
template<typename F> void add_on_state_callback(F &&callback) {
|
||||
this->state_callback_.add(std::forward<F>(callback));
|
||||
}
|
||||
@@ -97,7 +101,7 @@ class ESP32ImprovComponent final : public Component, public improv_base::ImprovB
|
||||
|
||||
improv::State state_{improv::STATE_STOPPED};
|
||||
improv::Error error_state_{improv::ERROR_NONE};
|
||||
#ifdef USE_ESP32_IMPROV_STATE_CALLBACK
|
||||
#ifdef USE_IMPROV_BLE_STATE_CALLBACK
|
||||
CallbackManager<void(improv::State, improv::Error)> state_callback_{};
|
||||
#endif
|
||||
|
||||
@@ -125,8 +129,8 @@ class ESP32ImprovComponent final : public Component, public improv_base::ImprovB
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
extern ESP32ImprovComponent *global_improv_component;
|
||||
extern ImprovBLEComponent *global_improv_component;
|
||||
|
||||
} // namespace esphome::esp32_improv
|
||||
} // namespace esphome::improv_ble
|
||||
|
||||
#endif
|
||||
@@ -70,7 +70,7 @@ FINAL_VALIDATE_SCHEMA = validate_transport
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await improv_base.setup_improv_core(var, config, "improv_serial")
|
||||
await improv_base.setup_improv_core(var, config)
|
||||
cg.add_define("USE_IMPROV_SERIAL")
|
||||
if (uart_id := config.get(CONF_UART_ID)) is not None:
|
||||
cg.add(var.set_uart(await cg.get_variable(uart_id)))
|
||||
|
||||
@@ -208,7 +208,7 @@ void ImprovSerialComponent::add_webserver_urls_(improv::RpcResponseBuilder &buil
|
||||
void ImprovSerialComponent::send_settings_response_(improv::Command command) {
|
||||
std::array<uint8_t, improv::RPC_RESPONSE_MAX_SIZE> buf;
|
||||
improv::RpcResponseBuilder builder(buf, command);
|
||||
#ifdef USE_IMPROV_SERIAL_NEXT_URL
|
||||
#ifdef USE_IMPROV_NEXT_URL
|
||||
this->add_next_url_(builder, MAX_NEXT_URL_LEN);
|
||||
#endif
|
||||
#ifdef USE_WEBSERVER
|
||||
|
||||
@@ -55,7 +55,7 @@ static const uint8_t IMPROV_SERIAL_VERSION = 1;
|
||||
#ifdef USE_WIFI
|
||||
// Wi-Fi connect failure timers: a fresh provision reports at 30 s (stock behavior), while
|
||||
// switching networks on an already-connected device (disconnect + reconnect) can legitimately
|
||||
// take longer; 90 s matches esp32_improv's default wifi_timeout.
|
||||
// take longer; 90 s matches improv_ble's default wifi_timeout.
|
||||
static const uint32_t WIFI_CONNECT_TIMEOUT_MS = 30000;
|
||||
static const uint32_t WIFI_SWITCH_TIMEOUT_MS = 90000;
|
||||
#endif
|
||||
|
||||
@@ -355,7 +355,7 @@ def final_validate(config):
|
||||
has_sta = bool(config.get(CONF_NETWORKS, True))
|
||||
has_ap = CONF_AP in config
|
||||
full_config = fv.full_config.get()
|
||||
has_improv = "esp32_improv" in full_config
|
||||
has_improv = "improv_ble" in full_config
|
||||
has_improv_serial = "improv_serial" in full_config
|
||||
has_captive_portal = "captive_portal" in full_config
|
||||
has_web_server = "web_server" in full_config
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
#include "esphome/components/captive_portal/captive_portal.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_IMPROV
|
||||
#include "esphome/components/esp32_improv/esp32_improv_component.h"
|
||||
#ifdef USE_IMPROV_BLE
|
||||
#include "esphome/components/improv_ble/improv_ble_component.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_IMPROV_SERIAL
|
||||
@@ -226,7 +226,7 @@ bool CompactString::operator==(const StringRef &other) const {
|
||||
/// ┌──────────────────────────────────────────────────────────────────────┐
|
||||
/// │ Captive Portal / Improv Mode (AP active, scanning disabled) │
|
||||
/// ├──────────────────────────────────────────────────────────────────────┤
|
||||
/// │ When captive_portal or esp32_improv is active, WiFi scanning is │
|
||||
/// │ When captive_portal or improv_ble is active, WiFi scanning is │
|
||||
/// │ disabled because it disrupts AP clients (radio leaves AP channel │
|
||||
/// │ to hop through other channels, causing client disconnections). │
|
||||
/// │ │
|
||||
@@ -478,9 +478,9 @@ bool WiFiComponent::needs_full_scan_results_() const {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_IMPROV
|
||||
#ifdef USE_IMPROV_BLE
|
||||
// BLE improv also needs results during provisioning
|
||||
if (esp32_improv::global_improv_component != nullptr && esp32_improv::global_improv_component->is_active()) {
|
||||
if (improv_ble::global_improv_component != nullptr && improv_ble::global_improv_component->is_active()) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -746,10 +746,10 @@ void WiFiComponent::start() {
|
||||
#endif
|
||||
#endif // USE_WIFI_AP
|
||||
}
|
||||
#ifdef USE_IMPROV
|
||||
if (!this->has_sta() && esp32_improv::global_improv_component != nullptr) {
|
||||
#ifdef USE_IMPROV_BLE
|
||||
if (!this->has_sta() && improv_ble::global_improv_component != nullptr) {
|
||||
if (this->wifi_mode_(true, {}))
|
||||
esp32_improv::global_improv_component->start();
|
||||
improv_ble::global_improv_component->start();
|
||||
}
|
||||
#endif
|
||||
this->wifi_apply_hostname_();
|
||||
@@ -805,7 +805,7 @@ void WiFiComponent::loop() {
|
||||
break;
|
||||
}
|
||||
// Use longer cooldown when captive portal/improv is active to avoid disrupting user config
|
||||
bool portal_active = this->is_captive_portal_active_() || this->is_esp32_improv_active_();
|
||||
bool portal_active = this->is_captive_portal_active_() || this->is_improv_ble_active_();
|
||||
uint32_t cooldown_duration = portal_active ? WIFI_COOLDOWN_WITH_AP_ACTIVE_MS : WIFI_COOLDOWN_DURATION_MS;
|
||||
if (now - this->action_started_ > cooldown_duration) {
|
||||
// After cooldown we either restarted the adapter because of
|
||||
@@ -894,12 +894,12 @@ void WiFiComponent::loop() {
|
||||
}
|
||||
#endif // USE_WIFI_AP
|
||||
|
||||
#ifdef USE_IMPROV
|
||||
if (esp32_improv::global_improv_component != nullptr && !esp32_improv::global_improv_component->is_active() &&
|
||||
!esp32_improv::global_improv_component->should_start()) {
|
||||
if (now - this->last_connected_ > esp32_improv::global_improv_component->get_wifi_timeout()) {
|
||||
#ifdef USE_IMPROV_BLE
|
||||
if (improv_ble::global_improv_component != nullptr && !improv_ble::global_improv_component->is_active() &&
|
||||
!improv_ble::global_improv_component->should_start()) {
|
||||
if (now - this->last_connected_ > improv_ble::global_improv_component->get_wifi_timeout()) {
|
||||
if (this->wifi_mode_(true, {}))
|
||||
esp32_improv::global_improv_component->start();
|
||||
improv_ble::global_improv_component->start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1644,9 +1644,9 @@ void WiFiComponent::check_connecting_finished(uint32_t now) {
|
||||
ESP_LOGD(TAG, "Disabling AP");
|
||||
this->wifi_mode_({}, false);
|
||||
}
|
||||
#ifdef USE_IMPROV
|
||||
if (this->is_esp32_improv_active_()) {
|
||||
esp32_improv::global_improv_component->stop();
|
||||
#ifdef USE_IMPROV_BLE
|
||||
if (this->is_improv_ble_active_()) {
|
||||
improv_ble::global_improv_component->stop();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1878,7 +1878,7 @@ WiFiRetryPhase WiFiComponent::determine_next_phase_() {
|
||||
return WiFiRetryPhase::RETRY_HIDDEN;
|
||||
}
|
||||
// Need to scan for captive portal
|
||||
} else if (this->is_esp32_improv_active_()) {
|
||||
} else if (this->is_improv_ble_active_()) {
|
||||
// Improv doesn't need scan results
|
||||
return WiFiRetryPhase::RETRY_HIDDEN;
|
||||
}
|
||||
@@ -1969,7 +1969,7 @@ bool WiFiComponent::transition_to_phase_(WiFiRetryPhase new_phase) {
|
||||
// Skip actual adapter restart if captive portal/improv is active
|
||||
// This allows state machine to reset num_retried_ and trigger fresh scan
|
||||
// without disrupting the captive portal/improv connection
|
||||
if (!this->is_captive_portal_active_() && !this->is_esp32_improv_active_()) {
|
||||
if (!this->is_captive_portal_active_() && !this->is_improv_ble_active_()) {
|
||||
this->restart_adapter();
|
||||
} else {
|
||||
// Even when skipping full restart, disconnect to clear driver state
|
||||
@@ -2228,9 +2228,9 @@ bool WiFiComponent::is_captive_portal_active_() {
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
bool WiFiComponent::is_esp32_improv_active_() {
|
||||
#ifdef USE_IMPROV
|
||||
return esp32_improv::global_improv_component != nullptr && esp32_improv::global_improv_component->is_active();
|
||||
bool WiFiComponent::is_improv_ble_active_() {
|
||||
#ifdef USE_IMPROV_BLE
|
||||
return improv_ble::global_improv_component != nullptr && improv_ble::global_improv_component->is_active();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
@@ -797,7 +797,7 @@ class WiFiComponent final : public Component {
|
||||
network::IPAddress wifi_dns_ip_(int num);
|
||||
|
||||
bool is_captive_portal_active_();
|
||||
bool is_esp32_improv_active_();
|
||||
bool is_improv_ble_active_();
|
||||
|
||||
#ifdef USE_WIFI_FAST_CONNECT
|
||||
bool load_fast_connect_settings_(WiFiAP ¶ms);
|
||||
|
||||
@@ -70,7 +70,6 @@
|
||||
#define USE_ESP32_CAMERA_JPEG_CONVERSION
|
||||
#define USE_ESP32_HOSTED
|
||||
#define USE_ESP32_HOSTED_HTTP_UPDATE
|
||||
#define USE_ESP32_IMPROV_STATE_CALLBACK
|
||||
#define USE_ESP_NOW_HOSTED
|
||||
#define USE_EVENT
|
||||
#define USE_FAN
|
||||
@@ -83,6 +82,7 @@
|
||||
#define USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT 8000 // NOLINT
|
||||
#define USE_I2S_AUDIO_SPDIF_MODE
|
||||
#define USE_IMAGE
|
||||
#define USE_IMPROV_BLE_STATE_CALLBACK
|
||||
#define USE_INFRARED
|
||||
#define USE_IR_RF
|
||||
#define USE_JSON
|
||||
@@ -266,7 +266,7 @@
|
||||
#define MAX_API_CONNECTIONS 6
|
||||
// The Improv library is not in the Zephyr tidy environment
|
||||
#define USE_IMPROV_SERIAL
|
||||
#define USE_IMPROV_SERIAL_NEXT_URL
|
||||
#define USE_IMPROV_NEXT_URL
|
||||
#define USE_MD5
|
||||
#define USE_NOISE
|
||||
#define USE_SHA256
|
||||
@@ -392,8 +392,7 @@
|
||||
#define USE_ESP32_CAMERA_JPEG_ENCODER
|
||||
#define USE_HTTP_REQUEST_RESPONSE
|
||||
#define USE_I2C
|
||||
#define USE_IMPROV
|
||||
#define USE_ESP32_IMPROV_NEXT_URL
|
||||
#define USE_IMPROV_BLE
|
||||
#define USE_MICROPHONE
|
||||
#define USE_PSRAM
|
||||
#define USE_SENDSPIN
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ lib_deps =
|
||||
${common.lib_deps_base}
|
||||
https://github.com/dudanov/MideaUART.git#eeea6c3e9b4474f067054592b435be1c4e466815 ; midea
|
||||
esphome/noise-c@0.1.30 ; noise (api, ota)
|
||||
improv/Improv@1.2.7 ; improv_serial / esp32_improv
|
||||
improv/Improv@1.2.7 ; improv_serial / improv_ble
|
||||
kikuchan98/pngle@1.1.0 ; online_image
|
||||
; Using the repository directly, otherwise ESP-IDF can't use the library
|
||||
https://github.com/bitbank2/JPEGDEC.git#1.8.4 ; online_image
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user