Files
location-mqtt-tracker-app/README.md
Joachim Hummel e8a5f59e1d Update README with MQTT tables and parent_user_id documentation
Added documentation for:
- parent_user_id column in User table (hierarchical user management)
- mqtt_credentials table with device authentication
- mqtt_acl_rules table for topic permissions
- mqtt_sync_status table for broker synchronization
- All new database indexes
- Updated ER diagram with new relationships

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 13:53:27 +00:00

909 lines
24 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Location Tracker - Next.js Anwendung
Eine moderne Location-Tracking Anwendung basierend auf Next.js 14 mit MQTT/OwnTracks Integration, SQLite-Datenbank, Admin-Panel und Authentifizierung.
## 📋 Inhaltsverzeichnis
- [Features](#-features)
- [Tech Stack](#-tech-stack)
- [Installation](#-installation)
- [Datenbank-Setup](#-datenbank-setup)
- [Verwendung](#-verwendung)
- [Architektur](#-architektur)
- [API-Endpunkte](#-api-endpunkte)
- [Device Management](#-device-management)
- [Wartung](#-wartung)
- [Deployment](#-deployment)
---
## ✨ Features
### Öffentliche Features
- 🗺️ **Interaktive Karte** - Echtzeit-Standortverfolgung mit Leaflet.js
- 🎨 **Mehrere Kartenansichten** - Standard, Satellit, Dark Mode
- 🔍 **Device-Filterung** - Filtern nach Gerät und Zeitraum
- ⏱️ **Flexible Zeitfilter**:
- **Quick Filters:** 1h, 3h, 6h, 12h, 24h, All
- **Custom Range:** Benutzerdefinierter Zeitraum mit DateTime-Picker (z.B. 16.11.2025 16:00 - 17.11.2025 06:00)
- Kompakte UI - Custom Range nur sichtbar wenn aktiviert
- 🔄 **Auto-Refresh** - Automatische Aktualisierung alle 5 Sekunden mit Pause/Resume Button
- 🎯 **Auto-Center** - Karte zentriert automatisch auf neueste Position
- ⏸️ **Pause/Resume** - Toggle-Button zum Stoppen/Starten des Auto-Refresh
- 📱 **Responsive Design** - Optimiert für Desktop und Mobile
- 📊 **Polylines** - Bewegungspfade mit farbcodierter Darstellung
- 🎨 **Marker-Sortierung** - Neueste Position immer im Vordergrund (z-index optimiert)
- 📍 **Zoom-basierte Icon-Skalierung** - Marker passen sich automatisch an Zoom-Level an
### Admin-Panel (Login erforderlich)
- 🔐 **Authentifizierung** - NextAuth.js v5 mit bcrypt-Hashing
- 📊 **Dashboard** - Übersicht über Geräte, Statistiken und Datenbankstatus
- ⏱️ **System Status** - Live-Uptime, Memory Usage, Runtime Info
- 📱 **Device Management** - Geräte hinzufügen, bearbeiten, löschen
- 💾 **Datenbank-Wartung**:
- 🧹 Cleanup alter Daten (7, 15, 30, 90 Tage)
- ⚡ Datenbank-Optimierung (VACUUM)
- 📈 Detaillierte Statistiken
- 🟢 **Online/Offline Status** - Echtzeit-Status (< 10 Min = Online)
- 🔋 **Telemetrie-Daten** - Batterie, Geschwindigkeit, letzte Position (speed=0 wird korrekt behandelt)
---
## 🛠 Tech Stack
- **Framework:** Next.js 14 (App Router)
- **Sprache:** TypeScript 5.9
- **Styling:** Tailwind CSS v4
- **Karten:** Leaflet 1.9.4 + React-Leaflet 5.0
- **Authentifizierung:** NextAuth.js v5 (beta)
- **Datenbank:** SQLite (better-sqlite3)
- **Passwort-Hashing:** bcryptjs
- **Datenquelle:** MQTT Broker + lokale SQLite-Cache
### Dual-Database Architektur
- **database.sqlite** - User, Geräte (kritische Daten)
- **locations.sqlite** - Location-Tracking (hohe Schreibrate, isoliert)
---
## 📦 Installation
### Voraussetzungen
- Node.js 18+
- npm oder yarn
### Schritte
1. **Repository klonen**
```bash
git clone https://github.com/yourusername/location-tracker-app.git
cd location-tracker-app
```
2. **Dependencies installieren**
```bash
npm install
```
3. **Datenbank initialisieren**
```bash
npm run db:init
```
Dies erstellt:
- `data/database.sqlite` (User + Devices)
- `data/locations.sqlite` (Location-Tracking)
- Standard Admin-User: `admin` / `admin123`
- Standard Devices (ID 10, 11)
4. **Development Server starten**
```bash
npm run dev
```
5. **Im Browser öffnen**
- Karte: http://localhost:3000
- Login: http://localhost:3000/login
- Admin: http://localhost:3000/admin
- Devices: http://localhost:3000/admin/devices
---
## 🗄️ Datenbank-Setup
### Initialisierung
**Beide Datenbanken erstellen:**
```bash
npm run db:init
```
**Nur database.sqlite (User/Devices):**
```bash
npm run db:init:app
```
**Nur locations.sqlite (Tracking):**
```bash
npm run db:init:locations
```
### Datenbank zurücksetzen
**Admin-User neu anlegen:**
```bash
node scripts/reset-admin.js
```
**Alte Locations löschen:**
```bash
npm run db:cleanup # Älter als 7 Tage
npm run db:cleanup:7d # Älter als 7 Tage
npm run db:cleanup:30d # Älter als 30 Tage
```
**Duplikate entfernen (falls vorhanden):**
```bash
node scripts/remove-duplicates.js
```
### Schema
#### **database.sqlite** (User & Devices)
**User Tabelle:**
```sql
id TEXT PRIMARY KEY
username TEXT UNIQUE NOT NULL
email TEXT
passwordHash TEXT NOT NULL
role TEXT NOT NULL DEFAULT 'VIEWER' -- ADMIN oder VIEWER
parent_user_id TEXT -- FK zu User.id (Hierarchie)
createdAt TEXT DEFAULT (datetime('now'))
updatedAt TEXT DEFAULT (datetime('now'))
lastLoginAt TEXT
```
**Device Tabelle:**
```sql
id TEXT PRIMARY KEY
name TEXT NOT NULL
color TEXT NOT NULL
ownerId TEXT -- FK zu User.id
isActive INTEGER DEFAULT 1 -- 0 oder 1
description TEXT
icon TEXT
createdAt TEXT DEFAULT (datetime('now'))
updatedAt TEXT DEFAULT (datetime('now'))
```
**MQTT Credentials Tabelle:**
```sql
id INTEGER PRIMARY KEY AUTOINCREMENT
device_id TEXT NOT NULL UNIQUE -- FK zu Device.id
mqtt_username TEXT NOT NULL UNIQUE
mqtt_password_hash TEXT NOT NULL
enabled INTEGER DEFAULT 1 -- 0 oder 1
created_at TEXT DEFAULT (datetime('now'))
updated_at TEXT DEFAULT (datetime('now'))
```
**MQTT ACL Rules Tabelle:**
```sql
id INTEGER PRIMARY KEY AUTOINCREMENT
device_id TEXT NOT NULL -- FK zu Device.id
topic_pattern TEXT NOT NULL
permission TEXT NOT NULL -- 'read', 'write', 'readwrite'
created_at TEXT DEFAULT (datetime('now'))
```
**MQTT Sync Status Tabelle:**
```sql
id INTEGER PRIMARY KEY CHECK (id = 1) -- Singleton
pending_changes INTEGER DEFAULT 0
last_sync_at TEXT
last_sync_status TEXT
created_at TEXT DEFAULT (datetime('now'))
updated_at TEXT DEFAULT (datetime('now'))
```
**Indexes:**
- `idx_user_username` ON User(username)
- `idx_user_parent` ON User(parent_user_id)
- `idx_device_owner` ON Device(ownerId)
- `idx_device_active` ON Device(isActive)
- `idx_mqtt_credentials_device` ON mqtt_credentials(device_id)
- `idx_mqtt_credentials_username` ON mqtt_credentials(mqtt_username)
- `idx_mqtt_acl_device` ON mqtt_acl_rules(device_id)
---
#### **locations.sqlite** (Tracking Data)
**Location Tabelle:**
```sql
id INTEGER PRIMARY KEY AUTOINCREMENT
latitude REAL NOT NULL -- -90 bis +90
longitude REAL NOT NULL -- -180 bis +180
timestamp TEXT NOT NULL -- ISO 8601 format
user_id INTEGER DEFAULT 0
first_name TEXT
last_name TEXT
username TEXT -- Device Tracker ID
marker_label TEXT
display_time TEXT -- Formatierte Zeit für UI
chat_id INTEGER DEFAULT 0
battery INTEGER -- Batteriestand in %
speed REAL -- Geschwindigkeit in km/h
created_at TEXT DEFAULT (datetime('now'))
```
**Indexes:**
- `idx_location_timestamp` ON Location(timestamp DESC)
- `idx_location_username` ON Location(username)
- `idx_location_user_id` ON Location(user_id)
- `idx_location_composite` ON Location(user_id, username, timestamp DESC)
- `idx_location_unique` UNIQUE ON Location(timestamp, username, latitude, longitude)
**Constraints:**
- Latitude: -90 bis +90
- Longitude: -180 bis +180
- UNIQUE: Kombination aus timestamp, username, latitude, longitude verhindert Duplikate
**WAL Mode:** Beide Datenbanken nutzen Write-Ahead Logging für bessere Concurrency
---
## 🚀 Verwendung
### Login
Standard-Zugangsdaten:
```
Benutzername: admin
Passwort: admin123
```
**Wichtig:** Für Production neuen User anlegen und Passwort ändern!
### Geräte hinzufügen
1. Admin-Panel öffnen: `/admin/devices`
2. "Add Device" klicken
3. Device ID (muss mit OwnTracks `tid` übereinstimmen)
4. Name und Farbe festlegen
5. Speichern
**Wichtig:** Die Device ID muss mit der OwnTracks Tracker-ID übereinstimmen!
### OwnTracks konfigurieren
In der OwnTracks App:
- **Tracker ID (tid):** z.B. `12`
- **Topic:** `owntracks/user/12`
- MQTT Broker konfigurieren (siehe MQTT Setup)
Die App empfängt die Daten direkt vom MQTT Broker.
### Zeitfilter verwenden
Die App bietet zwei Modi für die Zeitfilterung:
#### **Quick Filters** (Schnellauswahl)
Vordefinierte Zeiträume für schnellen Zugriff:
- **1 Hour** - Locations der letzten Stunde
- **3 Hours** - Locations der letzten 3 Stunden
- **6 Hours** - Locations der letzten 6 Stunden
- **12 Hours** - Locations der letzten 12 Stunden
- **24 Hours** - Locations der letzten 24 Stunden
- **All** - Alle verfügbaren Locations
**Verwendung:**
1. Im Header unter "Time:" gewünschten Zeitraum auswählen
2. Die Karte aktualisiert sich automatisch
#### **Custom Range** (Benutzerdefiniert)
Für spezifische Zeiträume, z.B. "Route von gestern Abend 18:00 bis heute Morgen 08:00":
**Verwendung:**
1. Auf den **"📅 Custom"** Button klicken
2. Custom Range Felder erscheinen:
- **From:** Start-Datum und -Zeit wählen (z.B. 16.11.2025 16:00)
- **To:** End-Datum und -Zeit wählen (z.B. 17.11.2025 06:00)
3. Die Route wird automatisch für den gewählten Zeitraum angezeigt
4. Zum Zurückschalten: **"📅 Quick"** Button klicken
**Hinweis:** Custom Range Controls sind nur sichtbar wenn aktiviert - spart Platz im Header!
---
## 🏗 Architektur
### Datenfluss
```mermaid
flowchart TD
A[📱 OwnTracks App] -->|MQTT Publish| B[🔌 MQTT Broker]
B -->|Subscribe| C[📡 Next.js MQTT Subscriber]
C -->|Store Locations| D[(🗄️ SQLite Cache<br/>locations.sqlite)]
E[🖥️ Browser Client] -->|GET /api/locations<br/>alle 5 Sek| F[📡 Next.js API Route]
D -->|Query Filtered Data| F
F -->|JSON Response| E
E -->|Render| G[🗺️ React Leaflet Map]
H[👤 Admin User] -->|Login| I[🔐 NextAuth.js]
I -->|Authenticated| J[📊 Admin Panel]
J -->|CRUD Operations| K[(💼 SQLite DB<br/>database.sqlite)]
style A fill:#4CAF50
style B fill:#FF9800
style C fill:#2196F3
style D fill:#FFC107
style F fill:#00BCD4
style G fill:#8BC34A
style I fill:#E91E63
style K fill:#FFC107
```
### Komponenten-Übersicht
```mermaid
graph LR
subgraph "External Services"
A[OwnTracks App]
B[MQTT Broker]
end
subgraph "Next.js Application"
C[MQTT Subscriber]
D[Frontend<br/>React/Leaflet]
E[API Routes]
F[Auth Layer<br/>NextAuth.js]
end
subgraph "Data Layer"
G[locations.sqlite<br/>Tracking Data]
H[database.sqlite<br/>Users & Devices]
end
A -->|MQTT| B
B -->|Subscribe| C
C -->|Write| G
D -->|HTTP| E
E -->|Read/Write| G
E -->|Read/Write| H
D -->|Auth| F
F -->|Validate| H
style A fill:#4CAF50,color:#fff
style B fill:#FF9800,color:#fff
style C fill:#2196F3,color:#fff
style D fill:#00BCD4,color:#000
style E fill:#00BCD4,color:#000
style F fill:#E91E63,color:#fff
style G fill:#FFC107,color:#000
style H fill:#FFC107,color:#000
```
### Datenbank-Architektur
```mermaid
erDiagram
USER ||--o{ USER : "parent_user_id"
USER ||--o{ DEVICE : owns
DEVICE ||--o{ LOCATION : tracks
DEVICE ||--o| MQTT_CREDENTIALS : has
DEVICE ||--o{ MQTT_ACL_RULES : has
USER {
string id PK
string username UK
string email
string passwordHash
string role
string parent_user_id FK
datetime createdAt
datetime lastLoginAt
}
DEVICE {
string id PK
string name
string color
string ownerId FK
boolean isActive
string description
datetime createdAt
}
MQTT_CREDENTIALS {
int id PK
string device_id FK_UK
string mqtt_username UK
string mqtt_password_hash
boolean enabled
datetime created_at
datetime updated_at
}
MQTT_ACL_RULES {
int id PK
string device_id FK
string topic_pattern
string permission
datetime created_at
}
MQTT_SYNC_STATUS {
int id PK
int pending_changes
datetime last_sync_at
string last_sync_status
datetime created_at
datetime updated_at
}
LOCATION {
int id PK
float latitude
float longitude
datetime timestamp
string username FK
int user_id
string display_time
int battery
float speed
int chat_id
}
```
### Auto-Refresh Mechanismus
Die App verwendet einen **Echtzeit-Ansatz**:
1. **MQTT Subscriber** empfängt OwnTracks Messages direkt vom Broker
2. **Locations** werden sofort in SQLite gespeichert
3. **Frontend polling** (alle 5 Sek.) `/api/locations`
4. **API liest** gefilterte Daten aus lokalem SQLite Cache
5. **Duplikate** werden durch UNIQUE Index verhindert
**Vorteile:**
- Echtzeitdaten ohne Verzögerung
- Schnelle Antwortzeiten (direkter SQLite Zugriff)
- Längere Zeiträume abrufbar (24h+)
- Keine externen Dependencies (kein n8n nötig)
- Duplikate werden automatisch verhindert (UNIQUE Index)
### Datenvalidierung & Normalisierung
Die App behandelt spezielle Fälle bei speed/battery korrekt:
**speed = 0 Behandlung:**
- MQTT sendet `speed: 0` (gültig - Gerät steht still)
- Wird mit `typeof === 'number'` Check explizit als `0` gespeichert
- Wird NICHT zu `null` konvertiert (wichtig für Telemetrie)
- Popup zeigt "Speed: 0.0 km/h" an
**Debug-Logging:**
- Server-Logs zeigen MQTT Message-Verarbeitung
- Browser Console zeigt Daten-Flow (MapView, Popup)
- Hilfreich für Troubleshooting
---
## 📡 API-Endpunkte
### Öffentlich
**GET /api/locations**
- Location-Daten abrufen (aus SQLite Cache)
- Query-Parameter:
- `username` - Device-Filter (z.B. "10", "11")
- **Zeitfilter (wähle eine Methode):**
- `timeRangeHours` - Quick Filter (1, 3, 6, 12, 24)
- `startTime` & `endTime` - Custom Range (ISO 8601 Format)
- `limit` - Max. Anzahl (Standard: 1000)
**Beispiele:**
```bash
# Quick Filter: Letzte 3 Stunden
GET /api/locations?timeRangeHours=3
# Custom Range: Spezifischer Zeitraum
GET /api/locations?startTime=2025-11-16T16:00:00.000Z&endTime=2025-11-17T06:00:00.000Z
# Kombiniert: Device + Custom Range
GET /api/locations?username=10&startTime=2025-11-16T16:00:00.000Z&endTime=2025-11-17T06:00:00.000Z
```
**GET /api/devices/public**
- Öffentliche Device-Liste (nur ID, Name, Color)
### Geschützt (Login erforderlich)
**GET /api/devices**
- Alle Geräte mit Latest Location und Telemetrie
**POST /api/devices**
- Neues Gerät erstellen
- Body: `{ id, name, color, description? }`
**PATCH /api/devices/:id**
- Gerät aktualisieren
- Body: `{ name?, color?, description? }`
**DELETE /api/devices/:id**
- Gerät löschen (soft delete)
**POST /api/locations/cleanup**
- Alte Locations löschen
- Body: `{ retentionHours }`
**POST /api/locations/optimize**
- VACUUM + ANALYZE ausführen
- Gibt freigegebenen Speicher zurück
**GET /api/locations/stats**
- Detaillierte DB-Statistiken
- Größe, Zeitraum, Locations pro Device
**GET /api/system/status**
- System-Status abrufen
- Returns: Uptime, Memory Usage, Node.js Version, Platform
- Auto-Refresh: Alle 10 Sekunden im Admin-Panel
---
## 📱 Device Management
### Device-Karte zeigt:
- 🟢/⚫ **Online/Offline Status**
- Online = letzte Location < 10 Minuten
- Offline = letzte Location > 10 Minuten
- 🕒 **Last Seen** - Zeitstempel letzter Location
- 🔋 **Batterie** - Prozent (Rot bei < 20%)
- 🚗 **Geschwindigkeit** - km/h (umgerechnet von m/s)
- 📍 **Koordinaten** - Lat/Lon mit 5 Dezimalen
### Auto-Refresh
- Devices-Seite aktualisiert sich alle 10 Sekunden
- Online/Offline Status wird automatisch aktualisiert
---
## 🧹 Wartung
### Datenbank aufräumen
**Via Admin-Panel:**
- `/admin` Database Maintenance Cleanup Buttons
**Via CLI:**
```bash
npm run db:cleanup # 7 Tage
npm run db:cleanup:30d # 30 Tage
```
### Datenbank optimieren
**Via Admin-Panel:**
- `/admin` Database Maintenance Optimize Button
**Via CLI:**
```bash
# Manuell
node scripts/optimize-db.js
```
**Was macht Optimize:**
- `VACUUM` - Speicherplatz freigeben
- `ANALYZE` - Query-Statistiken aktualisieren
### Logs prüfen
```bash
# Development Server Logs
npm run dev
# Production Logs (PM2)
pm2 logs location-tracker-app
```
### Zeitfilter debuggen
Bei Problemen mit der Zeitfilterung (z.B. alte Locations werden nicht ausgefiltert):
```bash
node scripts/test-time-filter.js
```
**Das Script zeigt:**
- Aktuelle Zeit (UTC und lokal)
- Letzte Locations in der Datenbank
- Welche Locations mit 1-Stunden-Filter angezeigt werden sollten
- Vergleich zwischen alter (SQLite datetime) und neuer (JavaScript) Methode
- Anzahl der gefilterten Locations
**Verwendung:**
1. Script ausführen um zu sehen, welche Locations in der DB sind
2. Überprüfen ob die Zeitfilterung korrekt funktioniert
3. Bei Problemen: App neu starten nach Code-Updates
---
## 🚀 Deployment
### Environment Variables
Erstelle `.env.local`:
```env
# NextAuth
AUTH_SECRET=<generiere-mit-openssl-rand-base64-32>
NEXTAUTH_URL=https://your-domain.com
```
**Secret generieren:**
```bash
openssl rand -base64 32
```
### Production Build
```bash
# Build
npm run build
# Start
npm run start
```
### Mit PM2 (empfohlen)
```bash
# PM2 installieren
npm install -g pm2
# App starten
pm2 start npm --name "location-tracker-app" -- start
# Auto-Start bei Server-Neustart
pm2 startup
pm2 save
```
### Nginx Reverse Proxy
```nginx
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
```
---
## 🔒 Sicherheit
### Production Checklist
- [ ] `AUTH_SECRET` mit starkem Wert setzen
- [ ] `NEXTAUTH_URL` auf Production-Domain setzen
- [ ] Admin-Passwort ändern (nicht `admin123`)
- [ ] Ggf. weitere User anlegen mit VIEWER Rolle
- [ ] HTTPS aktivieren (Let's Encrypt)
- [ ] Firewall-Regeln prüfen
- [ ] Regelmäßige Backups einrichten
### User-Rollen
- **ADMIN** - Voller Zugriff auf alle Admin-Funktionen
- **VIEWER** - Nur lesender Zugriff (geplant, noch nicht implementiert)
---
## 📂 Projektstruktur
```
location-tracker-app/
├── app/
│ ├── api/
│ │ ├── auth/[...nextauth]/ # NextAuth API
│ │ ├── devices/ # Device CRUD
│ │ ├── locations/ # Location API + Sync/Cleanup/Stats
│ │ └── system/status/ # System Status (Uptime, Memory)
│ ├── admin/
│ │ ├── devices/ # Device Management
│ │ └── page.tsx # Dashboard
│ ├── login/ # Login-Seite
│ ├── page.tsx # Öffentliche Karte
│ └── layout.tsx # Root Layout
├── components/
│ └── map/
│ └── MapView.tsx # Leaflet Map Component
├── lib/
│ ├── auth.ts # NextAuth Config
│ └── db.ts # SQLite Database Layer
├── scripts/
│ ├── init-database.js # Database.sqlite Setup
│ ├── init-locations-db.js # Locations.sqlite Setup
│ ├── reset-admin.js # Admin User Reset
│ ├── remove-duplicates.js # Duplikate bereinigen
│ └── cleanup-old-locations.js # Alte Daten löschen
├── data/
│ ├── database.sqlite # User + Devices
│ └── locations.sqlite # Location Tracking
├── types/
│ └── location.ts # TypeScript Interfaces
└── middleware.ts # Route Protection
```
---
## 📝 Changelog
### Version 1.1.0 - November 2025
#### 🆕 Neue Features
- **Custom Date Range Filter**
- Benutzerdefinierte Zeiträume mit DateTime-Picker (z.B. 16.11.2025 16:00 - 17.11.2025 06:00)
- Toggle-Button zwischen Quick Filters und Custom Range
- Kompakte UI - Custom Range nur sichtbar wenn aktiviert
- Backend-Support mit `startTime` und `endTime` API-Parametern
#### 🐛 Bug Fixes
- **Zeitfilter-Bug behoben**
- Alte Locations (z.B. 6+ Stunden alt) werden jetzt korrekt ausgefiltert
- JavaScript-basierte Zeitberechnung statt SQLite `datetime('now')`
- Verhindert Zeitversatz-Probleme
#### 🛠️ Verbesserungen
- Zoom-basierte Icon-Skalierung für bessere Sichtbarkeit
- Optimierte Zeitfilter-Logik in Datenbank-Queries
- Debug-Script `test-time-filter.js` für Troubleshooting
#### 📚 Dokumentation
- README aktualisiert mit Custom Range Anleitung
- API-Endpunkte Dokumentation erweitert
- Wartungs-Abschnitt mit Debug-Script Information
---
## 🐛 Troubleshooting
### "Invalid username or password"
**Lösung:**
```bash
node scripts/reset-admin.js
```
### Datenbank-Dateien fehlen
**Lösung:**
```bash
npm run db:init
```
### Duplikate in locations.sqlite
**Lösung:**
```bash
# Erst Duplikate entfernen
node scripts/remove-duplicates.js
# Dann UNIQUE Index hinzufügen
node scripts/init-locations-db.js
```
### Map zeigt keine Daten
1. MQTT Broker erreichbar? `mosquitto_sub -h localhost -p 1883 -t '#'`
2. Locations in Datenbank? `/admin` Database Statistics prüfen
3. MQTT Subscriber läuft? Server-Logs prüfen
### "ENOENT: no such file or directory, open 'data/database.sqlite'"
**Lösung:**
```bash
mkdir -p data
npm run db:init
```
---
## 📝 NPM Scripts
```bash
# Development
npm run dev # Dev Server starten
# Production
npm run build # Production Build
npm run start # Production Server
# Database
npm run db:init # Beide DBs initialisieren
npm run db:init:app # Nur database.sqlite
npm run db:init:locations # Nur locations.sqlite
npm run db:cleanup # Cleanup 7 Tage
npm run db:cleanup:7d # Cleanup 7 Tage
npm run db:cleanup:30d # Cleanup 30 Tage
# Linting
npm run lint # ESLint ausführen
```
---
## 📄 Lizenz
MIT License - Open Source
---
## 📜 Open Source Lizenzen
Diese Anwendung verwendet folgende Open-Source-Software:
### MIT License
- [Next.js](https://github.com/vercel/next.js) - Copyright (c) Vercel, Inc.
- [React](https://github.com/facebook/react) - Copyright (c) Meta Platforms, Inc.
- [React-DOM](https://github.com/facebook/react) - Copyright (c) Meta Platforms, Inc.
- [Tailwind CSS](https://github.com/tailwindlabs/tailwindcss) - Copyright (c) Tailwind Labs, Inc.
- [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) - Copyright (c) Joshua Wise
- [bcryptjs](https://github.com/dcodeIO/bcrypt.js) - Copyright (c) Daniel Wirtz
### Apache License 2.0
- [TypeScript](https://github.com/microsoft/TypeScript) - Copyright (c) Microsoft Corporation
### ISC License
- [NextAuth.js](https://github.com/nextauthjs/next-auth) - Copyright (c) NextAuth.js Contributors
### BSD-2-Clause License
- [Leaflet](https://github.com/Leaflet/Leaflet) - Copyright (c) Vladimir Agafonkin
### Hippocratic License 2.1
- [React-Leaflet](https://github.com/PaulLeCam/react-leaflet) - Copyright (c) Paul Le Cam
**Vollständige Lizenztexte:**
Alle vollständigen Lizenztexte der verwendeten Bibliotheken finden Sie in den jeweiligen GitHub-Repositories oder in der `node_modules` Directory nach Installation.
---
## 🙏 Credits
- **Next.js 14** - React Framework
- **Leaflet.js** - Karten-Bibliothek
- **NextAuth.js** - Authentifizierung
- **better-sqlite3** - SQLite für Node.js
- **Tailwind CSS** - Utility-First CSS
- **MQTT.js** - MQTT Client für Node.js
- **OwnTracks** - Location Tracking Apps
---
## 📞 Support
Bei Fragen oder Problemen:
1. Logs prüfen (`npm run dev` Output)
2. Browser Console öffnen (F12)
3. Datenbank-Status in `/admin` prüfen
4. Issues im Repository erstellen