Files
rfcp/RFCP-Iteration-1.5.1-Fixes-Boundaries.md
2026-01-31 02:07:57 +02:00

5.6 KiB

RFCP Iteration 1.5.1: Fixes & Boundaries

Date: January 31, 2025
Type: Bugfix & Polish
Estimated: 2-3 hours
Location: /opt/rfcp/frontend/ + /opt/rfcp/backend/


🎯 Goal

Fix Fresnel endpoint 500 error, restore coverage boundary visualization, minor polish.


🐛 Issues to Fix

1. Fresnel Endpoint 500 Error

Symptom:

curl "/api/terrain/fresnel?tx_lat=48.46&tx_lon=35.05&tx_height=30&rx_lat=48.47&rx_lon=35.06&rx_height=1.5&frequency=1800"
# Returns: 500 Internal Server Error

Location: backend/app/api/routes/terrain.py

Likely cause: Missing rx_height default or async issue in los_service.check_fresnel_clearance()

Fix:

@router.get("/fresnel")
async def check_fresnel(
    tx_lat: float,
    tx_lon: float,
    tx_height: float,
    rx_lat: float,
    rx_lon: float,
    rx_height: float = 1.5,  # Default receiver height
    frequency: float = 1800   # Default frequency MHz
):
    try:
        result = await los_service.check_fresnel_clearance(
            tx_lat, tx_lon, tx_height,
            rx_lat, rx_lon, rx_height,
            frequency
        )
        return result
    except Exception as e:
        raise HTTPException(500, f"Fresnel calculation error: {str(e)}")

Debug: Check backend logs for actual error:

journalctl -u rfcp-backend -n 50 | grep -i error

2. Coverage Boundary Not Showing

Symptom: Boundary contour line (-100 dBm) not visible on map after API integration

Location: frontend/src/components/map/CoverageBoundary.tsx

Likely cause: Component expecting old data format, not new API response

Check:

  1. Is CoverageBoundary still mounted in map?
  2. Does it receive points from coverage store?
  3. Is boundary calculation using correct field (rsrp vs old field name)?

Fix approach:

// CoverageBoundary.tsx
import { useCoverageStore } from '../../store/coverage';

export function CoverageBoundary() {
  const { points, settings } = useCoverageStore();
  
  // Generate boundary from API points
  const boundaryPoints = useMemo(() => {
    if (!points.length) return [];
    
    // Filter points near threshold
    const threshold = settings.min_signal; // -100 dBm
    const tolerance = 5; // ±5 dBm
    
    return points
      .filter(p => Math.abs(p.rsrp - threshold) < tolerance)
      .map(p => [p.lat, p.lon] as [number, number]);
  }, [points, settings.min_signal]);

  // ... rest of boundary rendering
}

Alternative: Use convex hull or marching squares for proper contour:

import { concaveman } from 'concaveman';

const boundaryPolygon = useMemo(() => {
  const edgePoints = points
    .filter(p => p.rsrp >= settings.min_signal && p.rsrp < settings.min_signal + 10)
    .map(p => [p.lon, p.lat]);
  
  if (edgePoints.length < 3) return null;
  
  return concaveman(edgePoints, 2); // concavity factor
}, [points, settings.min_signal]);

3. Minor Polish

a) Stats panel — show models used:

// StatsPanel.tsx
{lastCalculation && (
  <div className="models-used">
    <span className="label">Models:</span>
    <div className="model-tags">
      {lastCalculation.models.map(m => (
        <span key={m} className="model-tag">{m}</span>
      ))}
    </div>
  </div>
)}

b) Loading state during long calculations:

// Show elapsed time during calculation
const [elapsed, setElapsed] = useState(0);

useEffect(() => {
  if (!isCalculating) {
    setElapsed(0);
    return;
  }
  
  const start = Date.now();
  const interval = setInterval(() => {
    setElapsed(Math.floor((Date.now() - start) / 1000));
  }, 1000);
  
  return () => clearInterval(interval);
}, [isCalculating]);

// In render:
{isCalculating && (
  <div className="calculating-status">
    Calculating... {elapsed}s
  </div>
)}

c) Error toast for API failures:

// In coverage store calculateCoverage()
catch (error) {
  const message = error instanceof Error ? error.message : 'Calculation failed';
  toast.error(message); // If using toast library
  set({ error: message, isCalculating: false });
}

Tasks

  • Fix Fresnel endpoint (backend)
  • Debug and check logs for actual error
  • Restore CoverageBoundary with API points
  • Test boundary renders correctly
  • Add elapsed time counter during calculation
  • Add model tags to stats panel
  • Test all presets still work
  • Run integration test — should be 21/21

🧪 Testing

# 1. Test Fresnel fix
curl "https://api.rfcp.eliah.one/api/terrain/fresnel?tx_lat=48.46&tx_lon=35.05&tx_height=30&rx_lat=48.47&rx_lon=35.06&rx_height=1.5&frequency=1800"
# Should return: {"clearance_percent": ..., "has_adequate_clearance": ...}

# 2. Run integration test
./rfcp-integration-test.sh
# Should be 21/21

# 3. Visual test
# - Calculate coverage
# - Verify boundary line appears at -100 dBm edge
# - Verify elapsed time shows during calculation

📁 Files to Modify

backend/app/
├── api/routes/terrain.py          # Fresnel fix
└── services/los_service.py        # Check fresnel method

frontend/src/
├── components/
│   ├── map/CoverageBoundary.tsx   # Fix boundary rendering
│   └── panels/
│       ├── CoverageStats.tsx      # Add model tags
│       └── StatsPanel.tsx         # Elapsed time
└── store/coverage.ts              # Error handling

📝 Notes

  • Boundary can use simple edge detection or proper contour algorithm
  • concaveman is lightweight (~2KB) for concave hull
  • Elapsed time helps user know calculation is progressing

Quick iteration — should be fast 🚀