Skip to content

jrichter24/moldqueen

Repository files navigation

moldqueen

Latest release Website — live License: MIT Raspberry Pi Android ESP32-S3 Gamepad Python 3.13 status: two-hub control working GitHub Sponsors Ko-fi: support

Drive a Mould King building-block RC toy — over a reverse-engineered BLE protocol, through one clean WebSocket API.

moldqueen — Mould King RC control

jrichter24.github.io/moldqueen — explore the project website

Sponsor moldqueen on GitHub   Support moldqueen on Ko-fi
Free & open source. No ads, no affiliate links.

Contents

Download — install the app

📲 Latest signed release — the standalone Android app, signed by the author.

  1. Download moldqueen-v0.1.2.apk from the latest release.
  2. On your phone, allow install from unknown sources for your browser or file manager (Android prompts the first time).
  3. Open the APK to install, then launch MoldQueen → Connect → Ready → drive.

It's one self-contained app — it owns the radio and serves the UI on-device, so no Pi or network is needed. Prefer to build it yourself? cd android-core && ./gradlew installDebug (over USB).

Also available on F-Droid:

Get it on F-Droid

The Raspberry Pi path is in Quickstart below.

The idea: API-first — thin transport, smart client

moldqueen is built around one documented WebSocket contract and an unusual split:

  • The radio core is a thin transport. It takes a raw set {slot, channel, value}, turns it into a Mould King BLE "telegram," crypts it, and broadcasts it. It knows nothing about functions, channel maps, inversion, caps, or your specific toy.
  • A single web client is the smart half. It resolves function → (slot, channel, value), owns the per-layout channel map, and runs the keepalive + STOP safety latch.

Because all the smarts live above the contract, the radio core is swappable: a Raspberry Pi (raw HCI/BlueZ), a standalone Android app (native BLE), and an ESP32-S3 (ESP-IDF + NimBLE, over WiFi) each expose the identical WebSocket API and serve the same client — so the UI is written once and the hardware is pluggable (swap the radio core, keep the client). (The hubs are driven by broadcasting crafted BLE adverts, not over GATT.) The Mould King 13112 excavator is the hardware-proven reference; the layout system + auto-assign let you drive any Mould King toy on these hubs.

Quickstart

Raspberry Pi (primary path)

Pi with a USB BLE dongle, Python 3.13, a solid 5 V/3 A PSU:

git clone https://github.com/jrichter24/moldqueen && cd moldqueen
scripts/start.sh        # frees the adapter from bluetoothd, brings the dongle up by MAC, runs both processes
# → open http://<pi>:8080/  →  Connect  →  button one hub to slot 1  →  Ready  →  drive

With avahi-utils installed the Pi is discoverable by name as moldqueenrasp.local (ws://moldqueenrasp.local:8765), mirroring the ESP32's moldqueenesp.local — additive, the IP still works. Full prep (disable onboard BT, mask bluetoothd, caps), mDNS, and a dry-run mode: dev-docs/QUICKSTART.md.

The Raspberry Pi running the moldqueen radio core


ESP32-S3 (the third radio core)

A tiny ESP-IDF + NimBLE board that drives real toys over WiFi today, exposing the same WebSocket contract as the Pi and Android cores. It's a usable standalone appliance: no credentials are baked in, so on first boot it opens a setup WiFi (moldqueen-setup) for you to enter your network; after that it's discoverable as moldqueenesp.local and carries a built-in management page at moldqueenesp.local:8080 (status, restart, switch-to-setup, change-network). Point the client at ws://moldqueenesp.local:8765 and drive.

🔌 Download the firmware: grab moldqueen-esp32-<tag>.bin from the latest release (current: esp-v0.1.0) and flash the single image at offset 0x0:

esptool.py --chip esp32s3 write_flash 0x0 moldqueen-esp32-<tag>.bin

Step-by-step setup walkthrough: dev-docs/ESP32_SETUP.md.

An ESP32-S3 running the moldqueen radio core, driving a Mould King hub over WiFi


Android (standalone, no Pi)

Own native radio + bundled client in one APK:

cd android-core && ./gradlew installDebug    # build + install to a connected device
# → open the MoldQueen app  →  Connect  →  Ready  →  drive

Build/device detail: dev-docs/ANDROID.md.

MoldQueen running standalone on an Android phone


Run the client with Docker (no Python)

A published, public client-only image serves the web UI with one command, no Python, no build. It hosts the client over http://localhost, so it can connect to a plain ws:// device on your LAN (same protocol, no mixed-content block). It's a real local-hosting option for driving your own device, not a hosted demo:

docker run --rm -p 8080:8080 ghcr.io/jrichter24/moldqueen-client:latest
# → open http://localhost:8080/  →  point the WS endpoint at your device
#   (ws://moldqueenrasp.local:8765 / ws://moldqueenesp.local:8765 / ws://<ip>:8765)

The host port is the left number, so remap freely (e.g. -p 9090:8080). Use :latest for the newest build or pin :0.1.0 for the current version. Image on the GitHub Packages page; depth in dev-docs/REMOTE_CLIENT.md.

Just exploring? Run the client alone against a Pi — dev-docs/DEV_CLIENT.md (dev server) or dev-docs/REMOTE_CLIENT.md (Docker).

What it does

The moldqueen start-page chooser — layout cards with Generic/Model and MK4/MK6 badges

  • Layouts — pick one from the start-page chooser:
    • Excavator (model-specific): landscape HMI dashboard, drag-joysticks + hold buttons.
    • 12-axis and Brick / PS-like (model-agnostic): generic gamepads with 12 motors you map to any toy.
    • RAW (debug): a protocol bench over the raw set/stop path (slot/channel/value, telegram + on-air bytes console).
  • Chooser / start page — cards with a Generic / Model badge and MK4 / MK6 protocol badges (both MK4 and MK6 are live; MK6 ships on the Pi + web client), a jump-to-layout dropdown, and the RAW bench behind a debug icon.
  • One shared chrome (MK4Chrome) — every layout gets the same menu, settings, connect wizard, status light, language picker, keyboard STOP, and gamepad path.
  • Profile-driven auto-assign — map a generic controller's 12 motors to channels by toy profile (vehicle / car / custom) with an inline editor and a zero-box guide.
  • Gamepad — pair a DualSense (or any) controller over Bluetooth and drive, on the excavator and the generic layouts — in the browser or the Android app; touch always works too. (detail: dev-docs/GAMEPAD.md)

PlayStation and Xbox controllers — gamepad support

  • 6 languages (EN/DE complete; ZH/KO/ES/FR seeded, EN fallback), editable per-layout title + colour.
  • Safety — affirmative keepalive (the client re-affirms intent ~10/s; the server auto-neutralizes any un-refreshed channel) + STOP = kill-and-reconnect-at-neutral. More ↓ · 📸 Screenshots.

Connection wizard

Cold-starting these hubs is fiddly, so the shared client chrome (MK4Chrome) has a guided connection wizard: it walks you from power on to Ready, and it shows the hub's real LED-flash patterns so you can confirm you're talking to the right hub and assigning the right slot (one long flash = powered on; fast flashing = connecting; button a hub to one/two/three fast flashes to put it on slot 0/1/2). It's a client feature, so you get it on every layout and against every radio core (Raspberry Pi or the standalone Android app), not something Pi- or Android-specific.

A Mould King hub showing one long flash (powered on)    A Mould King hub fast-flashing (connecting)
The wizard's real hub-LED flash patterns: one long flash = powered on, fast flashing = connecting.

Architecture

Thin transport (server) + smart client (UI), with a swappable radio core behind one WebSocket contract:

client/        # the INDEPENDENT smart web client (chooser · layouts · MK4Chrome · channel maps)
   │  ws://…:8765  (the contract: setup · set · stop · state · info)
   ├── linux-core/   # Pi radio core — raw HCI/BlueZ; serves the client (Python)
   ├── android-core/ # standalone Android radio core — native BLE; serves the client (Kotlin)
   └── esp32-core/   # ESP32-S3 radio core — ESP-IDF + NimBLE over WiFi (C)

The same UI on a Raspberry Pi, an Android phone, a laptop and an ESP32 — one WebSocket contract

The client resolves function → channel and sends only low-level set; the core makes a nibble, crypts it (MouldKingCrypt), and broadcasts the BLE telegram. One MK4 telegram drives all hubs at once (12 nibbles = 3 slots × 4 channels). The Raspberry Pi + web client also speak MK6 (a byte-per-channel, per-device-addressed telegram) and can drive an MK4 box and an MK6 box at the same time, which the official Mould King app can't do (how mixed mode works); the ESP32 and Android cores are MK4-only for now. Deep dive: protocol, crypto, the dual-radio finding, the WS contract: dev-docs/PROJECT.md (the source of truth) and the machine-readable asyncapi.yaml.

Run it… How Detail
On the Pi (served) scripts/start.shhttp://<pi>:8080/ QUICKSTART
Android (standalone) ./gradlew installDebug ANDROID
On an ESP32-S3 (over WiFi) idf.py flash → join moldqueen-setup, enter WiFi → ws://moldqueenesp.local:8765 PORTING
Client on the desktop client/serve.py → point at a Pi DEV_CLIENT
Client in Docker docker run … ghcr.io/jrichter24/moldqueen-client:latest → point at a device REMOTE_CLIENT
On another board port the thin-transport core (the cores are hardware-bound) PORTING
Add your own toy/layout a generic slot/channel layout, no core fork ADDING_A_LAYOUT

Roadmap

The ESP32-S3 radio core is now a working third sibling, a usable standalone appliance. It drives real toys over WiFi today (clean-room C MouldKingCrypt port, NimBLE 0xFFF0 advertiser, 300 ms auto-neutral safety, WiFi WebSocket server mirroring the Pi's api.py), plus WiFi provisioning (no creds baked in: a fallback moldqueen-setup AP + a branded bilingual setup page), mDNS discovery as moldqueenesp.local, a management page at moldqueenesp.local:8080 (status, restart, switch-to-setup, change-network), Pi mDNS (moldqueenrasp.local for linux-core), and a binary/release pipeline (a downloadable .bin, published per esp-v* tag). The ESP32 core is complete and stays a thin-transport radio core that a hosted client drives; serving the client from the board's own flash was decided against (the several-MB client vs limited flash, and the page-load asset burst coexisting with BLE on the shared 2.4 GHz radio). What's still ahead:

  • MK6 on the ESP32 & Android cores. MK6 (and simultaneous mixed MK4+MK6) already ships on the Pi + web client; the remaining work is the MK6 telegram path on the ESP32 and Android radios.
  • Camera, ToF sensor — telemetry over/alongside the API.
  • AI brain / console client — an agent driving the toy through the same WebSocket API.

Detail + status: dev-docs/ROADMAP.md.

Contributing

Issues, PRs, and especially new toy layouts are welcome. See CONTRIBUTING.md for how to contribute and the conventions to respect (thin transport / smart client, one client / no forks, the safety model). It also explains why this repo keeps its AI-assisted-workflow files (CLAUDE.md + the .claude/agents/) in version control on purpose — for transparency about how the project is built, and as a working example you can copy for your own setup.

Credit & attribution

Building on, forking, or reusing moldqueen? A credit back is genuinely appreciated — it's MIT-licensed, so this is a request, not a requirement. Drop this line in your README, About screen, or docs:

Built with [MoldQueen](https://github.com/jrichter24/moldqueen)https://jrichter24.github.io/moldqueen/

→ Built with MoldQueenhttps://jrichter24.github.io/moldqueen/

Credits, license & disclaimer

  • Author: Dr. Jens Richter — physics & electrical engineering; by day, tour optimization with genetic/AI algorithms at DNA Evolutions (LinkedIn · Website). Built for my son Jonas, who loves excavators. AI coding assistants helped with implementation. Architecture, product decisions, testing, and final code review remained under human control.
  • Protocol groundwork: J0EK3R/mkconnect-python — our mouldking_crypt.py is a port/derivative of MouldKingCrypt, used under the MIT License (© 2024 J0EK3R), verified byte-exact against the MK+tech app; see THIRD-PARTY-NOTICES.md. Additional reference: BrickController2.
  • Independent & unofficialnot affiliated with, authorized by, or endorsed by Mould King / Shenzhen Yuxing; trademarks used descriptively. The BLE protocol was reverse-engineered for interoperability with hardware the author owns, for educational / personal use. Provided "as is", without warranty — you assume all risk.

License: MIT © 2026 Jens Richter. Bundled third-party code keeps its own license — see THIRD-PARTY-NOTICES.md.

About

Control Mould King BLE building-block toys from a Raspberry Pi over a reverse-engineered protocol. Simultaneous multi-hub control, a WebSocket API for custom clients, and a multi-language web dashboard.

Topics

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages