gnss-js 1.61.0 → 1.63.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.
@@ -563,6 +563,116 @@ function decodeEphemeris(frame) {
563
563
  }
564
564
  }
565
565
 
566
+ // src/rtcm3/legacy-obs.ts
567
+ var PRUNIT_GPS = 299792.458;
568
+ var PRUNIT_GLO = 599584.916;
569
+ var LAM_GPS_L1 = C_LIGHT / 157542e4;
570
+ var LAM_GPS_L2 = C_LIGHT / 12276e5;
571
+ var PPR_INVALID = -(2 ** 19);
572
+ var PR21_INVALID = -(2 ** 13);
573
+ function legacyLockSec(i) {
574
+ if (i < 24) return i;
575
+ if (i < 48) return 2 * i - 24;
576
+ if (i < 72) return 4 * i - 120;
577
+ if (i < 96) return 8 * i - 408;
578
+ if (i < 120) return 16 * i - 1176;
579
+ if (i < 127) return 32 * i - 3096;
580
+ return 937;
581
+ }
582
+ var two = (n) => n.toString().padStart(2, "0");
583
+ function decodeLegacyObs(frame) {
584
+ const type = frame.messageType;
585
+ const gps = type >= 1001 && type <= 1004;
586
+ const glo = type >= 1009 && type <= 1012;
587
+ if (!gps && !glo) return null;
588
+ const ext = type === 1002 || type === 1004 || type === 1010 || type === 1012;
589
+ const dual = type === 1003 || type === 1004 || type === 1011 || type === 1012;
590
+ const system = gps ? "G" : "R";
591
+ const r = new BitReader(frame.payload);
592
+ r.readU(12);
593
+ r.readU(12);
594
+ let epochMs;
595
+ let nsat;
596
+ if (gps) {
597
+ epochMs = r.readU(30);
598
+ r.readU(1);
599
+ nsat = r.readU(5);
600
+ r.readU(1);
601
+ r.readU(3);
602
+ } else {
603
+ const tk = r.readU(27);
604
+ r.readU(1);
605
+ nsat = r.readU(5);
606
+ r.readU(1);
607
+ r.readU(3);
608
+ const gloDow = new Date(Date.now() + 3 * 36e5).getUTCDay();
609
+ epochMs = (gloDow << 27 | tk) >>> 0;
610
+ }
611
+ const observations = [];
612
+ for (let s = 0; s < nsat; s++) {
613
+ const satId = r.readU(6);
614
+ const code1 = r.readU(1);
615
+ const freqCh = glo ? r.readU(5) : 0;
616
+ const pr1raw = r.readU(gps ? 24 : 25);
617
+ const ppr1 = r.readS(20);
618
+ const lock1 = r.readU(7);
619
+ let amb = 0;
620
+ let cnr1 = 0;
621
+ if (ext) {
622
+ amb = r.readU(gps ? 8 : 7);
623
+ cnr1 = r.readU(8);
624
+ }
625
+ let code2 = 0;
626
+ let pr21 = 0;
627
+ let ppr2 = 0;
628
+ let lock2 = 0;
629
+ let cnr2 = 0;
630
+ if (dual) {
631
+ code2 = r.readU(2);
632
+ pr21 = r.readS(14);
633
+ ppr2 = r.readS(20);
634
+ lock2 = r.readU(7);
635
+ if (ext) cnr2 = r.readU(8);
636
+ }
637
+ if (gps && (satId < 1 || satId > 32)) continue;
638
+ if (glo && (satId < 1 || satId > 24)) continue;
639
+ const prunit = gps ? PRUNIT_GPS : PRUNIT_GLO;
640
+ const pr1 = pr1raw * 0.02 + amb * prunit;
641
+ const k = freqCh - 7;
642
+ const lamL1 = gps ? LAM_GPS_L1 : C_LIGHT / (GLO_F1_BASE + k * GLO_F1_STEP);
643
+ const lamL2 = gps ? LAM_GPS_L2 : C_LIGHT / (GLO_F2_BASE + k * GLO_F2_STEP);
644
+ const signals = [];
645
+ {
646
+ const sig = {
647
+ rinexCode: gps ? code1 ? "1W" : "1C" : code1 ? "1P" : "1C",
648
+ pseudorange: pr1,
649
+ wavelength: lamL1,
650
+ lockTime: legacyLockSec(lock1)
651
+ };
652
+ if (ppr1 !== PPR_INVALID) sig.phase = (pr1 + ppr1 * 5e-4) / lamL1;
653
+ if (ext && cnr1 > 0) sig.cn0 = cnr1 * 0.25;
654
+ signals.push(sig);
655
+ }
656
+ if (dual) {
657
+ const sig = {
658
+ rinexCode: gps ? code2 === 0 ? "2X" : "2W" : code2 === 0 ? "2C" : "2P",
659
+ wavelength: lamL2,
660
+ lockTime: legacyLockSec(lock2)
661
+ };
662
+ if (pr21 !== PR21_INVALID) sig.pseudorange = pr1 + pr21 * 0.02;
663
+ if (ppr2 !== PPR_INVALID) sig.phase = (pr1 + ppr2 * 5e-4) / lamL2;
664
+ if (ext && cnr2 > 0) sig.cn0 = cnr2 * 0.25;
665
+ signals.push(sig);
666
+ }
667
+ observations.push({
668
+ prn: `${system}${two(satId)}`,
669
+ system,
670
+ signals
671
+ });
672
+ }
673
+ return { messageType: type, epochMs, system, observations };
674
+ }
675
+
566
676
  // src/rtcm3/msm.ts
567
677
  var GPS_L1 = FREQ.G["1"];
568
678
  var GPS_L2 = FREQ.G["2"];
@@ -1447,6 +1557,7 @@ export {
1447
1557
  Rtcm3Decoder,
1448
1558
  readString,
1449
1559
  decodeEphemeris,
1560
+ decodeLegacyObs,
1450
1561
  decodeMsmFull,
1451
1562
  msmEpochToDate,
1452
1563
  setGloFreqNumber,
@@ -1251,6 +1251,23 @@ var VAR_ICORR = [
1251
1251
  187.0826
1252
1252
  ];
1253
1253
  var varicorr = (give) => give > 0 && give <= 15 ? VAR_ICORR[give - 1] : 0;
1254
+ var GIVE_METERS = [
1255
+ 0.3,
1256
+ 0.6,
1257
+ 0.9,
1258
+ 1.2,
1259
+ 1.5,
1260
+ 1.8,
1261
+ 2.1,
1262
+ 2.4,
1263
+ 2.7,
1264
+ 3,
1265
+ 3.6,
1266
+ 4.5,
1267
+ 6,
1268
+ 15,
1269
+ 45
1270
+ ];
1254
1271
  var DEGF = [
1255
1272
  0,
1256
1273
  5e-5,
@@ -1687,6 +1704,35 @@ var SbasProcessor = class {
1687
1704
  }
1688
1705
  return n;
1689
1706
  }
1707
+ /**
1708
+ * The current ionospheric grid — every IGP that carries a valid broadcast
1709
+ * vertical delay (MT18 mask populated by MT26 delays), across all bands, with
1710
+ * its GIVE (DO-229D Table A-17). For visualising the SBAS ionosphere; the
1711
+ * count matches {@link ionoGridPoints}. `week`/`tow` set the reference epoch
1712
+ * for each point's `ageSec` (the same argument the solver passes).
1713
+ */
1714
+ ionoGrid(week, tow) {
1715
+ const now = gpsSeconds(week, tow);
1716
+ const out = [];
1717
+ for (let band = 0; band < this.ion.length; band++) {
1718
+ const b = this.ion[band];
1719
+ if (!b) continue;
1720
+ for (const g of b.igp) {
1721
+ if (g.give <= 0) continue;
1722
+ const givei = g.give - 1;
1723
+ out.push({
1724
+ latDeg: g.lat,
1725
+ lonDeg: g.lon,
1726
+ band,
1727
+ delayM: g.delay,
1728
+ givei,
1729
+ giveMeters: GIVE_METERS[givei] ?? NaN,
1730
+ ageSec: g.t0s ? now - g.t0s : NaN
1731
+ });
1732
+ }
1733
+ }
1734
+ return out;
1735
+ }
1690
1736
  /**
1691
1737
  * Correction-coverage census at a GPS week/time — a diagnostic funnel over
1692
1738
  * the current state, explaining how many masked satellites are actually
package/dist/index.cjs CHANGED
@@ -144,6 +144,7 @@ __export(src_exports, {
144
144
  dateToEpoch: () => dateToEpoch,
145
145
  decodeBinexEph: () => decodeBinexEph,
146
146
  decodeEphemeris: () => decodeEphemeris,
147
+ decodeLegacyObs: () => decodeLegacyObs,
147
148
  decodeMsmFull: () => decodeMsmFull,
148
149
  decodeSbfNavigation: () => decodeSbfNavigation,
149
150
  deg2dms: () => deg2dms,
@@ -5019,6 +5020,116 @@ function decodeEphemeris(frame) {
5019
5020
  }
5020
5021
  }
5021
5022
 
5023
+ // src/rtcm3/legacy-obs.ts
5024
+ var PRUNIT_GPS = 299792.458;
5025
+ var PRUNIT_GLO = 599584.916;
5026
+ var LAM_GPS_L1 = C_LIGHT / 157542e4;
5027
+ var LAM_GPS_L2 = C_LIGHT / 12276e5;
5028
+ var PPR_INVALID = -(2 ** 19);
5029
+ var PR21_INVALID = -(2 ** 13);
5030
+ function legacyLockSec(i) {
5031
+ if (i < 24) return i;
5032
+ if (i < 48) return 2 * i - 24;
5033
+ if (i < 72) return 4 * i - 120;
5034
+ if (i < 96) return 8 * i - 408;
5035
+ if (i < 120) return 16 * i - 1176;
5036
+ if (i < 127) return 32 * i - 3096;
5037
+ return 937;
5038
+ }
5039
+ var two = (n) => n.toString().padStart(2, "0");
5040
+ function decodeLegacyObs(frame) {
5041
+ const type = frame.messageType;
5042
+ const gps = type >= 1001 && type <= 1004;
5043
+ const glo = type >= 1009 && type <= 1012;
5044
+ if (!gps && !glo) return null;
5045
+ const ext = type === 1002 || type === 1004 || type === 1010 || type === 1012;
5046
+ const dual = type === 1003 || type === 1004 || type === 1011 || type === 1012;
5047
+ const system = gps ? "G" : "R";
5048
+ const r = new BitReader(frame.payload);
5049
+ r.readU(12);
5050
+ r.readU(12);
5051
+ let epochMs;
5052
+ let nsat;
5053
+ if (gps) {
5054
+ epochMs = r.readU(30);
5055
+ r.readU(1);
5056
+ nsat = r.readU(5);
5057
+ r.readU(1);
5058
+ r.readU(3);
5059
+ } else {
5060
+ const tk = r.readU(27);
5061
+ r.readU(1);
5062
+ nsat = r.readU(5);
5063
+ r.readU(1);
5064
+ r.readU(3);
5065
+ const gloDow = new Date(Date.now() + 3 * 36e5).getUTCDay();
5066
+ epochMs = (gloDow << 27 | tk) >>> 0;
5067
+ }
5068
+ const observations = [];
5069
+ for (let s = 0; s < nsat; s++) {
5070
+ const satId = r.readU(6);
5071
+ const code1 = r.readU(1);
5072
+ const freqCh = glo ? r.readU(5) : 0;
5073
+ const pr1raw = r.readU(gps ? 24 : 25);
5074
+ const ppr1 = r.readS(20);
5075
+ const lock1 = r.readU(7);
5076
+ let amb = 0;
5077
+ let cnr1 = 0;
5078
+ if (ext) {
5079
+ amb = r.readU(gps ? 8 : 7);
5080
+ cnr1 = r.readU(8);
5081
+ }
5082
+ let code2 = 0;
5083
+ let pr21 = 0;
5084
+ let ppr2 = 0;
5085
+ let lock2 = 0;
5086
+ let cnr2 = 0;
5087
+ if (dual) {
5088
+ code2 = r.readU(2);
5089
+ pr21 = r.readS(14);
5090
+ ppr2 = r.readS(20);
5091
+ lock2 = r.readU(7);
5092
+ if (ext) cnr2 = r.readU(8);
5093
+ }
5094
+ if (gps && (satId < 1 || satId > 32)) continue;
5095
+ if (glo && (satId < 1 || satId > 24)) continue;
5096
+ const prunit = gps ? PRUNIT_GPS : PRUNIT_GLO;
5097
+ const pr1 = pr1raw * 0.02 + amb * prunit;
5098
+ const k = freqCh - 7;
5099
+ const lamL1 = gps ? LAM_GPS_L1 : C_LIGHT / (GLO_F1_BASE + k * GLO_F1_STEP);
5100
+ const lamL2 = gps ? LAM_GPS_L2 : C_LIGHT / (GLO_F2_BASE + k * GLO_F2_STEP);
5101
+ const signals = [];
5102
+ {
5103
+ const sig = {
5104
+ rinexCode: gps ? code1 ? "1W" : "1C" : code1 ? "1P" : "1C",
5105
+ pseudorange: pr1,
5106
+ wavelength: lamL1,
5107
+ lockTime: legacyLockSec(lock1)
5108
+ };
5109
+ if (ppr1 !== PPR_INVALID) sig.phase = (pr1 + ppr1 * 5e-4) / lamL1;
5110
+ if (ext && cnr1 > 0) sig.cn0 = cnr1 * 0.25;
5111
+ signals.push(sig);
5112
+ }
5113
+ if (dual) {
5114
+ const sig = {
5115
+ rinexCode: gps ? code2 === 0 ? "2X" : "2W" : code2 === 0 ? "2C" : "2P",
5116
+ wavelength: lamL2,
5117
+ lockTime: legacyLockSec(lock2)
5118
+ };
5119
+ if (pr21 !== PR21_INVALID) sig.pseudorange = pr1 + pr21 * 0.02;
5120
+ if (ppr2 !== PPR_INVALID) sig.phase = (pr1 + ppr2 * 5e-4) / lamL2;
5121
+ if (ext && cnr2 > 0) sig.cn0 = cnr2 * 0.25;
5122
+ signals.push(sig);
5123
+ }
5124
+ observations.push({
5125
+ prn: `${system}${two(satId)}`,
5126
+ system,
5127
+ signals
5128
+ });
5129
+ }
5130
+ return { messageType: type, epochMs, system, observations };
5131
+ }
5132
+
5022
5133
  // src/rtcm3/msm.ts
5023
5134
  var GPS_L1 = FREQ.G["1"];
5024
5135
  var GPS_L2 = FREQ.G["2"];
@@ -6349,7 +6460,7 @@ function weekOfToe(week, tow, toe) {
6349
6460
  if (toe - tow < -HALF_WEEK3) return week + 1;
6350
6461
  return week;
6351
6462
  }
6352
- var two = (n) => String(n).padStart(2, "0");
6463
+ var two2 = (n) => String(n).padStart(2, "0");
6353
6464
  function decodeGalInavWords(words) {
6354
6465
  if (words.length < 96) return null;
6355
6466
  const b = words;
@@ -6437,7 +6548,7 @@ function decodeGalInavWords(words) {
6437
6548
  const tocDate = gpsDate2(week, tocs);
6438
6549
  return {
6439
6550
  system: "E",
6440
- prn: `E${two(svid)}`,
6551
+ prn: `E${two2(svid)}`,
6441
6552
  toc: tocDate.getTime() / 1e3 % SEC_PER_WEEK5,
6442
6553
  tocDate,
6443
6554
  af0,
@@ -6545,7 +6656,7 @@ function decodeGalFnavPages(pages) {
6545
6656
  const tocDate = gpsDate2(week, tocs);
6546
6657
  return {
6547
6658
  system: "E",
6548
- prn: `E${two(svid)}`,
6659
+ prn: `E${two2(svid)}`,
6549
6660
  toc: tocDate.getTime() / 1e3 % SEC_PER_WEEK5,
6550
6661
  tocDate,
6551
6662
  af0,
@@ -6601,7 +6712,7 @@ var GalInavAssembler = class {
6601
6712
  sat.words[type * 16 + 15] = getBitU(page, 124, 8);
6602
6713
  if (type !== 5) return null;
6603
6714
  const eph = decodeGalInavWords(sat.words);
6604
- if (!eph || eph.prn !== `E${two(prn)}`) return null;
6715
+ if (!eph || eph.prn !== `E${two2(prn)}`) return null;
6605
6716
  const key = dedupKey(eph);
6606
6717
  if (key === sat.lastKey) return null;
6607
6718
  sat.lastKey = key;
@@ -6628,7 +6739,7 @@ var GalFnavAssembler = class {
6628
6739
  sat.words.set(page.subarray(0, 31), (type - 1) * 31);
6629
6740
  if (type !== 4) return null;
6630
6741
  const eph = decodeGalFnavPages(sat.words);
6631
- if (!eph || eph.prn !== `E${two(prn)}`) return null;
6742
+ if (!eph || eph.prn !== `E${two2(prn)}`) return null;
6632
6743
  const key = dedupKey(eph);
6633
6744
  if (key === sat.lastKey) return null;
6634
6745
  sat.lastKey = key;
@@ -6802,7 +6913,7 @@ var GloStringAssembler = class {
6802
6913
  // src/navbits/sbas.ts
6803
6914
  var GPS_EPOCH_MS7 = Date.UTC(1980, 0, 6);
6804
6915
  var MS_PER_WEEK3 = 7 * 86400 * 1e3;
6805
- var two2 = (n) => String(n).padStart(2, "0");
6916
+ var two3 = (n) => String(n).padStart(2, "0");
6806
6917
  var SBAS_MT_GEO_NAV = 9;
6807
6918
  function sbasMessageType(msg) {
6808
6919
  return getBitU(msg, 8, 6);
@@ -6821,7 +6932,7 @@ function decodeSbasGeoNav(msg, prn, week, tow) {
6821
6932
  const ura = getBitU(msg, 35, 4);
6822
6933
  return {
6823
6934
  system: "S",
6824
- prn: `S${two2(prn - 100)}`,
6935
+ prn: `S${two3(prn - 100)}`,
6825
6936
  tocDate: new Date(GPS_EPOCH_MS7 + week * MS_PER_WEEK3 + t0Sec * 1e3),
6826
6937
  tauN: getBitS(msg, 206, 12) * 2 ** -31,
6827
6938
  // a_Gf0, clock offset (s)
@@ -6845,7 +6956,7 @@ function decodeSbasGeoNav(msg, prn, week, tow) {
6845
6956
  // src/ubx/rawnav.ts
6846
6957
  var GPS_EPOCH_MS8 = Date.UTC(1980, 0, 6);
6847
6958
  var SEC_PER_WEEK7 = 7 * 86400;
6848
- var two3 = (n) => String(n).padStart(2, "0");
6959
+ var two4 = (n) => String(n).padStart(2, "0");
6849
6960
  function parseUbxRawNav(data, opts = {}) {
6850
6961
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
6851
6962
  const ephemerides = [];
@@ -6921,7 +7032,7 @@ function parseUbxRawNav(data, opts = {}) {
6921
7032
  badParity++;
6922
7033
  continue;
6923
7034
  }
6924
- const eph = bds.push(`C${two3(svId)}`, sf);
7035
+ const eph = bds.push(`C${two4(svId)}`, sf);
6925
7036
  if (eph) ephemerides.push(eph);
6926
7037
  } else if (gnssId === 6) {
6927
7038
  if (p.length < 8 + 16) continue;
@@ -6940,7 +7051,7 @@ function parseUbxRawNav(data, opts = {}) {
6940
7051
  continue;
6941
7052
  }
6942
7053
  if (!refDate) continue;
6943
- const eph = glo.push(`R${two3(svId)}`, str2, refDate, p[3] - 7);
7054
+ const eph = glo.push(`R${two4(svId)}`, str2, refDate, p[3] - 7);
6944
7055
  if (eph) ephemerides.push(eph);
6945
7056
  } else if (gnssId === 1) {
6946
7057
  if (p.length < 8 + 32) continue;
@@ -7042,20 +7153,20 @@ var SIGNALS = {
7042
7153
  // GLONASS L1OF, L2OF
7043
7154
  };
7044
7155
  function prnFor(gnssId, svId) {
7045
- const two9 = (n) => String(n).padStart(2, "0");
7156
+ const two10 = (n) => String(n).padStart(2, "0");
7046
7157
  switch (gnssId) {
7047
7158
  case 0:
7048
- return svId >= 1 && svId <= 32 ? `G${two9(svId)}` : null;
7159
+ return svId >= 1 && svId <= 32 ? `G${two10(svId)}` : null;
7049
7160
  case 1:
7050
- return svId >= 120 && svId <= 158 ? `S${two9(svId - 100)}` : null;
7161
+ return svId >= 120 && svId <= 158 ? `S${two10(svId - 100)}` : null;
7051
7162
  case 2:
7052
- return svId >= 1 && svId <= 36 ? `E${two9(svId)}` : null;
7163
+ return svId >= 1 && svId <= 36 ? `E${two10(svId)}` : null;
7053
7164
  case 3:
7054
- return svId >= 1 && svId <= 63 ? `C${two9(svId)}` : null;
7165
+ return svId >= 1 && svId <= 63 ? `C${two10(svId)}` : null;
7055
7166
  case 5:
7056
- return svId >= 1 && svId <= 10 ? `J${two9(svId)}` : null;
7167
+ return svId >= 1 && svId <= 10 ? `J${two10(svId)}` : null;
7057
7168
  case 6:
7058
- return svId >= 1 && svId <= 32 ? `R${two9(svId)}` : null;
7169
+ return svId >= 1 && svId <= 32 ? `R${two10(svId)}` : null;
7059
7170
  default:
7060
7171
  return null;
7061
7172
  }
@@ -7158,22 +7269,22 @@ function scanSbfFrames(data, view, onBlock) {
7158
7269
  }
7159
7270
  return badCrc;
7160
7271
  }
7161
- var two4 = (n) => String(n).padStart(2, "0");
7272
+ var two5 = (n) => String(n).padStart(2, "0");
7162
7273
  function svidToPrn(svid) {
7163
- if (svid >= 1 && svid <= 37) return svid <= 32 ? `G${two4(svid)}` : null;
7164
- if (svid <= 61) return svid - 37 <= 27 ? `R${two4(svid - 37)}` : null;
7274
+ if (svid >= 1 && svid <= 37) return svid <= 32 ? `G${two5(svid)}` : null;
7275
+ if (svid <= 61) return svid - 37 <= 27 ? `R${two5(svid - 37)}` : null;
7165
7276
  if (svid <= 62) return null;
7166
- if (svid <= 68) return svid - 38 <= 27 ? `R${two4(svid - 38)}` : null;
7277
+ if (svid <= 68) return svid - 38 <= 27 ? `R${two5(svid - 38)}` : null;
7167
7278
  if (svid <= 70) return null;
7168
- if (svid <= 106) return svid - 70 <= 36 ? `E${two4(svid - 70)}` : null;
7279
+ if (svid <= 106) return svid - 70 <= 36 ? `E${two5(svid - 70)}` : null;
7169
7280
  if (svid <= 119) return null;
7170
- if (svid <= 140) return `S${two4(svid - 100)}`;
7171
- if (svid <= 180) return svid - 140 <= 50 ? `C${two4(svid - 140)}` : null;
7172
- if (svid <= 190) return `J${two4(svid - 180)}`;
7173
- if (svid <= 197) return svid - 190 <= 14 ? `I${two4(svid - 190)}` : null;
7174
- if (svid <= 215) return `S${two4(svid - 157)}`;
7175
- if (svid <= 222) return svid - 208 <= 14 ? `I${two4(svid - 208)}` : null;
7176
- if (svid <= 245) return svid - 182 <= 50 ? `C${two4(svid - 182)}` : null;
7281
+ if (svid <= 140) return `S${two5(svid - 100)}`;
7282
+ if (svid <= 180) return svid - 140 <= 50 ? `C${two5(svid - 140)}` : null;
7283
+ if (svid <= 190) return `J${two5(svid - 180)}`;
7284
+ if (svid <= 197) return svid - 190 <= 14 ? `I${two5(svid - 190)}` : null;
7285
+ if (svid <= 215) return `S${two5(svid - 157)}`;
7286
+ if (svid <= 222) return svid - 208 <= 14 ? `I${two5(svid - 208)}` : null;
7287
+ if (svid <= 245) return svid - 182 <= 50 ? `C${two5(svid - 182)}` : null;
7177
7288
  return null;
7178
7289
  }
7179
7290
 
@@ -8785,23 +8896,23 @@ var MEAS2_SIG = [
8785
8896
  ["J", "1E"],
8786
8897
  ["J", "5P"]
8787
8898
  ];
8788
- var two5 = (n) => String(n).padStart(2, "0");
8899
+ var two6 = (n) => String(n).padStart(2, "0");
8789
8900
  function m3Prn(navsys, svid) {
8790
8901
  switch (navsys) {
8791
8902
  case 0:
8792
- return svid < 32 ? `G${two5(svid + 1)}` : null;
8903
+ return svid < 32 ? `G${two6(svid + 1)}` : null;
8793
8904
  case 1:
8794
- return svid < 27 ? `R${two5(svid + 1)}` : null;
8905
+ return svid < 27 ? `R${two6(svid + 1)}` : null;
8795
8906
  case 2:
8796
- return svid < 36 ? `E${two5(svid + 1)}` : null;
8907
+ return svid < 36 ? `E${two6(svid + 1)}` : null;
8797
8908
  case 3:
8798
- return svid < 50 ? `C${two5(svid + 1)}` : null;
8909
+ return svid < 50 ? `C${two6(svid + 1)}` : null;
8799
8910
  case 4:
8800
- return svid <= 38 ? `S${two5(svid + 20)}` : null;
8911
+ return svid <= 38 ? `S${two6(svid + 20)}` : null;
8801
8912
  case 5:
8802
- return svid < 10 ? `J${two5(svid + 1)}` : null;
8913
+ return svid < 10 ? `J${two6(svid + 1)}` : null;
8803
8914
  case 6:
8804
- return svid < 14 ? `I${two5(svid + 1)}` : null;
8915
+ return svid < 14 ? `I${two6(svid + 1)}` : null;
8805
8916
  default:
8806
8917
  return null;
8807
8918
  }
@@ -10635,7 +10746,7 @@ var MS_PER_WEEK12 = SEC_PER_WEEK11 * 1e3;
10635
10746
  var SC2RAD = GPS_PI;
10636
10747
  var gpsMs4 = (week, sec) => GPS_EPOCH_MS20 + week * MS_PER_WEEK12 + sec * 1e3;
10637
10748
  var sowOf5 = (dateMs) => (dateMs / 1e3 % SEC_PER_WEEK11 + SEC_PER_WEEK11) % SEC_PER_WEEK11;
10638
- var two6 = (n) => String(n).padStart(2, "0");
10749
+ var two7 = (n) => String(n).padStart(2, "0");
10639
10750
  var Reader = class {
10640
10751
  constructor(view, start, le) {
10641
10752
  this.view = view;
@@ -10730,7 +10841,7 @@ function decodeGpsQzss(view, p, le, sys) {
10730
10841
  const tocDate = new Date(gpsMs4(week, toes));
10731
10842
  return {
10732
10843
  system: sys,
10733
- prn: `${sys}${two6(prn)}`,
10844
+ prn: `${sys}${two7(prn)}`,
10734
10845
  toc: sowOf5(tocDate.getTime()),
10735
10846
  tocDate,
10736
10847
  af0,
@@ -10763,7 +10874,7 @@ function decodeGalileo(view, p, le) {
10763
10874
  const tocDate = new Date(gpsMs4(week, toes));
10764
10875
  return {
10765
10876
  system: "E",
10766
- prn: `E${two6(prn)}`,
10877
+ prn: `E${two7(prn)}`,
10767
10878
  toc: sowOf5(tocDate.getTime()),
10768
10879
  tocDate,
10769
10880
  af0,
@@ -10801,7 +10912,7 @@ function decodeBeidou(view, p, le) {
10801
10912
  const tocDate = new Date(BDT_EPOCH_MS5 + week * MS_PER_WEEK12 + toes * 1e3);
10802
10913
  return {
10803
10914
  system: "C",
10804
- prn: `C${two6(prn)}`,
10915
+ prn: `C${two7(prn)}`,
10805
10916
  toc: sowOf5(tocDate.getTime()),
10806
10917
  tocDate,
10807
10918
  af0,
@@ -10841,7 +10952,7 @@ function decodeGlonass(view, p, le) {
10841
10952
  );
10842
10953
  return {
10843
10954
  system: "R",
10844
- prn: `R${two6(slot)}`,
10955
+ prn: `R${two7(slot)}`,
10845
10956
  tocDate,
10846
10957
  tauN,
10847
10958
  gammaN,
@@ -10880,7 +10991,7 @@ function decodeSbas(view, p, le) {
10880
10991
  if (prn < 120 || prn > 158) return null;
10881
10992
  return {
10882
10993
  system: "S",
10883
- prn: `S${two6(prn - 100)}`,
10994
+ prn: `S${two7(prn - 100)}`,
10884
10995
  tocDate: new Date(gpsMs4(week, toe)),
10885
10996
  tauN: af0,
10886
10997
  gammaN: af1,
@@ -11057,22 +11168,22 @@ var OBS_CODES = {
11057
11168
  ]
11058
11169
  // QZSS
11059
11170
  };
11060
- var two7 = (n) => String(n).padStart(2, "0");
11171
+ var two8 = (n) => String(n).padStart(2, "0");
11061
11172
  function obsPrn(sys, prn) {
11062
11173
  switch (sys) {
11063
11174
  case 0:
11064
- return prn >= 1 && prn <= 32 ? `G${two7(prn)}` : null;
11175
+ return prn >= 1 && prn <= 32 ? `G${two8(prn)}` : null;
11065
11176
  case 1:
11066
- return prn >= 1 && prn <= 27 ? `R${two7(prn)}` : null;
11177
+ return prn >= 1 && prn <= 27 ? `R${two8(prn)}` : null;
11067
11178
  case 2:
11068
- return prn >= 120 && prn <= 158 ? `S${two7(prn - 100)}` : null;
11179
+ return prn >= 120 && prn <= 158 ? `S${two8(prn - 100)}` : null;
11069
11180
  case 3:
11070
- return prn >= 1 && prn <= 36 ? `E${two7(prn)}` : null;
11181
+ return prn >= 1 && prn <= 36 ? `E${two8(prn)}` : null;
11071
11182
  case 4:
11072
- return prn >= 1 && prn <= 63 ? `C${two7(prn)}` : null;
11183
+ return prn >= 1 && prn <= 63 ? `C${two8(prn)}` : null;
11073
11184
  case 5:
11074
- if (prn >= 193 && prn <= 202) return `J${two7(prn - 192)}`;
11075
- return prn >= 1 && prn <= 10 ? `J${two7(prn)}` : null;
11185
+ if (prn >= 193 && prn <= 202) return `J${two8(prn - 192)}`;
11186
+ return prn >= 1 && prn <= 10 ? `J${two8(prn)}` : null;
11076
11187
  default:
11077
11188
  return null;
11078
11189
  }
@@ -13425,7 +13536,7 @@ var SEC_PER_WEEK12 = 604800;
13425
13536
  var MAXSBSAGEF = 30;
13426
13537
  var MAXSBSAGEL = 360;
13427
13538
  var MAXBAND = 10;
13428
- var two8 = (n) => String(n).padStart(2, "0");
13539
+ var two9 = (n) => String(n).padStart(2, "0");
13429
13540
  var VAR_FCORR = [
13430
13541
  0.052,
13431
13542
  0.0924,
@@ -13461,6 +13572,23 @@ var VAR_ICORR = [
13461
13572
  187.0826
13462
13573
  ];
13463
13574
  var varicorr = (give) => give > 0 && give <= 15 ? VAR_ICORR[give - 1] : 0;
13575
+ var GIVE_METERS = [
13576
+ 0.3,
13577
+ 0.6,
13578
+ 0.9,
13579
+ 1.2,
13580
+ 1.5,
13581
+ 1.8,
13582
+ 2.1,
13583
+ 2.4,
13584
+ 2.7,
13585
+ 3,
13586
+ 3.6,
13587
+ 4.5,
13588
+ 6,
13589
+ 15,
13590
+ 45
13591
+ ];
13464
13592
  var DEGF = [
13465
13593
  0,
13466
13594
  5e-5,
@@ -13554,10 +13682,10 @@ var igpband2 = [
13554
13682
  ];
13555
13683
  var gpsSeconds = (week, tow) => week * SEC_PER_WEEK12 + tow;
13556
13684
  function maskPrn(i) {
13557
- if (i >= 1 && i <= 37) return `G${two8(i)}`;
13558
- if (i >= 38 && i <= 61) return `R${two8(i - 37)}`;
13559
- if (i >= 120 && i <= 138) return `S${two8(i - 100)}`;
13560
- if (i >= 193 && i <= 202) return `J${two8(i - 192)}`;
13685
+ if (i >= 1 && i <= 37) return `G${two9(i)}`;
13686
+ if (i >= 38 && i <= 61) return `R${two9(i - 37)}`;
13687
+ if (i >= 120 && i <= 138) return `S${two9(i - 100)}`;
13688
+ if (i >= 193 && i <= 202) return `J${two9(i - 192)}`;
13561
13689
  return null;
13562
13690
  }
13563
13691
  function ionppp(latRad, lonRad, azRad, elRad, re, hion) {
@@ -13596,7 +13724,7 @@ var SbasProcessor = class {
13596
13724
  if (week === 0) return -1;
13597
13725
  const type = sbasMessageType(msg);
13598
13726
  if (geoPrn != null && geoPrn >= 120 && geoPrn <= 158)
13599
- this.geoPrns.add(`S${two8(geoPrn - 100)}`);
13727
+ this.geoPrns.add(`S${two9(geoPrn - 100)}`);
13600
13728
  switch (type) {
13601
13729
  case 1:
13602
13730
  return this.decodeMask(msg) ? type : -1;
@@ -13897,6 +14025,35 @@ var SbasProcessor = class {
13897
14025
  }
13898
14026
  return n;
13899
14027
  }
14028
+ /**
14029
+ * The current ionospheric grid — every IGP that carries a valid broadcast
14030
+ * vertical delay (MT18 mask populated by MT26 delays), across all bands, with
14031
+ * its GIVE (DO-229D Table A-17). For visualising the SBAS ionosphere; the
14032
+ * count matches {@link ionoGridPoints}. `week`/`tow` set the reference epoch
14033
+ * for each point's `ageSec` (the same argument the solver passes).
14034
+ */
14035
+ ionoGrid(week, tow) {
14036
+ const now = gpsSeconds(week, tow);
14037
+ const out = [];
14038
+ for (let band = 0; band < this.ion.length; band++) {
14039
+ const b = this.ion[band];
14040
+ if (!b) continue;
14041
+ for (const g of b.igp) {
14042
+ if (g.give <= 0) continue;
14043
+ const givei = g.give - 1;
14044
+ out.push({
14045
+ latDeg: g.lat,
14046
+ lonDeg: g.lon,
14047
+ band,
14048
+ delayM: g.delay,
14049
+ givei,
14050
+ giveMeters: GIVE_METERS[givei] ?? NaN,
14051
+ ageSec: g.t0s ? now - g.t0s : NaN
14052
+ });
14053
+ }
14054
+ }
14055
+ return out;
14056
+ }
13900
14057
  /**
13901
14058
  * Correction-coverage census at a GPS week/time — a diagnostic funnel over
13902
14059
  * the current state, explaining how many masked satellites are actually
@@ -18116,6 +18273,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
18116
18273
  dateToEpoch,
18117
18274
  decodeBinexEph,
18118
18275
  decodeEphemeris,
18276
+ decodeLegacyObs,
18119
18277
  decodeMsmFull,
18120
18278
  decodeSbfNavigation,
18121
18279
  deg2dms,
package/dist/index.d.cts CHANGED
@@ -10,7 +10,7 @@ export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResul
10
10
  export { C as CnavEphemeris, E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, R as RinexCnavEphemeris, p as parseNavFile } from './nav-DImXUdbp.cjs';
11
11
  export { C as ClkFile, I as IonexGrid, S as Sp3File, a as Sp3Sample, c as clkBias, p as parseClk, b as parseIonex, d as parseSp3, s as sp3Position } from './clk-DGVBGRzA.cjs';
12
12
  export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.cjs';
13
- export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.cjs';
13
+ export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeLegacyObs, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.cjs';
14
14
  export { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxPvtResult, UbxRawNavOptions, UbxRawNavResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxPvt, parseUbxRawNav, parseUbxRawx, ubxFrames } from './ubx.cjs';
15
15
  export { DfmcCensus, DfmcMessageCb, GeoL5Result, HasMessage, SBAS_L5_MT_NAMES, SBAS_L5_PREAMBLE_UW, SbasMessageCb, SbfBdsNavResult, SbfCnavEphemeris, SbfCnavResult, SbfGalEphemeris, SbfGalNavResult, SbfGeoL5Result, SbfGeoNavResult, SbfGloNavResult, SbfGpsNavResult, SbfHasMessage, SbfHasResult, SbfIonoUtcResult, SbfMeasEpoch, SbfMeasurement, SbfNavCounts, SbfNavigation, SbfParseResult, SbfPvt, SbfPvtResult, SbfReceiverSetup, decodeSbfNavigation, feedGeoBlock, feedGeoL5Block, isSbasL1Preamble, isSbasL5Correction, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoL5, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, sbasL5MessageName, sbasL5MessageType, sbfCrc16, scanSbfFrames } from './sbf.cjs';
16
16
  export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, NovatelPvtResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelPvt, parseNovatelRange } from './novatel.cjs';
@@ -18,7 +18,7 @@ export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, Trimb
18
18
  export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.cjs';
19
19
  export { AllPositionsData, AlmanacPosition, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris } from './orbit.cjs';
20
20
  export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.cjs';
21
- export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, Degradation, DgnssOptions, DgnssSolution, EphemerisSource, FixedPositionResult, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, NetworkFcbResult, NetworkFcbSummary, NlArc, NlFcbResult, PppAntennaModel, PppArc, PppCorrectionConfig, PppCorrections, PppEpoch, PppEpochContext, PppEpochResult, PppFixState, PppOptions, PppSatObs, PppSolution, RawObservation, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, RtkObsEpoch, RtkObsInput, RtkPostProcessOptions, RtkPostProcessResult, RtkTrackPoint, SatGeom, SbasCorrectionSource, SbasIonoDelay, SbasProcessor, SbasSatCorrection, SppOptions, SppSolution, TropoMapping, WlArc, WlFcbOptions, WlFcbResult, WlObs, buildPppAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, fixPppPosition, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, postProcessRtk, resolvePppAmbiguities, satClockCorrection, sbasIonoDeg, sbasLongTermDeg, sbasProtectionLevels, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.cjs';
21
+ export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, Degradation, DgnssOptions, DgnssSolution, EphemerisSource, FixedPositionResult, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, NetworkFcbResult, NetworkFcbSummary, NlArc, NlFcbResult, PppAntennaModel, PppArc, PppCorrectionConfig, PppCorrections, PppEpoch, PppEpochContext, PppEpochResult, PppFixState, PppOptions, PppSatObs, PppSolution, RawObservation, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, RtkObsEpoch, RtkObsInput, RtkPostProcessOptions, RtkPostProcessResult, RtkTrackPoint, SatGeom, SbasCorrectionSource, SbasIgp, SbasIonoDelay, SbasProcessor, SbasSatCorrection, SppOptions, SppSolution, TropoMapping, WlArc, WlFcbOptions, WlFcbResult, WlObs, buildPppAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, fixPppPosition, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, postProcessRtk, resolvePppAmbiguities, satClockCorrection, sbasIonoDeg, sbasLongTermDeg, sbasProtectionLevels, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.cjs';
22
22
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.cjs';
23
23
  export { CompleteSatSignal, CompleteSignalStats, CompletenessAccumulator, CompletenessResult, CycleSlipAccumulator, CycleSlipEvent, CycleSlipResult, CycleSlipSignalStats, IonoAccumulator, IonoDcbResult, IonoPoint, IonoRatePoint, IonoRateSeries, IonoResult, IonoSeries, MultipathAccumulator, MultipathPoint, MultipathResult, MultipathSeries, MultipathSignalStat, QualityResult, SatDcbMap, analyzeQuality, applyIonoDcb, computeIonoRate, detrendIonoArcs, parseSinexBiasDcb } from './analysis.cjs';
24
24
  export { AntennaEntry, AntexFile, FrequencyData, frequencyLabel, parseAntex } from './antex.cjs';
package/dist/index.d.ts CHANGED
@@ -10,7 +10,7 @@ export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResul
10
10
  export { C as CnavEphemeris, E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, R as RinexCnavEphemeris, p as parseNavFile } from './nav-DImXUdbp.js';
11
11
  export { C as ClkFile, I as IonexGrid, S as Sp3File, a as Sp3Sample, c as clkBias, p as parseClk, b as parseIonex, d as parseSp3, s as sp3Position } from './clk-DGVBGRzA.js';
12
12
  export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.js';
13
- export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.js';
13
+ export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeLegacyObs, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.js';
14
14
  export { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxPvtResult, UbxRawNavOptions, UbxRawNavResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxPvt, parseUbxRawNav, parseUbxRawx, ubxFrames } from './ubx.js';
15
15
  export { DfmcCensus, DfmcMessageCb, GeoL5Result, HasMessage, SBAS_L5_MT_NAMES, SBAS_L5_PREAMBLE_UW, SbasMessageCb, SbfBdsNavResult, SbfCnavEphemeris, SbfCnavResult, SbfGalEphemeris, SbfGalNavResult, SbfGeoL5Result, SbfGeoNavResult, SbfGloNavResult, SbfGpsNavResult, SbfHasMessage, SbfHasResult, SbfIonoUtcResult, SbfMeasEpoch, SbfMeasurement, SbfNavCounts, SbfNavigation, SbfParseResult, SbfPvt, SbfPvtResult, SbfReceiverSetup, decodeSbfNavigation, feedGeoBlock, feedGeoL5Block, isSbasL1Preamble, isSbasL5Correction, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoL5, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, sbasL5MessageName, sbasL5MessageType, sbfCrc16, scanSbfFrames } from './sbf.js';
16
16
  export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, NovatelPvtResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelPvt, parseNovatelRange } from './novatel.js';
@@ -18,7 +18,7 @@ export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, Trimb
18
18
  export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.js';
19
19
  export { AllPositionsData, AlmanacPosition, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, VisibilityPass, VisibilityResult, almanacEpochMs, almanacSatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, computeVisibility, computeVisibilityFromPositions, dopplerHz, ecefToAzEl, ephInfoToEphemeris, glonassAlmanacEpochMs, glonassAlmanacPosition, glonassPosition, keplerPosition, maskRadForAzimuth, navTimesFromEph, rangeRate, selectEphemeris } from './orbit.js';
20
20
  export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.js';
21
- export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, Degradation, DgnssOptions, DgnssSolution, EphemerisSource, FixedPositionResult, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, NetworkFcbResult, NetworkFcbSummary, NlArc, NlFcbResult, PppAntennaModel, PppArc, PppCorrectionConfig, PppCorrections, PppEpoch, PppEpochContext, PppEpochResult, PppFixState, PppOptions, PppSatObs, PppSolution, RawObservation, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, RtkObsEpoch, RtkObsInput, RtkPostProcessOptions, RtkPostProcessResult, RtkTrackPoint, SatGeom, SbasCorrectionSource, SbasIonoDelay, SbasProcessor, SbasSatCorrection, SppOptions, SppSolution, TropoMapping, WlArc, WlFcbOptions, WlFcbResult, WlObs, buildPppAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, fixPppPosition, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, postProcessRtk, resolvePppAmbiguities, satClockCorrection, sbasIonoDeg, sbasLongTermDeg, sbasProtectionLevels, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.js';
21
+ export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, Degradation, DgnssOptions, DgnssSolution, EphemerisSource, FixedPositionResult, IONO_L1_M_PER_TECU, KlobucharCoeffs, LambdaResult, NetworkFcbResult, NetworkFcbSummary, NlArc, NlFcbResult, PppAntennaModel, PppArc, PppCorrectionConfig, PppCorrections, PppEpoch, PppEpochContext, PppEpochResult, PppFixState, PppOptions, PppSatObs, PppSolution, RawObservation, RtkEpochMeasurements, RtkFloatEngine, RtkFloatOptions, RtkFloatSolution, RtkMeasurement, RtkObsEpoch, RtkObsInput, RtkPostProcessOptions, RtkPostProcessResult, RtkTrackPoint, SatGeom, SbasCorrectionSource, SbasIgp, SbasIonoDelay, SbasProcessor, SbasSatCorrection, SppOptions, SppSolution, TropoMapping, WlArc, WlFcbOptions, WlFcbResult, WlObs, buildPppAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, fixPppPosition, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, postProcessRtk, resolvePppAmbiguities, satClockCorrection, sbasIonoDeg, sbasLongTermDeg, sbasProtectionLevels, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.js';
22
22
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.js';
23
23
  export { CompleteSatSignal, CompleteSignalStats, CompletenessAccumulator, CompletenessResult, CycleSlipAccumulator, CycleSlipEvent, CycleSlipResult, CycleSlipSignalStats, IonoAccumulator, IonoDcbResult, IonoPoint, IonoRatePoint, IonoRateSeries, IonoResult, IonoSeries, MultipathAccumulator, MultipathPoint, MultipathResult, MultipathSeries, MultipathSignalStat, QualityResult, SatDcbMap, analyzeQuality, applyIonoDcb, computeIonoRate, detrendIonoArcs, parseSinexBiasDcb } from './analysis.js';
24
24
  export { AntennaEntry, AntexFile, FrequencyData, frequencyLabel, parseAntex } from './antex.js';
package/dist/index.js CHANGED
@@ -178,7 +178,7 @@ import {
178
178
  sunEcef,
179
179
  toRtkEpoch,
180
180
  wlWavelength
181
- } from "./chunk-GWN2F3PQ.js";
181
+ } from "./chunk-TWAC2BZF.js";
182
182
  import "./chunk-WQX354KD.js";
183
183
  import {
184
184
  almanacEpochMs,
@@ -275,6 +275,7 @@ import {
275
275
  createStationMeta,
276
276
  createStreamStats,
277
277
  decodeEphemeris,
278
+ decodeLegacyObs,
278
279
  decodeMsmFull,
279
280
  msmEpochToDate,
280
281
  readString,
@@ -285,7 +286,7 @@ import {
285
286
  setRtcm3DebugHandler,
286
287
  updateStationMeta,
287
288
  updateStreamStats
288
- } from "./chunk-BRT6XZ7B.js";
289
+ } from "./chunk-QN7Q2ALS.js";
289
290
  import {
290
291
  getBdsTime,
291
292
  getDateFromBdsTime,
@@ -494,6 +495,7 @@ export {
494
495
  dateToEpoch,
495
496
  decodeBinexEph,
496
497
  decodeEphemeris,
498
+ decodeLegacyObs,
497
499
  decodeMsmFull,
498
500
  decodeSbfNavigation,
499
501
  deg2dms,
@@ -1727,6 +1727,23 @@ var VAR_ICORR = [
1727
1727
  187.0826
1728
1728
  ];
1729
1729
  var varicorr = (give) => give > 0 && give <= 15 ? VAR_ICORR[give - 1] : 0;
1730
+ var GIVE_METERS = [
1731
+ 0.3,
1732
+ 0.6,
1733
+ 0.9,
1734
+ 1.2,
1735
+ 1.5,
1736
+ 1.8,
1737
+ 2.1,
1738
+ 2.4,
1739
+ 2.7,
1740
+ 3,
1741
+ 3.6,
1742
+ 4.5,
1743
+ 6,
1744
+ 15,
1745
+ 45
1746
+ ];
1730
1747
  var DEGF = [
1731
1748
  0,
1732
1749
  5e-5,
@@ -2163,6 +2180,35 @@ var SbasProcessor = class {
2163
2180
  }
2164
2181
  return n;
2165
2182
  }
2183
+ /**
2184
+ * The current ionospheric grid — every IGP that carries a valid broadcast
2185
+ * vertical delay (MT18 mask populated by MT26 delays), across all bands, with
2186
+ * its GIVE (DO-229D Table A-17). For visualising the SBAS ionosphere; the
2187
+ * count matches {@link ionoGridPoints}. `week`/`tow` set the reference epoch
2188
+ * for each point's `ageSec` (the same argument the solver passes).
2189
+ */
2190
+ ionoGrid(week, tow) {
2191
+ const now = gpsSeconds(week, tow);
2192
+ const out = [];
2193
+ for (let band = 0; band < this.ion.length; band++) {
2194
+ const b = this.ion[band];
2195
+ if (!b) continue;
2196
+ for (const g of b.igp) {
2197
+ if (g.give <= 0) continue;
2198
+ const givei = g.give - 1;
2199
+ out.push({
2200
+ latDeg: g.lat,
2201
+ lonDeg: g.lon,
2202
+ band,
2203
+ delayM: g.delay,
2204
+ givei,
2205
+ giveMeters: GIVE_METERS[givei] ?? NaN,
2206
+ ageSec: g.t0s ? now - g.t0s : NaN
2207
+ });
2208
+ }
2209
+ }
2210
+ return out;
2211
+ }
2166
2212
  /**
2167
2213
  * Correction-coverage census at a GPS week/time — a diagnostic funnel over
2168
2214
  * the current state, explaining how many masked satellites are actually
@@ -599,6 +599,25 @@ interface SbasIonoDelay {
599
599
  /** Variance (m²). */
600
600
  varM2: number;
601
601
  }
602
+ /** One ionospheric grid point (IGP) of the SBAS grid — its location, the
603
+ * broadcast vertical delay and its GIVE (grid ionospheric vertical error).
604
+ * For visualising the SBAS ionosphere (MT18 mask + MT26 delays). */
605
+ interface SbasIgp {
606
+ /** IGP geodetic latitude (deg). */
607
+ latDeg: number;
608
+ /** IGP geodetic longitude (deg, −180..180). */
609
+ lonDeg: number;
610
+ /** SBAS band index (0..10) the point belongs to. */
611
+ band: number;
612
+ /** Broadcast vertical L1 ionospheric delay (m). */
613
+ delayM: number;
614
+ /** GIVEI (0..14) — the broadcast grid-ionospheric-vertical-error indicator. */
615
+ givei: number;
616
+ /** GIVE — the 99.9% vertical-error bound (m), DO-229D Table A-17. */
617
+ giveMeters: number;
618
+ /** Age of the delay estimate (s) at the query epoch. */
619
+ ageSec: number;
620
+ }
602
621
  declare class SbasProcessor {
603
622
  private sats;
604
623
  private satIdx;
@@ -640,6 +659,14 @@ declare class SbasProcessor {
640
659
  activeSats(): string[];
641
660
  /** Number of ionospheric grid points with a valid delay across all bands. */
642
661
  ionoGridPoints(): number;
662
+ /**
663
+ * The current ionospheric grid — every IGP that carries a valid broadcast
664
+ * vertical delay (MT18 mask populated by MT26 delays), across all bands, with
665
+ * its GIVE (DO-229D Table A-17). For visualising the SBAS ionosphere; the
666
+ * count matches {@link ionoGridPoints}. `week`/`tow` set the reference epoch
667
+ * for each point's `ageSec` (the same argument the solver passes).
668
+ */
669
+ ionoGrid(week: number, tow: number): SbasIgp[];
643
670
  /**
644
671
  * Correction-coverage census at a GPS week/time — a diagnostic funnel over
645
672
  * the current state, explaining how many masked satellites are actually
@@ -1381,4 +1408,4 @@ declare function sbasProtectionLevels(sats: readonly {
1381
1408
  */
1382
1409
  declare function solveSpp(pseudoranges: Map<string, number>, ephemerides: Map<string, Ephemeris>, timeMs: number, opts?: SppOptions): SppSolution | null;
1383
1410
 
1384
- export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, type Degradation, type DgnssOptions, type DgnssSolution, type EphemerisSource, type FixedPositionResult, IONO_L1_M_PER_TECU, type KlobucharCoeffs, type LambdaResult, type NetworkFcbResult, type NetworkFcbSummary, type NlArc, type NlFcbResult, type PppAntennaModel, type PppArc, type PppCorrectionConfig, type PppCorrections, type PppEpoch, type PppEpochContext, type PppEpochResult, type PppFixState, type PppOptions, type PppSatObs, type PppSolution, type RawObservation, type RtkEpochMeasurements, RtkFloatEngine, type RtkFloatOptions, type RtkFloatSolution, type RtkMeasurement, type RtkObsEpoch, type RtkObsInput, type RtkPostProcessOptions, type RtkPostProcessResult, type RtkTrackPoint, type SatGeom, type SbasCorrectionSource, type SbasIonoDelay, SbasProcessor, type SbasSatCorrection, type SppOptions, type SppSolution, type TropoMapping, type WlArc, type WlFcbOptions, type WlFcbResult, type WlObs, buildPppAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, fixPppPosition, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, postProcessRtk, resolvePppAmbiguities, satClockCorrection, sbasIonoDeg, sbasLongTermDeg, sbasProtectionLevels, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
1411
+ export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, type Degradation, type DgnssOptions, type DgnssSolution, type EphemerisSource, type FixedPositionResult, IONO_L1_M_PER_TECU, type KlobucharCoeffs, type LambdaResult, type NetworkFcbResult, type NetworkFcbSummary, type NlArc, type NlFcbResult, type PppAntennaModel, type PppArc, type PppCorrectionConfig, type PppCorrections, type PppEpoch, type PppEpochContext, type PppEpochResult, type PppFixState, type PppOptions, type PppSatObs, type PppSolution, type RawObservation, type RtkEpochMeasurements, RtkFloatEngine, type RtkFloatOptions, type RtkFloatSolution, type RtkMeasurement, type RtkObsEpoch, type RtkObsInput, type RtkPostProcessOptions, type RtkPostProcessResult, type RtkTrackPoint, type SatGeom, type SbasCorrectionSource, type SbasIgp, type SbasIonoDelay, SbasProcessor, type SbasSatCorrection, type SppOptions, type SppSolution, type TropoMapping, type WlArc, type WlFcbOptions, type WlFcbResult, type WlObs, buildPppAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, fixPppPosition, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, postProcessRtk, resolvePppAmbiguities, satClockCorrection, sbasIonoDeg, sbasLongTermDeg, sbasProtectionLevels, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
@@ -599,6 +599,25 @@ interface SbasIonoDelay {
599
599
  /** Variance (m²). */
600
600
  varM2: number;
601
601
  }
602
+ /** One ionospheric grid point (IGP) of the SBAS grid — its location, the
603
+ * broadcast vertical delay and its GIVE (grid ionospheric vertical error).
604
+ * For visualising the SBAS ionosphere (MT18 mask + MT26 delays). */
605
+ interface SbasIgp {
606
+ /** IGP geodetic latitude (deg). */
607
+ latDeg: number;
608
+ /** IGP geodetic longitude (deg, −180..180). */
609
+ lonDeg: number;
610
+ /** SBAS band index (0..10) the point belongs to. */
611
+ band: number;
612
+ /** Broadcast vertical L1 ionospheric delay (m). */
613
+ delayM: number;
614
+ /** GIVEI (0..14) — the broadcast grid-ionospheric-vertical-error indicator. */
615
+ givei: number;
616
+ /** GIVE — the 99.9% vertical-error bound (m), DO-229D Table A-17. */
617
+ giveMeters: number;
618
+ /** Age of the delay estimate (s) at the query epoch. */
619
+ ageSec: number;
620
+ }
602
621
  declare class SbasProcessor {
603
622
  private sats;
604
623
  private satIdx;
@@ -640,6 +659,14 @@ declare class SbasProcessor {
640
659
  activeSats(): string[];
641
660
  /** Number of ionospheric grid points with a valid delay across all bands. */
642
661
  ionoGridPoints(): number;
662
+ /**
663
+ * The current ionospheric grid — every IGP that carries a valid broadcast
664
+ * vertical delay (MT18 mask populated by MT26 delays), across all bands, with
665
+ * its GIVE (DO-229D Table A-17). For visualising the SBAS ionosphere; the
666
+ * count matches {@link ionoGridPoints}. `week`/`tow` set the reference epoch
667
+ * for each point's `ageSec` (the same argument the solver passes).
668
+ */
669
+ ionoGrid(week: number, tow: number): SbasIgp[];
643
670
  /**
644
671
  * Correction-coverage census at a GPS week/time — a diagnostic funnel over
645
672
  * the current state, explaining how many masked satellites are actually
@@ -1381,4 +1408,4 @@ declare function sbasProtectionLevels(sats: readonly {
1381
1408
  */
1382
1409
  declare function solveSpp(pseudoranges: Map<string, number>, ephemerides: Map<string, Ephemeris>, timeMs: number, opts?: SppOptions): SppSolution | null;
1383
1410
 
1384
- export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, type Degradation, type DgnssOptions, type DgnssSolution, type EphemerisSource, type FixedPositionResult, IONO_L1_M_PER_TECU, type KlobucharCoeffs, type LambdaResult, type NetworkFcbResult, type NetworkFcbSummary, type NlArc, type NlFcbResult, type PppAntennaModel, type PppArc, type PppCorrectionConfig, type PppCorrections, type PppEpoch, type PppEpochContext, type PppEpochResult, type PppFixState, type PppOptions, type PppSatObs, type PppSolution, type RawObservation, type RtkEpochMeasurements, RtkFloatEngine, type RtkFloatOptions, type RtkFloatSolution, type RtkMeasurement, type RtkObsEpoch, type RtkObsInput, type RtkPostProcessOptions, type RtkPostProcessResult, type RtkTrackPoint, type SatGeom, type SbasCorrectionSource, type SbasIonoDelay, SbasProcessor, type SbasSatCorrection, type SppOptions, type SppSolution, type TropoMapping, type WlArc, type WlFcbOptions, type WlFcbResult, type WlObs, buildPppAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, fixPppPosition, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, postProcessRtk, resolvePppAmbiguities, satClockCorrection, sbasIonoDeg, sbasLongTermDeg, sbasProtectionLevels, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
1411
+ export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, type Degradation, type DgnssOptions, type DgnssSolution, type EphemerisSource, type FixedPositionResult, IONO_L1_M_PER_TECU, type KlobucharCoeffs, type LambdaResult, type NetworkFcbResult, type NetworkFcbSummary, type NlArc, type NlFcbResult, type PppAntennaModel, type PppArc, type PppCorrectionConfig, type PppCorrections, type PppEpoch, type PppEpochContext, type PppEpochResult, type PppFixState, type PppOptions, type PppSatObs, type PppSolution, type RawObservation, type RtkEpochMeasurements, RtkFloatEngine, type RtkFloatOptions, type RtkFloatSolution, type RtkMeasurement, type RtkObsEpoch, type RtkObsInput, type RtkPostProcessOptions, type RtkPostProcessResult, type RtkTrackPoint, type SatGeom, type SbasCorrectionSource, type SbasIgp, type SbasIonoDelay, SbasProcessor, type SbasSatCorrection, type SppOptions, type SppSolution, type TropoMapping, type WlArc, type WlFcbOptions, type WlFcbResult, type WlObs, buildPppAntenna, createPppCorrections, estimateNarrowlaneFcb, estimateNetworkFcbs, estimateWidelaneFcb, extractWidelaneArcs, fixPppPosition, gimSlantIonoDelayL1, gimVerticalTec, gmst, ionoFree, klobucharDelay, lambdaReduction, lambdaSearch, moonEcef, niellMapping, nlWavelength, postProcessRtk, resolvePppAmbiguities, satClockCorrection, sbasIonoDeg, sbasLongTermDeg, sbasProtectionLevels, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
@@ -32,7 +32,7 @@ import {
32
32
  sunEcef,
33
33
  toRtkEpoch,
34
34
  wlWavelength
35
- } from "./chunk-GWN2F3PQ.js";
35
+ } from "./chunk-TWAC2BZF.js";
36
36
  import "./chunk-WQX354KD.js";
37
37
  import "./chunk-MHGNKSSH.js";
38
38
  import "./chunk-MIIM4LDY.js";
package/dist/rtcm3.cjs CHANGED
@@ -26,6 +26,7 @@ __export(rtcm3_exports, {
26
26
  createStationMeta: () => createStationMeta,
27
27
  createStreamStats: () => createStreamStats,
28
28
  decodeEphemeris: () => decodeEphemeris,
29
+ decodeLegacyObs: () => decodeLegacyObs,
29
30
  decodeMsmFull: () => decodeMsmFull,
30
31
  msmEpochToDate: () => msmEpochToDate,
31
32
  readString: () => readString,
@@ -587,6 +588,145 @@ function decodeEphemeris(frame) {
587
588
  }
588
589
  }
589
590
 
591
+ // src/constants/gnss.ts
592
+ var C_LIGHT = 299792458;
593
+ var FREQ = {
594
+ G: { "1": 157542e4, "2": 12276e5, "5": 117645e4 },
595
+ // R bands 4/6 are the CDMA L1OC/L2OC center frequencies
596
+ R: { "3": 1202025e3, "4": 1600995e3, "6": 124806e4 },
597
+ E: {
598
+ "1": 157542e4,
599
+ "5": 117645e4,
600
+ "6": 127875e4,
601
+ "7": 120714e4,
602
+ "8": 1191795e3
603
+ },
604
+ C: {
605
+ "1": 157542e4,
606
+ "2": 1561098e3,
607
+ "5": 117645e4,
608
+ "6": 126852e4,
609
+ "7": 120714e4
610
+ },
611
+ J: { "1": 157542e4, "2": 12276e5, "5": 117645e4, "6": 127875e4 },
612
+ I: { "5": 117645e4, "9": 2492028e3 },
613
+ S: { "1": 157542e4, "5": 117645e4 }
614
+ };
615
+ var GLO_F1_BASE = 1602e6;
616
+ var GLO_F1_STEP = 562500;
617
+ var GLO_F2_BASE = 1246e6;
618
+ var GLO_F2_STEP = 437500;
619
+
620
+ // src/rtcm3/legacy-obs.ts
621
+ var PRUNIT_GPS = 299792.458;
622
+ var PRUNIT_GLO = 599584.916;
623
+ var LAM_GPS_L1 = C_LIGHT / 157542e4;
624
+ var LAM_GPS_L2 = C_LIGHT / 12276e5;
625
+ var PPR_INVALID = -(2 ** 19);
626
+ var PR21_INVALID = -(2 ** 13);
627
+ function legacyLockSec(i) {
628
+ if (i < 24) return i;
629
+ if (i < 48) return 2 * i - 24;
630
+ if (i < 72) return 4 * i - 120;
631
+ if (i < 96) return 8 * i - 408;
632
+ if (i < 120) return 16 * i - 1176;
633
+ if (i < 127) return 32 * i - 3096;
634
+ return 937;
635
+ }
636
+ var two = (n) => n.toString().padStart(2, "0");
637
+ function decodeLegacyObs(frame) {
638
+ const type = frame.messageType;
639
+ const gps = type >= 1001 && type <= 1004;
640
+ const glo = type >= 1009 && type <= 1012;
641
+ if (!gps && !glo) return null;
642
+ const ext = type === 1002 || type === 1004 || type === 1010 || type === 1012;
643
+ const dual = type === 1003 || type === 1004 || type === 1011 || type === 1012;
644
+ const system = gps ? "G" : "R";
645
+ const r = new BitReader(frame.payload);
646
+ r.readU(12);
647
+ r.readU(12);
648
+ let epochMs;
649
+ let nsat;
650
+ if (gps) {
651
+ epochMs = r.readU(30);
652
+ r.readU(1);
653
+ nsat = r.readU(5);
654
+ r.readU(1);
655
+ r.readU(3);
656
+ } else {
657
+ const tk = r.readU(27);
658
+ r.readU(1);
659
+ nsat = r.readU(5);
660
+ r.readU(1);
661
+ r.readU(3);
662
+ const gloDow = new Date(Date.now() + 3 * 36e5).getUTCDay();
663
+ epochMs = (gloDow << 27 | tk) >>> 0;
664
+ }
665
+ const observations = [];
666
+ for (let s = 0; s < nsat; s++) {
667
+ const satId = r.readU(6);
668
+ const code1 = r.readU(1);
669
+ const freqCh = glo ? r.readU(5) : 0;
670
+ const pr1raw = r.readU(gps ? 24 : 25);
671
+ const ppr1 = r.readS(20);
672
+ const lock1 = r.readU(7);
673
+ let amb = 0;
674
+ let cnr1 = 0;
675
+ if (ext) {
676
+ amb = r.readU(gps ? 8 : 7);
677
+ cnr1 = r.readU(8);
678
+ }
679
+ let code2 = 0;
680
+ let pr21 = 0;
681
+ let ppr2 = 0;
682
+ let lock2 = 0;
683
+ let cnr2 = 0;
684
+ if (dual) {
685
+ code2 = r.readU(2);
686
+ pr21 = r.readS(14);
687
+ ppr2 = r.readS(20);
688
+ lock2 = r.readU(7);
689
+ if (ext) cnr2 = r.readU(8);
690
+ }
691
+ if (gps && (satId < 1 || satId > 32)) continue;
692
+ if (glo && (satId < 1 || satId > 24)) continue;
693
+ const prunit = gps ? PRUNIT_GPS : PRUNIT_GLO;
694
+ const pr1 = pr1raw * 0.02 + amb * prunit;
695
+ const k = freqCh - 7;
696
+ const lamL1 = gps ? LAM_GPS_L1 : C_LIGHT / (GLO_F1_BASE + k * GLO_F1_STEP);
697
+ const lamL2 = gps ? LAM_GPS_L2 : C_LIGHT / (GLO_F2_BASE + k * GLO_F2_STEP);
698
+ const signals = [];
699
+ {
700
+ const sig = {
701
+ rinexCode: gps ? code1 ? "1W" : "1C" : code1 ? "1P" : "1C",
702
+ pseudorange: pr1,
703
+ wavelength: lamL1,
704
+ lockTime: legacyLockSec(lock1)
705
+ };
706
+ if (ppr1 !== PPR_INVALID) sig.phase = (pr1 + ppr1 * 5e-4) / lamL1;
707
+ if (ext && cnr1 > 0) sig.cn0 = cnr1 * 0.25;
708
+ signals.push(sig);
709
+ }
710
+ if (dual) {
711
+ const sig = {
712
+ rinexCode: gps ? code2 === 0 ? "2X" : "2W" : code2 === 0 ? "2C" : "2P",
713
+ wavelength: lamL2,
714
+ lockTime: legacyLockSec(lock2)
715
+ };
716
+ if (pr21 !== PR21_INVALID) sig.pseudorange = pr1 + pr21 * 0.02;
717
+ if (ppr2 !== PPR_INVALID) sig.phase = (pr1 + ppr2 * 5e-4) / lamL2;
718
+ if (ext && cnr2 > 0) sig.cn0 = cnr2 * 0.25;
719
+ signals.push(sig);
720
+ }
721
+ observations.push({
722
+ prn: `${system}${two(satId)}`,
723
+ system,
724
+ signals
725
+ });
726
+ }
727
+ return { messageType: type, epochMs, system, observations };
728
+ }
729
+
590
730
  // src/constants/time.ts
591
731
  var MILLISECONDS_IN_WEEK = 6048e5;
592
732
  var MILLISECONDS_IN_SECOND = 1e3;
@@ -677,35 +817,6 @@ function getGpsLeap(date) {
677
817
  return leap_seconds - 19;
678
818
  }
679
819
 
680
- // src/constants/gnss.ts
681
- var C_LIGHT = 299792458;
682
- var FREQ = {
683
- G: { "1": 157542e4, "2": 12276e5, "5": 117645e4 },
684
- // R bands 4/6 are the CDMA L1OC/L2OC center frequencies
685
- R: { "3": 1202025e3, "4": 1600995e3, "6": 124806e4 },
686
- E: {
687
- "1": 157542e4,
688
- "5": 117645e4,
689
- "6": 127875e4,
690
- "7": 120714e4,
691
- "8": 1191795e3
692
- },
693
- C: {
694
- "1": 157542e4,
695
- "2": 1561098e3,
696
- "5": 117645e4,
697
- "6": 126852e4,
698
- "7": 120714e4
699
- },
700
- J: { "1": 157542e4, "2": 12276e5, "5": 117645e4, "6": 127875e4 },
701
- I: { "5": 117645e4, "9": 2492028e3 },
702
- S: { "1": 157542e4, "5": 117645e4 }
703
- };
704
- var GLO_F1_BASE = 1602e6;
705
- var GLO_F1_STEP = 562500;
706
- var GLO_F2_BASE = 1246e6;
707
- var GLO_F2_STEP = 437500;
708
-
709
820
  // src/rtcm3/msm.ts
710
821
  var GPS_L1 = FREQ.G["1"];
711
822
  var GPS_L2 = FREQ.G["2"];
@@ -1590,6 +1701,7 @@ function updateStreamStats(stats, frames, rawBytes) {
1590
1701
  createStationMeta,
1591
1702
  createStreamStats,
1592
1703
  decodeEphemeris,
1704
+ decodeLegacyObs,
1593
1705
  decodeMsmFull,
1594
1706
  msmEpochToDate,
1595
1707
  readString,
package/dist/rtcm3.d.cts CHANGED
@@ -82,6 +82,12 @@ declare function setGloFreqNumber(slot: number, k: number): void;
82
82
  */
83
83
  declare function resetGloFreqCache(): void;
84
84
 
85
+ /**
86
+ * Decode a legacy RTCM3 observation frame (1001–1004 GPS, 1009–1012 GLONASS)
87
+ * into an {@link MsmEpoch}, or null for any other message type.
88
+ */
89
+ declare function decodeLegacyObs(frame: Rtcm3Frame): MsmEpoch | null;
90
+
85
91
  /**
86
92
  * RTCM3 station metadata decoders (messages 1005/1006, 1007/1008, 1029, 1033).
87
93
  */
@@ -154,4 +160,4 @@ declare function rtcm3Constellation(msgType: number): string | null;
154
160
  declare function createStreamStats(): StreamStats;
155
161
  declare function updateStreamStats(stats: StreamStats, frames: Rtcm3Frame[], rawBytes: number): void;
156
162
 
157
- export { EphemerisInfo, type MessageTypeStats, type MsmEpoch, type MsmSatObs, type MsmSignal, RTCM3_MESSAGE_NAMES, Rtcm3Frame, type SatCn0, type SignalCn0, type StationMeta, type StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats };
163
+ export { EphemerisInfo, type MessageTypeStats, type MsmEpoch, type MsmSatObs, type MsmSignal, RTCM3_MESSAGE_NAMES, Rtcm3Frame, type SatCn0, type SignalCn0, type StationMeta, type StreamStats, createStationMeta, createStreamStats, decodeLegacyObs, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats };
package/dist/rtcm3.d.ts CHANGED
@@ -82,6 +82,12 @@ declare function setGloFreqNumber(slot: number, k: number): void;
82
82
  */
83
83
  declare function resetGloFreqCache(): void;
84
84
 
85
+ /**
86
+ * Decode a legacy RTCM3 observation frame (1001–1004 GPS, 1009–1012 GLONASS)
87
+ * into an {@link MsmEpoch}, or null for any other message type.
88
+ */
89
+ declare function decodeLegacyObs(frame: Rtcm3Frame): MsmEpoch | null;
90
+
85
91
  /**
86
92
  * RTCM3 station metadata decoders (messages 1005/1006, 1007/1008, 1029, 1033).
87
93
  */
@@ -154,4 +160,4 @@ declare function rtcm3Constellation(msgType: number): string | null;
154
160
  declare function createStreamStats(): StreamStats;
155
161
  declare function updateStreamStats(stats: StreamStats, frames: Rtcm3Frame[], rawBytes: number): void;
156
162
 
157
- export { EphemerisInfo, type MessageTypeStats, type MsmEpoch, type MsmSatObs, type MsmSignal, RTCM3_MESSAGE_NAMES, Rtcm3Frame, type SatCn0, type SignalCn0, type StationMeta, type StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats };
163
+ export { EphemerisInfo, type MessageTypeStats, type MsmEpoch, type MsmSatObs, type MsmSignal, RTCM3_MESSAGE_NAMES, Rtcm3Frame, type SatCn0, type SignalCn0, type StationMeta, type StreamStats, createStationMeta, createStreamStats, decodeLegacyObs, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats };
package/dist/rtcm3.js CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  createStationMeta,
6
6
  createStreamStats,
7
7
  decodeEphemeris,
8
+ decodeLegacyObs,
8
9
  decodeMsmFull,
9
10
  msmEpochToDate,
10
11
  readString,
@@ -15,7 +16,7 @@ import {
15
16
  setRtcm3DebugHandler,
16
17
  updateStationMeta,
17
18
  updateStreamStats
18
- } from "./chunk-BRT6XZ7B.js";
19
+ } from "./chunk-QN7Q2ALS.js";
19
20
  import "./chunk-HVXYFUCB.js";
20
21
  import "./chunk-LEEU5OIO.js";
21
22
  import "./chunk-FIEWO4J4.js";
@@ -26,6 +27,7 @@ export {
26
27
  createStationMeta,
27
28
  createStreamStats,
28
29
  decodeEphemeris,
30
+ decodeLegacyObs,
29
31
  decodeMsmFull,
30
32
  msmEpochToDate,
31
33
  readString,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gnss-js",
3
- "version": "1.61.0",
3
+ "version": "1.63.0",
4
4
  "description": "Comprehensive GNSS library for JavaScript — time scales, coordinates, RINEX parsing, RTCM3 decoding, orbit computation, and signal analysis",
5
5
  "type": "module",
6
6
  "sideEffects": false,