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.
186 lines
6.7 KiB
Markdown
186 lines
6.7 KiB
Markdown
# 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 |
|