Skip to content

Commit 9f3be34

Browse files
authored
Merge pull request #19 from d3mocide/claude/review-rf-simulator-MnX2h
2 parents 6197167 + dd30329 commit 9f3be34

1 file changed

Lines changed: 197 additions & 0 deletions

File tree

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# RF Simulator — Audit & Roadmap
2+
3+
**Audited:** 2026-05-18
4+
**Version at audit:** 1.16.1
5+
6+
---
7+
8+
## Pipeline Overview
9+
10+
The end-to-end flow is functional:
11+
12+
```
13+
Map click → CoverageClickHandler → useRFCoverageTool.runAnalysis()
14+
→ fetch 3×3 elevation tiles (zoom 10 or 12)
15+
→ stitch tiles (tileStitcher)
16+
→ WASM ITM (calculate_rf_coverage)
17+
→ Float32Array of dBm values
18+
→ ScatterplotLayer (DeckGL dots)
19+
```
20+
21+
All RF parameters flow correctly into the calculation: frequency, TX power, antenna gain, cable loss, RX sensitivity, ground type (epsilon/sigma), and climate zone. The transmitter marker is draggable and recalculates on drop. The `recalcTimestamp` mechanism triggers recalculation when sidebar parameters change.
22+
23+
---
24+
25+
## Known Bugs
26+
27+
### BUG-1 — CSS Syntax Error in Loading Spinner (Low)
28+
29+
**File:** `src/components/Map/layers/CoverageLayerManager.jsx:194`
30+
31+
```css
32+
/* Current (broken) */
33+
@keyframes pulse-text { 0%, 100% { opacity: 1; } 50% { opacity: 0.7); } }
34+
^
35+
stray closing paren
36+
```
37+
38+
The `pulse-text` animation is silently invalid. The spinner rotates but the text does not pulse as intended.
39+
40+
**Fix:** Remove the stray `)`.
41+
42+
---
43+
44+
### BUG-2 — WASM Cache-Busted on Every Page Load (Medium)
45+
46+
**File:** `src/hooks/useRFCoverageTool.js:28`
47+
48+
```js
49+
return `/meshrf.wasm?v=${new Date().getTime()}`;
50+
```
51+
52+
A unique timestamp query string is appended on every load, bypassing the browser cache and forcing a fresh 109 KB download each visit. The viewshed and ITM hooks do not do this.
53+
54+
**Fix:** Remove the timestamp or use a build-time hash (e.g., `import.meta.env.VITE_BUILD_HASH`).
55+
56+
---
57+
58+
### BUG-3 — WASM Load Errors Are Silently Dropped (Medium)
59+
60+
**File:** `src/components/Map/MapContainer.jsx:104–109`
61+
62+
```js
63+
const {
64+
runAnalysis: runRFAnalysis,
65+
resultLayer: rfResultLayer,
66+
isCalculating: isRFCalculating,
67+
clear: clearRFCoverage,
68+
// wasmError is returned by the hook but never destructured here
69+
} = useRFCoverageTool(toolMode === "rf_coverage");
70+
```
71+
72+
`useRFCoverageTool` returns `wasmError` and guards against running without a loaded module, but `MapContainer` never reads it. If WASM fails to load, the user clicks the map and nothing happens — no feedback.
73+
74+
**Fix:** Destructure `wasmError` and display it in `CoverageLayerManager` (same pattern as the `isCalculating` spinner).
75+
76+
---
77+
78+
### BUG-4 — `RFCoverageLayer.js` (BitmapLayer) Is Written but Never Used (High)
79+
80+
**File:** `src/components/Map/RFCoverageLayer.js`
81+
82+
A complete custom `BitmapLayer` subclass with a GLSL fragment shader was implemented. It:
83+
- Decodes dBm from a texture (encoding: `byte = (dBm + 150) / 200 * 255`)
84+
- Computes SNR from a noise floor uniform
85+
- Maps SNR to a smooth color gradient (Excellent → Poor)
86+
- Fades signals below sensitivity to faint blue rather than discarding them
87+
- Accepts `rxSensitivity`, `noiseFloor`, `opacity`, and `bounds` as uniforms
88+
89+
**What's used instead:** `MapContainer.jsx:245` instantiates a plain `ScatterplotLayer` — one dot per grid pixel, 2–6 px radius. At large radii or low zoom levels, dots have visible gaps and the rendering looks sparse.
90+
91+
**Fix:** Build a texture from `resultLayer.data`, pass it to `RFCoverageLayer`, and replace the `ScatterplotLayer` block. The shader already handles all color logic; `MapContainer` only needs to handle texture creation.
92+
93+
---
94+
95+
## Missing / Incomplete Features
96+
97+
### FEAT-1 — No RF Simulator Control Panel (High)
98+
99+
The Viewshed tool has a dedicated floating control panel (`ViewshedLayerManager`) with a radius slider, recalculate button, and progress bar. The RF Simulator has none of this. There is no way for the user to:
100+
- Adjust coverage radius (hardcoded to 25 km — see FEAT-2)
101+
- Manually trigger recalculation without changing a sidebar parameter
102+
- See calculation progress beyond a generic spinner
103+
104+
**Reference:** `src/components/Map/layers/ViewshedLayerManager.jsx` for the UX pattern to follow.
105+
106+
---
107+
108+
### FEAT-2 — Coverage Radius Is Hardcoded to 25 km (Medium)
109+
110+
**Files:** `src/components/Map/layers/CoverageLayerManager.jsx:53,117`
111+
112+
```js
113+
runAnalysis(lat, lng, h, 25000, rfParams); // on recalc
114+
runAnalysis(lat, lng, h, 25000, rfParams); // on drag end
115+
```
116+
117+
Users cannot change the radius. For dense urban planning a 5 km radius would be more useful; for hilltop mesh planning 40 km might be needed.
118+
119+
**Fix:** Add a radius slider to the RF control panel (FEAT-1) and thread the value through to `runAnalysis`.
120+
121+
---
122+
123+
### FEAT-3 — No Signal Quality Legend on Map (Low)
124+
125+
The `rf-simulator.md` documentation defines a color table:
126+
127+
| Color | Quality | Threshold |
128+
|-------|---------|-----------|
129+
| Dark Green | Excellent | > 10 dB margin |
130+
| Light Green | Good | 5–10 dB |
131+
| Yellow | Fair | 0–5 dB |
132+
| Orange | Marginal | near sensitivity floor |
133+
| Purple/Fade | Poor | below sensitivity |
134+
135+
Nothing renders this on the map. Users have no in-app reference for what the colors mean.
136+
137+
**Fix:** Small fixed legend overlay, similar to the one used in the Optimization heatmap.
138+
139+
---
140+
141+
### FEAT-4 — No Propagation Model Selection (Medium) — ROADMAP P3-2
142+
143+
The coverage tool is hardwired to WASM ITM regardless of the model selected in the Link Analysis panel. For large areas, ITM is slow; FSPL or Hata would allow fast "preview" quality maps.
144+
145+
**Planned work (P3-2):** Add a model dispatch in `useRFCoverageTool.js` and a selector in the RF control panel (FEAT-1). ITM remains the default.
146+
147+
**Dependency:** P3-1 (client-side Hata/FSPL) must land first so the frontend is not backend-dependent for non-ITM models.
148+
149+
---
150+
151+
### FEAT-5 — Batch Processing Lacks ITM — ROADMAP P3-3
152+
153+
Batch mesh reports use FSPL + Bullington (frontend only). The WASM ITM path used by link analysis and RF coverage is not called for batch node pairs, so batch results are less accurate in terrain.
154+
155+
**Planned work (P3-3):** Fetch elevation profiles for each node pair in `BatchProcessing.jsx` and route through `useWasmITM`.
156+
157+
---
158+
159+
### FEAT-6 — Per-Node Coverage Visualization — ROADMAP P6-1
160+
161+
Multi-site analysis returns a merged composite overlay. Individual node coverage footprints are not visualized, making it impossible to tell which node covers which area.
162+
163+
**Planned work (P6-1):** Backend returns labeled per-node bitmasks; frontend renders distinct color layers or dashed boundary outlines per node.
164+
165+
---
166+
167+
## Recommended Fix Order
168+
169+
### Immediate (bugs, minimal effort)
170+
1. **BUG-1** — Fix CSS syntax error (`0.7)``0.7`)
171+
2. **BUG-2** — Remove WASM timestamp cache-bust
172+
3. **BUG-3** — Destructure and display `wasmError` in `MapContainer`
173+
174+
### High Impact (complete the half-baked work)
175+
4. **BUG-4** — Wire up `RFCoverageLayer.js` BitmapLayer to replace ScatterplotLayer dots
176+
5. **FEAT-1 + FEAT-2** — Add RF control panel with radius slider and recalculate button
177+
6. **FEAT-3** — Add signal quality legend overlay
178+
179+
### Roadmap (larger scope)
180+
7. **FEAT-4** — Propagation model selection (P3-2, depends on P3-1)
181+
8. **FEAT-5** — WASM ITM for batch processing (P3-3)
182+
9. **FEAT-6** — Per-node coverage visualization (P6-1)
183+
184+
---
185+
186+
## Key Files
187+
188+
| Role | Path |
189+
|------|------|
190+
| Main hook | `src/hooks/useRFCoverageTool.js` |
191+
| Click handler | `src/components/Map/Controls/CoverageClickHandler.jsx` |
192+
| Marker + UI manager | `src/components/Map/layers/CoverageLayerManager.jsx` |
193+
| Unused BitmapLayer | `src/components/Map/RFCoverageLayer.js` |
194+
| Rendering (MapContainer) | `src/components/Map/MapContainer.jsx:185–266` |
195+
| WASM C++ core | `libmeshrf/src/meshrf_coverage.cpp` |
196+
| WASM bindings | `libmeshrf/src/bindings.cpp` |
197+
| RF constants | `src/utils/rfConstants.js` |

0 commit comments

Comments
 (0)