gnss-js 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +26 -0
  2. package/dist/analysis.cjs +143 -36
  3. package/dist/analysis.js +3 -3
  4. package/dist/{chunk-HKN3PUGN.js → chunk-5SPJH4MG.js} +35 -26
  5. package/dist/{chunk-WR7LCB52.js → chunk-BJHTBYNG.js} +15 -4
  6. package/dist/{chunk-Y3R57B5P.js → chunk-G3N4S3DM.js} +37 -8
  7. package/dist/{chunk-PRSZIWKM.js → chunk-JDO3LEPC.js} +100 -132
  8. package/dist/{chunk-K7WZQFBV.js → chunk-MIIM4LDY.js} +4 -1
  9. package/dist/{chunk-CB6EOOLA.js → chunk-OZCYOM5D.js} +70 -21
  10. package/dist/{chunk-SDRRAJT5.js → chunk-PGHDJFQK.js} +31 -14
  11. package/dist/{chunk-IS4UUDBV.js → chunk-W4YMQKWH.js} +54 -9
  12. package/dist/{chunk-354IRDOG.js → chunk-W5WKEV7U.js} +39 -9
  13. package/dist/constants.cjs +39 -9
  14. package/dist/constants.js +26 -26
  15. package/dist/coordinates.cjs +4 -1
  16. package/dist/coordinates.js +1 -1
  17. package/dist/{ephemeris-BUWzfmBy.d.cts → ephemeris-Ohl6NAfw.d.cts} +12 -2
  18. package/dist/{ephemeris-BUWzfmBy.d.ts → ephemeris-Ohl6NAfw.d.ts} +12 -2
  19. package/dist/index.cjs +366 -220
  20. package/dist/index.d.cts +2 -2
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +40 -34
  23. package/dist/ntrip.cjs +15 -4
  24. package/dist/ntrip.js +1 -1
  25. package/dist/orbit.cjs +31 -14
  26. package/dist/orbit.d.cts +1 -1
  27. package/dist/orbit.d.ts +1 -1
  28. package/dist/orbit.js +2 -1
  29. package/dist/rinex.cjs +123 -29
  30. package/dist/rinex.js +3 -3
  31. package/dist/rtcm3.cjs +123 -131
  32. package/dist/rtcm3.d.cts +9 -3
  33. package/dist/rtcm3.d.ts +9 -3
  34. package/dist/rtcm3.js +9 -2
  35. package/dist/signals.cjs +55 -26
  36. package/dist/signals.d.cts +26 -26
  37. package/dist/signals.d.ts +26 -26
  38. package/dist/signals.js +2 -1
  39. package/package.json +1 -2
package/README.md CHANGED
@@ -167,6 +167,32 @@ Every exported function has JSDoc with `@param` and `@returns` annotations inclu
167
167
  - **Class-based API** — Ergonomic wrappers like `GnssTime.fromUtc(date).gps` and `Position.fromGeodetic(lat, lon, h).utm` on top of the existing functional core
168
168
  - **RINEX observation writers** (RINEX 2/3/4 with gzip compression)
169
169
 
170
+ ## Development
171
+
172
+ ```bash
173
+ pnpm install
174
+ bash scripts/fetch-test-data.sh # RINEX test fixtures (~5 MB, checksummed; gitignored)
175
+ pnpm test
176
+ pnpm run lint
177
+ pnpm run build
178
+ ```
179
+
180
+ Without the fixtures, the nav-file test suites are skipped silently (`describe.skipIf`), so run the fetch script before trusting a green test run.
181
+
182
+ **Releasing**: bump the version and push the tag — CI publishes to npm via Trusted Publishing (one-time setup: npm package settings → Trusted Publisher → this repo + publish.yml) and creates the GitHub Release:
183
+
184
+ ```bash
185
+ npm version patch # or minor/major; updates package.json + creates the tag
186
+ git push --follow-tags
187
+ ```
188
+
189
+ **Developing against [gnsscalc](https://github.com/MiguelPuntoEs/gnsscalc)** without publishing:
190
+
191
+ ```bash
192
+ cd ../gnsscalc && pnpm link ../gnss-js # then `pnpm run build --watch` here
193
+ # undo with: pnpm unlink gnss-js && pnpm install
194
+ ```
195
+
170
196
  ## License
171
197
 
172
198
  This project is dual-licensed:
package/dist/analysis.cjs CHANGED
@@ -40,9 +40,22 @@ var SYSTEM_NAMES = {
40
40
  var C_LIGHT = 299792458;
41
41
  var FREQ = {
42
42
  G: { "1": 157542e4, "2": 12276e5, "5": 117645e4 },
43
- R: { "3": 1202025e3 },
44
- E: { "1": 157542e4, "5": 117645e4, "6": 127875e4, "7": 120714e4, "8": 1191795e3 },
45
- C: { "1": 157542e4, "2": 1561098e3, "5": 117645e4, "6": 126852e4, "7": 120714e4 },
43
+ // R bands 4/6 are the CDMA L1OC/L2OC center frequencies
44
+ R: { "3": 1202025e3, "4": 1600995e3, "6": 124806e4 },
45
+ E: {
46
+ "1": 157542e4,
47
+ "5": 117645e4,
48
+ "6": 127875e4,
49
+ "7": 120714e4,
50
+ "8": 1191795e3
51
+ },
52
+ C: {
53
+ "1": 157542e4,
54
+ "2": 1561098e3,
55
+ "5": 117645e4,
56
+ "6": 126852e4,
57
+ "7": 120714e4
58
+ },
46
59
  J: { "1": 157542e4, "2": 12276e5, "5": 117645e4, "6": 127875e4 },
47
60
  I: { "5": 117645e4, "9": 2492028e3 },
48
61
  S: { "1": 157542e4, "5": 117645e4 }
@@ -57,11 +70,28 @@ var BAND_LABELS = {
57
70
  S: { "1": "L1", "5": "L5" }
58
71
  };
59
72
  var DUAL_FREQ_PAIRS = {
60
- G: [["1", "2"], ["1", "5"]],
61
- R: [["1", "2"], ["1", "3"]],
62
- E: [["1", "5"], ["1", "7"], ["1", "6"]],
63
- C: [["2", "7"], ["2", "6"], ["1", "5"]],
64
- J: [["1", "2"], ["1", "5"]],
73
+ G: [
74
+ ["1", "2"],
75
+ ["1", "5"]
76
+ ],
77
+ R: [
78
+ ["1", "2"],
79
+ ["1", "3"]
80
+ ],
81
+ E: [
82
+ ["1", "5"],
83
+ ["1", "7"],
84
+ ["1", "6"]
85
+ ],
86
+ C: [
87
+ ["2", "7"],
88
+ ["2", "6"],
89
+ ["1", "5"]
90
+ ],
91
+ J: [
92
+ ["1", "2"],
93
+ ["1", "5"]
94
+ ],
65
95
  I: [["5", "9"]],
66
96
  S: [["1", "5"]]
67
97
  };
@@ -69,7 +99,6 @@ var GLO_F1_BASE = 1602e6;
69
99
  var GLO_F1_STEP = 562500;
70
100
  var GLO_F2_BASE = 1246e6;
71
101
  var GLO_F2_STEP = 437500;
72
- var GLO_F3 = 1202025e3;
73
102
  var GLO_CHANNEL_FALLBACK = {
74
103
  R01: 1,
75
104
  R02: -4,
@@ -105,11 +134,11 @@ function buildGloChannelMap(slots) {
105
134
  return map;
106
135
  }
107
136
  function gloFreq(gloChannels, prn, band) {
137
+ if (band === "3" || band === "4" || band === "6") return FREQ.R[band];
108
138
  const k = gloChannels[prn];
109
139
  if (k === void 0) return void 0;
110
140
  if (band === "1") return GLO_F1_BASE + k * GLO_F1_STEP;
111
141
  if (band === "2") return GLO_F2_BASE + k * GLO_F2_STEP;
112
- if (band === "3") return GLO_F3;
113
142
  return void 0;
114
143
  }
115
144
  function getFreq(gloChannels, prn, band) {
@@ -270,8 +299,18 @@ var MultipathAccumulator = class {
270
299
  time: t,
271
300
  mp: arc.rawMp[i] - mean
272
301
  }));
273
- const rms = Math.sqrt(points.reduce((s, p) => s + p.mp * p.mp, 0) / points.length);
274
- this.results.push({ prn, system: sys, band, refBand, label, points, rms });
302
+ const rms = Math.sqrt(
303
+ points.reduce((s, p) => s + p.mp * p.mp, 0) / points.length
304
+ );
305
+ this.results.push({
306
+ prn,
307
+ system: sys,
308
+ band,
309
+ refBand,
310
+ label,
311
+ points,
312
+ rms
313
+ });
275
314
  }
276
315
  state.arc = { times: [], rawMp: [] };
277
316
  }
@@ -425,10 +464,20 @@ var CycleSlipAccumulator = class {
425
464
  const sigKey = `${sys}:${signal}`;
426
465
  this.countEpoch(sigKey);
427
466
  const stddev = mwSmoothStddev(prevSmooth);
428
- const threshold = Math.max(MW_MIN_THRESHOLD, MW_SIGMA_FACTOR * stddev);
467
+ const threshold = Math.max(
468
+ MW_MIN_THRESHOLD,
469
+ MW_SIGMA_FACTOR * stddev
470
+ );
429
471
  const deviation = Math.abs(mw - prevSmooth.mean);
430
472
  if (deviation > threshold) {
431
- this.recordSlip(sigKey, time, prn, signal, deviation, /* @__PURE__ */ new Set([b1, b2]));
473
+ this.recordSlip(
474
+ sigKey,
475
+ time,
476
+ prn,
477
+ signal,
478
+ deviation,
479
+ /* @__PURE__ */ new Set([b1, b2])
480
+ );
432
481
  mwSmooth.set(pairKey, mwSmoothInit(mw));
433
482
  } else {
434
483
  mwSmooth.set(pairKey, mwSmoothUpdate(prevSmooth, mw));
@@ -483,7 +532,13 @@ var CycleSlipAccumulator = class {
483
532
  }
484
533
  }
485
534
  }
486
- this.prev.set(prn, { time, mwSmooth, gf: gfMap, phase: phaseM, code: codeM });
535
+ this.prev.set(prn, {
536
+ time,
537
+ mwSmooth,
538
+ gf: gfMap,
539
+ phase: phaseM,
540
+ code: codeM
541
+ });
487
542
  };
488
543
  finalize() {
489
544
  const satSlipCounts = {};
@@ -491,7 +546,10 @@ var CycleSlipAccumulator = class {
491
546
  satSlipCounts[ev.prn] = (satSlipCounts[ev.prn] ?? 0) + 1;
492
547
  }
493
548
  const signalStats = [];
494
- const allKeys = /* @__PURE__ */ new Set([...this.signalEpochs.keys(), ...this.signalSlips.keys()]);
549
+ const allKeys = /* @__PURE__ */ new Set([
550
+ ...this.signalEpochs.keys(),
551
+ ...this.signalSlips.keys()
552
+ ]);
495
553
  for (const sigKey of allKeys) {
496
554
  const [sys, ...rest] = sigKey.split(":");
497
555
  const signal = rest.join(":");
@@ -650,10 +708,20 @@ function parseCrxDataLine(line, ntype) {
650
708
  if (token.length >= 3 && token[1] === "&") {
651
709
  const arcOrder = parseInt(token[0]);
652
710
  const value = parseInt(token.substring(2));
653
- fields.push({ empty: false, init: true, arcOrder, value: isNaN(value) ? 0 : value });
711
+ fields.push({
712
+ empty: false,
713
+ init: true,
714
+ arcOrder,
715
+ value: isNaN(value) ? 0 : value
716
+ });
654
717
  } else {
655
718
  const value = parseInt(token);
656
- fields.push({ empty: false, init: false, arcOrder: -1, value: isNaN(value) ? 0 : value });
719
+ fields.push({
720
+ empty: false,
721
+ init: false,
722
+ arcOrder: -1,
723
+ value: isNaN(value) ? 0 : value
724
+ });
657
725
  }
658
726
  }
659
727
  const flagStr = pos < line.length ? line.substring(pos) : "";
@@ -663,7 +731,10 @@ function crxDecompress(prev, field) {
663
731
  if (field.init) {
664
732
  const a = new Array(Math.max(field.arcOrder + 1, 1)).fill(0);
665
733
  a[0] = field.value;
666
- return { state: { accum: a, order: 0, arcOrder: field.arcOrder }, result: field.value };
734
+ return {
735
+ state: { accum: a, order: 0, arcOrder: field.arcOrder },
736
+ result: field.value
737
+ };
667
738
  }
668
739
  if (!prev) {
669
740
  return { state: { accum: [0], order: 0, arcOrder: 0 }, result: 0 };
@@ -676,7 +747,10 @@ function crxDecompress(prev, field) {
676
747
  for (let k = order; k >= 1; k--) {
677
748
  accum[k - 1] += accum[k];
678
749
  }
679
- return { state: { accum, order, arcOrder: prev.arcOrder }, result: accum[0] };
750
+ return {
751
+ state: { accum, order, arcOrder: prev.arcOrder },
752
+ result: accum[0]
753
+ };
680
754
  }
681
755
 
682
756
  // src/rinex/parser.ts
@@ -684,7 +758,9 @@ var CHUNK_SIZE = 2 * 1024 * 1024;
684
758
  var yieldToMain = () => new Promise((r) => setTimeout(r, 0));
685
759
  var noYield = () => Promise.resolve();
686
760
  var SYSTEM_ORDER = ["G", "R", "E", "C", "J", "I", "S"];
687
- var SYSTEM_RANK = Object.fromEntries(SYSTEM_ORDER.map((s, i) => [s, i]));
761
+ var SYSTEM_RANK = Object.fromEntries(
762
+ SYSTEM_ORDER.map((s, i) => [s, i])
763
+ );
688
764
  function systemCmp(a, b) {
689
765
  const ra = SYSTEM_RANK[a.charAt(0)] ?? 99;
690
766
  const rb = SYSTEM_RANK[b.charAt(0)] ?? 99;
@@ -867,7 +943,11 @@ function parseEpochLine3(line) {
867
943
  const wholeSec = Math.floor(sc);
868
944
  const ms = Math.round((sc - wholeSec) * 1e3);
869
945
  const time = Date.UTC(yr, mo - 1, dy, hr, mn, wholeSec, ms);
870
- return { time, flag: isNaN(flag) ? 0 : flag, numSats: isNaN(numSats) ? 0 : numSats };
946
+ return {
947
+ time,
948
+ flag: isNaN(flag) ? 0 : flag,
949
+ numSats: isNaN(numSats) ? 0 : numSats
950
+ };
871
951
  }
872
952
  function parseEpochLine2(line) {
873
953
  const yr2 = parseInt(line.substring(1, 3));
@@ -889,7 +969,12 @@ function parseEpochLine2(line) {
889
969
  const id = satPart.substring(i, i + 3).trim();
890
970
  if (id) satIds.push(id);
891
971
  }
892
- return { time, flag: isNaN(flag) ? 0 : flag, numSats: isNaN(numSats) ? 0 : numSats, satIds };
972
+ return {
973
+ time,
974
+ flag: isNaN(flag) ? 0 : flag,
975
+ numSats: isNaN(numSats) ? 0 : numSats,
976
+ satIds
977
+ };
893
978
  }
894
979
  async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode) {
895
980
  const skipEpochs = !!workerMode;
@@ -942,16 +1027,19 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
942
1027
  if (!skipEpochs) {
943
1028
  const snrBySys = {};
944
1029
  for (const [sys, vals] of Object.entries(snrPerSystemAccum)) {
945
- if (vals.length > 0) snrBySys[sys] = vals.reduce((a, b) => a + b, 0) / vals.length;
1030
+ if (vals.length > 0)
1031
+ snrBySys[sys] = vals.reduce((a, b) => a + b, 0) / vals.length;
946
1032
  }
947
1033
  const meanSnr = snrValues.length > 0 ? snrValues.reduce((a, b) => a + b, 0) / snrValues.length : null;
948
1034
  const snrPerSat = {};
949
1035
  for (const [prn, vals] of Object.entries(snrPerSatAccum)) {
950
- if (vals.length > 0) snrPerSat[prn] = vals.reduce((a, b) => a + b, 0) / vals.length;
1036
+ if (vals.length > 0)
1037
+ snrPerSat[prn] = vals.reduce((a, b) => a + b, 0) / vals.length;
951
1038
  }
952
1039
  const snrPerSatBand = {};
953
1040
  for (const [key, vals] of Object.entries(snrPerSatBandAccum)) {
954
- if (vals.length > 0) snrPerSatBand[key] = vals.reduce((a, b) => a + b, 0) / vals.length;
1041
+ if (vals.length > 0)
1042
+ snrPerSatBand[key] = vals.reduce((a, b) => a + b, 0) / vals.length;
955
1043
  }
956
1044
  epochs.push({
957
1045
  time: epochInfo.time,
@@ -996,7 +1084,8 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
996
1084
  const codes = header.obsTypes[sys] ?? [];
997
1085
  if (onSatObs && epochInfo) {
998
1086
  const values = new Array(codes.length);
999
- for (let i = 0; i < codes.length; i++) values[i] = readObsValue(obsLine, i);
1087
+ for (let i = 0; i < codes.length; i++)
1088
+ values[i] = readObsValue(obsLine, i);
1000
1089
  if (!skipEpochs) {
1001
1090
  for (const { idx, band } of getSnrIndices(sys)) {
1002
1091
  const val = values[idx] ?? null;
@@ -1233,7 +1322,10 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
1233
1322
  v2SnrBandInfo = snrIndicesWithBandV2(header.obsTypes);
1234
1323
  v2SatIndex = 0;
1235
1324
  v2CurrentSatLine = 0;
1236
- const continuationLines = Math.max(0, Math.ceil((info.numSats - 12) / 12));
1325
+ const continuationLines = Math.max(
1326
+ 0,
1327
+ Math.ceil((info.numSats - 12) / 12)
1328
+ );
1237
1329
  if (continuationLines > 0) {
1238
1330
  v2ContinuationSatsRemaining = continuationLines;
1239
1331
  } else {
@@ -1273,7 +1365,9 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
1273
1365
  const magic = new Uint8Array(await file.slice(0, 2).arrayBuffer());
1274
1366
  const isGz = magic[0] === 31 && magic[1] === 139;
1275
1367
  if (magic[0] === 31 && magic[1] === 157) {
1276
- throw new Error("Unix compress (.Z) files are not supported. Please decompress first (e.g. uncompress or gzip -d).");
1368
+ throw new Error(
1369
+ "Unix compress (.Z) files are not supported. Please decompress first (e.g. uncompress or gzip -d)."
1370
+ );
1277
1371
  }
1278
1372
  if (isGz) {
1279
1373
  let bytesRead = 0;
@@ -1289,7 +1383,9 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
1289
1383
  if (done) break;
1290
1384
  bytesRead += value.byteLength;
1291
1385
  processChunkText(decoder.decode(value, { stream: true }), false);
1292
- onProgress?.(Math.min(99, Math.round(bytesRead / (file.size * 4) * 100)));
1386
+ onProgress?.(
1387
+ Math.min(99, Math.round(bytesRead / (file.size * 4) * 100))
1388
+ );
1293
1389
  await yield_();
1294
1390
  }
1295
1391
  processChunkText(decoder.decode(), true);
@@ -1299,7 +1395,10 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
1299
1395
  const end = Math.min(offset + CHUNK_SIZE, file.size);
1300
1396
  const slice = file.slice(offset, end);
1301
1397
  const arrayBuf = await slice.arrayBuffer();
1302
- processChunkText(decoder.decode(arrayBuf, { stream: end < file.size }), false);
1398
+ processChunkText(
1399
+ decoder.decode(arrayBuf, { stream: end < file.size }),
1400
+ false
1401
+ );
1303
1402
  onProgress?.(Math.min(99, Math.round(end / file.size * 100)));
1304
1403
  await yield_();
1305
1404
  }
@@ -1307,19 +1406,27 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
1307
1406
  processChunkText("", true);
1308
1407
  }
1309
1408
  }
1310
- if (epochInfo && satLinesRemaining === 0 && crxPhase === "epoch") finishEpoch();
1311
- if (!header) throw new Error("No valid RINEX header found (missing END OF HEADER).");
1409
+ if (epochInfo && satLinesRemaining === 0 && crxPhase === "epoch")
1410
+ finishEpoch();
1411
+ if (!header)
1412
+ throw new Error("No valid RINEX header found (missing END OF HEADER).");
1312
1413
  onProgress?.(100);
1313
- return { header, epochs, stats: computeStats(header, epochs, satellitesSeen) };
1414
+ return {
1415
+ header,
1416
+ epochs,
1417
+ stats: computeStats(header, epochs, satellitesSeen)
1418
+ };
1314
1419
  }
1315
1420
  function computeStats(header, epochs, satellitesSeen) {
1316
1421
  const n = epochs.length;
1317
1422
  const startTime = n > 0 ? new Date(epochs[0].time) : header.timeOfFirstObs;
1318
1423
  const endTime = n > 0 ? new Date(epochs[n - 1].time) : header.timeOfLastObs;
1319
1424
  let duration = null;
1320
- if (startTime && endTime) duration = (endTime.getTime() - startTime.getTime()) / 1e3;
1425
+ if (startTime && endTime)
1426
+ duration = (endTime.getTime() - startTime.getTime()) / 1e3;
1321
1427
  let interval = header.interval;
1322
- if (interval === null && n >= 2) interval = (epochs[1].time - epochs[0].time) / 1e3;
1428
+ if (interval === null && n >= 2)
1429
+ interval = (epochs[1].time - epochs[0].time) / 1e3;
1323
1430
  const uniqueSatsPerSystem = {};
1324
1431
  let totalUnique = 0;
1325
1432
  const systems = [];
package/dist/analysis.js CHANGED
@@ -3,9 +3,9 @@ import {
3
3
  CycleSlipAccumulator,
4
4
  MultipathAccumulator,
5
5
  analyzeQuality
6
- } from "./chunk-Y3R57B5P.js";
7
- import "./chunk-CB6EOOLA.js";
8
- import "./chunk-354IRDOG.js";
6
+ } from "./chunk-G3N4S3DM.js";
7
+ import "./chunk-OZCYOM5D.js";
8
+ import "./chunk-W5WKEV7U.js";
9
9
  export {
10
10
  CompletenessAccumulator,
11
11
  CycleSlipAccumulator,
@@ -1,30 +1,39 @@
1
+ import {
2
+ FREQ,
3
+ GLO_F1_BASE,
4
+ GLO_F1_STEP,
5
+ GLO_F2_BASE,
6
+ GLO_F2_STEP
7
+ } from "./chunk-W5WKEV7U.js";
8
+
1
9
  // src/signals/definitions.ts
2
- var FREQ_GPS_L1 = 1575.42;
3
- var FREQ_GPS_L2 = 1227.6;
4
- var FREQ_GPS_L5 = 1176.45;
5
- var FREQ_GLO_L1 = 1602;
6
- var FREQ_GLO_L2 = 1246;
7
- var DELTA_GLO_L1 = 0.5625;
8
- var DELTA_GLO_L2 = 0.4375;
9
- var FREQ_GLO_L1OC = 1600.995;
10
- var FREQ_GLO_L2OC = 1248.06;
11
- var FREQ_GLO_L3OC = 1202.025;
12
- var FREQ_GAL_E1 = 1575.42;
13
- var FREQ_GAL_E5 = 1191.795;
14
- var FREQ_GAL_E5a = 1176.45;
15
- var FREQ_GAL_E5b = 1207.14;
16
- var FREQ_GAL_E6 = 1278.75;
17
- var FREQ_BDS_B1I = 1561.098;
18
- var FREQ_BDS_B2I = 1207.14;
19
- var FREQ_BDS_B3I = 1268.52;
20
- var FREQ_BDS_B1A = 1575.42;
21
- var FREQ_BDS_B1C = 1575.42;
22
- var FREQ_BDS_B3A = 1268.52;
23
- var FREQ_QZS_L1 = 1575.42;
24
- var FREQ_QZS_L2 = 1227.6;
25
- var FREQ_QZS_L5 = 1176.45;
26
- var FREQ_QZS_L6 = 1278.75;
27
- var FREQ_NAVIC_L5 = 1176.45;
10
+ var MHz = 1e6;
11
+ var FREQ_GPS_L1 = FREQ.G["1"] / MHz;
12
+ var FREQ_GPS_L2 = FREQ.G["2"] / MHz;
13
+ var FREQ_GPS_L5 = FREQ.G["5"] / MHz;
14
+ var FREQ_GLO_L1 = GLO_F1_BASE / MHz;
15
+ var FREQ_GLO_L2 = GLO_F2_BASE / MHz;
16
+ var DELTA_GLO_L1 = GLO_F1_STEP / MHz;
17
+ var DELTA_GLO_L2 = GLO_F2_STEP / MHz;
18
+ var FREQ_GLO_L1OC = FREQ.R["4"] / MHz;
19
+ var FREQ_GLO_L2OC = FREQ.R["6"] / MHz;
20
+ var FREQ_GLO_L3OC = FREQ.R["3"] / MHz;
21
+ var FREQ_GAL_E1 = FREQ.E["1"] / MHz;
22
+ var FREQ_GAL_E5 = FREQ.E["8"] / MHz;
23
+ var FREQ_GAL_E5a = FREQ.E["5"] / MHz;
24
+ var FREQ_GAL_E5b = FREQ.E["7"] / MHz;
25
+ var FREQ_GAL_E6 = FREQ.E["6"] / MHz;
26
+ var FREQ_BDS_B1I = FREQ.C["2"] / MHz;
27
+ var FREQ_BDS_B2I = FREQ.C["7"] / MHz;
28
+ var FREQ_BDS_B3I = FREQ.C["6"] / MHz;
29
+ var FREQ_BDS_B1A = FREQ.C["1"] / MHz;
30
+ var FREQ_BDS_B1C = FREQ.C["1"] / MHz;
31
+ var FREQ_BDS_B3A = FREQ.C["6"] / MHz;
32
+ var FREQ_QZS_L1 = FREQ.J["1"] / MHz;
33
+ var FREQ_QZS_L2 = FREQ.J["2"] / MHz;
34
+ var FREQ_QZS_L5 = FREQ.J["5"] / MHz;
35
+ var FREQ_QZS_L6 = FREQ.J["6"] / MHz;
36
+ var FREQ_NAVIC_L5 = FREQ.I["5"] / MHz;
28
37
  var GPS_COLOR = "#4ade80";
29
38
  var GPS_M_COLOR = "#ef4444";
30
39
  var GPS_P_COLOR = "#dbc51f";
@@ -98,14 +98,18 @@ async function ntripFetch(proxyUrl, path, headers, signal) {
98
98
  } catch (err) {
99
99
  if (err instanceof Error && err.name === "AbortError") throw err;
100
100
  const message = err instanceof Error ? err.message : "The service may be temporarily unavailable.";
101
- throw new Error(`Could not reach the NTRIP proxy: ${message}`, { cause: err });
101
+ throw new Error(`Could not reach the NTRIP proxy: ${message}`, {
102
+ cause: err
103
+ });
102
104
  }
103
105
  }
104
106
  async function fetchSourcetable(proxyUrl, info, signal) {
105
107
  const headers = ntripHeaders(info);
106
108
  const res = await ntripFetch(proxyUrl, "/", headers, signal);
107
109
  if (res.status === 401) {
108
- throw new Error("Authentication required. Please provide valid credentials.");
110
+ throw new Error(
111
+ "Authentication required. Please provide valid credentials."
112
+ );
109
113
  }
110
114
  if (!res.ok) {
111
115
  throw new Error(`Caster returned ${res.status} ${res.statusText}`);
@@ -117,7 +121,12 @@ async function connectToMountpoint(proxyUrl, info, signal) {
117
121
  const headers = ntripHeaders(info);
118
122
  const controller = new AbortController();
119
123
  const combinedSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
120
- const res = await ntripFetch(proxyUrl, `/${info.mountpoint}`, headers, combinedSignal);
124
+ const res = await ntripFetch(
125
+ proxyUrl,
126
+ `/${info.mountpoint}`,
127
+ headers,
128
+ combinedSignal
129
+ );
121
130
  if (res.status === 401) {
122
131
  throw new Error("Authentication required for this mountpoint.");
123
132
  }
@@ -128,7 +137,9 @@ async function connectToMountpoint(proxyUrl, info, signal) {
128
137
  throw new Error(`Caster returned ${res.status} ${res.statusText}`);
129
138
  }
130
139
  if (!res.body) {
131
- throw new Error("No response body \u2014 streaming not supported by this environment.");
140
+ throw new Error(
141
+ "No response body \u2014 streaming not supported by this environment."
142
+ );
132
143
  }
133
144
  return {
134
145
  reader: res.body.getReader(),
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseRinexStream
3
- } from "./chunk-CB6EOOLA.js";
3
+ } from "./chunk-OZCYOM5D.js";
4
4
  import {
5
5
  ARC_GAP_FACTOR,
6
6
  BAND_LABELS,
@@ -11,7 +11,7 @@ import {
11
11
  buildGloChannelMap,
12
12
  buildObsIndices,
13
13
  getFreq
14
- } from "./chunk-354IRDOG.js";
14
+ } from "./chunk-W5WKEV7U.js";
15
15
 
16
16
  // src/analysis/multipath.ts
17
17
  var MIN_ARC_LENGTH = 10;
@@ -99,8 +99,18 @@ var MultipathAccumulator = class {
99
99
  time: t,
100
100
  mp: arc.rawMp[i] - mean
101
101
  }));
102
- const rms = Math.sqrt(points.reduce((s, p) => s + p.mp * p.mp, 0) / points.length);
103
- this.results.push({ prn, system: sys, band, refBand, label, points, rms });
102
+ const rms = Math.sqrt(
103
+ points.reduce((s, p) => s + p.mp * p.mp, 0) / points.length
104
+ );
105
+ this.results.push({
106
+ prn,
107
+ system: sys,
108
+ band,
109
+ refBand,
110
+ label,
111
+ points,
112
+ rms
113
+ });
104
114
  }
105
115
  state.arc = { times: [], rawMp: [] };
106
116
  }
@@ -254,10 +264,20 @@ var CycleSlipAccumulator = class {
254
264
  const sigKey = `${sys}:${signal}`;
255
265
  this.countEpoch(sigKey);
256
266
  const stddev = mwSmoothStddev(prevSmooth);
257
- const threshold = Math.max(MW_MIN_THRESHOLD, MW_SIGMA_FACTOR * stddev);
267
+ const threshold = Math.max(
268
+ MW_MIN_THRESHOLD,
269
+ MW_SIGMA_FACTOR * stddev
270
+ );
258
271
  const deviation = Math.abs(mw - prevSmooth.mean);
259
272
  if (deviation > threshold) {
260
- this.recordSlip(sigKey, time, prn, signal, deviation, /* @__PURE__ */ new Set([b1, b2]));
273
+ this.recordSlip(
274
+ sigKey,
275
+ time,
276
+ prn,
277
+ signal,
278
+ deviation,
279
+ /* @__PURE__ */ new Set([b1, b2])
280
+ );
261
281
  mwSmooth.set(pairKey, mwSmoothInit(mw));
262
282
  } else {
263
283
  mwSmooth.set(pairKey, mwSmoothUpdate(prevSmooth, mw));
@@ -312,7 +332,13 @@ var CycleSlipAccumulator = class {
312
332
  }
313
333
  }
314
334
  }
315
- this.prev.set(prn, { time, mwSmooth, gf: gfMap, phase: phaseM, code: codeM });
335
+ this.prev.set(prn, {
336
+ time,
337
+ mwSmooth,
338
+ gf: gfMap,
339
+ phase: phaseM,
340
+ code: codeM
341
+ });
316
342
  };
317
343
  finalize() {
318
344
  const satSlipCounts = {};
@@ -320,7 +346,10 @@ var CycleSlipAccumulator = class {
320
346
  satSlipCounts[ev.prn] = (satSlipCounts[ev.prn] ?? 0) + 1;
321
347
  }
322
348
  const signalStats = [];
323
- const allKeys = /* @__PURE__ */ new Set([...this.signalEpochs.keys(), ...this.signalSlips.keys()]);
349
+ const allKeys = /* @__PURE__ */ new Set([
350
+ ...this.signalEpochs.keys(),
351
+ ...this.signalSlips.keys()
352
+ ]);
324
353
  for (const sigKey of allKeys) {
325
354
  const [sys, ...rest] = sigKey.split(":");
326
355
  const signal = rest.join(":");