gnss-js 1.50.0 → 1.51.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.
@@ -705,7 +705,7 @@ function parseSbfGloNav(data) {
705
705
  }
706
706
 
707
707
  // src/sbf/rawnav-sbas.ts
708
- function feedGeoBlock(view, b) {
708
+ function feedGeoBlock(view, b, onSbasMessage) {
709
709
  const tow = view.getUint32(b + 8, true);
710
710
  const wnc = view.getUint16(b + 12, true);
711
711
  const svid = view.getUint8(b + 14);
@@ -721,10 +721,11 @@ function feedGeoBlock(view, b) {
721
721
  }
722
722
  if (!sbasCrcOk(msg)) return { badCrc: true };
723
723
  const prn = Number(prnStr.slice(1)) + 100;
724
+ onSbasMessage?.(msg, prn, wnc, tow / 1e3);
724
725
  const eph = decodeSbasGeoNav(msg, prn, wnc, tow / 1e3);
725
726
  return eph ? { eph } : {};
726
727
  }
727
- function parseSbfGeoNav(data) {
728
+ function parseSbfGeoNav(data, opts = {}) {
728
729
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
729
730
  const ephemerides = [];
730
731
  const seen = /* @__PURE__ */ new Set();
@@ -733,7 +734,7 @@ function parseSbfGeoNav(data) {
733
734
  scanSbfFrames(data, view, (id, b, len) => {
734
735
  if (id !== 4020 || len < 52) return;
735
736
  messages++;
736
- const r = feedGeoBlock(view, b);
737
+ const r = feedGeoBlock(view, b, opts.onSbasMessage);
737
738
  if (r.eph) {
738
739
  const key = `${r.eph.prn}|${r.eph.tocDate.getTime()}`;
739
740
  if (!seen.has(key)) {
@@ -753,7 +754,7 @@ function ephKey(e) {
753
754
  const source = "source" in e ? e.source : "";
754
755
  return `${e.prn}|${e.tocDate.getTime()}|${source}`;
755
756
  }
756
- function decodeSbfNavigation(data) {
757
+ function decodeSbfNavigation(data, opts = {}) {
757
758
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
758
759
  const ephemerides = [];
759
760
  const seen = /* @__PURE__ */ new Set();
@@ -874,7 +875,7 @@ function decodeSbfNavigation(data) {
874
875
  case 4020: {
875
876
  if (len < 52) return;
876
877
  counts.sbasRaw++;
877
- const r = feedGeoBlock(view, b);
878
+ const r = feedGeoBlock(view, b, opts.onSbasMessage);
878
879
  if (r.eph) addEph(r.eph);
879
880
  else if (r.badCrc) counts.badFrames++;
880
881
  return;
@@ -3074,9 +3074,11 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
3074
3074
  convergenceM = 1e-4,
3075
3075
  tgd = true,
3076
3076
  iono,
3077
- gim
3077
+ gim,
3078
+ sbas
3078
3079
  } = opts;
3079
3080
  const gpsTow = (timeMs - GPS_EPOCH_MS_SPP) / 1e3 % 604800;
3081
+ const gpsWeek = Math.floor((timeMs - GPS_EPOCH_MS_SPP) / 1e3 / 604800);
3080
3082
  const all = [...pseudoranges.keys()].filter((p) => ephemerides.has(p));
3081
3083
  const minSats = (list) => 3 + new Set(list.map((p) => p[0])).size;
3082
3084
  if (all.length < minSats(all)) return null;
@@ -3113,7 +3115,16 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
3113
3115
  const sat = computeSatPosition(eph, tTx - dtsClock * 1e3);
3114
3116
  if (!Number.isFinite(sat.x)) continue;
3115
3117
  const isKepler = eph.system !== "R" && eph.system !== "S";
3116
- const dts = dtsClock - (tgd && isKepler ? eph.tgd : 0);
3118
+ let dts = dtsClock - (tgd && isKepler ? eph.tgd : 0);
3119
+ if (sbas) {
3120
+ const sc = sbas.satCorrection(prn, gpsWeek, gpsTow);
3121
+ if (sc) {
3122
+ sat.x += sc.dPos[0];
3123
+ sat.y += sc.dPos[1];
3124
+ sat.z += sc.dPos[2];
3125
+ dts += sc.dClkS;
3126
+ }
3127
+ }
3117
3128
  const travel = Math.hypot(sat.x - x9, sat.y - y2, sat.z - z2) / C_LIGHT;
3118
3129
  const [sx, sy, sz] = sagnac2(sat, travel);
3119
3130
  const rho = Math.hypot(sx - x9, sy - y2, sz - z2);
@@ -3134,9 +3145,21 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
3134
3145
  }
3135
3146
  const tropo = troposphere && positionSane ? tropoDelay2(elev, rxLat, rxHgt) : 0;
3136
3147
  let ionoM = 0;
3137
- if ((gim || iono) && positionSane) {
3148
+ if ((sbas || gim || iono) && positionSane) {
3138
3149
  let l1M = null;
3139
- if (gim)
3150
+ if (sbas) {
3151
+ const si = sbas.ionoDelay(
3152
+ gpsWeek,
3153
+ gpsTow,
3154
+ rxLat,
3155
+ rxLon,
3156
+ rxHgt,
3157
+ azim,
3158
+ elev
3159
+ );
3160
+ if (si) l1M = si.delayM;
3161
+ }
3162
+ if (l1M === null && gim)
3140
3163
  l1M = gimSlantIonoDelayL1(gim, rxLat, rxLon, azim, elev, timeMs);
3141
3164
  if (l1M === null && iono) {
3142
3165
  l1M = C_LIGHT * klobucharDelay(iono, rxLat, rxLon, azim, elev, gpsTow);
@@ -261,7 +261,7 @@ function decodeGpsQzssEphemeris(view, p, sys) {
261
261
  tgd: view.getFloat64(p + 172, true)
262
262
  };
263
263
  }
264
- function parseNovatelNav(data) {
264
+ function parseNovatelNav(data, opts = {}) {
265
265
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
266
266
  const stats = { badCrc: 0 };
267
267
  const ephemerides = [];
@@ -334,6 +334,7 @@ function parseNovatelNav(data) {
334
334
  const prn = view.getUint32(p + 4, true);
335
335
  const msg = new Uint8Array(32);
336
336
  msg.set(data.subarray(p + 12, p + 41));
337
+ opts.onSbasMessage?.(msg, prn, frame.week, frame.towMs / 1e3);
337
338
  const eph = decodeSbasGeoNav(msg, prn, frame.week, frame.towMs / 1e3);
338
339
  if (!eph) continue;
339
340
  const prev = lastGlo.get(eph.prn);
package/dist/index.cjs CHANGED
@@ -7727,7 +7727,7 @@ function parseSbfGloNav(data) {
7727
7727
  }
7728
7728
 
7729
7729
  // src/sbf/rawnav-sbas.ts
7730
- function feedGeoBlock(view, b) {
7730
+ function feedGeoBlock(view, b, onSbasMessage) {
7731
7731
  const tow = view.getUint32(b + 8, true);
7732
7732
  const wnc = view.getUint16(b + 12, true);
7733
7733
  const svid = view.getUint8(b + 14);
@@ -7743,10 +7743,11 @@ function feedGeoBlock(view, b) {
7743
7743
  }
7744
7744
  if (!sbasCrcOk(msg)) return { badCrc: true };
7745
7745
  const prn = Number(prnStr.slice(1)) + 100;
7746
+ onSbasMessage?.(msg, prn, wnc, tow / 1e3);
7746
7747
  const eph = decodeSbasGeoNav(msg, prn, wnc, tow / 1e3);
7747
7748
  return eph ? { eph } : {};
7748
7749
  }
7749
- function parseSbfGeoNav(data) {
7750
+ function parseSbfGeoNav(data, opts = {}) {
7750
7751
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
7751
7752
  const ephemerides = [];
7752
7753
  const seen = /* @__PURE__ */ new Set();
@@ -7755,7 +7756,7 @@ function parseSbfGeoNav(data) {
7755
7756
  scanSbfFrames(data, view, (id, b, len) => {
7756
7757
  if (id !== 4020 || len < 52) return;
7757
7758
  messages++;
7758
- const r = feedGeoBlock(view, b);
7759
+ const r = feedGeoBlock(view, b, opts.onSbasMessage);
7759
7760
  if (r.eph) {
7760
7761
  const key = `${r.eph.prn}|${r.eph.tocDate.getTime()}`;
7761
7762
  if (!seen.has(key)) {
@@ -7775,7 +7776,7 @@ function ephKey(e) {
7775
7776
  const source = "source" in e ? e.source : "";
7776
7777
  return `${e.prn}|${e.tocDate.getTime()}|${source}`;
7777
7778
  }
7778
- function decodeSbfNavigation(data) {
7779
+ function decodeSbfNavigation(data, opts = {}) {
7779
7780
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
7780
7781
  const ephemerides = [];
7781
7782
  const seen = /* @__PURE__ */ new Set();
@@ -7896,7 +7897,7 @@ function decodeSbfNavigation(data) {
7896
7897
  case 4020: {
7897
7898
  if (len < 52) return;
7898
7899
  counts.sbasRaw++;
7899
- const r = feedGeoBlock(view, b);
7900
+ const r = feedGeoBlock(view, b, opts.onSbasMessage);
7900
7901
  if (r.eph) addEph(r.eph);
7901
7902
  else if (r.badCrc) counts.badFrames++;
7902
7903
  return;
@@ -9368,7 +9369,7 @@ function decodeGpsQzssEphemeris(view, p, sys) {
9368
9369
  tgd: view.getFloat64(p + 172, true)
9369
9370
  };
9370
9371
  }
9371
- function parseNovatelNav(data) {
9372
+ function parseNovatelNav(data, opts = {}) {
9372
9373
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
9373
9374
  const stats = { badCrc: 0 };
9374
9375
  const ephemerides = [];
@@ -9441,6 +9442,7 @@ function parseNovatelNav(data) {
9441
9442
  const prn = view.getUint32(p + 4, true);
9442
9443
  const msg = new Uint8Array(32);
9443
9444
  msg.set(data.subarray(p + 12, p + 41));
9445
+ opts.onSbasMessage?.(msg, prn, frame.week, frame.towMs / 1e3);
9444
9446
  const eph = decodeSbasGeoNav(msg, prn, frame.week, frame.towMs / 1e3);
9445
9447
  if (!eph) continue;
9446
9448
  const prev = lastGlo.get(eph.prn);
@@ -15002,9 +15004,11 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
15002
15004
  convergenceM = 1e-4,
15003
15005
  tgd = true,
15004
15006
  iono,
15005
- gim
15007
+ gim,
15008
+ sbas
15006
15009
  } = opts;
15007
15010
  const gpsTow = (timeMs - GPS_EPOCH_MS_SPP) / 1e3 % 604800;
15011
+ const gpsWeek = Math.floor((timeMs - GPS_EPOCH_MS_SPP) / 1e3 / 604800);
15008
15012
  const all = [...pseudoranges.keys()].filter((p) => ephemerides.has(p));
15009
15013
  const minSats = (list) => 3 + new Set(list.map((p) => p[0])).size;
15010
15014
  if (all.length < minSats(all)) return null;
@@ -15041,7 +15045,16 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
15041
15045
  const sat = computeSatPosition(eph, tTx - dtsClock * 1e3);
15042
15046
  if (!Number.isFinite(sat.x)) continue;
15043
15047
  const isKepler3 = eph.system !== "R" && eph.system !== "S";
15044
- const dts = dtsClock - (tgd && isKepler3 ? eph.tgd : 0);
15048
+ let dts = dtsClock - (tgd && isKepler3 ? eph.tgd : 0);
15049
+ if (sbas) {
15050
+ const sc = sbas.satCorrection(prn, gpsWeek, gpsTow);
15051
+ if (sc) {
15052
+ sat.x += sc.dPos[0];
15053
+ sat.y += sc.dPos[1];
15054
+ sat.z += sc.dPos[2];
15055
+ dts += sc.dClkS;
15056
+ }
15057
+ }
15045
15058
  const travel = Math.hypot(sat.x - x9, sat.y - y2, sat.z - z2) / C_LIGHT;
15046
15059
  const [sx, sy, sz] = sagnac2(sat, travel);
15047
15060
  const rho = Math.hypot(sx - x9, sy - y2, sz - z2);
@@ -15062,9 +15075,21 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
15062
15075
  }
15063
15076
  const tropo = troposphere && positionSane ? tropoDelay2(elev, rxLat, rxHgt) : 0;
15064
15077
  let ionoM = 0;
15065
- if ((gim || iono) && positionSane) {
15078
+ if ((sbas || gim || iono) && positionSane) {
15066
15079
  let l1M = null;
15067
- if (gim)
15080
+ if (sbas) {
15081
+ const si = sbas.ionoDelay(
15082
+ gpsWeek,
15083
+ gpsTow,
15084
+ rxLat,
15085
+ rxLon,
15086
+ rxHgt,
15087
+ azim,
15088
+ elev
15089
+ );
15090
+ if (si) l1M = si.delayM;
15091
+ }
15092
+ if (l1M === null && gim)
15068
15093
  l1M = gimSlantIonoDelayL1(gim, rxLat, rxLon, azim, elev, timeMs);
15069
15094
  if (l1M === null && iono) {
15070
15095
  l1M = C_LIGHT * klobucharDelay(iono, rxLat, rxLon, azim, elev, gpsTow);
package/dist/index.d.cts CHANGED
@@ -17,7 +17,7 @@ export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, Trimb
17
17
  export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.cjs';
18
18
  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';
19
19
  export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.cjs';
20
- export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, 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, 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, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.cjs';
20
+ export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, 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, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.cjs';
21
21
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.cjs';
22
22
  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';
23
23
  export { AntennaEntry, AntexFile, FrequencyData, frequencyLabel, parseAntex } from './antex.cjs';
package/dist/index.d.ts CHANGED
@@ -17,7 +17,7 @@ export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, Trimb
17
17
  export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.js';
18
18
  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';
19
19
  export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.js';
20
- export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, 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, 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, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.js';
20
+ export { AntennaOffset, ArFixedSat, ArOptions, ArResult, ArSat, CorrectionResult, 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, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength } from './positioning.js';
21
21
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.js';
22
22
  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';
23
23
  export { AntennaEntry, AntexFile, FrequencyData, frequencyLabel, parseAntex } from './antex.js';
package/dist/index.js CHANGED
@@ -68,7 +68,7 @@ import {
68
68
  parseSbfNav,
69
69
  parseSbfReceiverSetup,
70
70
  scanSbfFrames
71
- } from "./chunk-XFPDTGSV.js";
71
+ } from "./chunk-DE5IUULR.js";
72
72
  import "./chunk-FA2UTLEQ.js";
73
73
  import {
74
74
  OEM4_HLEN,
@@ -76,7 +76,7 @@ import {
76
76
  oem4Frames,
77
77
  parseNovatelNav,
78
78
  parseNovatelRange
79
- } from "./chunk-2IM5JYKP.js";
79
+ } from "./chunk-ZS5RLFWI.js";
80
80
  import {
81
81
  parseTrimble,
82
82
  parseTrimbleNav,
@@ -164,7 +164,7 @@ import {
164
164
  sunEcef,
165
165
  toRtkEpoch,
166
166
  wlWavelength
167
- } from "./chunk-VYC2FRDV.js";
167
+ } from "./chunk-E3QCNJL4.js";
168
168
  import "./chunk-WQX354KD.js";
169
169
  import {
170
170
  almanacEpochMs,
package/dist/novatel.cjs CHANGED
@@ -729,7 +729,7 @@ function decodeGpsQzssEphemeris(view, p, sys) {
729
729
  tgd: view.getFloat64(p + 172, true)
730
730
  };
731
731
  }
732
- function parseNovatelNav(data) {
732
+ function parseNovatelNav(data, opts = {}) {
733
733
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
734
734
  const stats = { badCrc: 0 };
735
735
  const ephemerides = [];
@@ -802,6 +802,7 @@ function parseNovatelNav(data) {
802
802
  const prn = view.getUint32(p + 4, true);
803
803
  const msg = new Uint8Array(32);
804
804
  msg.set(data.subarray(p + 12, p + 41));
805
+ opts.onSbasMessage?.(msg, prn, frame.week, frame.towMs / 1e3);
805
806
  const eph = decodeSbasGeoNav(msg, prn, frame.week, frame.towMs / 1e3);
806
807
  if (!eph) continue;
807
808
  const prev = lastGlo.get(eph.prn);
@@ -105,7 +105,13 @@ interface NovatelNavResult {
105
105
  * Galileo by IODNav + toe + toc per data source, BeiDou by toe + toc,
106
106
  * GLONASS by reference time and health.
107
107
  */
108
- declare function parseNovatelNav(data: Uint8Array): NovatelNavResult;
108
+ declare function parseNovatelNav(data: Uint8Array, opts?: {
109
+ /** Called for each SBAS L1 message (all types) from RAWSBASFRAME. The
110
+ * frame carries 232 bits — the correction fields fit, but the inner SBAS
111
+ * CRC does not; the outer OEM4 CRC-32 guarantees the bytes. Feed an
112
+ * {@link ../positioning/sbas.SbasProcessor}. */
113
+ onSbasMessage?: (msg: Uint8Array, prn: number, week: number, tow: number) => void;
114
+ }): NovatelNavResult;
109
115
 
110
116
  /**
111
117
  * NovAtel OEM4/6/7 raw-measurement decoding (RANGE log, message 43).
package/dist/novatel.d.ts CHANGED
@@ -105,7 +105,13 @@ interface NovatelNavResult {
105
105
  * Galileo by IODNav + toe + toc per data source, BeiDou by toe + toc,
106
106
  * GLONASS by reference time and health.
107
107
  */
108
- declare function parseNovatelNav(data: Uint8Array): NovatelNavResult;
108
+ declare function parseNovatelNav(data: Uint8Array, opts?: {
109
+ /** Called for each SBAS L1 message (all types) from RAWSBASFRAME. The
110
+ * frame carries 232 bits — the correction fields fit, but the inner SBAS
111
+ * CRC does not; the outer OEM4 CRC-32 guarantees the bytes. Feed an
112
+ * {@link ../positioning/sbas.SbasProcessor}. */
113
+ onSbasMessage?: (msg: Uint8Array, prn: number, week: number, tow: number) => void;
114
+ }): NovatelNavResult;
109
115
 
110
116
  /**
111
117
  * NovAtel OEM4/6/7 raw-measurement decoding (RANGE log, message 43).
package/dist/novatel.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  oem4Frames,
5
5
  parseNovatelNav,
6
6
  parseNovatelRange
7
- } from "./chunk-2IM5JYKP.js";
7
+ } from "./chunk-ZS5RLFWI.js";
8
8
  import "./chunk-WQX354KD.js";
9
9
  import "./chunk-YUW33VXK.js";
10
10
  import "./chunk-V2D5KUKH.js";
@@ -3619,9 +3619,11 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
3619
3619
  convergenceM = 1e-4,
3620
3620
  tgd = true,
3621
3621
  iono,
3622
- gim
3622
+ gim,
3623
+ sbas
3623
3624
  } = opts;
3624
3625
  const gpsTow = (timeMs - GPS_EPOCH_MS_SPP) / 1e3 % 604800;
3626
+ const gpsWeek = Math.floor((timeMs - GPS_EPOCH_MS_SPP) / 1e3 / 604800);
3625
3627
  const all = [...pseudoranges.keys()].filter((p) => ephemerides.has(p));
3626
3628
  const minSats = (list) => 3 + new Set(list.map((p) => p[0])).size;
3627
3629
  if (all.length < minSats(all)) return null;
@@ -3658,7 +3660,16 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
3658
3660
  const sat = computeSatPosition(eph, tTx - dtsClock * 1e3);
3659
3661
  if (!Number.isFinite(sat.x)) continue;
3660
3662
  const isKepler = eph.system !== "R" && eph.system !== "S";
3661
- const dts = dtsClock - (tgd && isKepler ? eph.tgd : 0);
3663
+ let dts = dtsClock - (tgd && isKepler ? eph.tgd : 0);
3664
+ if (sbas) {
3665
+ const sc = sbas.satCorrection(prn, gpsWeek, gpsTow);
3666
+ if (sc) {
3667
+ sat.x += sc.dPos[0];
3668
+ sat.y += sc.dPos[1];
3669
+ sat.z += sc.dPos[2];
3670
+ dts += sc.dClkS;
3671
+ }
3672
+ }
3662
3673
  const travel = Math.hypot(sat.x - x9, sat.y - y2, sat.z - z2) / C_LIGHT;
3663
3674
  const [sx, sy, sz] = sagnac2(sat, travel);
3664
3675
  const rho = Math.hypot(sx - x9, sy - y2, sz - z2);
@@ -3679,9 +3690,21 @@ function solveSpp(pseudoranges, ephemerides, timeMs, opts = {}) {
3679
3690
  }
3680
3691
  const tropo = troposphere && positionSane ? tropoDelay2(elev, rxLat, rxHgt) : 0;
3681
3692
  let ionoM = 0;
3682
- if ((gim || iono) && positionSane) {
3693
+ if ((sbas || gim || iono) && positionSane) {
3683
3694
  let l1M = null;
3684
- if (gim)
3695
+ if (sbas) {
3696
+ const si = sbas.ionoDelay(
3697
+ gpsWeek,
3698
+ gpsTow,
3699
+ rxLat,
3700
+ rxLon,
3701
+ rxHgt,
3702
+ azim,
3703
+ elev
3704
+ );
3705
+ if (si) l1M = si.delayM;
3706
+ }
3707
+ if (l1M === null && gim)
3685
3708
  l1M = gimSlantIonoDelayL1(gim, rxLat, rxLon, azim, elev, timeMs);
3686
3709
  if (l1M === null && iono) {
3687
3710
  l1M = C_LIGHT * klobucharDelay(iono, rxLat, rxLon, azim, elev, gpsTow);
@@ -1223,6 +1223,28 @@ interface SppOptions {
1223
1223
  * reference the broadcast clock already matches. Default true.
1224
1224
  */
1225
1225
  tgd?: boolean;
1226
+ /**
1227
+ * SBAS wide-area corrections (WAAS/EGNOS/…). When given, each satellite in
1228
+ * the SBAS PRN mask has its position + clock adjusted by the fast/long-term
1229
+ * corrections, and — where the ionospheric pierce point is covered by the
1230
+ * SBAS grid — the SBAS slant ionosphere replaces the Klobuchar/GIM model.
1231
+ * Pass an {@link ./sbas.SbasProcessor} (or anything with these two methods).
1232
+ * Combine with single-frequency pseudoranges, not iono-free input.
1233
+ */
1234
+ sbas?: SbasCorrectionSource;
1235
+ }
1236
+ /** The two SBAS corrections `solveSpp` consumes — {@link ./sbas.SbasProcessor}
1237
+ * satisfies this structurally. */
1238
+ interface SbasCorrectionSource {
1239
+ satCorrection(prn: string, week: number, tow: number): {
1240
+ dPos: [number, number, number];
1241
+ dClkS: number;
1242
+ varM2: number;
1243
+ } | null;
1244
+ ionoDelay(week: number, tow: number, latRad: number, lonRad: number, heightM: number, azRad: number, elRad: number): {
1245
+ delayM: number;
1246
+ varM2: number;
1247
+ } | null;
1226
1248
  }
1227
1249
  interface SppSolution {
1228
1250
  /** Receiver position, ECEF meters. */
@@ -1263,4 +1285,4 @@ declare function ionoFree(p1: number, p2: number, f1: number, f2: number): numbe
1263
1285
  */
1264
1286
  declare function solveSpp(pseudoranges: Map<string, number>, ephemerides: Map<string, Ephemeris>, timeMs: number, opts?: SppOptions): SppSolution | null;
1265
1287
 
1266
- export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, 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 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, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
1288
+ export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, 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, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
@@ -1223,6 +1223,28 @@ interface SppOptions {
1223
1223
  * reference the broadcast clock already matches. Default true.
1224
1224
  */
1225
1225
  tgd?: boolean;
1226
+ /**
1227
+ * SBAS wide-area corrections (WAAS/EGNOS/…). When given, each satellite in
1228
+ * the SBAS PRN mask has its position + clock adjusted by the fast/long-term
1229
+ * corrections, and — where the ionospheric pierce point is covered by the
1230
+ * SBAS grid — the SBAS slant ionosphere replaces the Klobuchar/GIM model.
1231
+ * Pass an {@link ./sbas.SbasProcessor} (or anything with these two methods).
1232
+ * Combine with single-frequency pseudoranges, not iono-free input.
1233
+ */
1234
+ sbas?: SbasCorrectionSource;
1235
+ }
1236
+ /** The two SBAS corrections `solveSpp` consumes — {@link ./sbas.SbasProcessor}
1237
+ * satisfies this structurally. */
1238
+ interface SbasCorrectionSource {
1239
+ satCorrection(prn: string, week: number, tow: number): {
1240
+ dPos: [number, number, number];
1241
+ dClkS: number;
1242
+ varM2: number;
1243
+ } | null;
1244
+ ionoDelay(week: number, tow: number, latRad: number, lonRad: number, heightM: number, azRad: number, elRad: number): {
1245
+ delayM: number;
1246
+ varM2: number;
1247
+ } | null;
1226
1248
  }
1227
1249
  interface SppSolution {
1228
1250
  /** Receiver position, ECEF meters. */
@@ -1263,4 +1285,4 @@ declare function ionoFree(p1: number, p2: number, f1: number, f2: number): numbe
1263
1285
  */
1264
1286
  declare function solveSpp(pseudoranges: Map<string, number>, ephemerides: Map<string, Ephemeris>, timeMs: number, opts?: SppOptions): SppSolution | null;
1265
1287
 
1266
- export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, 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 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, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
1288
+ export { type AntennaOffset, type ArFixedSat, type ArOptions, type ArResult, type ArSat, type CorrectionResult, 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, solidEarthTide, solveDgnss, solvePpp, solveSpp, sunEcef, toRtkEpoch, wlWavelength };
@@ -29,7 +29,7 @@ import {
29
29
  sunEcef,
30
30
  toRtkEpoch,
31
31
  wlWavelength
32
- } from "./chunk-VYC2FRDV.js";
32
+ } from "./chunk-E3QCNJL4.js";
33
33
  import "./chunk-WQX354KD.js";
34
34
  import "./chunk-MHGNKSSH.js";
35
35
  import "./chunk-MIIM4LDY.js";
package/dist/sbf.cjs CHANGED
@@ -1981,7 +1981,7 @@ function decodeSbasGeoNav(msg, prn, week, tow) {
1981
1981
  }
1982
1982
 
1983
1983
  // src/sbf/rawnav-sbas.ts
1984
- function feedGeoBlock(view, b) {
1984
+ function feedGeoBlock(view, b, onSbasMessage) {
1985
1985
  const tow = view.getUint32(b + 8, true);
1986
1986
  const wnc = view.getUint16(b + 12, true);
1987
1987
  const svid = view.getUint8(b + 14);
@@ -1997,10 +1997,11 @@ function feedGeoBlock(view, b) {
1997
1997
  }
1998
1998
  if (!sbasCrcOk(msg)) return { badCrc: true };
1999
1999
  const prn = Number(prnStr.slice(1)) + 100;
2000
+ onSbasMessage?.(msg, prn, wnc, tow / 1e3);
2000
2001
  const eph = decodeSbasGeoNav(msg, prn, wnc, tow / 1e3);
2001
2002
  return eph ? { eph } : {};
2002
2003
  }
2003
- function parseSbfGeoNav(data) {
2004
+ function parseSbfGeoNav(data, opts = {}) {
2004
2005
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
2005
2006
  const ephemerides = [];
2006
2007
  const seen = /* @__PURE__ */ new Set();
@@ -2009,7 +2010,7 @@ function parseSbfGeoNav(data) {
2009
2010
  scanSbfFrames(data, view, (id, b, len) => {
2010
2011
  if (id !== 4020 || len < 52) return;
2011
2012
  messages++;
2012
- const r = feedGeoBlock(view, b);
2013
+ const r = feedGeoBlock(view, b, opts.onSbasMessage);
2013
2014
  if (r.eph) {
2014
2015
  const key = `${r.eph.prn}|${r.eph.tocDate.getTime()}`;
2015
2016
  if (!seen.has(key)) {
@@ -2029,7 +2030,7 @@ function ephKey(e) {
2029
2030
  const source = "source" in e ? e.source : "";
2030
2031
  return `${e.prn}|${e.tocDate.getTime()}|${source}`;
2031
2032
  }
2032
- function decodeSbfNavigation(data) {
2033
+ function decodeSbfNavigation(data, opts = {}) {
2033
2034
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
2034
2035
  const ephemerides = [];
2035
2036
  const seen = /* @__PURE__ */ new Set();
@@ -2150,7 +2151,7 @@ function decodeSbfNavigation(data) {
2150
2151
  case 4020: {
2151
2152
  if (len < 52) return;
2152
2153
  counts.sbasRaw++;
2153
- const r = feedGeoBlock(view, b);
2154
+ const r = feedGeoBlock(view, b, opts.onSbasMessage);
2154
2155
  if (r.eph) addEph(r.eph);
2155
2156
  else if (r.badCrc) counts.badFrames++;
2156
2157
  return;
package/dist/sbf.d.cts CHANGED
@@ -265,7 +265,11 @@ interface SbfNavigation {
265
265
  * F/NAV, GLONASS strings, BeiDou D1/D2, and the Klobuchar/NeQuick iono +
266
266
  * GPS-UTC leap-second blocks. See the module header for merge semantics.
267
267
  */
268
- declare function decodeSbfNavigation(data: Uint8Array): SbfNavigation;
268
+ declare function decodeSbfNavigation(data: Uint8Array, opts?: {
269
+ /** Called for every CRC-valid SBAS L1 message (all types) — feed an
270
+ * {@link ../positioning/sbas.SbasProcessor} to build SBAS corrections. */
271
+ onSbasMessage?: (msg: Uint8Array, prn: number, week: number, tow: number) => void;
272
+ }): SbfNavigation;
269
273
 
270
274
  /**
271
275
  * Septentrio SBF raw Galileo navigation-page blocks: GALRawINAV (4023)
@@ -372,7 +376,7 @@ declare function parseSbfGloNav(data: Uint8Array): SbfGloNavResult;
372
376
  * message type 9. Returns the ephemeris, `{ badCrc: true }` on a failed
373
377
  * CRC, or `{}` for any other (non–type-9) message.
374
378
  */
375
- declare function feedGeoBlock(view: DataView, b: number): {
379
+ declare function feedGeoBlock(view: DataView, b: number, onSbasMessage?: (msg: Uint8Array, prn: number, week: number, tow: number) => void): {
376
380
  eph?: GlonassEphemeris;
377
381
  badCrc?: boolean;
378
382
  };
@@ -391,7 +395,9 @@ interface SbfGeoNavResult {
391
395
  * the same blocks through {@link feedGeoBlock}; this standalone parser
392
396
  * mirrors the per-constellation `parseSbf*` helpers.
393
397
  */
394
- declare function parseSbfGeoNav(data: Uint8Array): SbfGeoNavResult;
398
+ declare function parseSbfGeoNav(data: Uint8Array, opts?: {
399
+ onSbasMessage?: (msg: Uint8Array, prn: number, week: number, tow: number) => void;
400
+ }): SbfGeoNavResult;
395
401
 
396
402
  /** Constellations HAS corrects: GPS (GNSS ID 0), Galileo (GNSS ID 2). */
397
403
  type HasSystem = 'G' | 'E';
package/dist/sbf.d.ts CHANGED
@@ -265,7 +265,11 @@ interface SbfNavigation {
265
265
  * F/NAV, GLONASS strings, BeiDou D1/D2, and the Klobuchar/NeQuick iono +
266
266
  * GPS-UTC leap-second blocks. See the module header for merge semantics.
267
267
  */
268
- declare function decodeSbfNavigation(data: Uint8Array): SbfNavigation;
268
+ declare function decodeSbfNavigation(data: Uint8Array, opts?: {
269
+ /** Called for every CRC-valid SBAS L1 message (all types) — feed an
270
+ * {@link ../positioning/sbas.SbasProcessor} to build SBAS corrections. */
271
+ onSbasMessage?: (msg: Uint8Array, prn: number, week: number, tow: number) => void;
272
+ }): SbfNavigation;
269
273
 
270
274
  /**
271
275
  * Septentrio SBF raw Galileo navigation-page blocks: GALRawINAV (4023)
@@ -372,7 +376,7 @@ declare function parseSbfGloNav(data: Uint8Array): SbfGloNavResult;
372
376
  * message type 9. Returns the ephemeris, `{ badCrc: true }` on a failed
373
377
  * CRC, or `{}` for any other (non–type-9) message.
374
378
  */
375
- declare function feedGeoBlock(view: DataView, b: number): {
379
+ declare function feedGeoBlock(view: DataView, b: number, onSbasMessage?: (msg: Uint8Array, prn: number, week: number, tow: number) => void): {
376
380
  eph?: GlonassEphemeris;
377
381
  badCrc?: boolean;
378
382
  };
@@ -391,7 +395,9 @@ interface SbfGeoNavResult {
391
395
  * the same blocks through {@link feedGeoBlock}; this standalone parser
392
396
  * mirrors the per-constellation `parseSbf*` helpers.
393
397
  */
394
- declare function parseSbfGeoNav(data: Uint8Array): SbfGeoNavResult;
398
+ declare function parseSbfGeoNav(data: Uint8Array, opts?: {
399
+ onSbasMessage?: (msg: Uint8Array, prn: number, week: number, tow: number) => void;
400
+ }): SbfGeoNavResult;
395
401
 
396
402
  /** Constellations HAS corrects: GPS (GNSS ID 0), Galileo (GNSS ID 2). */
397
403
  type HasSystem = 'G' | 'E';
package/dist/sbf.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  parseSbfNav,
16
16
  parseSbfReceiverSetup,
17
17
  scanSbfFrames
18
- } from "./chunk-XFPDTGSV.js";
18
+ } from "./chunk-DE5IUULR.js";
19
19
  import "./chunk-FA2UTLEQ.js";
20
20
  import "./chunk-WQX354KD.js";
21
21
  import "./chunk-37QNKGTC.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gnss-js",
3
- "version": "1.50.0",
3
+ "version": "1.51.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,