fix(gnss): address review - reference source wiring, honest method, 429 backoff, QA render proof

- Route the adsb.lol GNSS source through createReferenceSources and the
  constructCatalog contract; app layer module is a thin pass-through.
- Describe the method honestly: gpsjam.org's published cell formula and
  bands; per-aircraft thresholds are the 14 CFR 91.227(c) ADS-B Out minima
  (NIC < 7, NACp < 8) plus readsb gpsOkBefore.
- Proxy: reuse the adsb.lol anchor parser, honour upstream Retry-After
  (clamped 5-120 s), serve stale during cooldown, cap the body size.
- Layer: redraw only when a cell id or band changes, treat a settling
  camera as a retry rather than a rejected enable, keep low cells visible,
  skip rows without finite coordinates, state the 3-aircraft rule in the
  legend blurb.
- Voice: gnss-interference in set_layer_visibility / show_data_layers_menu
  plus common aliases; voice pins re-derived.
- qa-gnss: stub the route in-page (request interception stalls Cesium's
  geometry workers), assert every cell is built, cover all bands over land
  and sea, screenshot every state with the Data Layers row open.

Hex project - Crew Leo Agile dev team.

Co-Authored-By: Claude <[email protected]>
This commit is contained in:
Leo PechnickiandClaude authored and Mazeyar Moeini Feizabadi committed 2026-10-13 17:20:03 +02:00
1 parent eefcb338b3
commit 21201c78f0
17 files changed
+514 -139

No files matched your search

+29 -1
View File
@@ -32,8 +32,11 @@ test('normalization keeps only airborne self-reported ADS-B v1/v2 positions', ()
aircraft({ hex: '000005', seen_pos: 120 }),
aircraft({ hex: '000006', nic: undefined }),
aircraft({ hex: '000007', lat: 95 }),
aircraft({ hex: '000008', version: undefined }),
aircraft({ hex: 'not-hex' }),
aircraft(),
// A non-ICAO (`~`) address still self-reports over 1090ES ADS-B.
aircraft({ hex: '~a1b2c3' }),
null,
],
});
@@ -47,6 +50,15 @@ test('normalization keeps only airborne self-reported ADS-B v1/v2 positions', ()
gpsLost: false,
degraded: false,
},
{
hex: '~a1b2c3',
lat: 50.1,
lon: 19.9,
nic: 8,
nacp: 10,
gpsLost: false,
degraded: false,
},
]);
assert.equal(normalizeGnssAircraft({}), null);
assert.equal(normalizeGnssAircraft(null), null);
@@ -77,9 +89,11 @@ test('cell keys are stable half-degree bins, clamped at the poles and antimeridi
assert.notEqual(gnssCellKey(50.1, 19.9), gnssCellKey(50.6, 19.9));
assert.equal(gnssCellKey(90, 180), gnssCellKey(89.9, 179.9));
assert.equal(gnssCellKey(-90, -180), '0:0');
// Just south-west of the origin falls in the last cell before 0°, not cell 0.
assert.equal(gnssCellKey(-0.1, -0.1), '179:359');
});
test('interference level follows the published gpsjam formula and bands', () => {
test('interference level follows the gpsjam.org published cell formula and bands', () => {
assert.deepEqual(gnssInterferenceLevel(10, 0), { percent: 0, level: 'low' });
// One degraded aircraft is always discounted.
assert.deepEqual(gnssInterferenceLevel(10, 1), { percent: 0, level: 'low' });
@@ -116,6 +130,20 @@ test('observations count each aircraft once per cell and expire after the window
assert.deepEqual(binGnssCells(store), []);
});
test('rows without finite coordinates never key a cell', () => {
const store = new Map();
accumulateGnssObservations(
store,
[
{ hex: 'n1', lat: Number.NaN, lon: 10.1, degraded: true },
{ hex: 'n2', lat: 10.1, lon: '10.1', degraded: true },
null,
],
0,
);
assert.equal(store.size, 0);
});
test('cells below the minimum aircraft count are withheld', () => {
const store = new Map();
accumulateGnssObservations(