Proxi AI — Spielzeug-Roboter mit natürlicher Sprache steuern
Firmware, Bluetooth-Brücke und Agent-Skill für den KOSMOS-Proxi: einmal flashen, danach hört der Roboter über Bluetooth LE auf Textbefehle. Was die Befehle schickt, ist ihm egal — ein Skript, ein curl, oder ein KI-Agent, der aus "mach mal was Lustiges" eine Choreografie baut. firmware/ MakeCode-Projekt (TypeScript) und fertige .hex für V1 und V2 bridge/ BLE-Brücke und HTTP-API, einzige Abhängigkeit ist bleak agent/ Skill-Definition: Alltagssprache -> Befehle tools/ Quelltext aus .hex extrahieren, Musik-Tabellen prüfen docs/ Protokoll, Einrichtung, Hardware, Lizenzen Zwei Dinge, die sonst nirgends stehen und in docs/HARDWARE.md dokumentiert sind: die Pin-Belegung des Roboters ist nicht öffentlich, sie wurde aus den mitgelieferten .hex-Dateien rekonstruiert (tools/hex_source.py holt sie heraus). Und der Ton braucht zwingend eine ganzzahlige Frequenz sowie Pin P0 — sonst kracht der Lautsprecher, der Aufruf hängt und die Bluetooth- Verbindung stirbt. Am echten Roboter durchgetestet: Verbindung, Sensoren, Display, 41 Sekunden Musik am Stück, alle Bewegungsrichtungen, Musik und Fahren gleichzeitig, Tanzfiguren, Not-Stopp mitten in der Bewegung, Autostart nach Neustart. MIT-Lizenz. Die Hardware-Extension stammt von kaku111 (TobbieII) und die Notendaten aus pxt-microbit, beide ebenfalls MIT — siehe THIRD-PARTY-NOTICES.
This commit is contained in:
+185
@@ -0,0 +1,185 @@
|
||||
# Einrichtung
|
||||
|
||||
Zwei Schritte: Firmware auf den micro:bit, Brücke auf irgendeinen Rechner mit
|
||||
Bluetooth.
|
||||
|
||||
```
|
||||
KI / LLM --HTTP--> proxi_bridge.py --BLE--> micro:bit im Proxi
|
||||
(Pi Zero W, Laptop, ...)
|
||||
```
|
||||
|
||||
## 1. Firmware flashen
|
||||
|
||||
Läuft auf micro:bit **V1 und V2** — die `.hex` ist ein Universal Hex und
|
||||
enthält beides.
|
||||
|
||||
1. micro:bit per USB anschließen — er meldet sich als Laufwerk `MICROBIT`
|
||||
2. [`firmware/proxi-ai.hex`](../firmware/proxi-ai.hex) darauf kopieren
|
||||
3. Die gelbe LED blinkt, das Laufwerk verschwindet und kommt zurück — fertig
|
||||
|
||||
Danach zeigt Proxi ein schlafendes Gesicht: Firmware läuft, wartet auf
|
||||
Bluetooth.
|
||||
|
||||
Ein Nachflashen ist nie nötig. Alles Weitere passiert über Befehle.
|
||||
|
||||
### Selbst bauen
|
||||
|
||||
Nur nötig, wenn du am Code etwas änderst.
|
||||
|
||||
```bash
|
||||
cd firmware/proxi-ai
|
||||
npm install pxt
|
||||
./node_modules/.bin/pxt target microbit
|
||||
./node_modules/.bin/pxt install
|
||||
./build.sh # -> proxi-ai.hex
|
||||
```
|
||||
|
||||
Der C++-Teil wird vom MakeCode-Build-Service kompiliert, dafür braucht der
|
||||
erste Build Internet. `build.sh` prüft am Ende, ob die erzeugte `.hex`
|
||||
tatsächlich den aktuellen `main.ts` enthält.
|
||||
|
||||
Auf dem V1 ist der Flash mit Bluetooth-Stack fast voll. Kommt beim Erweitern
|
||||
`program too big by ... bytes`, betrifft das die V1-Variante.
|
||||
|
||||
Alternativ im Browser: [makecode.microbit.org](https://makecode.microbit.org)
|
||||
öffnen, neues Projekt, in der JavaScript-Ansicht `main.ts` einfügen, über den
|
||||
Explorer eine Datei `proxi.ts` anlegen und deren Inhalt einfügen. Die
|
||||
Bluetooth-Extension muss hinzugefügt und in den Projekteinstellungen
|
||||
`bluetooth.open` auf `1` gesetzt werden — sonst verlangt der micro:bit Pairing
|
||||
und die Brücke kommt nicht rein.
|
||||
|
||||
## 2. Brücke einrichten
|
||||
|
||||
Läuft auf allem mit Linux und Bluetooth. Ein Pi Zero W reicht.
|
||||
|
||||
```bash
|
||||
pip3 install bleak
|
||||
cd bridge
|
||||
python3 proxi_bridge.py --scan
|
||||
```
|
||||
|
||||
Ausgabe etwa:
|
||||
|
||||
```
|
||||
C4:1F:2B:AA:BB:CC BBC micro:bit [tuvig]
|
||||
```
|
||||
|
||||
Testen:
|
||||
|
||||
```bash
|
||||
python3 proxi_bridge.py --ping
|
||||
python3 proxi_bridge.py "FACE:HEART" "MOVE:FWD:1000" "DANCE:2"
|
||||
python3 proxi_bridge.py --script demo.txt
|
||||
python3 proxi_bridge.py -i # interaktiv
|
||||
```
|
||||
|
||||
Die Adresse lässt sich festnageln, das spart den Suchlauf:
|
||||
|
||||
```bash
|
||||
export PROXI_ADDRESS=C4:1F:2B:AA:BB:CC
|
||||
```
|
||||
|
||||
## 3. HTTP-API für die KI
|
||||
|
||||
```bash
|
||||
python3 proxi_bridge.py --serve 8080
|
||||
```
|
||||
|
||||
| Route | Zweck |
|
||||
|---|---|
|
||||
| `POST /command` | `{"command": "MOVE:FWD:1000"}` |
|
||||
| `POST /commands` | `{"commands": ["FACE:HAPPY", "DANCE:2"]}` |
|
||||
| `GET /status` | Verbindungszustand und die letzten Meldungen vom Roboter |
|
||||
|
||||
```bash
|
||||
curl -X POST localhost:8080/command \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"command":"DANCE:3"}'
|
||||
```
|
||||
|
||||
```json
|
||||
{"command": "DANCE:3", "response": "OK:DANCE:3", "ok": true}
|
||||
```
|
||||
|
||||
> ### ⚠️ Nur im eigenen Netz betreiben
|
||||
>
|
||||
> Die API hat **keine Authentifizierung**. Wer sie erreicht, fährt den Roboter —
|
||||
> ohne Passwort, ohne Rückfrage.
|
||||
>
|
||||
> Im heimischen WLAN ist das unproblematisch und bewusst so gehalten: es soll
|
||||
> ohne Hürden funktionieren. **Aber gib den Port nicht nach außen frei** und
|
||||
> richte keine Portweiterleitung darauf ein. Sonst lässt sich ein Roboter, der
|
||||
> im Kinderzimmer herumfährt, von jedem beliebigen Fremden steuern.
|
||||
>
|
||||
> Soll er über das Heimnetz hinaus erreichbar sein, gehört ein VPN davor —
|
||||
> nicht eine Portfreigabe.
|
||||
|
||||
Im `--serve`-Modus startet der HTTP-Server **sofort** und sucht den Roboter
|
||||
danach im Hintergrund, alle 10 Sekunden. Die API ist damit auch erreichbar,
|
||||
wenn Proxi gerade aus ist — `GET /status` meldet dann `"connected": false`,
|
||||
Befehle antworten mit `ERR:not_connected`. Sobald Proxi eingeschaltet wird,
|
||||
verbindet sich die Brücke von selbst; niemand muss sich einloggen.
|
||||
|
||||
Das ist der Unterschied zu den interaktiven Modi: die brechen sofort ab, wenn
|
||||
der Roboter nicht da ist, weil man dort auf eine Antwort wartet.
|
||||
|
||||
Als Autostart auf einem Pi:
|
||||
|
||||
```ini
|
||||
# /etc/systemd/system/proxi-bridge.service
|
||||
[Unit]
|
||||
Description=Proxi BLE Bridge
|
||||
After=bluetooth.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/python3 /home/pi/proxi/proxi_bridge.py --serve 8080
|
||||
Environment=PROXI_ADDRESS=C4:1F:2B:AA:BB:CC
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
User=pi
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
## 4. KI anbinden
|
||||
|
||||
[`agent/proxi-control.md`](../agent/proxi-control.md) ist ein fertiger
|
||||
Agent-Skill: er enthält das Protokoll und die Regeln, nach denen aus
|
||||
"lass ihn tanzen" eine Befehlsfolge wird.
|
||||
|
||||
Der Skill enthält **keine feste Adresse** — er erwartet sie in der
|
||||
Umgebungsvariablen `PROXI_URL`. Die muss in der Umgebung des Agenten gesetzt
|
||||
sein:
|
||||
|
||||
```bash
|
||||
export PROXI_URL=http://<hostname-des-pi>.local:8080
|
||||
# oder, falls der Name nicht auflöst:
|
||||
export PROXI_URL=http://<ip-des-pi>:8080
|
||||
```
|
||||
|
||||
Absichtlich so: die Adresse hängt vom eigenen Netz ab und hat in einer Datei,
|
||||
die weitergegeben wird, nichts verloren.
|
||||
|
||||
**mDNS-Namen (`*.local`) funktionieren nur im selben Netz.** Sitzt der Agent in
|
||||
einem anderen VLAN als der Pi, nimm die IP-Adresse — oder aktiviere im Router
|
||||
die mDNS-Weiterleitung.
|
||||
|
||||
Der Agent braucht **nur HTTP-Zugriff**, weder das Repo noch Python. Er soll
|
||||
`proxi_bridge.py` ausdrücklich nicht selbst starten: Bluetooth LE erlaubt nur
|
||||
eine Verbindung zum Roboter, und die hält der Dienst.
|
||||
|
||||
## Wenn etwas klemmt
|
||||
|
||||
| Symptom | Ursache |
|
||||
|---|---|
|
||||
| `--scan` findet nichts | Proxi aus, oder schon mit einem anderen Gerät verbunden — BLE erlaubt nur eine Verbindung |
|
||||
| Verbindung bricht sofort ab | Firmware ohne `bluetooth.open=1` gebaut, der micro:bit verlangt dann Pairing |
|
||||
| Befehle kommen mit `OK` zurück, Proxi bewegt sich nicht | `SENSOR:PWR` prüfen. `0` heißt: Enable-Leitung P8 ist low, meist der Batterieschalter |
|
||||
| Antworten bleiben aus, Befehle wirken | Auf dem falschen Characteristic gelauscht. Host schreibt auf `…0003`, der micro:bit meldet sich auf `…0002` |
|
||||
| Lange `TEXT:`-Zeilen abgeschnitten | BLE-Attribute sind 20 Byte, längere Zeilen müssen gestückelt werden — `proxi_bridge.py` macht das |
|
||||
| Dienst startet immer wieder neu, Port nie offen | Alte Fassung: die Brücke verband sich zuerst und startete den Server danach. Ab Werk behoben — im `--serve`-Modus kommt der Server zuerst |
|
||||
| Pi nach dem Abziehen des Kabels nicht mehr da | Er hat per WLAN eine **andere** Adresse als per Kabel. `avahi-daemon` installieren, dann geht `<hostname>.local`. mDNS bleibt aber im eigenen Netz — über VLAN-Grenzen hinweg braucht es einen mDNS-Repeater im Router |
|
||||
| Display bleibt schwarz | Firmware ohne Bluetooth-Extension gebaut, `bluetooth.startUartService()` stirbt dann still beim Start |
|
||||
| Ton kracht, Proxi hängt, Verbindung weg | Eine Frequenz kam als Kommazahl in `music.playTone()`. Siehe HARDWARE.md, "Ton: keine Kommazahlen" |
|
||||
| Ein behobener Fehler tritt wieder auf | Vermutlich läuft noch die alte Firmware. `STATUS` schicken und die Build-Kennung dahinter mit der Ausgabe von `build.sh` vergleichen |
|
||||
Reference in New Issue
Block a user