gnss-js 1.53.0 → 1.54.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.
@@ -355,8 +355,57 @@ function parseNovatelNav(data, opts = {}) {
355
355
  };
356
356
  }
357
357
 
358
- // src/novatel/index.ts
358
+ // src/novatel/pvt.ts
359
359
  var GPS_EPOCH_MS2 = Date.UTC(1980, 0, 6);
360
+ var BESTPOS = 42;
361
+ function posTypeToMode(t) {
362
+ if (t === 0) return "no-pvt";
363
+ if (t === 16) return "standalone";
364
+ if (t === 17) return "differential";
365
+ if (t === 18 || t === 20) return "sbas-aided";
366
+ if (t === 32 || t === 33 || t === 34) return "rtk-float";
367
+ if (t === 48 || t === 50) return "rtk-fixed";
368
+ if (t >= 68 && t <= 78) return "ppp";
369
+ return `mode-${t}`;
370
+ }
371
+ function parseNovatelPvt(data) {
372
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
373
+ const records = [];
374
+ let messages = 0;
375
+ const stats = { badCrc: 0 };
376
+ for (const f of oem4Frames(data, view, stats)) {
377
+ if (f.id !== BESTPOS || !f.binary || f.msgLen < 72) continue;
378
+ messages++;
379
+ const p = f.payload;
380
+ const posType = view.getUint32(p + 4, true);
381
+ const lat = view.getFloat64(p + 8, true);
382
+ const lon = view.getFloat64(p + 16, true);
383
+ const hgtMsl = view.getFloat64(p + 24, true);
384
+ const undulation = view.getFloat32(p + 32, true);
385
+ const latSig = view.getFloat32(p + 40, true);
386
+ const lonSig = view.getFloat32(p + 44, true);
387
+ const hgtSig = view.getFloat32(p + 48, true);
388
+ const nrSV = view.getUint8(p + 65);
389
+ const hasFix = posType !== 0 && Number.isFinite(lat) && Number.isFinite(lon);
390
+ records.push({
391
+ timeMs: GPS_EPOCH_MS2 + f.week * 6048e5 + f.towMs,
392
+ week: f.week,
393
+ tow: f.towMs / 1e3,
394
+ mode: posTypeToMode(posType),
395
+ latDeg: hasFix ? lat : null,
396
+ lonDeg: hasFix ? lon : null,
397
+ // BESTPOS height is above MSL; ellipsoidal = MSL + geoid undulation.
398
+ heightM: hasFix ? hgtMsl + undulation : null,
399
+ nrSV,
400
+ hAccuracyM: hasFix ? Math.hypot(latSig, lonSig) : null,
401
+ vAccuracyM: hasFix ? hgtSig : null
402
+ });
403
+ }
404
+ return { records, messages };
405
+ }
406
+
407
+ // src/novatel/index.ts
408
+ var GPS_EPOCH_MS3 = Date.UTC(1980, 0, 6);
360
409
  var MS_PER_WEEK2 = 7 * 864e5;
361
410
  var HDR = 28;
362
411
  var ID_RANGE = 43;
@@ -526,7 +575,7 @@ function parseNovatelRange(data) {
526
575
  if (!codes.includes(code)) codes.push(code);
527
576
  }
528
577
  epochs.push({
529
- timeMs: GPS_EPOCH_MS2 + week * MS_PER_WEEK2 + towMs,
578
+ timeMs: GPS_EPOCH_MS3 + week * MS_PER_WEEK2 + towMs,
530
579
  meas
531
580
  });
532
581
  }
@@ -578,7 +627,7 @@ function parseNovatelRange(data) {
578
627
  if (!codes.includes(code)) codes.push(code);
579
628
  }
580
629
  epochs.push({
581
- timeMs: GPS_EPOCH_MS2 + week * MS_PER_WEEK2 + towMs,
630
+ timeMs: GPS_EPOCH_MS3 + week * MS_PER_WEEK2 + towMs,
582
631
  meas
583
632
  });
584
633
  }
@@ -593,5 +642,6 @@ export {
593
642
  crc32,
594
643
  oem4Frames,
595
644
  parseNovatelNav,
645
+ parseNovatelPvt,
596
646
  parseNovatelRange
597
647
  };
@@ -306,8 +306,59 @@ function parseUbxRawNav(data, opts = {}) {
306
306
  return { ephemerides, counts, badParity };
307
307
  }
308
308
 
309
- // src/ubx/index.ts
309
+ // src/ubx/pvt.ts
310
310
  var GPS_EPOCH_MS2 = Date.UTC(1980, 0, 6);
311
+ function parseUbxPvt(data) {
312
+ const records = [];
313
+ let messages = 0;
314
+ for (const f of ubxFrames(data)) {
315
+ if (f.msgClass !== 1 || f.msgId !== 7 || f.payload.length < 92)
316
+ continue;
317
+ messages++;
318
+ const v = new DataView(
319
+ f.payload.buffer,
320
+ f.payload.byteOffset,
321
+ f.payload.byteLength
322
+ );
323
+ const iTow = v.getUint32(0, true);
324
+ const year = v.getUint16(4, true);
325
+ const month = v.getUint8(6);
326
+ const day = v.getUint8(7);
327
+ const hour = v.getUint8(8);
328
+ const min = v.getUint8(9);
329
+ const sec = v.getUint8(10);
330
+ const fixType = v.getUint8(20);
331
+ const flags = v.getUint8(21);
332
+ const numSV = v.getUint8(23);
333
+ const lon = v.getInt32(24, true) * 1e-7;
334
+ const lat = v.getInt32(28, true) * 1e-7;
335
+ const height = v.getInt32(32, true) / 1e3;
336
+ const hAcc = v.getUint32(40, true) / 1e3;
337
+ const vAcc = v.getUint32(44, true) / 1e3;
338
+ const carrSoln = flags >> 6 & 3;
339
+ const diffSoln = flags >> 1 & 1;
340
+ const mode = carrSoln === 2 ? "rtk-fixed" : carrSoln === 1 ? "rtk-float" : diffSoln ? "differential" : fixType >= 2 ? "standalone" : "no-pvt";
341
+ const hasFix = fixType >= 2;
342
+ const timeMs = year > 1980 ? Date.UTC(year, month - 1, day, hour, min, sec) : GPS_EPOCH_MS2 + iTow;
343
+ const week = Math.floor((timeMs - GPS_EPOCH_MS2) / 1e3 / 604800);
344
+ records.push({
345
+ timeMs,
346
+ week,
347
+ tow: iTow / 1e3,
348
+ mode,
349
+ latDeg: hasFix ? lat : null,
350
+ lonDeg: hasFix ? lon : null,
351
+ heightM: hasFix ? height : null,
352
+ nrSV: numSV,
353
+ hAccuracyM: hasFix ? hAcc : null,
354
+ vAccuracyM: hasFix ? vAcc : null
355
+ });
356
+ }
357
+ return { records, messages };
358
+ }
359
+
360
+ // src/ubx/index.ts
361
+ var GPS_EPOCH_MS3 = Date.UTC(1980, 0, 6);
311
362
  var MS_PER_WEEK = 7 * 864e5;
312
363
  var SIGNALS = {
313
364
  0: { 0: ["G", "1C"], 3: ["G", "2X"], 4: ["G", "2X"] },
@@ -390,7 +441,7 @@ function parseUbxRawx(data) {
390
441
  if (!codes.includes(sig[1])) codes.push(sig[1]);
391
442
  }
392
443
  epochs.push({
393
- timeMs: GPS_EPOCH_MS2 + week * MS_PER_WEEK + Math.round(rcvTow * 1e3),
444
+ timeMs: GPS_EPOCH_MS3 + week * MS_PER_WEEK + Math.round(rcvTow * 1e3),
394
445
  leapS: leapValid ? leapS : null,
395
446
  meas
396
447
  });
@@ -405,5 +456,6 @@ export {
405
456
  parseUbxIonoUtc,
406
457
  parseUbxCnav,
407
458
  parseUbxRawNav,
459
+ parseUbxPvt,
408
460
  parseUbxRawx
409
461
  };
package/dist/index.cjs CHANGED
@@ -256,6 +256,7 @@ __export(src_exports, {
256
256
  parseNavFile: () => parseNavFile,
257
257
  parseNmeaFile: () => parseNmeaFile,
258
258
  parseNovatelNav: () => parseNovatelNav,
259
+ parseNovatelPvt: () => parseNovatelPvt,
259
260
  parseNovatelRange: () => parseNovatelRange,
260
261
  parseRinexStream: () => parseRinexStream,
261
262
  parseSbfAlmanac: () => parseSbfAlmanac,
@@ -279,6 +280,7 @@ __export(src_exports, {
279
280
  parseUbxCnav: () => parseUbxCnav,
280
281
  parseUbxIonoUtc: () => parseUbxIonoUtc,
281
282
  parseUbxNav: () => parseUbxNav,
283
+ parseUbxPvt: () => parseUbxPvt,
282
284
  parseUbxRawNav: () => parseUbxRawNav,
283
285
  parseUbxRawx: () => parseUbxRawx,
284
286
  phiAltBOC: () => phiAltBOC,
@@ -6961,8 +6963,59 @@ function parseUbxRawNav(data, opts = {}) {
6961
6963
  return { ephemerides, counts, badParity };
6962
6964
  }
6963
6965
 
6964
- // src/ubx/index.ts
6966
+ // src/ubx/pvt.ts
6965
6967
  var GPS_EPOCH_MS9 = Date.UTC(1980, 0, 6);
6968
+ function parseUbxPvt(data) {
6969
+ const records = [];
6970
+ let messages = 0;
6971
+ for (const f of ubxFrames(data)) {
6972
+ if (f.msgClass !== 1 || f.msgId !== 7 || f.payload.length < 92)
6973
+ continue;
6974
+ messages++;
6975
+ const v = new DataView(
6976
+ f.payload.buffer,
6977
+ f.payload.byteOffset,
6978
+ f.payload.byteLength
6979
+ );
6980
+ const iTow = v.getUint32(0, true);
6981
+ const year = v.getUint16(4, true);
6982
+ const month = v.getUint8(6);
6983
+ const day = v.getUint8(7);
6984
+ const hour = v.getUint8(8);
6985
+ const min = v.getUint8(9);
6986
+ const sec = v.getUint8(10);
6987
+ const fixType = v.getUint8(20);
6988
+ const flags = v.getUint8(21);
6989
+ const numSV = v.getUint8(23);
6990
+ const lon = v.getInt32(24, true) * 1e-7;
6991
+ const lat = v.getInt32(28, true) * 1e-7;
6992
+ const height = v.getInt32(32, true) / 1e3;
6993
+ const hAcc = v.getUint32(40, true) / 1e3;
6994
+ const vAcc = v.getUint32(44, true) / 1e3;
6995
+ const carrSoln = flags >> 6 & 3;
6996
+ const diffSoln = flags >> 1 & 1;
6997
+ const mode = carrSoln === 2 ? "rtk-fixed" : carrSoln === 1 ? "rtk-float" : diffSoln ? "differential" : fixType >= 2 ? "standalone" : "no-pvt";
6998
+ const hasFix = fixType >= 2;
6999
+ const timeMs = year > 1980 ? Date.UTC(year, month - 1, day, hour, min, sec) : GPS_EPOCH_MS9 + iTow;
7000
+ const week = Math.floor((timeMs - GPS_EPOCH_MS9) / 1e3 / 604800);
7001
+ records.push({
7002
+ timeMs,
7003
+ week,
7004
+ tow: iTow / 1e3,
7005
+ mode,
7006
+ latDeg: hasFix ? lat : null,
7007
+ lonDeg: hasFix ? lon : null,
7008
+ heightM: hasFix ? height : null,
7009
+ nrSV: numSV,
7010
+ hAccuracyM: hasFix ? hAcc : null,
7011
+ vAccuracyM: hasFix ? vAcc : null
7012
+ });
7013
+ }
7014
+ return { records, messages };
7015
+ }
7016
+
7017
+ // src/ubx/index.ts
7018
+ var GPS_EPOCH_MS10 = Date.UTC(1980, 0, 6);
6966
7019
  var MS_PER_WEEK4 = 7 * 864e5;
6967
7020
  var SIGNALS = {
6968
7021
  0: { 0: ["G", "1C"], 3: ["G", "2X"], 4: ["G", "2X"] },
@@ -7045,7 +7098,7 @@ function parseUbxRawx(data) {
7045
7098
  if (!codes.includes(sig[1])) codes.push(sig[1]);
7046
7099
  }
7047
7100
  epochs.push({
7048
- timeMs: GPS_EPOCH_MS9 + week * MS_PER_WEEK4 + Math.round(rcvTow * 1e3),
7101
+ timeMs: GPS_EPOCH_MS10 + week * MS_PER_WEEK4 + Math.round(rcvTow * 1e3),
7049
7102
  leapS: leapValid ? leapS : null,
7050
7103
  meas
7051
7104
  });
@@ -7116,7 +7169,7 @@ function svidToPrn(svid) {
7116
7169
 
7117
7170
  // src/sbf/nav.ts
7118
7171
  var PI2 = Math.PI;
7119
- var GPS_EPOCH_MS10 = Date.UTC(1980, 0, 6);
7172
+ var GPS_EPOCH_MS11 = Date.UTC(1980, 0, 6);
7120
7173
  var BDT_EPOCH_MS2 = Date.UTC(2006, 0, 1);
7121
7174
  var SEC_PER_WEEK8 = 7 * 86400;
7122
7175
  var MS_PER_WEEK5 = SEC_PER_WEEK8 * 1e3;
@@ -7128,7 +7181,7 @@ function adjustWeek(refWeek, wn, mod) {
7128
7181
  if (offset < -(mod / 2 - 1)) offset += mod;
7129
7182
  return refWeek - offset;
7130
7183
  }
7131
- var gpsMs = (week, sec) => GPS_EPOCH_MS10 + week * MS_PER_WEEK5 + sec * 1e3;
7184
+ var gpsMs = (week, sec) => GPS_EPOCH_MS11 + week * MS_PER_WEEK5 + sec * 1e3;
7132
7185
  var sowOf2 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK8;
7133
7186
  function decodeGpsQzsNav(view, b, sys) {
7134
7187
  const svid = view.getUint8(b + 14);
@@ -7278,7 +7331,7 @@ function decodeGloNav(view, b) {
7278
7331
  const tocDate = new Date(toeGpsMs - leapMs);
7279
7332
  const tofGpsMs = gpsMs(wnc, 0) + view.getUint32(b + 8, true);
7280
7333
  const tofLeapMs = getGpsLeap(new Date(tofGpsMs)) * 1e3;
7281
- const messageFrameTime = (tofGpsMs - tofLeapMs - GPS_EPOCH_MS10) / 1e3 % SEC_PER_WEEK8;
7334
+ const messageFrameTime = (tofGpsMs - tofLeapMs - GPS_EPOCH_MS11) / 1e3 % SEC_PER_WEEK8;
7282
7335
  return {
7283
7336
  system: "R",
7284
7337
  prn,
@@ -7511,7 +7564,7 @@ function parseSbfReceiverSetup(data) {
7511
7564
  }
7512
7565
 
7513
7566
  // src/sbf/pvt.ts
7514
- var GPS_EPOCH_MS11 = Date.UTC(1980, 0, 6);
7567
+ var GPS_EPOCH_MS12 = Date.UTC(1980, 0, 6);
7515
7568
  var RAD2DEG = 180 / Math.PI;
7516
7569
  var DNU_F8 = -2e10;
7517
7570
  var MODE_LABELS = {
@@ -7546,7 +7599,7 @@ function parseSbfPvt(data) {
7546
7599
  const vAcc = view.getUint16(b + 92, true);
7547
7600
  const hasFix = lat > DNU_F8 && lon > DNU_F8 && hgt > DNU_F8;
7548
7601
  records.push({
7549
- timeMs: GPS_EPOCH_MS11 + wnc * 6048e5 + tow,
7602
+ timeMs: GPS_EPOCH_MS12 + wnc * 6048e5 + tow,
7550
7603
  week: wnc,
7551
7604
  tow: tow / 1e3,
7552
7605
  modeType,
@@ -7697,7 +7750,7 @@ function isFnavDummy(page) {
7697
7750
  }
7698
7751
 
7699
7752
  // src/sbf/rawnav-bds.ts
7700
- var GPS_EPOCH_MS12 = Date.UTC(1980, 0, 6);
7753
+ var GPS_EPOCH_MS13 = Date.UTC(1980, 0, 6);
7701
7754
  var MS_PER_WEEK6 = 7 * 86400 * 1e3;
7702
7755
  var TOW_DNU = 4294967295;
7703
7756
  var WNC_DNU2 = 65535;
@@ -7758,7 +7811,7 @@ function feedGloBlock(view, b, assembler) {
7758
7811
  const eph = assembler.push(
7759
7812
  prn,
7760
7813
  str2,
7761
- new Date(GPS_EPOCH_MS12 + wnc * MS_PER_WEEK6 + towMs),
7814
+ new Date(GPS_EPOCH_MS13 + wnc * MS_PER_WEEK6 + towMs),
7762
7815
  view.getUint8(b + 18) - 8
7763
7816
  // FreqNr, offset by 8
7764
7817
  );
@@ -8508,7 +8561,7 @@ function parseSbfHas(data) {
8508
8561
 
8509
8562
  // src/sbf/index.ts
8510
8563
  var CLIGHT = 299792458;
8511
- var GPS_EPOCH_MS13 = Date.UTC(1980, 0, 6);
8564
+ var GPS_EPOCH_MS14 = Date.UTC(1980, 0, 6);
8512
8565
  var MS_PER_WEEK7 = 7 * 864e5;
8513
8566
  var M3_SYS = ["G", "R", "E", "C", "S", "J", "I"];
8514
8567
  var M3_PR_BASE = [19e6, 19e6, 22e6, 2e7, 34e6, 34e6, 34e6];
@@ -9162,7 +9215,7 @@ function parseSbfMeas(data) {
9162
9215
  const tow = view.getUint32(i + 8, true);
9163
9216
  const wnc = view.getUint16(i + 12, true);
9164
9217
  if (tow !== 4294967295 && wnc !== 65535) {
9165
- ensureEpoch(GPS_EPOCH_MS13 + wnc * MS_PER_WEEK7 + tow);
9218
+ ensureEpoch(GPS_EPOCH_MS14 + wnc * MS_PER_WEEK7 + tow);
9166
9219
  if (id === 4109) decodeMeas3Ranges(i, tow);
9167
9220
  else if (id === 4110) decodeMeas3CN0(i, len);
9168
9221
  else if (id === 4111) decodeMeas3Doppler(i, len);
@@ -9229,15 +9282,15 @@ var ID_GPSEPHEM = 7;
9229
9282
  var ID_BDSEPHEMERIS = 1696;
9230
9283
  var ID_RAWWAASFRAME = 287;
9231
9284
  var ID_RAWSBASFRAME = 973;
9232
- var GPS_EPOCH_MS14 = Date.UTC(1980, 0, 6);
9285
+ var GPS_EPOCH_MS15 = Date.UTC(1980, 0, 6);
9233
9286
  var BDT_EPOCH_MS3 = Date.UTC(2006, 0, 1);
9234
9287
  var SEC_PER_WEEK9 = 7 * 86400;
9235
9288
  var SEC_PER_DAY2 = 86400;
9236
9289
  var MS_PER_WEEK8 = SEC_PER_WEEK9 * 1e3;
9237
- var gpsMs2 = (week, sec) => GPS_EPOCH_MS14 + week * MS_PER_WEEK8 + sec * 1e3;
9290
+ var gpsMs2 = (week, sec) => GPS_EPOCH_MS15 + week * MS_PER_WEEK8 + sec * 1e3;
9238
9291
  var sowOf3 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK9;
9239
9292
  function nearWeekMs(refMs, sow) {
9240
- const refWeek = Math.floor((refMs - GPS_EPOCH_MS14) / MS_PER_WEEK8);
9293
+ const refWeek = Math.floor((refMs - GPS_EPOCH_MS15) / MS_PER_WEEK8);
9241
9294
  let ms = gpsMs2(refWeek, sow);
9242
9295
  if (ms < refMs - MS_PER_WEEK8 / 2) ms += MS_PER_WEEK8;
9243
9296
  else if (ms > refMs + MS_PER_WEEK8 / 2) ms -= MS_PER_WEEK8;
@@ -9264,9 +9317,9 @@ function decodeGloEphemeris(view, p) {
9264
9317
  tof += Math.floor(tow / SEC_PER_DAY2) * SEC_PER_DAY2;
9265
9318
  if (tof < tow - 43200) tof += SEC_PER_DAY2;
9266
9319
  else if (tof > tow + 43200) tof -= SEC_PER_DAY2;
9267
- const toeGpsMs = GPS_EPOCH_MS14 + (week * SEC_PER_WEEK9 + tow) * 1e3;
9268
- const tofGpsMs = GPS_EPOCH_MS14 + (week * SEC_PER_WEEK9 + tof) * 1e3;
9269
- const tofUtcSec = (getUtcDate(new Date(tofGpsMs)).getTime() - GPS_EPOCH_MS14) / 1e3;
9320
+ const toeGpsMs = GPS_EPOCH_MS15 + (week * SEC_PER_WEEK9 + tow) * 1e3;
9321
+ const tofGpsMs = GPS_EPOCH_MS15 + (week * SEC_PER_WEEK9 + tof) * 1e3;
9322
+ const tofUtcSec = (getUtcDate(new Date(tofGpsMs)).getTime() - GPS_EPOCH_MS15) / 1e3;
9270
9323
  return {
9271
9324
  system: "R",
9272
9325
  prn: `R${String(slot).padStart(2, "0")}`,
@@ -9331,7 +9384,7 @@ function decodeGalEphemeris(view, p, headerMs) {
9331
9384
  omega: view.getFloat64(p + 60, true),
9332
9385
  omegaDot: view.getFloat64(p + 140, true),
9333
9386
  idot: view.getFloat64(p + 124, true),
9334
- week: Math.floor((toeMs - GPS_EPOCH_MS14) / MS_PER_WEEK8),
9387
+ week: Math.floor((toeMs - GPS_EPOCH_MS15) / MS_PER_WEEK8),
9335
9388
  // RINEX Galileo SVH bit layout (E1B DVS/HS in bits 0-2, E5a in
9336
9389
  // 3-5, E5b in 6-8) — same packing as RTKLIB.
9337
9390
  svHealth: svhE5b << 7 | dvsE5b << 6 | svhE5a << 4 | dvsE5a << 3 | svhE1b << 1 | dvsE1b,
@@ -9517,8 +9570,57 @@ function parseNovatelNav(data, opts = {}) {
9517
9570
  };
9518
9571
  }
9519
9572
 
9573
+ // src/novatel/pvt.ts
9574
+ var GPS_EPOCH_MS16 = Date.UTC(1980, 0, 6);
9575
+ var BESTPOS = 42;
9576
+ function posTypeToMode(t) {
9577
+ if (t === 0) return "no-pvt";
9578
+ if (t === 16) return "standalone";
9579
+ if (t === 17) return "differential";
9580
+ if (t === 18 || t === 20) return "sbas-aided";
9581
+ if (t === 32 || t === 33 || t === 34) return "rtk-float";
9582
+ if (t === 48 || t === 50) return "rtk-fixed";
9583
+ if (t >= 68 && t <= 78) return "ppp";
9584
+ return `mode-${t}`;
9585
+ }
9586
+ function parseNovatelPvt(data) {
9587
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
9588
+ const records = [];
9589
+ let messages = 0;
9590
+ const stats = { badCrc: 0 };
9591
+ for (const f of oem4Frames(data, view, stats)) {
9592
+ if (f.id !== BESTPOS || !f.binary || f.msgLen < 72) continue;
9593
+ messages++;
9594
+ const p = f.payload;
9595
+ const posType = view.getUint32(p + 4, true);
9596
+ const lat = view.getFloat64(p + 8, true);
9597
+ const lon = view.getFloat64(p + 16, true);
9598
+ const hgtMsl = view.getFloat64(p + 24, true);
9599
+ const undulation = view.getFloat32(p + 32, true);
9600
+ const latSig = view.getFloat32(p + 40, true);
9601
+ const lonSig = view.getFloat32(p + 44, true);
9602
+ const hgtSig = view.getFloat32(p + 48, true);
9603
+ const nrSV = view.getUint8(p + 65);
9604
+ const hasFix = posType !== 0 && Number.isFinite(lat) && Number.isFinite(lon);
9605
+ records.push({
9606
+ timeMs: GPS_EPOCH_MS16 + f.week * 6048e5 + f.towMs,
9607
+ week: f.week,
9608
+ tow: f.towMs / 1e3,
9609
+ mode: posTypeToMode(posType),
9610
+ latDeg: hasFix ? lat : null,
9611
+ lonDeg: hasFix ? lon : null,
9612
+ // BESTPOS height is above MSL; ellipsoidal = MSL + geoid undulation.
9613
+ heightM: hasFix ? hgtMsl + undulation : null,
9614
+ nrSV,
9615
+ hAccuracyM: hasFix ? Math.hypot(latSig, lonSig) : null,
9616
+ vAccuracyM: hasFix ? hgtSig : null
9617
+ });
9618
+ }
9619
+ return { records, messages };
9620
+ }
9621
+
9520
9622
  // src/novatel/index.ts
9521
- var GPS_EPOCH_MS15 = Date.UTC(1980, 0, 6);
9623
+ var GPS_EPOCH_MS17 = Date.UTC(1980, 0, 6);
9522
9624
  var MS_PER_WEEK9 = 7 * 864e5;
9523
9625
  var HDR = 28;
9524
9626
  var ID_RANGE = 43;
@@ -9688,7 +9790,7 @@ function parseNovatelRange(data) {
9688
9790
  if (!codes.includes(code)) codes.push(code);
9689
9791
  }
9690
9792
  epochs.push({
9691
- timeMs: GPS_EPOCH_MS15 + week * MS_PER_WEEK9 + towMs,
9793
+ timeMs: GPS_EPOCH_MS17 + week * MS_PER_WEEK9 + towMs,
9692
9794
  meas
9693
9795
  });
9694
9796
  }
@@ -9740,7 +9842,7 @@ function parseNovatelRange(data) {
9740
9842
  if (!codes.includes(code)) codes.push(code);
9741
9843
  }
9742
9844
  epochs.push({
9743
- timeMs: GPS_EPOCH_MS15 + week * MS_PER_WEEK9 + towMs,
9845
+ timeMs: GPS_EPOCH_MS17 + week * MS_PER_WEEK9 + towMs,
9744
9846
  meas
9745
9847
  });
9746
9848
  }
@@ -9791,14 +9893,14 @@ function* trimbleFrames(data, stats) {
9791
9893
  }
9792
9894
 
9793
9895
  // src/trimble/nav.ts
9794
- var GPS_EPOCH_MS16 = Date.UTC(1980, 0, 6);
9896
+ var GPS_EPOCH_MS18 = Date.UTC(1980, 0, 6);
9795
9897
  var BDT_EPOCH_MS4 = Date.UTC(2006, 0, 1);
9796
9898
  var SEC_PER_WEEK10 = 7 * 86400;
9797
9899
  var MS_PER_WEEK10 = SEC_PER_WEEK10 * 1e3;
9798
9900
  var GPS_PI2 = 3.1415926535898;
9799
9901
  var BDS_WEEK_OFFSET = 1356;
9800
9902
  var BDS_LEAP_SEC = 14;
9801
- var gpsMs3 = (week, sec) => GPS_EPOCH_MS16 + week * MS_PER_WEEK10 + sec * 1e3;
9903
+ var gpsMs3 = (week, sec) => GPS_EPOCH_MS18 + week * MS_PER_WEEK10 + sec * 1e3;
9802
9904
  var sowOf4 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK10;
9803
9905
  var SUB_GPS_EPHEMERIS = 1;
9804
9906
  var SUB_ION_UTC = 3;
@@ -9951,7 +10053,7 @@ function decodeGloEphemeris2(view, base) {
9951
10053
  // RINEX stores −τn as the clock bias; the record carries τn (ICD sign).
9952
10054
  tauN: -view.getFloat64(base + 113, false),
9953
10055
  gammaN: view.getFloat64(base + 121, false),
9954
- messageFrameTime: (tocMs - GPS_EPOCH_MS16) / 1e3 % SEC_PER_WEEK10,
10056
+ messageFrameTime: (tocMs - GPS_EPOCH_MS18) / 1e3 % SEC_PER_WEEK10,
9955
10057
  // State vector: metres / m·s⁻¹ / m·s⁻² → km / km·s⁻¹ / km·s⁻².
9956
10058
  x: view.getFloat64(base + 33, false) / 1e3,
9957
10059
  xDot: view.getFloat64(base + 41, false) / 1e3,
@@ -10022,7 +10124,7 @@ function parseTrimbleNav(data) {
10022
10124
  }
10023
10125
 
10024
10126
  // src/trimble/index.ts
10025
- var GPS_EPOCH_MS17 = Date.UTC(1980, 0, 6);
10127
+ var GPS_EPOCH_MS19 = Date.UTC(1980, 0, 6);
10026
10128
  var MS_PER_WEEK11 = 7 * 864e5;
10027
10129
  var REC_TYPE_27 = 6;
10028
10130
  var SYS = {
@@ -10220,7 +10322,7 @@ function decodeEpoch(epoch, epochs, obsCodes) {
10220
10322
  o += c.length;
10221
10323
  }
10222
10324
  const dv = new DataView(M.buffer, M.byteOffset, M.byteLength);
10223
- const timeMs = GPS_EPOCH_MS17 + epoch.week * MS_PER_WEEK11 + epoch.towMs;
10325
+ const timeMs = GPS_EPOCH_MS19 + epoch.week * MS_PER_WEEK11 + epoch.towMs;
10224
10326
  const meas = [];
10225
10327
  let q = 0;
10226
10328
  for (let sv = 0; sv < epoch.nsv && q + 8 <= M.length; sv++) {
@@ -10401,13 +10503,13 @@ function* binexRecords(data, view, stats) {
10401
10503
  }
10402
10504
 
10403
10505
  // src/binex/nav.ts
10404
- var GPS_EPOCH_MS18 = Date.UTC(1980, 0, 6);
10506
+ var GPS_EPOCH_MS20 = Date.UTC(1980, 0, 6);
10405
10507
  var GLO_DAY0_MS = Date.UTC(1980, 0, 1);
10406
10508
  var BDT_EPOCH_MS5 = Date.UTC(2006, 0, 1);
10407
10509
  var SEC_PER_WEEK11 = 7 * 86400;
10408
10510
  var MS_PER_WEEK12 = SEC_PER_WEEK11 * 1e3;
10409
10511
  var SC2RAD = GPS_PI;
10410
- var gpsMs4 = (week, sec) => GPS_EPOCH_MS18 + week * MS_PER_WEEK12 + sec * 1e3;
10512
+ var gpsMs4 = (week, sec) => GPS_EPOCH_MS20 + week * MS_PER_WEEK12 + sec * 1e3;
10411
10513
  var sowOf5 = (dateMs) => (dateMs / 1e3 % SEC_PER_WEEK11 + SEC_PER_WEEK11) % SEC_PER_WEEK11;
10412
10514
  var two6 = (n) => String(n).padStart(2, "0");
10413
10515
  var Reader = class {
@@ -10695,7 +10797,7 @@ function decodeBinexEph(view, body, len, le) {
10695
10797
  }
10696
10798
 
10697
10799
  // src/binex/index.ts
10698
- var GPS_EPOCH_MS19 = Date.UTC(1980, 0, 6);
10800
+ var GPS_EPOCH_MS21 = Date.UTC(1980, 0, 6);
10699
10801
  var CLIGHT2 = 299792458;
10700
10802
  var OBS_CODES = {
10701
10803
  0: [
@@ -10953,7 +11055,7 @@ function decodeObsRecord(data, view, body, len, obsCodes) {
10953
11055
  p += 4;
10954
11056
  const msec = view.getUint16(p);
10955
11057
  p += 2;
10956
- const timeMs = GPS_EPOCH_MS19 + min * 6e4 + msec;
11058
+ const timeMs = GPS_EPOCH_MS21 + min * 6e4 + msec;
10957
11059
  const flag = data[p++];
10958
11060
  const nsat = (flag & 63) + 1;
10959
11061
  if (flag & 128) p += 3;
@@ -11039,7 +11141,7 @@ function parseBinex(data) {
11039
11141
  var GM_GPS = 3986005e8;
11040
11142
  var GM_GAL = 3986004418e5;
11041
11143
  var GM_BDS = 3986004418e5;
11042
- var GPS_EPOCH_MS20 = Date.UTC(1980, 0, 6);
11144
+ var GPS_EPOCH_MS22 = Date.UTC(1980, 0, 6);
11043
11145
  var BDT_EPOCH_MS6 = Date.UTC(2006, 0, 1);
11044
11146
  var WEEK_MS = 6048e5;
11045
11147
  var BDT_MINUS_GPST_MS = 14e3;
@@ -11048,7 +11150,7 @@ function almanacEpochMs(alm) {
11048
11150
  if (alm.system === "C") {
11049
11151
  return BDT_EPOCH_MS6 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3 + BDT_MINUS_GPST_MS;
11050
11152
  }
11051
- return GPS_EPOCH_MS20 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3;
11153
+ return GPS_EPOCH_MS22 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3;
11052
11154
  }
11053
11155
  function almanacSatPosition(alm, timeMs) {
11054
11156
  const GM = alm.system === "E" ? GM_GAL : alm.system === "C" ? GM_BDS : GM_GPS;
@@ -11557,10 +11659,10 @@ function selectBest(ephs, timeMs) {
11557
11659
  }
11558
11660
  return best;
11559
11661
  }
11560
- var GPS_EPOCH_MS21 = START_GPS_TIME.getTime();
11662
+ var GPS_EPOCH_MS23 = START_GPS_TIME.getTime();
11561
11663
  var MS_PER_WEEK13 = 7 * 864e5;
11562
11664
  var BDS_EPOCH_MS = START_BDS_TIME.getTime();
11563
- var GAL_EPOCH_MS = GPS_EPOCH_MS21 + 1024 * MS_PER_WEEK13;
11665
+ var GAL_EPOCH_MS = GPS_EPOCH_MS23 + 1024 * MS_PER_WEEK13;
11564
11666
  function ephInfoToEphemeris(info) {
11565
11667
  const sys = info.prn.charAt(0);
11566
11668
  if (sys === "R") {
@@ -11611,8 +11713,8 @@ function ephInfoToEphemeris(info) {
11611
11713
  } else if (sys === "E") {
11612
11714
  epochMs = GAL_EPOCH_MS;
11613
11715
  } else {
11614
- epochMs = GPS_EPOCH_MS21;
11615
- const weeksNow = (info.lastReceived - GPS_EPOCH_MS21) / MS_PER_WEEK13;
11716
+ epochMs = GPS_EPOCH_MS23;
11717
+ const weeksNow = (info.lastReceived - GPS_EPOCH_MS23) / MS_PER_WEEK13;
11616
11718
  week += 1024 * Math.round((weeksNow - week) / 1024);
11617
11719
  }
11618
11720
  const tocDate = new Date(epochMs + week * MS_PER_WEEK13 + tocSec * 1e3);
@@ -17819,6 +17921,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
17819
17921
  parseNavFile,
17820
17922
  parseNmeaFile,
17821
17923
  parseNovatelNav,
17924
+ parseNovatelPvt,
17822
17925
  parseNovatelRange,
17823
17926
  parseRinexStream,
17824
17927
  parseSbfAlmanac,
@@ -17842,6 +17945,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
17842
17945
  parseUbxCnav,
17843
17946
  parseUbxIonoUtc,
17844
17947
  parseUbxNav,
17948
+ parseUbxPvt,
17845
17949
  parseUbxRawNav,
17846
17950
  parseUbxRawx,
17847
17951
  phiAltBOC,
package/dist/index.d.cts CHANGED
@@ -1,3 +1,4 @@
1
+ export { R as ReceiverPvt } from './receiver-pvt-CVFvi4kT.cjs';
1
2
  export { D as DAYS_MJD2000_MJD, a as DAYS_MJD_JULIAN, H as HourCode, M as MILLISECONDS_GPS_TAI, b as MILLISECONDS_IN_DAY, c as MILLISECONDS_IN_HOUR, d as MILLISECONDS_IN_MINUTE, e as MILLISECONDS_IN_SECOND, f as MILLISECONDS_IN_WEEK, g as MILLISECONDS_TT_TAI, R as RINEX_CODES, S as SECONDS_IN_DAY, h as SECONDS_IN_HOUR, i as SECONDS_IN_MINUTE, j as SECONDS_IN_WEEK, k as START_BDS_TIME, l as START_GAL_TIME, m as START_GLO_LEAP, n as START_GPS_TIME, o as START_JULIAN_TAI, p as START_MJD_UNIX_SECONDS, q as START_NTP_TIME, r as START_TAI_TIME, s as START_UNIX_TIME, T as TimeDifference } from './time-DnI1VpE8.cjs';
2
3
  export { WGS84_ECCENTRICITY_SQUARED, WGS84_FLATTENING, WGS84_SEMI_MAJOR_AXIS, WGS84_SEMI_MINOR_AXIS } from './constants.cjs';
3
4
  export { A as ARC_GAP_FACTOR, B as BAND_LABELS, a as BDS_SATELLITES, b as BdsSatellite, C as C_LIGHT, D as DEFAULT_ELEV_MASK_DEG, c as DUAL_FREQ_PAIRS, F as FREQ, G as GLO_CHANNEL_FALLBACK, d as GLO_F1_BASE, e as GLO_F1_STEP, f as GLO_F2_BASE, g as GLO_F2_STEP, h as GLO_F3, O as OMEGA_E, i as OnSlipDetected, S as SYSTEM_NAMES, j as SYS_SHORT, k as buildGloChannelMap, l as buildObsIndices, m as formatUTCTime, n as getFreq, o as gloFreq } from './gnss-BtXrG3zH.cjs';
@@ -10,9 +11,9 @@ export { C as CnavEphemeris, E as Ephemeris, G as GlonassEphemeris, K as KeplerE
10
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';
11
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';
12
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 { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxRawNavOptions, UbxRawNavResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxRawNav, parseUbxRawx, ubxFrames } from './ubx.cjs';
14
+ export { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxPvtResult, UbxRawNavOptions, UbxRawNavResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxPvt, parseUbxRawNav, parseUbxRawx, ubxFrames } from './ubx.cjs';
14
15
  export { HasMessage, SbfBdsNavResult, SbfCnavEphemeris, SbfCnavResult, SbfGalEphemeris, SbfGalNavResult, SbfGeoNavResult, SbfGloNavResult, SbfGpsNavResult, SbfHasMessage, SbfHasResult, SbfIonoUtcResult, SbfMeasEpoch, SbfMeasurement, SbfNavCounts, SbfNavigation, SbfParseResult, SbfPvt, SbfPvtResult, SbfReceiverSetup, decodeSbfNavigation, feedGeoBlock, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, sbfCrc16, scanSbfFrames } from './sbf.cjs';
15
- export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelRange } from './novatel.cjs';
16
+ export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, NovatelPvtResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelPvt, parseNovatelRange } from './novatel.cjs';
16
17
  export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, TrimbleParseResult, parseTrimble, parseTrimbleNav, trimbleFrames } from './trimble.cjs';
17
18
  export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.cjs';
18
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';
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export { R as ReceiverPvt } from './receiver-pvt-CVFvi4kT.js';
1
2
  export { D as DAYS_MJD2000_MJD, a as DAYS_MJD_JULIAN, H as HourCode, M as MILLISECONDS_GPS_TAI, b as MILLISECONDS_IN_DAY, c as MILLISECONDS_IN_HOUR, d as MILLISECONDS_IN_MINUTE, e as MILLISECONDS_IN_SECOND, f as MILLISECONDS_IN_WEEK, g as MILLISECONDS_TT_TAI, R as RINEX_CODES, S as SECONDS_IN_DAY, h as SECONDS_IN_HOUR, i as SECONDS_IN_MINUTE, j as SECONDS_IN_WEEK, k as START_BDS_TIME, l as START_GAL_TIME, m as START_GLO_LEAP, n as START_GPS_TIME, o as START_JULIAN_TAI, p as START_MJD_UNIX_SECONDS, q as START_NTP_TIME, r as START_TAI_TIME, s as START_UNIX_TIME, T as TimeDifference } from './time-DnI1VpE8.js';
2
3
  export { WGS84_ECCENTRICITY_SQUARED, WGS84_FLATTENING, WGS84_SEMI_MAJOR_AXIS, WGS84_SEMI_MINOR_AXIS } from './constants.js';
3
4
  export { A as ARC_GAP_FACTOR, B as BAND_LABELS, a as BDS_SATELLITES, b as BdsSatellite, C as C_LIGHT, D as DEFAULT_ELEV_MASK_DEG, c as DUAL_FREQ_PAIRS, F as FREQ, G as GLO_CHANNEL_FALLBACK, d as GLO_F1_BASE, e as GLO_F1_STEP, f as GLO_F2_BASE, g as GLO_F2_STEP, h as GLO_F3, O as OMEGA_E, i as OnSlipDetected, S as SYSTEM_NAMES, j as SYS_SHORT, k as buildGloChannelMap, l as buildObsIndices, m as formatUTCTime, n as getFreq, o as gloFreq } from './gnss-DhnEr0Dy.js';
@@ -10,9 +11,9 @@ export { C as CnavEphemeris, E as Ephemeris, G as GlonassEphemeris, K as KeplerE
10
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';
11
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';
12
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 { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxRawNavOptions, UbxRawNavResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxRawNav, parseUbxRawx, ubxFrames } from './ubx.js';
14
+ export { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxPvtResult, UbxRawNavOptions, UbxRawNavResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxPvt, parseUbxRawNav, parseUbxRawx, ubxFrames } from './ubx.js';
14
15
  export { HasMessage, SbfBdsNavResult, SbfCnavEphemeris, SbfCnavResult, SbfGalEphemeris, SbfGalNavResult, SbfGeoNavResult, SbfGloNavResult, SbfGpsNavResult, SbfHasMessage, SbfHasResult, SbfIonoUtcResult, SbfMeasEpoch, SbfMeasurement, SbfNavCounts, SbfNavigation, SbfParseResult, SbfPvt, SbfPvtResult, SbfReceiverSetup, decodeSbfNavigation, feedGeoBlock, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, sbfCrc16, scanSbfFrames } from './sbf.js';
15
- export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelRange } from './novatel.js';
16
+ export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, NovatelPvtResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelPvt, parseNovatelRange } from './novatel.js';
16
17
  export { TrimbleEpoch, TrimbleFrame, TrimbleMeasurement, TrimbleNavResult, TrimbleParseResult, parseTrimble, parseTrimbleNav, trimbleFrames } from './trimble.js';
17
18
  export { BinexEpoch, BinexMeasurement, BinexParseResult, BinexRecord, binexCrc16, binexCrc32, binexCsum8, binexRecords, decodeBinexEph, getBnxi, parseBinex } from './binex.js';
18
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';
package/dist/index.js CHANGED
@@ -47,10 +47,11 @@ import {
47
47
  parseUbxCnav,
48
48
  parseUbxIonoUtc,
49
49
  parseUbxNav,
50
+ parseUbxPvt,
50
51
  parseUbxRawNav,
51
52
  parseUbxRawx,
52
53
  ubxFrames
53
- } from "./chunk-DEVUKH6A.js";
54
+ } from "./chunk-MRC6LIPM.js";
54
55
  import {
55
56
  crc16,
56
57
  decodeSbfNavigation,
@@ -76,8 +77,9 @@ import {
76
77
  crc32,
77
78
  oem4Frames,
78
79
  parseNovatelNav,
80
+ parseNovatelPvt,
79
81
  parseNovatelRange
80
- } from "./chunk-ZS5RLFWI.js";
82
+ } from "./chunk-KUTNIP3O.js";
81
83
  import {
82
84
  parseTrimble,
83
85
  parseTrimbleNav,
@@ -594,6 +596,7 @@ export {
594
596
  parseNavFile,
595
597
  parseNmeaFile,
596
598
  parseNovatelNav,
599
+ parseNovatelPvt,
597
600
  parseNovatelRange,
598
601
  parseRinexStream,
599
602
  parseSbfAlmanac,
@@ -617,6 +620,7 @@ export {
617
620
  parseUbxCnav,
618
621
  parseUbxIonoUtc,
619
622
  parseUbxNav,
623
+ parseUbxPvt,
620
624
  parseUbxRawNav,
621
625
  parseUbxRawx,
622
626
  phiAltBOC,
package/dist/novatel.cjs CHANGED
@@ -24,6 +24,7 @@ __export(novatel_exports, {
24
24
  crc32: () => crc32,
25
25
  oem4Frames: () => oem4Frames,
26
26
  parseNovatelNav: () => parseNovatelNav,
27
+ parseNovatelPvt: () => parseNovatelPvt,
27
28
  parseNovatelRange: () => parseNovatelRange
28
29
  });
29
30
  module.exports = __toCommonJS(novatel_exports);
@@ -823,8 +824,57 @@ function parseNovatelNav(data, opts = {}) {
823
824
  };
824
825
  }
825
826
 
826
- // src/novatel/index.ts
827
+ // src/novatel/pvt.ts
827
828
  var GPS_EPOCH_MS5 = Date.UTC(1980, 0, 6);
829
+ var BESTPOS = 42;
830
+ function posTypeToMode(t) {
831
+ if (t === 0) return "no-pvt";
832
+ if (t === 16) return "standalone";
833
+ if (t === 17) return "differential";
834
+ if (t === 18 || t === 20) return "sbas-aided";
835
+ if (t === 32 || t === 33 || t === 34) return "rtk-float";
836
+ if (t === 48 || t === 50) return "rtk-fixed";
837
+ if (t >= 68 && t <= 78) return "ppp";
838
+ return `mode-${t}`;
839
+ }
840
+ function parseNovatelPvt(data) {
841
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
842
+ const records = [];
843
+ let messages = 0;
844
+ const stats = { badCrc: 0 };
845
+ for (const f of oem4Frames(data, view, stats)) {
846
+ if (f.id !== BESTPOS || !f.binary || f.msgLen < 72) continue;
847
+ messages++;
848
+ const p = f.payload;
849
+ const posType = view.getUint32(p + 4, true);
850
+ const lat = view.getFloat64(p + 8, true);
851
+ const lon = view.getFloat64(p + 16, true);
852
+ const hgtMsl = view.getFloat64(p + 24, true);
853
+ const undulation = view.getFloat32(p + 32, true);
854
+ const latSig = view.getFloat32(p + 40, true);
855
+ const lonSig = view.getFloat32(p + 44, true);
856
+ const hgtSig = view.getFloat32(p + 48, true);
857
+ const nrSV = view.getUint8(p + 65);
858
+ const hasFix = posType !== 0 && Number.isFinite(lat) && Number.isFinite(lon);
859
+ records.push({
860
+ timeMs: GPS_EPOCH_MS5 + f.week * 6048e5 + f.towMs,
861
+ week: f.week,
862
+ tow: f.towMs / 1e3,
863
+ mode: posTypeToMode(posType),
864
+ latDeg: hasFix ? lat : null,
865
+ lonDeg: hasFix ? lon : null,
866
+ // BESTPOS height is above MSL; ellipsoidal = MSL + geoid undulation.
867
+ heightM: hasFix ? hgtMsl + undulation : null,
868
+ nrSV,
869
+ hAccuracyM: hasFix ? Math.hypot(latSig, lonSig) : null,
870
+ vAccuracyM: hasFix ? hgtSig : null
871
+ });
872
+ }
873
+ return { records, messages };
874
+ }
875
+
876
+ // src/novatel/index.ts
877
+ var GPS_EPOCH_MS6 = Date.UTC(1980, 0, 6);
828
878
  var MS_PER_WEEK3 = 7 * 864e5;
829
879
  var HDR = 28;
830
880
  var ID_RANGE = 43;
@@ -994,7 +1044,7 @@ function parseNovatelRange(data) {
994
1044
  if (!codes.includes(code)) codes.push(code);
995
1045
  }
996
1046
  epochs.push({
997
- timeMs: GPS_EPOCH_MS5 + week * MS_PER_WEEK3 + towMs,
1047
+ timeMs: GPS_EPOCH_MS6 + week * MS_PER_WEEK3 + towMs,
998
1048
  meas
999
1049
  });
1000
1050
  }
@@ -1046,7 +1096,7 @@ function parseNovatelRange(data) {
1046
1096
  if (!codes.includes(code)) codes.push(code);
1047
1097
  }
1048
1098
  epochs.push({
1049
- timeMs: GPS_EPOCH_MS5 + week * MS_PER_WEEK3 + towMs,
1099
+ timeMs: GPS_EPOCH_MS6 + week * MS_PER_WEEK3 + towMs,
1050
1100
  meas
1051
1101
  });
1052
1102
  }
@@ -1061,5 +1111,6 @@ function parseNovatelRange(data) {
1061
1111
  crc32,
1062
1112
  oem4Frames,
1063
1113
  parseNovatelNav,
1114
+ parseNovatelPvt,
1064
1115
  parseNovatelRange
1065
1116
  });
@@ -1,4 +1,5 @@
1
1
  import { E as Ephemeris, C as CnavEphemeris } from './nav-DImXUdbp.cjs';
2
+ import { R as ReceiverPvt } from './receiver-pvt-CVFvi4kT.cjs';
2
3
 
3
4
  /**
4
5
  * NovAtel OEM4/6/7 binary framing shared by the measurement and
@@ -113,6 +114,13 @@ declare function parseNovatelNav(data: Uint8Array, opts?: {
113
114
  onSbasMessage?: (msg: Uint8Array, prn: number, week: number, tow: number) => void;
114
115
  }): NovatelNavResult;
115
116
 
117
+ interface NovatelPvtResult {
118
+ records: ReceiverPvt[];
119
+ messages: number;
120
+ }
121
+ /** Decode every BESTPOS (binary) message in a NovAtel OEM4/7 byte stream. */
122
+ declare function parseNovatelPvt(data: Uint8Array): NovatelPvtResult;
123
+
116
124
  /**
117
125
  * NovAtel OEM4/6/7 raw-measurement decoding (RANGE log, message 43).
118
126
  *
@@ -170,4 +178,4 @@ interface NovatelParseResult {
170
178
  */
171
179
  declare function parseNovatelRange(data: Uint8Array): NovatelParseResult;
172
180
 
173
- export { type NovatelEpoch, type NovatelMeasurement, type NovatelNavResult, type NovatelParseResult, OEM4_HLEN, type Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelRange };
181
+ export { type NovatelEpoch, type NovatelMeasurement, type NovatelNavResult, type NovatelParseResult, type NovatelPvtResult, OEM4_HLEN, type Oem4Frame, ReceiverPvt, crc32, oem4Frames, parseNovatelNav, parseNovatelPvt, parseNovatelRange };
package/dist/novatel.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { E as Ephemeris, C as CnavEphemeris } from './nav-DImXUdbp.js';
2
+ import { R as ReceiverPvt } from './receiver-pvt-CVFvi4kT.js';
2
3
 
3
4
  /**
4
5
  * NovAtel OEM4/6/7 binary framing shared by the measurement and
@@ -113,6 +114,13 @@ declare function parseNovatelNav(data: Uint8Array, opts?: {
113
114
  onSbasMessage?: (msg: Uint8Array, prn: number, week: number, tow: number) => void;
114
115
  }): NovatelNavResult;
115
116
 
117
+ interface NovatelPvtResult {
118
+ records: ReceiverPvt[];
119
+ messages: number;
120
+ }
121
+ /** Decode every BESTPOS (binary) message in a NovAtel OEM4/7 byte stream. */
122
+ declare function parseNovatelPvt(data: Uint8Array): NovatelPvtResult;
123
+
116
124
  /**
117
125
  * NovAtel OEM4/6/7 raw-measurement decoding (RANGE log, message 43).
118
126
  *
@@ -170,4 +178,4 @@ interface NovatelParseResult {
170
178
  */
171
179
  declare function parseNovatelRange(data: Uint8Array): NovatelParseResult;
172
180
 
173
- export { type NovatelEpoch, type NovatelMeasurement, type NovatelNavResult, type NovatelParseResult, OEM4_HLEN, type Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelRange };
181
+ export { type NovatelEpoch, type NovatelMeasurement, type NovatelNavResult, type NovatelParseResult, type NovatelPvtResult, OEM4_HLEN, type Oem4Frame, ReceiverPvt, crc32, oem4Frames, parseNovatelNav, parseNovatelPvt, parseNovatelRange };
package/dist/novatel.js CHANGED
@@ -3,8 +3,9 @@ import {
3
3
  crc32,
4
4
  oem4Frames,
5
5
  parseNovatelNav,
6
+ parseNovatelPvt,
6
7
  parseNovatelRange
7
- } from "./chunk-ZS5RLFWI.js";
8
+ } from "./chunk-KUTNIP3O.js";
8
9
  import "./chunk-WQX354KD.js";
9
10
  import "./chunk-YUW33VXK.js";
10
11
  import "./chunk-V2D5KUKH.js";
@@ -15,5 +16,6 @@ export {
15
16
  crc32,
16
17
  oem4Frames,
17
18
  parseNovatelNav,
19
+ parseNovatelPvt,
18
20
  parseNovatelRange
19
21
  };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * A receiver's own navigation solution (position/velocity/time), normalised
3
+ * across manufacturers: Septentrio PVTGeodetic, NovAtel BESTPOS, u-blox
4
+ * NAV-PVT. Useful as a truth/reference to cross-check an independent SPP/SBAS
5
+ * solution against (position + accuracy), and to know the receiver's own
6
+ * solution mode.
7
+ */
8
+ interface ReceiverPvt {
9
+ /** GPS-scale epoch time (ms). */
10
+ timeMs: number;
11
+ week: number;
12
+ /** Time of week (s). */
13
+ tow: number;
14
+ /** Solution mode: 'standalone' | 'differential' | 'sbas-aided' |
15
+ * 'rtk-float' | 'rtk-fixed' | 'ppp' | 'no-pvt' | 'fixed-location' | … */
16
+ mode: string;
17
+ latDeg: number | null;
18
+ lonDeg: number | null;
19
+ /** Ellipsoidal height (m). */
20
+ heightM: number | null;
21
+ /** Satellites used in the receiver's solution. */
22
+ nrSV: number | null;
23
+ /** Receiver horizontal accuracy estimate (m). */
24
+ hAccuracyM: number | null;
25
+ /** Receiver vertical accuracy estimate (m). */
26
+ vAccuracyM: number | null;
27
+ }
28
+
29
+ export type { ReceiverPvt as R };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * A receiver's own navigation solution (position/velocity/time), normalised
3
+ * across manufacturers: Septentrio PVTGeodetic, NovAtel BESTPOS, u-blox
4
+ * NAV-PVT. Useful as a truth/reference to cross-check an independent SPP/SBAS
5
+ * solution against (position + accuracy), and to know the receiver's own
6
+ * solution mode.
7
+ */
8
+ interface ReceiverPvt {
9
+ /** GPS-scale epoch time (ms). */
10
+ timeMs: number;
11
+ week: number;
12
+ /** Time of week (s). */
13
+ tow: number;
14
+ /** Solution mode: 'standalone' | 'differential' | 'sbas-aided' |
15
+ * 'rtk-float' | 'rtk-fixed' | 'ppp' | 'no-pvt' | 'fixed-location' | … */
16
+ mode: string;
17
+ latDeg: number | null;
18
+ lonDeg: number | null;
19
+ /** Ellipsoidal height (m). */
20
+ heightM: number | null;
21
+ /** Satellites used in the receiver's solution. */
22
+ nrSV: number | null;
23
+ /** Receiver horizontal accuracy estimate (m). */
24
+ hAccuracyM: number | null;
25
+ /** Receiver vertical accuracy estimate (m). */
26
+ vAccuracyM: number | null;
27
+ }
28
+
29
+ export type { ReceiverPvt as R };
package/dist/sbf.d.cts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { S as SbfAlmanac, a as SbfAlmanacResult, b as SbfGlonassAlmanac, c as SbfKeplerAlmanac, d as SbfNavResult, p as parseSbfAlmanac, e as parseSbfNav } from './nav-BYmYoh9A.cjs';
2
+ import { R as ReceiverPvt } from './receiver-pvt-CVFvi4kT.cjs';
2
3
  import { K as KeplerEphemeris, C as CnavEphemeris, E as Ephemeris, G as GlonassEphemeris } from './nav-DImXUdbp.cjs';
3
4
 
4
5
  /**
@@ -124,26 +125,9 @@ interface SbfReceiverSetup {
124
125
  */
125
126
  declare function parseSbfReceiverSetup(data: Uint8Array): SbfReceiverSetup | null;
126
127
 
127
- interface SbfPvt {
128
- /** GPS-scale epoch time (ms). */
129
- timeMs: number;
130
- week: number;
131
- /** Time of week (s). */
132
- tow: number;
133
- /** PVT solution type (Mode & 0x0F). */
128
+ interface SbfPvt extends ReceiverPvt {
129
+ /** PVT solution type (Mode & 0x0F) — the raw Septentrio code. */
134
130
  modeType: number;
135
- /** Human label for `modeType` ('standalone', 'sbas-aided', 'rtk-fixed', …). */
136
- mode: string;
137
- /** Geodetic position, or null when the receiver has no fix this epoch. */
138
- latDeg: number | null;
139
- lonDeg: number | null;
140
- heightM: number | null;
141
- /** Satellites used in the receiver's solution. */
142
- nrSV: number | null;
143
- /** Receiver 2-σ horizontal accuracy estimate (m), or null. */
144
- hAccuracyM: number | null;
145
- /** Receiver 2-σ vertical accuracy estimate (m), or null. */
146
- vAccuracyM: number | null;
147
131
  }
148
132
  interface SbfPvtResult {
149
133
  records: SbfPvt[];
@@ -663,4 +647,4 @@ interface SbfParseResult {
663
647
  */
664
648
  declare function parseSbfMeas(data: Uint8Array): SbfParseResult;
665
649
 
666
- export { CnavEphemeris, type HasMessage, type SbfBdsNavResult, type SbfCnavEphemeris, type SbfCnavResult, type SbfGalEphemeris, type SbfGalNavResult, type SbfGeoNavResult, type SbfGloNavResult, type SbfGpsNavResult, type SbfHasMessage, type SbfHasResult, type SbfIonoUtcResult, type SbfMeasEpoch, type SbfMeasurement, type SbfNavCounts, type SbfNavigation, type SbfParseResult, type SbfPvt, type SbfPvtResult, type SbfReceiverSetup, decodeSbfNavigation, feedGeoBlock, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, crc16 as sbfCrc16, scanSbfFrames };
650
+ export { CnavEphemeris, type HasMessage, ReceiverPvt, type SbfBdsNavResult, type SbfCnavEphemeris, type SbfCnavResult, type SbfGalEphemeris, type SbfGalNavResult, type SbfGeoNavResult, type SbfGloNavResult, type SbfGpsNavResult, type SbfHasMessage, type SbfHasResult, type SbfIonoUtcResult, type SbfMeasEpoch, type SbfMeasurement, type SbfNavCounts, type SbfNavigation, type SbfParseResult, type SbfPvt, type SbfPvtResult, type SbfReceiverSetup, decodeSbfNavigation, feedGeoBlock, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, crc16 as sbfCrc16, scanSbfFrames };
package/dist/sbf.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { S as SbfAlmanac, a as SbfAlmanacResult, b as SbfGlonassAlmanac, c as SbfKeplerAlmanac, d as SbfNavResult, p as parseSbfAlmanac, e as parseSbfNav } from './nav-CN8rxL4h.js';
2
+ import { R as ReceiverPvt } from './receiver-pvt-CVFvi4kT.js';
2
3
  import { K as KeplerEphemeris, C as CnavEphemeris, E as Ephemeris, G as GlonassEphemeris } from './nav-DImXUdbp.js';
3
4
 
4
5
  /**
@@ -124,26 +125,9 @@ interface SbfReceiverSetup {
124
125
  */
125
126
  declare function parseSbfReceiverSetup(data: Uint8Array): SbfReceiverSetup | null;
126
127
 
127
- interface SbfPvt {
128
- /** GPS-scale epoch time (ms). */
129
- timeMs: number;
130
- week: number;
131
- /** Time of week (s). */
132
- tow: number;
133
- /** PVT solution type (Mode & 0x0F). */
128
+ interface SbfPvt extends ReceiverPvt {
129
+ /** PVT solution type (Mode & 0x0F) — the raw Septentrio code. */
134
130
  modeType: number;
135
- /** Human label for `modeType` ('standalone', 'sbas-aided', 'rtk-fixed', …). */
136
- mode: string;
137
- /** Geodetic position, or null when the receiver has no fix this epoch. */
138
- latDeg: number | null;
139
- lonDeg: number | null;
140
- heightM: number | null;
141
- /** Satellites used in the receiver's solution. */
142
- nrSV: number | null;
143
- /** Receiver 2-σ horizontal accuracy estimate (m), or null. */
144
- hAccuracyM: number | null;
145
- /** Receiver 2-σ vertical accuracy estimate (m), or null. */
146
- vAccuracyM: number | null;
147
131
  }
148
132
  interface SbfPvtResult {
149
133
  records: SbfPvt[];
@@ -663,4 +647,4 @@ interface SbfParseResult {
663
647
  */
664
648
  declare function parseSbfMeas(data: Uint8Array): SbfParseResult;
665
649
 
666
- export { CnavEphemeris, type HasMessage, type SbfBdsNavResult, type SbfCnavEphemeris, type SbfCnavResult, type SbfGalEphemeris, type SbfGalNavResult, type SbfGeoNavResult, type SbfGloNavResult, type SbfGpsNavResult, type SbfHasMessage, type SbfHasResult, type SbfIonoUtcResult, type SbfMeasEpoch, type SbfMeasurement, type SbfNavCounts, type SbfNavigation, type SbfParseResult, type SbfPvt, type SbfPvtResult, type SbfReceiverSetup, decodeSbfNavigation, feedGeoBlock, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, crc16 as sbfCrc16, scanSbfFrames };
650
+ export { CnavEphemeris, type HasMessage, ReceiverPvt, type SbfBdsNavResult, type SbfCnavEphemeris, type SbfCnavResult, type SbfGalEphemeris, type SbfGalNavResult, type SbfGeoNavResult, type SbfGloNavResult, type SbfGpsNavResult, type SbfHasMessage, type SbfHasResult, type SbfIonoUtcResult, type SbfMeasEpoch, type SbfMeasurement, type SbfNavCounts, type SbfNavigation, type SbfParseResult, type SbfPvt, type SbfPvtResult, type SbfReceiverSetup, decodeSbfNavigation, feedGeoBlock, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, crc16 as sbfCrc16, scanSbfFrames };
package/dist/ubx.cjs CHANGED
@@ -23,6 +23,7 @@ __export(ubx_exports, {
23
23
  parseUbxCnav: () => parseUbxCnav,
24
24
  parseUbxIonoUtc: () => parseUbxIonoUtc,
25
25
  parseUbxNav: () => parseUbxNav,
26
+ parseUbxPvt: () => parseUbxPvt,
26
27
  parseUbxRawNav: () => parseUbxRawNav,
27
28
  parseUbxRawx: () => parseUbxRawx,
28
29
  ubxFrames: () => ubxFrames
@@ -1423,8 +1424,59 @@ function parseUbxRawNav(data, opts = {}) {
1423
1424
  return { ephemerides, counts, badParity };
1424
1425
  }
1425
1426
 
1426
- // src/ubx/index.ts
1427
+ // src/ubx/pvt.ts
1427
1428
  var GPS_EPOCH_MS7 = Date.UTC(1980, 0, 6);
1429
+ function parseUbxPvt(data) {
1430
+ const records = [];
1431
+ let messages = 0;
1432
+ for (const f of ubxFrames(data)) {
1433
+ if (f.msgClass !== 1 || f.msgId !== 7 || f.payload.length < 92)
1434
+ continue;
1435
+ messages++;
1436
+ const v = new DataView(
1437
+ f.payload.buffer,
1438
+ f.payload.byteOffset,
1439
+ f.payload.byteLength
1440
+ );
1441
+ const iTow = v.getUint32(0, true);
1442
+ const year = v.getUint16(4, true);
1443
+ const month = v.getUint8(6);
1444
+ const day = v.getUint8(7);
1445
+ const hour = v.getUint8(8);
1446
+ const min = v.getUint8(9);
1447
+ const sec = v.getUint8(10);
1448
+ const fixType = v.getUint8(20);
1449
+ const flags = v.getUint8(21);
1450
+ const numSV = v.getUint8(23);
1451
+ const lon = v.getInt32(24, true) * 1e-7;
1452
+ const lat = v.getInt32(28, true) * 1e-7;
1453
+ const height = v.getInt32(32, true) / 1e3;
1454
+ const hAcc = v.getUint32(40, true) / 1e3;
1455
+ const vAcc = v.getUint32(44, true) / 1e3;
1456
+ const carrSoln = flags >> 6 & 3;
1457
+ const diffSoln = flags >> 1 & 1;
1458
+ const mode = carrSoln === 2 ? "rtk-fixed" : carrSoln === 1 ? "rtk-float" : diffSoln ? "differential" : fixType >= 2 ? "standalone" : "no-pvt";
1459
+ const hasFix = fixType >= 2;
1460
+ const timeMs = year > 1980 ? Date.UTC(year, month - 1, day, hour, min, sec) : GPS_EPOCH_MS7 + iTow;
1461
+ const week = Math.floor((timeMs - GPS_EPOCH_MS7) / 1e3 / 604800);
1462
+ records.push({
1463
+ timeMs,
1464
+ week,
1465
+ tow: iTow / 1e3,
1466
+ mode,
1467
+ latDeg: hasFix ? lat : null,
1468
+ lonDeg: hasFix ? lon : null,
1469
+ heightM: hasFix ? height : null,
1470
+ nrSV: numSV,
1471
+ hAccuracyM: hasFix ? hAcc : null,
1472
+ vAccuracyM: hasFix ? vAcc : null
1473
+ });
1474
+ }
1475
+ return { records, messages };
1476
+ }
1477
+
1478
+ // src/ubx/index.ts
1479
+ var GPS_EPOCH_MS8 = Date.UTC(1980, 0, 6);
1428
1480
  var MS_PER_WEEK3 = 7 * 864e5;
1429
1481
  var SIGNALS = {
1430
1482
  0: { 0: ["G", "1C"], 3: ["G", "2X"], 4: ["G", "2X"] },
@@ -1507,7 +1559,7 @@ function parseUbxRawx(data) {
1507
1559
  if (!codes.includes(sig[1])) codes.push(sig[1]);
1508
1560
  }
1509
1561
  epochs.push({
1510
- timeMs: GPS_EPOCH_MS7 + week * MS_PER_WEEK3 + Math.round(rcvTow * 1e3),
1562
+ timeMs: GPS_EPOCH_MS8 + week * MS_PER_WEEK3 + Math.round(rcvTow * 1e3),
1511
1563
  leapS: leapValid ? leapS : null,
1512
1564
  meas
1513
1565
  });
@@ -1520,6 +1572,7 @@ function parseUbxRawx(data) {
1520
1572
  parseUbxCnav,
1521
1573
  parseUbxIonoUtc,
1522
1574
  parseUbxNav,
1575
+ parseUbxPvt,
1523
1576
  parseUbxRawNav,
1524
1577
  parseUbxRawx,
1525
1578
  ubxFrames
package/dist/ubx.d.cts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { E as Ephemeris, C as CnavEphemeris } from './nav-DImXUdbp.cjs';
2
+ import { R as ReceiverPvt } from './receiver-pvt-CVFvi4kT.cjs';
2
3
 
3
4
  /**
4
5
  * u-blox UBX framing shared by the measurement and navigation decoders:
@@ -267,6 +268,13 @@ interface UbxRawNavResult {
267
268
  */
268
269
  declare function parseUbxRawNav(data: Uint8Array, opts?: UbxRawNavOptions): UbxRawNavResult;
269
270
 
271
+ interface UbxPvtResult {
272
+ records: ReceiverPvt[];
273
+ messages: number;
274
+ }
275
+ /** Decode every UBX-NAV-PVT message in a u-blox byte stream. */
276
+ declare function parseUbxPvt(data: Uint8Array): UbxPvtResult;
277
+
270
278
  /**
271
279
  * u-blox UBX raw-measurement decoding (RXM-RAWX) — the path from a
272
280
  * receiver log to RINEX-grade observables.
@@ -323,4 +331,4 @@ interface UbxParseResult {
323
331
  */
324
332
  declare function parseUbxRawx(data: Uint8Array): UbxParseResult;
325
333
 
326
- export { type UbxCnavResult, type UbxFrame, type UbxIonoUtcResult, type UbxMeasurement, type UbxNavOptions, type UbxNavResult, type UbxParseResult, type UbxRawNavOptions, type UbxRawNavResult, type UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxRawNav, parseUbxRawx, ubxFrames };
334
+ export { ReceiverPvt, type UbxCnavResult, type UbxFrame, type UbxIonoUtcResult, type UbxMeasurement, type UbxNavOptions, type UbxNavResult, type UbxParseResult, type UbxPvtResult, type UbxRawNavOptions, type UbxRawNavResult, type UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxPvt, parseUbxRawNav, parseUbxRawx, ubxFrames };
package/dist/ubx.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { E as Ephemeris, C as CnavEphemeris } from './nav-DImXUdbp.js';
2
+ import { R as ReceiverPvt } from './receiver-pvt-CVFvi4kT.js';
2
3
 
3
4
  /**
4
5
  * u-blox UBX framing shared by the measurement and navigation decoders:
@@ -267,6 +268,13 @@ interface UbxRawNavResult {
267
268
  */
268
269
  declare function parseUbxRawNav(data: Uint8Array, opts?: UbxRawNavOptions): UbxRawNavResult;
269
270
 
271
+ interface UbxPvtResult {
272
+ records: ReceiverPvt[];
273
+ messages: number;
274
+ }
275
+ /** Decode every UBX-NAV-PVT message in a u-blox byte stream. */
276
+ declare function parseUbxPvt(data: Uint8Array): UbxPvtResult;
277
+
270
278
  /**
271
279
  * u-blox UBX raw-measurement decoding (RXM-RAWX) — the path from a
272
280
  * receiver log to RINEX-grade observables.
@@ -323,4 +331,4 @@ interface UbxParseResult {
323
331
  */
324
332
  declare function parseUbxRawx(data: Uint8Array): UbxParseResult;
325
333
 
326
- export { type UbxCnavResult, type UbxFrame, type UbxIonoUtcResult, type UbxMeasurement, type UbxNavOptions, type UbxNavResult, type UbxParseResult, type UbxRawNavOptions, type UbxRawNavResult, type UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxRawNav, parseUbxRawx, ubxFrames };
334
+ export { ReceiverPvt, type UbxCnavResult, type UbxFrame, type UbxIonoUtcResult, type UbxMeasurement, type UbxNavOptions, type UbxNavResult, type UbxParseResult, type UbxPvtResult, type UbxRawNavOptions, type UbxRawNavResult, type UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxPvt, parseUbxRawNav, parseUbxRawx, ubxFrames };
package/dist/ubx.js CHANGED
@@ -2,10 +2,11 @@ import {
2
2
  parseUbxCnav,
3
3
  parseUbxIonoUtc,
4
4
  parseUbxNav,
5
+ parseUbxPvt,
5
6
  parseUbxRawNav,
6
7
  parseUbxRawx,
7
8
  ubxFrames
8
- } from "./chunk-DEVUKH6A.js";
9
+ } from "./chunk-MRC6LIPM.js";
9
10
  import "./chunk-FA2UTLEQ.js";
10
11
  import "./chunk-WQX354KD.js";
11
12
  import "./chunk-YUW33VXK.js";
@@ -16,6 +17,7 @@ export {
16
17
  parseUbxCnav,
17
18
  parseUbxIonoUtc,
18
19
  parseUbxNav,
20
+ parseUbxPvt,
19
21
  parseUbxRawNav,
20
22
  parseUbxRawx,
21
23
  ubxFrames
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gnss-js",
3
- "version": "1.53.0",
3
+ "version": "1.54.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,