**Documentation:** - Added docs/geofence-testing.md with comprehensive test guide - Includes all test scripts, manual testing procedures - Troubleshooting section for common issues - Cleanup instructions **Configuration:** - Updated admin user email to joachim.hummel@gmail.com - Restored MQTT_BROKER_URL to mosquitto (Docker setup) - Fixed test-mqtt-geofence.js to use admin credentials **Test Results:** ✅ Database & Logic Test - Working perfectly ✅ Email Notification Test - Email sent successfully ✅ MQTT Integration - Server connects, receives messages ⚠️ Full chain test - Works but duplicate detection prevents retests **What's Working:** - Geofence creation and management via API - Distance calculations (Haversine formula) - Enter/Exit event generation with state tracking - SMTP email delivery with React Email templates - MQTT subscriber integration **Ready for Production:** The geofencing MVP is fully functional and ready for real-world testing with OwnTracks devices sending unique location updates. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
7.0 KiB
7.0 KiB
Geofence Testing Guide
This document describes how to test the geofencing functionality.
Prerequisites
- Database initialized:
npm run db:init - SMTP configured in
.envor admin panel - MQTT broker running (for full integration test)
Test Scripts
1. Database & Logic Test
Tests geofence core functionality without MQTT or emails.
npm run test:geofence
What it does:
- Creates a test geofence in Frankfurt (50.1109, 8.6821)
- Simulates 4 location updates (Outside → Inside → Inside → Outside)
- Generates Enter and Exit events
- Shows event history
Expected output:
✓ Created geofence (ID: ...)
📌 Processing location "Outside (Start)"...
📏 Distance from center: 1158m (OUTSIDE)
ℹ No event (no state change)
📌 Processing location "Inside (Enter)"...
📏 Distance from center: 0m (INSIDE)
🔔 Generated ENTER event (ID: 1)
📌 Processing location "Inside (Stay)"...
📏 Distance from center: 73m (INSIDE)
ℹ No event (no state change)
📌 Processing location "Outside (Exit)"...
📏 Distance from center: 1158m (OUTSIDE)
🔔 Generated EXIT event (ID: 2)
Total events generated: 2
2. Email Notification Test
Tests SMTP connection and email delivery without MQTT.
npm run test:geofence:email
What it does:
- Connects to SMTP server
- Sends a test geofence notification email
- Validates email template rendering
Expected output:
✓ SMTP connection successful!
✓ Email prepared
✅ Email sent successfully!
Message ID: <...>
Check your inbox at: joachim.hummel@gmail.com
Email you should receive:
- Subject: "Device A hat Test Zone betreten"
- Formatted HTML with geofence details
- Time, position, distance from center
3. Full MQTT Integration Test
Tests the complete flow: MQTT → Location → Geofence → Email.
Requirements:
- MQTT broker must be accessible
- Admin credentials in
.env(MQTT_ADMIN_USERNAME, MQTT_ADMIN_PASSWORD)
npm run test:geofence:mqtt
What it does:
- Creates a test geofence
- Connects to MQTT broker
- Publishes 4 OwnTracks location messages
- Triggers geofence events
- Results in email notifications (if dev server is running)
Expected output:
✓ Created test geofence: "MQTT Integration Test Zone"
✓ Connected to MQTT broker
📡 Publishing location: Outside (Start)
✓ Published
📡 Publishing location: Inside (Enter - should trigger EMAIL)
✓ Published
...
✅ Published 4 MQTT location messages
✅ Expected: 2 email notifications (Enter + Exit)
Manual Testing with OwnTracks
Setup
- Create a geofence via API or script
- Configure OwnTracks app with your MQTT credentials
- Move device in/out of geofence zone
Create Geofence Manually
# Get session cookie from browser (login first)
curl -X POST http://localhost:3000/api/geofences \
-H "Content-Type: application/json" \
-H "Cookie: authjs.session-token=YOUR_COOKIE" \
-d '{
"name": "My Test Zone",
"center_latitude": 50.1109,
"center_longitude": 8.6821,
"radius_meters": 500,
"device_id": "12",
"color": "#10b981"
}'
Send Test MQTT Message
# ENTER geofence (inside the zone)
mosquitto_pub -h localhost -p 1883 \
-u admin -P 'YOUR_ADMIN_PASSWORD' \
-t "owntracks/user/12" \
-m '{"_type":"location","tid":"12","lat":50.1109,"lon":8.6821,"tst":'"$(date +%s)"',"batt":85,"vel":0}'
# Wait 5 seconds, then EXIT geofence (outside the zone)
mosquitto_pub -h localhost -p 1883 \
-u admin -P 'YOUR_ADMIN_PASSWORD' \
-t "owntracks/user/12" \
-m '{"_type":"location","tid":"12","lat":50.1200,"lon":8.6900,"tst":'"$(date +%s)"',"batt":84,"vel":5}'
Expected:
- Dev server logs show:
✓ Location saved: 12 at (...) - Geofence events logged:
[Geofence] Detected 1 event(s) for device 12 - Email notification sent to owner
Verify Results
Check Events in Database
sqlite3 data/database.sqlite "
SELECT
id,
event_type,
timestamp,
CAST(distance_from_center AS INTEGER) as distance,
CASE notification_sent
WHEN 0 THEN 'Pending'
WHEN 1 THEN 'Sent'
WHEN 2 THEN 'Failed'
END as notification
FROM GeofenceEvent
ORDER BY id DESC
LIMIT 10
"
Check Geofences
sqlite3 data/database.sqlite "
SELECT
id,
name,
device_id,
radius_meters,
is_active
FROM Geofence
"
View Events via API
curl http://localhost:3000/api/geofences \
-H "Cookie: authjs.session-token=YOUR_COOKIE"
Troubleshooting
No Events Generated
Problem: Location updates don't trigger events.
Possible causes:
- Duplicate location - The unique index prevents duplicate locations
- Solution: Send locations with unique timestamps and coordinates
- Geofence inactive - Check
is_active = 1in database - Wrong device - Geofence is for different device
- MQTT subscriber not running - Start dev server:
npm run dev
Email Not Received
Problem: Events are created but no email arrives.
Check:
- SMTP configuration - Test with
npm run test:geofence:email - User email - Check owner has email in database:
sqlite3 data/database.sqlite "SELECT id, username, email FROM User" - Notification status - Check
notification_sentin GeofenceEvent table - Spam folder - Check your spam/junk folder
MQTT Connection Failed
Problem: MQTT connection error: ECONNREFUSED or Not authorized
Solutions:
- Check broker URL - Verify
MQTT_BROKER_URLin.env - Check credentials - Verify
MQTT_ADMIN_USERNAMEandMQTT_ADMIN_PASSWORD - Broker running - Check:
nc -zv localhost 1883 - Firewall - Ensure port 1883 is open
Cleanup
Delete Test Geofences
# List all geofences
sqlite3 data/database.sqlite "SELECT id, name FROM Geofence"
# Delete specific geofence (CASCADE deletes events and status)
sqlite3 data/database.sqlite "DELETE FROM Geofence WHERE id = 'GEOFENCE_ID'"
# Or via API
curl -X DELETE http://localhost:3000/api/geofences/GEOFENCE_ID \
-H "Cookie: authjs.session-token=YOUR_COOKIE"
Delete Old Events
# Delete events older than 30 days
sqlite3 data/database.sqlite "
DELETE FROM GeofenceEvent
WHERE timestamp < datetime('now', '-30 days')
"
Next Steps
After successful testing:
- Deploy to production - Ensure SMTP and MQTT are configured
- Create frontend UI - Visual geofence editor on map (not yet implemented)
- Configure real devices - Set up OwnTracks on mobile devices
- Monitor notifications - Check GeofenceEvent table regularly
Test Summary
| Test | What it validates | Duration |
|---|---|---|
npm run test:geofence |
Database, logic, calculations | ~1 second |
npm run test:geofence:email |
SMTP, email templates | ~3 seconds |
npm run test:geofence:mqtt |
Full integration chain | ~10 seconds |
| Manual OwnTracks test | Real-world usage | Varies |
All tests are non-destructive and create test data that can be easily cleaned up.