Merge branch 'store-yaml-secret-helpers' into store-yaml-helpers-core

# Conflicts:
#	esphome/components/packages/__init__.py
This commit is contained in:
J. Nick Koston
2026-10-09 07:28:04 -10:00
1992 changed files with 5438 additions and 2131 deletions
+25 -23
View File
@@ -286,7 +286,7 @@ jobs:
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
- name: Run prek
uses: j178/prek-action@4e14d07f9231acabce116ccfca13b13dd9755ece # v3.0.0
uses: j178/prek-action@1382ad72dea72f9d53832f2bcb65b3e87a947204 # v3.0.1
with:
prek-version: ${{ steps.prek.outputs.version }}
# This job only runs on pull requests, so nothing ever populates
@@ -893,14 +893,20 @@ jobs:
matrix:
include:
- id: clang-tidy
name: Run script/clang-tidy for ESP32 IDF 1/3
options: --environment esp32-idf-tidy --split-num 3 --split-at 1
name: Run script/clang-tidy for ESP32 IDF 1/5
options: --environment esp32-idf-tidy --split-num 5 --split-at 1
- id: clang-tidy
name: Run script/clang-tidy for ESP32 IDF 2/3
options: --environment esp32-idf-tidy --split-num 3 --split-at 2
name: Run script/clang-tidy for ESP32 IDF 2/5
options: --environment esp32-idf-tidy --split-num 5 --split-at 2
- id: clang-tidy
name: Run script/clang-tidy for ESP32 IDF 3/3
options: --environment esp32-idf-tidy --split-num 3 --split-at 3
name: Run script/clang-tidy for ESP32 IDF 3/5
options: --environment esp32-idf-tidy --split-num 5 --split-at 3
- id: clang-tidy
name: Run script/clang-tidy for ESP32 IDF 4/5
options: --environment esp32-idf-tidy --split-num 5 --split-at 4
- id: clang-tidy
name: Run script/clang-tidy for ESP32 IDF 5/5
options: --environment esp32-idf-tidy --split-num 5 --split-at 5
steps:
- name: Check out code from GitHub
@@ -1416,31 +1422,27 @@ jobs:
echo "::warning::ci_memory_impact_extract.py not found on target branch, skipping memory impact analysis"
fi
# Check if test files exist on the target branch for the requested
# components and platform. When a PR adds new test files for a platform,
# the target branch won't have them yet, so skip instead of failing.
# This check must be done here (not in determine-jobs.py) because
# determine-jobs runs on the PR branch and cannot see what the target
# branch has.
# The build below uses --base-only, so skip unless the target branch has
# test.<platform>.yaml for every requested component (test-*.yaml
# variants alone compile nothing, and a partial set would compare a
# smaller target build against the PR build). Checked here, not in
# determine-jobs.py, because determine-jobs runs on the PR branch and
# cannot see the target branch.
- name: Check for test files on target branch
id: check-tests
if: steps.check-script.outputs.skip != 'true'
run: |
components='${{ toJSON(fromJSON(needs.determine-jobs.outputs.memory_impact).components) }}'
platform="${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}"
found=false
missing=""
for component in $(echo "$components" | jq -r '.[]'); do
# Check for test files matching the platform (test.platform.yaml or test-*.platform.yaml)
for f in tests/components/${component}/test*.${platform}.yaml; do
if [ -f "$f" ]; then
found=true
break 2
fi
done
if [ ! -f "tests/components/${component}/test.${platform}.yaml" ]; then
missing="${missing} ${component}"
fi
done
if [ "$found" = false ]; then
if [ -n "$missing" ]; then
echo "skip=true" >> $GITHUB_OUTPUT
echo "::warning::No test files found on target branch for platform ${platform}, skipping memory impact analysis"
echo "::warning::No test.${platform}.yaml on target branch for${missing}, skipping memory impact analysis"
else
echo "skip=false" >> $GITHUB_OUTPUT
fi
+12
View File
@@ -177,6 +177,13 @@ file does, and it is the authority when they disagree. The most useful starting
Pick the primitive by cadence: under 250 ms use a gated `loop()`; 500 ms and above use
`set_interval`. Full reasoning, including why `set_interval` costs more below 500 ms:
https://developers.esphome.io/architecture/components/advanced/#quick-rule-of-thumb
* **Scheduler ids:** name a timer only when it must be cancelled or replaced, and use a
`static constexpr uint32_t` id, never a string. Ids are per component instance and cannot clash with other
components, so number them from 0 and keep all of a component's ids together in one place.
```cpp
static constexpr uint32_t READ_TIMEOUT_ID = 0;
this->set_timeout(READ_TIMEOUT_ID, 50, [this]() { this->read_(); });
```
* **Don't override a default with the same value:** if a base class method already returns what you
want, do not override it. `Component::get_setup_priority()` returns `setup_priority::DATA`, so a
component that wants `DATA` should simply leave it alone.
@@ -230,6 +237,10 @@ file does, and it is the authority when they disagree. The most useful starting
```
* **Component Metadata:**
- `DOMAIN`: Required in every component's `__init__.py`, set to the component's own name as a plain
string (e.g. `DOMAIN = "my_component"`). Other code refers to the component through it, e.g.
`from esphome.components.my_component import DOMAIN`. Keep it in alphabetical order with the other
metadata constants. CI (`lint_component_domain`) fails without it.
- `DEPENDENCIES`: List of required components
- `AUTO_LOAD`: Components to automatically load
- `CONFLICTS_WITH`: Incompatible components
@@ -243,6 +254,7 @@ file does, and it is the authority when they disagree. The most useful starting
import esphome.config_validation as cv
from esphome.const import CONF_KEY, CONF_ID
DOMAIN = "my_component"
CONF_PARAM = "param" # A constant that does not yet exist in esphome/const.py
my_component_ns = cg.esphome_ns.namespace("my_component")
+2
View File
@@ -188,6 +188,7 @@ esphome/components/esp32_rmt_led_strip/* @jesserockz
esphome/components/esp8266/* @esphome/core
esphome/components/esp_ldo/* @clydebarrow
esphome/components/espectre/* @francescopace
esphome/components/esphome/ota/* @esphome/core
esphome/components/espnow/* @jesserockz
esphome/components/espnow/packet_transport/* @EasilyBoredEngineer
esphome/components/ethernet_info/* @gtjadsonsantos
@@ -518,6 +519,7 @@ esphome/components/sound_level/* @kahrendt
esphome/components/spa06_base/* @danielkent-net
esphome/components/spa06_i2c/* @danielkent-net
esphome/components/spa06_spi/* @danielkent-net
esphome/components/spd2010/* @grischard
esphome/components/speaker/* @jesserockz @kahrendt
esphome/components/speaker/media_player/* @kahrendt @synesthesiam
esphome/components/speaker_source/* @kahrendt
+14 -14
View File
@@ -49,40 +49,40 @@ class FrameworkRelease(NamedTuple):
# Arduino core version -> its build in esphome-libs/arduino-esp8266
FRAMEWORK_RELEASES: dict[Version, FrameworkRelease] = {
Version(3, 1, 2): FrameworkRelease(
"3.1.2-esphome.1",
"e80751e3123676b967143e39c61f2d8693946db4c7806f2a83dcaaf797ecd582",
37189311,
"3.1.2-esphome.3",
"3af533a85163804e164500a5b254dc23b922080e25ecb7dc37b3dd8ac84651db",
37185650,
),
}
TOOLCHAIN_PACKAGE = "toolchain-xtensa-lx106-elf"
# gcc 10.3, the toolchain Arduino core 3.x builds with; the build
# generator's compile flags are tuned to it.
TOOLCHAIN_VERSION = "10.3.0-esphome.2"
TOOLCHAIN_VERSION = "10.3.0-esphome.3"
_TOOLCHAIN_RELEASES = (
"https://github.com/esphome-libs/xtensa-lx106-elf-toolchain/releases/"
)
# Registry system tag -> (sha256, size) of that host's archive
TOOLCHAIN_BUILDS: dict[str, tuple[str, int]] = {
"darwin_arm64": (
"849cede44d4d5c6ea0f14099783239f559f46327bea314281814f2652b486201",
60830321,
"ad0ea929238d9b527c43e0d20257acc2a5680bdb0d2b1cf8f2c99169786217e9",
60747260,
),
"darwin_x86_64": (
"ca69904daabf0c5983b372423e5e62f49182a793e992c052e94666852470c897",
64149487,
"997090cac80c8eb59604ec52b73fb3568e5f2d9b2971f83c3f2a5c545c9c949c",
64065752,
),
"linux_aarch64": (
"60a49a4f082bf246544bd409a9517dbbcab19bb30ac9decbee544b896aaccbd6",
67573397,
"403f14d0d5755682fcd6eaea1e4c457a1d8cad30690e52fb0c804d8db266b908",
67487067,
),
"linux_x86_64": (
"1fba33ca1494ec79f2776e0e37eca93282d30f8bb9992f5f4f9a655d6fff1db4",
68431336,
"64f21fa3ba736b363dc8c234dbbb39e005e574e33de08a78e9a00c55a64ae706",
68343668,
),
"windows_amd64": (
"af9066b0e5bf036f04f2bd9d08b89b81a7f183c57dac0abcaff71dd861cf5f3b",
67664137,
"1e62abf8df041ce5158f5770dffef955f2f981ce7f7adee88fcd5a8197705aa6",
67536405,
),
}
+41 -26
View File
@@ -54,6 +54,7 @@ from esphome.components.esp8266.const import (
KEY_ESP8266,
KEY_FLASH_SIZE,
KEY_SCANF_FLOAT,
THROW_STUBS_HEADER,
)
from esphome.core import CORE, EsphomeError
from esphome.framework_helpers import get_project_cxx_compile_flags
@@ -1087,32 +1088,8 @@ def write_project(paths: InstalledPaths, ccache: str | None) -> bool:
if "USE_ESP8266_WAVEFORM_STUBS" in flag_defines:
core_exclude |= _CORE_EXCLUDE_WAVEFORM
archives = []
# variant_dir existence was already enforced with the include dirs
variant_sources = collect_sources(variant_dir)
if variant_sources:
objs = compile_edges(lines, variant_sources, variant_dir, "variant")
lines.append(f"build libFrameworkArduinoVariant.a: ar {' '.join(objs)}")
archives.append("libFrameworkArduinoVariant.a")
core_objs = compile_edges(
lines, collect_sources(core_dir, core_exclude), core_dir, "core"
)
if not core_objs:
# An empty archive would link into a wall of undefined references
# (app_entry, the exception vectors) far from the cause
raise EsphomeError(
f"{_INCOMPLETE_INSTALL}: no core sources in {core_dir}; {_CLEAN_HINT}"
)
lines.append(f"build libFrameworkArduino.a: ar {' '.join(core_objs)}")
archives.append("libFrameworkArduino.a")
lib_archives, direct_objs = library_edges(lines, libraries)
archives += lib_archives
# One source of truth with the PlatformIO path: esp8266/__init__ pins
# build_src_flags (the throw_stubs force-include); -include paths
# resolve against the source root
# esp8266/__init__ pins build_src_flags (the throw_stubs force-include), as on
# the PlatformIO path; -include paths resolve against the source root
src_other: list[str] = []
src_includes: list[str] = []
src_it = iter(
@@ -1131,7 +1108,45 @@ def write_project(paths: InstalledPaths, ccache: str | None) -> bool:
src_includes.append(tok[len("-include") :])
else:
src_other.append(_shell_token(tok))
# The throw stubs abort: none anywhere with exceptions on, else the core and
# libraries get them too (src keeps them after its pch include)
if config.exceptions:
src_includes = [h for h in src_includes if h != THROW_STUBS_HEADER]
include_flags = [f"-include {_q(src_dir / h)}" for h in src_includes]
framework_flags = ""
if THROW_STUBS_HEADER in src_includes:
stubs_flag = include_flags[src_includes.index(THROW_STUBS_HEADER)]
lines.append(f"frameworkflags = {stubs_flag}")
framework_flags = "$frameworkflags"
archives = []
# variant_dir existence was already enforced with the include dirs
variant_sources = collect_sources(variant_dir)
if variant_sources:
objs = compile_edges(
lines, variant_sources, variant_dir, "variant", flags=framework_flags
)
lines.append(f"build libFrameworkArduinoVariant.a: ar {' '.join(objs)}")
archives.append("libFrameworkArduinoVariant.a")
core_objs = compile_edges(
lines,
collect_sources(core_dir, core_exclude),
core_dir,
"core",
flags=framework_flags,
)
if not core_objs:
# An empty archive would link into a wall of undefined references
# (app_entry, the exception vectors) far from the cause
raise EsphomeError(
f"{_INCOMPLETE_INSTALL}: no core sources in {core_dir}; {_CLEAN_HINT}"
)
lines.append(f"build libFrameworkArduino.a: ar {' '.join(core_objs)}")
archives.append("libFrameworkArduino.a")
lib_archives, direct_objs = library_edges(lines, libraries, framework_flags)
archives += lib_archives
# One shared variable instead of repeating the flags line on every src
# edge (hundreds of edges in a real project)
lines.append(f"srcflags = {' '.join(src_other + include_flags)}")
+4 -2
View File
@@ -207,10 +207,12 @@ def compile_edges(
def library_edges(
lines: list[str], libraries: list[ArduinoLibrary]
lines: list[str], libraries: list[ArduinoLibrary], extra_flags: str = ""
) -> tuple[list[str], list[str]]:
"""Emit every library's compile and archive edges.
``extra_flags`` (raw ninja text) precede each library's own flags.
Returns the archive names and the objects that link directly. A
library's own include dirs lead its compile lines, as PlatformIO searched
them first: the include path is one global list, so another library's
@@ -232,7 +234,7 @@ def library_edges(
lib.sources,
common_parent(lib.sources),
f"lib/{lib.name}",
flags=" ".join(_shell_token(f) for f in lib.flags),
flags=" ".join(filter(None, [extra_flags, *map(_shell_token, lib.flags)])),
own_includes=" ".join(f"-I{_q(d)}" for d in lib.include_dirs),
)
if not lib.lib_archive:
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@MrSuicideParrot"]
DOMAIN = "a01nyub"
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::a01nyub {
static const char *const TAG = "a01nyub.sensor";
ESPHOME_LOG_TAG(TAG, "a01nyub.sensor");
void A01nyubComponent::loop() {
uint8_t data;
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@TH-Braemer"]
DOMAIN = "a02yyuw"
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::a02yyuw {
static const char *const TAG = "a02yyuw.sensor";
ESPHOME_LOG_TAG(TAG, "a02yyuw.sensor");
void A02yyuwComponent::loop() {
uint8_t data;
+1
View File
@@ -0,0 +1 @@
DOMAIN = "a4988"
+1 -1
View File
@@ -3,7 +3,7 @@
namespace esphome::a4988 {
static const char *const TAG = "a4988.stepper";
ESPHOME_LOG_TAG(TAG, "a4988.stepper");
void A4988::setup() {
if (this->sleep_pin_ != nullptr) {
@@ -1 +1,2 @@
CODEOWNERS = ["@DAVe3283"]
DOMAIN = "absolute_humidity"
@@ -3,7 +3,7 @@
namespace esphome::absolute_humidity {
static const char *const TAG{"absolute_humidity.sensor"};
ESPHOME_LOG_TAG(TAG, "absolute_humidity.sensor");
void AbsoluteHumidityComponent::setup() {
this->temperature_sensor_->add_on_state_callback([this](float state) {
+1
View File
@@ -0,0 +1 @@
DOMAIN = "ac_dimmer"
+1 -1
View File
@@ -14,7 +14,7 @@
namespace esphome::ac_dimmer {
static const char *const TAG = "ac_dimmer";
ESPHOME_LOG_TAG(TAG, "ac_dimmer");
// Global array to store dimmer objects
static AcDimmerDataStore *all_dimmers[32]; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
@@ -9,7 +9,7 @@
#include "esp_clk_tree.h"
#include "soc/clk_tree_defs.h"
static const char *const TAG = "hw_timer_esp_idf";
ESPHOME_LOG_TAG(TAG, "hw_timer_esp_idf");
namespace esphome::ac_dimmer {
+1
View File
@@ -9,6 +9,7 @@ from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
DEPENDENCIES = ["uart"]
DOMAIN = "adalight"
adalight_ns = cg.esphome_ns.namespace("adalight")
AdalightLightEffect = adalight_ns.class_(
@@ -3,7 +3,7 @@
namespace esphome::adalight {
static const char *const TAG = "adalight_light_effect";
ESPHOME_LOG_TAG(TAG, "adalight_light_effect");
static const uint32_t ADALIGHT_ACK_INTERVAL = 1000;
static const uint32_t ADALIGHT_RECEIVE_TIMEOUT = 1000;
+1
View File
@@ -22,6 +22,7 @@ from esphome.core import CORE
from esphome.types import ConfigType
CODEOWNERS = ["@esphome/core"]
DOMAIN = "adc"
adc_ns = cg.esphome_ns.namespace("adc")
+1 -1
View File
@@ -3,7 +3,7 @@
namespace esphome::adc {
static const char *const TAG = "adc";
ESPHOME_LOG_TAG(TAG, "adc");
const LogString *sampling_mode_to_str(SamplingMode mode) {
switch (mode) {
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::adc {
static const char *const TAG = "adc";
ESPHOME_LOG_TAG(TAG, "adc");
adc_oneshot_unit_handle_t ADCSensor::shared_adc_handles[2] = {nullptr, nullptr};
@@ -13,7 +13,7 @@ ADC_MODE(ADC_VCC)
namespace esphome::adc {
static const char *const TAG = "adc";
ESPHOME_LOG_TAG(TAG, "adc");
void ADCSensor::setup() {
#ifndef USE_ADC_SENSOR_VCC
@@ -5,7 +5,7 @@
namespace esphome::adc {
static const char *const TAG = "adc";
ESPHOME_LOG_TAG(TAG, "adc");
void ADCSensor::setup() {
#ifndef USE_ADC_SENSOR_VCC
+1 -1
View File
@@ -17,7 +17,7 @@
namespace esphome::adc {
static const char *const TAG = "adc";
ESPHOME_LOG_TAG(TAG, "adc");
// The on-die temperature sensor sits on the last ADC channel: input 4 on RP2040
// and RP2350A, but input 8 on RP2350B, which has eight external channels rather
+1 -1
View File
@@ -7,7 +7,7 @@
namespace esphome::adc {
static const char *const TAG = "adc";
ESPHOME_LOG_TAG(TAG, "adc");
void ADCSensor::setup() {
if (!adc_is_ready_dt(this->channel_)) {
@@ -5,6 +5,7 @@ from esphome.const import CONF_ID
from esphome.types import ConfigType
DEPENDENCIES = ["spi"]
DOMAIN = "adc128s102"
MULTI_CONF = True
CODEOWNERS = ["@DeerMaximum"]
+1 -1
View File
@@ -3,7 +3,7 @@
namespace esphome::adc128s102 {
static const char *const TAG = "adc128s102";
ESPHOME_LOG_TAG(TAG, "adc128s102");
float ADC128S102::get_setup_priority() const { return setup_priority::HARDWARE; }
@@ -4,7 +4,7 @@
namespace esphome::adc128s102 {
static const char *const TAG = "adc128s102.sensor";
ESPHOME_LOG_TAG(TAG, "adc128s102.sensor");
ADC128S102Sensor::ADC128S102Sensor(uint8_t channel) : channel_(channel) {}
@@ -0,0 +1 @@
DOMAIN = "addressable_light"
@@ -3,7 +3,7 @@
namespace esphome::addressable_light {
static const char *const TAG = "addressable_light.display";
ESPHOME_LOG_TAG(TAG, "addressable_light.display");
int AddressableLightDisplay::get_width_internal() { return this->width_; }
int AddressableLightDisplay::get_height_internal() { return this->height_; }
+1
View File
@@ -0,0 +1 @@
DOMAIN = "ade7880"
+1 -1
View File
@@ -15,7 +15,7 @@
namespace esphome::ade7880 {
static const char *const TAG = "ade7880";
ESPHOME_LOG_TAG(TAG, "ade7880");
void IRAM_ATTR ADE7880Store::gpio_intr(ADE7880Store *arg) { arg->reset_done = true; }
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@angelnu"]
DOMAIN = "ade7953"
@@ -27,6 +27,7 @@ from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
CODEOWNERS = ["@angelnu"]
DOMAIN = "ade7953_base"
CONF_CURRENT_A = "current_a"
CONF_CURRENT_B = "current_b"
@@ -5,7 +5,7 @@
namespace esphome::ade7953_base {
static const char *const TAG = "ade7953";
ESPHOME_LOG_TAG(TAG, "ade7953");
constexpr uint16_t CONFIG_DEFAULT = 0x8004u;
constexpr uint16_t CONFIG_LOCK_BIT = 0x8000u;
@@ -1 +1,2 @@
CODEOWNERS = ["@angelnu"]
DOMAIN = "ade7953_i2c"
@@ -4,7 +4,7 @@
namespace esphome::ade7953_i2c {
static const char *const TAG = "ade7953";
ESPHOME_LOG_TAG(TAG, "ade7953");
void AdE7953I2c::dump_config() {
ESP_LOGCONFIG(TAG, "ADE7953_i2c:");
@@ -1 +1,2 @@
CODEOWNERS = ["@angelnu"]
DOMAIN = "ade7953_spi"
@@ -4,7 +4,7 @@
namespace esphome::ade7953_spi {
static const char *const TAG = "ade7953";
ESPHOME_LOG_TAG(TAG, "ade7953");
// Datasheet requires at least 1.2µs after clearing CONFIG LOCK_BIT before raising CS
constexpr uint8_t CONFIG_LOCK_SETTLE_US = 2;
+1
View File
@@ -5,6 +5,7 @@ from esphome.const import CONF_ID
from esphome.types import ConfigType
DEPENDENCIES = ["i2c"]
DOMAIN = "ads1115"
MULTI_CONF = True
ads1115_ns = cg.esphome_ns.namespace("ads1115")
+1 -1
View File
@@ -4,7 +4,7 @@
namespace esphome::ads1115 {
static const char *const TAG = "ads1115";
ESPHOME_LOG_TAG(TAG, "ads1115");
static const uint8_t ADS1115_REGISTER_CONVERSION = 0x00;
static const uint8_t ADS1115_REGISTER_CONFIG = 0x01;
@@ -4,7 +4,7 @@
namespace esphome::ads1115 {
static const char *const TAG = "ads1115.sensor";
ESPHOME_LOG_TAG(TAG, "ads1115.sensor");
float ADS1115Sensor::sample() {
return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_, this->samplerate_);
+1
View File
@@ -6,6 +6,7 @@ from esphome.types import ConfigType
CODEOWNERS = ["@solomondg1"]
DEPENDENCIES = ["spi"]
DOMAIN = "ads1118"
MULTI_CONF = True
CONF_ADS1118_ID = "ads1118_id"
+1 -1
View File
@@ -4,7 +4,7 @@
namespace esphome::ads1118 {
static const char *const TAG = "ads1118";
ESPHOME_LOG_TAG(TAG, "ads1118");
static const uint8_t ADS1118_DATA_RATE_860_SPS = 0b111;
void ADS1118::setup() {
@@ -4,7 +4,7 @@
namespace esphome::ads1118 {
static const char *const TAG = "ads1118.sensor";
ESPHOME_LOG_TAG(TAG, "ads1118.sensor");
void ADS1118Sensor::dump_config() {
LOG_SENSOR(" ", "ADS1118 Sensor", this);
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@mak-42"]
DOMAIN = "ags10"
+1 -1
View File
@@ -4,7 +4,7 @@
#include <cinttypes>
namespace esphome::ags10 {
static const char *const TAG = "ags10";
ESPHOME_LOG_TAG(TAG, "ags10");
// Data acquisition.
static const uint8_t REG_TVOC = 0x00;
+1
View File
@@ -0,0 +1 @@
DOMAIN = "aht10"
+1 -1
View File
@@ -19,7 +19,7 @@
namespace esphome::aht10 {
static const char *const TAG = "aht10";
ESPHOME_LOG_TAG(TAG, "aht10");
static const uint8_t AHT10_INITIALIZE_CMD[] = {0xE1, 0x08, 0x00};
static const uint8_t AHT20_INITIALIZE_CMD[] = {0xBE, 0x08, 0x00};
static const uint8_t AHT10_MEASURE_CMD[] = {0xAC, 0x33, 0x00};
+1
View File
@@ -0,0 +1 @@
DOMAIN = "aic3204"
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::aic3204 {
static const char *const TAG = "aic3204";
ESPHOME_LOG_TAG(TAG, "aic3204");
#define ERROR_CHECK(err, msg) \
if (!(err)) { \
@@ -6,6 +6,7 @@ from esphome.types import ConfigType
AUTO_LOAD = ["ble_device_base"]
CODEOWNERS = ["@jeromelaban"]
DOMAIN = "airthings_ble"
airthings_ble_ns = cg.esphome_ns.namespace("airthings_ble")
AirthingsListener = airthings_ble_ns.class_(
@@ -4,7 +4,7 @@
namespace esphome::airthings_ble {
static const char *const TAG = "airthings_ble";
ESPHOME_LOG_TAG(TAG, "airthings_ble");
bool AirthingsListener::parse_device(const ble_device_base::ESPBTDevice &device) {
for (auto &it : device.get_manufacturer_datas()) {
@@ -24,6 +24,7 @@ from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
CODEOWNERS = ["@ncareau", "@jeromelaban"]
DOMAIN = "airthings_wave_base"
DEPENDENCIES = ["ble_client"]
@@ -8,7 +8,10 @@
namespace esphome::airthings_wave_base {
static const char *const TAG = "airthings_wave_base";
ESPHOME_LOG_TAG(TAG, "airthings_wave_base");
static constexpr uint32_t BATTERY_READ_TIMEOUT_ID = 0;
static constexpr uint32_t RESPONSE_TIMEOUT_ID = 1;
void AirthingsWaveBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
esp_ble_gattc_cb_param_t *param) {
@@ -181,7 +184,7 @@ void AirthingsWaveBase::read_battery_(uint8_t *raw_value, uint16_t value_len) {
// read the battery again at the configured update interval
if (this->battery_update_interval_ != this->update_interval_) {
this->read_battery_next_update_ = false;
this->set_timeout("battery", this->battery_update_interval_,
this->set_timeout(BATTERY_READ_TIMEOUT_ID, this->battery_update_interval_,
[this]() { this->read_battery_next_update_ = true; });
}
}
@@ -204,7 +207,7 @@ void AirthingsWaveBase::response_received_() {
}
void AirthingsWaveBase::set_response_timeout_() {
this->set_timeout("response_timeout", 30 * 1000, [this]() {
this->set_timeout(RESPONSE_TIMEOUT_ID, 30 * 1000, [this]() {
this->responses_pending_ = 1;
this->response_received_();
});
@@ -1 +1,2 @@
CODEOWNERS = ["@ncareau"]
DOMAIN = "airthings_wave_mini"
@@ -4,7 +4,7 @@
namespace esphome::airthings_wave_mini {
static const char *const TAG = "airthings_wave_mini";
ESPHOME_LOG_TAG(TAG, "airthings_wave_mini");
void AirthingsWaveMini::read_sensors(uint8_t *raw_value, uint16_t value_len) {
auto *value = (WaveMiniReadings *) raw_value;
@@ -1 +1,2 @@
CODEOWNERS = ["@jeromelaban", "@precurse"]
DOMAIN = "airthings_wave_plus"
@@ -4,7 +4,7 @@
namespace esphome::airthings_wave_plus {
static const char *const TAG = "airthings_wave_plus";
ESPHOME_LOG_TAG(TAG, "airthings_wave_plus");
void AirthingsWavePlus::read_sensors(uint8_t *raw_value, uint16_t value_len) {
auto *value = (WavePlusReadings *) raw_value;
@@ -21,6 +21,7 @@ from esphome.core.entity_helpers import (
from esphome.cpp_generator import MockObjClass
CODEOWNERS = ["@grahambrown11", "@hwstar"]
DOMAIN = "alarm_control_panel"
IS_PLATFORM_COMPONENT = True
CONF_ON_TRIGGERED = "on_triggered"
@@ -10,7 +10,7 @@
namespace esphome::alarm_control_panel {
static const char *const TAG = "alarm_control_panel";
ESPHOME_LOG_TAG(TAG, "alarm_control_panel");
AlarmControlPanelCall AlarmControlPanel::make_call() { return AlarmControlPanelCall(this); }
@@ -6,7 +6,7 @@
namespace esphome::alarm_control_panel {
static const char *const TAG = "alarm_control_panel";
ESPHOME_LOG_TAG(TAG, "alarm_control_panel");
AlarmControlPanelCall::AlarmControlPanelCall(AlarmControlPanel *parent) : parent_(parent) {}
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@jan-hofmeier"]
DOMAIN = "alpha3"
+1 -1
View File
@@ -7,7 +7,7 @@
namespace esphome::alpha3 {
static const char *const TAG = "alpha3";
ESPHOME_LOG_TAG(TAG, "alpha3");
void Alpha3::dump_config() {
ESP_LOGCONFIG(TAG, "ALPHA3");
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@swoboda1337"]
DOMAIN = "am2315c"
+1 -1
View File
@@ -26,7 +26,7 @@
namespace esphome::am2315c {
static const char *const TAG = "am2315c";
ESPHOME_LOG_TAG(TAG, "am2315c");
bool AM2315C::reset_register_(uint8_t reg) {
// code based on demo code sent by www.aosong.com
+1
View File
@@ -0,0 +1 @@
DOMAIN = "am2320"
+1 -1
View File
@@ -10,7 +10,7 @@
namespace esphome::am2320 {
static const char *const TAG = "am2320";
ESPHOME_LOG_TAG(TAG, "am2320");
void AM2320Component::update() {
uint8_t data[8];
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@buxtronix"]
DOMAIN = "am43"
+1 -1
View File
@@ -5,7 +5,7 @@
namespace esphome::am43 {
static const char *const TAG = "am43_cover";
ESPHOME_LOG_TAG(TAG, "am43_cover");
using namespace esphome::cover;
@@ -6,7 +6,7 @@
namespace esphome::am43 {
static const char *const TAG = "am43";
ESPHOME_LOG_TAG(TAG, "am43");
void Am43::dump_config() {
ESP_LOGCONFIG(TAG, "AM43");
@@ -1 +1,2 @@
CODEOWNERS = ["@ianchi"]
DOMAIN = "analog_threshold"
@@ -3,7 +3,7 @@
namespace esphome::analog_threshold {
static const char *const TAG = "analog_threshold.binary_sensor";
ESPHOME_LOG_TAG(TAG, "analog_threshold.binary_sensor");
void AnalogThresholdBinarySensor::setup() {
float sensor_value = this->sensor_->get_state();
+1
View File
@@ -0,0 +1 @@
DOMAIN = "anova"
+1 -1
View File
@@ -5,7 +5,7 @@
namespace esphome::anova {
static const char *const TAG = "anova";
ESPHOME_LOG_TAG(TAG, "anova");
using namespace esphome::climate;
+1
View File
@@ -2,3 +2,4 @@
# https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf
CODEOWNERS = ["@aodrenah"]
DOMAIN = "apds9306"
+1 -1
View File
@@ -7,7 +7,7 @@
namespace esphome::apds9306 {
static const char *const TAG = "apds9306";
ESPHOME_LOG_TAG(TAG, "apds9306");
enum { // APDS9306 registers
APDS9306_MAIN_CTRL = 0x00,
+1
View File
@@ -5,6 +5,7 @@ from esphome.const import CONF_ID
from esphome.types import ConfigType
DEPENDENCIES = ["i2c"]
DOMAIN = "apds9960"
MULTI_CONF = True
CONF_APDS9960_ID = "apds9960_id"
+1 -1
View File
@@ -4,7 +4,7 @@
namespace esphome::apds9960 {
static const char *const TAG = "apds9960";
ESPHOME_LOG_TAG(TAG, "apds9960");
#define APDS9960_ERROR_CHECK(func) \
if (!(func)) { \
+2 -1
View File
@@ -8,6 +8,7 @@ from esphome.automation import Condition
import esphome.codegen as cg
from esphome.components.const import CONF_DESCRIPTION, CONF_HOST
from esphome.components.logger import request_log_listener
from esphome.components.network import DOMAIN as NETWORK_DOMAIN
# ENCRYPTION_SCHEMA and validate_encryption_key are re-exported for external
# components and downstream consumers that import them from api
@@ -514,7 +515,7 @@ def _validate_outgoing_host_ipv6(config: ConfigType) -> ConfigType:
or host.version != 6
):
return config
network_conf = fv.full_config.get().get("network") or {}
network_conf = fv.full_config.get().get(NETWORK_DOMAIN) or {}
if not network_conf.get(CONF_ENABLE_IPV6):
raise cv.Invalid(
"outgoing_connection host is an IPv6 address but IPv6 is not "
+39
View File
@@ -81,6 +81,8 @@ service APIConnection {
rpc subscribe_serial_proxy_identity(SubscribeSerialProxyIdentityRequest) returns (void) {}
rpc serial_proxy_request(SerialProxyRequest) returns (void) {}
rpc serial_proxy_set_mode(SerialProxySetModeRequest) returns (void) {}
rpc sendspin_pairing_token(SendspinPairingTokenRequest) returns (SendspinPairingTokenResponse) {}
}
@@ -398,6 +400,11 @@ message WizardCapabilities {
bool configured = 1;
}
message SendspinCapabilities {
// Bitmask of the Sendspin features this device supports
uint32 feature_flags = 1;
}
message DeviceCapabilitiesResponse {
option (id) = 150;
option (source) = SOURCE_SERVER;
@@ -408,6 +415,7 @@ message DeviceCapabilitiesResponse {
repeated SerialProxyInfo serial_proxies = 4
[(field_ifdef) = "USE_SERIAL_PROXY", (fixed_array_size_define) = "SERIAL_PROXY_COUNT"];
WizardCapabilities wizard = 5 [(field_ifdef) = "USE_API_WIZARD"];
SendspinCapabilities sendspin = 6 [(field_ifdef) = "USE_SENDSPIN"];
}
// ==================== DEVICE WIZARD ====================
@@ -3069,3 +3077,34 @@ message BluetoothSetConnectionParamsResponse {
uint64 address = 1;
int32 error = 2;
}
// ==================== SENDSPIN ====================
enum SendspinPairingTokenStatus {
// The Sendspin client has not started yet, so the token does not exist yet. Ask again later.
SENDSPIN_PAIRING_TOKEN_STATUS_NOT_READY = 0;
SENDSPIN_PAIRING_TOKEN_STATUS_OK = 1;
// The device has no API encryption key, so it will not send the token. Ask again once a key is set.
SENDSPIN_PAIRING_TOKEN_STATUS_ENCRYPTION_REQUIRED = 2;
// Sendspin is turned off and has not started since boot, so the token does not exist yet.
SENDSPIN_PAIRING_TOKEN_STATUS_DISABLED = 3;
// The Sendspin client failed to start, and will not start until the device reboots.
SENDSPIN_PAIRING_TOKEN_STATUS_FAILED = 4;
}
// Requests the Sendspin pairing token, which a Sendspin server uses to pair with this device
message SendspinPairingTokenRequest {
option (id) = 159;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_SENDSPIN";
// Empty
}
message SendspinPairingTokenResponse {
option (id) = 160;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_SENDSPIN";
SendspinPairingTokenStatus status = 1;
// The pairing token (Sendspin pairing.md "Pairing Token"). Set only when status is OK.
string token = 2 [(max_data_length) = 127];
}
+42 -2
View File
@@ -48,6 +48,9 @@
#ifdef USE_ZWAVE_PROXY
#include "esphome/components/zwave_proxy/zwave_proxy.h"
#endif
#if defined(USE_SENDSPIN) && defined(USE_ESP_IDF)
#include "esphome/components/sendspin/sendspin_hub.h"
#endif
#ifdef USE_WATER_HEATER
#include "esphome/components/water_heater/water_heater.h"
#endif
@@ -88,7 +91,7 @@ static_assert(sizeof(ESPHOME_VERSION) - 1 <= 32, "Update max_data_length for esp
static_assert(ESPHOME_DEVICE_NAME_MAX_LEN <= 31, "Update max_data_length for name in api.proto");
static_assert(ESPHOME_FRIENDLY_NAME_MAX_LEN <= 120, "Update max_data_length for friendly_name in api.proto");
static const char *const TAG = "api.connection";
ESPHOME_LOG_TAG(TAG, "api.connection");
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_WARN
void log_dropped_message(const char *tag, int line, const LogString *what) {
@@ -1402,6 +1405,40 @@ void APIConnection::on_z_wave_proxy_request(const ZWaveProxyRequest &msg) {
}
#endif
#if defined(USE_SENDSPIN) && defined(USE_ESP_IDF)
bool APIConnection::send_sendspin_pairing_token_response_() {
SendspinPairingTokenResponse resp;
#ifdef USE_API_NOISE
// has_psk() stands in for "this session proved the key": with a key active, plaintext and zero-key sessions
// never reach hello, and activating a key closes every session opened before it.
if (!this->parent_->get_noise_ctx().has_psk()) {
resp.status = enums::SENDSPIN_PAIRING_TOKEN_STATUS_ENCRYPTION_REQUIRED;
return this->send_message(resp);
}
auto token = sendspin_::global_sendspin_hub->get_pairing_token();
if (token.has_value()) {
resp.status = enums::SENDSPIN_PAIRING_TOKEN_STATUS_OK;
resp.token = StringRef(*token);
} else if (sendspin_::global_sendspin_hub->status_has_error()) {
resp.status = enums::SENDSPIN_PAIRING_TOKEN_STATUS_FAILED;
} else if (sendspin_::global_sendspin_hub->is_disabled()) {
resp.status = enums::SENDSPIN_PAIRING_TOKEN_STATUS_DISABLED;
} else {
resp.status = enums::SENDSPIN_PAIRING_TOKEN_STATUS_NOT_READY;
}
#else
resp.status = enums::SENDSPIN_PAIRING_TOKEN_STATUS_ENCRYPTION_REQUIRED;
#endif
return this->send_message(resp);
}
void APIConnection::on_sendspin_pairing_token_request() {
if (!this->send_sendspin_pairing_token_response_()) {
this->on_fatal_error();
}
}
#endif
#ifdef USE_ALARM_CONTROL_PANEL
bool APIConnection::send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
return this->send_message_smart_(a_alarm_control_panel, AlarmControlPanelStateResponse::MESSAGE_TYPE,
@@ -1872,7 +1909,7 @@ bool APIConnection::send_hello_response_(const HelloRequest &msg) {
HelloResponse resp;
resp.api_version_major = 1;
resp.api_version_minor = 18;
resp.api_version_minor = 19;
// Send only the version string - the client only logs this for debugging and doesn't use it otherwise
resp.server_info = ESPHOME_VERSION_REF;
resp.name = StringRef(App.get_name());
@@ -2088,6 +2125,9 @@ bool APIConnection::send_device_capabilities_response_() {
#endif
#ifdef USE_API_WIZARD
resp.wizard.configured = true;
#endif
#if defined(USE_SENDSPIN) && defined(USE_ESP_IDF)
resp.sendspin.feature_flags = sendspin_::global_sendspin_hub->get_feature_flags();
#endif
return this->send_message(resp);
}
+7
View File
@@ -223,6 +223,10 @@ class APIConnection final : public APIServerConnectionBase {
void on_z_wave_proxy_request(const ZWaveProxyRequest &msg);
#endif
#if defined(USE_SENDSPIN) && defined(USE_ESP_IDF)
void on_sendspin_pairing_token_request();
#endif
#ifdef USE_ALARM_CONTROL_PANEL
bool send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel);
void on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg);
@@ -432,6 +436,9 @@ class APIConnection final : public APIServerConnectionBase {
#ifdef USE_VOICE_ASSISTANT
bool send_voice_assistant_get_configuration_response_(const VoiceAssistantConfigurationRequest &msg);
#endif
#if defined(USE_SENDSPIN) && defined(USE_ESP_IDF)
bool send_sendspin_pairing_token_response_();
#endif
#ifdef USE_CAMERA
void try_send_camera_image_();
+1 -1
View File
@@ -10,7 +10,7 @@
namespace esphome::api {
static const char *const TAG = "api.frame_helper";
ESPHOME_LOG_TAG(TAG, "api.frame_helper");
// Maximum bytes to log in hex format (168 * 3 = 504, under TX buffer size of 512)
static constexpr size_t API_MAX_LOG_BYTES = 168;
@@ -22,7 +22,7 @@ using noise::noise_err_to_logstr;
static_assert(MAX_HANDSHAKE_SIZE == noise::MAX_HANDSHAKE_SIZE,
"api and noise component handshake size limits must match");
static const char *const TAG = "api.noise";
ESPHOME_LOG_TAG(TAG, "api.noise");
static constexpr char PROLOGUE_INIT[] PROGMEM = "NoiseAPIInit";
static constexpr size_t PROLOGUE_INIT_LEN = 12; // strlen("NoiseAPIInit")
@@ -16,7 +16,7 @@
namespace esphome::api {
static const char *const TAG = "api.plaintext";
ESPHOME_LOG_TAG(TAG, "api.plaintext");
// Maximum bytes to log in hex format (168 * 3 = 504, under TX buffer size of 512)
static constexpr size_t API_MAX_LOG_BYTES = 168;
@@ -15,7 +15,7 @@
namespace esphome::api {
static const char *const TAG = "api.outgoing";
ESPHOME_LOG_TAG(TAG, "api.outgoing");
#ifndef API_OUTGOING_CONNECTION_HOST
static constexpr uint32_t OUTGOING_TARGET_PREF_HASH = 629847102UL;
+35
View File
@@ -306,6 +306,19 @@ uint32_t WizardCapabilities::calc_size_msg(const void *self) {
return size;
}
#endif
#ifdef USE_SENDSPIN
uint8_t *SendspinCapabilities::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
const auto &msg = *static_cast<const SendspinCapabilities *>(self);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.feature_flags);
return pos;
}
uint32_t SendspinCapabilities::calc_size_msg(const void *self) {
const auto &msg = *static_cast<const SendspinCapabilities *>(self);
uint32_t size = 0;
size += ProtoSize::calc_uint32(1, msg.feature_flags);
return size;
}
#endif
uint8_t *DeviceCapabilitiesResponse::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
const auto &msg = *static_cast<const DeviceCapabilitiesResponse *>(self);
#ifdef USE_BLUETOOTH_PROXY
@@ -324,6 +337,9 @@ uint8_t *DeviceCapabilitiesResponse::encode_msg(const void *self, uint8_t *__res
#endif
#ifdef USE_API_WIZARD
pos = ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.wizard);
#endif
#ifdef USE_SENDSPIN
pos = ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.sendspin);
#endif
return pos;
}
@@ -346,6 +362,9 @@ uint32_t DeviceCapabilitiesResponse::calc_size_msg(const void *self) {
#endif
#ifdef USE_API_WIZARD
size += ProtoSize::calc_message(1, msg.wizard.calculate_size());
#endif
#ifdef USE_SENDSPIN
size += ProtoSize::calc_message(1, msg.sendspin.calculate_size());
#endif
return size;
}
@@ -4229,6 +4248,22 @@ uint32_t BluetoothSetConnectionParamsResponse::calc_size_msg(const void *self) {
return size;
}
#endif
#ifdef USE_SENDSPIN
uint8_t *SendspinPairingTokenResponse::encode_msg(const void *self,
uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
const auto &msg = *static_cast<const SendspinPairingTokenResponse *>(self);
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast<uint32_t>(msg.status));
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, msg.token);
return pos;
}
uint32_t SendspinPairingTokenResponse::calc_size_msg(const void *self) {
const auto &msg = *static_cast<const SendspinPairingTokenResponse *>(self);
uint32_t size = 0;
size += msg.status ? 2 : 0;
size += !msg.token.empty() ? 2 + msg.token.size() : 0;
return size;
}
#endif
#ifndef HAS_PROTO_MESSAGE_DUMP
static_assert(!std::is_polymorphic_v<HelloRequest>, "decodable messages carry no vtable");
static_assert(!std::is_polymorphic_v<DisconnectRequest>, "decodable messages carry no vtable");
+53 -1
View File
@@ -383,6 +383,15 @@ enum SerialProxyIdentityFlag : uint32_t {
SERIAL_PROXY_IDENTITY_FLAG_CONNECTED = 1,
SERIAL_PROXY_IDENTITY_FLAG_ERROR = 2,
};
#ifdef USE_SENDSPIN
enum SendspinPairingTokenStatus : uint32_t {
SENDSPIN_PAIRING_TOKEN_STATUS_NOT_READY = 0,
SENDSPIN_PAIRING_TOKEN_STATUS_OK = 1,
SENDSPIN_PAIRING_TOKEN_STATUS_ENCRYPTION_REQUIRED = 2,
SENDSPIN_PAIRING_TOKEN_STATUS_DISABLED = 3,
SENDSPIN_PAIRING_TOKEN_STATUS_FAILED = 4,
};
#endif
} // namespace enums
@@ -737,10 +746,27 @@ class WizardCapabilities final : public ProtoMessage {
protected:
};
#endif
#ifdef USE_SENDSPIN
class SendspinCapabilities final : public ProtoMessage {
public:
uint32_t feature_flags{0};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
}
static uint32_t calc_size_msg(const void *self);
uint32_t calculate_size() const { return calc_size_msg(this); }
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
protected:
};
#endif
class DeviceCapabilitiesResponse final : public ProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 150;
static constexpr uint8_t ESTIMATED_SIZE = 119;
static constexpr uint8_t ESTIMATED_SIZE = 136;
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("device_capabilities_response"); }
#endif
@@ -758,6 +784,9 @@ class DeviceCapabilitiesResponse final : public ProtoMessage {
#endif
#ifdef USE_API_WIZARD
WizardCapabilities wizard{};
#endif
#ifdef USE_SENDSPIN
SendspinCapabilities sendspin{};
#endif
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
@@ -4138,5 +4167,28 @@ class BluetoothSetConnectionParamsResponse final : public ProtoMessage {
protected:
};
#endif
#ifdef USE_SENDSPIN
class SendspinPairingTokenResponse final : public ProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 160;
static constexpr uint8_t ESTIMATED_SIZE = 11;
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("sendspin_pairing_token_response"); }
#endif
enums::SendspinPairingTokenStatus status{};
StringRef token{nullptr, 0}; // null until set, encode only
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
}
static uint32_t calc_size_msg(const void *self);
uint32_t calculate_size() const { return calc_size_msg(this); }
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
protected:
};
#endif
} // namespace esphome::api
+39
View File
@@ -928,6 +928,25 @@ template<> const char *proto_enum_to_string<enums::SerialProxyIdentityFlag>(enum
return ESPHOME_PSTR("UNKNOWN");
}
}
#ifdef USE_SENDSPIN
template<>
const char *proto_enum_to_string<enums::SendspinPairingTokenStatus>(enums::SendspinPairingTokenStatus value) {
switch (value) {
case enums::SENDSPIN_PAIRING_TOKEN_STATUS_NOT_READY:
return ESPHOME_PSTR("SENDSPIN_PAIRING_TOKEN_STATUS_NOT_READY");
case enums::SENDSPIN_PAIRING_TOKEN_STATUS_OK:
return ESPHOME_PSTR("SENDSPIN_PAIRING_TOKEN_STATUS_OK");
case enums::SENDSPIN_PAIRING_TOKEN_STATUS_ENCRYPTION_REQUIRED:
return ESPHOME_PSTR("SENDSPIN_PAIRING_TOKEN_STATUS_ENCRYPTION_REQUIRED");
case enums::SENDSPIN_PAIRING_TOKEN_STATUS_DISABLED:
return ESPHOME_PSTR("SENDSPIN_PAIRING_TOKEN_STATUS_DISABLED");
case enums::SENDSPIN_PAIRING_TOKEN_STATUS_FAILED:
return ESPHOME_PSTR("SENDSPIN_PAIRING_TOKEN_STATUS_FAILED");
default:
return ESPHOME_PSTR("UNKNOWN");
}
}
#endif
const char *HelloRequest::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("HelloRequest"));
@@ -1096,6 +1115,13 @@ const char *WizardCapabilities::dump_to(DumpBuffer &out) const {
return out.c_str();
}
#endif
#ifdef USE_SENDSPIN
const char *SendspinCapabilities::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("SendspinCapabilities"));
dump_field(out, ESPHOME_PSTR("feature_flags"), this->feature_flags);
return out.c_str();
}
#endif
const char *DeviceCapabilitiesResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("DeviceCapabilitiesResponse"));
#ifdef USE_BLUETOOTH_PROXY
@@ -1124,6 +1150,11 @@ const char *DeviceCapabilitiesResponse::dump_to(DumpBuffer &out) const {
out.append(2, ' ').append_p(ESPHOME_PSTR("wizard")).append(": ");
this->wizard.dump_to(out);
out.append("\n");
#endif
#ifdef USE_SENDSPIN
out.append(2, ' ').append_p(ESPHOME_PSTR("sendspin")).append(": ");
this->sendspin.dump_to(out);
out.append("\n");
#endif
return out.c_str();
}
@@ -2944,6 +2975,14 @@ const char *BluetoothSetConnectionParamsResponse::dump_to(DumpBuffer &out) const
return out.c_str();
}
#endif
#ifdef USE_SENDSPIN
const char *SendspinPairingTokenResponse::dump_to(DumpBuffer &out) const {
MessageDumpHelper helper(out, ESPHOME_PSTR("SendspinPairingTokenResponse"));
dump_field(out, ESPHOME_PSTR("status"), static_cast<enums::SendspinPairingTokenStatus>(this->status));
dump_field(out, ESPHOME_PSTR("token"), this->token);
return out.c_str();
}
#endif
} // namespace esphome::api
+10 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::api {
static const char *const TAG = "api.service";
ESPHOME_LOG_TAG(TAG, "api.service");
#ifdef HAS_PROTO_MESSAGE_DUMP
void APIServerConnectionBase::log_send_message_(const LogString *name, const char *dump) {
@@ -751,6 +751,15 @@ void APIConnection::read_message_(uint32_t msg_size, uint32_t msg_type, const ui
this->on_wizard_input_set_request(msg);
break;
}
#endif
#ifdef USE_SENDSPIN
case 159 /* SendspinPairingTokenRequest is empty */: {
#ifdef HAS_PROTO_MESSAGE_DUMP
this->log_receive_message_(LOG_STR("on_sendspin_pairing_token_request"));
#endif
this->on_sendspin_pairing_token_request();
break;
}
#endif
default:
break;
+4
View File
@@ -252,6 +252,10 @@ class APIServerConnectionBase {
#ifdef USE_BLUETOOTH_PROXY_CONNECTIONS
void on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &value){};
#endif
#ifdef USE_SENDSPIN
void on_sendspin_pairing_token_request(){};
#endif
};
} // namespace esphome::api
+1 -1
View File
@@ -23,7 +23,7 @@
namespace esphome::api {
static const char *const TAG = "api";
ESPHOME_LOG_TAG(TAG, "api");
// APIServer
APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
+1 -1
View File
@@ -11,7 +11,7 @@
namespace esphome::api {
static const char *const TAG = "api.wizard";
ESPHOME_LOG_TAG(TAG, "api.wizard");
#ifdef USE_API_WIZARD_INPUTS
static bool wizard_entity_id_valid(const char *entity_id, size_t length) {
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::api {
static const char *const TAG = "api.proto";
ESPHOME_LOG_TAG(TAG, "api.proto");
uint32_t ProtoSize::varint_slow(uint32_t value) { return varint_wide(value); }
+2 -1
View File
@@ -11,6 +11,7 @@ from typing import Any
from esphome import automation
import esphome.codegen as cg
from esphome.components.const import CONF_DESCRIPTION
from esphome.components.homeassistant import DOMAIN as HOMEASSISTANT_DOMAIN
import esphome.config_validation as cv
from esphome.const import (
CONF_DEVICE_CLASS,
@@ -265,7 +266,7 @@ def _validate_wizard_input(conf: ConfigType) -> ConfigType:
fv.full_config.get(), conf[CONF_ENTITY]
)
if (
declaration.get(CONF_PLATFORM) != "homeassistant"
declaration.get(CONF_PLATFORM) != HOMEASSISTANT_DOMAIN
or domain not in WIZARD_INPUT_DOMAINS
):
raise cv.Invalid(
+1
View File
@@ -1,6 +1,7 @@
import esphome.codegen as cg
CODEOWNERS = ["@jasstrong", "@ximex", "@freekode"]
DOMAIN = "aqi"
aqi_ns = cg.esphome_ns.namespace("aqi")
AQICalculatorType = aqi_ns.enum("AQICalculatorType")
+5 -3
View File
@@ -3,20 +3,22 @@
namespace esphome::aqi {
static const char *const TAG = "aqi";
ESPHOME_LOG_TAG(TAG, "aqi");
static constexpr uint32_t CALCULATE_DEFER_ID = 0;
void AQISensor::setup() {
if (this->pm_2_5_sensor_ != nullptr) {
this->pm_2_5_sensor_->add_on_state_callback([this](float value) {
this->pm_2_5_value_ = value;
// Defer calculation to avoid double-publishing if both sensors update in the same loop
this->defer("update", [this]() { this->calculate_aqi_(); });
this->defer(CALCULATE_DEFER_ID, [this]() { this->calculate_aqi_(); });
});
}
if (this->pm_10_0_sensor_ != nullptr) {
this->pm_10_0_sensor_->add_on_state_callback([this](float value) {
this->pm_10_0_value_ = value;
this->defer("update", [this]() { this->calculate_aqi_(); });
this->defer(CALCULATE_DEFER_ID, [this]() { this->calculate_aqi_(); });
});
}
}
+1
View File
@@ -17,6 +17,7 @@ from esphome.const import (
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
DOMAIN = "as3935"
MULTI_CONF = True
CONF_AS3935_ID = "as3935_id"

Some files were not shown because too many files have changed in this diff Show More