AI assistant for developing ESPHome IoT firmware. Helps with YAML configs, C++ components, Python code generation, and platform-specific implementations for ESP32/ESP8266/RP2040.
An AI assistant specialized in ESPHome development - a system to control ESP8266/ESP32/RP2040 microcontrollers through YAML configuration files that generate C++ firmware for home automation.
This skill helps you work with the ESPHome codebase by:
ESPHome follows a **code-generation architecture**:
1. Python code parses YAML configuration files
2. Generates C++ source code based on configuration
3. Compiles and flashes to target microcontroller via PlatformIO
**Key directories:**
**Core systems:**
**Python (PEP 8):**
**C++ (Google Style Guide with ESPHome specifics):**
**C++ Field Visibility:**
- Pointer lifetime issues (setters validate against known lists)
- Invariant coupling (fields must stay synchronized)
- Resource management (cleanup/registration in setters)
**Preprocessor:**
**Standard component structure:**
```
components/[component_name]/
├── __init__.py # Config schema and code generation
├── [component].h # C++ header
├── [component].cpp # C++ implementation
└── [platform]/ # Platform-specific code
├── __init__.py
├── [platform].h
└── [platform].cpp
```
**Component metadata in `__init__.py`:**
**Configuration schema pattern:**
```python
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.const import CONF_KEY, CONF_ID
CONF_PARAM = "param" # New constant
my_component_ns = cg.esphome_ns.namespace("my_component")
MyComponent = my_component_ns.class_("MyComponent", cg.Component)
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_id(MyComponent),
cv.Required(CONF_KEY): cv.string,
cv.Optional(CONF_PARAM, default=42): cv.int_,
}).extend(cv.COMPONENT_SCHEMA)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)
cg.add(var.set_key(config[CONF_KEY]))
cg.add(var.set_param(config[CONF_PARAM]))
```
**C++ class pattern:**
```cpp
namespace esphome::my_component {
class MyComponent : public Component {
public:
void setup() override;
void loop() override;
void dump_config() override;
void set_key(const std::string &key) { this->key_ = key; }
void set_param(int param) { this->param_ = param; }
protected:
std::string key_;
int param_{0};
};
} // namespace esphome::my_component
```
**Sensor:**
```python
from esphome.components import sensor
CONFIG_SCHEMA = sensor.sensor_schema(MySensor).extend(cv.polling_component_schema("60s"))
async def to_code(config):
var = await sensor.new_sensor(config)
await cg.register_component(var, config)
```
**Binary Sensor:**
```python
from esphome.components import binary_sensor
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend({ ... })
async def to_code(config):
var = await binary_sensor.new_binary_sensor(config)
```
**Switch:**
```python
from esphome.components import switch
CONFIG_SCHEMA = switch.switch_schema().extend({ ... })
async def to_code(config):
var = await switch.new_switch(config)
```
**Common validators:**
**Platform/framework filtering:**
**Schema extensions:**
```python
CONFIG_SCHEMA = cv.Schema({ ... })
.extend(cv.COMPONENT_SCHEMA)
.extend(uart.UART_DEVICE_SCHEMA)
.extend(i2c.i2c_device_schema(0x48))
.extend(spi.spi_device_schema(cs_pin_required=True))
```
**ESP32** (`components/esp32/`):
**ESP8266** (`components/esp8266/`):
**RP2040** (`components/rp2040/`):
**LibreTiny** (`components/libretiny/`):
**Python tests:**
```bash
pytest
```
**C++ static analysis:**
```bash
clang-tidy
```
**Component compilation tests:**
```bash
./script/test_build_components -c <component> -t <target>
```
**Test all components together (catch conflicts):**
```bash
./script/test_component_grouping.py -e config --all
```
**Linting:**
```bash
python3 script/run-in-env.py pre-commit run
```
**Python:**
**C++:**
**Communication:**
**Creating a simple sensor component:**
1. Create directory `components/my_sensor/`
2. Add `__init__.py` with schema and code generation
3. Add `my_sensor.h` and `my_sensor.cpp` with C++ implementation
4. Use `this->` for all member access, `protected` fields with trailing underscore
5. Add tests in `tests/components/my_sensor/`
6. Run `./script/test_build_components -c my_sensor`
**Platform-specific implementation:**
1. Check platform with `cv.only_on(["esp32"])`
2. Use variant filtering: `esp32.only_on_variant(["esp32c3"])`
3. Framework check: `cv.only_with_esp_idf`
4. Add platform subdirectory if needed
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/esphome-development-assistant-qnn5z7/raw