Convierte un GeekMagic SmallTV en un Mini Dashboard de Home Assistant por 15€

GeekMagic SmallTV mostrando dashboard de Home Assistant con ESPHome - temperatura, consumo y estado de la caldera

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:

  1. Ajustes → Complementos → Tienda de complementos
  2. Busca “ESPHome Device Builder”
  3. 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_temperature en vez del estado (que sería el modo: heat/auto/off)
  • Sensores binarios (movimiento, presencia): Usa text_sensor con platform: homeassistant y 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:

  1. En ESPHome Dashboard, crea un nuevo dispositivo (New Device)
  2. Selecciona “Import Configuration” o copia el YAML del paso 3 del tutorial
  3. 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
  4. Dale a “Install”“Manual Download” → selecciona “Modern format”
  5. Descarga el archivo .bin y 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:

  1. Conecta el SmallTV por USB-C (cargador de móvil vale)
  2. En tu móvil u ordenador, busca la red WiFi “GeekMagic-XXXX” (el nombre varía según el modelo)
  3. Conéctate a esa red — abrirá automáticamente el portal de configuración (si no, navega a 192.168.4.1)
  4. Abre la opción settings y “Upload firmware” y elige el archivo .bin que descargaste del ESPHome Dashboard
  5. Confirma y espera — el dispositivo flasheará el firmware y se reiniciará automáticamente
  6. 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:

  1. Vuelve al ESPHome Dashboard — el dispositivo debería aparecer como “online” o podrás añadirlo manualmente con su IP
  2. Edita el YAML y añade toda la configuración del display (sensores de HA, fonts, display lambda, etc.) del Paso 3 del tutorial
  3. 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:

  1. Abre el SmallTV (dos tornillos en la base)
  2. Conecta: GND→GND, TXD0→RX, RXD0→TX, 3V3→3.3V, GPIO0→GND (modo flash)
  3. 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 SmallTV

Asigna 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ónQué mostrar
CocinaTemperatura, movimiento, consumo eléctrico, caldera/duchas, tiempo
PasilloTemperatura + humedad, quién está en casa, alarma, consumo
DormitorioTemp+humedad del cuarto + del bebé, estado calefacción
DespachoTemp+humedad, modo radiador, consumo, presencia, alarma
Rack servidorCPU, 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_id son correctos. Cópialos directamente desde HA → Ajustes → Entidades.
  • Se reinicia en bucle: El ESP8266 tiene poca RAM. Reduce sensores o sube fragmentation a 40-50.
  • Error mDNS al flashear: Usa use_address con 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.