Features: - Multi-channel notifications (Email + Telegram) - User-configurable notification settings per channel - Telegram bot integration with rich messages, location pins, and inline buttons - QR code generation for easy bot access (@myidbot support) - Admin UI for notification settings management - Test functionality for Telegram connection - Comprehensive documentation Implementation: - lib/telegram-service.ts: Telegram API integration - lib/notification-settings-db.ts: Database layer for user notification preferences - lib/geofence-notifications.ts: Extended for parallel multi-channel delivery - API routes for settings management and testing - Admin UI with QR code display and step-by-step instructions - Database table: UserNotificationSettings Documentation: - docs/telegram.md: Technical implementation guide - docs/telegram-anleitung.md: User guide with @myidbot instructions - docs/telegram-setup.md: Admin setup guide - README.md: Updated NPM scripts section Docker: - Updated Dockerfile to copy public directory - Added TELEGRAM_BOT_TOKEN environment variable - Integrated notification settings initialization in db:init 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1217 lines
37 KiB
Markdown
1217 lines
37 KiB
Markdown
# 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
|
||
- 🎯 **Geofencing** - Kreisförmige Geofences mit Enter/Exit-Benachrichtigungen:
|
||
- Geofences erstellen, bearbeiten und löschen
|
||
- Radius 50m bis 50km konfigurierbar
|
||
- Visualisierung auf der Karte mit Toggle-Button
|
||
- Event-Historie mit Enter/Exit-Ereignissen
|
||
- E-Mail und MQTT-Benachrichtigungen bei Grenzüberschreitung
|
||
- 💾 **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 16.0.7 (App Router)
|
||
- **Runtime:** React 19.2.1
|
||
- **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)
|
||
- **MQTT:** MQTT.js v5 + Eclipse Mosquitto
|
||
- **E-Mail:** Nodemailer + React Email
|
||
- **Passwort-Hashing:** bcryptjs
|
||
- **Datenquelle:** MQTT Broker + lokale SQLite-Cache
|
||
|
||
### Dual-Database Architektur
|
||
- **database.sqlite** - User, Geräte, MQTT-Credentials, Geofences (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 + MQTT + Geofences)
|
||
- `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
|
||
```
|
||
|
||
**Nur Geofence-Tabellen:**
|
||
```bash
|
||
npm run db:init:geofence
|
||
```
|
||
|
||
### 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'))
|
||
```
|
||
|
||
**Geofence Tabelle:**
|
||
```sql
|
||
id TEXT PRIMARY KEY
|
||
name TEXT NOT NULL
|
||
description TEXT
|
||
shape_type TEXT NOT NULL DEFAULT 'circle' -- Only 'circle' for MVP
|
||
center_latitude REAL NOT NULL
|
||
center_longitude REAL NOT NULL
|
||
radius_meters INTEGER NOT NULL
|
||
owner_id TEXT NOT NULL -- FK zu User.id
|
||
device_id TEXT NOT NULL -- FK zu Device.id
|
||
is_active INTEGER DEFAULT 1 -- 0 oder 1
|
||
color TEXT DEFAULT '#3b82f6'
|
||
created_at TEXT DEFAULT (datetime('now'))
|
||
updated_at TEXT DEFAULT (datetime('now'))
|
||
```
|
||
|
||
**GeofenceEvent Tabelle:**
|
||
```sql
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT
|
||
geofence_id TEXT NOT NULL -- FK zu Geofence.id
|
||
device_id TEXT NOT NULL -- FK zu Device.id
|
||
location_id INTEGER NOT NULL
|
||
event_type TEXT NOT NULL -- 'enter' oder 'exit'
|
||
latitude REAL NOT NULL
|
||
longitude REAL NOT NULL
|
||
distance_from_center REAL
|
||
notification_sent INTEGER DEFAULT 0 -- 0=not sent, 1=sent, 2=failed
|
||
notification_error TEXT
|
||
timestamp TEXT NOT NULL
|
||
created_at TEXT DEFAULT (datetime('now'))
|
||
```
|
||
|
||
**GeofenceStatus Tabelle:**
|
||
```sql
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT
|
||
device_id TEXT NOT NULL -- FK zu Device.id
|
||
geofence_id TEXT NOT NULL -- FK zu Geofence.id
|
||
is_inside INTEGER NOT NULL DEFAULT 0 -- 0 oder 1
|
||
last_enter_time TEXT
|
||
last_exit_time TEXT
|
||
last_checked_at 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)
|
||
- `idx_geofence_owner` ON Geofence(owner_id)
|
||
- `idx_geofence_device` ON Geofence(device_id)
|
||
- `idx_geofence_active` ON Geofence(is_active)
|
||
- `idx_geofence_event_geofence` ON GeofenceEvent(geofence_id)
|
||
- `idx_geofence_event_device` ON GeofenceEvent(device_id)
|
||
- `idx_geofence_event_timestamp` ON GeofenceEvent(timestamp DESC)
|
||
- `idx_geofence_event_notification` ON GeofenceEvent(notification_sent)
|
||
- `idx_geofence_event_composite` ON GeofenceEvent(device_id, geofence_id, timestamp DESC)
|
||
- `idx_geofence_status_device` ON GeofenceStatus(device_id)
|
||
- `idx_geofence_status_geofence` ON GeofenceStatus(geofence_id)
|
||
- `idx_geofence_status_inside` ON GeofenceStatus(is_inside)
|
||
|
||
---
|
||
|
||
#### **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 publishes automatically to `owntracks/<username>/<device_id>`
|
||
- Example: `owntracks/device_12_4397af93/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)]
|
||
C -->|Check Geofences| L[🎯 Geofence Monitor]
|
||
L -->|Store Events| K[(💼 SQLite DB<br/>database.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]
|
||
E -->|Render Geofences| M[🔵 Geofence Circles]
|
||
|
||
H[👤 Admin User] -->|Login| I[🔐 NextAuth.js]
|
||
I -->|Authenticated| J[📊 Admin Panel]
|
||
J -->|CRUD Operations| K
|
||
J -->|Manage Geofences| K
|
||
K -->|Query Events| J
|
||
|
||
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
|
||
style L fill:#9C27B0
|
||
style M fill:#3F51B5
|
||
```
|
||
|
||
### Komponenten-Übersicht
|
||
|
||
```mermaid
|
||
graph LR
|
||
subgraph "External Services"
|
||
A[OwnTracks App]
|
||
B[MQTT Broker]
|
||
end
|
||
|
||
subgraph "Next.js Application"
|
||
C[MQTT Subscriber]
|
||
I[Geofence Monitor]
|
||
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<br/>MQTT, Geofences]
|
||
end
|
||
|
||
A -->|MQTT| B
|
||
B -->|Subscribe| C
|
||
C -->|Write Locations| G
|
||
C -->|Trigger| I
|
||
I -->|Check & Store Events| H
|
||
|
||
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 I fill:#9C27B0,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
|
||
USER ||--o{ GEOFENCE : owns
|
||
DEVICE ||--o{ LOCATION : tracks
|
||
DEVICE ||--o| MQTT_CREDENTIALS : has
|
||
DEVICE ||--o{ MQTT_ACL_RULES : has
|
||
DEVICE ||--o{ GEOFENCE : monitors
|
||
GEOFENCE ||--o{ GEOFENCE_EVENT : triggers
|
||
GEOFENCE ||--o{ GEOFENCE_STATUS : tracks
|
||
DEVICE ||--o{ GEOFENCE_EVENT : generates
|
||
DEVICE ||--o{ GEOFENCE_STATUS : 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
|
||
}
|
||
|
||
GEOFENCE {
|
||
string id PK
|
||
string name
|
||
string description
|
||
string shape_type
|
||
float center_latitude
|
||
float center_longitude
|
||
int radius_meters
|
||
string owner_id FK
|
||
string device_id FK
|
||
boolean is_active
|
||
string color
|
||
datetime created_at
|
||
datetime updated_at
|
||
}
|
||
|
||
GEOFENCE_EVENT {
|
||
int id PK
|
||
string geofence_id FK
|
||
string device_id FK
|
||
int location_id
|
||
string event_type
|
||
float latitude
|
||
float longitude
|
||
float distance_from_center
|
||
int notification_sent
|
||
string notification_error
|
||
datetime timestamp
|
||
datetime created_at
|
||
}
|
||
|
||
GEOFENCE_STATUS {
|
||
int id PK
|
||
string device_id FK
|
||
string geofence_id FK
|
||
boolean is_inside
|
||
datetime last_enter_time
|
||
datetime last_exit_time
|
||
datetime last_checked_at
|
||
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
|
||
- 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/
|
||
│ │ ├── admin/
|
||
│ │ │ ├── emails/
|
||
│ │ │ │ ├── preview/ # Email Template Preview
|
||
│ │ │ │ └── send-test/ # Test Email versenden
|
||
│ │ │ └── settings/
|
||
│ │ │ └── smtp/ # SMTP Einstellungen + Test
|
||
│ │ ├── auth/
|
||
│ │ │ ├── [...nextauth]/ # NextAuth API
|
||
│ │ │ ├── forgot-password/ # Passwort vergessen
|
||
│ │ │ ├── register/ # User Registrierung
|
||
│ │ │ └── reset-password/ # Passwort zurücksetzen
|
||
│ │ ├── devices/
|
||
│ │ │ ├── [id]/ # Device CRUD (einzelnes Device)
|
||
│ │ │ ├── public/ # Öffentliche Device-Liste
|
||
│ │ │ └── route.ts # Device Liste + Create
|
||
│ │ ├── export/
|
||
│ │ │ └── csv/ # CSV Export von Locations
|
||
│ │ ├── geofences/
|
||
│ │ │ ├── [id]/ # Geofence CRUD (einzelner Geofence)
|
||
│ │ │ ├── events/ # Geofence Events abfragen
|
||
│ │ │ └── route.ts # Geofence Liste + Create
|
||
│ │ ├── locations/
|
||
│ │ │ ├── cleanup/ # Alte Locations löschen
|
||
│ │ │ ├── ingest/ # Location Import (MQTT)
|
||
│ │ │ ├── optimize/ # DB Optimization (VACUUM)
|
||
│ │ │ ├── stats/ # DB Statistiken
|
||
│ │ │ ├── test/ # Test-Location hinzufügen
|
||
│ │ │ └── route.ts # Location Query API
|
||
│ │ ├── mqtt/
|
||
│ │ │ ├── acl/
|
||
│ │ │ │ ├── [id]/ # ACL Rule CRUD
|
||
│ │ │ │ └── route.ts # ACL Rules Liste + Create
|
||
│ │ │ ├── credentials/
|
||
│ │ │ │ ├── [device_id]/ # MQTT Credentials CRUD
|
||
│ │ │ │ └── route.ts # Credentials Liste + Create
|
||
│ │ │ ├── send-credentials/ # Credentials per Email versenden
|
||
│ │ │ └── sync/ # Mosquitto Config Sync
|
||
│ │ ├── system/
|
||
│ │ │ └── status/ # System Status (Uptime, Memory)
|
||
│ │ └── users/
|
||
│ │ ├── [id]/ # User CRUD (einzelner User)
|
||
│ │ └── route.ts # User Liste + Create
|
||
│ ├── admin/
|
||
│ │ ├── devices/ # Device Management
|
||
│ │ ├── emails/ # Email Template Management
|
||
│ │ ├── geofences/
|
||
│ │ │ ├── events/ # Geofence Event History
|
||
│ │ │ └── page.tsx # Geofence Management
|
||
│ │ ├── mqtt/ # MQTT Provisioning
|
||
│ │ ├── settings/ # SMTP Settings (Super Admin)
|
||
│ │ ├── setup/ # Setup Guide
|
||
│ │ ├── users/ # User Management
|
||
│ │ ├── layout.tsx # Admin Layout + Navigation
|
||
│ │ └── page.tsx # Dashboard
|
||
│ ├── export/ # CSV Export Seite
|
||
│ ├── forgot-password/ # Passwort vergessen Seite
|
||
│ ├── login/ # Login-Seite
|
||
│ ├── map/ # Karten-Seite (alternative Route)
|
||
│ ├── register/ # Registrierungs-Seite
|
||
│ ├── reset-password/ # Passwort zurücksetzen Seite
|
||
│ ├── unauthorized/ # Unauthorized Access Seite
|
||
│ ├── page.tsx # Öffentliche Karte (Home)
|
||
│ └── layout.tsx # Root Layout
|
||
├── components/
|
||
│ ├── demo/
|
||
│ │ └── DemoMap.tsx # Demo Map Component
|
||
│ ├── map/
|
||
│ │ ├── GeofenceLayer.tsx # Geofence Visualization Layer
|
||
│ │ └── MapView.tsx # Leaflet Map Component
|
||
│ └── AuthProvider.tsx # Auth Context Provider
|
||
├── lib/
|
||
│ ├── auth.ts # NextAuth Config
|
||
│ ├── crypto-utils.ts # Encryption/Decryption Utils
|
||
│ ├── db.ts # SQLite Database Layer (User/Devices)
|
||
│ ├── demo-data.ts # Demo/Test Data Generator
|
||
│ ├── devices.ts # Device Helper Functions
|
||
│ ├── email-renderer.ts # React Email Renderer
|
||
│ ├── email-service.ts # Email Service (Nodemailer)
|
||
│ ├── geofence-db.ts # Geofence Database Layer
|
||
│ ├── geofence-engine.ts # Geofence Detection Engine
|
||
│ ├── geofence-notifications.ts # Geofence Notification Handler
|
||
│ ├── geo-utils.ts # Geolocation Utils (Haversine)
|
||
│ ├── mosquitto-sync.ts # Mosquitto Config File Sync
|
||
│ ├── mqtt-db.ts # MQTT Database Layer
|
||
│ ├── mqtt-subscriber.ts # MQTT Subscriber Service
|
||
│ ├── password-reset-db.ts # Password Reset Token DB
|
||
│ ├── settings-db.ts # Settings Database Layer
|
||
│ ├── startup.ts # Application Startup Logic
|
||
│ ├── types.ts # TypeScript Type Definitions
|
||
│ └── types/
|
||
│ └── smtp.ts # SMTP Type Definitions
|
||
├── scripts/
|
||
│ ├── add-test-location.js # Test-Location hinzufügen
|
||
│ ├── cleanup-old-locations.js # Alte Locations löschen
|
||
│ ├── init-database.js # Database.sqlite Setup
|
||
│ ├── init-geofence-db.js # Geofence Tables Setup
|
||
│ ├── init-locations-db.js # Locations.sqlite Setup
|
||
│ ├── remove-duplicates.js # Duplikate bereinigen
|
||
│ ├── reset-admin.js # Admin User Reset
|
||
│ ├── show-schema.js # DB Schema anzeigen
|
||
│ ├── sync-mqtt-config.ts # MQTT Config manuell syncen
|
||
│ ├── test-geofence.js # Geofence Detektion testen
|
||
│ ├── test-geofence-email.js # Geofence Email testen
|
||
│ ├── test-geofence-notification.js # Geofence Notification testen
|
||
│ ├── test-mqtt-geofence.js # MQTT Geofence Integration testen
|
||
│ ├── test-smtp.js # SMTP Connection testen
|
||
│ └── test-time-filter.js # Zeitfilter debuggen
|
||
├── data/
|
||
│ ├── database.sqlite # User + Devices + MQTT + Geofences
|
||
│ └── locations.sqlite # Location Tracking
|
||
├── emails/ # React Email Templates
|
||
│ └── geofence-alert.tsx # Geofence Alert Email Template
|
||
├── mosquitto/
|
||
│ ├── config/ # Mosquitto Config Files
|
||
│ │ ├── mosquitto.conf # Broker Config
|
||
│ │ ├── password.txt # Password File (bcrypt hashes)
|
||
│ │ └── acl.txt # ACL Rules File
|
||
│ └── logs/ # Mosquitto Log Files
|
||
├── public/ # Static Assets
|
||
├── types/
|
||
│ └── (deprecated - moved to lib/types.ts)
|
||
├── middleware.ts # Route Protection Middleware
|
||
├── instrumentation.ts # Next.js Instrumentation Hook
|
||
├── docker-compose.yml # Docker Compose Setup
|
||
├── Dockerfile # App Docker Image
|
||
└── package.json # Dependencies + Scripts
|
||
```
|
||
|
||
---
|
||
|
||
## 📝 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:init:geofence # Nur Geofence-Tabellen
|
||
npm run db:cleanup # Cleanup 7 Tage
|
||
npm run db:cleanup:7d # Cleanup 7 Tage
|
||
npm run db:cleanup:30d # Cleanup 30 Tage
|
||
|
||
# Testing
|
||
npm run test:location # Test-Location hinzufügen
|
||
npm run test:geofence # Geofence Detektion testen
|
||
npm run test:geofence:email # Geofence Email testen
|
||
npm run test:geofence:mqtt # MQTT Geofence testen
|
||
|
||
# Documentation
|
||
npm run docs:check # Dokumentation validieren
|
||
npm run docs:sync # Dokumentation synchronisieren
|
||
|
||
# Email Development
|
||
npm run email:dev # Email Template Dev Server
|
||
|
||
# Linting
|
||
npm run lint # ESLint ausführen
|
||
```
|
||
---
|
||
|
||
## 📚 Automatische Dokumentations-Synchronisation
|
||
|
||
Diese App verwendet **automatische Checks**, um sicherzustellen, dass die README-Dokumentation immer aktuell bleibt.
|
||
|
||
### 🔍 **Wie es funktioniert**
|
||
|
||
**Pre-Commit Hook (automatisch):**
|
||
- Läuft automatisch vor jedem `git commit`
|
||
- Prüft ob Projektstruktur, API-Routes, oder NPM Scripts aktualisiert werden müssen
|
||
- Warnt dich, wenn Änderungen erkannt werden
|
||
|
||
**Manuell Dokumentation prüfen:**
|
||
```bash
|
||
npm run docs:check
|
||
```
|
||
|
||
**Dokumentation automatisch aktualisieren:**
|
||
```bash
|
||
npm run docs:sync
|
||
```
|
||
|
||
### ⚙️ **Workflow-Beispiel**
|
||
|
||
```bash
|
||
# 1. Du änderst Code oder fügst API-Routes hinzu
|
||
git add .
|
||
git commit -m "Add new feature"
|
||
|
||
# 2. Pre-commit Hook warnt (falls README veraltet ist)
|
||
⚠️ Documentation may be outdated:
|
||
- New API Route: /api/foo/bar
|
||
- New npm script: test:foo
|
||
|
||
# 3. Du hast 3 Optionen:
|
||
|
||
# Option A: Automatisch synchronisieren
|
||
npm run docs:sync
|
||
git add README.md
|
||
git commit -m "Update documentation"
|
||
|
||
# Option B: Manuell README bearbeiten
|
||
# ... edit README.md ...
|
||
git add README.md
|
||
git commit -m "Update documentation"
|
||
|
||
# Option C: Hook überspringen (nicht empfohlen)
|
||
git commit --no-verify
|
||
```
|
||
|
||
### 🎯 **Was wird geprüft?**
|
||
|
||
- ✅ **NPM Scripts** - Alle package.json Scripts dokumentiert?
|
||
- ✅ **API Routes** - Alle app/api/* Routen erwähnt?
|
||
- ✅ **App Struktur** - Alle app/* Verzeichnisse in Projektstruktur?
|
||
- ✅ **Components** - Alle Komponenten dokumentiert?
|
||
- ✅ **Scripts** - Alle scripts/*.js Dateien erwähnt?
|
||
|
||
### 💡 **Tipps**
|
||
|
||
- Der Hook ist **nicht blockierend** - du kannst mit `--no-verify` überspringen
|
||
- `docs:sync` aktualisiert nur NPM Scripts (weitere Bereiche können später hinzugefügt werden)
|
||
- Warnungen sind manchmal "false positives" - das ist okay, besser zu vorsichtig!
|
||
|
||
---
|
||
|
||
## 📄 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
|