# Multi-Frequency RF File Handling - Analysis & Recommendations

**Date:** January 14, 2026
**Status:** Current Limitation Identified
**Priority:** Medium (Future Enhancement)

---

## Current Behavior

### How the System Handles .sub Files Today

**Current Implementation:**
```python
# src/parser/sub_parser.py (line 79)
frequency = int(self.fields.get('Frequency', 0))  # Single frequency only

# src/api/main_simple.py (line 323)
frequency = metadata.frequency  # Extracts single frequency
```

**What Happens:**
1. Parser reads the `Frequency:` field from .sub file
2. Extracts **ONE** frequency value (integer)
3. Creates **ONE** capture record per file
4. Stores that single frequency with GPS coordinates

### Flipper Zero .sub File Format

**Standard Single-Frequency File:**
```
Filetype: Flipper SubGhz Key File
Version: 1
Frequency: 433920000
Preset: FuriHalSubGhzPresetOok270Async
Protocol: Princeton
Bit: 24
Key: 00 00 00 00 00 95 D5 D4
```

**Can .sub Files Contain Multiple Frequencies?**

Based on Flipper Zero's firmware and file format specification:

❌ **NO** - Standard Flipper Zero .sub files contain **ONE frequency per file**

Each .sub file represents a **single capture** at a **single frequency**.

### Multi-Frequency Scenarios

However, there are **edge cases** where multiple frequencies might appear:

#### Scenario 1: Multiple .sub Files in One Upload
✅ **SUPPORTED** - System handles this correctly

```python
# User uploads multiple files at once
files = [
    "capture_315MHz.sub",  # Frequency: 315000000
    "capture_433MHz.sub",  # Frequency: 433920000
    "capture_868MHz.sub"   # Frequency: 868000000
]

# System behavior:
for file in files:
    metadata = sub_parser.parse(file)  # Each file parsed separately
    capture = create_capture(metadata)  # Each creates separate capture
    # Result: 3 separate captures with 3 different frequencies
```

**Result:** ✅ Works correctly - creates 3 separate map markers

#### Scenario 2: Frequency-Hopping Devices (Future)
❌ **NOT SUPPORTED** - Would require new file format

Some devices transmit on multiple frequencies (e.g., Bluetooth frequency hopping, LoRa adaptive data rate):

```
Device transmits: 315 MHz → 433 MHz → 868 MHz
```

**Current behavior:** Flipper Zero would create 3 separate .sub files

**Hypothetical multi-frequency file (NOT STANDARD):**
```
Filetype: Flipper SubGhz Multi File  # DOES NOT EXIST
Version: 1
Frequency: 315000000
Frequency: 433920000  # Multiple Frequency fields
Frequency: 868000000
```

**Our parser behavior:** Only reads **first** Frequency field (line 79)

#### Scenario 3: Scanning/Waterfall Captures
❌ **NOT SUPPORTED** - Different file format

Flipper Zero's spectrum analyzer creates different file types:
- `.sub` files = Single frequency capture
- Waterfall scans = Not saved to .sub format

---

## Current System Limitations

### What Happens If Someone Manually Edits a .sub File?

Let's test what happens if a .sub file has multiple `Frequency:` lines:

**Malformed File:**
```
Filetype: Flipper SubGhz Key File
Version: 1
Frequency: 315000000
Frequency: 433920000  # Second frequency line
Protocol: Princeton
```

**Parser Behavior:**
```python
# src/parser/sub_parser.py (lines 54-61)
for line in content.split('\n'):
    if ':' in line:
        key, value = line.split(':', 1)
        self.fields[key.strip()] = value.strip()  # OVERWRITES previous value!
```

**Result:**
- First `Frequency: 315000000` is stored
- Second `Frequency: 433920000` **OVERWRITES** it
- Only **433920000** is used

❌ **Silent data loss** - First frequency is discarded without warning

### Upload Endpoint Behavior

```python
# src/api/main_simple.py (lines 305-376)
for file in files:
    metadata = sub_parser.parse(temp_path)  # Parses single frequency
    frequency = metadata.frequency          # Gets single frequency

    # Creates ONE capture per file
    capture_info = {
        "id": upload_counter,
        "frequency": frequency,  # Single frequency stored
        # ... other fields
    }
```

**Result:** One file = One frequency = One capture = One map marker

---

## Proposed Solutions

### Option 1: Detect and Reject Multi-Frequency Files (Recommended)

**Pros:**
- Maintains data integrity
- Prevents silent data loss
- Simple to implement

**Implementation:**
```python
def parse(self, file_path: str) -> SignalMetadata:
    # Count frequency fields
    freq_count = content.count('Frequency:')

    if freq_count > 1:
        raise ValueError(
            f"Multi-frequency files not supported. "
            f"Found {freq_count} frequency fields. "
            f"Please split into separate .sub files."
        )

    # Rest of parsing...
```

### Option 2: Parse All Frequencies and Create Multiple Captures (Complex)

**Pros:**
- Handles edge cases gracefully
- Future-proof for multi-frequency devices

**Cons:**
- Significant code changes required
- Not aligned with Flipper Zero standard
- GPS coordinates ambiguous (which freq was captured where?)

**Implementation:**
```python
def parse(self, file_path: str) -> List[SignalMetadata]:
    """Returns LIST of metadata objects"""

    # Parse all frequency fields
    frequencies = []
    for line in content.split('\n'):
        if line.startswith('Frequency:'):
            freq = int(line.split(':', 1)[1].strip())
            frequencies.append(freq)

    if len(frequencies) == 0:
        raise ValueError("No frequency found")

    # Create separate metadata for each frequency
    results = []
    for freq in frequencies:
        metadata = SignalMetadata(frequency=freq, ...)
        results.append(metadata)

    return results

# Upload endpoint changes needed:
for file in files:
    metadatas = sub_parser.parse(temp_path)  # Returns LIST
    for metadata in metadatas:  # Create multiple captures
        capture = create_capture(metadata)
```

**Database changes:**
- `captures_storage` would need to link related captures
- GPS coordinates: same for all captures from one file
- Map display: Multiple markers at same location?

### Option 3: Store Multiple Frequencies in Single Capture (Database Change)

**Pros:**
- Preserves all frequency data
- Single capture per file (simpler logic)

**Cons:**
- Database schema change required
- Map display complexity (show all frequencies?)
- Matching logic needs update

**Implementation:**
```python
# Database schema:
capture_info = {
    "id": 1,
    "filename": "multi_freq.sub",
    "frequencies": [315000000, 433920000, 868000000],  # Array instead of single
    "primary_frequency": 315000000,  # First or dominant frequency
    # ...
}

# Map display:
# Option A: Show primary frequency only
# Option B: Show all frequencies in popup
# Option C: Create multiple semi-transparent markers
```

### Option 4: Do Nothing (Current Behavior)

**Pros:**
- No code changes needed
- Aligns with Flipper Zero standard (one freq per file)

**Cons:**
- Silent data loss if malformed file uploaded
- No user feedback about issue

---

## Recommendations

### Short-Term (Implement Now)

**1. Add Validation Warning**
```python
def parse(self, file_path: str) -> SignalMetadata:
    freq_count = content.count('Frequency:')

    if freq_count > 1:
        logger.warning(
            f"File {file_path} contains {freq_count} frequency fields. "
            f"Only the last one will be used: {self.fields['Frequency']}"
        )
```

**2. Document Behavior**
- Update API docs to clarify: "One frequency per .sub file"
- Add to upload UI: "Multi-frequency files not supported"

**3. Add to Upload Response**
```python
if freq_count > 1:
    warnings.append({
        "filename": file.filename,
        "warning": "Multiple frequencies detected. Only last frequency used.",
        "frequencies_found": freq_count
    })
```

### Medium-Term (Future Enhancement)

**If multi-frequency support becomes needed:**

1. **Update File Format Spec**
   - Define multi-frequency .sub format
   - OR: Use separate file per frequency (Flipper standard)

2. **Update Parser**
   - Return `List[SignalMetadata]` instead of single
   - Parse all frequency fields

3. **Update Upload Endpoint**
   - Handle list of metadata objects
   - Create multiple captures per file
   - Link captures with `parent_file_id`

4. **Update Map Display**
   - Show multiple markers at same GPS location
   - OR: Single marker with frequency list in popup

5. **Update Database Schema**
   ```python
   # New fields:
   "is_multi_frequency": True,
   "parent_capture_id": None,  # For linked captures
   "frequency_index": 0,       # Which frequency in multi-freq file
   ```

---

## Testing

### Test Case 1: Normal Single-Frequency File
```python
# Input: standard_capture.sub
Frequency: 433920000

# Expected:
- Parse succeeds
- frequency = 433920000
- One capture created
```

### Test Case 2: Duplicate Frequency Lines
```python
# Input: duplicate_freq.sub
Frequency: 315000000
Frequency: 315000000  # Same frequency twice

# Current behavior:
- Parse succeeds
- frequency = 315000000 (last value)
- Warning logged

# Recommended:
- Parse succeeds
- Warning returned to user
```

### Test Case 3: Different Frequency Lines
```python
# Input: multi_freq.sub
Frequency: 315000000
Frequency: 433920000  # Different frequency

# Current behavior:
- Parse succeeds
- frequency = 433920000 (last value)
- 315000000 silently discarded

# Recommended:
- Parse fails OR
- Parse succeeds with warning
- User informed of data loss
```

### Test Case 4: Multiple Files Uploaded
```python
# Input: 3 separate .sub files
file1.sub: Frequency: 315000000
file2.sub: Frequency: 433920000
file3.sub: Frequency: 868000000

# Current behavior: ✅ WORKS
- Parse each file separately
- Create 3 captures
- 3 map markers with different frequencies
```

---

## FAQ

**Q: Can a single .sub file contain multiple frequencies?**
A: Not in the standard Flipper Zero format. Each .sub file represents one capture at one frequency.

**Q: What if I scan multiple frequencies?**
A: Flipper Zero creates separate .sub files for each frequency. Upload all files together.

**Q: What happens if I manually add multiple `Frequency:` lines?**
A: Currently, only the **last** frequency is used. Earlier ones are silently discarded.

**Q: Can I upload multiple .sub files with different frequencies?**
A: ✅ Yes! Upload them all at once. Each file creates a separate capture.

**Q: Why not support multi-frequency files?**
A:
1. Not part of Flipper Zero standard
2. GPS coordinates are per-file, not per-frequency
3. Adds significant complexity
4. No known devices that require this

**Q: Will this be supported in the future?**
A: Maybe, if:
1. Users frequently encounter multi-frequency devices
2. A clear use case emerges (frequency-hopping, channel scanning)
3. Standard file format is defined

---

## Impact Assessment

### Current Impact
- **Low** - Flipper Zero doesn't create multi-frequency files
- **Edge case only** - Manually edited/malformed files

### User Impact if Implemented
- **Positive:** Handle more file types
- **Negative:** Increased complexity, potential confusion (multiple markers at same GPS)

### Development Effort
- **Option 1 (Validation):** Low - 1-2 hours
- **Option 2 (Multi-capture):** High - 1-2 days
- **Option 3 (Database change):** Very High - 3-5 days + migration

---

## Conclusion

**Current Status:** System handles **one frequency per .sub file** correctly.

**Recommendation:** Implement **Option 1** (validation warning) in short-term.

**Reasoning:**
1. Aligns with Flipper Zero standard (one freq per file)
2. No known use cases for multi-frequency files
3. Minimal development effort
4. Prevents silent data loss
5. Future-proof: can enhance later if needed

**Action Items:**
- [ ] Add frequency count validation
- [ ] Log warning if multiple frequencies detected
- [ ] Return warning in upload API response
- [ ] Document behavior in API docs
- [ ] Add user-facing note in upload UI

---

**Status:** Analysis complete, awaiting decision on implementation priority.
