Guide AI models in developing ESPHome microcontroller configurations and components using YAML and C++ code generation patterns.
You are an expert in ESPHome, a system for configuring microcontrollers (ESP32, ESP8266, RP2040, LibreTiny-based chips) using YAML configuration files that generate C++ firmware for home automation.
ESPHome generates C++ firmware from YAML configurations, compiling and flashing it to microcontrollers for remote control through home automation systems.
**Core Technologies:**
**Code Generation Flow:**
1. Python parses YAML configurations
2. Generates C++ source code
3. Compiles via PlatformIO
4. Flashes to microcontroller
**Directory Structure:**
**Key Systems:**
1. **Configuration System** (`config*.py`): YAML parsing and validation with Voluptuous
2. **Code Generation** (`codegen.py`, `cpp_generator.py`): Python-to-C++ generation
3. **Component System** (`components/`): Modular hardware/software components
4. **Core Framework** (`core/`): Application lifecycle and hardware abstraction
5. **Dashboard**: Web interface for device management and OTA updates
**Platform Support:**
```
components/[component_name]/
├── __init__.py # Configuration schema and code generation
├── [component].h # C++ header file
├── [component].cpp # C++ implementation
└── [platform]/ # Platform-specific implementations
├── __init__.py # Platform-specific configuration
├── [platform].h # Platform C++ header
└── [platform].cpp # Platform C++ implementation
```
```python
DEPENDENCIES = ["required_component"]
AUTO_LOAD = ["auto_loaded_component"]
CONFLICTS_WITH = ["incompatible_component"]
CODEOWNERS = ["@username"]
MULTI_CONF = True # Allow multiple instances
```
```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 not in esphome/const.py
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]))
```
```cpp
namespace esphome {
namespace 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 my_component
} // namespace esphome
```
**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:**
**Complex Validation:**
**Platform-Specific:**
**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))
```
Use Docker container or Python virtual environment with `requirements_dev.txt`.
```bash
python3 script/run-in-env.py <command>
python3 script/run-in-env.py pre-commit run
```
**Python Tests:**
```bash
pytest
```
**Component Tests (YAML-based compilation):**
```bash
script/test_build_components -c <component> -t <target>
```
**Static Analysis:**
```bash
clang-tidy # For C++
```
**Python:**
**C++:**
**Static Analysis:**
1. **Fork & Branch:** Create feature branch in your fork
2. **Make Changes:** Follow all coding conventions and patterns
3. **Test:** Create component tests for all supported platforms, run full test suite
4. **Lint:** Run `pre-commit` to ensure compliance
5. **Commit:** Commit changes (no strict format)
6. **Pull Request:** Submit PR against `dev` branch with component prefix in title (e.g., `[display] Fix bug`, `[abc123] Add new component`)
**Pull Request Requirements:**
**Documentation:**
**Component Development:**
**Code Generation:**
**Configuration Design:**
**Security:**
**Dependencies:**
1. Always validate YAML configurations before generating code
2. Test on all supported platforms when modifying components
3. Keep generated C++ code minimal and efficient
4. Provide clear validation error messages
5. Write component tests for all platforms
6. Update `esphome/core/defines.h` when adding new defines
7. Document configuration options thoroughly
8. Consider memory constraints (especially ESP8266)
9. Follow the established component patterns
10. Run pre-commit hooks before submitting changes
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/esphome-configuration-and-component-development/raw