Test du TRMNL OG, l’écran e-ink sobre et personnalisable

Publié le 15 mai 2026 Temps de lecture : 13 min.

Beaucoup d’entre vous m’ont mentionné le TRMNL après mon article sur la tablette murale Home Assistant. Concept simple : un écran e-ink sans rétroéclairage qui affiche exactement ce que vous voulez, depuis un portail web. J’ai testé le modèle OG pendant plusieurs semaines (concours en fin d’article !).

Présentation du TRMNL OG

Le TRMNL OG est un écran e-ink de 7,5 pouces (800×480 pixels) dans un boîtier plastique avec un pied amovible. Il est disponible en plusieurs coloris : noir, blanc, transparent, sauge, gris et bordeaux. J’ai choisi le blanc, qui s’intègre bien sur un mur de cuisine ou dans un bureau sans attirer l’attention. C’est l’idée : l’écran se fond dans le décor plutôt que de le dominer.

L’écran fonctionne en 1-bit noir et blanc, sans rétroéclairage. Il ne consomme de l’énergie qu’au moment du rafraîchissement. Concrètement : l‘appareil se réveille à intervalles configurables, télécharge une image bitmap depuis le cloud TRMNL, l’affiche sur l’écran, puis se rendort. C’est ce principe qui rend possible une autonomie de plusieurs mois sur une seule charge.

Il est proposé à partir de 120,95€ avec livraison gratuite en Europe. Deux options s’ajoutent à la commande : le Battery Upgrade (+8,95€, passe la batterie de 1 800 mAh à 2 500 mAh) ou le Clarity Kit (+21,95€, qui regroupe le Battery Upgrade, la Developer Edition et un câble USB-C).

TRMNL OG (Code : ANTOINE15)

108 €

L’option Developer Edition débloque la création de plugins privés sur mesure, j’y reviens dans la section dédiée aux dashboards. Si vous ne la prenez pas à la commande, il est possible de l’ajouter après coup via trmnl.com/upgrade.

Deux points qui comptent pour moi sur le long terme. Le firmware est open source sous licence GPL-3. Le BYOS (Bring Your Own Server) est possible : on peut héberger son propre serveur TRMNL chez soi. Si la boîte fermait demain, les appareils continueraient de fonctionner. C’est une garantie rare sur ce type de produit !

Configuration et prise en main

Au premier allumage, l’écran affiche le numéro de firmware installé et une instruction simple : connecter son téléphone ou son ordinateur au réseau WiFi « TRMNL ». Un portail captif s’ouvre automatiquement. On choisit son réseau, on entre le mot de passe. J’ai mis l’appareil sur mon SSID IoT, pas de friction de ce côté.

Une fois connecté au réseau, on associe l’appareil à son compte depuis trmnl.com. Toute la gestion se fait ensuite depuis ce portail web, disponible en français. On y voit ses playlists actives, l’état de la batterie, l’historique d’activité de l’appareil.

Note : quand j’ai configuré mon appareil, il n’existait pas encore d’application mobile TRMNL. Une app est disponible depuis, la procédure d’activation a peut-être évolué.

Les plugins natifs et les playlists

Le catalogue compte plus de 2 700 plugins : météo, prix du Bitcoin, Google Calendar, flux RSS, stats YouTube, Strava, suivi de colis, et des dizaines d’autres dans des domaines très variés.

Chaque plugin se configure en quelques clics depuis le portail. Pour la météo, on entre sa ville. Pour Google Calendar, on autorise l’accès. Rien de compliqué pour la grande majorité, c’est vraiment du plug & play ! Ces plugins s’organisent en playlists. L’appareil les fait défiler à la fréquence choisie.

Il y a aussi les mashups, qui permettent d’afficher plusieurs widgets simultanément selon plusieurs mises en page. Je n’ai pas trop exploité cette option : à 800×480 pixels, le plein écran reste bien plus lisible dès qu’on affiche des données un peu denses. Au-delà de deux ou trois blocs, ça devient vite chargé.

Le taux de rafraîchissement est configurable par plugin. Plus il est fréquent, plus la batterie s’use. Sur les plugins peu changeants comme la météo, un rafraîchissement toutes les heures suffit. Sur un dashboard énergie qui évolue au fil de la journée, je suis passé à toutes les 15 minutes.

Intégration Home Assistant

Depuis la mise à jour Home Assistant 2026.4, une intégration officielle TRMNL est disponible. Elle surveille le niveau de batterie de l’appareil depuis HA, permet de contrôler le sleep mode (heure de début et de fin) via une automatisation, et expose la présence du device comme entité utilisable dans vos scènes.

La limite est franche : cette intégration ne permet pas de piloter la playlist depuis Home Assistant. Impossible de dire « à 8h du matin, bascule sur le plugin énergie ». La rotation reste gérée exclusivement depuis le portail TRMNL, avec ses règles de planification intégrées.

J’aurais adoré pouvoir gérer les deux de cette manière, peut être via le BYOS (à tester).

TRMNL OG (Code : ANTOINE15)

108 €

Créer ses propres dashboards

C’est là que le TRMNL prend tout son sens pour un profil un peu bidouilleur. Avec la Developer Edition, on débloque la création de plugins privés.

Le principe : on définit un template HTML avec le moteur Liquid dans le portail, on choisit comment les données arrivent (webhook, polling, statique et plusieurs autres modes), le TRMNL affiche le résultat.

Plugin Radarr : afficher les derniers films téléchargés

Il récupère les derniers films ajoutés sur mon instance Radarr. Un script tourne sur mon serveur Docker, il interroge l’API Radarr à fréquence régulière et envoie les données en webhook vers TRMNL. Sur le portail, j’ai défini un template qui affiche une liste avec le titre du film, le format d’encodage et la date d’ajout. Toutes les 4 heures, la liste se met à jour.

Voici le code pour l’affichage côté TRMNL :

<div class="layout">
  <div class="columns">
    <div class="column">
      <span class="label">Films récemment ajoutés</span>
      <table class="table">
        <thead>
          <tr>
            <th><span class="label label--small">Titre</span></th>
            <th><span class="label label--small">Qualité</span></th>
            <th><span class="label label--small">Date</span></th>
          </tr>
        </thead>
        <tbody>
          {% for record in records %}
          <tr>
            <td><span class="title title--small">{{ record.title }}</span></td>
            <td><span class="label">{{ record.quality }}</span></td>
            <td><span class="label">{{ record.date | date: "%d/%m" }}</span></td>
          </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
  </div>
</div>
<div class="title_bar">
  <img class="image" src="https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/radarr.svg">
  <span class="title">Radarr</span>
  <span class="instance">Films récents</span>
</div>

Et le code pour l’appel API à héberger sur un serveur, un mini PC :

#!/bin/bash
RADARR_URL="XXX"
RADARR_KEY="XXX"
TRMNL_UUID="XXX"
TRMNL_KEY="XXX"

DATA=$(curl -s "$RADARR_URL/api/v3/history?pageSize=200&sortKey=date&sortDirection=descending&eventType=3" \
  -H "X-Api-Key: $RADARR_KEY" | jq '{
    records: [
      .records
      | group_by(.movieId)
      | map(.[-1])
      | sort_by(.date)
      | reverse
      | .[0:6]
      | .[]
      | {
          title: (.data.importedPath | split("/")[2] | gsub(" \\([0-9]{4}\\)$"; "")),
          quality: .quality.quality.name,
          date: .date
        }
    ]
  }')

curl -s -X POST "https://usetrmnl.com/api/custom_plugins/$TRMNL_UUID" \
  -H "Authorization: Bearer $TRMNL_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"merge_variables\": $DATA}"

Il vous reste à remplacer les 4 variables dans le script à savoir l’URL de votre instance Radarr ainsi qu’une clé API. Côté TRMNL, l’UUID correspond à celui du plugin (on le trouve dans la sidebar) et la Key est à retrouver dans vos réglages développeurs sur votre compte TRMNL.

Une tâche cron pour activer tout cela et le tour est joué !

Plugin Home Assistant : afficher les infos de vos entités (exemple : énergie)

Le deuxième est un dashboard d’énergie qui remonte des données depuis Home Assistant. Pour ceux qui me suivent, c’est une version condensée de cet article : consommation du jour, puissance solaire en cours, production totale de la journée, prévisions Solcast pour aujourd’hui et demain, etc. Un webhook envoyé depuis HA toutes les 15 minutes tient le dashboard à jour.

Voici le code pour l’affichage côté TRMNL :

<div class="layout">
  <div class="columns">

    <div class="column">

      <span class="label">Consommation</span>
      <table class="table">
        <tbody>
          <tr>
            <td><span class="label label--small">Aujourd'hui</span></td>
            <td><span class="title title--small">{{ conso_jour }} kWh</span></td>
          </tr>
          <tr>
            <td><span class="label label--small">Réseau</span></td>
            <td><span class="label">{{ reseau_w }}</span></td>
          </tr>
        </tbody>
      </table>

      <span class="label" style="margin-top: 12px; display: block;">Solaire</span>
      <table class="table">
        <tbody>
          <tr>
            <td><span class="label label--small">Puissance PV</span></td>
            <td><span class="title title--small">{{ pv_w }} W</span></td>
          </tr>
          <tr>
            <td><span class="label label--small">Produit aujourd'hui</span></td>
            <td><span class="title title--small">{{ prod_jour }} kWh</span></td>
          </tr>
        </tbody>
      </table>

      <span class="label" style="margin-top: 12px; display: block;">Prévisions Solcast</span>
      <table class="table">
        <tbody>
          <tr>
            <td><span class="label label--small">Aujourd'hui</span></td>
            <td><span class="title title--small">{{ sc_today }} kWh</span></td>
          </tr>
          <tr>
            <td><span class="label label--small">Demain</span></td>
            <td><span class="title title--small">{{ sc_tomorrow }} kWh</span></td>
          </tr>
        </tbody>
      </table>

    </div>

    <div class="column">

      <span class="label">Batteries</span>
      <table class="table">
        <thead>
          <tr>
            <th><span class="label label--small">Batterie</span></th>
            <th><span class="label label--small">SOC</span></th>
            <th><span class="label label--small">État</span></th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td><span class="label label--small">IzyPower</span></td>
            <td><span class="label">{{ izy_soc }}%</span></td>
            <td><span class="label">{{ izy_state }}</span></td>
          </tr>
          <tr>
            <td><span class="label label--small">Zendure AC</span></td>
            <td><span class="label">{{ zen_ac_soc }}%</span></td>
            <td><span class="label">{{ zen_ac_state }}</span></td>
          </tr>
          <tr>
            <td><span class="label label--small">Zendure AC+</span></td>
            <td><span class="label">{{ zen_acp_soc }}%</span></td>
            <td><span class="label">{{ zen_acp_state }}</span></td>
          </tr>
        </tbody>
      </table>

      <span class="label" style="margin-top: 12px; display: block;">Tempo EDF</span>
      <table class="table">
        <tbody>
          <tr>
            <td><span class="label label--small">Aujourd'hui</span></td>
            <td><span class="title title--small">{{ tempo_today }}</span></td>
          </tr>
          <tr>
            <td><span class="label label--small">Demain</span></td>
            <td><span class="title title--small">{{ tempo_tomorrow }}</span></td>
          </tr>
          <tr>
          </tr>
        </tbody>
      </table>

    </div>

  </div>
</div>

<div class="title_bar">
  <img class="image" src="https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/svg/home-assistant.svg">
  <span class="title">Home Assistant</span>
  <span class="instance">Énergie · màj {{ updated_at }}</span>
</div>

Et voici aussi le code pour Home Assistant (un peu plus costaud) :

#!/bin/bash

HA_URL="XXX"
HA_TOKEN="XXX"
TRMNL_UUID="XXX"
TRMNL_KEY="XXX"


# ── Helpers ──────────────────────────────────────────────────────────────────

ha_state() {
  curl -s "${HA_URL}/api/states/$1" \
    -H "Authorization: Bearer ${HA_TOKEN}" \
    -H "Accept: application/json" \
    | jq -r '.state // empty'
}

bat_state() {
  echo "$1" | awk '{
    v=$1+0
    if (v>10)       print "Décharge"
    else if (v<-10) print "Charge"
    else            print "Veille"
  }'
}

signed() {
  echo "$1" | awk '{
    v=int($1)
    if (v>=0) printf "+%d W", v
    else      printf "%d W", v
  }'
}

# ── Production & Réseau ──────────────────────────────────────────────────────

CONSO_JOUR=$(ha_state "sensor.izypower_consommation_jour")
PV_W=$(ha_state "sensor.izypower_puissance_pv")
RESEAU_W=$(signed "$(ha_state "sensor.izypower_puissance_reseau")")
PROD_JOUR=$(ha_state "sensor.izypower_production_jour")

# ── Batteries ────────────────────────────────────────────────────────────────

IZY_SOC=$(ha_state "sensor.izypower_etat_de_charge_batterie")
IZY_W=$(ha_state "sensor.izypower_puissance_batterie")
IZY_STATE=$(bat_state "$IZY_W")

ZEN_AC_SOC=$(ha_state "sensor.sf2400ac_635_electric_level")
ZEN_AC_W=$(ha_state "sensor.zendure_ac_635_puissance_affichage")
ZEN_AC_STATE=$(bat_state "$ZEN_AC_W")

ZEN_ACP_SOC=$(ha_state "sensor.sf2400ac_856_electric_level")
ZEN_ACP_W=$(ha_state "sensor.zendure_ac_856_puissance_affichage")
ZEN_ACP_STATE=$(bat_state "$ZEN_ACP_W")

# ── Tempo ─────────────────────────────────────────────────────────────────────

TEMPO_TODAY=$(ha_state "sensor.rte_tempo_couleur_actuelle")
TEMPO_TOMORROW=$(ha_state "sensor.rte_tempo_prochaine_couleur")
TEMPO_BLANC_J=$(ha_state "sensor.rte_tempo_cycle_jours_restants_blanc")
TEMPO_ROUGE_J=$(ha_state "sensor.rte_tempo_cycle_jours_restants_rouge")

# ── Solcast ──────────────────────────────────────────────────────────────────

SC_TODAY=$(curl -s "${HA_URL}/api/states/sensor.solcast_pv_forecast_previsions_pour_aujourd_hui" \
  -H "Authorization: Bearer ${HA_TOKEN}" | jq -r '(.state | tonumber? // 0) * 100 | round / 100 | tostring')

SC_TOMORROW=$(curl -s "${HA_URL}/api/states/sensor.solcast_pv_forecast_previsions_pour_demain" \
  -H "Authorization: Bearer ${HA_TOKEN}" | jq -r '(.state | tonumber? // 0) * 100 | round / 100 | tostring')

UPDATED_AT=$(date +"%H:%M")

# ── Push ──────────────────────────────────────────────────────────────────────

DATA=$(jq -n \
  --arg  conso_jour    "$CONSO_JOUR" \
  --arg  pv_w           "$PV_W" \
  --arg  reseau_w       "$RESEAU_W" \
  --arg  prod_jour      "$PROD_JOUR" \
  --arg  izy_soc        "$IZY_SOC" \
  --arg  izy_state      "$IZY_STATE" \
  --arg  zen_ac_soc     "$ZEN_AC_SOC" \
  --arg  zen_ac_state   "$ZEN_AC_STATE" \
  --arg  zen_acp_soc    "$ZEN_ACP_SOC" \
  --arg  zen_acp_state  "$ZEN_ACP_STATE" \
  --arg  tempo_today    "$TEMPO_TODAY" \
  --arg  tempo_tomorrow "$TEMPO_TOMORROW" \
  --arg  tempo_blanc_j  "$TEMPO_BLANC_J" \
  --arg  tempo_rouge_j  "$TEMPO_ROUGE_J" \
  --arg  sc_today      "$SC_TODAY" \
  --arg  sc_tomorrow   "$SC_TOMORROW" \
  --arg  updated_at     "$UPDATED_AT" \
  '{
    conso_jour:    $conso_jour,
    pv_w:          $pv_w,
    reseau_w:      $reseau_w,
    prod_jour:     $prod_jour,
    izy_soc:       $izy_soc,
    izy_state:     $izy_state,
    zen_ac_soc:    $zen_ac_soc,
    zen_ac_state:  $zen_ac_state,
    zen_acp_soc:   $zen_acp_soc,
    zen_acp_state: $zen_acp_state,
    tempo_today:   $tempo_today,
    tempo_tomorrow:$tempo_tomorrow,
    tempo_blanc_j: $tempo_blanc_j,
    tempo_rouge_j: $tempo_rouge_j,
    sc_today:      $sc_today,
    sc_tomorrow:   $sc_tomorrow,
    updated_at:    $updated_at
  }')

curl -s -X POST "https://usetrmnl.com/api/custom_plugins/${TRMNL_UUID}" \
  -H "Authorization: Bearer ${TRMNL_KEY}" \
  -H "Content-Type: application/json" \
  -d "{\"merge_variables\": ${DATA}}"

Même chose que pour Radarr, n’oubliez pas de changer les variables en haut (et bien sûr à adapter).

Pour les deux plugins, je me suis largement appuyé sur Claude pour écrire les scripts et les templates. Sans IA, ça aurait demandé bien plus de temps. Avec quelques échanges, les webhooks tournaient. C’est pour moi une approche accessible, même sans être développeur de métier.

Autonomie en conditions réelles

J’ai pris le Battery Upgrade (2 500 mAh). Après plusieurs semaines avec un sleep mode de 8 heures par nuit et un rafraîchissement toutes les 15 minutes sur le dashboard HA, la batterie affiche encore 35%.

C’est LA force du TRMNL sur ce segment : on pose l’appareil quelque part et on l’oublie. Pas de câble à gérer, pas de surveillance quotidienne. L’appareil envoie un email quand la batterie approche du seuil bas, ce qui évite la mauvaise surprise. Les 6 mois annoncés avec le Battery Upgrade semblent crédibles si on opte pour un rafraîchissement moins fréquent que le mien.

Ce qui manque sur le TRMNL OG : un bouton pour interagir

Le vrai défaut que j’ai ressenti à l’usage : l’absence totale d’interaction. Pas de bouton de navigation, pas de tactile, rien. On passe devant l’écran, il affiche ce qu’il affiche.

Dans les faits, ça m’est arrivé plusieurs fois d’avoir envie de passer au plugin suivant en passant devant, ou de déclencher un rafraîchissement à un moment précis. Impossible sur l’OG. Ce n’est pas rédhibitoire pour un usage passif, mais il faut bien l’intégrer avant d’acheter : le TRMNL n’est pas une tablette murale.

Tablette murale pour Home Assistant : mon installation DIY pour moins de 100€

Ce sont deux objets complémentaires, pour des usages différents. Sur la tablette, j’interagis, je pilote, je déclenche des automatisations. Sur le TRMNL, je consulte.

Le TRMNL X, sorti depuis, corrige justement ce point. Il ajoute une barre tactile pour naviguer entre les plugins, un écran plus grand avec une meilleure définition, retire le logo de la marque sur l’avant du boîtier, ajoute une protection étanche et supporte l’orientation portrait. Ce sont précisément les retours de la communauté sur l’OG !

Côté flicker : le clignotement noir complet à chaque rafraîchissement est inhérent à la technologie e-ink. Ça ne m’a pas gêné une fois passé les premiers jours, on s’y habitue très vite.

Code promo et concours 🎁

Bonne nouvelle si vous êtes convaincu : le code ANTOINE15 donne 15$ de réduction sur votre commande. Il suffit de passer par ce lien.

Et si vous préférez tenter votre chance avant d’acheter, j’organise un concours pour gagner un TRMNL OG avec le Clarity Kit complet (Battery Upgrade et Developer Edition inclus). Deux façons de participer :

Vous pouvez cumuler les deux pour doubler vos chances. Bonne chance à tous ! Le tirage au sort aura lieu le 22 mai 2026.

Mon avis sur le TRMNL OG : une belle découverte

Le TRMNL s’est installé naturellement chez moi. Il vient se fondre dans le décor, on l’oublie, on y jette un œil en passant pour récupérer l’info dont on a besoin. Pas de distraction, pas de lumière qui attire le regard. C’est exactement le positionnement annoncé et il tient ses promesses.

Je le recommande surtout à ceux qui ont envie de créer leurs propres dashboards. C’est là que le produit devient vraiment utile. Avec un peu d’aide de l’IA pour coder les webhooks, c’est accessible même sans background développeur. Pour un usage exclusivement natif avec les plugins du catalogue, c’est déjà sympa, mais ça reste davantage un gadget qu’un outil.

Le firmware open source et le BYOS sont des arguments solides sur le long terme. On n’est pas pieds et poings liés à un cloud qui peut fermer du jour au lendemain.

Si vous avez des questions sur la configuration ou les dashboards custom, les commentaires sont là pour ça ☺️

TRMNL OG

4.5/ 5

Écran e-ink 7,5 pouces sans rétroéclairage, autonomie de plusieurs mois, pilotable via portail web. Idéal pour afficher vos propres données depuis Home Assistant ou n'importe quelle API.

Avantages

- Personnalisable à souhait
- Autonomie de 6 mois
- Mode développeur (avec API)

Inconvénients

- Absence de bouton

Cet article contient des liens affiliés. Si vous effectuez un achat via ces liens, je touche une petite commission sans frais supplémentaires pour vous.

Laisser un commentaire