# SubGHz Wigle-Like Wardriving System
**Complete GPS+RF Capture and Export System**

## Overview

This system creates a Wigle-like wardriving platform for sub-GHz RF signals, pairing GPS coordinates with Bruce T-Embed RF captures in a standardized format similar to Wigle WiFi wardriving.

**Architecture:**
```
┌──────────────────────────────────────────────────────────┐
│ GPS Sources (termux-location)                            │
└─────────────────┬────────────────────────────────────────┘
                  │
                  ▼
┌──────────────────────────────────────────────────────────┐
│ Bruce T-Embed RF Captures (.sub files)                   │
│ - Frequency, Protocol, Preset                            │
│ - RAW data, Key data                                     │
└─────────────────┬────────────────────────────────────────┘
                  │
                  ▼
┌──────────────────────────────────────────────────────────┐
│ SubGHz Wardriving Database (~/logs/subghz_wardriving.db) │
│ ├─ wardriving_sessions                                   │
│ ├─ gps_track (GPS breadcrumbs)                           │
│ └─ subghz_signals (RF+GPS pairs)                         │
└─────────────────┬────────────────────────────────────────┘
                  │
                  ▼
┌──────────────────────────────────────────────────────────┐
│ Export Formats                                           │
│ ├─ JSON (detailed)                                       │
│ ├─ CSV (standard wardriving)                             │
│ ├─ Wigle CSV (standardized for sharing)                  │
│ └─ SQLite (database backup)                              │
└──────────────────────────────────────────────────────────┘
```

## Quick Start

### 1. Capture GPS + Associate with RF File

```bash
# Capture current GPS and pair with Bruce .sub file
python3 ~/python/subghz_wardriving/quick_capture.py \
    ~/projects/device-integration/bruce/data/captures/raw10.sub

# With custom session name
python3 ~/python/subghz_wardriving/quick_capture.py \
    raw10.sub downtown_survey
```

**Latest GPS:**
- **Coordinates:** 34.07362505, -118.35955673
- **Accuracy:** 24.5m
- **Timestamp:** 2026-01-13T11:17:51-08:00
- **Provider:** GPS

### 2. Export to Wigle Format

```bash
# Export all data to Wigle CSV
gps wigle-export

# Export specific session
gps wigle-export --session downtown_survey

# Direct export
python3 -c "
from subghz_wardriving.exporter import SubGHzExporter, ExportConfig
exporter = SubGHzExporter()
config = ExportConfig(format='wigle', compress=False)
result = exporter.export_session(config)
print(f'Exported to: {result[\"output_file\"]}')
"
```

**Output Location:** `~/exports/subghz_wardriving/`

## Database Schema

### Table: `subghz_signals`

Stores RF captures paired with GPS coordinates:

| Column | Type | Description |
|--------|------|-------------|
| `id` | INTEGER | Primary key |
| `session_id` | TEXT | Wardriving session ID |
| `capture_id` | TEXT | Unique capture identifier |
| `timestamp` | TEXT | ISO 8601 timestamp |
| `bruce_filename` | TEXT | Original .sub filename |
| `bruce_file_path` | TEXT | Full path to .sub file |
| `file_size_bytes` | INTEGER | File size |
| `frequency_hz` | INTEGER | RF frequency in Hz |
| `protocol` | TEXT | Protocol (RAW, Princeton, etc.) |
| `gps_latitude` | REAL | Latitude (decimal degrees) |
| `gps_longitude` | REAL | Longitude (decimal degrees) |
| `gps_accuracy_meters` | REAL | GPS accuracy |
| `interpolated` | BOOLEAN | GPS interpolated? |
| `interpolation_confidence` | REAL | Confidence score (0-1) |
| `time_gap_seconds` | REAL | Time since last capture |
| `distance_traveled_meters` | REAL | Distance from last capture |
| `estimated_speed_mps` | REAL | Speed in m/s |
| `file_hash_md5` | TEXT | MD5 hash of file |
| `notes` | TEXT | Additional notes |

### Table: `gps_track`

GPS breadcrumb trail:

| Column | Type | Description |
|--------|------|-------------|
| `id` | INTEGER | Primary key |
| `session_id` | TEXT | Session identifier |
| `timestamp` | TEXT | ISO 8601 timestamp |
| `latitude` | REAL | Latitude |
| `longitude` | REAL | Longitude |
| `altitude` | REAL | Altitude (meters) |
| `accuracy` | REAL | Horizontal accuracy (meters) |
| `speed` | REAL | Speed (m/s) |
| `provider` | TEXT | GPS provider (gps/network/passive) |

### Table: `wardriving_sessions`

Session metadata:

| Column | Type | Description |
|--------|------|-------------|
| `session_id` | TEXT | Primary key |
| `start_time` | TEXT | Session start time |
| `end_time` | TEXT | Session end time |
| `total_signals` | INTEGER | Number of signals captured |
| `total_distance_km` | REAL | Total distance traveled |
| `device_info` | TEXT | Device information |
| `notes` | TEXT | Session notes |

## Wigle CSV Format

### Header Format

```csv
WigleWifi-1.4,appRelease=SubGHz-Wardrive-1.0,model=BruceT-Embed,release=Android,device=Phone,display=SubGHzWardrive,board=termux,brand=custom
SignalHash,Frequency(MHz),Protocol,RSSI(dBm),Latitude,Longitude,Altitude,Accuracy,FirstSeen,LastSeen,CaptureCount,Interpolated,Confidence,BruceFile,SessionID
```

### Columns

| Column | Description |
|--------|-------------|
| `SignalHash` | SHA256 hash of frequency+protocol (16 chars) |
| `Frequency(MHz)` | Frequency in MHz (e.g., 433.92) |
| `Protocol` | Protocol name (RAW, Princeton, etc.) |
| `RSSI(dBm)` | Signal strength (not available from .sub files) |
| `Latitude` | Decimal degrees |
| `Longitude` | Decimal degrees |
| `Altitude` | Meters above sea level |
| `Accuracy` | GPS accuracy in meters |
| `FirstSeen` | ISO 8601 timestamp of first capture |
| `LastSeen` | ISO 8601 timestamp of last capture |
| `CaptureCount` | Number of times signal was seen |
| `Interpolated` | true/false - was GPS interpolated? |
| `Confidence` | Interpolation confidence (0-1) |
| `BruceFile` | Original .sub filename |
| `SessionID` | Wardriving session ID |

### Signal Aggregation

Signals are grouped by hash (frequency + protocol), similar to how Wigle groups WiFi by BSSID. Multiple captures of the same signal show:
- First and last seen timestamps
- Total capture count
- Location from first capture

## Usage Examples

### Example 1: Quick Capture

```bash
# Capture GPS now with Bruce file
python3 ~/python/subghz_wardriving/quick_capture.py raw10.sub
```

**Output:**
```
📡 SubGHz GPS Capture
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Bruce File: raw10.sub
Session: quick_20260113_112045

🛰️  Getting GPS location...
✓ GPS Location: 34.073625, -118.359557
  Accuracy: 24.5m

📻 Parsing RF file...
✓ Frequency: 433920000 Hz (433.920 MHz)
  Protocol: RAW
  Preset: FCC_433

💾 Storing to database...
✓ Stored signal: quick_20260113_112045_raw10_1736789645

✅ Capture paired successfully!
   Database: ~/logs/subghz_wardriving.db
```

### Example 2: Export Session

```bash
# Export to Wigle CSV
gps wigle-export --session downtown_survey
```

**Output File:** `~/exports/subghz_wardriving/downtown_survey_20260113_112130_wigle.csv`

**Content:**
```csv
WigleWifi-1.4,appRelease=SubGHz-Wardrive-1.0,model=BruceT-Embed,release=Android,device=Phone,display=SubGHzWardrive,board=termux,brand=custom
SignalHash,Frequency(MHz),Protocol,RSSI(dBm),Latitude,Longitude,Altitude,Accuracy,FirstSeen,LastSeen,CaptureCount,Interpolated,Confidence,BruceFile,SessionID
8a3f2d1c4e5b6a7f,433.920,RAW,,34.073625,-118.359557,,24.5,2026-01-13T19:17:51Z,2026-01-13T19:17:51Z,1,false,1.0,raw10.sub,downtown_survey
```

### Example 3: Wardriving Session

```bash
# Start GPS logging
gps on --session wardrive_session1 --interval 158.4

# Bruce captures RF signals to /BruceRF/*.sub files
# (Manually on Bruce device)

# After session, run batch import
for subfile in ~/projects/device-integration/bruce/data/captures/*.sub; do
    python3 ~/python/subghz_wardriving/quick_capture.py "$subfile" wardrive_session1
done

# Stop GPS logging
gps off

# Export to Wigle format
gps wigle-export --session wardrive_session1
```

## File Locations

| Component | Path |
|-----------|------|
| **Database** | `~/logs/subghz_wardriving.db` |
| **GPS Quick Log** | `~/logs/gps_quick.jsonl` |
| **GPS Correlations** | `~/logs/gps_correlations.db` (legacy) |
| **Exports** | `~/exports/subghz_wardriving/` |
| **Bruce Captures** | `~/projects/device-integration/bruce/data/captures/` |
| **Quick Capture Script** | `~/python/subghz_wardriving/quick_capture.py` |
| **Exporter Module** | `~/python/subghz_wardriving/exporter.py` |
| **Database Module** | `~/python/subghz_wardriving/database.py` |

## Integration with Existing GPS Infrastructure

This system integrates with your existing GPS wardriving infrastructure:

### Existing Systems
1. **`gps` command** - CLI tool for GPS operations
2. **`gps_service.py`** - Background GPS logging (158.4s interval)
3. **`smart_gps_detector.py`** - Auto-detection and file renaming
4. **`realtime_gps_attribution.py`** - Real-time GPS attribution

### New Additions
1. **`quick_capture.py`** - Quick GPS+RF pairing
2. **Wigle export format** - Added to `exporter.py`
3. **`gps wigle-export`** - New command in `gps` script
4. **Standardized database** - Uses existing `subghz_wardriving.db`

## Advanced Features

### GPS Interpolation

When RF captures occur between GPS readings, the system interpolates GPS coordinates based on:
- Time gap between captures
- Distance traveled
- Estimated speed
- Interpolation confidence score

### Session Management

```python
from subghz_wardriving.database import SubGHzWardrivingDB

db = SubGHzWardrivingDB()

# Create session
db.create_session("my_session", device_info="Bruce T-Embed", notes="Downtown survey")

# End session (calculates statistics)
db.end_session("my_session")

# Get summary
summary = db.get_session_summary("my_session")
print(f"Signals: {summary['session']['total_signals']}")
print(f"Distance: {summary['session']['total_distance_km']} km")
```

### Filtering Exports

```python
from subghz_wardriving.exporter import SubGHzExporter, ExportConfig

exporter = SubGHzExporter()

# Export only 433 MHz signals
config = ExportConfig(
    format='wigle',
    frequency_filter=(433_000_000, 434_000_000),  # 433-434 MHz
    confidence_threshold=0.8,  # High confidence only
    protocol_filter='RAW'
)

result = exporter.export_session(config)
```

## Comparison to WiFi Wigle

| Feature | WiFi Wigle | SubGHz Wigle |
|---------|------------|--------------|
| **Signal ID** | BSSID (MAC address) | SignalHash (freq+protocol) |
| **Signal Name** | SSID | Protocol name |
| **Frequency** | WiFi channels (2.4/5 GHz) | SubGHz (300-928 MHz) |
| **Strength** | RSSI (dBm) | Not available from .sub |
| **Device** | WiFi adapter | Bruce T-Embed CC1101 |
| **Format** | CSV | CSV (Wigle-compatible) |
| **Location** | GPS | GPS |
| **Aggregation** | By BSSID | By SignalHash |

## Future Enhancements

1. **RSSI Integration** - If Bruce firmware provides signal strength
2. **Real-time Export** - Live streaming to Wigle format
3. **Map Visualization** - Plot signals on map
4. **Protocol Decoding** - Decode known protocols (garage doors, car keys, etc.)
5. **Community Database** - Share SubGHz signal maps
6. **Cross-device Correlation** - Combine with Pineapple WiFi wardriving

## Troubleshooting

### No GPS Fix

```bash
# Check GPS status
gps status

# Try network provider
termux-location -p network

# Use test coordinates
# Edit gps script to add test coordinate option
```

### Database Locked

```bash
# Check for running processes
ps aux | grep python | grep subghz

# Close database connections
pkill -f subghz_wardriving
```

### Export Fails

```bash
# Check database exists
ls -lh ~/logs/subghz_wardriving.db

# Check export directory
mkdir -p ~/exports/subghz_wardriving

# Test export directly
python3 -m subghz_wardriving.exporter
```

## Resources

- **Bruce Firmware:** https://github.com/pr3y/Bruce
- **Flipper SubGHz Format:** https://docs.flipperzero.one/sub-ghz
- **Wigle.net:** https://wigle.net/
- **CC1101 Datasheet:** https://www.ti.com/product/CC1101

---

**Created:** 2026-01-13
**System Version:** 1.0
**Database:** ~/logs/subghz_wardriving.db
**Latest GPS:** 34.07362505, -118.35955673 (24.5m accuracy)
