Descripción de la integración de Home-Ambient en Home Assistant mediante el framework ESPHome. Integración de varias configuraciones como climatizador, sensores ambientales, actuadores y displays de tinta electrónica.
Introducción
ESPHome es un framework para crear firmwares personalizados que se integran muy fácilmente con Home Assistant. El hardware soportado es el basado principalmente en ESP8266 y ESP32, si bien también soporta RP2040 y ha comenzado un desarrollo para el nRF52840.
A diferencia de la programación en C/C++, en ESPHome el comportamiento se define mediante archivos de configuración YAML (texto plano legible).
Integración termostato
El termostato es el componente principal de Home-Ambient y su razón de ser. ESPHome dispone de este componente para usar de una forma muy directa y sencilla, simplemente se debe definir un sensor que mida el parámetro a controlar y un actuador que gobierne el elemento calefactor.
Sensores y actuadores en ESPHome
La integración de sensores y actuadores con ESPHome puede ser cualquiera de las descritas a continuación. Es posible utilizar cualquier tipo de sensor, incluso fusionar varios promediando o añadiendo lógicas diversas.
BME680. Temperatura, humedad, presión y calidad del aire

Para más información sobre este sensor consultar la documentación oficial en ‘ESPHome: BME 68X via BSEC2’.
El sensor BME680 depende de un canal I2C como interfaz de comunicación. Se especifican los pines físicos, la velocidad y la activación de un escaneo automático al iniciar. Este escaneo es muy útil para diagnóstico y depuración. La asignación de un identificador sirve para referenciar sin lugar a dudas este bus.
A continuación, se establece la configuración específica del sensor ambiental, sin incluir nada que merezca especial atención.
Finalmente, se describen las magnitudes ambientales que serán publicadas, ajustando las cifras significativas. El filtro ‘delta’ ayuda a reducir el tráfico de datos al obviar cambios de estado inferiores al indicado.
‘text_sensor:’ podría excluirse sin problema, aunque aporta información que podría resultar vistosa en algunos dashboards de Home Assistant.
# BME68X I2C bus
i2c:
sda: GPIO6
scl: GPIO7
frequency: 400kHz
scan: true
id: i2c_a
# BME68X Device
bme68x_bsec2_i2c:
i2c_id: i2c_a
address: 0x77
model: bme680
operating_age: 28d
sample_rate: ULP
supply_voltage: 3.3V
state_save_interval: 6h
sensor:
# BME68X Sensor reading
# Temperature, humidity, pressure air quality sensor
- platform: bme68x_bsec2
temperature:
id: temperature_sensor
name: "Temperature"
accuracy_decimals: 1
filters:
- delta: 0.2
pressure:
id: pressure_sensor
name: "Pressure"
unit_of_measurement: mbar
accuracy_decimals: 0
filters:
- delta: 1
humidity:
id: humidity_sensor
name: "Humidity"
accuracy_decimals: 0
filters:
- delta: 1
co2_equivalent:
name: "CO2 Equivalent"
accuracy_decimals: 0
breath_voc_equivalent:
name: "Breath VOC Equivalent"
text_sensor:
- platform: bme68x_bsec2
iaq_accuracy:
name: "IAQ Accuracy"
- platform: template
name: "IAQ Classification"
lambda: |-
if ( int(id(iaq).state) <= 50) {
return {"Excellent"};
}
else if (int(id(iaq).state) >= 51 && int(id(iaq).state) <= 100) {
return {"Good"};
}
else if (int(id(iaq).state) >= 101 && int(id(iaq).state) <= 150) {
return {"Lightly polluted"};
}
else if (int(id(iaq).state) >= 151 && int(id(iaq).state) <= 200) {
return {"Moderately polluted"};
}
else if (int(id(iaq).state) >= 201 && int(id(iaq).state) <= 250) {
return {"Heavily polluted"};
}
else if (int(id(iaq).state) >= 251 && int(id(iaq).state) <= 350) {
return {"Severely polluted"};
}
else if (int(id(iaq).state) >= 351) {
return {"Extremely polluted"};
}
else {
return {"error"};
}Sensor de temperatura analógico
Aunque un sensor analógico no es una opción de precisión, resulta muy económico y podría servir en multitud de situaciones.

sensor:
# Analog temperature monitor
- platform: adc
id: temperature_sensor
pin: GPIO0
name: "Temperature"
attenuation: 12db
unit_of_measurement: "°C"
accuracy_decimals: 1
update_interval: 10s
filters:
- sliding_window_moving_average:
window_size: 12
send_every: 12
- multiply: 1000
- lambda: return (1575 - x) / (8.1f);
- delta: 0.2Es prácticamente obligatorio filtrar una lectura analógica de un ESP32-C3. El filtro utilizado es una media móvil de dos minutos, con muestras cada 10 segundos. Solo se publican variaciones de temperatura superiores a 0,2°C.
Las operaciones matemáticas sirven para convertir la lectura en milivoltios del ADC a temperatura en grados centígrados para el sensor LMT85.
Las o

Leer sensores/datos de Home Assistant
En ocasiones puede ser necesario obtener el valor de un sensor o estado que se esté ejecutando en el propio Home Assistant, las posibilidades son infinitas. En el siguiente ejemplo se obtiene la temperatura de un sensor situado en la calle.
sensor:
# Street parameters
- platform: homeassistant
id: street_temp_id
entity_id: sensor.street_temperatureActuador y contador energético
Un añadido muy interesante al actuador del calefactor es el conteo de la energía consumida. Es totalmente opcional, pero resulta muy interesante para quien desea obtener datos y estadísticas.

Obviamente la medida no es 100% real, pero el sistema no necesitará un medidor dedicado, estimando el consumo energético basándose en la potencia conocida del calentador y el tiempo que permanece encendido.
sensor:
# Virtual power sensor
- platform: template
name: "Power"
id: thermostat_power
state_class: measurement
device_class: power
unit_of_measurement: "W"
accuracy_decimals: 0
# Virtual energy sensor
- platform: integration
name: "Energy"
sensor: thermostat_power
time_unit: h
state_class: total_increasing
device_class: energy
unit_of_measurement: "kWh"
accuracy_decimals: 3
integration_method: left
filters:
- multiply: 0.001
# Heating relay
switch:
- platform: gpio
id: heater_switch
pin: GPIO4
name: "Heater"
on_turn_on:
- sensor.template.publish:
id: thermostat_power
# Heating power
state: 2300
on_turn_off:
- sensor.template.publish:
id: thermostat_power
state: 0Obligatoriamente solo es necesario declarar un switch para que el termostato funcione, por lo que todo lo demás es totalmente opcional.
Se crea un sensor de potencia basado en template que no mide un valor físico real, sino un valor asignado internamente. Se configura como una magnitud de potencia y con clase measurement, lo que permite que Home Assistant lo interprete correctamente dentro de la aplicación de energía.
Un segundo sensor calcula la energía consumida. Al integrar la potencia instantánea se tiene la energía total expresada en kilovatios hora. Se aplica un factor de conversión para adaptar la escala de unidades y se asigna la clase energy.
Cuando el calentador se enciende, se publica un valor fijo de potencia que representa el consumo nominal del equipo.
Termostato
climate:
- platform: thermostat
name: "Thermostat"
id: ha_thermostat
sensor: temperature_sensor
visual:
min_temperature: 10
max_temperature: 28
temperature_step: 0.2
min_heating_off_time: 30s
min_heating_run_time: 5s
min_idle_time: 30s
heat_deadband: 0.3
heat_overrun: 0.5
heat_action:
- switch.turn_on: heater_switch
- light.turn_on:
id: rgb_led
red: 1.0
green: 0.0
blue: 0.0
brightness: 0.5
idle_action:
- switch.turn_off: heater_switch
- light.turn_off: rgb_led
default_preset: Home
preset:
- name: Home
default_target_temperature_low: 12 °CEste bloque configura un termostato digital que utiliza la temperatura medida como referencia para controlar automáticamente el sistema de calefacción.
Se define un tiempo mínimo entre encendidos, así como un tiempo mínimo de funcionamiento una vez encendida. También se fija un periodo mínimo en estado inactivo y un margen de histéresis alrededor de la temperatura objetivo.
Como depuración, se enciende el RGB en rojo para mostrar que la calefacción está funcionando.
Finalmente, default_preset define una temperatura inicial baja cuando el sistema arranca o tras reinicios.
Una vez implementado el termostato es posible obtener un control como el siguiente:

Programador de temperaturas
Programar las temperaturas de un termostato es la principal característica de un termostato inteligente. En Home Assistant sería posible realizar esto mediante automatizaciones, sin embargo, gestionar esto sería tedioso.
Una opción flexible y fiable es el programador desarrollado por Niels Faber.

Instalar este programador en Home Assistant no es complicado, pero tampoco fácil. Como es un proyecto vivo, lo mejor es acudir a la fuente para encontrar el manual de instalación y usuario. Consta de dos partes que deben instalarse en orden:
Para este proyecto se ha utilizado una pantalla de tinta electrónica de 4,2″ con una resolución de 400×300 pixeles. La elección se realizó fundamentalmente por ser el mayor tamaño disponible para el formato del termostato, el precio también ayudó a la decisión al ser un display económico.

Configuración e impresión de una imagen
spi:
id: spi_a
clk_pin: GPIO2
mosi_pin: GPIO5
image:
- file: "P_FC.bmp"
type: binary
id: floor_plan
invert_alpha: true
display:
- platform: waveshare_epaper
spi_id: spi_a
model: gdey042t81
cs_pin: GPIO3
busy_pin: GPIO18
dc_pin: GPIO10
reset_pin: GPIO19
reset_duration: 2ms
update_interval: 60s
full_update_every: 1
lambda: |-
auto color_back = COLOR_OFF;
auto color_print = COLOR_ON;
it.fill(color_back);
it.image(0, 0, id(floor_plan));La interfaz con el display se realiza a través de un canal SPI.
El siguiente paso es la propia implementación del display con la directiva display: seguida de la configuración hardware básica. Importante a tener en cuenta es el modelo de driver declarado. Solo ha funcionado el ‘gdey042t81’, y no con ninguno de la familia ‘4.20in’.
Finalmente se muestra como ejemplo la visualización de una imagen, que en este caso es el plano de una planta de un piso, sobre la que se irá mostrando información con las herramientas que proporciona el componente display que se irán mostrando a continuación.

En el ejemplo anterior las declaraciones de las variables color_back y color_print son opcionales, pero recomendables al dar un control total en el momento de mostrar elementos por pantalla. Gracias a estas declaraciones es posible invertir los colores de toda la pantalla fácilmente sin cambiar cada elemento uno a uno.
Mostrando textos y formas básicas
Antes de imprimir una cadena de caracteres es necesario declarar la fuente que será usada en el renderizado del texto. Lo más sencillo es utilizar las fuentes de Google gfonts, pero también es posible instalar fuentes de forma local.
font:
- file:
type: gfonts
family: Source Code Pro
weight: 600
id: roboto_20
size: 20
- file:
type: gfonts
family: Source Code Pro
weight: 800
id: roboto_26
size: 26
# Los siguientes ejemplos siguen a la directiva 'lambda: |-'
it.printf(290, 0, id(roboto_20), color_print, "P:%.0fW", id(grid_power_id).state);
it.rectangle(320, 115, 70, 70, color_print);
it.printf(330, 115, id(roboto_20), color_print, "Ext.");
it.printf(327, 140, id(roboto_20), color_print, "%.1f°", id(street_temp_id).state);
it.printf(335, 160, id(roboto_20), color_print, "%.0f%%", id(street_humi_id).state);
El desarrollo de Home-Ambient
Todas las etapas de desarrollo del termostato Home-Ambient se recogen en las siguientes entradas:
Home-Ambient: Termostato inteligente a dos hilos
Publicado: 31/10/2025
Home-Ambient: El prototipo
Publicado: 16/11/2025
Home-Ambient: Hardware, esquema y PCB
Publicado: 18/12/2025

