Admin seite umgebaut mit PW
This commit is contained in:
+336
@@ -0,0 +1,336 @@
|
||||
# CUNO – Admin-Dokumentation
|
||||
|
||||
Stand: 2026-05-21
|
||||
|
||||
---
|
||||
|
||||
## 1. Hardware & Betriebssystem
|
||||
|
||||
| Eigenschaft | Wert |
|
||||
|---|---|
|
||||
| Hardware | Raspberry Pi 4 Model B Rev 1.4 |
|
||||
| Betriebssystem | Debian GNU/Linux 13 (Trixie) |
|
||||
| Kernel | 6.12.75+rpt-rpi-v8 (64-bit ARM) |
|
||||
| Python | 3.13.5 |
|
||||
| Docker | 26.1.5 |
|
||||
|
||||
---
|
||||
|
||||
## 2. Raspberry Pi – Zugangsdaten
|
||||
|
||||
| Eigenschaft | Wert |
|
||||
|---|---|
|
||||
| Hostname | `ExoMyCuno` |
|
||||
| Benutzer | `pi` |
|
||||
| Passwort | `Sonneberg` |
|
||||
| LAN-IP | `192.168.1.83` |
|
||||
| WLAN-IP | `192.168.1.9` |
|
||||
|
||||
**SSH-Zugang:**
|
||||
```
|
||||
ssh pi@192.168.1.9
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. WLAN-Logik
|
||||
|
||||
Der Rover wählt automatisch das beste verfügbare Netzwerk. Ein Hintergrunddienst (`exomy-wifi-fallback`) prüft alle 20 Sekunden die Verbindung und schaltet bei Bedarf um.
|
||||
|
||||
### Prioritätenreihenfolge
|
||||
|
||||
| Priorität | SSID | Typ | Wann aktiv |
|
||||
|---|---|---|---|
|
||||
| 1 (höchste) | `eskimue.de` | Heimnetz | wenn im Heimnetz |
|
||||
| 2 | `4pi` | Mobiler Hotspot | wenn unterwegs mit Handy |
|
||||
| 3 (Fallback) | `CUNO` | Eigener AP des Rovers | wenn kein bekanntes WLAN erreichbar |
|
||||
|
||||
### Netzwerk-Passwörter
|
||||
|
||||
| SSID | Passwort |
|
||||
|---|---|
|
||||
| `4pi` | `st89Saf6H86n` |
|
||||
| `CUNO` (Rover-AP) | `astr0cun042` |
|
||||
|
||||
### Verhalten im Detail
|
||||
|
||||
- Ist `eskimue.de` erreichbar → Verbindung wird hergestellt und gehalten.
|
||||
- Ist `eskimue.de` nicht erreichbar, aber `4pi` sichtbar → Verbindung mit `4pi`.
|
||||
- Ist keines der beiden Netze erreichbar → Rover öffnet den eigenen WLAN-Hotspot **CUNO**.
|
||||
- Sobald ein besser priorisiertes Netz wieder verfügbar wird, schaltet der Dienst automatisch zurück.
|
||||
|
||||
### Eigener Access Point (CUNO)
|
||||
|
||||
Wenn der Rover als AP läuft, ist er unter einer festen IP erreichbar:
|
||||
|
||||
| Eigenschaft | Wert |
|
||||
|---|---|
|
||||
| SSID | `CUNO` |
|
||||
| Passwort | `astr0cun042` |
|
||||
| IP des Rovers | `192.168.50.1` |
|
||||
| Sicherheit | WPA2-PSK |
|
||||
|
||||
Browser-Adresse im AP-Modus: `http://192.168.50.1:8000/`
|
||||
|
||||
---
|
||||
|
||||
## 4. Offene Ports und Dienste
|
||||
|
||||
Alle Dienste laufen auf dem **Host** (Raspberry Pi), nicht im Docker-Container.
|
||||
|
||||
| Port | Dienst | Beschreibung |
|
||||
|---|---|---|
|
||||
| `8000` | Web-GUI | Haupt-Steuerseite und Admin-Seite (Python HTTP-Server im Container) |
|
||||
| `8081` | Kamerastream (Quelle) | Rohstream direkt von der Kamera, kein Delay. Nur intern genutzt. |
|
||||
| `8082` | Admin-API | REST-API für Systemsteuerung (Neustart, Status, Delay). Kein Browser-Frontend. |
|
||||
| `8083` | Video-Delay-Proxy | Kamerastream **mit** eingestellter Verzögerung. Wird von der Web-GUI gezeigt. |
|
||||
| `9090` | ROSBridge WebSocket | Verbindung zwischen Browser und ROS im Container. |
|
||||
|
||||
### Kamera-Signalkette
|
||||
|
||||
```
|
||||
Kamera (Hardware)
|
||||
↓
|
||||
libcamera_mjpeg_server → Port 8081 (Rohstream, kein Delay)
|
||||
↓
|
||||
video_delay_proxy → Port 8083 (mit Delay, 0–10 s einstellbar)
|
||||
↓
|
||||
Web-GUI (Browser)
|
||||
```
|
||||
|
||||
Bei Delay = 0 s wird das Bild sofort weitergegeben (kein echtes Buffern).
|
||||
|
||||
---
|
||||
|
||||
## 5. Webseiten
|
||||
|
||||
### 4.1 Steuerung – `http://<IP>:8000/`
|
||||
|
||||
Die Haupt-Steuerseite des Rovers.
|
||||
|
||||
**Inhalt:**
|
||||
- Kamerabild (live, mit Delay wenn eingestellt)
|
||||
- Virtueller Joystick (Maussteuerung)
|
||||
- Modus-Anzeige (Ackermann / Punkt-Drehen / Crabbing)
|
||||
- Systemstatus-Panel (rechts): Verbindung, CPU, RAM, Temp, WLAN, Uptime, Speicher
|
||||
|
||||
**Besonderheiten:**
|
||||
- Physischer Controller und Web-Joystick können gleichzeitig betrieben werden.
|
||||
- Wenn die Web-GUI aktiv gesteuert hat, wird der physische Controller für 2 Sekunden ignoriert (Prioritätslogik).
|
||||
- Moduswechsel vom physischen Controller werden in der Web-GUI sofort angezeigt.
|
||||
- Die Joystick-Spiegelanzeige zeigt, welche Eingaben der physische Controller gerade sendet.
|
||||
|
||||
---
|
||||
|
||||
### 4.2 Admin-Seite – `http://<IP>:8000/admin.html`
|
||||
|
||||
Systemverwaltung des Rovers. Die Seite ist passwortgeschützt — bei jedem Aufruf wird das Passwort abgefragt.
|
||||
|
||||
| Eigenschaft | Wert |
|
||||
|---|---|
|
||||
| Passwort | `cuno` |
|
||||
|
||||
**Bereiche:**
|
||||
|
||||
#### Aktionen
|
||||
| Schaltfläche | Funktion |
|
||||
|---|---|
|
||||
| Kameradienst neu starten | Startet `exomy-camera-stream.service` neu |
|
||||
| ExoMy-Container neu starten | Startet Docker-Container `exomy_autostart` neu (ROS, Motoren, Joystick) |
|
||||
| Raspberry Pi neu starten | Fährt den Pi neu hoch |
|
||||
| Raspberry Pi herunterfahren | Fährt den Pi aus |
|
||||
|
||||
#### Dienststatus
|
||||
Zeigt den Live-Status von Kamera, Admin-API und ExoMy-Container.
|
||||
|
||||
#### Motorentest
|
||||
Link zur separaten Motortest-Seite (siehe 4.3).
|
||||
|
||||
#### Latenz-Simulation
|
||||
Dropdown 0–10 Sekunden. Verzögert **gleichzeitig**:
|
||||
- Steuerbefehle (sowohl Web-GUI als auch physischer Controller)
|
||||
- Kamerabild
|
||||
|
||||
So lässt sich realitätsnahe Steuerung mit erhöhter Signallaufzeit simulieren (z. B. Mond-Delay ≈ 1 s hin + 1 s zurück → 2 s einstellen).
|
||||
|
||||
#### Systemstatus
|
||||
| Anzeige | Quelle |
|
||||
|---|---|
|
||||
| WLAN-Status | nmcli |
|
||||
| IP-Adressen | wlan0 |
|
||||
| CPU-Temperatur | `/sys/class/thermal/thermal_zone0/temp` |
|
||||
| Unterspannung | `vcgencmd get_throttled` |
|
||||
| Uptime | `/proc/uptime` |
|
||||
| Freier Speicherplatz | Root-Partition |
|
||||
|
||||
---
|
||||
|
||||
### 4.3 Motortest – `http://<IP>:8000/admin-motor-test.html`
|
||||
|
||||
Separate Testseite zum Kalibrieren und Prüfen einzelner Räder.
|
||||
|
||||
**Wichtig:** Der ExoMy-Container muss für den Motortest **gestoppt** sein (Schaltfläche auf der Seite). Nach dem Test kann er wieder gestartet werden.
|
||||
|
||||
**Funktionen:**
|
||||
- Lenkung links / rechts je Rad testen
|
||||
- Vorwärts / Rückwärts je Rad testen
|
||||
- Servo-Mittenwerte (Lenkung) einstellen und speichern
|
||||
- Antriebsneutralwert einstellen und speichern
|
||||
|
||||
---
|
||||
|
||||
## 7. Controller-Belegung (Logitech F710)
|
||||
|
||||
Der Controller muss im **D-Modus** (Schalter auf der Rückseite) betrieben werden.
|
||||
|
||||
| Taste / Achse | Funktion |
|
||||
|---|---|
|
||||
| **Linker Stick** | Fahren und Lenken |
|
||||
| **A** | Ackermann-Modus (normales Kurvenfahren) |
|
||||
| **X** | Punkt-Drehen (Rover dreht auf der Stelle) |
|
||||
| **Y** | Crabbing (seitliche Fahrt, alle Räder gleich eingeschlagen) |
|
||||
| **B** | (nicht belegt) |
|
||||
| **START** | Motoren ein- / ausschalten (Toggle) |
|
||||
| **SELECT** | (nicht belegt) |
|
||||
|
||||
### Fahrmodi im Detail
|
||||
|
||||
**Ackermann** (Standard):
|
||||
Normales Kurvenfahren wie ein Auto. Die Vorder- und Hinterräder lenken gegenläufig für einen engen Wendekreis.
|
||||
|
||||
**Punkt-Drehen:**
|
||||
Der Rover dreht sich auf der Stelle. Alle Räder stehen schräg, der Antrieb dreht links und rechts gegeneinander.
|
||||
|
||||
**Crabbing:**
|
||||
Alle Räder werden auf den gleichen Winkel eingeschlagen. Der Rover fährt seitlich (wie eine Krabbe). Lenkrichtung folgt dem X-Achsen-Ausschlag des Sticks.
|
||||
|
||||
---
|
||||
|
||||
## 6. Docker-Container
|
||||
|
||||
### Container `exomy_autostart`
|
||||
|
||||
| Eigenschaft | Wert |
|
||||
|---|---|
|
||||
| Image | `exomy:latest` (lokal gebaut, basiert auf `ros:melodic`) |
|
||||
| ROS-Version | ROS 1 Melodic (Ubuntu 18.04-Basis im Container) |
|
||||
| Startet automatisch | ja (`--restart=always`) |
|
||||
| Ports (Host → Container) | `8000→8000` (Web-GUI), `8080→8080` (alt, nicht aktiv genutzt), `9090→9090` (ROSBridge) |
|
||||
|
||||
### ROS-Knoten im Container
|
||||
|
||||
| Knoten | Funktion |
|
||||
|---|---|
|
||||
| `/delay_node` | Puffert `/joy` → `/joy_delayed` mit einstellbarer Verzögerung (0–10 s) |
|
||||
| `/f710_joy_node` | Liest den Logitech F710 Controller und publiziert auf `/joy` |
|
||||
| `/joystick_parser_node` | Übersetzt Joystick-Eingaben in Rover-Befehle (`/rover_command`) |
|
||||
| `/robot_node` | Berechnet Rad-Winkel und -Geschwindigkeiten aus dem Rover-Befehl |
|
||||
| `/motors` | Schreibt PWM-Werte auf den Servo-Controller (I²C) |
|
||||
| `/rosbridge_websocket` | WebSocket-Brücke zwischen Browser und ROS (Port 9090) |
|
||||
| `/rosapi_node` | Erlaubt dem Browser, ROS-Parameter zu lesen/schreiben |
|
||||
|
||||
### ROS-Signalfluss
|
||||
|
||||
```
|
||||
Controller (USB)
|
||||
↓
|
||||
/f710_joy_node → /joy
|
||||
↓
|
||||
/delay_node → /joy_delayed
|
||||
↓
|
||||
Web-GUI (Browser) → /joy /joystick_parser_node
|
||||
(frame_id="webgui") ↓
|
||||
/rover_command
|
||||
↓
|
||||
/robot_node
|
||||
↓
|
||||
/motor_commands
|
||||
↓
|
||||
/motors (PWM → Servos)
|
||||
```
|
||||
|
||||
### Nützliche Container-Befehle
|
||||
|
||||
```bash
|
||||
# Container neu starten
|
||||
docker restart exomy_autostart
|
||||
|
||||
# Shell im Container öffnen
|
||||
docker exec -it exomy_autostart bash
|
||||
|
||||
# ROS-Knoten anzeigen
|
||||
docker exec exomy_autostart bash -c 'source /opt/ros/melodic/setup.bash && rosnode list'
|
||||
|
||||
# Alle ROS-Topics anzeigen
|
||||
docker exec exomy_autostart bash -c 'source /opt/ros/melodic/setup.bash && rostopic list'
|
||||
|
||||
# Delay-Parameter im ROS lesen/setzen
|
||||
docker exec exomy_autostart bash -c 'source /opt/ros/melodic/setup.bash && rosparam get /delay_seconds'
|
||||
docker exec exomy_autostart bash -c 'source /opt/ros/melodic/setup.bash && rosparam set /delay_seconds 2.0'
|
||||
|
||||
# Alten Image-Schrott aufräumen (dangling images)
|
||||
docker image prune -f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Systemdienste (Übersicht)
|
||||
|
||||
Alle laufen auf dem Raspberry Pi als systemd-Dienste:
|
||||
|
||||
| Dienst | Beschreibung | Startet automatisch |
|
||||
|---|---|---|
|
||||
| `exomy-camera-stream` | MJPEG-Kamerastream auf Port 8081 | ja |
|
||||
| `exomy-video-delay` | Delay-Proxy auf Port 8083 | ja |
|
||||
| `exomy-admin-api` | REST-API auf Port 8082 | ja |
|
||||
| `exomy-wifi-fallback` | WLAN-Priorisierung und AP-Fallback | ja |
|
||||
|
||||
Der **Docker-Container** `exomy_autostart` enthält ROS und startet ebenfalls automatisch (via `docker run --restart=always` oder manuell).
|
||||
|
||||
### Nützliche SSH-Befehle
|
||||
|
||||
```bash
|
||||
# Dienststatus prüfen
|
||||
systemctl status exomy-camera-stream
|
||||
systemctl status exomy-video-delay
|
||||
systemctl status exomy-admin-api
|
||||
|
||||
# Dienst neu starten
|
||||
sudo systemctl restart exomy-camera-stream
|
||||
|
||||
# Container-Status
|
||||
docker ps
|
||||
|
||||
# Container-Logs
|
||||
docker logs exomy_autostart
|
||||
|
||||
# ROS-Topic live anzeigen (im Container)
|
||||
docker exec exomy_autostart bash -c \
|
||||
'source /opt/ros/melodic/setup.bash && rostopic echo /rover_command'
|
||||
|
||||
# Aktuellen Delay prüfen
|
||||
cat /tmp/exomy_delay.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Latenz-Simulation – technischer Hintergrund
|
||||
|
||||
Die Verzögerung wirkt auf zwei Ebenen gleichzeitig:
|
||||
|
||||
1. **Steuerbefehle** (ROS-Ebene):
|
||||
Der `delay_node` puffert alle Joystick-Nachrichten vom Topic `/joy` und gibt sie verzögert auf `/joy_delayed` aus. Der Joystick-Parser liest nur `/joy_delayed`.
|
||||
|
||||
2. **Kamerabild** (Host-Ebene):
|
||||
Der `video_delay_proxy` puffert JPEG-Frames aus Port 8081 mit Timestamps. Beim Abruf wird der Frame geliefert, der zum Zeitpunkt `jetzt − Delay` aufgezeichnet wurde.
|
||||
|
||||
Der eingestellte Wert wird in `/tmp/exomy_delay.txt` gespeichert und von beiden Komponenten gleichzeitig gelesen. Änderungen über die Admin-Seite wirken sofort.
|
||||
|
||||
---
|
||||
|
||||
## 10. Bekannte Eigenheiten
|
||||
|
||||
- **Crabbing**: Funktioniert softwareseitig, mechanische Einstellung der Einzelräder ist noch nicht abgeschlossen.
|
||||
- **Containerstart**: Niemals `sudo docker run ...` nutzen – das falsche Home-Verzeichnis wird gemountet.
|
||||
- **Browser-Cache**: Nach GUI-Updates ggf. Shift+F5 (Hard Reload) im Browser nötig.
|
||||
- **Port 8081 direkt**: Erreichbar für Debug-Zwecke, zeigt immer das Live-Bild ohne Delay.
|
||||
@@ -35,6 +35,7 @@ then
|
||||
rosparam load /root/exomy_ws/src/exomy/config/exomy.yaml
|
||||
rosparam set /controller logitech-F710
|
||||
rosparam set /delay_seconds 0.0
|
||||
echo 0.0 > /tmp/exomy_delay.txt
|
||||
|
||||
/opt/ros/melodic/lib/rosbridge_server/rosbridge_websocket > /tmp/rosbridge.log 2>&1 &
|
||||
ROSBRIDGE_PID=$!
|
||||
|
||||
@@ -138,8 +138,32 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div id="auth_overlay" class="auth_overlay">
|
||||
<div class="auth_box">
|
||||
<p class="eyebrow" style="margin:0;">Admin-Zugang</p>
|
||||
<h2 style="margin:0;">CUNO System</h2>
|
||||
<p style="margin:0; font-size:0.88rem; opacity:.6;">Passwort eingeben um fortzufahren</p>
|
||||
<input type="password" id="auth_input" class="auth_input" placeholder="••••••••" autocomplete="current-password">
|
||||
<p id="auth_error" class="auth_error"></p>
|
||||
<button class="button buttonX" onclick="submitPassword()">Entsperren</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var adminApiBase = window.location.protocol + '//' + window.location.hostname + ':8082';
|
||||
var AUTH_TOKEN = 'Y3Vubw==';
|
||||
|
||||
function submitPassword() {
|
||||
var input = document.getElementById('auth_input');
|
||||
var error = document.getElementById('auth_error');
|
||||
if (btoa(input.value) === AUTH_TOKEN) {
|
||||
document.getElementById('auth_overlay').remove();
|
||||
} else {
|
||||
error.textContent = 'Falsches Passwort';
|
||||
input.value = '';
|
||||
input.focus();
|
||||
}
|
||||
}
|
||||
|
||||
function setAdminStatus(text) {
|
||||
var status = document.getElementById('admin_status');
|
||||
@@ -307,6 +331,12 @@
|
||||
}
|
||||
|
||||
window.addEventListener('load', function () {
|
||||
var input = document.getElementById('auth_input');
|
||||
input.focus();
|
||||
input.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter') submitPassword();
|
||||
});
|
||||
|
||||
fetchStatus();
|
||||
fetchDelay();
|
||||
window.setInterval(fetchStatus, 10000);
|
||||
|
||||
@@ -464,6 +464,54 @@ h2 {
|
||||
}
|
||||
}
|
||||
|
||||
.auth_overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: #05080F;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.auth_box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
padding: 2.5rem 2rem;
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
background: rgba(255,255,255,0.04);
|
||||
width: 100%;
|
||||
max-width: 320px;
|
||||
color: #e8f0f3;
|
||||
}
|
||||
|
||||
.auth_input {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0.7rem 0.9rem;
|
||||
border-radius: 6px;
|
||||
border: 1px solid rgba(255,255,255,0.15);
|
||||
background: rgba(0,0,0,0.35);
|
||||
color: #e8f0f3;
|
||||
font-size: 1rem;
|
||||
letter-spacing: 0.1em;
|
||||
outline: none;
|
||||
transition: border-color 0.15s;
|
||||
}
|
||||
|
||||
.auth_input:focus {
|
||||
border-color: rgba(0,136,255,0.6);
|
||||
}
|
||||
|
||||
.auth_error {
|
||||
margin: 0;
|
||||
min-height: 1.1em;
|
||||
font-size: 0.82rem;
|
||||
color: #e05555;
|
||||
}
|
||||
|
||||
.admin-page {
|
||||
color: #1b2730;
|
||||
overflow-y: auto;
|
||||
|
||||
Reference in New Issue
Block a user