[fastled_base] Use FastLED IDF component on ESP32 (#16804)

This commit is contained in:
Jonathan Swoboda
2026-06-05 21:01:29 -04:00
committed by GitHub
parent 2a4913713a
commit 8aa4157574
8 changed files with 73 additions and 8 deletions

View File

@@ -1 +1 @@
0b8325f52fca9224efb80dacca51ccbc8b3499bde7bb4aaa6f28a848c2e0a6a8
d583091c0f465aed86a825138e309af6d9db6834106ab424f36712424a6c2223

View File

@@ -41,10 +41,16 @@ async def new_fastled_light(config):
if CONF_MAX_REFRESH_RATE in config:
cg.add(var.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE]))
cg.add_library("fastled/FastLED", "3.9.16")
if CORE.is_esp32:
from esphome.components.esp32 import include_builtin_idf_component
from esphome.components.esp32 import add_idf_component
include_builtin_idf_component("esp_lcd")
add_idf_component(
name="fastled/FastLED",
repo="https://github.com/FastLED/FastLED.git",
ref="d44c800a9e876a8394caefc2ce4915dd96dac77b",
)
cg.add_library("SPI", None)
else:
cg.add_library("fastled/FastLED", "3.9.16")
await light.register_light(var, config)
return var

View File

@@ -143,7 +143,6 @@ class FastLEDLightOutput : public light::AddressableLight {
}
}
#ifdef FASTLED_HAS_CLOCKLESS
template<template<uint8_t DATA_PIN, EOrder RGB_ORDER> class CHIPSET, uint8_t DATA_PIN, EOrder RGB_ORDER>
CLEDController &add_leds(int num_leds) {
static CHIPSET<DATA_PIN, RGB_ORDER> controller;
@@ -160,7 +159,6 @@ class FastLEDLightOutput : public light::AddressableLight {
static CHIPSET<DATA_PIN> controller;
return add_leds(&controller, num_leds);
}
#endif
template<template<EOrder RGB_ORDER> class CHIPSET, EOrder RGB_ORDER> CLEDController &add_leds(int num_leds) {
static CHIPSET<RGB_ORDER> controller;

View File

@@ -160,6 +160,12 @@ def _setup_core(work_dir: Path, settings: _Settings) -> None:
CORE.data.setdefault(KEY_CORE, {})[KEY_TARGET_PLATFORM] = "esp32"
CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = settings.target_framework
# Gates arduino-only components in esphome/idf_component.yml (IDF reads it at
# reconfigure time). Set here -- before the manifest is written/reconfigured.
os.environ["ESPHOME_ARDUINO"] = (
"1" if settings.target_framework == "arduino" else "0"
)
# Special IDF "components" that are tools/subprojects, not requirable by an app
# (they provide no public includes and break requirement resolution), plus our

View File

@@ -103,3 +103,8 @@ dependencies:
version: 0.6.1
lvgl/lvgl:
version: 9.5.0
fastled/FastLED:
git: https://github.com/FastLED/FastLED.git
version: d44c800a9e876a8394caefc2ce4915dd96dac77b
rules:
- if: "$ESPHOME_ARDUINO == 1"

View File

@@ -79,7 +79,6 @@ lib_deps =
SPI ; spi (Arduino built-in)
Wire ; i2c (Arduino built-int)
heman/AsyncMqttClient-esphome@1.0.0 ; mqtt
fastled/FastLED@3.9.16 ; fastled_base
freekode/TM1651@1.0.1 ; tm1651
dudanov/MideaUART@1.1.9 ; midea
tonia/HeatpumpIR@1.0.41 ; heatpumpir
@@ -108,6 +107,7 @@ platform_packages =
framework = arduino
lib_deps =
${common:arduino.lib_deps}
fastled/FastLED@3.9.16 ; fastled_base
bblanchon/ArduinoJson@7.4.2 ; json
ESP8266WiFi ; wifi (Arduino built-in)
Update ; ota (Arduino built-in)
@@ -198,6 +198,7 @@ platform_packages =
framework = arduino
lib_deps =
${common:arduino.lib_deps}
fastled/FastLED@3.9.16 ; fastled_base
ayushsharma82/RPAsyncTCP@1.3.2 ; async_tcp
bblanchon/ArduinoJson@7.4.2 ; json
ESP32Async/ESPAsyncWebServer@3.9.6 ; web_server_base

View File

@@ -35,9 +35,19 @@ def clang_options(idedata):
# extract target architecture from triplet in g++ filename
triplet = Path(idedata["cxx_path"]).name[:-4]
if triplet.startswith("xtensa-"):
# clang doesn't support Xtensa (yet?), so compile in 32-bit mode and pretend we're the Xtensa compiler
# clang has an Xtensa frontend, but only a generic core -- the esp32 IDF
# toolchain headers (xtruntime, xtensa/config) need the GCC core config
# (XCHAL_*) it doesn't ship, so we still compile in 32-bit x86 mode and
# just pretend to be Xtensa. Undefine the host x86 arch macros -m32 sets,
# so libraries with x86 SIMD paths (FastLED's fl/math/simd, simd_x86.hpp)
# fall back to their scalar implementation instead of an incomplete
# host-x86 one, and define the xtensa endianness macro newlib's
# machine/ieeefp.h then needs in their place.
cmd.append("-m32")
cmd.append("-U__i386__")
cmd.append("-U__x86_64__")
cmd.append("-D__XTENSA__")
cmd.append("-D__XTENSA_EL__")
cmd.append("-D_LIBC")
else:
# RISC-V (and other non-Xtensa targets) have a real clang backend, so

View File

@@ -0,0 +1,39 @@
"""Tests for esphome.espidf.clang_tidy tidy-project setup."""
import os
from pathlib import Path
import pytest
from esphome.espidf.clang_tidy import _Settings, _setup_core
def _settings(target_framework: str) -> _Settings:
return _Settings(
idf_target="esp32",
variant="ESP32",
idf_version="5.5.4",
target_framework=target_framework,
platform_defines=("USE_ESP32",),
framework_deps={},
)
@pytest.mark.parametrize(
("target_framework", "expected"),
[("arduino", "1"), ("espidf", "0")],
)
def test_setup_core_sets_arduino_env(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
target_framework: str,
expected: str,
) -> None:
"""_setup_core sets ESPHOME_ARDUINO, which gates arduino-only manifest deps."""
# monkeypatch snapshots os.environ, so the env var _setup_core writes is
# restored after the test instead of leaking into later tests.
monkeypatch.delenv("ESPHOME_ARDUINO", raising=False)
_setup_core(tmp_path / "proj", _settings(target_framework))
assert os.environ["ESPHOME_ARDUINO"] == expected