python-mister-fpga
Async Python client for the mrext Remote API (REST + WebSocket) and optional SSH telemetry for the MiSTer FPGA. Zero Home Assistant dependency — use it in any Python project.
Install
pip install python-mister-fpga
Usage
REST client
import asyncio
from mister_fpga import MisterClient
async def main():
client = MisterClient("192.168.1.50")
status = await client.async_get_status()
print(status.core, status.game)
await client.async_launch_game("/media/fat/games/SNES/Chrono.sfc")
await client.async_close()
asyncio.run(main())
WebSocket (real-time updates)
import asyncio
from mister_fpga import MisterWebSocketClient, MisterStatus, apply_ws_message
state = MisterStatus(online=True)
menu_path = None
index_state = (False, False)
def on_message(text: str) -> None:
global state, menu_path, index_state
state, menu_path, index_state = apply_ws_message(text, state, menu_path, index_state)
print(state.core, state.game)
async def main():
ws = MisterWebSocketClient("192.168.1.50")
await ws.listen(on_message)
asyncio.run(main())
SSH telemetry
import asyncio
from mister_fpga import MisterSSH
async def main():
ssh = MisterSSH("192.168.1.50", 22, "root", "1")
data = await ssh.async_probe()
print(data)
await ssh.async_close()
asyncio.run(main())
Main health, volume and Super Attract Mode (SSH)
data = await ssh.async_probe()
data["cmd_fifo_pending"] # >0 on two probes in a row: Main is hung
data["volume"], data["muted"], data["game_id"], data["sam_game"]
await ssh.async_set_volume(5) # 0-7, never blocks on a hung Main
await ssh.async_send_command("load_core /media/fat/menu.rbf")
Virtual gamepad (MiSTer Companion Remote daemon, port 9191)
from mister_fpga import MisterGamepad
pad = MisterGamepad("192.168.1.50")
await pad.async_press("start") # a real controller press: works in cores, menu, SAM
RetroAchievements events (odelot Main with debug=1)
from mister_fpga import MisterRA
ra = MisterRA(ssh)
offset, events = await ra.async_read_log(0) # login / game_identified / achievement / ...
RetroAchievements cloud stats
MisterRAWeb queries the public RetroAchievements.org Web API to pull a player's points, rank, recently-played games, and latest unlocked achievement — no SSH required. You need a Web API key from retroachievements.org/settings.
import asyncio
from mister_fpga import MisterRAWeb
async def main():
web = MisterRAWeb("myuser", "my_api_key")
stats = await web.async_fetch_stats()
print(stats.hardcore_points, stats.rank, stats.current_game)
await web.async_close()
asyncio.run(main())
MisterRAWeb(username, api_key, *, session=None, timeout=15)
Async HTTPS client for the RA Web API. When session is None the client creates its own aiohttp.ClientSession; call await web.async_close() to release it. Pass a shared session to manage its lifetime yourself.
| Method | Description |
|---|---|
await async_fetch_stats() -> MisterRAWebStats |
Fire all three API calls concurrently and return an aggregated stats snapshot. |
await async_validate() |
Lightweight credential check — raises MisterRAWebError if the username or API key is wrong. |
await async_get_badge_image(url) -> bytes |
Fetch a badge or icon image by absolute URL (e.g. stats.last_achievement.badge_url). |
await async_close() |
Close the session if this client created it. |
Dataclasses
MisterRAWebStats — aggregated snapshot returned by async_fetch_stats():
| Field | Type | Description |
|---|---|---|
hardcore_points |
int |
Total hardcore score. |
softcore_points |
int |
Total softcore score. |
rank |
int | None |
Global hardcore rank (None if unranked). |
total_ranked |
int | None |
Total number of ranked players. |
current_game |
RAGameProgress | None |
Most recently played game (first entry in the recent-games list). |
recent_games |
list[RAGameProgress] |
Up to 10 recently played games, most-recent first. |
last_achievement |
RAAchievement | None |
Most recently unlocked achievement (within the last 7 days). |
RAGameProgress — per-game achievement progress:
| Field | Type | Description |
|---|---|---|
game_id |
int |
RA game ID. |
title |
str |
Game title. |
console |
str |
Console name (e.g. "SNES"). |
num_achieved |
int |
Achievements unlocked by the player. |
num_possible |
int |
Total achievements in the set. |
percent |
float |
Completion percentage (0–100). |
last_played |
str | None |
ISO-ish timestamp of last session. |
icon_url |
str | None |
Absolute URL of the game icon. |
RAAchievement — a single unlocked achievement:
| Field | Type | Description |
|---|---|---|
title |
str |
Achievement title. |
description |
str |
Achievement description. |
points |
int |
Point value. |
game_title |
str |
Title of the game it belongs to. |
date |
str | None |
Unlock timestamp. |
badge_url |
str | None |
Absolute URL of the badge image. |
MisterRAWebError — raised by MisterRAWeb on network failures, HTTP errors, or API-level errors (including bad credentials).
API
MisterClient(host, port=8182, *, session=None, timeout=10)— async REST client; callawait client.async_close()when done, or inject your ownaiohttp.ClientSession.MisterStatus— dataclass snapshot:online,core,system,game,hostname,version,ip,ips,dns,disk_total/used/free. Propertyis_running_game.MisterConnectionError— raised on network/HTTP errors.MisterWebSocketClient(host, port=8182, *, session=None, reconnect_delay=5)— reconnecting WS loop;await ws.listen(callback), callws.stop()to exit.apply_ws_message(message, status, menu_path, index_state)— pure reducer; apply a single WS text frame and return updated(status, menu_path, index_state).MisterSSH(host, port, username, password)— persistent asyncssh connection;await ssh.async_probe()returns telemetry dict.parse_ssh_probe(raw)— parse the raw batched SSH output into a telemetry dict.MisterRAWeb(username, api_key, *, session=None, timeout=15)— async RA Web API client;await web.async_fetch_stats()returnsMisterRAWebStats.MisterRAWebStats,RAGameProgress,RAAchievement— cloud-stats dataclasses (see section above).MisterRAWebError— raised on RA Web API failures.KEYBOARD_NAMES,INI_VIDEO_KEYS,WS_PATH,DEFAULT_PORT— protocol constants.
Documentation
Full documentation is available at https://hudsonbrendon.github.io/python-mister-fpga/ — usage guide, runnable examples, and auto-generated API reference.
Credits
REST/WebSocket API by wizzomafizzo/mrext. MiSTer-kun logo by the MiSTer-devel project. Author @hudsonbrendon.
License
MIT — see LICENSE.
Metadata
Release files for python-mister-fpga 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| python_mister_fpga-0.3.0.tar.gz | 198.1 kB | With provenance | Details for python_mister_fpga-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| python_mister_fpga-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for python_mister_fpga-0.3.0-py3-none-any.whl |
Total release size: 226.8 kB
Release files / python_mister_fpga-0.3.0.tar.gz
| Download URL | python_mister_fpga-0.3.0.tar.gz |
|---|---|
| Size | 198.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
75926c90461a759f1ef275d61147e9c14480b9c417e30da2e0c122c44f9cd71f
|
|
BLAKE2b-256 checksum How to use checksums |
eb13f1d3ccc3648760485e639a52dae4cfcb73edefe9e7db0d037371b02b1e94
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.
Transparency logRelease files / python_mister_fpga-0.3.0-py3-none-any.whl
| Download URL | python_mister_fpga-0.3.0-py3-none-any.whl |
|---|---|
| Size | 28.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2f2921a93c247c834177c74ff53ce599a2c70c1d7c4fec9bc20e7e9092cce272
|
|
BLAKE2b-256 checksum How to use checksums |
a45931137f843b2ac2284babdecc89d8ea609a6015f0d267e128f93bcab03ae8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.
Transparency logSecurity for python-mister-fpga 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for python_mister_fpga-0.3.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.