# Location Tracker für n8n
Ein MQTT-basiertes Location-Tracking-System mit n8n, NocoDB und interaktiver Web-Visualisierung für OwnTracks-Geräte.
## Überblick
Dieses Repository enthält ein **MQTT-basiertes Location-Tracking-System** mit folgenden Komponenten:
- **n8n-tracker.json** - n8n-Workflow zur MQTT-Datenerfassung und API-Bereitstellung
- **index.html** - Interaktive Web-Oberfläche mit Leaflet.js
Das System empfängt Location-Updates von OwnTracks-kompatiblen Geräten über MQTT, speichert diese in einer NocoDB-Datenbank und bietet sowohl eine REST-API als auch eine Web-Visualisierung mit Echtzeit-Updates.
## Funktionen
### Workflow-Features
- **MQTT-Erfassung**: Automatischer Empfang von OwnTracks-Standortdaten über MQTT
- **Persistente Speicherung**: Unbegrenzte Historie in NocoDB-Datenbank
- **Telemetrie-Daten**: Batteriestatus und Geschwindigkeit werden mitgespeichert
- **REST-API**: JSON-Endpunkt für externe Anwendungen
- **Fehlerbehandlung**: Validierung und Fehlertoleranz bei ungültigen MQTT-Nachrichten
### Web-Oberflächen-Features
- **📍 Interaktive Karte** mit Leaflet.js
- **🗺️ 4 Kartenebenen**: Standard (OpenStreetMap), Satellit (Esri), Gelände (OpenTopoMap), Dunkel-Modus (CartoDB)
- **📱 Geräte-Filter**: Separate Ansicht pro Gerät
- **⏱️ Zeitfilter**: 1h, 3h, 6h, 12h, 24h
- **🔄 Auto-Refresh**: Toggle-fähig, 5-Sekunden-Intervall
- **📊 Bewegungshistorie**: Farbcodierte Polyline-Darstellung pro Gerät
- **🔋 Telemetrie-Anzeige**: Batteriestatus und Geschwindigkeit in Popups
- **🎨 Geräte-spezifische Farben**: Unterschiedliche Farben pro Gerät
## Voraussetzungen
### Basis-Anforderungen
- Eine laufende **n8n-Instanz** (Version 1.0+)
- **NocoDB-Instanz** mit API-Zugriff
- **MQTT-Broker** (z.B. Mosquitto)
- **OwnTracks-App** oder kompatibles MQTT-Gerät
### MQTT-Broker
Wenn noch kein MQTT-Broker vorhanden ist:
```bash
# Ubuntu/Debian
sudo apt install mosquitto mosquitto-clients
# Mosquitto starten
sudo systemctl start mosquitto
sudo systemctl enable mosquitto
# Test
mosquitto_sub -h localhost -p 1883 -t 'owntracks/#' -v
```
## Installation
### Schritt 1: n8n-Workflow importieren
1. Öffne deine n8n-Instanz
2. Navigiere zu **Workflows** → **Import from File**
3. Wähle `n8n-tracker.json` aus diesem Repository
4. Workflow wird als "Telegram Location Tracker - NocoDB" importiert (Name kann angepasst werden)
### Schritt 2: NocoDB-Datenbank einrichten
#### NocoDB-Tabelle erstellen
1. Erstelle ein neues Project in NocoDB
2. Erstelle eine Tabelle mit folgendem Schema:
| Spaltenname | Datentyp | Beschreibung |
|-------------|----------|--------------|
| `latitude` | Decimal | Breitengrad |
| `longitude` | Decimal | Längengrad |
| `timestamp` | DateTime | Zeitstempel (ISO 8601) |
| `user_id` | Number | Immer 0 für MQTT |
| `first_name` | Text | Tracker-ID (z.B. "10") |
| `last_name` | Text | Source-Typ (z.B. "fused") |
| `username` | Text | Tracker-ID (wie first_name) |
| `marker_label` | Text | Anzeigename für Karte |
| `display_time` | Text | Formatierter Zeitstempel |
| `chat_id` | Number | Immer 0 für MQTT |
| `battery` | Number | Batteriestatus (0-100) |
| `speed` | Decimal | Geschwindigkeit in m/s |
3. Notiere **Project ID** und **Table ID** aus der NocoDB-URL:
```
https://nocodb.example.com/nc/PROJECT_ID/TABLE_ID
```
#### NocoDB API-Token generieren
1. In NocoDB: **Account Settings** → **Tokens** → **Create Token**
2. Kopiere den generierten Token
### Schritt 3: Credentials in n8n konfigurieren
#### MQTT-Credentials
1. In n8n: **Credentials** → **Create New**
2. Wähle **"MQTT"**
3. Konfiguriere:
- **Protocol**: mqtt (oder mqtts für TLS)
- **Host**: Dein MQTT-Broker (z.B. `localhost` oder `broker.example.com`)
- **Port**: 1883 (Standard) oder 8883 (TLS)
- **Username**: MQTT-Benutzername
- **Password**: MQTT-Passwort
4. Speichere als "MQTT account"
#### NocoDB-Credentials
1. In n8n: **Credentials** → **Create New**
2. Wähle **"NocoDB API Token"**
3. Konfiguriere:
- **API Token**: Token aus Schritt 2
- **Base URL**: NocoDB-URL (z.B. `https://nocodb.example.com`)
4. Speichere als "NocoDB Token account"
### Schritt 4: Workflow-IDs anpassen
Öffne den importierten Workflow in n8n und passe an:
**In den Nodes "Lade Daten aus NocoDB" und "Speichere in NocoDB":**
- **Project ID**: Deine NocoDB-Projekt-ID (ersetze `pdxl4cx4dbu9nxi`)
- **Table ID**: Deine NocoDB-Tabellen-ID (ersetze `m8pqj5ixgnnrzkg`)
**Credential-Zuordnung prüfen:**
- MQTT Trigger → Wähle deine "MQTT account" Credentials
- NocoDB-Nodes → Wähle deine "NocoDB Token account" Credentials
### Schritt 5: OwnTracks-App konfigurieren
1. **OwnTracks-App installieren** (Android/iOS)
2. **MQTT-Modus aktivieren:**
- Öffne OwnTracks → **Preferences**
- **Mode**: MQTT
- **Host**: Dein MQTT-Broker (z.B. `broker.example.com`)
- **Port**: 1883 (oder 8883 für TLS)
- **Username**: MQTT-Benutzername
- **Password**: MQTT-Passwort
- **Device ID** (tid): z.B. "10" oder "11" (wichtig für Geräte-Identifikation!)
- **Tracker ID** (tid): Gleicher Wert wie Device ID
3. **TLS/Verschlüsselung** (optional aber empfohlen):
- Port auf 8883 ändern
- TLS aktivieren
4. **Tracking-Einstellungen:**
- **Monitoring**: Signifikante Standortänderungen
- **Move Mode**: 100m (oder nach Bedarf)
### Schritt 6: Web-Oberfläche konfigurieren
#### API-Endpunkt anpassen
Öffne `index.html` und passe die API-URL an (Zeile 178):
```javascript
const API_URL = 'https://deine-n8n-instanz.de/webhook/location';
```
**Webhook-URL finden:**
- In n8n: Öffne den Workflow
- Klicke auf den Node "Webhook - Location API"
- Die URL steht unter "Webhook URLs" (z.B. `https://n8n.example.com/webhook/location`)
#### Geräte-Namen konfigurieren
Passe die Geräte-Zuordnung in `index.html` an (Zeilen 142-152):
```javascript
const DEVICE_NAMES = {
'10': 'Joachim Pixel', // Device ID '10' → Anzeigename
'11': 'Huawei Smartphone' // Device ID '11' → Anzeigename
};
const DEVICE_COLORS = {
'10': '#e74c3c', // Rot
'11': '#3498db', // Blau
'default': '#95a5a6' // Grau für unbekannte Geräte
};
```
**Wichtig:** Die Keys (`'10'`, `'11'`) müssen mit der **Tracker ID (tid)** aus OwnTracks übereinstimmen!
#### Web-Oberfläche hosten
**Option 1: Webserver (empfohlen)**
```bash
# Apache
sudo cp index.html /var/www/html/tracker/
# nginx
sudo cp index.html /usr/share/nginx/html/tracker/
```
**Option 2: Lokaler Test**
- Öffne `index.html` direkt im Browser
- Funktioniert nur, wenn CORS korrekt konfiguriert ist
**Option 3: Static Hosting**
- GitHub Pages
- Netlify
- Vercel
### Schritt 7: Workflow aktivieren und testen
1. **Workflow aktivieren:**
- In n8n: Öffne den Workflow
- Klicke auf **"Active"** (Toggle oben rechts)
- Prüfe, dass alle Nodes grün sind (keine roten Fehler)
2. **Testen:**
- Öffne OwnTracks-App
- Sende einen Location-Update (App sendet automatisch oder manuell triggern)
- Prüfe in n8n die **Execution History**
- Öffne die Web-Oberfläche → Standort sollte erscheinen
3. **API-Test:**
```bash
curl https://deine-n8n-instanz.de/webhook/location
```
Sollte JSON zurückgeben mit `success: true` und Location-Daten
## Verwendung
### Standort senden (OwnTracks)
Die OwnTracks-App sendet automatisch Location-Updates basierend auf deinen Einstellungen:
- **Automatisch**: Bei signifikanten Standortänderungen
- **Manuell**: In der App auf "Publish" klicken
- **Intervall**: Konfigurierbar in App-Einstellungen
**MQTT-Topic-Format:**
```
owntracks/user/device
```
Beispiel: `owntracks/joachim/pixel`
**Nachrichtenformat (JSON):**
```json
{
"_type": "location",
"lat": 48.1351,
"lon": 11.5820,
"tst": 1700000000,
"tid": "10",
"batt": 85,
"vel": 5,
"acc": 10,
"alt": 520
}
```
### Web-Oberfläche verwenden
#### Filter-Optionen
**🗺️ Kartenebene:**
- **Standard**: OpenStreetMap (gut für Navigation)
- **Satellit**: Esri World Imagery (Luftbild)
- **Gelände**: OpenTopoMap (Höhenlinien)
- **Dunkel**: CartoDB Dark (Nachtmodus)
**📱 Gerät-Filter:**
- **Alle Geräte**: Zeigt alle MQTT-Geräte
- **Einzelnes Gerät**: Wähle aus Dropdown (wird dynamisch befüllt)
**⏱️ Zeitfilter:**
- **1 Stunde**: Nur letzte Stunde (Standard)
- **3/6/12/24 Stunden**: Weitere Zeiträume
- Alle älteren Punkte werden ausgeblendet
**🔄 Auto-Refresh:**
- **AN** (grün): Aktualisiert alle 5 Sekunden
- **AUS** (rot): Keine automatische Aktualisierung
#### Karte verstehen
**Marker:**
- **Größe**: Größter Marker = neuester Standort (32x32px), kleinere = Historie (16x16px)
- **Farbe**: Geräte-spezifisch (siehe `DEVICE_COLORS` Konfiguration)
- **Icon**: Kreisförmig mit dekorativem Zeiger (kein tatsächlicher Richtungsindikator)
**Polylines:**
- Verbinden Standorte chronologisch
- Farbe entspricht Gerät
- Zeigen Bewegungspfad
**Popups:**
- Klicke auf Marker für Details
- Zeigt: Gerätename, Zeitstempel, Batterie %, Geschwindigkeit (km/h)
### REST-API verwenden
**Endpunkt:**
```
GET https://deine-n8n-instanz.de/webhook/location
```
**Beispiel-Antwort:**
```json
{
"success": true,
"current": {
"latitude": 48.1351,
"longitude": 11.5820,
"timestamp": "2025-11-14T10:30:00.000Z",
"user_id": 0,
"first_name": "10",
"last_name": "fused",
"username": "10",
"marker_label": "10",
"display_time": "14.11.2025, 11:30:00",
"chat_id": 0,
"battery": 85,
"speed": 5.2
},
"history": [
{ /* weitere Location-Objekte */ }
],
"total_points": 42,
"last_updated": "2025-11-14T10:30:00.000Z"
}
```
**Integration in eigene Apps:**
```javascript
// JavaScript Beispiel
fetch('https://n8n.example.com/webhook/location')
.then(response => response.json())
.then(data => {
console.log('Aktueller Standort:', data.current);
console.log('Batterie:', data.current.battery + '%');
});
```
```python
# Python Beispiel
import requests
response = requests.get('https://n8n.example.com/webhook/location')
data = response.json()
if data['success']:
current = data['current']
print(f"Position: {current['latitude']}, {current['longitude']}")
print(f"Batterie: {current['battery']}%")
```
## Workflow-Architektur
### Übersicht
Der **n8n-tracker.json** Workflow besteht aus zwei unabhängigen Flows:
```
Flow 1: MQTT Location Capture
┌──────────────┐
│ MQTT Trigger │ (owntracks/#)
└──────┬───────┘
│
v
┌──────────────────────────┐
│ MQTT Location verarbeiten│ (JavaScript)
└──────┬───────────────────┘
│
v
┌──────────────────┐
│ Speichere in │ (NocoDB Create)
│ NocoDB │
└──────────────────┘
Flow 2: Location API
┌──────────────────────┐
│ Webhook - Location │ (GET /webhook/location)
│ API │
└──────┬───────────────┘
│
v
┌──────────────────────┐
│ Lade Daten aus │ (NocoDB Get All)
│ NocoDB │
└──────┬───────────────┘
│
v
┌──────────────────────┐
│ Format API Response │ (JavaScript)
└──────┬───────────────┘
│
v
┌──────────────────────┐
│ JSON Response │ (CORS + JSON)
└──────────────────────┘
```
### Flow 1: MQTT Location Capture (Details)
**MQTT Trigger:**
- Subscribed auf Topic: `owntracks/#`
- Empfängt alle OwnTracks-Messages
- Keine Filter auf Trigger-Ebene
**MQTT Location verarbeiten (JavaScript):**
```javascript
// Wichtige Schritte:
1. Parse JSON aus message-Feld
2. Validiere lat, lon, tst (erforderlich)
3. Konvertiere Unix-Timestamp → ISO 8601
4. Extrahiere tid (Tracker ID) → username
5. Formatiere displayTime (de-DE, Europe/Berlin)
6. Packe Telemetrie in mqtt_data Objekt
7. Überspringe ungültige Nachrichten mit continue
```
**Speichere in NocoDB:**
- Erstellt neuen Datensatz pro Location
- Mappt 12 Felder (inkl. battery, speed)
- Keine Duplikatsprüfung (alle Updates werden gespeichert)
### Flow 2: Location API (Details)
**Webhook - Location API:**
- HTTP GET auf `/location`
- CORS: `Access-Control-Allow-Origin: *`
- Keine Authentifizierung (öffentlich!)
**Lade Daten aus NocoDB:**
- Holt ALLE Datensätze (`returnAll: true`)
- Keine Sortierung auf DB-Ebene
- Keine Pagination
**Format API Response (JavaScript):**
```javascript
// Schritte:
1. Sammle alle Location-Objekte
2. Sortiere nach timestamp (neueste zuerst)
3. Wähle neuste als "current"
4. Baue Response-Struktur
5. Zähle total_points
```
**JSON Response:**
- Content-Type: application/json
- CORS-Header gesetzt
- Keine Kompression
## Datenspeicherung & Schema
### NocoDB-Konfiguration
**Aktuelle IDs im Workflow:**
- **Project ID**: `pdxl4cx4dbu9nxi` (muss angepasst werden!)
- **Table ID**: `m8pqj5ixgnnrzkg` (muss angepasst werden!)
- **Credential**: "NocoDB Token account"
### Datenbank-Schema
Vollständiges Schema mit Beispieldaten:
| Feld | Typ | Beispielwert | Beschreibung |
|------|-----|--------------|--------------|
| `latitude` | Decimal | `48.1383784` | Breitengrad (WGS84) |
| `longitude` | Decimal | `11.4276172` | Längengrad (WGS84) |
| `timestamp` | DateTime | `2025-11-14T18:00:37.000Z` | UTC-Zeitstempel (ISO 8601) |
| `user_id` | Number | `0` | Immer 0 für MQTT-Geräte |
| `first_name` | Text | `"11"` | Tracker-ID (tid) |
| `last_name` | Text | `"fused"` | Location-Source |
| `username` | Text | `"11"` | Tracker-ID (gleich wie first_name) |
| `marker_label` | Text | `"11"` | Anzeigename für Karte |
| `display_time` | Text | `"14.11.2025, 19:00:37"` | Formatiert (de-DE) |
| `chat_id` | Number | `0` | Immer 0 für MQTT-Geräte |
| `battery` | Number | `73` | Batteriestatus (0-100%) |
| `speed` | Decimal | `0` | Geschwindigkeit in m/s |
### OwnTracks-Feld-Mapping
| NocoDB-Feld | OwnTracks-Feld | Transformation |
|-------------|----------------|----------------|
| `latitude` | `lat` | Direkt |
| `longitude` | `lon` | Direkt |
| `timestamp` | `tst` | Unix → ISO 8601 |
| `user_id` | - | Konstant: `0` |
| `first_name` | `tid` | Tracker-ID |
| `last_name` | `source` | Location-Quelle |
| `username` | `tid` | Tracker-ID |
| `marker_label` | `tid` | Tracker-ID |
| `display_time` | `tst` | Formatiert (de-DE, Berlin) |
| `chat_id` | - | Konstant: `0` |
| `battery` | `batt` | Direkt |
| `speed` | `vel` | m/s (nicht konvertiert!) |
**Nicht gespeicherte OwnTracks-Felder:**
- `acc` - Genauigkeit (Meter)
- `alt` - Höhe (Meter)
- `cog` - Kurs über Grund
- `conn` - Verbindungstyp (w/m)
- `_id` - Device Identifier
## Anpassungen & Customization
### Neues Gerät hinzufügen
**Schritt 1: OwnTracks-App konfigurieren**
- Setze Tracker ID (tid) auf eindeutige ID, z.B. "12"
- Konfiguriere MQTT-Verbindung wie oben beschrieben
**Schritt 2: index.html anpassen (Zeilen 142-152)**
```javascript
const DEVICE_NAMES = {
'10': 'Joachim Pixel',
'11': 'Huawei Smartphone',
'12': 'Neues Gerät' // HINZUFÜGEN
};
const DEVICE_COLORS = {
'10': '#e74c3c',
'11': '#3498db',
'12': '#2ecc71', // HINZUFÜGEN (Grün)
'default': '#95a5a6'
};
```
**Farb-Vorschläge:**
- `#e74c3c` - Rot
- `#3498db` - Blau
- `#2ecc71` - Grün
- `#f39c12` - Orange
- `#9b59b6` - Lila
- `#1abc9c` - Türkis
**Schritt 3: Testen**
- Sende Location von neuem Gerät
- Prüfe Web-Oberfläche → Gerät sollte im Dropdown erscheinen
- Marker sollte in konfigurierter Farbe erscheinen
### Zeitzone ändern
**In n8n-Workflow, Node "MQTT Location verarbeiten" (Zeile 124):**
```javascript
// Aktuell: Berlin-Zeit
const displayTime = new Date(timestampMs).toLocaleString('de-DE', {
timeZone: 'Europe/Berlin'
});
// Ändern zu New York:
const displayTime = new Date(timestampMs).toLocaleString('en-US', {
timeZone: 'America/New_York'
});
// Ändern zu UTC:
const displayTime = new Date(timestampMs).toISOString();
// Eigenes Format:
const displayTime = new Date(timestampMs).toLocaleString('de-DE', {
timeZone: 'Europe/Berlin',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
```
### Standard-Zeitfilter ändern
**In index.html (Zeile 125):**
```html
```
### Auto-Refresh-Intervall anpassen
**In index.html (Zeile 419):**
```javascript
// Aktuell: 5 Sekunden (5000ms)
refreshInterval = setInterval(loadLocations, 5000);
// Ändern zu 10 Sekunden:
refreshInterval = setInterval(loadLocations, 10000);
// Ändern zu 1 Minute:
refreshInterval = setInterval(loadLocations, 60000);
```
### CORS einschränken (Sicherheit!)
**In n8n-Workflow, Node "JSON Response" (Zeile 67):**
```json
// Aktuell (unsicher):
{
"name": "Access-Control-Allow-Origin",
"value": "*"
}
// Ändern zu spezifischer Domain:
{
"name": "Access-Control-Allow-Origin",
"value": "https://web.example.com"
}
```
### Weitere NocoDB-Felder speichern
**Beispiel: Genauigkeit (accuracy) und Höhe (altitude) hinzufügen**
**Schritt 1: NocoDB-Spalten erstellen**
- `accuracy` (Number)
- `altitude` (Number)
**Schritt 2: Workflow-Node "MQTT Location verarbeiten" anpassen:**
```javascript
// In mqtt_data Objekt ergänzen:
mqtt_data: {
accuracy: mqttData.acc,
altitude: mqttData.alt,
battery: mqttData.batt,
velocity: mqttData.vel,
course: mqttData.cog,
connection: mqttData.conn,
device_id: mqttData._id
}
```
**Schritt 3: Node "Speichere in NocoDB" anpassen:**
Füge in `fieldsUi.fieldValues` hinzu:
```json
{
"fieldName": "accuracy",
"fieldValue": "={{ $json.mqtt_data.accuracy }}"
},
{
"fieldName": "altitude",
"fieldValue": "={{ $json.mqtt_data.altitude }}"
}
```
**Schritt 4: index.html Popups erweitern (Zeile 320):**
```javascript
// Nach Speed-Anzeige hinzufügen:
if (loc.accuracy !== undefined && loc.accuracy !== null) {
popupContent += `
📍 Genauigkeit: ${loc.accuracy}m`;
}
if (loc.altitude !== undefined && loc.altitude !== null) {
popupContent += `
⛰️ Höhe: ${loc.altitude}m`;
}
```
### MQTT-Topic einschränken
**In n8n-Workflow, Node "MQTT Trigger" (Zeile 104):**
```javascript
// Aktuell: Alle OwnTracks-Topics
topics: "owntracks/#"
// Nur spezifischer Benutzer:
topics: "owntracks/joachim/#"
// Nur spezifisches Gerät:
topics: "owntracks/joachim/pixel"
// Mehrere Topics:
topics: "owntracks/joachim/#,owntracks/lisa/#"
```
## Sicherheitshinweise
### Kritisch (sofort beheben!)
**1. API ohne Authentifizierung**
- ⚠️ **Problem**: Jeder kann Standortdaten abrufen, wenn er die URL kennt
- ⚠️ **Risiko**: DSGVO-Verstoß, Privatsphäre-Verletzung
- ✅ **Lösung**:
- Implementiere API-Key-Authentifizierung in n8n
- Oder nutze Reverse-Proxy mit Basic Auth
- Oder beschränke Zugriff per IP-Whitelist
**2. CORS offen für alle Domains**
- ⚠️ **Problem**: `Access-Control-Allow-Origin: *`
- ⚠️ **Risiko**: XSS-Angriffe, unautorisierten Zugriff
- ✅ **Lösung**: Beschränke auf deine Domain (siehe "CORS einschränken")
**3. DSGVO-Compliance**
- ⚠️ **Problem**: Personenbezogene Standortdaten ohne Einwilligung/Löschkonzept
- ⚠️ **Pflichten**: Informationspflicht, Einwilligung, Auskunftsrecht, Löschung
- ✅ **Lösung**:
- Hole explizite Einwilligung von Nutzern ein
- Implementiere automatische Löschung alter Daten (z.B. >30 Tage)
- Dokumentiere Datenschutzmaßnahmen
- Stelle Löschfunktion bereit
### Wichtig (empfohlen)
**4. MQTT ohne TLS**
- ⚠️ **Problem**: Unverschlüsselte Übertragung auf Port 1883
- ⚠️ **Risiko**: Standortdaten können abgefangen werden
- ✅ **Lösung**:
- Aktiviere TLS in Mosquitto (Port 8883)
- Konfiguriere OwnTracks mit TLS
**5. Keine Rate-Limiting**
- ⚠️ **Problem**: API kann unbegrenzt oft abgerufen werden
- ⚠️ **Risiko**: DoS-Angriff, Server-Überlastung
- ✅ **Lösung**: Implementiere Rate-Limiting (z.B. via nginx)
**6. NocoDB-Token zu weitreichend**
- ⚠️ **Problem**: Token hat möglicherweise Schreibrechte für API-Endpunkt
- ⚠️ **Risiko**: Datenmanipulation
- ✅ **Lösung**: Nutze separaten Read-Only-Token für API-Endpunkt (falls möglich)
### Best Practices
- **HTTPS erzwingen**: n8n-Webhooks nur über HTTPS erreichbar machen
- **Monitoring**: Überwache ungewöhnliche API-Zugriffe
- **Backup**: Sichere NocoDB-Datenbank regelmäßig
- **Updates**: Halte n8n, NocoDB, Mosquitto und Dependencies aktuell
- **Secrets**: Speichere Credentials nur in n8n Credential Store, nicht im Code
- **Logging**: Aktiviere Audit-Logging für Zugriffe
## Fehlerbehebung
### MQTT-Daten kommen nicht an
**Symptome**: OwnTracks sendet, aber nichts in NocoDB gespeichert
**Lösungen:**
1. **MQTT-Broker testen:**
```bash
mosquitto_sub -h broker.example.com -p 1883 -u user -P pass -t 'owntracks/#' -v
```
Sollte Nachrichten anzeigen, wenn OwnTracks sendet.
2. **OwnTracks-Konfiguration prüfen:**
- Mode: MQTT (nicht HTTP!)
- Topic: `owntracks/USER/DEVICE`
- Verbindungsstatus in App prüfen
- Test-Nachricht senden (Publish Button)
3. **n8n MQTT-Node prüfen:**
- Credentials korrekt?
- Topic-Pattern passt? (`owntracks/#`)
- Workflow ist aktiviert?
4. **n8n Execution History prüfen:**
- Workflows → n8n-tracker → Executions
- Gibt es Executions?
- Gibt es Fehler (rot markiert)?
5. **Debug mit manuellem Test:**
```bash
# Sende Test-Nachricht per mosquitto_pub
mosquitto_pub -h broker.example.com -p 1883 -u user -P pass \
-t 'owntracks/test/device' \
-m '{"_type":"location","lat":48.1351,"lon":11.5820,"tid":"10","tst":1700000000,"batt":85,"vel":5}'
```
### API gibt leere Daten zurück
**Symptome**: API antwortet mit `{"history": []}` oder `"current": null`
**Lösungen:**
1. **NocoDB-Verbindung testen:**
- In n8n: Credentials → NocoDB → Test Connection
- Sollte grüner Haken erscheinen
2. **NocoDB direkt testen:**
```bash
curl -H "xc-token: YOUR_TOKEN" \
"https://nocodb.example.com/api/v1/db/data/v1/PROJECT_ID/TABLE_ID"
```
Sollte JSON mit Daten zurückgeben.
3. **Project/Table IDs prüfen:**
- Öffne NocoDB-Tabelle im Browser
- URL enthält die IDs: `/nc/PROJECT_ID/TABLE_ID`
- Vergleiche mit IDs in n8n-Workflow
4. **Daten in NocoDB vorhanden?**
- Öffne Tabelle in NocoDB
- Sind Einträge vorhanden?
- Wenn nicht: Problem liegt bei MQTT-Erfassung (siehe oben)
### Web-Oberfläche zeigt keine Karte
**Symptome**: Weiße Seite, Karte lädt nicht, Marker fehlen
**Lösungen:**
1. **Browser-Console prüfen (F12 → Console):**
- CORS-Fehler? → API-CORS-Header prüfen
- 404 auf Leaflet.js? → CDN-Problem (lokale Kopie nutzen)
- API-Fehler? → Siehe "API gibt leere Daten zurück"
- JavaScript-Fehler? → Code-Syntax prüfen
2. **API-URL prüfen:**
- In index.html Zeile 178: `const API_URL = '...'`
- URL muss erreichbar sein
- Test im Browser: URL direkt aufrufen → Sollte JSON zurückgeben
3. **Netzwerk-Tab prüfen (F12 → Network):**
- Request zu API wird gesendet?
- Status 200 OK?
- Response enthält Daten?
- CORS-Header vorhanden?
4. **Leaflet.js CDN erreichbar?**
- Prüfe ob `https://unpkg.com/leaflet@1.9.4/dist/leaflet.js` geladen wird
- Falls CDN-Problem: Nutze lokale Kopie
### Koordinaten sind falsch/vertauscht
**Symptome**: Marker erscheinen im Meer, falsche Position
**Lösungen:**
1. **Reihenfolge prüfen:**
- Leaflet erwartet: `[latitude, longitude]`
- NICHT: `[longitude, latitude]`
- OwnTracks sendet korrekt: `lat`, `lon`
2. **Daten in NocoDB prüfen:**
- Öffne Tabelle
- Ist `latitude` der Breitengrad (z.B. 48.x)?
- Ist `longitude` der Längengrad (z.B. 11.x)?
- Für München: ca. 48°N, 11°O
3. **JavaScript-Code prüfen:**
```javascript
// RICHTIG:
const lat = parseFloat(loc.latitude);
const lon = parseFloat(loc.longitude);
L.marker([lat, lon])
// FALSCH:
L.marker([lon, lat]) // Vertauscht!
```
### Geräte-Filter zeigt nicht alle Geräte
**Symptome**: Dropdown zeigt "Alle Geräte" aber keine einzelnen Geräte
**Lösungen:**
1. **MQTT-Daten vorhanden?**
- API aufrufen und prüfen: Gibt es Einträge mit `user_id: 0`?
- Wenn nicht: Keine MQTT-Daten in Datenbank
2. **username-Feld befüllt?**
- In NocoDB prüfen: Ist `username` gesetzt?
- Sollte gleich wie `first_name` sein (tid)
3. **JavaScript-Console prüfen:**
```javascript
// In Browser-Console (F12):
console.log(allData.history.filter(loc => loc.user_id == 0));
```
Sollte MQTT-Einträge zeigen.
4. **Filter-Code prüfen (index.html Zeile 267):**
```javascript
let filteredData = allData.history.filter(loc => loc.user_id == 0);
```
Muss MQTT-Daten filtern.
### Geschwindigkeit wird nicht angezeigt
**Symptome**: Popup zeigt keine Geschwindigkeit, obwohl OwnTracks sendet
**Lösungen:**
1. **OwnTracks sendet velocity?**
- Prüfe MQTT-Nachricht (mosquitto_sub)
- Sollte `vel` Feld enthalten
2. **NocoDB-Feld `speed` vorhanden?**
- Tabellen-Schema prüfen
- Spalte `speed` (Decimal) muss existieren
3. **Workflow speichert speed?**
- Node "Speichere in NocoDB" prüfen
- Mapping: `fieldName: "speed"`, `fieldValue: "={{ $json.mqtt_data.velocity }}"`
4. **Null-Werte prüfen:**
- Nicht alle OwnTracks-Messages enthalten `vel`
- Code prüft auf `!== null` (index.html Zeile 328)
### Batteriestatus zeigt 0% oder fehlt
**Symptome**: Batterie wird als 0% angezeigt oder fehlt im Popup
**Lösungen:**
1. **OwnTracks sendet battery?**
- Android/iOS unterscheiden sich
- Manche Geräte senden kein `batt` Feld
- Prüfe MQTT-Nachricht
2. **Berechtigungen in OwnTracks:**
- Android: Batterie-Optimierung deaktivieren
- iOS: Standortfreigabe "Immer" setzen
3. **NocoDB-Wert prüfen:**
- Tabelle öffnen
- Ist `battery` befüllt?
- Typ Number (nicht Text!)
## Repository-Inhalte
| Datei | Beschreibung |
|-------|--------------|
| `n8n-tracker.json` | n8n-Workflow für MQTT-Erfassung und API |
| `index.html` | Web-Oberfläche mit Leaflet.js |
| `database-example.csv` | Beispiel-Datenexport aus NocoDB |
| `README.md` | Diese Dokumentation |
| `CLAUDE.md` | Technische Architektur-Dokumentation |
## Lizenz
Dieses Projekt steht unter der **MIT-Lizenz** zur freien Verfügung.
## Support & Contributing
- **Issues**: Melde Bugs oder Feature-Requests via GitHub Issues
- **Pull Requests**: Beiträge sind willkommen!
- **Fragen**: Öffne eine Discussion auf GitHub
## Roadmap (Potenzielle Features)
- [ ] API-Authentifizierung (API-Key, JWT)
- [ ] Automatische Datenlöschung (DSGVO-Compliance)
- [ ] Geofencing / Location-Alerts
- [ ] Multi-User-Support mit Zugriffsrechten
- [ ] Erweiterte Statistiken (Distanz, Durchschnittsgeschwindigkeit)
- [ ] Export-Funktion (GPX, KML, CSV)
- [ ] Push-Notifications bei Location-Updates
- [ ] Offline-Support für Web-UI (PWA)
- [ ] Mobile App (React Native / Flutter)