mirror of
https://github.com/esphome/esphome.git
synced 2026-09-30 16:30:22 +00:00
Merge remote-tracking branch 'upstream/dev' into integration
This commit is contained in:
@@ -7,6 +7,7 @@ from typing import Any
|
|||||||
|
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
|
from esphome.components.const import CONF_USE_PSRAM
|
||||||
from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant
|
from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant
|
||||||
from esphome.components.esp32.const import VARIANT_ESP32C2
|
from esphome.components.esp32.const import VARIANT_ESP32C2
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
@@ -342,6 +343,9 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
cv.Optional(CONF_MAX_CONNECTIONS, default=DEFAULT_MAX_CONNECTIONS): cv.All(
|
cv.Optional(CONF_MAX_CONNECTIONS, default=DEFAULT_MAX_CONNECTIONS): cv.All(
|
||||||
cv.positive_int, cv.Range(min=1, max=IDF_MAX_CONNECTIONS)
|
cv.positive_int, cv.Range(min=1, max=IDF_MAX_CONNECTIONS)
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_USE_PSRAM): cv.All(
|
||||||
|
cv.only_on_esp32, cv.requires_component("psram"), cv.boolean
|
||||||
|
),
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
@@ -598,6 +602,22 @@ async def to_code(config):
|
|||||||
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
|
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
|
||||||
add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True)
|
add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True)
|
||||||
|
|
||||||
|
# When PSRAM and BT are used together, Bluedroid should prefer SPIRAM for
|
||||||
|
# heap allocations and use dynamic (heap-based) environment memory tables
|
||||||
|
# instead of large static DRAM arrays. This frees ~40 kB of internal RAM.
|
||||||
|
# Reference: Espressif ADF Design Considerations
|
||||||
|
# https://espressif-docs.readthedocs-hosted.com/projects/esp-adf/en/latest/
|
||||||
|
# design-guide/design-considerations.html
|
||||||
|
if config.get(CONF_USE_PSRAM, False):
|
||||||
|
cg.add_define("USE_ESP32_BLE_PSRAM")
|
||||||
|
# CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is only available on ESP32
|
||||||
|
# (BTDM dual-mode controller). BLE-only SoCs (C3, S3, C2, H2) do not
|
||||||
|
# expose this Kconfig symbol; applying it there would cause a build error.
|
||||||
|
if get_esp32_variant() == const.VARIANT_ESP32:
|
||||||
|
add_idf_sdkconfig_option("CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST", True)
|
||||||
|
# CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY applies to all Bluedroid-enabled variants.
|
||||||
|
add_idf_sdkconfig_option("CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY", True)
|
||||||
|
|
||||||
# Register the core BLE loggers that are always needed
|
# Register the core BLE loggers that are always needed
|
||||||
register_bt_logger(BTLoggers.GAP, BTLoggers.BTM, BTLoggers.HCI)
|
register_bt_logger(BTLoggers.GAP, BTLoggers.BTM, BTLoggers.HCI)
|
||||||
|
|
||||||
|
|||||||
@@ -667,6 +667,9 @@ void ESP32BLE::dump_config() {
|
|||||||
" MAC address: %s\n"
|
" MAC address: %s\n"
|
||||||
" IO Capability: %s",
|
" IO Capability: %s",
|
||||||
mac_s, io_capability_s);
|
mac_s, io_capability_s);
|
||||||
|
#ifdef USE_ESP32_BLE_PSRAM
|
||||||
|
ESP_LOGCONFIG(TAG, " PSRAM BLE allocation: enabled");
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS
|
#ifdef ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS
|
||||||
const char *auth_req_mode_s = "<default>";
|
const char *auth_req_mode_s = "<default>";
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
|
|||||||
from esphome.util import Registry
|
from esphome.util import Registry
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
|
|
||||||
DEVICE_CLASSES = [
|
DEVICE_CLASSES = [
|
||||||
DEVICE_CLASS_ABSOLUTE_HUMIDITY,
|
DEVICE_CLASS_ABSOLUTE_HUMIDITY,
|
||||||
DEVICE_CLASS_APPARENT_POWER,
|
DEVICE_CLASS_APPARENT_POWER,
|
||||||
@@ -293,6 +294,7 @@ SensorInRangeCondition = sensor_ns.class_("SensorInRangeCondition", Filter)
|
|||||||
ClampFilter = sensor_ns.class_("ClampFilter", Filter)
|
ClampFilter = sensor_ns.class_("ClampFilter", Filter)
|
||||||
RoundFilter = sensor_ns.class_("RoundFilter", Filter)
|
RoundFilter = sensor_ns.class_("RoundFilter", Filter)
|
||||||
RoundMultipleFilter = sensor_ns.class_("RoundMultipleFilter", Filter)
|
RoundMultipleFilter = sensor_ns.class_("RoundMultipleFilter", Filter)
|
||||||
|
RoundSignificantDigitsFilter = sensor_ns.class_("RoundSignificantDigitsFilter", Filter)
|
||||||
|
|
||||||
validate_unit_of_measurement = cv.All(
|
validate_unit_of_measurement = cv.All(
|
||||||
cv.string_strict,
|
cv.string_strict,
|
||||||
@@ -900,6 +902,18 @@ async def round_multiple_filter_to_code(config, filter_id):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@FILTER_REGISTRY.register(
|
||||||
|
"round_to_significant_digits",
|
||||||
|
RoundSignificantDigitsFilter,
|
||||||
|
cv.int_range(min=1, max=6),
|
||||||
|
)
|
||||||
|
async def round_significant_digits_filter_to_code(config, filter_id):
|
||||||
|
return cg.new_Pvariable(
|
||||||
|
filter_id,
|
||||||
|
cg.TemplateArguments(config),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def build_filters(config):
|
async def build_filters(config):
|
||||||
return await cg.build_registry_list(FILTER_REGISTRY, config)
|
return await cg.build_registry_list(FILTER_REGISTRY, config)
|
||||||
|
|
||||||
|
|||||||
@@ -604,6 +604,19 @@ class RoundMultipleFilter : public Filter {
|
|||||||
float multiple_;
|
float multiple_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<uint8_t Digits> class RoundSignificantDigitsFilter : public Filter {
|
||||||
|
public:
|
||||||
|
optional<float> new_value(float value) override {
|
||||||
|
if (std::isfinite(value)) {
|
||||||
|
if (value == 0.0f)
|
||||||
|
return 0.0f;
|
||||||
|
float factor = pow10_int(Digits - 1 - ilog10(value));
|
||||||
|
return roundf(value * factor) / factor;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ToNTCResistanceFilter : public Filter {
|
class ToNTCResistanceFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
ToNTCResistanceFilter(double a, double b, double c) : a_(a), b_(b), c_(c) {}
|
ToNTCResistanceFilter(double a, double b, double c) : a_(a), b_(b), c_(c) {}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
#define USE_ENTITY_DEVICE_CLASS
|
#define USE_ENTITY_DEVICE_CLASS
|
||||||
#define USE_ENTITY_ICON
|
#define USE_ENTITY_ICON
|
||||||
#define USE_ENTITY_UNIT_OF_MEASUREMENT
|
#define USE_ENTITY_UNIT_OF_MEASUREMENT
|
||||||
|
#define USE_ESP32_BLE_PSRAM
|
||||||
#define USE_ESP32_CAMERA_JPEG_CONVERSION
|
#define USE_ESP32_CAMERA_JPEG_CONVERSION
|
||||||
#define USE_ESP32_HOSTED
|
#define USE_ESP32_HOSTED
|
||||||
#define USE_ESP32_IMPROV_STATE_CALLBACK
|
#define USE_ESP32_IMPROV_STATE_CALLBACK
|
||||||
|
|||||||
@@ -413,6 +413,23 @@ ParseOnOffState parse_on_off(const char *str, const char *on, const char *off) {
|
|||||||
return PARSE_NONE;
|
return PARSE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t ilog10(float value) {
|
||||||
|
float abs_val = fabsf(value);
|
||||||
|
int8_t exp = 0;
|
||||||
|
if (abs_val >= 10.0f) {
|
||||||
|
while (abs_val >= 10.0f) {
|
||||||
|
abs_val /= 10.0f;
|
||||||
|
exp++;
|
||||||
|
}
|
||||||
|
} else if (abs_val < 1.0f) {
|
||||||
|
while (abs_val < 1.0f) {
|
||||||
|
abs_val *= 10.0f;
|
||||||
|
exp--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exp;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void normalize_accuracy_decimals(float &value, int8_t &accuracy_decimals) {
|
static inline void normalize_accuracy_decimals(float &value, int8_t &accuracy_decimals) {
|
||||||
if (accuracy_decimals < 0) {
|
if (accuracy_decimals < 0) {
|
||||||
float divisor;
|
float divisor;
|
||||||
|
|||||||
@@ -740,6 +740,11 @@ template<size_t STACK_SIZE, typename T = uint8_t> class SmallBufferWithHeapFallb
|
|||||||
/// @name Mathematics
|
/// @name Mathematics
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
|
/// Compute floor(log10(fabs(value))) using iterative comparison.
|
||||||
|
/// Avoids pulling in __ieee754_logf/log10f (~1KB flash).
|
||||||
|
/// Only valid for finite, non-zero values.
|
||||||
|
int8_t ilog10(float value);
|
||||||
|
|
||||||
/// Compute 10^exp using iterative multiplication/division.
|
/// Compute 10^exp using iterative multiplication/division.
|
||||||
/// Avoids pulling in powf/__ieee754_powf (~2.3KB flash) for small integer exponents. // NOLINT
|
/// Avoids pulling in powf/__ieee754_powf (~2.3KB flash) for small integer exponents. // NOLINT
|
||||||
/// Matches powf(10, exp) for the int8_t exponent range used by sensor accuracy_decimals. // NOLINT
|
/// Matches powf(10, exp) for the int8_t exponent range used by sensor accuracy_decimals. // NOLINT
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <cmath>
|
||||||
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
|
||||||
|
TEST(HelpersTest, Ilog10PowersOfTen) {
|
||||||
|
EXPECT_EQ(ilog10(1.0f), 0);
|
||||||
|
EXPECT_EQ(ilog10(10.0f), 1);
|
||||||
|
EXPECT_EQ(ilog10(100.0f), 2);
|
||||||
|
EXPECT_EQ(ilog10(1000.0f), 3);
|
||||||
|
EXPECT_EQ(ilog10(10000.0f), 4);
|
||||||
|
EXPECT_EQ(ilog10(100000.0f), 5);
|
||||||
|
EXPECT_EQ(ilog10(0.1f), -1);
|
||||||
|
EXPECT_EQ(ilog10(0.001f), -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(HelpersTest, Ilog10General) {
|
||||||
|
EXPECT_EQ(ilog10(5.0f), 0);
|
||||||
|
EXPECT_EQ(ilog10(9.99f), 0);
|
||||||
|
EXPECT_EQ(ilog10(50.0f), 1);
|
||||||
|
EXPECT_EQ(ilog10(99.0f), 1);
|
||||||
|
EXPECT_EQ(ilog10(999.0f), 2);
|
||||||
|
EXPECT_EQ(ilog10(0.5f), -1);
|
||||||
|
EXPECT_EQ(ilog10(0.0072f), -3);
|
||||||
|
EXPECT_EQ(ilog10(120000.0f), 5);
|
||||||
|
EXPECT_EQ(ilog10(123456.789f), 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(HelpersTest, Ilog10Negative) {
|
||||||
|
EXPECT_EQ(ilog10(-1.0f), 0);
|
||||||
|
EXPECT_EQ(ilog10(-10.0f), 1);
|
||||||
|
EXPECT_EQ(ilog10(-0.1f), -1);
|
||||||
|
EXPECT_EQ(ilog10(-123.456f), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that ilog10 + pow10_int produces the same rounding result as log10/pow.
|
||||||
|
// ilog10 may differ from floor(log10f()) for values not exactly representable in float
|
||||||
|
// (e.g. 0.01f is 0.00999...), but the full round-trip must match.
|
||||||
|
TEST(HelpersTest, Ilog10RoundTripMatchesLog10) {
|
||||||
|
float values[] = {0.0072f, 0.05f, 0.1f, 0.5f, 1.0f, 3.14f, 9.99f, 10.0f, 42.0f, 100.0f,
|
||||||
|
1234.5f, 9999.0f, 10000.0f, 99999.0f, 120000.0f, 999999.0f, -1.0f, -0.1f, -123.456f, -10000.0f};
|
||||||
|
for (uint8_t digits = 1; digits <= 6; digits++) {
|
||||||
|
for (float v : values) {
|
||||||
|
// New implementation using ilog10 + pow10_int
|
||||||
|
float factor_new = pow10_int(digits - 1 - ilog10(v));
|
||||||
|
float result_new = roundf(v * factor_new) / factor_new;
|
||||||
|
|
||||||
|
// Reference using log10/pow
|
||||||
|
double factor_ref = pow(10.0, digits - std::ceil(std::log10(std::fabs(v))));
|
||||||
|
float result_ref = static_cast<float>(round(v * factor_ref) / factor_ref);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(result_new, result_ref) << "mismatch for value=" << v << " digits=" << (int) digits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace esphome
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
esp32_ble:
|
||||||
|
use_psram: true
|
||||||
|
|
||||||
|
psram:
|
||||||
@@ -1 +1,2 @@
|
|||||||
<<: !include common.yaml
|
<<: !include common.yaml
|
||||||
|
<<: !include common_use_psram.yaml
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<<: !include common.yaml
|
<<: !include common.yaml
|
||||||
|
<<: !include common_use_psram.yaml
|
||||||
|
|
||||||
esp32_ble:
|
esp32_ble:
|
||||||
io_capability: keyboard_only
|
io_capability: keyboard_only
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ packages:
|
|||||||
ble: !include ../../test_build_components/common/ble/esp32-p4-idf.yaml
|
ble: !include ../../test_build_components/common/ble/esp32-p4-idf.yaml
|
||||||
|
|
||||||
<<: !include common.yaml
|
<<: !include common.yaml
|
||||||
|
<<: !include common_use_psram.yaml
|
||||||
|
|
||||||
esp32_ble:
|
esp32_ble:
|
||||||
io_capability: keyboard_only
|
io_capability: keyboard_only
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ sensor:
|
|||||||
quantile: .9
|
quantile: .9
|
||||||
- round: 1
|
- round: 1
|
||||||
- round_to_multiple_of: 0.25
|
- round_to_multiple_of: 0.25
|
||||||
|
- round_to_significant_digits: 3
|
||||||
- skip_initial: 3
|
- skip_initial: 3
|
||||||
- sliding_window_moving_average:
|
- sliding_window_moving_average:
|
||||||
window_size: 15
|
window_size: 15
|
||||||
|
|||||||
Reference in New Issue
Block a user