A native Android dashboard "smart home remotes" — built for the Sanytron Astrion HA100 — that talks directly to Home Assistant over one WebSocket. It replaces the stock vendor app entirely.
No Lovelace, no embedded browser, no cloud. State changes land on the screen as fast as Home Assistant emits them, and the whole layout is one JSON file you can edit without rebuilding.
Status: in daily use on the author's device. Everything documented here is running on real hardware, not aspirational.
▶ Demo video + writeup on r/homeassistant — see it running on the actual remote.
Quick start: grab the APK from Releases, sideload it, then push a config with your own Home Assistant details — no build toolchain needed, just ADB. Full steps in docs/SETUP.md. Building from source is still supported and required if you want to change behaviour rather than layout.
What it does
| Live HA connection | One WebSocket: auth → get_states → subscribe_events. Auto-reconnects with backoff. ~450 entities tracked without lag. |
| Swipeable pages | Any number, defined in config. Instead of a fixed set of vendor-defined cards, you compose your own. |
| Tappable floorplan | Drop a floorplan image in, place dots by percentage coordinates, tap to toggle. Dots recolor live with state. |
| Physical buttons | Every hardware key mapped to HA services, IR blasts, page jumps, or device actions. Tap and long-press are separate. |
| Voice | Tap-to-talk into HA Assist (works with a local LLM). Client-side silence detection ends the recording. |
| Media | Transport controls for any HA media_player, plus Plex poster rows (On Deck / Recently Added) — tap to play on a TV client. |
| Battery reporting | The remote pushes its own battery level to HA as a sensor so you can alert before it dies. |
| Survives reality | Runs as the launcher, comes back after reboot or dead battery, and self-heals the accessibility service this firmware randomly drops. |
Cards
bubble_light · scene_grid · climate · cover · media_player · clock_weather ·
picture_elements (floorplan) · button_grid · plex
Adding a card type is one new file plus one line in CardRegistry.kt — see
docs/ARCHITECTURE.md.
Start here
| If you want to… | Read |
|---|---|
| Install it on your remote | docs/SETUP.md |
| Change pages, cards, entities, dots | docs/CONFIG.md |
| Make the buttons drive your TV | docs/IR-CODES.md |
| Know the device's quirks before they bite you | docs/HARDWARE.md |
| Understand or extend the code | docs/ARCHITECTURE.md |
| Recover a bricked/reset remote | recovery/RESTORE.md |
Short version: install JDK 17 + Android SDK, put your HA URL and a long-lived token in
app/src/main/res/raw/default_dashboard.json, run ./gradlew assembleRelease, sideload the
APK. Full detail — including the two commands people always forget — is in
docs/SETUP.md.
Hardware
Built and tested on the Sanytron Astrion HA100: Android 8.1, MediaTek MT6580, 1 GB RAM, 480×800 portrait touchscreen, IR blaster, and a full physical keypad. Sold under several names; if yours runs Android and has an IR blaster, most of this applies — the parts that are device-specific (keycodes, the IR bridge quirk) are called out in docs/HARDWARE.md.
It is a slow chip. Build release, never debug — the debug build is roughly 14× slower here and feels broken.
Configuration is the point
Pages, cards, entities, floorplan dot positions, colors, icons, and the physical button map
all live in default_dashboard.json. That file is baked into the APK and copied to
/sdcard/astrion/dashboard.json on first launch, then re-read every time the app resumes:
adb push dashboard.json /sdcard/astrion/dashboard.json
Reopen the app and the change is live. No rebuild. Only new card types or behavior changes need Kotlin.
Security
This app authenticates with a Home Assistant long-lived access token stored in plain text in the config file and compiled into the APK. That is a deliberate tradeoff for a wall-mounted device on a home LAN, but you should know what it means:
- Anyone with the APK or physical access to the device can read the token.
- A long-lived token is full control of your Home Assistant.
- Never commit your real config or a built APK to a public repo.
.gitignorecovers the obvious cases, but check before you push. - Consider a dedicated HA user with limited access rather than your admin account.
- If a token leaks, revoke it in HA (Profile → Security → Long-lived access tokens).
The same applies to the optional Plex token.
Why it asks for scary permissions
This app requests three permissions that would be alarming in a normal app. Each is granted manually over ADB — none can be enabled silently, and the app works (with the noted losses) if you skip them:
| Permission | Why | Skip it and… |
|---|---|---|
| Accessibility service | The firmware's pull-down shortcut launches the vendor app over the dashboard. The service detects that and bounces back, and rescues the Home button. | The vendor app hijacks the screen and you have to swipe back manually. |
| Device admin | The only API that lets an app turn the screen off, used for hold-power-to-sleep. | Hold-power-to-sleep does nothing; the screen sleeps on its own timeout. |
WRITE_SECURE_SETTINGS |
Re-enables the accessibility binding this firmware randomly drops, and keeps the firmware's hair-trigger wake gestures off. | You re-run two ADB commands by hand whenever the binding drops. |
No network destination other than your Home Assistant instance (and your Plex server, if you
configure the Plex card). Nothing is sent anywhere else — read
HaClient.kt and
BatteryReporter.kt if you want
to confirm that yourself.
Credit and license
MIT — see LICENSE.
Built on the shoulders of the Home Assistant community's reverse-engineering of these remotes.
The Plex card was adapted from baes-cloud/astrion-dashboard. Thanks Bae! That project is a parallel build on the same hardware and worth a look. It has card types this one doesn't.
Not affiliated with Sanytron, Home Assistant, or Plex. "Plex" is a trademark of Plex GmbH; no Plex artwork is redistributed here.
Comments