Architecture Decision Records¶
Page en anglais
Cette page n'existe qu'en anglais.
Lightweight ADRs capturing why a non-obvious choice was made in this codebase — not just what the code does (the code and Tab5/README.md/CARTOGRAPHIE_TAB5.md already say that), but the reasoning and the alternatives that were rejected. Written retroactively from the project's development history so an agent or contributor doesn't have to re-derive (or worse, re-litigate) a decision that was already made deliberately.
Kept in English only, unlike the rest of the docs, to stay short — these are an internal reference for contributors and AI agents, not user-facing documentation.
Format: Context / Decision / Consequences. One page max. Add a new one whenever you make a call that isn't obvious from reading the code alone, especially if you expect a future audit (human or AI) to flag it as a "bug."
Index¶
| # | Decision |
|---|---|
| 0001 | Push-only architecture, zero polling from the device |
| 0002 | Single LVGL page + swipe navigation instead of a multi-page tab bar |
| 0003 | Delimited-string payloads instead of one service call per data point |
| 0004 | No PNG alpha channel — pre-baked opaque backgrounds |
| 0005 | Blocking boot delay before the display reset sequence: 1 s on the Tab5 (display reset behind an I/O expander), none on the Waveshare 7B since 2026-10-17 (carte_attente_ecran_ms) |
| 0006 | All non-trivial LVGL logic centralized in C++, never inline in sensor lambdas |
| 0007 | climate_popup.yaml deliberately left un-factorized |
| 0008 | Single Home Assistant instance (Freebox) instead of a Deck failover |
| 0009 | Shared modal chrome + one compact title bar for every popup |
| 0010 | Microphone and speaker share one I2S bus — every local sound relays the mic itself |
| 0011 | api: reboot_timeout: 60min — anti-zombie net kept, HA outages no longer cycle the tablet |
| 0012 | Landscape dashboard via rotation: 270, one console flips to portrait at runtime |
| 0013 | One C++ registry lists the 8 consoles and the modal windows — no list is ever copied into YAML |
| 0014 | The 8 consoles share game_common.h; every console keeps its palette local; every engine has a Python mirror |
| 0015 | ~~OTA encrypted with the API key — plain uploads refused, no OTA password~~ (superseded by 0020) |
| 0016 | CI compiles with ESPHome latest on purpose — a free upstream canary |
| 0017 | ~~Public HA files hold placeholders only — real IDs in placeholders.yaml, HA runs rendered/~~ (placeholders superseded by 0024; the leak guard stays) |
| 0018 | Optional zones — a zone disappears only when HA confirms its entity does not exist |
| 0019 | Logical slots — the device knows slots, a Home Assistant blueprint maps them to entities |
| 0020 | No secret in the firmware — Home Assistant provisions the API key, OTA images are signed |
| 0021 | The screen is rendered off the tablet — the host platform, stubbed hardware, no firmware change |
| 0022 | Published firmware — signed in CI, a web flasher on GitHub Pages, stable and beta channels |
| 0023 | Rooms — each page of the five bottom tiles is a room of up to five devices, described by Home Assistant |
| 0024 | Packages without placeholders — every home value is picked in Home Assistant, the tablet is detected by its model |
| 0025 | Events only — the device never calls a Home Assistant action, one HA package maps its events to a whitelist |
| 0026 | The climate popup follows the device — settings pushed by HA (key climr), the screen's commands translated by the blueprint |
| 0027 | Every climate tile opens the climate popup for its own unit — settings (crRT) and state (ceRT) per tile, one translation of the commands |
| 0028 | An Energy popup for a solar installation — sensors picked in the blueprint, live values and production history (recorder statistics) pushed by HA while the popup is open |
| 0029 | Themes — one C++ palette (struct Palette, UIColor = the active one), role styles in the YAML instead of colours set on widgets, games stay dark |
| 0030 | A documentation website built from docs/ — MkDocs with Material, no plugin, the language split and the links done by tools/site/construire.py |
| 0031 | A row under the clock — up to three lines of four sensors plus the plants line, rotating with the central card, picked in the blueprint (hLI, hp, hd) |
| 0032 | A Temperature popup — the history of the two home-screen temperatures (24 h, 7 days, 30 days) and the forecast for the second one, pushed by HA from its recorder statistics while the popup is open |
| 0033 | The − / + tile of the climate card adjusts a device chosen on the tablet — the climate, up to eight devices picked in the blueprint (rN), or the tablet's volume |
| 0034 | Alerts of the central card — HA remembers each alert and its revision, a read alert comes back only when it changes, subscriptions and history live in HA |
| 0035 | A « Tab5 » integration, installed by HACS, puts the Home Assistant files in place in one click — the release asset carries the files, backup, configuration check and rollback, then the firmware of the same version |
| 0036 | A long press on a light, a shutter or a climate opens a wheel of quick actions around the tile — two rings: its commands and their families, then the « Maison » and « Détails » links |
| 0037 | A House popup — every room of the blueprint at once, one column per room, rows drawn and touched like the tiles, « Éteindre les lumières » in the title bar |
| 0038 | The climate popup is a carousel — one page per climate the tablet knows (one list, clims_enumerer()), opened by a tap on the room's temperature; the − / + list moves to a long press on the value |
| 0039 | The home gestures — the clock in three touch areas (hours, minutes, date), the tap and long press of the clock and of the three top buttons chosen in the blueprint (gestes key), screens or actions |
| 0040 | In HA mode, the climate card shows the room on screen — its temperature and humidity (pR, sensors picked in the room's section of the blueprint), and the − / + tile adjusts its climate (crpR / cepR, commands at cpR) |
| 0041 | The « Ok Nabu » panel takes lines like the row under the clock (nLI, np, nd), the hours tap shows its next line, and the row, the panel and the − / + tile scroll by choice (defil key) |
| 0042 | A long press on the central card opens a navigation wheel — six buttons (Alertes, Pièces, Appareils, Agenda, Tablette, Assistant), the families unfolding their screens, only what the home has; three new screens (lights, shutter, temperature) and a « roue » gesture |
| 0043 | A Weather popup — the forecast HA already pushes drawn as graphs on three pages (today's hours as a curve, ten days as low-to-high bars, details), pages like the Settings, contract unchanged |
| 0045 | Three settings — charging mode (quick charge only while the charger is on), animations (energy saving forces « Aucune »), eco Wi-Fi (WIFI_PS_MIN_MODEM on battery or always, never during a stream) |
| 0046 | Popups with pages — one shared brick (tab5_pages.cpp: swipe and page names at the top); the Lights and Shutters popups show the whole house, one page per room, rows drawn and touched like the tiles |
| 0047 | The Temperature popup draws the humidity with the temperature (longer fields of tab5_maj_historique, no new variable) and has one page per known temperature — tabs and a swipe |
| 0049 | A Cameras popup — a still image of each camera picked in the blueprint, refreshed every 5 s while the popup is open, one page per camera; the tablet asks for the entity_picture URLs (token rotated every 5 min) at the opening and every 4 min |
| 0048 | A tap on the room's temperature opens the quick-action wheel of a climate (the tile wheel's own code, any ClimRef), « Clims ▸ » to switch to another unit, « Détails » = the carousel on it |
| 0053 | The setup assistant also proposes the blueprint's home inputs (TV, phone battery, temperatures, climate, pots, weather, ESPHome name) only when Home Assistant has a single answer, and the « Tab5 · … » lists (a plausible choice for the four the package never guesses), set through select.select_option and checked |
| 0052 | A setup assistant in the « Tab5 » integration (a repair at first install, a box in its options) proposes up to five Home Assistant areas (ten since ADR-0066) with their tiles, temperature, humidity and climate, and writes the blueprint's automation into automations.yaml — never over an existing one unless asked, the YAML to paste when the file is not safe to write |
| 0051 | The zone left of the clock shows a content chosen in the blueprint (gauche key) — the voice controls, a chart of the coming hours or a compact music player, the next one by a tap on the second temperature or a zone_gauche_suivante gesture |
| 0050 | A music player popup for any media_player (centred card, cover, controls the player supports, one chip per chosen player), pushed by tab5_maj_lecteur, commands as esphome.tab5_lecteur events; a « now playing » bar over Ok Nabu; players chosen in a « Tab5 · … » list |
| 0056 | The remote popup drives up to four remotes chosen in the blueprint (the TV's, then « Autres télécommandes »), one page each with their names at the top and the shared swipe; keys keep the Samsung codes, the slot (tv, tv1…) is the page, and the blueprint translates them for an Apple TV / Freebox Player box (pad, playback row, volume, no apps) |
| 0055 | Fridges and freezers — two « Tab5 · … » lists (four appliances in all), levels decided by Home Assistant against food-safety norms (thresholds in one place, door left open, silent sensor, incidents), pushed by tab5_maj_froid: a « Froid » popup, central-card alerts and a fridge-alert icon blinking on the clock at the serious level |
| 0054 | Tracked sensors — any numeric sensor chosen in a « Tab5 · … » list, pushed by tab5_maj_suivi (24 h of hourly statistics, change of the day or over 24 h): a « Suivi » popup, one card each, and the first one as the « capteur » content left of the clock |
| 0057 | Cameras by room — the blueprint sends each camera's Home Assistant area and offline time (« nom|image|pièce|depuis », sixteen cameras), a room column from two rooms (swipe and dots inside the room, choice kept in NVS), the last image of each camera kept while the popup is open (8 MiB at most), « Hors ligne depuis … »; lot 2: a mosaic of four squares per page (thumbnails asked at 480 × 270, cropped or reduced to cover), tap = large, tap = back, one image at a time |
| 0058 | The Energy popup in four pages (Flux, Aujourd'hui, Production, Bilan): the power flow between solar, home, grid and battery, the sun's course with the day's forecast learned from the home's own production and the weather, and a balance with export and savings — two more actions, tab5_maj_energie_soleil and tab5_maj_energie_bilan, both optional on the Home Assistant side |
| 0062 | The Bilan page of the Energy popup in kWh: a « Grid battery » card for the calendar month (net, gauge centred on 0, end-of-month projection at the 7-day pace, share covered by the sun) and the net per hour / day of the month / month of the year with its running total; three fields at the end of the tab5_maj_energie_bilan payload (prod, conso, estime), calendar views, an optional home-consumption meter, and import / export estimated hour by hour by Home Assistant without grid meters; money only with a price |
| 0059 | An « AI server » popup — one local LLM server, sensors picked in ten « Tab5 · serveur IA, … » lists, pushed by tab5_maj_serveur_ia on change (two seconds apart at least), the tokens-per-second curve kept by the tablet, nothing repainted while it is closed |
| 0060 | Three buttons in the AI server popup — unload the model (Ollama, LM Studio), wake the PC (Wake-on-LAN), restart the service (a script or a button picked in a « Tab5 · … » list) — offered by Home Assistant in a 14th field (code / -code greyed), asked by one esphome.tab5_serveur_ia_action event, a second tap to unload or restart, one action every 5 s |
| 0063 | Several screens in one home: a name per screen (tab5_nom, tab5_nom_affiche, tab5-ha-hmi by default), a « Préfixe des actions » sensor published by the firmware, and every push of the packages and the blueprint sent in a loop to each connected tablet (tab5_destinataires()), a calendar answer to the screen that asked; what reads a tablet's own entities (sensor.tab5_tablette) still follows one |
| 0064 | Screen off means a black panel: a black veil drawn before LVGL pauses, then the DCS « display off » / « sleep in » the panel supports (carte_dalle_extinction per board and panel: 7B sleeps, the three Tab5 panels keep the veil only until tried), the 7B also black during an OTA; a night window chosen in a « Tab5 · extinction de nuit » list (00:00-06:00 by default, « Aucune » with a presence sensor) applied by the firmware's auto-off (1 min); first start at 75 % |
| 0061 | The board and its screen size are a compile-time choice: tab5_carte picks carte-<board>.yaml (hardware + geometrie-<board>.yaml: size, panel, LVGL rotation, scale of the large fonts), the size written once (tokens derived from it, -DTAB5_ECRAN_L/H for the C++), the hardware a board lacks kept as stubs with the same ids; the Waveshare ESP32-P4 7B (1024×600) runs on a board since 2026-10-14 (panel upside down: rotation 180) |
| 0065 | The games are an optional module: tab5-arcade.yaml brings their C++ files, pages, colours and chess font, picked by tab5_jeux (oui on the Tab5, non by default on a board without an IMU, the Waveshare 7B); without it tab5-arcade-absente.yaml gives the core the same plugs, empty, and the Arcade is no screen; the gamepad's « auto » tap then opens the audio player (Music popup), its long press stays the TV remote |
| 0066 | The number of rooms is chosen in Home Assistant (1 to 10, pn key; rooms beyond the fifth get a page after the weather days, drawn as in HA mode) and a room takes up to twenty elements: the last tiles of its list cut in two (top / bottom), then in four, every cell its own touch target, T keys 0-9 then a-j |
| 0067 | Whole-home HiFi in the Music popup through Music Assistant: a « Pièces » page (every output, eight, volume, power, groups, transfer, source) and a « Bibliothèque » page (favourites, playlists, albums, artists, radios, podcasts, recent; ten covers; play now / next / at the end / radio mode), pushed by tab5_maj_musique_pieces and tab5_maj_musique_liste in answer to one esphome.tab5_musique event; without Music Assistant, Pièces with the chosen players only |
| 0068 | Favourite playlists in the Music popup: « Name | link » lines in a blueprint input (eight at most), only the names pushed (playlists key of tab5_maj_emplacements), a second « Playlists » page through the shared page brick, a tap sends the rank (esphome.tab5_lecteur, action playlist) and the blueprint starts script.tab5_lecteur_playlist with the link: youtube://…?list= on an Apple TV's YouTube app, sequence measured on the author's Apple TV (standby, tvOS « Open in YouTube? » dialog answered with select) |
| 0069 | The screen direction of the Waveshare 7B is a device setting chosen in Home Assistant: « Sens de l'écran » (Normal / Retourné, kept in NVS, restored before the boot bar and LVGL), « Retourné » = 180° more than the board's rest angle while running (LvglComponent::set_rotation, the touch follows); at 0° the frame goes to the panel unrotated (~69 ms a full screen instead of ~83); a board mounted upside down runs the published firmware and follows the releases; the Tab5 keeps its compiled 270° |