GeekMagic 显示器 (SmallTV Pro/Ultra) 的 Home Assistant 集成。服务器端渲染,无需设备闪烁。
GeekMagic 显示器 (SmallTV Pro/Ultra) 的 Home Assistant 集成。服务器端渲染,无需设备闪烁。
A Home Assistant custom integration for GeekMagic displays (SmallTV Pro, Ultra, and similar ESP8266/ESP32-based devices).
How it works: This integration renders dashboard images directly in Home Assistant using Python/Pillow and pushes them to your GeekMagic device over HTTP. It supports the known stock firmware profiles and the newer SD_PRO-style firmware used by some Ultra units.
Early Software: This project is in active development. Expect bugs, breaking changes, and incomplete features. The API and configuration format may change between versions.
Vibe Coded: This integration was largely vibe-coded with AI assistance. While functional, it may contain unconventional patterns or rough edges. Contributions and feedback welcome!
I have a GeekMagic Ultra with ESP8266, which has limited possibilities for flashing with ESPHome. Instead of fighting the hardware, this integration takes a different approach: render everything server-side and push images to the device.
Special thanks to:
The same dashboards in the StandBy theme (widgets on translucent cards) and the Night theme (a single red ramp for the bedside, overriding every widget colour):
Binary sensors display human-readable states and state-specific icons based on their device_class. Icons are sourced from Home Assistant's official icon definitions.
Entities like lights, switches, and fans show different icons based on their state (on/off).
| Widget | 1x1 | 1x2 | 2x1 | 2x2 | 2x3 | 3x3 |
|---|---|---|---|---|---|---|
| Gauge (Bar) | ||||||
| Gauge (Ring) | ||||||
| Gauge (Arc) | ||||||
| Entity (Icon) | ||||||
| Entity (Plain) | ||||||
| Clock | ||||||
| Text | ||||||
| Progress | ||||||
| Weather | ||||||
| Status | ||||||
| Chart | ||||||
| Candlestick | ||||||
| Climate | ||||||
| Attribute List |
Display OHLC (Open/High/Low/Close) candlestick charts from any numeric entity's history. Configurable candle intervals (1 hour, 4 hours, 1 day) and count.
All rendering is powered by the Blitz HTML/CSS engine via blitz-py (Stylo + Taffy + Parley + Vello — no browser). Every widget is an HTML fragment rasterized per-cell, so real CSS drives the design: flexbox, gradients, glows, border-radius, media queries, SVG charts, embedded fonts. Each cell is its own CSS viewport — one widget template adapts fluidly from a 76px 3×3 cell to 240px fullscreen, shedding detail bands as space runs out. Themes are full stylesheets (fonts, chrome, backdrops, overlay effects like CRT scanlines), not just palettes.
blitz-py ships prebuilt wheels on PyPI (Linux glibc/musl x86_64 +
aarch64, macOS, Windows) and installs automatically with the
integration.
Design your own cells with HTML/CSS + Jinja. A 240×240 cell renders in ~20-40ms.
Modern CSS works: gradients (linear/radial/conic), border-radius,
box-shadow glows, translucent rgba() fills and borders, flexbox,
CSS grid, media queries, and viewport units.
Each cell is its own CSS viewport, so one template adapts to every cell
size — vmin/vw scale the type with the cell, and media queries shed
detail when space runs out. A built-in fluid kit is injected into every
document:
| Class | Purpose |
|---|---|
.cell |
Flex-column scaffold filling the cell (space-evenly); add .row for horizontal |
.t-hero |
Primary value — scales with cell size, capped by width |
.t-value |
Secondary emphasized value |
.t-unit |
Unit suffix, secondary color |
.t-label |
Caps caption, tertiary color |
.hide-short |
Hidden when the cell is under 100px tall |
.hide-narrow |
Hidden when the cell is under 100px wide |
.hide-small |
Hidden when either dimension is under 130px |
The same template at fullscreen, 2×2, and 3×3 — hero scales, captions and detail bands drop out automatically:
Samples are generated by scripts/generate_html_samples.py.
The HTML option is a Jinja template with access to entity data:
state, name, unit, attributes — the widget's configured entitystates('sensor.x'), state_attr('sensor.x', 'attr'), is_state('sensor.x', 'on') —
any referenced entity is tracked and pre-fetched automaticallynow — timezone-aware current datetimevar(--text-primary), var(--text-secondary),
var(--text-tertiary), var(--primary), var(--success), var(--warning),
var(--error), var(--info), var(--muted), var(--bg)Limitations: no JavaScript, no network fetches (use data: URIs for
images), no background-clip: text, no text-shadow.
Turn on the device's Animations switch entity and any HTML widget
with its Animate option enabled renders its CSS animations
(@keyframes, transitions) to a looping animated GIF which the display
plays natively. Views without animated widgets keep the smaller/faster
JPEG path, and static cells in an animated view are rendered once and
shared across frames. The Animation Loop option sets the loop
length (0.8–4s; the view uses the longest loop among its widgets, at
10fps up to 2s and 7fps beyond).
Favor ambient motion over movement — glows that breathe, gradients
that drift, colors that shift. Opacity, background-color, text
color, box-shadow, and background-position all interpolate:
Seamless-loop rules: animation durations should equal (or evenly divide) the loop length, and drifting gradients must tile — use a 90° gradient whose first and last color stops match (diagonal gradients show a seam when the tile repeats).
Animations are off by default: a GIF costs upload size (~100KB vs ~30KB JPEG) and device decode time.
Choose from 17 built-in themes that go beyond just colors — they apply a complete design system: typography (rounded Nunito font on most themes), spacing, shapes, tinted gauge tracks, and visual effects.
The default watchOS theme is inspired by Apple's watchOS Human Interface Guidelines: true-black background, Apple system colors (red/orange/yellow/green/mint/teal/cyan/blue/indigo/purple/pink), opacity-based text hierarchy, tinted Activity-ring style gauges, and no card chrome — widgets float on the background for maximum information density. StandBy is the same system on translucent cards, like iOS StandBy widgets; Night is a red-on-black bedside mode that overrides every widget colour.
| watchOS | StandBy | Night | Classic | Minimal | Neon | Retro | Soft |
|---|---|---|---|---|---|---|---|
| Default — Apple watchOS HIG-inspired | Subtle card chrome, system colors | Sharp, monochrome | Cyberpunk with glow | Terminal scanlines | Cozy, very rounded |
| Ocean | Sunset | Forest | Light | Candy |
|---|---|---|---|---|
| Deep blue, nautical | Warm coral/orange | Natural earth tones | Clean white background | Playful pastels |
| Blueprint | Ink | Aurora | Brutal |
|---|---|---|---|
| Engineering drawing on drafting-grid paper | Warm newsprint with one pot of red ink | Luminous mesh-gradient poster, frosted glass | Neo-brutalism: hard borders, harder shadows |
custom_components/geekmagic to your Home Assistant's custom_components folderAfter installation, a GeekMagic item appears in your sidebar.
Create and manage display views:
The editor provides a live preview and widget configuration:
Assign views to your GeekMagic devices:
Each device exposes entities for brightness, refresh interval, mode selection, and status:
Each GeekMagic device creates the following entities for control and monitoring:
| Entity | Type | Description |
|---|---|---|
number.geekmagic_brightness |
Number | Display brightness (0-100%) |
number.geekmagic_refresh_interval |
Number | Update interval (5-300 seconds) |
number.geekmagic_cycle_interval |
Number | View cycle interval (0 = manual only) |
select.geekmagic_mode |
Select | Device mode (Custom Views, Clock, Weather, System Info) |
select.geekmagic_current_view |
Select | Currently displayed view (when in Custom mode) |
switch.geekmagic_active |
Switch | Enable/disable the display (sleep/wake) |
switch.geekmagic_view_cycling |
Switch | Enable/disable automatic view cycling |
| Entity | Type | Description | |--------|
暂无开放 Issues,或尚未同步最近议题。