Add geofence testing documentation and finalize setup
**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>
This commit is contained in:
278
docs/geofence-testing.md
Normal file
278
docs/geofence-testing.md
Normal file
@@ -0,0 +1,278 @@
|
||||
# Geofence Testing Guide
|
||||
|
||||
This document describes how to test the geofencing functionality.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Database initialized: `npm run db:init`
|
||||
- SMTP configured in `.env` or admin panel
|
||||
- MQTT broker running (for full integration test)
|
||||
|
||||
## Test Scripts
|
||||
|
||||
### 1. Database & Logic Test
|
||||
|
||||
Tests geofence core functionality without MQTT or emails.
|
||||
|
||||
```bash
|
||||
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.
|
||||
|
||||
```bash
|
||||
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)
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
1. Create a geofence via API or script
|
||||
2. Configure OwnTracks app with your MQTT credentials
|
||||
3. Move device in/out of geofence zone
|
||||
|
||||
### Create Geofence Manually
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
sqlite3 data/database.sqlite "
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
device_id,
|
||||
radius_meters,
|
||||
is_active
|
||||
FROM Geofence
|
||||
"
|
||||
```
|
||||
|
||||
### View Events via API
|
||||
|
||||
```bash
|
||||
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:**
|
||||
1. **Duplicate location** - The unique index prevents duplicate locations
|
||||
- Solution: Send locations with unique timestamps and coordinates
|
||||
2. **Geofence inactive** - Check `is_active = 1` in database
|
||||
3. **Wrong device** - Geofence is for different device
|
||||
4. **MQTT subscriber not running** - Start dev server: `npm run dev`
|
||||
|
||||
### Email Not Received
|
||||
|
||||
**Problem:** Events are created but no email arrives.
|
||||
|
||||
**Check:**
|
||||
1. **SMTP configuration** - Test with `npm run test:geofence:email`
|
||||
2. **User email** - Check owner has email in database:
|
||||
```bash
|
||||
sqlite3 data/database.sqlite "SELECT id, username, email FROM User"
|
||||
```
|
||||
3. **Notification status** - Check `notification_sent` in GeofenceEvent table
|
||||
4. **Spam folder** - Check your spam/junk folder
|
||||
|
||||
### MQTT Connection Failed
|
||||
|
||||
**Problem:** `MQTT connection error: ECONNREFUSED` or `Not authorized`
|
||||
|
||||
**Solutions:**
|
||||
1. **Check broker URL** - Verify `MQTT_BROKER_URL` in `.env`
|
||||
2. **Check credentials** - Verify `MQTT_ADMIN_USERNAME` and `MQTT_ADMIN_PASSWORD`
|
||||
3. **Broker running** - Check: `nc -zv localhost 1883`
|
||||
4. **Firewall** - Ensure port 1883 is open
|
||||
|
||||
## Cleanup
|
||||
|
||||
### Delete Test Geofences
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# Delete events older than 30 days
|
||||
sqlite3 data/database.sqlite "
|
||||
DELETE FROM GeofenceEvent
|
||||
WHERE timestamp < datetime('now', '-30 days')
|
||||
"
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
After successful testing:
|
||||
|
||||
1. **Deploy to production** - Ensure SMTP and MQTT are configured
|
||||
2. **Create frontend UI** - Visual geofence editor on map (not yet implemented)
|
||||
3. **Configure real devices** - Set up OwnTracks on mobile devices
|
||||
4. **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.
|
||||
@@ -22,8 +22,8 @@ console.log('🧪 Complete MQTT Geofence Integration Test\n');
|
||||
// Configuration
|
||||
const CONFIG = {
|
||||
mqttBroker: process.env.MQTT_BROKER_URL || 'mqtt://localhost:1883',
|
||||
mqttUsername: process.env.MQTT_USERNAME,
|
||||
mqttPassword: process.env.MQTT_PASSWORD,
|
||||
mqttUsername: process.env.MQTT_ADMIN_USERNAME || process.env.MQTT_USERNAME,
|
||||
mqttPassword: process.env.MQTT_ADMIN_PASSWORD || process.env.MQTT_PASSWORD,
|
||||
|
||||
deviceId: '10',
|
||||
userId: 'admin-001',
|
||||
|
||||
Reference in New Issue
Block a user