# RTL_433 API Endpoints - Documentation

## Overview

The GigLez API now includes RTL_433 integration endpoints for device identification and protocol information.

**Base URL:** `http://localhost:8000` (development)

**API Version:** 1.0.0

---

## New Endpoints

### 1. GET `/api/rtl433/status`

**Description:** Check RTL_433 decoder availability and status

**Response:**
```json
{
  "available": true,
  "version": "rtl_433 version 23.11 (2023-11-28) inputs file rtl_tcp RTL-SDR SoapySDR",
  "binary_path": "rtl_433",
  "timeout": 10,
  "status": "operational"
}
```

**Status Codes:**
- `200 OK` - Request successful
- `500 Internal Server Error` - Server error

**Example:**
```bash
curl http://localhost:8000/api/rtl433/status
```

---

### 2. GET `/api/rtl433/protocols`

**Description:** Get list of all supported RTL_433 protocols

**Response:**
```json
{
  "total": 244,
  "protocols": [
    {
      "id": 1,
      "name": "Silvercrest Remote Control"
    },
    {
      "id": 2,
      "name": "Rubicson, TFA 30.3197 or InFactory PT-310 Temperature Sensor"
    },
    ...
  ]
}
```

**Status Codes:**
- `200 OK` - Request successful
- `503 Service Unavailable` - RTL_433 not available

**Example:**
```bash
curl http://localhost:8000/api/rtl433/protocols
```

**Filter Protocols (client-side):**
```bash
# Get only weather sensor protocols
curl -s http://localhost:8000/api/rtl433/protocols | \
  jq '.protocols[] | select(.name | contains("Weather") or contains("Temperature"))'
```

---

### 3. GET `/rtl433/protocols/{protocol_id}`

**Description:** Get information about a specific protocol

**Path Parameters:**
- `protocol_id` (integer) - Protocol ID number (1-244)

**Response:**
```json
{
  "id": 12,
  "name": "Oregon Scientific Weather Sensor"
}
```

**Status Codes:**
- `200 OK` - Protocol found
- `404 Not Found` - Protocol ID doesn't exist
- `503 Service Unavailable` - RTL_433 not available

**Example:**
```bash
curl http://localhost:8000/rtl433/protocols/12
```

---

### 4. POST `/api/v1/captures/upload` (Updated)

**Description:** Upload .sub files for processing (now includes RTL_433 decoding)

**Request:**
- `files`: List of .sub files
- `manifest`: JSON metadata

**Updated Response:**
```json
{
  "success": true,
  "message": "Processed 1 files successfully",
  "successful": [
    {
      "id": 1,
      "filename": "capture.sub",
      "frequency": 433920000,
      "protocol": "RAW",
      "device_name": "Acurite Temperature Sensor",
      "match_confidence": 0.95,
      "match_method": "rtl433_decode",

      // NEW: RTL_433 decoded devices
      "rtl433_decoded": [
        {
          "model": "Acurite Tower Sensor",
          "manufacturer": "Acurite",
          "device_id": "12345",
          "protocol_id": 40,
          "confidence": 0.95
        }
      ],

      // NEW: Combined matches (signature + RTL_433)
      "matched_devices": [
        {
          "device_name": "Acurite Tower Sensor",
          "category": "RTL_433 Decoded",
          "confidence": 0.95,
          "method": "rtl433_decode",
          "description": "Acurite Acurite Tower Sensor (Protocol 40)"
        },
        {
          "device_name": "Weather Station",
          "category": "Weather Sensor",
          "confidence": 0.75,
          "method": "frequency_match",
          "description": "Generic 433MHz weather sensor"
        }
      ]
    }
  ],
  "failed": [],
  "total_uploaded": 1,
  "total_successful": 1,
  "total_failed": 0
}
```

**New Fields:**
- `rtl433_decoded[]` - Array of devices decoded by RTL_433
- `matched_devices[]` - Combined matches from all matchers (RTL_433 + signature matching)

---

## Testing the API

### Quick Test Script

```bash
#!/bin/bash

echo "Testing RTL_433 API Endpoints"
echo "=============================="

# Test 1: Status
echo -e "\n1. Testing /api/rtl433/status"
curl -s http://localhost:8000/api/rtl433/status | jq .

# Test 2: Protocol count
echo -e "\n2. Testing /api/rtl433/protocols (count)"
curl -s http://localhost:8000/api/rtl433/protocols | jq '{total: .total}'

# Test 3: First 5 protocols
echo -e "\n3. First 5 protocols:"
curl -s http://localhost:8000/api/rtl433/protocols | jq '.protocols[:5]'

# Test 4: Specific protocol
echo -e "\n4. Protocol 40 (Acurite):"
curl -s http://localhost:8000/rtl433/protocols/40 | jq .

echo -e "\nAll tests complete!"
```

**Save as:** `tests/test_rtl433_api.sh`

**Run:**
```bash
chmod +x tests/test_rtl433_api.sh
./tests/test_rtl433_api.sh
```

---

## Python Client Examples

### Example 1: Check RTL_433 Status

```python
import requests

response = requests.get('http://localhost:8000/api/rtl433/status')
data = response.json()

if data['available']:
    print(f"RTL_433 is operational")
    print(f"Version: {data['version']}")
else:
    print("RTL_433 is not available")
```

### Example 2: Get All Weather Sensor Protocols

```python
import requests

response = requests.get('http://localhost:8000/api/rtl433/protocols')
protocols = response.json()['protocols']

weather_protocols = [
    p for p in protocols
    if 'weather' in p['name'].lower() or
       'temperature' in p['name'].lower() or
       'sensor' in p['name'].lower()
]

print(f"Found {len(weather_protocols)} weather-related protocols:")
for p in weather_protocols[:10]:
    print(f"  [{p['id']:3d}] {p['name']}")
```

### Example 3: Upload File with RTL_433 Decoding

```python
import requests
import json

# Prepare manifest
manifest = {
    "captures": [{
        "latitude": 34.0478,
        "longitude": -118.2348,
        "timestamp": "2026-01-14T12:00:00Z"
    }],
    "data_source": "test"
}

# Upload file
files = {'files': open('capture.sub', 'rb')}
data = {'manifest': json.dumps(manifest)}

response = requests.post(
    'http://localhost:8000/api/v1/captures/upload',
    files=files,
    data=data
)

result = response.json()

if result['success']:
    for capture in result['successful']:
        print(f"File: {capture['filename']}")

        # Check RTL_433 results
        if capture.get('rtl433_decoded'):
            print(f"  RTL_433 Decoded:")
            for device in capture['rtl433_decoded']:
                print(f"    - {device['manufacturer']} {device['model']}")
                print(f"      Protocol: {device['protocol_id']}")
                print(f"      Confidence: {device['confidence']}")
        else:
            print("  No RTL_433 decode")

        # Check signature matches
        if capture.get('matched_devices'):
            print(f"  All Matches ({len(capture['matched_devices'])}):")
            for match in capture['matched_devices'][:3]:
                print(f"    - {match['device_name']} ({match['confidence']})")
```

---

## API Documentation

Interactive API documentation is available at:

- **Swagger UI:** http://localhost:8000/docs
- **ReDoc:** http://localhost:8000/redoc

Both provide:
- Interactive endpoint testing
- Request/response schemas
- Example requests
- Authentication details

---

## Response Format Standards

### Success Response
```json
{
  "success": true,
  "data": { ... },
  "message": "Optional success message"
}
```

### Error Response
```json
{
  "success": false,
  "error": "Error description",
  "detail": "Detailed error message"
}
```

### RTL_433 Unavailable
```json
{
  "available": false,
  "status": "unavailable",
  "error": "RTL_433 binary not found"
}
```

---

## Rate Limiting

Currently no rate limiting is implemented.

**Recommended limits for production:**
- `/api/rtl433/status` - 60 requests/minute
- `/api/rtl433/protocols` - 10 requests/minute
- `/api/v1/captures/upload` - 100 uploads/hour

---

## Common Use Cases

### 1. Check if RTL_433 is Available Before Upload

```javascript
async function uploadWithRTL433() {
  // Check RTL_433 status first
  const status = await fetch('/api/rtl433/status').then(r => r.json());

  if (!status.available) {
    console.warn('RTL_433 not available, falling back to signature matching');
  }

  // Proceed with upload
  const formData = new FormData();
  formData.append('files', file);
  formData.append('manifest', JSON.stringify(manifest));

  const result = await fetch('/api/v1/captures/upload', {
    method: 'POST',
    body: formData
  }).then(r => r.json());

  return result;
}
```

### 2. Display RTL_433 Protocols in UI

```javascript
async function loadProtocols() {
  const data = await fetch('/api/rtl433/protocols').then(r => r.json());

  const select = document.getElementById('protocol-select');
  data.protocols.forEach(protocol => {
    const option = document.createElement('option');
    option.value = protocol.id;
    option.textContent = `[${protocol.id}] ${protocol.name}`;
    select.appendChild(option);
  });
}
```

### 3. Show RTL_433 Results in Capture Details

```javascript
function displayCapture(capture) {
  const container = document.getElementById('capture-details');

  // Show RTL_433 decoded devices
  if (capture.rtl433_decoded && capture.rtl433_decoded.length > 0) {
    const rtlSection = document.createElement('div');
    rtlSection.className = 'rtl433-results';
    rtlSection.innerHTML = `
      <h3>RTL_433 Decoded (High Confidence)</h3>
      ${capture.rtl433_decoded.map(d => `
        <div class="device">
          <strong>${d.manufacturer} ${d.model}</strong>
          <span class="confidence">${(d.confidence * 100).toFixed(0)}%</span>
          <span class="protocol">Protocol ${d.protocol_id}</span>
        </div>
      `).join('')}
    `;
    container.appendChild(rtlSection);
  }

  // Show all matches
  if (capture.matched_devices && capture.matched_devices.length > 0) {
    const matchSection = document.createElement('div');
    matchSection.innerHTML = `
      <h3>All Matches</h3>
      ${capture.matched_devices.map(m => `
        <div class="match">
          <span>${m.device_name}</span>
          <span class="method">${m.method}</span>
          <span class="confidence">${(m.confidence * 100).toFixed(0)}%</span>
        </div>
      `).join('')}
    `;
    container.appendChild(matchSection);
  }
}
```

---

## Troubleshooting

### RTL_433 Status Returns "unavailable"

**Problem:** `/api/rtl433/status` shows `"available": false`

**Solutions:**
1. Install RTL_433:
   ```bash
   sudo apt-get install rtl-433
   ```

2. Verify installation:
   ```bash
   rtl_433 -V
   ```

3. Check PATH:
   ```bash
   which rtl_433
   ```

### Protocols Endpoint Returns Empty

**Problem:** `/api/rtl433/protocols` returns `"total": 0`

**Cause:** RTL_433 binary not accessible

**Solution:** Restart API server after installing RTL_433

### Upload Returns No RTL_433 Decodes

**Problem:** `rtl433_decoded` is always empty

**Possible Causes:**
1. Signal too short/noisy for RTL_433
2. Protocol not supported
3. RAW data missing from .sub file

**Check:**
- Verify .sub file has `RAW_Data` field
- Try with known working captures (weather sensors)
- Check decoder logs for errors

---

## Performance Notes

### RTL_433 Decode Time
- Average: 0.01-0.05 seconds per file
- Timeout: 10 seconds
- Subprocess overhead: ~10-50ms

### Caching (Future)
Phase 7 will add caching to reduce repeated decodes:
- Cache key: SHA256 of RAW_Data
- TTL: 15 minutes
- Expected speedup: 90%+ for duplicates

---

## Security Considerations

### Input Validation
- File size limits: 1MB per .sub file
- File type validation: Must be valid .sub format
- GPS coordinate validation: -90 to 90 lat, -180 to 180 lon

### Subprocess Safety
- RTL_433 runs in isolated subprocess
- 10 second timeout prevents hangs
- Temp files cleaned up automatically
- No user input passed to shell

### Rate Limiting (TODO)
Production deployment should implement:
- Per-IP rate limiting
- API key authentication
- Upload quotas

---

## Changelog

### Version 1.0.0 (2026-01-14)

**Added:**
- `GET /api/rtl433/status` - Check RTL_433 availability
- `GET /api/rtl433/protocols` - List supported protocols
- `GET /rtl433/protocols/{id}` - Get specific protocol info
- RTL_433 decoding in `/api/v1/captures/upload`

**Updated:**
- Upload response now includes `rtl433_decoded[]` array
- Upload response includes combined `matched_devices[]` array
- Best match now prioritizes RTL_433 results

---

## Support

**Documentation:**
- Implementation Plan: `docs/RTL433_INTEGRATION_PLAN.md`
- Status Report: `docs/RTL433_IMPLEMENTATION_STATUS.md`

**Testing:**
- Test Suite: `tests/test_rtl433_integration.py`
- API Tests: `tests/test_rtl433_api.sh`

**Code:**
- Converter: `src/parser/rtl433_converter.py`
- Decoder: `src/matcher/rtl433_decoder.py`
- Strategies: `src/matcher/strategies.py`
- API Routes: `src/api/routes/hardware.py`, `src/api/main_simple.py`
