initial commit: Web Bluetooth controller template for M-Spacer / Apollo board
This commit is contained in:
parent
b62d6fa338
commit
3c94bb9fbb
2 changed files with 65 additions and 2 deletions
23
README.md
23
README.md
|
|
@ -1,3 +1,22 @@
|
||||||
# m-spacer-controller
|
# M-Spacer / MotionSpace / Apollo BLE Workout Controller
|
||||||
|
|
||||||
Custom Web Bluetooth & BLE Workout Controller for MotionSpace / Apollo Smart Fitness Board
|
Custom Web Bluetooth controller for MotionSpace (M-Spacer) and Apollo smart motor fitness boards. Replaces the default QiSense app with a clean web interface for exercise programming, resistance control, and live telemetry.
|
||||||
|
|
||||||
|
## Features (Planned)
|
||||||
|
- **Web Bluetooth API Connection**: Connect directly from Chrome/Edge/Safari without app store installation.
|
||||||
|
- **BLE GATT Reverse Engineering**: Packet sniffer for pull force, rep count, position encoder, and resistance commands.
|
||||||
|
- **Workout Modes**:
|
||||||
|
- Constant Resistance Mode
|
||||||
|
- Eccentric Overload Mode
|
||||||
|
- Isokinetic Mode
|
||||||
|
- **Custom Routines**: Program sets, reps, rest timers, and progressive overload.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
Open `index.html` in Chrome or any Web Bluetooth-supported browser:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Local web server
|
||||||
|
python3 -m http.server 8080
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `http://localhost:8080` and click **Connect Board**.
|
||||||
|
|
|
||||||
44
index.html
Normal file
44
index.html
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>M-Spacer Controller</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: system-ui, sans-serif; background: #0f1113; color: #e8eaec; padding: 2rem; max-width: 600px; margin: 0 auto; }
|
||||||
|
button { background: #c8a45c; color: #000; border: 0; padding: 0.75rem 1.5rem; font-weight: bold; border-radius: 4px; cursor: pointer; }
|
||||||
|
button:hover { opacity: 0.9; }
|
||||||
|
.card { background: #16191c; border: 1px solid #2a2f34; padding: 1.5rem; border-radius: 8px; margin-top: 1rem; }
|
||||||
|
.status { color: #9aa3ab; font-size: 0.9rem; margin-top: 0.5rem; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>M-Spacer / Apollo Controller</h1>
|
||||||
|
<p>Custom Web Bluetooth controller for smart motor workout board.</p>
|
||||||
|
|
||||||
|
<button id="connectBtn">Connect Board</button>
|
||||||
|
|
||||||
|
<div className="card">
|
||||||
|
<h3>Device Status</h3>
|
||||||
|
<div id="status" className="status">Disconnected</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.getElementById('connectBtn').addEventListener('click', async () => {
|
||||||
|
const statusEl = document.getElementById('status');
|
||||||
|
try {
|
||||||
|
statusEl.innerText = "Scanning for BLE board...";
|
||||||
|
const device = await navigator.bluetooth.requestDevice({
|
||||||
|
acceptAllDevices: true,
|
||||||
|
optionalServices: ['0000ffe0-0000-1000-8000-00805f9b34fb']
|
||||||
|
});
|
||||||
|
statusEl.innerText = `Connecting to ${device.name || 'Board'}...`;
|
||||||
|
const server = await device.gatt.connect();
|
||||||
|
statusEl.innerText = `Connected to ${device.name || 'Board'}!`;
|
||||||
|
} catch (err) {
|
||||||
|
statusEl.innerText = `Connection failed: ${err.message}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Reference in a new issue