Skip to content

Repository files navigation

MoniStat

CI Packages

MoniCard Station

Relief from itchy proprietary upload protocols.

MoniCard Station - or, as I've recently taken to calling it, MoniStat - is an independent, open-source desktop client for discovering and managing MoniCard wearable displays without requiring WeChat.

MoniStat is an unofficial interoperability project and is not affiliated with or endorsed by the MoniCard manufacturer.

Quick start

Packaged builds

Download the package for your operating system from the GitHub Releases page.

On Windows, extract the entire portable ZIP and launch MoniStat.exe. Keep the _internal directory beside the executable; running PyInstaller's temporary build\MoniStat\MoniStat.exe or moving the packaged executable by itself will produce a missing python312.dll error.

MoniStat packages are currently unsigned development builds, so Windows SmartScreen and macOS Gatekeeper may display a warning.

Run from source

MoniStat requires Python 3.11 or newer and a platform supported by PySide6 and Bleak with Bluetooth LE.

Windows PowerShell:

py -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e .
monistat-gui

Linux or macOS:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e .
monistat-gui

Connect a card

  1. Turn on the MoniCard and keep it awake near the computer.
  2. Select Scan for MoniCards.
  3. Choose the card and select Connect.
  4. Use the Media, Card Controls, Peer Card, Interest Tags, and Diagnostics tabs.

Features

MoniStat currently provides:

  • Bluetooth LE discovery, connection, signal strength, identity, MTU, and live storage reporting;
  • image upload from PNG, JPEG, WebP, and BMP sources;
  • animated GIF and short video conversion to the card's confirmed MJPEG MP4 format;
  • an exact media preview and explicit confirmation before every upload;
  • a private local catalog with export and same-name re-upload actions;
  • buzzer, vibration, friend-detection, and RGB-lighting toggles;
  • automatic media carousel controls with 3/10/30/60-second intervals;
  • Bluetooth peer-discovery business-card profile writing;
  • Bluetooth peer-matching interest-tag writing and clearing;
  • Android Bluetooth capture analysis and protocol diagnostics;
  • guarded transfers with device-response checking, alignment padding, and CRC verification.

Official static-image and animated-GIF uploads have been decoded successfully. See docs/protocol.md for the observed framing, commands, and media behavior.

Known limitations

  • Physical-device testing has primarily been performed on Windows with a MoniCard Pass running firmware 2.0. Linux and macOS reports are welcome.
  • Firmware 2.0 exposes no BLE command to list, download, or delete stored media. MoniStat's media catalog is local; card-side deletion still requires the physical media menu.
  • NFC behavior remains unverified. The tested unit did not appear as a standard Android NFC/NDEF tag, and the printed manual provides no NFC operating instructions.
  • Firmware 2.0 exposes no BLE command to read interest tags back. Writing tags replaces the complete card-side list. MoniStat includes the first confirmed Mini Program category and advanced numeric IDs while the remaining catalog is mapped.
  • The observed RGB and buzzer controls are simple firmware toggles. No direct buzzer trigger, color picker, brightness control, or programmable effect command has been found.
  • Firmware updates are intentionally not exposed.
  • Video input codec support varies by operating system and Qt package.
  • Packaged applications are not yet code-signed.

Media preparation

Direct upload accepts PNG, JPEG, WebP, and BMP images supported by Qt. MoniStat center-crops each image and first emits a full-color 240×320, 8-bit RGBA PNG. If the card's confirmed one-block limit requires compression, MoniStat uses an indexed-color PNG and preserves the highest practical working resolution before reducing the palette further. It checks every device response and does not expose firmware-update or card-side delete operations.

Animated GIF upload uses Qt's image decoder and JPEG encoder plus MoniStat's small native MP4 muxer to create a silent 240×320 MJPEG Baseline stream, matching the official Mini Program capture. It does not require or bundle an FFmpeg executable. MoniStat also accepts MP4 files that already contain a 240×320 MJPEG video track with no audio.

MP4, MOV, M4V, AVI, MKV, WebM, WMV, MPEG, and MPG inputs are decoded in an isolated Qt Multimedia helper process. MoniStat samples at up to eight frames per second, center-crops each frame, removes audio, and creates a silent 240×320 MJPEG MP4. The initial safety limit is 15 seconds. Exact input codec support can vary by operating system and Qt package.

Qt Multimedia uses dynamically linked FFmpeg libraries on most desktop platforms. Packaged MoniStat builds therefore include those codec libraries, but do not include or launch an FFmpeg command-line executable. See THIRD_PARTY_NOTICES.md for licensing and source links.

Device protocol notes

The guarded uploader has completed live static-image and animated-GIF transfers successfully against a MoniCard Pass using the protocol recovered from the official Mini Program.

The management controls and peer-card writer were recovered from a second official capture. Firmware 2.0 exposes no BLE command to list, read, or unlink stored media. The official Mini Program also keeps only phone-side working files and offers upload rather than device file management. MoniStat therefore labels its media list as a local catalog: Export Cached Copy does not read from the card, and Forget Local Copy does not delete from it. Card-side deletion remains available only through the card's physical media menu unless a future firmware adds a remote operation.

The official lighting controls are on/off behaviors: flash the RGB lights when another MoniCard is detected, and gently pulse the rear ambient RGB lights. No direct buzzer trigger, color picker, brightness control, or programmable lighting-effect command has been observed, so MoniStat does not invent those controls.

The peer-card panel previews the exact official profile payload before writing. The captured friend-scan response carries peer-card text over BLE, confirming that it participates in MoniCard's Bluetooth friend-detection feature. Retail listings explicitly advertise NFC business-card exchange, but the tested unit produced no standard Android NFC/NDEF discovery event while ordinary NFC tags worked on the same phone. The printed manual documents MoniCard-to-MoniCard friend detection and its buzzer, vibration, and lighting alerts, but gives no NFC operating instructions. NFC behavior therefore remains unverified and is not exposed as a MoniStat control. Firmware 2.0 exposes no Bluetooth command to read back the local profile.

The same peer feature accepts up to five numeric interest tags. MoniStat can write or clear the complete tag list using the protocol recovered from four controlled Mini Program transactions. Firmware 2.0 exposes no tag readback command. The built-in picker currently covers the first confirmed Mini Program category, and advanced category/tag ID fields support continued catalog research without changing the wire protocol.

Decode an official upload

Android can record the Bluetooth traffic produced by the official Mini Program. This workflow remains read-only from MoniStat's perspective.

  1. Enable Developer options and Bluetooth HCI snoop log on the phone.
  2. Turn Bluetooth off and back on.
  3. Upload one tiny, recognizable test image through the Mini Program.
  4. Connect the phone with USB debugging enabled.
  5. Capture a bug report:
.\scripts\capture-android.ps1

If the bug report contains a standalone BTSnoop file, extract and decode it:

monistat extract-bugreport captures\bugreport-....zip
monistat decode-capture captures\bugreport-....btsnoop.log

The desktop interface can also open a .log, .btsnoop, .pcap, or .pcapng capture using Analyze Bluetooth Log. Capture decoding requires TShark from Wireshark.

Bluetooth captures and Android bug reports can contain device addresses, hostnames, account activity, and other identifying information. Keep them private. The captures/ directory is excluded from Git.

Development

Install the development extras and run the test suite with:

python -m pip install -e ".[dev]"
python -m pytest -q

The application and media-preparation code are platform-independent. GitHub Actions runs the suite on Windows, Linux, and macOS with Python 3.11 and 3.13.

The diagnostic command-line interface is also available:

monistat scan
monistat info AA:BB:CC:DD:EE:FF
monistat storage AA:BB:CC:DD:EE:FF
monistat decode-capture captures\btsnoop_hci.log
monistat upload AA:BB:CC:DD:EE:FF photo.jpg --yes
monistat upload AA:BB:CC:DD:EE:FF animation.gif --yes
monistat upload AA:BB:CC:DD:EE:FF compatible.mp4 --yes

Generate a deterministic 240×320 protocol test image:

python .\scripts\create-probe-image.py

The image is written beneath the private, ignored captures/ directory.

Building packages

Tagged builds and manually dispatched package workflows create:

  • a Windows x64 portable ZIP and Inno Setup installer;
  • a Linux x86_64 AppImage;
  • a zipped macOS application bundle.

Windows

Create a portable one-folder build:

.\scripts\build-windows.ps1

The executable will be written to dist\MoniStat\MoniStat.exe. GIF and video conversion are included without adding a separate FFmpeg executable.

For an optional single-file build:

.\scripts\build-windows.ps1 -OneFile

Create the portable ZIP and installer after installing Inno Setup 6:

.\scripts\package-windows.ps1 -Version 0.1.1

Linux

Provide the official appimagetool executable through APPIMAGETOOL, then:

APPIMAGETOOL=/path/to/appimagetool bash ./scripts/build-linux.sh 0.1.1

macOS

bash ./scripts/build-macos.sh 0.1.1

The result is dist/MoniStat-0.1.1-macos.zip, containing MoniStat.app.

Releasing

The package workflow can be run manually to test all three platform packages without publishing a release. Its version input must match both pyproject.toml and monistat.__version__.

To publish a release:

  1. Update the version in pyproject.toml and src/monistat/__init__.py.
  2. Commit and push the version change.
  3. Create and push a matching tag, such as v0.2.0.

The tag triggers a release test gate, Windows/Linux/macOS package builds, SHA-256 checksum generation, and a GitHub Release with generated notes. Tags containing a hyphen, such as v0.2.0-rc.1, produce prereleases. The workflow uses GitHub's repository-scoped token; no personal access token or release secret is required.

License

MoniStat is available under the MIT License. See LICENSE.

About

Relief from itchy proprietary upload protocols: Cross-platform desktop app for MoniCard smart badges. Upload media over Bluetooth, manage card controls, and ditch the proprietary WeChat interface.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages