
Imagina tener un mini monitor en cada habitación que te muestra la temperatura, la humedad, el consumo eléctrico y si las duchas están listas. Sin abrir el móvil, sin mirar el dashboard de Home Assistant. Solo un vistazo al pasar. Por menos de 15€ y con ESPHome, eso es exactamente lo que puedes tener.
En este tutorial te enseño paso a paso cómo convertir un GeekMagic SmallTV en un dashboard físico de Home Assistant que muestra datos de tus sensores en tiempo real.
¿Qué es el GeekMagic SmallTV?
Es un mini dispositivo con forma de televisor retro que esconde dentro un ESP8266 y una pantalla TFT de 240×240 píxeles. De fábrica muestra el tiempo y GIFs decorativos, pero al flashearlo con ESPHome se convierte en un display completamente personalizable conectado a tu Home Assistant.
Hay varios modelos disponibles:
- SmallTV Ultra (~12€) — ESP8266, pantalla ST7789V. Compralo aqui
- SmallTV Pro (~20€) — ESP32, con sensor táctil superior. Compralo aqui
Todos se pueden flashear con ESPHome. El modelo básico es más que suficiente para lo que vamos a hacer.
El resultado final
Al terminar este tutorial tendrás un display que muestra en tiempo real:
- 🌡️ Temperatura de la habitación (en grande, legible de un vistazo)
- 💧 Humedad con colores según severidad (verde si OK, naranja >75%, rojo >80%)
- ⚡ Consumo eléctrico total de la casa
- 🚿 Estado de la caldera (con indicador “Duchas OK”)
- 👁️ Detección de movimiento
- 🔒 Estado de la alarma
- 🏠 Quién está en casa
- 🌤️ Tiempo exterior
Todo actualizado cada 10 segundos, con brillo automático que baja por la noche para no molestar.
Material necesario
- GeekMagic SmallTV (versión ESP8266, ~12-15€ en AliExpress)
- Cable USB para alimentación
- Conversor USB-Serial FTDI (solo para el primer flasheo, ~3€) (Opcional ya que se puede hacer por wifi)
- Home Assistant con el addon ESPHome Device Builder
- Sensores en HA que quieras mostrar (temperatura, humedad, consumo…)
Paso 1: Instalar ESPHome en Home Assistant
Si no tienes el addon ESPHome:
- Ajustes → Complementos → Tienda de complementos
- Busca “ESPHome Device Builder”
- Instala, activa, y abre la interfaz web
Paso 2: La configuración base
Vamos a crear un archivo base que comparten todos los displays. Esto incluye la configuración del hardware (pantalla, SPI, backlight), fuentes, iconos y el ajuste automático de brillo. Crea el archivo base-smalltv.yaml en /config/esphome/:
esphome:
name: ${device_name}
friendly_name: ${friendly_name}
platformio_options:
board_build.f_cpu: 160000000L
on_boot:
- priority: 600
then:
- delay: 1s
- output.turn_on: backlight
- output.set_level:
id: backlight
level: 50%
esp8266:
board: esp12e
external_components:
- source:
type: git
url: https://github.com/lhartmann/esphome-st7789v-fractional-framebuffer
ref: main
refresh: 0s
components: [st7789v]
logger:
level: WARN
api:
reboot_timeout: 0s
encryption:
key: !secret api_key
ota:
- platform: esphome
password: !secret ota_password
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
fast_connect: true
ap:
ssid: "${device_name}-AP"
password: !secret ap_password
captive_portal:
time:
- platform: sntp
id: sntp_time
timezone: Europe/Madrid
font:
- id: font_big
file: "gfonts://Roboto@700"
size: 42
glyphs: "0123456789.°C%:-"
- id: font_medium
file: "gfonts://Roboto@500"
size: 22
- id: font_small
file: "gfonts://Roboto"
size: 16
- id: font_tiny
file: "gfonts://Roboto"
size: 12
- id: icon_font
file:
type: web
url: https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/fonts/materialdesignicons-webfont.ttf
size: 22
glyphs:
- "\U000F050F" # thermometer
- "\U000F058E" # water-percent
- "\U000F0009" # account
- "\U000F0F29" # account-check
- "\U000F0238" # flash (power)
- "\U000F0A07" # shield-home
- "\U000F0590" # weather-cloudy
- "\U000F0D0B" # shower-head
- "\U000F0510" # eye (occupancy)
spi:
id: spihwd
clk_pin: GPIO14
mosi_pin: GPIO13
interface: hardware
output:
- id: backlight
platform: esp8266_pwm
pin: GPIO05
inverted: true
frequency: 1000 Hz
light:
- platform: monochromatic
output: backlight
name: "${friendly_name} Backlight"
restore_mode: ALWAYS_ON
color:
- id: white
hex: "FFFFFF"
- id: cyan
hex: "00E5FF"
- id: green
hex: "4CAF50"
- id: yellow
hex: "FFC107"
- id: orange
hex: "FF9800"
- id: red
hex: "F44336"
- id: blue
hex: "2196F3"
- id: gray
hex: "9E9E9E"
sensor:
- platform: uptime
name: "${friendly_name} Uptime"
entity_category: diagnostic
- platform: wifi_signal
name: "${friendly_name} WiFi"
id: wifi_db
entity_category: diagnostic
# Brillo automático según hora
interval:
- interval: 60s
then:
- lambda: |-
auto now = id(sntp_time).now();
if (!now.is_valid()) return;
float b = 0.4;
if (now.hour >= 23 || now.hour < 7) b = 0.05;
else if (now.hour < 9) b = 0.15; else if (now.hour >= 21) b = 0.20;
id(backlight).set_level(b);¿Por qué external_components? El ESP8266 tiene muy poca RAM. El componente st7789v-fractional-framebuffer renderiza la pantalla en trozos (fragmentos) en vez de guardar toda la imagen en memoria. Sin esto, el ESP se quedaría sin RAM y se reiniciaría constantemente.
Paso 3: Configuración por habitación
Cada display tiene su propio archivo que define qué sensores mostrar. Aquí un ejemplo completo para una cocina — crea smalltv-cocina.yaml:
substitutions:
device_name: smalltv-cocina
friendly_name: "SmallTV Cocina"
packages:
base: !include base-smalltv.yaml
sensor:
- platform: homeassistant
id: ha_temp
entity_id: climate.radiadorcocina
attribute: current_temperature
internal: true
- platform: homeassistant
id: ha_power
entity_id: sensor.consumo_actual
internal: true
- platform: homeassistant
id: ha_caldera
entity_id: sensor.tempcaldera_ds18b20_temperature
internal: true
text_sensor:
- platform: homeassistant
id: ha_occupancy
entity_id: binary_sensor.cocinasensor_occupancy
internal: true
- platform: homeassistant
id: ha_weather_state
entity_id: weather.aemet
internal: true
display:
- id: my_display
platform: st7789v
model: custom
spi_id: spihwd
height: 240
width: 240
offset_height: 0
offset_width: 0
fragmentation: 30
dc_pin: GPIO00
reset_pin: GPIO02
eightbitcolor: false
update_interval: 10s
spi_mode: mode3
data_rate: 40000000
auto_clear_enabled: true
lambda: |-
int W = it.get_width();
int H = it.get_height();
auto now = id(sntp_time).now();
it.printf(6, 4, id(font_small), id(cyan), "COCINA");
if (now.is_valid()) {
it.printf(W-6, 4, id(font_small), id(gray),
TextAlign::TOP_RIGHT, "%02d:%02d", now.hour, now.minute);
}
it.horizontal_line(0, 24, W, id(gray));
// Temperatura (grande)
if (!isnan(id(ha_temp).state)) {
it.printf(W/2, 38, id(font_big), id(white),
TextAlign::TOP_CENTER, "%.0f°C", id(ha_temp).state);
}
// Ocupación
auto occ_color = id(gray);
auto occ_text = "Sin movimiento";
if (id(ha_occupancy).has_state() &&
id(ha_occupancy).state == "on") {
occ_color = id(green);
occ_text = "Movimiento";
}
it.printf(6, 90, id(icon_font), occ_color, "\U000F0510");
it.printf(32, 92, id(font_small), occ_color, occ_text);
it.horizontal_line(6, 116, W-12, id(gray));
// Consumo eléctrico (colores según vatios)
if (!isnan(id(ha_power).state)) {
auto pwr_color = id(green);
if (id(ha_power).state > 2000) pwr_color = id(yellow);
if (id(ha_power).state > 3000) pwr_color = id(red);
it.printf(6, 124, id(icon_font), id(yellow), "\U000F0238");
it.printf(32, 126, id(font_medium), pwr_color,
"%.0fW", id(ha_power).state);
}
// Caldera + indicador duchas
if (!isnan(id(ha_caldera).state)) {
auto cal_color = id(cyan);
if (id(ha_caldera).state < 30) cal_color = id(red); it.printf(6, 154, id(icon_font), id(orange), "\U000F0D0B"); it.printf(32, 156, id(font_medium), cal_color, "%.0f°C", id(ha_caldera).state); if (id(ha_caldera).state >= 30) {
it.printf(100, 156, id(font_small), id(green), "Duchas OK");
}
}
it.horizontal_line(6, 184, W-12, id(gray));
// Weather
it.printf(6, 192, id(icon_font), id(blue), "\U000F0590");
if (id(ha_weather_state).has_state()) {
it.printf(32, 194, id(font_small), id(white),
"%s", id(ha_weather_state).state.c_str());
}Cómo adaptar los sensores a tu casa
Para mostrar datos de otra habitación, simplemente cambia los entity_id por los tuyos. Algunos tips:
- Temperatura de un termostato: Usa
attribute: current_temperatureen vez del estado (que sería el modo: heat/auto/off) - Sensores binarios (movimiento, presencia): Usa
text_sensorconplatform: homeassistanty compara con"on"/"off" - Colores dinámicos: Cambia el color según el valor — verde para normal, naranja para precaución, rojo para alarma
Paso 4: Secretos WiFi
Crea /config/esphome/secrets.yaml:
wifi_ssid: "TU_RED_WIFI"
wifi_password: "TU_PASSWORD"
api_key: "genera-una-al-crear-dispositivo"
ota_password: "tu-password-ota"
ap_password: "fallback123"Paso 5: Flasheo sin cables método WiFi (sin FTDI)
Si no tienes un adaptador FTDI o prefieres evitar abrir el dispositivo, hay una alternativa más sencilla. El GeekMagic SmallTV incluye de fábrica un interfaz web de configuración que permite subir firmwares personalizados (.bin) directamente vía WiFi, sin necesidad de soldar ni usar adaptadores USB-serie.
Este método funciona porque el firmware de fábrica incluye una función de actualización que no está firmada ni bloqueada, permitiendo cargar cualquier firmware ESPHome compatible.
– Preparar el firmware en ESPHome
Antes de tocar el dispositivo, necesitas generar el archivo .bin que vas a subir:
- En ESPHome Dashboard, crea un nuevo dispositivo (New Device)
- Selecciona “Import Configuration” o copia el YAML del paso 3 del tutorial
- Usa esta configuración mínima inicial (solo para el primer flasheo):
esphome: name: minitv friendly_name: "GeekMagic Mini-TV" esp8266: board: d1_mini wifi: ssid: !secret wifi_ssid password: !secret wifi_password api: ota: - platform: esphome logger: # Después del primer flasheo añades aquí tu configuración completa del display - Dale a “Install” → “Manual Download” → selecciona “Modern format”
- Descarga el archivo
.biny guárdalo en tu ordenador
Importante: Esta configuración inicial es mínima — solo conecta WiFi y habilita OTA/API. Una vez flasheado, actualizarás a tu configuración completa del display mediante OTA desde ESPHome.
– Subir el primer firmware ESPHome al dispositivo
El dispositivo de fábrica crea un punto de acceso propio:
- Conecta el SmallTV por USB-C (cargador de móvil vale)
- En tu móvil u ordenador, busca la red WiFi “GeekMagic-XXXX” (el nombre varía según el modelo)
- Conéctate a esa red — abrirá automáticamente el portal de configuración (si no, navega a
192.168.4.1) - Abre la opción settings y “Upload firmware” y elige el archivo
.binque descargaste del ESPHome Dashboard - Confirma y espera — el dispositivo flasheará el firmware y se reiniciará automáticamente
- Después de ~30-60 segundos, el dispositivo volverá a aparecer en tu red con el nuevo firmware ESPHome (aqui es probable que la pantalla se ponga en negro, es normal porque tiene el fw basico de ESPHome)
Paso 4: Actualizar a la configuración completa
Ahora que ya tienes ESPHome base instalado:
- Vuelve al ESPHome Dashboard — el dispositivo debería aparecer como “online” o podrás añadirlo manualmente con su IP
- Edita el YAML y añade toda la configuración del display (sensores de HA, fonts, display lambda, etc.) del Paso 3 del tutorial
- Dale a “Install → Wirelessly” para actualizar OTA con la configuración completa
Ventajas y limitaciones del método WiFi
✅ Ventajas:
- No necesitas adaptador FTDI ni soldar
- No hay que abrir el dispositivo ni perder la garantía
- Más rápido si tienes varios dispositivos para flashear
⚠️ Limitaciones:
- Si el firmware que subes está mal configurado (ej: WiFi incorrecto), el dispositivo puede quedar “brickado” y necesitarás el método FTDI para recuperarlo
- Algunas revisiones de hardware pueden tener el bootloader bloqueado (raro, pero posible)
- Verifica siempre que tu modelo tiene ESP8266/ESP32 antes de flashear firmware genérico
Método basado en la guía de SmarterKram.
Alternativa: Primer flasheo por USB (con FTDI)
La primera vez necesitas un conversor FTDI USB-Serial conectado a los pads del PCB:
- Abre el SmallTV (dos tornillos en la base)
- Conecta: GND→GND, TXD0→RX, RXD0→TX, 3V3→3.3V, GPIO0→GND (modo flash)
- En ESPHome dashboard: Install → Plug into this computer
⚠️ Importante: Usa 3.3V, NO 5V. El ESP8266 no lo soporta.
Paso 6: Actualizaciones OTA
Después del primer flasheo, todo es inalámbrico. Modifica el YAML → Install → Wirelessly → listo en ~1 minuto.
Si no encuentra el dispositivo por mDNS (común en algunos routers), añade la IP fija en el bloque wifi:
wifi:
use_address: 192.168.1.XXX # IP de tu SmallTVAsigna una IP estática desde tu router para que no cambie.
Paso 7: Integrar en Home Assistant
Al conectarse, HA detectará el nuevo dispositivo automáticamente en Ajustes → Dispositivos y servicios. Acéptalo y los sensores empezarán a fluir al display inmediatamente. También podrás controlar el brillo del backlight como una entidad de luz desde HA.
Ideas por habitación
| Ubicación | Qué mostrar |
|---|---|
| Cocina | Temperatura, movimiento, consumo eléctrico, caldera/duchas, tiempo |
| Pasillo | Temperatura + humedad, quién está en casa, alarma, consumo |
| Dormitorio | Temp+humedad del cuarto + del bebé, estado calefacción |
| Despacho | Temp+humedad, modo radiador, consumo, presencia, alarma |
| Rack servidor | CPU, RAM, temperatura discos, uso de red, uptime |
Problemas comunes y soluciones
- Display en blanco: Verifica que el dispositivo está integrado en HA. Sin conexión API, no llegan los datos.
- No muestra sensores: Comprueba que los
entity_idson correctos. Cópialos directamente desde HA → Ajustes → Entidades. - Se reinicia en bucle: El ESP8266 tiene poca RAM. Reduce sensores o sube
fragmentationa 40-50. - Error mDNS al flashear: Usa
use_addresscon la IP del dispositivo.
Conclusión
Por 12-15€ tienes un dashboard físico de Home Assistant en cada habitación. Sin cloud, sin apps, actualización inalámbrica, y totalmente personalizable. Una vez que lo pruebas, empiezas a querer uno en cada esquina de la casa.
Lo mejor es que todo corre 100% local — tus datos nunca salen de tu red. ESPHome se conecta directamente a Home Assistant sin pasar por ningún servidor externo. Eso es domótica como debe ser.
Basado en el componente st7789v-fractional-framebuffer y la comunidad Home Assistant.