Skip to content

Commit 9f2f26c

Browse files
Copilotpatrickrb
andauthored
Fix GridTracker API integration by adding comprehensive CORS support (#150)
* Initial plan * Add CORS support for GridTracker API integration Co-authored-by: patrickrb <6586559+patrickrb@users.noreply.github.com> * Complete CORS implementation for all Cloudlog endpoints + GridTracker setup guide Co-authored-by: patrickrb <6586559+patrickrb@users.noreply.github.com> * Fix ESLint errors preventing Vercel deployment Co-authored-by: patrickrb <6586559+patrickrb@users.noreply.github.com> * Fix missing CORS headers in PUT and DELETE API responses Co-authored-by: patrickrb <6586559+patrickrb@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: patrickrb <6586559+patrickrb@users.noreply.github.com>
1 parent 38036a0 commit 9f2f26c

File tree

7 files changed

+343
-46
lines changed

7 files changed

+343
-46
lines changed

GRIDTRACKER_SETUP.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# GridTracker Integration Guide
2+
3+
GridTracker is now fully supported with Nextlog's Cloudlog-compatible API. This guide explains how to configure GridTracker to automatically log QSOs to your Nextlog instance.
4+
5+
## Prerequisites
6+
7+
1. **Nextlog instance running** with API access
8+
2. **API key created** in Nextlog station settings
9+
3. **GridTracker installed** and configured for your station
10+
11+
## Configuration Steps
12+
13+
### 1. Create API Key in Nextlog
14+
15+
1. Log into your Nextlog instance
16+
2. Go to **Station Settings****API Key Management**
17+
3. Click **"Create New API Key"**
18+
4. Set permissions:
19+
-**Write access** (required for logging QSOs)
20+
-**Station access** (set to your station)
21+
5. Copy the generated API key (format: `nextlog_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`)
22+
23+
### 2. Configure GridTracker
24+
25+
1. **Open GridTracker settings**
26+
2. **Go to Logging section**
27+
3. **Select "Cloudlog" as logging type**
28+
4. **Configure the following:**
29+
30+
| Setting | Value |
31+
|---------|-------|
32+
| **API URL** | `http://your-nextlog-domain/api/cloudlog` |
33+
| **API Key** | Your generated Nextlog API key |
34+
| **Station ID** | Leave blank (auto-detected) |
35+
36+
**Example URL formats:**
37+
- Local: `http://localhost:3000/api/cloudlog`
38+
- Domain: `https://yourlog.example.com/api/cloudlog`
39+
- Vercel: `https://your-nextlog.vercel.app/api/cloudlog`
40+
41+
5. **Test the connection** using GridTracker's test button
42+
6. **Enable automatic logging** if desired
43+
44+
### 3. Verify Configuration
45+
46+
#### Test API Connection
47+
```bash
48+
curl -H "X-API-Key: your_api_key" \
49+
"http://your-nextlog-domain/api/cloudlog"
50+
```
51+
52+
**Expected response:**
53+
```json
54+
{
55+
"success": true,
56+
"api_name": "Nextlog Cloudlog-compatible API",
57+
"cloudlog_compatibility": "v2.7.0"
58+
}
59+
```
60+
61+
#### Test QSO Logging
62+
GridTracker will automatically test QSO logging when you configure it. You can also manually test:
63+
64+
```bash
65+
curl -X POST \
66+
-H "Content-Type: application/json" \
67+
-H "X-API-Key: your_api_key" \
68+
"http://your-nextlog-domain/api/cloudlog/qso" \
69+
-d '{
70+
"callsign": "W1AW",
71+
"band": "20M",
72+
"mode": "FT8",
73+
"qso_date": "2024-01-15",
74+
"time_on": "14:30:00",
75+
"gridsquare": "FN31pr"
76+
}'
77+
```
78+
79+
## Supported Features
80+
81+
GridTracker integration supports:
82+
83+
-**Automatic QSO logging** for FT4/FT8 contacts
84+
-**Real-time uploads** as contacts are made
85+
-**Grid square tracking** and mapping
86+
-**Band/mode information** from GridTracker
87+
-**Station identification** via API key
88+
-**Error handling** with detailed messages
89+
90+
## API Endpoints Used by GridTracker
91+
92+
GridTracker typically uses these Nextlog endpoints:
93+
94+
| Endpoint | Purpose |
95+
|----------|---------|
96+
| `GET /api/cloudlog` | API information and compatibility check |
97+
| `POST /api/cloudlog/qso` | Create new QSO records |
98+
| `GET /api/cloudlog/bands` | Available amateur radio bands |
99+
| `GET /api/cloudlog/modes` | Available transmission modes |
100+
101+
## Troubleshooting
102+
103+
### Common Issues
104+
105+
**1. "Connection failed" error**
106+
- ✅ Check API URL is correct (include `/api/cloudlog`)
107+
- ✅ Verify Nextlog instance is accessible
108+
- ✅ Check firewall settings
109+
110+
**2. "Authentication failed" error**
111+
- ✅ Verify API key is copied correctly
112+
- ✅ Check API key hasn't expired
113+
- ✅ Ensure API key has write permissions
114+
115+
**3. "CORS error" in browser**
116+
- ✅ This is now fixed - update to latest Nextlog version
117+
- ✅ Restart GridTracker after Nextlog update
118+
119+
**4. "QSO not appearing in log"**
120+
- ✅ Check API key station permissions
121+
- ✅ Verify station is set up in Nextlog
122+
- ✅ Check Nextlog dashboard for new contacts
123+
124+
### Enable Debug Logging
125+
126+
In GridTracker:
127+
1. Enable **"Debug logging"** in settings
128+
2. Check log files for detailed error messages
129+
3. Look for HTTP response codes and error details
130+
131+
### API Testing
132+
133+
Test your API configuration manually:
134+
135+
```bash
136+
# Test authentication
137+
curl -H "X-API-Key: YOUR_KEY" http://your-domain/api/cloudlog
138+
139+
# Test QSO creation
140+
curl -X POST \
141+
-H "Content-Type: application/json" \
142+
-H "X-API-Key: YOUR_KEY" \
143+
"http://your-domain/api/cloudlog/qso" \
144+
-d '{"callsign":"TEST","band":"20M","mode":"FT8"}'
145+
```
146+
147+
## Security Notes
148+
149+
- 🔒 **API keys are sensitive** - treat them like passwords
150+
- 🔒 **Use HTTPS** in production for encrypted communication
151+
- 🔒 **Limit API key permissions** to only what GridTracker needs
152+
- 🔒 **Rotate API keys** periodically for security
153+
154+
## Support
155+
156+
If you encounter issues:
157+
158+
1. **Check this guide** for common solutions
159+
2. **Test API manually** with curl commands above
160+
3. **Check Nextlog logs** for server-side errors
161+
4. **Report issues** on the Nextlog GitHub repository
162+
163+
---
164+
165+
**Note**: This integration uses Nextlog's Cloudlog-compatible API, which supports all standard amateur radio logging software that works with Cloudlog.

src/app/api/cloudlog/bands/route.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import { NextRequest, NextResponse } from 'next/server';
55
import { verifyApiKey } from '@/lib/api-auth';
6+
import { addCorsHeaders, createCorsPreflightResponse } from '@/lib/cors';
67

78
// Standard amateur radio bands with frequencies
89
const AMATEUR_BANDS = [
@@ -38,14 +39,20 @@ const AMATEUR_BANDS = [
3839
{ band: '1MM', freq_start: 241000.0, freq_end: 250000.0, wavelength: '1 millimeter' }
3940
];
4041

42+
// OPTIONS /api/cloudlog/bands - Handle CORS preflight requests
43+
export async function OPTIONS() {
44+
return createCorsPreflightResponse();
45+
}
46+
4147
export async function GET(request: NextRequest) {
4248
const authResult = await verifyApiKey(request);
4349

4450
if (!authResult.success) {
45-
return NextResponse.json({
51+
const response = NextResponse.json({
4652
success: false,
4753
error: authResult.error
4854
}, { status: authResult.statusCode || 500 });
55+
return addCorsHeaders(response);
4956
}
5057

5158
const auth = authResult.auth!;
@@ -92,13 +99,14 @@ export async function GET(request: NextRequest) {
9299
response.headers.set('X-RateLimit-Limit', auth.rateLimitPerHour.toString());
93100
response.headers.set('X-RateLimit-Remaining', '999'); // TODO: Get actual remaining
94101

95-
return response;
102+
return addCorsHeaders(response);
96103

97104
} catch (error) {
98105
console.error('Bands retrieval error:', error);
99-
return NextResponse.json({
106+
const response = NextResponse.json({
100107
success: false,
101108
error: 'Internal server error'
102109
}, { status: 500 });
110+
return addCorsHeaders(response);
103111
}
104112
}

src/app/api/cloudlog/modes/route.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import { NextRequest, NextResponse } from 'next/server';
55
import { verifyApiKey } from '@/lib/api-auth';
6+
import { addCorsHeaders, createCorsPreflightResponse } from '@/lib/cors';
67

78
// Standard amateur radio modes organized by category
89
const AMATEUR_MODES = {
@@ -55,14 +56,20 @@ const AMATEUR_MODES = {
5556
]
5657
};
5758

59+
// OPTIONS /api/cloudlog/modes - Handle CORS preflight requests
60+
export async function OPTIONS() {
61+
return createCorsPreflightResponse();
62+
}
63+
5864
export async function GET(request: NextRequest) {
5965
const authResult = await verifyApiKey(request);
6066

6167
if (!authResult.success) {
62-
return NextResponse.json({
68+
const response = NextResponse.json({
6369
success: false,
6470
error: authResult.error
6571
}, { status: authResult.statusCode || 500 });
72+
return addCorsHeaders(response);
6673
}
6774

6875
const auth = authResult.auth!;
@@ -129,13 +136,14 @@ export async function GET(request: NextRequest) {
129136
response.headers.set('X-RateLimit-Limit', auth.rateLimitPerHour.toString());
130137
response.headers.set('X-RateLimit-Remaining', '999'); // TODO: Get actual remaining
131138

132-
return response;
139+
return addCorsHeaders(response);
133140

134141
} catch (error) {
135142
console.error('Modes retrieval error:', error);
136-
return NextResponse.json({
143+
const response = NextResponse.json({
137144
success: false,
138145
error: 'Internal server error'
139146
}, { status: 500 });
147+
return addCorsHeaders(response);
140148
}
141149
}

0 commit comments

Comments
 (0)