gnss-js 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/constants.js CHANGED
@@ -1,29 +1,4 @@
1
1
  import "./chunk-5S5MONFK.js";
2
- import {
3
- DAYS_MJD2000_MJD,
4
- DAYS_MJD_JULIAN,
5
- MILLISECONDS_GPS_TAI,
6
- MILLISECONDS_IN_DAY,
7
- MILLISECONDS_IN_HOUR,
8
- MILLISECONDS_IN_MINUTE,
9
- MILLISECONDS_IN_SECOND,
10
- MILLISECONDS_IN_WEEK,
11
- MILLISECONDS_TT_TAI,
12
- RINEX_CODES,
13
- SECONDS_IN_DAY,
14
- SECONDS_IN_HOUR,
15
- SECONDS_IN_MINUTE,
16
- SECONDS_IN_WEEK,
17
- START_BDS_TIME,
18
- START_GAL_TIME,
19
- START_GLO_LEAP,
20
- START_GPS_TIME,
21
- START_JULIAN_TAI,
22
- START_MJD_UNIX_SECONDS,
23
- START_NTP_TIME,
24
- START_TAI_TIME,
25
- START_UNIX_TIME
26
- } from "./chunk-LEEU5OIO.js";
27
2
  import {
28
3
  ARC_GAP_FACTOR,
29
4
  BAND_LABELS,
@@ -45,13 +20,38 @@ import {
45
20
  formatUTCTime,
46
21
  getFreq,
47
22
  gloFreq
48
- } from "./chunk-LWNTWBHB.js";
23
+ } from "./chunk-W5WKEV7U.js";
49
24
  import {
50
25
  WGS84_ECCENTRICITY_SQUARED,
51
26
  WGS84_FLATTENING,
52
27
  WGS84_SEMI_MAJOR_AXIS,
53
28
  WGS84_SEMI_MINOR_AXIS
54
29
  } from "./chunk-6FAL6P4G.js";
30
+ import {
31
+ DAYS_MJD2000_MJD,
32
+ DAYS_MJD_JULIAN,
33
+ MILLISECONDS_GPS_TAI,
34
+ MILLISECONDS_IN_DAY,
35
+ MILLISECONDS_IN_HOUR,
36
+ MILLISECONDS_IN_MINUTE,
37
+ MILLISECONDS_IN_SECOND,
38
+ MILLISECONDS_IN_WEEK,
39
+ MILLISECONDS_TT_TAI,
40
+ RINEX_CODES,
41
+ SECONDS_IN_DAY,
42
+ SECONDS_IN_HOUR,
43
+ SECONDS_IN_MINUTE,
44
+ SECONDS_IN_WEEK,
45
+ START_BDS_TIME,
46
+ START_GAL_TIME,
47
+ START_GLO_LEAP,
48
+ START_GPS_TIME,
49
+ START_JULIAN_TAI,
50
+ START_MJD_UNIX_SECONDS,
51
+ START_NTP_TIME,
52
+ START_TAI_TIME,
53
+ START_UNIX_TIME
54
+ } from "./chunk-LEEU5OIO.js";
55
55
  export {
56
56
  ARC_GAP_FACTOR,
57
57
  BAND_LABELS,
@@ -7,6 +7,16 @@ interface Rtcm3Frame {
7
7
  length: number;
8
8
  payload: Uint8Array;
9
9
  }
10
+ /** Called when a message decoder swallows an exception. */
11
+ type Rtcm3DebugHandler = (context: string, error: unknown) => void;
12
+ /**
13
+ * Install a handler to observe decode errors that are otherwise
14
+ * silently mapped to null results (corrupt frames, truncated payloads).
15
+ * Pass null to remove.
16
+ */
17
+ declare function setRtcm3DebugHandler(fn: Rtcm3DebugHandler | null): void;
18
+ /** @internal Report a swallowed decode error to the debug handler. */
19
+ declare function reportDecodeError(context: string, error: unknown): void;
10
20
  /** Simple bit reader for parsing RTCM3 payloads at bit level. */
11
21
  declare class BitReader {
12
22
  private data;
@@ -111,4 +121,4 @@ declare function readString(r: BitReader, nChars: number): string;
111
121
  /** Decode any supported ephemeris message. Returns null for non-ephemeris or decode errors. */
112
122
  declare function decodeEphemeris(frame: Rtcm3Frame): EphemerisInfo | null;
113
123
 
114
- export { BitReader as B, type EphemerisInfo as E, Rtcm3Decoder as R, type Rtcm3Frame as a, decodeEphemeris as d, readString as r };
124
+ export { BitReader as B, type EphemerisInfo as E, type Rtcm3DebugHandler as R, Rtcm3Decoder as a, type Rtcm3Frame as b, reportDecodeError as c, decodeEphemeris as d, readString as r, setRtcm3DebugHandler as s };
@@ -7,6 +7,16 @@ interface Rtcm3Frame {
7
7
  length: number;
8
8
  payload: Uint8Array;
9
9
  }
10
+ /** Called when a message decoder swallows an exception. */
11
+ type Rtcm3DebugHandler = (context: string, error: unknown) => void;
12
+ /**
13
+ * Install a handler to observe decode errors that are otherwise
14
+ * silently mapped to null results (corrupt frames, truncated payloads).
15
+ * Pass null to remove.
16
+ */
17
+ declare function setRtcm3DebugHandler(fn: Rtcm3DebugHandler | null): void;
18
+ /** @internal Report a swallowed decode error to the debug handler. */
19
+ declare function reportDecodeError(context: string, error: unknown): void;
10
20
  /** Simple bit reader for parsing RTCM3 payloads at bit level. */
11
21
  declare class BitReader {
12
22
  private data;
@@ -111,4 +121,4 @@ declare function readString(r: BitReader, nChars: number): string;
111
121
  /** Decode any supported ephemeris message. Returns null for non-ephemeris or decode errors. */
112
122
  declare function decodeEphemeris(frame: Rtcm3Frame): EphemerisInfo | null;
113
123
 
114
- export { BitReader as B, type EphemerisInfo as E, Rtcm3Decoder as R, type Rtcm3Frame as a, decodeEphemeris as d, readString as r };
124
+ export { BitReader as B, type EphemerisInfo as E, type Rtcm3DebugHandler as R, Rtcm3Decoder as a, type Rtcm3Frame as b, reportDecodeError as c, decodeEphemeris as d, readString as r, setRtcm3DebugHandler as s };
package/dist/index.cjs CHANGED
@@ -206,10 +206,13 @@ __export(src_exports, {
206
206
  phiBPSK: () => phiBPSK,
207
207
  rad2deg: () => rad2deg,
208
208
  readString: () => readString,
209
+ reportDecodeError: () => reportDecodeError,
209
210
  resetGloFreqCache: () => resetGloFreqCache,
210
211
  rhumbLine: () => rhumbLine,
211
212
  rtcm3Constellation: () => rtcm3Constellation,
212
213
  selectEphemeris: () => selectEphemeris,
214
+ setGloFreqNumber: () => setGloFreqNumber,
215
+ setRtcm3DebugHandler: () => setRtcm3DebugHandler,
213
216
  systemCmp: () => systemCmp,
214
217
  systemName: () => systemName,
215
218
  updateStationMeta: () => updateStationMeta,
@@ -298,7 +301,8 @@ var SYS_SHORT = {
298
301
  var C_LIGHT = 299792458;
299
302
  var FREQ = {
300
303
  G: { "1": 157542e4, "2": 12276e5, "5": 117645e4 },
301
- R: { "3": 1202025e3 },
304
+ // R bands 4/6 are the CDMA L1OC/L2OC center frequencies
305
+ R: { "3": 1202025e3, "4": 1600995e3, "6": 124806e4 },
302
306
  E: {
303
307
  "1": 157542e4,
304
308
  "5": 117645e4,
@@ -392,11 +396,11 @@ function buildGloChannelMap(slots) {
392
396
  return map;
393
397
  }
394
398
  function gloFreq(gloChannels, prn, band) {
399
+ if (band === "3" || band === "4" || band === "6") return FREQ.R[band];
395
400
  const k = gloChannels[prn];
396
401
  if (k === void 0) return void 0;
397
402
  if (band === "1") return GLO_F1_BASE + k * GLO_F1_STEP;
398
403
  if (band === "2") return GLO_F2_BASE + k * GLO_F2_STEP;
399
- if (band === "3") return GLO_F3;
400
404
  return void 0;
401
405
  }
402
406
  function getFreq(gloChannels, prn, band) {
@@ -2556,6 +2560,13 @@ function writeRinexNav(nav) {
2556
2560
  }
2557
2561
 
2558
2562
  // src/rtcm3/decoder.ts
2563
+ var debugHandler = null;
2564
+ function setRtcm3DebugHandler(fn) {
2565
+ debugHandler = fn;
2566
+ }
2567
+ function reportDecodeError(context, error) {
2568
+ if (debugHandler) debugHandler(context, error);
2569
+ }
2559
2570
  var BitReader = class {
2560
2571
  data;
2561
2572
  bitPos = 0;
@@ -3090,31 +3101,32 @@ function decodeEphemeris(frame) {
3090
3101
  default:
3091
3102
  return null;
3092
3103
  }
3093
- } catch {
3104
+ } catch (err) {
3105
+ reportDecodeError("ephemeris", err);
3094
3106
  return null;
3095
3107
  }
3096
3108
  }
3097
3109
 
3098
3110
  // src/rtcm3/msm.ts
3099
- var GPS_L1 = 157542e4;
3100
- var GPS_L2 = 12276e5;
3101
- var GPS_L5 = 117645e4;
3102
- var GLO_L1a = 1600995e3;
3103
- var GLO_L2a = 124806e4;
3104
- var GLO_L3 = 1202025e3;
3105
- var GAL_E1 = 157542e4;
3106
- var GAL_E5a = 117645e4;
3107
- var GAL_E5b = 120714e4;
3108
- var GAL_E5 = 1191795e3;
3109
- var GAL_E6 = 127875e4;
3110
- var BDS_B1 = 1561098e3;
3111
- var BDS_B3 = 126852e4;
3112
- var BDS_B2 = 120714e4;
3113
- var BDS_B1C = 157542e4;
3114
- var BDS_B2a = 117645e4;
3115
- var BDS_B2b = 120714e4;
3116
- var QZSS_L6 = 127875e4;
3117
- var NAVIC_S = 2492028e3;
3111
+ var GPS_L1 = FREQ.G["1"];
3112
+ var GPS_L2 = FREQ.G["2"];
3113
+ var GPS_L5 = FREQ.G["5"];
3114
+ var GLO_L1a = FREQ.R["4"];
3115
+ var GLO_L2a = FREQ.R["6"];
3116
+ var GLO_L3 = FREQ.R["3"];
3117
+ var GAL_E1 = FREQ.E["1"];
3118
+ var GAL_E5a = FREQ.E["5"];
3119
+ var GAL_E5b = FREQ.E["7"];
3120
+ var GAL_E5 = FREQ.E["8"];
3121
+ var GAL_E6 = FREQ.E["6"];
3122
+ var BDS_B1 = FREQ.C["2"];
3123
+ var BDS_B3 = FREQ.C["6"];
3124
+ var BDS_B2 = FREQ.C["7"];
3125
+ var BDS_B1C = FREQ.C["1"];
3126
+ var BDS_B2a = FREQ.C["5"];
3127
+ var BDS_B2b = FREQ.C["7"];
3128
+ var QZSS_L6 = FREQ.J["6"];
3129
+ var NAVIC_S = FREQ.I["9"];
3118
3130
  var EMPTY = { code: "", freq: 0 };
3119
3131
  function sd(code, freq) {
3120
3132
  return { code, freq };
@@ -3366,40 +3378,6 @@ function signalTable(sys) {
3366
3378
  return GPS_SIGNALS;
3367
3379
  }
3368
3380
  }
3369
- var BitReader2 = class {
3370
- data;
3371
- pos;
3372
- constructor(data, startBit = 0) {
3373
- this.data = data;
3374
- this.pos = startBit;
3375
- }
3376
- /** Read unsigned value of numBits bits (max 53) */
3377
- u(numBits) {
3378
- let val = 0;
3379
- for (let i = 0; i < numBits; i++) {
3380
- const byteIdx = this.pos + i >>> 3;
3381
- const bitIdx = 7 - (this.pos + i & 7);
3382
- const bit = byteIdx < this.data.length ? this.data[byteIdx] >>> bitIdx & 1 : 0;
3383
- val = val * 2 + bit;
3384
- }
3385
- this.pos += numBits;
3386
- return val;
3387
- }
3388
- /** Read signed value (two's complement) */
3389
- s(numBits) {
3390
- const raw = this.u(numBits);
3391
- const half = 2 ** (numBits - 1);
3392
- return raw >= half ? raw - 2 ** numBits : raw;
3393
- }
3394
- /** Skip bits */
3395
- skip(n) {
3396
- this.pos += n;
3397
- }
3398
- /** Current bit position */
3399
- get position() {
3400
- return this.pos;
3401
- }
3402
- };
3403
3381
  var gloFreqNum = new Int8Array(64).fill(-128);
3404
3382
  function gloWavelength(satIdx, freqMarker) {
3405
3383
  const k = gloFreqNum[satIdx];
@@ -3434,28 +3412,9 @@ function lockTimeSec(msmType, lti) {
3434
3412
  if (variant <= 5) {
3435
3413
  return LTI_TABLE_4BIT[lti] ?? 0;
3436
3414
  }
3437
- if (lti < 64) return lti;
3438
- if (lti < 96) return (lti - 64) * 2 + 64;
3439
- if (lti < 128) return (lti - 96) * 4 + 128;
3440
- if (lti < 160) return (lti - 128) * 8 + 256;
3441
- if (lti < 192) return (lti - 160) * 16 + 512;
3442
- if (lti < 224) return (lti - 192) * 32 + 1024;
3443
- if (lti < 256) return (lti - 224) * 64 + 2048;
3444
- if (lti < 288) return (lti - 256) * 128 + 4096;
3445
- if (lti < 320) return (lti - 288) * 256 + 8192;
3446
- if (lti < 352) return (lti - 320) * 512 + 16384;
3447
- if (lti < 384) return (lti - 352) * 1024 + 32768;
3448
- if (lti < 416) return (lti - 384) * 2048 + 65536;
3449
- if (lti < 448) return (lti - 416) * 4096 + 131072;
3450
- if (lti < 480) return (lti - 448) * 8192 + 262144;
3451
- if (lti < 512) return (lti - 480) * 16384 + 524288;
3452
- if (lti < 544) return (lti - 512) * 32768 + 1048576;
3453
- if (lti < 576) return (lti - 544) * 65536 + 2097152;
3454
- if (lti < 608) return (lti - 576) * 131072 + 4194304;
3455
- if (lti < 640) return (lti - 608) * 262144 + 8388608;
3456
- if (lti < 672) return (lti - 640) * 524288 + 16777216;
3457
- if (lti < 704) return (lti - 672) * 1048576 + 33554432;
3458
- return (lti - 704) * 2097152 + 67108864;
3415
+ if (lti < 64) return lti / 1e3;
3416
+ const n = Math.min(20, Math.floor((lti - 64) / 32));
3417
+ return ((lti - 64 - 32 * n) * 2 ** (n + 1) + 2 ** (n + 6)) / 1e3;
3459
3418
  }
3460
3419
  function msmSystem(type) {
3461
3420
  if (type >= 1071 && type <= 1077) return "G";
@@ -3481,10 +3440,10 @@ function decodeMsmFull(frame) {
3481
3440
  const payload = frame.payload;
3482
3441
  if (!payload || payload.length < 10) return null;
3483
3442
  try {
3484
- const bits = new BitReader2(payload);
3443
+ const bits = new BitReader(payload);
3485
3444
  bits.skip(12);
3486
3445
  bits.skip(12);
3487
- const epochMs = bits.u(30);
3446
+ const epochMs = bits.readU(30);
3488
3447
  bits.skip(1);
3489
3448
  bits.skip(3);
3490
3449
  bits.skip(7);
@@ -3492,8 +3451,8 @@ function decodeMsmFull(frame) {
3492
3451
  bits.skip(2);
3493
3452
  bits.skip(1);
3494
3453
  bits.skip(3);
3495
- const satMaskHi = bits.u(32) >>> 0;
3496
- const satMaskLo = bits.u(32) >>> 0;
3454
+ const satMaskHi = bits.readU(32) >>> 0;
3455
+ const satMaskLo = bits.readU(32) >>> 0;
3497
3456
  const satIndices = [];
3498
3457
  for (let i = 0; i < 32; i++) {
3499
3458
  if (satMaskHi & 1 << 31 - i) satIndices.push(i + 1);
@@ -3503,7 +3462,7 @@ function decodeMsmFull(frame) {
3503
3462
  }
3504
3463
  const numSat = satIndices.length;
3505
3464
  if (numSat === 0) return null;
3506
- const sigMask = bits.u(32) >>> 0;
3465
+ const sigMask = bits.readU(32) >>> 0;
3507
3466
  const sigIndices = [];
3508
3467
  for (let i = 0; i < 32; i++) {
3509
3468
  if (sigMask & 1 << 31 - i) sigIndices.push(i);
@@ -3513,7 +3472,7 @@ function decodeMsmFull(frame) {
3513
3472
  const numCells = numSat * numSig;
3514
3473
  const cellMask = [];
3515
3474
  for (let i = 0; i < numCells; i++) {
3516
- cellMask.push(bits.u(1) === 1);
3475
+ cellMask.push(bits.readU(1) === 1);
3517
3476
  }
3518
3477
  let activeCells = 0;
3519
3478
  for (const c of cellMask) if (c) activeCells++;
@@ -3523,13 +3482,13 @@ function decodeMsmFull(frame) {
3523
3482
  const extsat = new Int8Array(numSat);
3524
3483
  const rdop = new Float64Array(numSat);
3525
3484
  if (variant === 4 || variant === 6) {
3526
- for (let j = 0; j < numSat; j++) rrint[j] = bits.u(8);
3527
- for (let j = 0; j < numSat; j++) rrmod[j] = bits.u(10) / 1024;
3485
+ for (let j = 0; j < numSat; j++) rrint[j] = bits.readU(8);
3486
+ for (let j = 0; j < numSat; j++) rrmod[j] = bits.readU(10) / 1024;
3528
3487
  } else {
3529
- for (let j = 0; j < numSat; j++) rrint[j] = bits.u(8);
3530
- for (let j = 0; j < numSat; j++) extsat[j] = bits.u(4);
3531
- for (let j = 0; j < numSat; j++) rrmod[j] = bits.u(10) / 1024;
3532
- for (let j = 0; j < numSat; j++) rdop[j] = bits.s(14) * 1;
3488
+ for (let j = 0; j < numSat; j++) rrint[j] = bits.readU(8);
3489
+ for (let j = 0; j < numSat; j++) extsat[j] = bits.readU(4);
3490
+ for (let j = 0; j < numSat; j++) rrmod[j] = bits.readU(10) / 1024;
3491
+ for (let j = 0; j < numSat; j++) rdop[j] = bits.readS(14) * 1;
3533
3492
  }
3534
3493
  if (sys === "R") {
3535
3494
  for (let j = 0; j < numSat; j++) {
@@ -3549,31 +3508,31 @@ function decodeMsmFull(frame) {
3549
3508
  cp.fill(-1e30);
3550
3509
  dop.fill(-1e30);
3551
3510
  if (variant === 4) {
3552
- for (let i = 0; i < activeCells; i++) psr[i] = bits.s(15) / 2 ** 24;
3553
- for (let i = 0; i < activeCells; i++) cp[i] = bits.s(22) / 2 ** 29;
3554
- for (let i = 0; i < activeCells; i++) ll[i] = bits.u(4);
3555
- for (let i = 0; i < activeCells; i++) hc[i] = bits.u(1);
3556
- for (let i = 0; i < activeCells; i++) cnr[i] = bits.u(6);
3511
+ for (let i = 0; i < activeCells; i++) psr[i] = bits.readS(15) / 2 ** 24;
3512
+ for (let i = 0; i < activeCells; i++) cp[i] = bits.readS(22) / 2 ** 29;
3513
+ for (let i = 0; i < activeCells; i++) ll[i] = bits.readU(4);
3514
+ for (let i = 0; i < activeCells; i++) hc[i] = bits.readU(1);
3515
+ for (let i = 0; i < activeCells; i++) cnr[i] = bits.readU(6);
3557
3516
  } else if (variant === 5) {
3558
- for (let i = 0; i < activeCells; i++) psr[i] = bits.s(15) / 2 ** 24;
3559
- for (let i = 0; i < activeCells; i++) cp[i] = bits.s(22) / 2 ** 29;
3560
- for (let i = 0; i < activeCells; i++) ll[i] = bits.u(4);
3561
- for (let i = 0; i < activeCells; i++) hc[i] = bits.u(1);
3562
- for (let i = 0; i < activeCells; i++) cnr[i] = bits.u(6);
3563
- for (let i = 0; i < activeCells; i++) dop[i] = bits.s(15) * 1e-4;
3517
+ for (let i = 0; i < activeCells; i++) psr[i] = bits.readS(15) / 2 ** 24;
3518
+ for (let i = 0; i < activeCells; i++) cp[i] = bits.readS(22) / 2 ** 29;
3519
+ for (let i = 0; i < activeCells; i++) ll[i] = bits.readU(4);
3520
+ for (let i = 0; i < activeCells; i++) hc[i] = bits.readU(1);
3521
+ for (let i = 0; i < activeCells; i++) cnr[i] = bits.readU(6);
3522
+ for (let i = 0; i < activeCells; i++) dop[i] = bits.readS(15) * 1e-4;
3564
3523
  } else if (variant === 6) {
3565
- for (let i = 0; i < activeCells; i++) psr[i] = bits.s(20) / 2 ** 29;
3566
- for (let i = 0; i < activeCells; i++) cp[i] = bits.s(24) / 2 ** 31;
3567
- for (let i = 0; i < activeCells; i++) ll[i] = bits.u(10);
3568
- for (let i = 0; i < activeCells; i++) hc[i] = bits.u(1);
3569
- for (let i = 0; i < activeCells; i++) cnr[i] = bits.u(10) / 16;
3524
+ for (let i = 0; i < activeCells; i++) psr[i] = bits.readS(20) / 2 ** 29;
3525
+ for (let i = 0; i < activeCells; i++) cp[i] = bits.readS(24) / 2 ** 31;
3526
+ for (let i = 0; i < activeCells; i++) ll[i] = bits.readU(10);
3527
+ for (let i = 0; i < activeCells; i++) hc[i] = bits.readU(1);
3528
+ for (let i = 0; i < activeCells; i++) cnr[i] = bits.readU(10) / 16;
3570
3529
  } else {
3571
- for (let i = 0; i < activeCells; i++) psr[i] = bits.s(20) / 2 ** 29;
3572
- for (let i = 0; i < activeCells; i++) cp[i] = bits.s(24) / 2 ** 31;
3573
- for (let i = 0; i < activeCells; i++) ll[i] = bits.u(10);
3574
- for (let i = 0; i < activeCells; i++) hc[i] = bits.u(1);
3575
- for (let i = 0; i < activeCells; i++) cnr[i] = bits.u(10) / 16;
3576
- for (let i = 0; i < activeCells; i++) dop[i] = bits.s(15) * 1e-4;
3530
+ for (let i = 0; i < activeCells; i++) psr[i] = bits.readS(20) / 2 ** 29;
3531
+ for (let i = 0; i < activeCells; i++) cp[i] = bits.readS(24) / 2 ** 31;
3532
+ for (let i = 0; i < activeCells; i++) ll[i] = bits.readU(10);
3533
+ for (let i = 0; i < activeCells; i++) hc[i] = bits.readU(1);
3534
+ for (let i = 0; i < activeCells; i++) cnr[i] = bits.readU(10) / 16;
3535
+ for (let i = 0; i < activeCells; i++) dop[i] = bits.readS(15) * 1e-4;
3577
3536
  }
3578
3537
  const sigTable = signalTable(sys);
3579
3538
  const observations = [];
@@ -3607,11 +3566,11 @@ function decodeMsmFull(frame) {
3607
3566
  wavelength
3608
3567
  };
3609
3568
  const psrVal = psr[cellIdx];
3610
- if (psrVal > -1 / (1 << 10)) {
3569
+ if (psrVal > -(2 ** -10)) {
3611
3570
  signal.pseudorange = psrVal * C_LIGHT / 1e3 + roughRange_m;
3612
3571
  }
3613
3572
  const cpVal = cp[cellIdx];
3614
- if (cpVal > -1 / (1 << 8) && wavelength > 0) {
3573
+ if (cpVal > -(2 ** -8) && wavelength > 0) {
3615
3574
  signal.phase = cpVal * C_LIGHT / 1e3 / wavelength + roughRange_m / wavelength;
3616
3575
  }
3617
3576
  if (variant === 5 || variant === 7) {
@@ -3639,12 +3598,13 @@ function decodeMsmFull(frame) {
3639
3598
  system: sys,
3640
3599
  observations
3641
3600
  };
3642
- } catch {
3601
+ } catch (err) {
3602
+ reportDecodeError("msm", err);
3643
3603
  return null;
3644
3604
  }
3645
3605
  }
3646
- var GPS_EPOCH = Date.UTC(1980, 0, 6);
3647
- var MS_PER_WEEK = 6048e5;
3606
+ var GPS_EPOCH = START_GPS_TIME.getTime();
3607
+ var MS_PER_WEEK = MILLISECONDS_IN_WEEK;
3648
3608
  function msmEpochToDate(sys, epochMs, refTime = /* @__PURE__ */ new Date()) {
3649
3609
  const refMs = refTime.getTime();
3650
3610
  if (sys === "R") {
@@ -3659,11 +3619,12 @@ function msmEpochToDate(sys, epochMs, refTime = /* @__PURE__ */ new Date()) {
3659
3619
  return new Date(t2);
3660
3620
  }
3661
3621
  if (sys === "C") {
3662
- const BDS_EPOCH = Date.UTC(2006, 0, 1) - 14e3;
3622
+ const BDS_EPOCH = START_BDS_TIME.getTime();
3663
3623
  const weeksSinceEpoch2 = Math.floor((refMs - BDS_EPOCH) / MS_PER_WEEK);
3664
3624
  let t2 = BDS_EPOCH + weeksSinceEpoch2 * MS_PER_WEEK + epochMs;
3665
3625
  if (t2 - refMs > MS_PER_WEEK / 2) t2 -= MS_PER_WEEK;
3666
3626
  else if (refMs - t2 > MS_PER_WEEK / 2) t2 += MS_PER_WEEK;
3627
+ t2 -= 18e3;
3667
3628
  return new Date(t2);
3668
3629
  }
3669
3630
  const weeksSinceEpoch = Math.floor((refMs - GPS_EPOCH) / MS_PER_WEEK);
@@ -3673,6 +3634,11 @@ function msmEpochToDate(sys, epochMs, refTime = /* @__PURE__ */ new Date()) {
3673
3634
  t -= 18e3;
3674
3635
  return new Date(t);
3675
3636
  }
3637
+ function setGloFreqNumber(slot, k) {
3638
+ if (slot >= 1 && slot <= 64 && k >= -7 && k <= 13) {
3639
+ gloFreqNum[slot - 1] = k;
3640
+ }
3641
+ }
3676
3642
  function resetGloFreqCache() {
3677
3643
  gloFreqNum.fill(-128);
3678
3644
  }
@@ -3806,7 +3772,8 @@ function updateStationMeta(meta, frame) {
3806
3772
  default:
3807
3773
  return false;
3808
3774
  }
3809
- } catch {
3775
+ } catch (err) {
3776
+ reportDecodeError("station", err);
3810
3777
  return false;
3811
3778
  }
3812
3779
  }
@@ -3994,6 +3961,9 @@ function updateStreamStats(stats, frames, rawBytes) {
3994
3961
  const eph = decodeEphemeris(frame);
3995
3962
  if (eph) {
3996
3963
  stats.ephemerides.set(eph.prn, eph);
3964
+ if (eph.freqChannel !== void 0 && eph.prn.startsWith("R")) {
3965
+ setGloFreqNumber(parseInt(eph.prn.slice(1), 10), eph.freqChannel);
3966
+ }
3997
3967
  }
3998
3968
  updateStationMeta(stats.stationMeta, frame);
3999
3969
  }
@@ -4013,6 +3983,8 @@ var GM_GAL = 3986004418e5;
4013
3983
  var GM_BDS = 3986004418e5;
4014
3984
  var GM_GLO = 39860044e7;
4015
3985
  var OMEGA_E = 72921151467e-15;
3986
+ var BDS_GEO_MAX_INCLINATION_RAD = 0.1;
3987
+ var BDS_GEO_MIN_SEMIMAJOR_AXIS_M = 4e7;
4016
3988
  var AE_GLO = 6378136;
4017
3989
  var J2_GLO = 108263e-8;
4018
3990
  var TWO_PI = 2 * Math.PI;
@@ -4050,7 +4022,7 @@ function keplerPosition(eph, t) {
4050
4022
  const ik = eph.i0 + dik + eph.idot * tk;
4051
4023
  const xp = rk * Math.cos(uk);
4052
4024
  const yp = rk * Math.sin(uk);
4053
- const isBdsGeo = eph.system === "C" && Math.abs(eph.i0) < 0.1 && a > 4e7;
4025
+ const isBdsGeo = eph.system === "C" && Math.abs(eph.i0) < BDS_GEO_MAX_INCLINATION_RAD && a > BDS_GEO_MIN_SEMIMAJOR_AXIS_M;
4054
4026
  if (isBdsGeo) {
4055
4027
  const omegak2 = eph.omega0 + eph.omegaDot * tk - OMEGA_E * eph.toe;
4056
4028
  const cosO2 = Math.cos(omegak2);
@@ -4231,9 +4203,10 @@ function computeSatPosition(eph, timeMs) {
4231
4203
  if (eph.system === "R" || eph.system === "S") {
4232
4204
  return glonassPosition(eph, timeMs / 1e3);
4233
4205
  }
4234
- const GPS_EPOCH2 = Date.UTC(1980, 0, 6);
4206
+ const GPS_EPOCH2 = START_GPS_TIME.getTime();
4235
4207
  const gpsSeconds = (timeMs - GPS_EPOCH2) / 1e3;
4236
- const tow = gpsSeconds % (7 * 86400);
4208
+ let tow = gpsSeconds % (7 * 86400);
4209
+ if (eph.system === "C") tow = (tow - 14 + 604800) % 604800;
4237
4210
  return keplerPosition(eph, tow);
4238
4211
  }
4239
4212
  function navTimesFromEph(ephs) {
@@ -4315,8 +4288,8 @@ function selectBest(ephs, timeMs) {
4315
4288
  }
4316
4289
  return best;
4317
4290
  }
4318
- var GPS_EPOCH_MS = Date.UTC(1980, 0, 6);
4319
- var BDS_EPOCH_MS = Date.UTC(2006, 0, 1);
4291
+ var GPS_EPOCH_MS = START_GPS_TIME.getTime();
4292
+ var BDS_EPOCH_MS = START_BDS_TIME.getTime();
4320
4293
  var GAL_EPOCH_MS = GPS_EPOCH_MS;
4321
4294
  function ephInfoToEphemeris(info) {
4322
4295
  const sys = info.prn.charAt(0);
@@ -4357,6 +4330,9 @@ function ephInfoToEphemeris(info) {
4357
4330
  }
4358
4331
  if (info.sqrtA === void 0 || info.eccentricity === void 0 || info.inclination === void 0 || info.omega0 === void 0 || info.argPerigee === void 0 || info.meanAnomaly === void 0 || info.toe === void 0 || info.week === void 0)
4359
4332
  return null;
4333
+ if (info.eccentricity < 0 || info.eccentricity >= 1 || info.sqrtA < 3e3 || info.sqrtA > 9e3 || info.toe < 0 || info.toe > 604800) {
4334
+ return null;
4335
+ }
4360
4336
  let epochMs;
4361
4337
  const tocSec = info.toc ?? info.toe;
4362
4338
  if (sys === "C") {
@@ -5487,32 +5463,33 @@ function parseNmeaFile(content) {
5487
5463
  }
5488
5464
 
5489
5465
  // src/signals/definitions.ts
5490
- var FREQ_GPS_L1 = 1575.42;
5491
- var FREQ_GPS_L2 = 1227.6;
5492
- var FREQ_GPS_L5 = 1176.45;
5493
- var FREQ_GLO_L1 = 1602;
5494
- var FREQ_GLO_L2 = 1246;
5495
- var DELTA_GLO_L1 = 0.5625;
5496
- var DELTA_GLO_L2 = 0.4375;
5497
- var FREQ_GLO_L1OC = 1600.995;
5498
- var FREQ_GLO_L2OC = 1248.06;
5499
- var FREQ_GLO_L3OC = 1202.025;
5500
- var FREQ_GAL_E1 = 1575.42;
5501
- var FREQ_GAL_E5 = 1191.795;
5502
- var FREQ_GAL_E5a = 1176.45;
5503
- var FREQ_GAL_E5b = 1207.14;
5504
- var FREQ_GAL_E6 = 1278.75;
5505
- var FREQ_BDS_B1I = 1561.098;
5506
- var FREQ_BDS_B2I = 1207.14;
5507
- var FREQ_BDS_B3I = 1268.52;
5508
- var FREQ_BDS_B1A = 1575.42;
5509
- var FREQ_BDS_B1C = 1575.42;
5510
- var FREQ_BDS_B3A = 1268.52;
5511
- var FREQ_QZS_L1 = 1575.42;
5512
- var FREQ_QZS_L2 = 1227.6;
5513
- var FREQ_QZS_L5 = 1176.45;
5514
- var FREQ_QZS_L6 = 1278.75;
5515
- var FREQ_NAVIC_L5 = 1176.45;
5466
+ var MHz = 1e6;
5467
+ var FREQ_GPS_L1 = FREQ.G["1"] / MHz;
5468
+ var FREQ_GPS_L2 = FREQ.G["2"] / MHz;
5469
+ var FREQ_GPS_L5 = FREQ.G["5"] / MHz;
5470
+ var FREQ_GLO_L1 = GLO_F1_BASE / MHz;
5471
+ var FREQ_GLO_L2 = GLO_F2_BASE / MHz;
5472
+ var DELTA_GLO_L1 = GLO_F1_STEP / MHz;
5473
+ var DELTA_GLO_L2 = GLO_F2_STEP / MHz;
5474
+ var FREQ_GLO_L1OC = FREQ.R["4"] / MHz;
5475
+ var FREQ_GLO_L2OC = FREQ.R["6"] / MHz;
5476
+ var FREQ_GLO_L3OC = FREQ.R["3"] / MHz;
5477
+ var FREQ_GAL_E1 = FREQ.E["1"] / MHz;
5478
+ var FREQ_GAL_E5 = FREQ.E["8"] / MHz;
5479
+ var FREQ_GAL_E5a = FREQ.E["5"] / MHz;
5480
+ var FREQ_GAL_E5b = FREQ.E["7"] / MHz;
5481
+ var FREQ_GAL_E6 = FREQ.E["6"] / MHz;
5482
+ var FREQ_BDS_B1I = FREQ.C["2"] / MHz;
5483
+ var FREQ_BDS_B2I = FREQ.C["7"] / MHz;
5484
+ var FREQ_BDS_B3I = FREQ.C["6"] / MHz;
5485
+ var FREQ_BDS_B1A = FREQ.C["1"] / MHz;
5486
+ var FREQ_BDS_B1C = FREQ.C["1"] / MHz;
5487
+ var FREQ_BDS_B3A = FREQ.C["6"] / MHz;
5488
+ var FREQ_QZS_L1 = FREQ.J["1"] / MHz;
5489
+ var FREQ_QZS_L2 = FREQ.J["2"] / MHz;
5490
+ var FREQ_QZS_L5 = FREQ.J["5"] / MHz;
5491
+ var FREQ_QZS_L6 = FREQ.J["6"] / MHz;
5492
+ var FREQ_NAVIC_L5 = FREQ.I["5"] / MHz;
5516
5493
  var GPS_COLOR = "#4ade80";
5517
5494
  var GPS_M_COLOR = "#ef4444";
5518
5495
  var GPS_P_COLOR = "#dbc51f";
@@ -6438,10 +6415,13 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
6438
6415
  phiBPSK,
6439
6416
  rad2deg,
6440
6417
  readString,
6418
+ reportDecodeError,
6441
6419
  resetGloFreqCache,
6442
6420
  rhumbLine,
6443
6421
  rtcm3Constellation,
6444
6422
  selectEphemeris,
6423
+ setGloFreqNumber,
6424
+ setRtcm3DebugHandler,
6445
6425
  systemCmp,
6446
6426
  systemName,
6447
6427
  updateStationMeta,
package/dist/index.d.cts CHANGED
@@ -7,8 +7,8 @@ export { c as clampUnit, e as ecefToGeodetic, g as geodeticToEcef, a as getAer,
7
7
  export { CrxField, DiffState, EMPTY_WARNINGS, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, writeRinexNav } from './rinex.cjs';
8
8
  export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResult, b as RinexStats, S as SYSTEM_ORDER, c as SatObsCallback, p as parseRinexStream, s as systemCmp, d as systemName } from './parser-JPjjFgeP.cjs';
9
9
  export { E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, p as parseNavFile } from './nav-BAI1a9vK.cjs';
10
- export { B as BitReader, E as EphemerisInfo, R as Rtcm3Decoder, a as Rtcm3Frame, d as decodeEphemeris, r as readString } from './ephemeris-C10stHhM.cjs';
11
- export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, updateStationMeta, updateStreamStats } from './rtcm3.cjs';
10
+ 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';
11
+ export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.cjs';
12
12
  export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, ecefToAzEl, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris } from './orbit.cjs';
13
13
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.cjs';
14
14
  export { CompleteSatSignal, CompleteSignalStats, CompletenessAccumulator, CompletenessResult, CycleSlipAccumulator, CycleSlipEvent, CycleSlipResult, CycleSlipSignalStats, MultipathAccumulator, MultipathPoint, MultipathResult, MultipathSeries, MultipathSignalStat, QualityResult, analyzeQuality } from './analysis.cjs';
package/dist/index.d.ts CHANGED
@@ -7,8 +7,8 @@ export { c as clampUnit, e as ecefToGeodetic, g as geodeticToEcef, a as getAer,
7
7
  export { CrxField, DiffState, EMPTY_WARNINGS, RinexWarning, RinexWarnings, WarningAccumulator, WarningSeverity, crxDecompress, crxRepair, fmtF, hdrLine, padL, padR, parseCrxDataLine, writeRinexNav } from './rinex.js';
8
8
  export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResult, b as RinexStats, S as SYSTEM_ORDER, c as SatObsCallback, p as parseRinexStream, s as systemCmp, d as systemName } from './parser-JPjjFgeP.js';
9
9
  export { E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, p as parseNavFile } from './nav-BAI1a9vK.js';
10
- export { B as BitReader, E as EphemerisInfo, R as Rtcm3Decoder, a as Rtcm3Frame, d as decodeEphemeris, r as readString } from './ephemeris-C10stHhM.js';
11
- export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, updateStationMeta, updateStreamStats } from './rtcm3.js';
10
+ 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';
11
+ export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.js';
12
12
  export { AllPositionsData, DopValues, EpochSkyData, SatAzEl, SatPoint, SatPosition, computeAllPositions, computeDop, computeLiveSkyPositions, computeSatPosition, ecefToAzEl, glonassPosition, keplerPosition, navTimesFromEph, selectEphemeris } from './orbit.js';
13
13
  export { NtripCaster, NtripConnectionInfo, NtripNetwork, NtripStream, NtripStreamConnection, NtripVersion, Sourcetable, SourcetableEntry, connectToMountpoint, fetchSourcetable, parseSourcetable } from './ntrip.js';
14
14
  export { CompleteSatSignal, CompleteSignalStats, CompletenessAccumulator, CompletenessResult, CycleSlipAccumulator, CycleSlipEvent, CycleSlipResult, CycleSlipSignalStats, MultipathAccumulator, MultipathPoint, MultipathResult, MultipathSeries, MultipathSignalStat, QualityResult, analyzeQuality } from './analysis.js';