Add Geofence MVP feature implementation

Implemented complete MVP for geofencing functionality with database,
backend logic, MQTT integration, and API endpoints.

**Phase 1: Database & Core Logic**
- scripts/init-geofence-db.js: Database initialization for Geofence tables
- lib/types.ts: TypeScript types for Geofence, GeofenceEvent, GeofenceStatus
- lib/geofence-engine.ts: Core geofencing logic (Haversine distance, state tracking)
- lib/geofence-db.ts: Database layer with CRUD operations
- package.json: Added db:init:geofence script

**Phase 2: MQTT Integration & Email Notifications**
- emails/geofence-enter.tsx: React Email template for enter events
- emails/geofence-exit.tsx: React Email template for exit events
- lib/email-renderer.ts: Added geofence email rendering functions
- lib/geofence-notifications.ts: Notification service for geofence events
- lib/mqtt-subscriber.ts: Integrated automatic geofence checking on location updates

**Phase 3: Minimal API**
- app/api/geofences/route.ts: GET (list) and POST (create) endpoints
- app/api/geofences/[id]/route.ts: DELETE endpoint
- All endpoints with authentication and ownership checks

**MVP Simplifications:**
- No zone limit enforcement (unlimited for all users)
- No notification flags (always send Enter + Exit emails)
- Device assignment required (no NULL device logic)
- Circular geofences only

**Features:**
 Automatic geofence detection on MQTT location updates
 Email notifications for enter/exit events
 State tracking to prevent duplicate events
 REST API for geofence management
 Non-blocking async processing

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-02 18:14:24 +00:00
parent 5369fe3963
commit bd6a7ab187
13 changed files with 1313 additions and 46 deletions

View File

@@ -1,6 +1,9 @@
// MQTT Subscriber Service für OwnTracks Location Updates
import mqtt from 'mqtt';
import { locationDb, Location } from './db';
import { checkGeofences } from './geofence-engine';
import { geofenceDb } from './geofence-db';
import { sendGeofenceNotifications } from './geofence-notifications';
// OwnTracks Message Format
interface OwnTracksMessage {
@@ -139,6 +142,27 @@ class MQTTSubscriber {
if (saved) {
console.log(`✓ Location saved: ${device} at (${payload.lat}, ${payload.lon})`);
// Geofence-Check asynchron ausführen (nicht blockieren)
setImmediate(async () => {
try {
const events = await checkGeofences(saved, device, geofenceDb);
if (events.length > 0) {
console.log(`[Geofence] Detected ${events.length} event(s) for device ${device}`);
// Events in Datenbank speichern
const savedEvents = events.map((eventData) =>
geofenceDb.createEvent(eventData)
);
// Benachrichtigungen versenden (asynchron)
await sendGeofenceNotifications(savedEvents);
}
} catch (error) {
console.error('[Geofence] Check failed:', error);
}
});
} else {
console.log(`⚠ Duplicate location ignored: ${device}`);
}