1. Pi vorbereiten
Raspberry Pi OS 64 Bit, Python ≥3.11, Ethernet und SSH einrichten. Benutzerkonto mit eigenem Passwort; Projekt nicht als root betreiben. Die GPIO-Verdrahtung aus HARDWARE.md vorher spannungsfrei prüfen. Auf dem Pi:
sudo apt update
sudo apt install python3-venv python3-dev build-essential cmake gcc-arm-none-eabi libnewlib-arm-none-eabi v4l-utils git
Den Ordner hardware-box auf den Pi kopieren, beispielsweise nach /home/pi/hardware-box. pi in allen Beispielen durch das tatsächlich eingerichtete Konto ersetzen. Virtuelle Umgebung, Demo-Logs und .env des Entwicklungsrechners nicht übertragen. Das Release-ZIP enthält diese Dateien nicht.
cd /home/pi/hardware-box
python3 -m venv .venv
.venv/bin/python -m pip install -e '.[capture,test]'
cp config/example.toml config/local.toml
Die Paketbereiche stehen in pyproject.toml; requirements-tested.txt dokumentiert die verwendeten Hostversionen dieses Entwicklungsstands. OpenCV/V4L2 auf ARM ist zusätzlich auf dem Pi zu testen. Wenn für die dortige Pythonversion kein passendes OpenCV-Wheel angeboten wird, das OS-Paket python3-opencv und eine neue Venv mit --system-site-packages verwenden; nicht zwei OpenCV-Versionen in derselben Umgebung mischen.
2. GPIO-UART statt Pi-Debug-UART
Über sudo raspi-config die serielle Login-Konsole ausschalten, UART-Hardware einschalten. Für den Pi-5-40-Pin-Header in /boot/firmware/config.txt ergänzen:
enable_uart=1
dtoverlay=uart0-pi5
Neustarten. /dev/serial0 zeigt beim Pi 5 gewöhnlich auf den separaten Debugheader; deshalb das Header-Gerät nach dieser Konfiguration ausdrücklich bestimmen:
pinctrl get 14 15
ls -l /dev/serial* /dev/ttyAMA*
dmesg | rg 'ttyAMA|uart'
Falls rg fehlt, im letzten Schritt grep -E 'ttyAMA|uart' verwenden. Die beiden Headerpins müssen UART-TX/RX statt GPIO zeigen. Das tatsächlich zugeordnete Gerät in serial_port eintragen; keine alte Pi-4-Gerätezuordnung ungeprüft übernehmen. Verhindern, dass ein serial-getty genau dieses Gerät beansprucht. Dem Anwendungskonto dialout und video zuweisen und neu anmelden:
sudo usermod -aG dialout,video pi
UART benutzt 115200/8N1 und 3,3 V. GPIO14/15 am Pi sind UART; GP14/15 am Pico sind ARM/Not-Aus. Pico-USB bleibt ausschließlich am Ziel. Der empfohlene Isolator wird aus den jeweiligen lokalen 3,3-V-Schienen versorgt; keine Versorgung oder Masse über die Isolationsgrenze brücken. Offizielle Pi-UART-Dokumentation
3. Pico-Firmware bauen
Bewusst versionierten SDK-Stand verwenden. Der Firmware-Code zielt auf Pico 2 / RP2350 und Pico SDK 2.1 oder neuer. Beispiel mit dem offiziellen Tag 2.1.1:
mkdir -p "$HOME/hardware-box-sdk"
git clone --branch 2.1.1 --depth 1 https://github.com/raspberrypi/pico-sdk.git "$HOME/hardware-box-sdk/pico-sdk"
git -C "$HOME/hardware-box-sdk/pico-sdk" submodule update --init lib/tinyusb
export PICO_SDK_PATH="$HOME/hardware-box-sdk/pico-sdk"
cd /home/pi/hardware-box
cmake -S pico -B pico/build -DPICO_BOARD=pico2 -DPICO_SDK_PATH="$PICO_SDK_PATH"
cmake --build pico/build --parallel 2
Ein Pico-2-Board unterstützt je nach SDK auch RISC-V-Varianten; dieser Referenzbuild nutzt den normalen Arm-Pfad. Nicht versehentlich PICO_BOARD=pico wählen. SDK-/Compilerkombination und Binary-Hash für die Hardwareabnahme dokumentieren. Das SDK stellt USB-Deskriptor-/Treiberbibliothek bereit; Python auf dem Pico wird hier nicht verwendet. Pico SDK, Pico 2
Die bereits gebaute firmware/hardware_box_pico.uf2 kann für den Referenzstand verwendet werden. Buildversionen und Hash stehen im Prüfnachweis. Bei jeder Firmwareänderung neu bauen.
Zum Flashen Pico vom Ziel abziehen, BOOTSEL gedrückt halten, an den Pi/Entwicklungsrechner anschließen und die entstandene pico/build/hardware_box_pico.uf2 auf das gemountete RP2350-BOOT-Laufwerk kopieren. Danach wieder vom Entwicklungsrechner abziehen und über den geprüften Datenpfad an den Ziel-PC anschließen. Das kurzzeitige BOOTSEL-Flashen gehört zur Einrichtung, nicht zum Steuerbetrieb. UART bleibt ein separater Kanal.
Der Code verwendet TinyUSBs Beispiel-VID für Entwicklung. Vor Gerätevertrieb eigenen korrekt zugeteilten VID/PID verwenden und Windows-/OS-Enumeration mit diesen IDs erneut prüfen. Ausgelieferte Geräte nicht als fremden Hersteller ausgeben.
4. Capture-Modus prüfen
HDMI OUT → Capture IN → LOOP THRU → Monitor; Capture USB3 → gespeister Hub → Pi. Zunächst ein Desktop, SDR, 1080p60. Gerätepfad und reale Formatliste prüfen:
v4l2-ctl --list-devices
v4l2-ctl --device=/dev/video0 --list-formats-ext
ls -l /dev/v4l/by-id/
Stabilen /dev/v4l/by-id/...-video-index0-Pfad in capture_device setzen. Auf manchen Geräten ist kein solcher Link vorhanden; dann einen gezielten udev-Link anhand Vendor-/Product-/Seriennummer einrichten. V4L2-Metadatenknoten nicht mit dem Videoaufnahmegerät verwechseln.
Referenzkonfiguration:
capture_width = 1920
capture_height = 1080
capture_fps = 60
capture_format = "YUYV"
screenshot_width = 1920
screenshot_height = 1080
target_width = 3840
target_height = 2160
target_width/height müssen dem tatsächlich ausgegebenen Desktop entsprechen, nicht einem angenommenen Monitorwert. Für den ersten 1080p-Test also zunächst beide auf 1920/1080 setzen. Danach 4K60/1080p60 getrennt abnehmen. Software liest FPS/FourCC zurück und verweigert einen anderen Modus; FPS-Werte des Treibers sind noch keine physische Framedrop-/Latenzmessung. MJPG nur wählen, wenn das tatsächliche Gerät dieses Format mit 60 fps enumeriert. Die Referenzkarte nutzt bevorzugt YUYV/YUY2. Magewell Modus-/Latenzdiagnose
5. Token und API-Key lokal konfigurieren
Eigenes OpenAI-API-Projekt mit passenden Modellrechten und Ausgabenlimit verwenden. Der ChatGPT-/Codex-Login allein liefert dem Pi keinen API-Key. .env.example nach .env kopieren, Key und einen zufälligen Token lokal eintragen. Dateien nicht in Logs, Git oder Browser-URL schreiben:
cp .env.example .env
chmod 600 .env
.venv/bin/python -c 'import secrets; print(secrets.token_urlsafe(32))'
Der Startbefehl liest Umgebungsvariablen; .env wird nicht selbständig geladen. .env muss deshalb syntaktisch gültige Shell-Zuweisungen enthalten. Zum interaktiven Start:
set -a
. ./.env
set +a
.venv/bin/hardware-box --demo
Nur eigene lokale .env sourcen. Beispiel: BOX_CONFIG=config/local.toml, BOX_WEB_TOKEN=<zufälliger Token>, OPENAI_API_KEY=<eigener API-Key>. Ein fehlender Webtoken erzeugt einen kurzlebigen Token, der in der Konsole erscheint. Im dauerhaften Dienst einen expliziten Token verwenden, damit er nicht als neu erzeugtes Geheimnis im Journal landet. Unter OPENAI.md stehen geprüfter API-Vertrag und Kontoverifikation.
6. Leitstand erreichen und kalibrieren
Am Pi http://127.0.0.1:8080 öffnen. Von einem anderen Rechner SSH-Tunnel nutzen:
ssh -L 8080:127.0.0.1:8080 pi@raspberrypi.local
Dann im dortigen Browser dieselbe localhost-URL und den Token eingeben. Der Dienst bindet ausschließlich Loopback. Für eine spätere Netzfreigabe wären TLS, belastbare Zugangskontrolle und eigene Netzabnahme erforderlich; diese Voreinstellung wird nicht über einen UI-Schalter aufgehoben.
Realer manueller HID-Test benötigt demo=false; der manuelle Test sendet keine Bilder an OpenAI und benötigt deshalb keine Screenshot-Uploadfreigabe. Noch keinen Agentenauftrag starten. ARM-Taste kurz drücken, im Leitstand einen einzelnen move-Test vorbereiten und freigeben. Neun bekannte Zielpunkte (Ecken, Kantenmitten, Mitte) prüfen. Danach in einem leeren Editor Layoutprobe sowie Enter, Tab, Löschen, Pfeile und freigegebene Kürzel prüfen. Beispielprobe: Aa Zz Yy 0123456789 äöüÄÖÜß € @ { } [ ] < > | \\ nur mit passend konfiguriertem DE/AT-PC-Profil.
Jeder manuelle Test disarmt nach seiner einzelnen Aktion. Für den nächsten Test erneut physisch ARM drücken. CapsLock/NumLock ausschalten und keinen Layoutwechsel während des Betriebs zulassen. Absoluten Zeiger, OS-Zuordnung, Bildschirm, Kamera und Not-Aus nach TESTPLAN.md abnehmen. Danach erst lokal setzen:
demo = false
keyboard_layout = "de"
calibration_confirmed = true
allow_screenshot_upload = true
allow_screenshot_upload=true ist die bewusste Entscheidung, sichtbare Inhalte an OpenAI zu übertragen. Der Host schreibt diese Freigabe nicht selbst. Nach einer Auflösungs-/Layoutänderung über das Webinterface wird die Kalibrierungsfreigabe gelöscht; speichern, Dienst stoppen/neustarten und neu prüfen.
7. Dienstbetrieb
deploy/hardware-box.service als Vorlage an tatsächliches Konto und Installationsverzeichnis anpassen. .env ist die EnvironmentFile; Pythonprozess bleibt unprivilegiert. Anschließend:
sudo cp deploy/hardware-box.service /etc/systemd/system/hardware-box.service
sudo systemctl daemon-reload
sudo systemctl enable --now hardware-box.service
sudo systemctl status hardware-box.service
Die Installation aktiviert nur den Leitstand, keinen Auftrag und keine automatische ARM-Freigabe. Ein Dienstneustart setzt keine unterbrochene Agentensitzung fort. Für laufende Diagnose journalctl -u hardware-box.service; vertrauliche Protokolle nicht unredigiert weitergeben. Datenlogs regelmäßig lokal löschen/archivieren; diese Version hat keine automatische zeitgesteuerte Löschung.
8. Erstauftrag
API-Modellzugriff prüfen; der Button bestätigt nur Modelllesezugriff, die tatsächliche Computer-Tool-Nutzung wird erst beim ersten Responses-Aufruf geprüft. Eine Kopie der Excel-Datei verwenden. ARM lokal drücken, Auftrag eingeben, starten, Einzelaktionen am Monitor beobachten/freigeben. Bei fehlendem Fokus, falscher Datei, Passwort, Warnung, MFA oder unklarem Ergebnis stoppen und manuell übernehmen. Nach Modellende wird der HID-Ausgang disarmt; Datei und B7 am Ziel überprüfen und „Ergebnis bestätigt“ wählen.