gnss-js 1.25.0 → 1.26.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/index.cjs CHANGED
@@ -111,6 +111,10 @@ __export(src_exports, {
111
111
  analyzeQuality: () => analyzeQuality,
112
112
  applyHelmert: () => applyHelmert,
113
113
  applyIonoDcb: () => applyIonoDcb,
114
+ binexCrc16: () => binexCrc16,
115
+ binexCrc32: () => binexCrc32,
116
+ binexCsum8: () => binexCsum8,
117
+ binexRecords: () => binexRecords,
114
118
  buildGloChannelMap: () => buildGloChannelMap,
115
119
  buildObsIndices: () => buildObsIndices,
116
120
  clampUnit: () => clampUnit,
@@ -131,6 +135,7 @@ __export(src_exports, {
131
135
  crxDecompress: () => crxDecompress,
132
136
  crxRepair: () => crxRepair,
133
137
  dateToEpoch: () => dateToEpoch,
138
+ decodeBinexEph: () => decodeBinexEph,
134
139
  decodeEphemeris: () => decodeEphemeris,
135
140
  decodeMsmFull: () => decodeMsmFull,
136
141
  deg2dms: () => deg2dms,
@@ -152,6 +157,7 @@ __export(src_exports, {
152
157
  geodeticToUtm: () => geodeticToUtm,
153
158
  getAer: () => getAer,
154
159
  getBdsTime: () => getBdsTime,
160
+ getBnxi: () => getBnxi,
155
161
  getDateFromBdsTime: () => getDateFromBdsTime,
156
162
  getDateFromDayOfWeek: () => getDateFromDayOfWeek,
157
163
  getDateFromDayOfYear: () => getDateFromDayOfYear,
@@ -225,6 +231,7 @@ __export(src_exports, {
225
231
  padL: () => padL,
226
232
  padR: () => padR,
227
233
  parseAntex: () => parseAntex,
234
+ parseBinex: () => parseBinex,
228
235
  parseCrxDataLine: () => parseCrxDataLine,
229
236
  parseIonex: () => parseIonex,
230
237
  parseNavFile: () => parseNavFile,
@@ -244,6 +251,8 @@ __export(src_exports, {
244
251
  parseSinexBiasDcb: () => parseSinexBiasDcb,
245
252
  parseSourcetable: () => parseSourcetable,
246
253
  parseSp3: () => parseSp3,
254
+ parseTrimble: () => parseTrimble,
255
+ parseTrimbleNav: () => parseTrimbleNav,
247
256
  parseUbxCnav: () => parseUbxCnav,
248
257
  parseUbxIonoUtc: () => parseUbxIonoUtc,
249
258
  parseUbxNav: () => parseUbxNav,
@@ -274,6 +283,7 @@ __export(src_exports, {
274
283
  systemName: () => systemName,
275
284
  toRtkEpoch: () => toRtkEpoch,
276
285
  transformFrame: () => transformFrame,
286
+ trimbleFrames: () => trimbleFrames,
277
287
  ubxFrames: () => ubxFrames,
278
288
  updateStationMeta: () => updateStationMeta,
279
289
  updateStreamStats: () => updateStreamStats,
@@ -6280,20 +6290,20 @@ var SIGNALS = {
6280
6290
  // GLONASS L1OF, L2OF
6281
6291
  };
6282
6292
  function prnFor(gnssId, svId) {
6283
- const two5 = (n) => String(n).padStart(2, "0");
6293
+ const two7 = (n) => String(n).padStart(2, "0");
6284
6294
  switch (gnssId) {
6285
6295
  case 0:
6286
- return svId >= 1 && svId <= 32 ? `G${two5(svId)}` : null;
6296
+ return svId >= 1 && svId <= 32 ? `G${two7(svId)}` : null;
6287
6297
  case 1:
6288
- return svId >= 120 && svId <= 158 ? `S${two5(svId - 100)}` : null;
6298
+ return svId >= 120 && svId <= 158 ? `S${two7(svId - 100)}` : null;
6289
6299
  case 2:
6290
- return svId >= 1 && svId <= 36 ? `E${two5(svId)}` : null;
6300
+ return svId >= 1 && svId <= 36 ? `E${two7(svId)}` : null;
6291
6301
  case 3:
6292
- return svId >= 1 && svId <= 63 ? `C${two5(svId)}` : null;
6302
+ return svId >= 1 && svId <= 63 ? `C${two7(svId)}` : null;
6293
6303
  case 5:
6294
- return svId >= 1 && svId <= 10 ? `J${two5(svId)}` : null;
6304
+ return svId >= 1 && svId <= 10 ? `J${two7(svId)}` : null;
6295
6305
  case 6:
6296
- return svId >= 1 && svId <= 32 ? `R${two5(svId)}` : null;
6306
+ return svId >= 1 && svId <= 32 ? `R${two7(svId)}` : null;
6297
6307
  default:
6298
6308
  return null;
6299
6309
  }
@@ -8680,20 +8690,1180 @@ function parseNovatelRange(data) {
8680
8690
  return { epochs, messageCounts, obsCodes, badCrc };
8681
8691
  }
8682
8692
 
8693
+ // src/trimble/frame.ts
8694
+ var STX = 2;
8695
+ var ETX = 3;
8696
+ var RAWDATA = 87;
8697
+ var RETSVDATA = 85;
8698
+ function* trimbleFrames(data, stats) {
8699
+ let i = 0;
8700
+ while (i + 6 <= data.length) {
8701
+ if (data[i] !== STX) {
8702
+ i++;
8703
+ continue;
8704
+ }
8705
+ const len = data[i + 3];
8706
+ const total = 4 + len + 2;
8707
+ if (i + total > data.length) {
8708
+ i++;
8709
+ continue;
8710
+ }
8711
+ if (data[i + total - 1] !== ETX) {
8712
+ i++;
8713
+ continue;
8714
+ }
8715
+ let cs = 0;
8716
+ for (let k = 1; k <= 3 + len; k++) cs = cs + data[i + k] & 255;
8717
+ if (cs !== data[i + 4 + len]) {
8718
+ stats.badChecksum++;
8719
+ i++;
8720
+ continue;
8721
+ }
8722
+ yield {
8723
+ start: i,
8724
+ status: data[i + 1],
8725
+ type: data[i + 2],
8726
+ len,
8727
+ payload: i + 4
8728
+ };
8729
+ i += total;
8730
+ }
8731
+ }
8732
+
8733
+ // src/trimble/nav.ts
8734
+ var GPS_EPOCH_MS13 = Date.UTC(1980, 0, 6);
8735
+ var SEC_PER_WEEK10 = 7 * 86400;
8736
+ var MS_PER_WEEK9 = SEC_PER_WEEK10 * 1e3;
8737
+ var GPS_PI2 = 3.1415926535898;
8738
+ var gpsMs3 = (week, sec) => GPS_EPOCH_MS13 + week * MS_PER_WEEK9 + sec * 1e3;
8739
+ var sowOf4 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK10;
8740
+ var SUB_GPS_EPHEMERIS = 1;
8741
+ var SUB_ION_UTC = 3;
8742
+ function decodeGpsEphemeris2(data, view, base) {
8743
+ const prn = data[base + 5];
8744
+ if (prn < 1 || prn > 32) return null;
8745
+ const week = view.getUint16(base + 6, false);
8746
+ const iode = data[base + 11];
8747
+ const toc = view.getInt32(base + 16, false);
8748
+ const toe = view.getUint32(base + 20, false);
8749
+ const tgd = view.getFloat64(base + 24, false);
8750
+ const af2 = view.getFloat64(base + 32, false);
8751
+ const af1 = view.getFloat64(base + 40, false);
8752
+ const af0 = view.getFloat64(base + 48, false);
8753
+ const crs = view.getFloat64(base + 56, false);
8754
+ const deltaN = view.getFloat64(base + 64, false) * GPS_PI2;
8755
+ const m0 = view.getFloat64(base + 72, false) * GPS_PI2;
8756
+ const cuc = view.getFloat64(base + 80, false) * GPS_PI2;
8757
+ const e = view.getFloat64(base + 88, false);
8758
+ const cus = view.getFloat64(base + 96, false) * GPS_PI2;
8759
+ const sqrtA = view.getFloat64(base + 104, false);
8760
+ const cic = view.getFloat64(base + 112, false) * GPS_PI2;
8761
+ const omega0 = view.getFloat64(base + 120, false) * GPS_PI2;
8762
+ const cis = view.getFloat64(base + 128, false) * GPS_PI2;
8763
+ const i0 = view.getFloat64(base + 136, false) * GPS_PI2;
8764
+ const crc = view.getFloat64(base + 144, false);
8765
+ const omega = view.getFloat64(base + 152, false) * GPS_PI2;
8766
+ const omegaDot = view.getFloat64(base + 160, false) * GPS_PI2;
8767
+ const idot = view.getFloat64(base + 168, false) * GPS_PI2;
8768
+ const flags = view.getUint32(base + 176, false);
8769
+ return {
8770
+ system: "G",
8771
+ prn: `G${String(prn).padStart(2, "0")}`,
8772
+ toc: sowOf4(gpsMs3(week, toc)),
8773
+ tocDate: new Date(gpsMs3(week, toc)),
8774
+ af0,
8775
+ af1,
8776
+ af2,
8777
+ iode,
8778
+ crs,
8779
+ deltaN,
8780
+ m0,
8781
+ cuc,
8782
+ e,
8783
+ cus,
8784
+ sqrtA,
8785
+ toe,
8786
+ cic,
8787
+ omega0,
8788
+ cis,
8789
+ i0,
8790
+ crc,
8791
+ omega,
8792
+ omegaDot,
8793
+ idot,
8794
+ week,
8795
+ svHealth: flags >>> 4 & 127,
8796
+ tgd
8797
+ };
8798
+ }
8799
+ function parseTrimbleNav(data) {
8800
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
8801
+ const stats = { badChecksum: 0 };
8802
+ const ephemerides = [];
8803
+ const ionoCorrections = {};
8804
+ const retsvCounts = {};
8805
+ let leapSeconds = null;
8806
+ const lastIode = /* @__PURE__ */ new Map();
8807
+ for (const f of trimbleFrames(data, stats)) {
8808
+ if (f.type !== RETSVDATA) continue;
8809
+ const sub = data[f.payload];
8810
+ retsvCounts[sub] = (retsvCounts[sub] ?? 0) + 1;
8811
+ if (sub === SUB_GPS_EPHEMERIS && f.len >= 178) {
8812
+ const eph = decodeGpsEphemeris2(data, view, f.start);
8813
+ if (!eph) continue;
8814
+ if (lastIode.get(eph.prn) === eph.iode) continue;
8815
+ lastIode.set(eph.prn, eph.iode);
8816
+ ephemerides.push(eph);
8817
+ } else if (sub === SUB_ION_UTC && f.len >= 125) {
8818
+ const p = f.start;
8819
+ const alpha = [];
8820
+ const beta = [];
8821
+ for (let i = 0; i < 4; i++) {
8822
+ alpha.push(view.getFloat64(p + 6 + i * 8, false));
8823
+ beta.push(view.getFloat64(p + 38 + i * 8, false));
8824
+ }
8825
+ ionoCorrections["GPSA"] = alpha;
8826
+ ionoCorrections["GPSB"] = beta;
8827
+ leapSeconds = Math.trunc(view.getFloat64(p + 94, false));
8828
+ }
8829
+ }
8830
+ return {
8831
+ ephemerides,
8832
+ ionoCorrections,
8833
+ leapSeconds,
8834
+ retsvCounts,
8835
+ badChecksum: stats.badChecksum
8836
+ };
8837
+ }
8838
+
8839
+ // src/trimble/index.ts
8840
+ var GPS_EPOCH_MS14 = Date.UTC(1980, 0, 6);
8841
+ var MS_PER_WEEK10 = 7 * 864e5;
8842
+ var REC_TYPE_27 = 6;
8843
+ var SYS = {
8844
+ 0: "G",
8845
+ // GPS
8846
+ 1: "S",
8847
+ // SBAS
8848
+ 2: "R",
8849
+ // GLONASS
8850
+ 3: "E",
8851
+ // Galileo
8852
+ 4: "J",
8853
+ // QZSS
8854
+ 5: "C",
8855
+ // BeiDou (pre-ICD numbering)
8856
+ 7: "C",
8857
+ // BeiDou (ICD numbering)
8858
+ 9: "I",
8859
+ // NavIC / IRNSS
8860
+ 10: "C"
8861
+ // BeiDou
8862
+ };
8863
+ var CODES = {
8864
+ "G0-0": "1C",
8865
+ "G0-20": "1L",
8866
+ "G1-2": "2W",
8867
+ "G1-5": "2L",
8868
+ "G2-6": "5I",
8869
+ "G2-7": "5Q",
8870
+ "G2-8": "5X",
8871
+ "R0-0": "1C",
8872
+ "R0-1": "1P",
8873
+ "R1-0": "2C",
8874
+ "R1-1": "2P",
8875
+ "E0-23": "1C",
8876
+ "E2-11": "5Q",
8877
+ "E3-11": "7Q",
8878
+ "E4-14": "8Q",
8879
+ "E5-36": "6C",
8880
+ "C0-20": "1P",
8881
+ "C2-8": "5P",
8882
+ "C3-6": "7D",
8883
+ "C6-26": "2I",
8884
+ "C7-29": "6I",
8885
+ "S0-0": "1C",
8886
+ "S2-6": "5I",
8887
+ "J0-0": "1C"
8888
+ };
8889
+ var BAND_DIGIT = {
8890
+ 0: "1",
8891
+ // L1 / E1 / B1C (1575.42)
8892
+ 1: "2",
8893
+ // L2 / G2 (1227.6)
8894
+ 2: "5",
8895
+ // L5 / E5a (1176.45)
8896
+ 3: "7",
8897
+ // E5b / B2b (1207.14)
8898
+ 4: "8",
8899
+ // E5 AltBOC (1191.795)
8900
+ 5: "6",
8901
+ // E6 (1278.75)
8902
+ 6: "2",
8903
+ // B1I (1561.098)
8904
+ 7: "6",
8905
+ // B3I (1268.52)
8906
+ 8: "1",
8907
+ // BeiDou E1 (1589.742)
8908
+ 9: "3",
8909
+ // GLONASS G3 CDMA (1202.025)
8910
+ 11: "9"
8911
+ // NavIC S-band (2492.028)
8912
+ };
8913
+ function rinexCode(sys, band, track) {
8914
+ const key = `${sys}${band}-${track}`;
8915
+ return CODES[key] ?? `${BAND_DIGIT[band] ?? "?"}X`;
8916
+ }
8917
+ function rinexPrn(sys, svid) {
8918
+ let n = svid;
8919
+ if (sys === "S")
8920
+ n = svid - 100;
8921
+ else if (sys === "J" && svid >= 193) n = svid - 192;
8922
+ return `${sys}${String(n).padStart(2, "0")}`;
8923
+ }
8924
+ var readS16 = (dv, o) => dv.getInt16(o, false);
8925
+ function readS24(d, o) {
8926
+ const v = d[o] << 16 | d[o + 1] << 8 | d[o + 2];
8927
+ return v & 8388608 ? v - 16777216 : v;
8928
+ }
8929
+ function readS48(d, dv, o) {
8930
+ const hi = d[o] << 8 | d[o + 1];
8931
+ const lo = dv.getUint32(o + 2, false);
8932
+ const v = hi * 4294967296 + lo;
8933
+ return hi & 32768 ? v - 281474976710656 : v;
8934
+ }
8935
+ function parseTrimble(data) {
8936
+ const stats = { badChecksum: 0 };
8937
+ const epochs = [];
8938
+ const obsCodes = {};
8939
+ const recordCounts = {};
8940
+ const retsvCounts = {};
8941
+ let pages = [];
8942
+ let msgReply = -1;
8943
+ let lastPage = 0;
8944
+ let msgPages = 0;
8945
+ let epoch = null;
8946
+ const finalize = () => {
8947
+ if (epoch) decodeEpoch(epoch, epochs, obsCodes);
8948
+ epoch = null;
8949
+ };
8950
+ const onMessage = (content, reply) => {
8951
+ if (epoch && reply === epoch.reply) {
8952
+ epoch.chunks.push(content);
8953
+ return;
8954
+ }
8955
+ finalize();
8956
+ if (content.length < 12) return;
8957
+ const dv = new DataView(
8958
+ content.buffer,
8959
+ content.byteOffset,
8960
+ content.byteLength
8961
+ );
8962
+ const headerLen = content[0];
8963
+ const week = dv.getUint16(1, false);
8964
+ const towMs = dv.getUint32(3, false);
8965
+ const nsv = content[10];
8966
+ const eflags = content[11];
8967
+ if (week < 1024 || week > 4096 || headerLen < 12 || nsv === 0) return;
8968
+ let svStart = headerLen;
8969
+ if (eflags & 32 && svStart < content.length) svStart += content[svStart];
8970
+ epoch = {
8971
+ reply,
8972
+ week,
8973
+ towMs,
8974
+ nsv,
8975
+ chunks: [content.subarray(svStart)]
8976
+ };
8977
+ };
8978
+ const completeMessage = () => {
8979
+ const total = pages.reduce((a, c) => a + c.length, 0);
8980
+ const content = new Uint8Array(total);
8981
+ let o = 0;
8982
+ for (const c of pages) {
8983
+ content.set(c, o);
8984
+ o += c.length;
8985
+ }
8986
+ const reply = msgReply;
8987
+ pages = [];
8988
+ onMessage(content, reply);
8989
+ };
8990
+ for (const f of trimbleFrames(data, stats)) {
8991
+ if (f.type !== RAWDATA) {
8992
+ if (f.type === 85) {
8993
+ const sub = data[f.payload];
8994
+ retsvCounts[sub] = (retsvCounts[sub] ?? 0) + 1;
8995
+ }
8996
+ continue;
8997
+ }
8998
+ const recType = data[f.payload];
8999
+ recordCounts[recType] = (recordCounts[recType] ?? 0) + 1;
9000
+ if (recType !== REC_TYPE_27) continue;
9001
+ const pageByte = data[f.payload + 1];
9002
+ const page = pageByte >> 4;
9003
+ const pagesTotal = pageByte & 15;
9004
+ const reply = data[f.payload + 2];
9005
+ const content = data.subarray(f.payload + 4, f.payload + f.len);
9006
+ if (page === 1) {
9007
+ pages = [content];
9008
+ msgReply = reply;
9009
+ msgPages = pagesTotal;
9010
+ lastPage = 1;
9011
+ } else if (reply === msgReply && page === lastPage + 1) {
9012
+ pages.push(content);
9013
+ lastPage = page;
9014
+ } else {
9015
+ pages = [];
9016
+ continue;
9017
+ }
9018
+ if (lastPage === msgPages) completeMessage();
9019
+ }
9020
+ finalize();
9021
+ return {
9022
+ epochs,
9023
+ obsCodes,
9024
+ recordCounts,
9025
+ retsvCounts,
9026
+ badChecksum: stats.badChecksum
9027
+ };
9028
+ }
9029
+ function decodeEpoch(epoch, epochs, obsCodes) {
9030
+ const total = epoch.chunks.reduce((a, c) => a + c.length, 0);
9031
+ const M = new Uint8Array(total);
9032
+ let o = 0;
9033
+ for (const c of epoch.chunks) {
9034
+ M.set(c, o);
9035
+ o += c.length;
9036
+ }
9037
+ const dv = new DataView(M.buffer, M.byteOffset, M.byteLength);
9038
+ const timeMs = GPS_EPOCH_MS14 + epoch.week * MS_PER_WEEK10 + epoch.towMs;
9039
+ const meas = [];
9040
+ let q = 0;
9041
+ for (let sv = 0; sv < epoch.nsv && q + 8 <= M.length; sv++) {
9042
+ const svLen = M[q];
9043
+ if (svLen < 8 || q + svLen > M.length) break;
9044
+ const svid = M[q + 1];
9045
+ const sys = SYS[M[q + 2] & 63];
9046
+ const chan = M[q + 3] << 24 >> 24;
9047
+ const nblk = M[q + 4];
9048
+ const prn = sys ? rinexPrn(sys, svid) : null;
9049
+ const gloChannel = sys === "R" ? chan : null;
9050
+ let r = q + svLen;
9051
+ let pr0 = 0;
9052
+ for (let b = 0; b < nblk; b++) {
9053
+ if (r + 5 > M.length) break;
9054
+ const mLen = M[r];
9055
+ if (mLen < 5 || r + mLen > M.length) break;
9056
+ const band = M[r + 1];
9057
+ const track = M[r + 2];
9058
+ const cn0 = dv.getUint16(r + 3, false) / 10;
9059
+ let p = r + 5;
9060
+ let pr;
9061
+ if (b === 0) {
9062
+ const scale = sys === "S" || sys === "J" ? 64 : 128;
9063
+ pr = dv.getUint32(p, false) / scale;
9064
+ p += 4;
9065
+ pr0 = pr;
9066
+ } else {
9067
+ pr = pr0 + readS16(dv, p) / 256;
9068
+ p += 2;
9069
+ }
9070
+ const cp = -readS48(M, dv, p) / 32768;
9071
+ p += 6;
9072
+ const cycleSlipCount = M[p];
9073
+ p += 1;
9074
+ const mf = M[p];
9075
+ p += 1;
9076
+ let mf2 = 0;
9077
+ if (mf & 128) {
9078
+ mf2 = M[p];
9079
+ p += 1;
9080
+ let f = mf2;
9081
+ while (f & 128) {
9082
+ f = M[p];
9083
+ p += 1;
9084
+ }
9085
+ }
9086
+ if (mf2 & 1) p += 1;
9087
+ let doppler = null;
9088
+ if (mf & 4) doppler = readS24(M, p) / 256;
9089
+ if (prn && sys) {
9090
+ const code = rinexCode(sys, band, track);
9091
+ meas.push({
9092
+ prn,
9093
+ code,
9094
+ pr: mf & 2 ? pr : null,
9095
+ cp: mf & 1 ? cp : null,
9096
+ doppler: mf & 1 ? doppler : null,
9097
+ cn0,
9098
+ cycleSlipCount,
9099
+ cycleSlip: (mf & 8) !== 0,
9100
+ gloChannel
9101
+ });
9102
+ const list = obsCodes[sys] ??= [];
9103
+ if (!list.includes(code)) list.push(code);
9104
+ }
9105
+ r += mLen;
9106
+ }
9107
+ q = r;
9108
+ }
9109
+ epochs.push({ timeMs, meas });
9110
+ }
9111
+
9112
+ // src/binex/frame.ts
9113
+ var CRC16_TABLE = (() => {
9114
+ const t = new Uint16Array(256);
9115
+ for (let n = 0; n < 256; n++) {
9116
+ let c = n << 8;
9117
+ for (let k = 0; k < 8; k++)
9118
+ c = c & 32768 ? (c << 1 ^ 4129) & 65535 : c << 1 & 65535;
9119
+ t[n] = c;
9120
+ }
9121
+ return t;
9122
+ })();
9123
+ function binexCrc16(data, start, end) {
9124
+ let crc = 0;
9125
+ for (let i = start; i < end; i++)
9126
+ crc = (crc << 8 ^ CRC16_TABLE[(crc >> 8 ^ data[i]) & 255]) & 65535;
9127
+ return crc;
9128
+ }
9129
+ var CRC32_TABLE = (() => {
9130
+ const t = new Uint32Array(256);
9131
+ for (let n = 0; n < 256; n++) {
9132
+ let c = n << 24;
9133
+ for (let k = 0; k < 8; k++)
9134
+ c = c & 2147483648 ? c << 1 ^ 79764919 : c << 1;
9135
+ t[n] = c >>> 0;
9136
+ }
9137
+ return t;
9138
+ })();
9139
+ function binexCrc32(data, start, end) {
9140
+ let crc = 0;
9141
+ for (let i = start; i < end; i++)
9142
+ crc = (crc << 8 ^ CRC32_TABLE[(crc >>> 24 ^ data[i]) & 255]) >>> 0;
9143
+ return crc >>> 0;
9144
+ }
9145
+ function binexCsum8(data, start, end) {
9146
+ let cs = 0;
9147
+ for (let i = start; i < end; i++) cs ^= data[i];
9148
+ return cs & 255;
9149
+ }
9150
+ function getBnxi(data, pos) {
9151
+ let value = 0;
9152
+ for (let i = 0; i < 3; i++) {
9153
+ const b = data[pos + i] ?? 0;
9154
+ value = value * 128 + (b & 127);
9155
+ if (!(b & 128)) return { value, size: i + 1 };
9156
+ }
9157
+ value = value * 256 + (data[pos + 3] ?? 0);
9158
+ return { value, size: 4 };
9159
+ }
9160
+ var SYNC = /* @__PURE__ */ new Map([
9161
+ [226, { littleEndian: false, enhanced: false }],
9162
+ [194, { littleEndian: true, enhanced: false }],
9163
+ [232, { littleEndian: false, enhanced: true }],
9164
+ [200, { littleEndian: true, enhanced: true }]
9165
+ ]);
9166
+ function csumWidth(covered, enhanced) {
9167
+ if (enhanced) {
9168
+ if (covered < 128) return 2;
9169
+ if (covered < 1048576) return 4;
9170
+ return 16;
9171
+ }
9172
+ if (covered < 128) return 1;
9173
+ if (covered < 4096) return 2;
9174
+ if (covered < 1048576) return 4;
9175
+ return 16;
9176
+ }
9177
+ function checksumOk(data, view, covStart, covEnd, width) {
9178
+ switch (width) {
9179
+ case 1:
9180
+ return binexCsum8(data, covStart, covEnd) === (data[covEnd] ?? -1);
9181
+ case 2:
9182
+ return binexCrc16(data, covStart, covEnd) === view.getUint16(covEnd);
9183
+ case 4:
9184
+ return binexCrc32(data, covStart, covEnd) === view.getUint32(covEnd);
9185
+ default:
9186
+ return false;
9187
+ }
9188
+ }
9189
+ function* binexRecords(data, view, stats) {
9190
+ let i = 0;
9191
+ while (i + 2 <= data.length) {
9192
+ const sync = SYNC.get(data[i]);
9193
+ if (!sync) {
9194
+ i++;
9195
+ continue;
9196
+ }
9197
+ const id = data[i + 1];
9198
+ const { value: len, size: lenH } = getBnxi(data, i + 2);
9199
+ const body = i + 2 + lenH;
9200
+ const covStart = i + 1;
9201
+ const covEnd = body + len;
9202
+ const covered = covEnd - covStart;
9203
+ const width = csumWidth(covered, sync.enhanced);
9204
+ if (width === 16 || covEnd + width > data.length) {
9205
+ i++;
9206
+ continue;
9207
+ }
9208
+ if (!checksumOk(data, view, covStart, covEnd, width)) {
9209
+ stats.badCrc++;
9210
+ i++;
9211
+ continue;
9212
+ }
9213
+ yield { id, start: i, body, len, ...sync };
9214
+ i = covEnd + width;
9215
+ }
9216
+ }
9217
+
9218
+ // src/binex/nav.ts
9219
+ var GPS_EPOCH_MS15 = Date.UTC(1980, 0, 6);
9220
+ var GLO_DAY0_MS = Date.UTC(1980, 0, 1);
9221
+ var BDT_EPOCH_MS4 = Date.UTC(2006, 0, 1);
9222
+ var SEC_PER_WEEK11 = 7 * 86400;
9223
+ var MS_PER_WEEK11 = SEC_PER_WEEK11 * 1e3;
9224
+ var SC2RAD = GPS_PI;
9225
+ var gpsMs4 = (week, sec) => GPS_EPOCH_MS15 + week * MS_PER_WEEK11 + sec * 1e3;
9226
+ var sowOf5 = (dateMs) => (dateMs / 1e3 % SEC_PER_WEEK11 + SEC_PER_WEEK11) % SEC_PER_WEEK11;
9227
+ var two5 = (n) => String(n).padStart(2, "0");
9228
+ var Reader = class {
9229
+ constructor(view, start, le) {
9230
+ this.view = view;
9231
+ this.le = le;
9232
+ this.p = start;
9233
+ }
9234
+ p;
9235
+ u1() {
9236
+ return this.view.getUint8(this.p++);
9237
+ }
9238
+ i1() {
9239
+ return this.view.getInt8(this.p++);
9240
+ }
9241
+ u2() {
9242
+ const v = this.view.getUint16(this.p, this.le);
9243
+ this.p += 2;
9244
+ return v;
9245
+ }
9246
+ i4() {
9247
+ const v = this.view.getInt32(this.p, this.le);
9248
+ this.p += 4;
9249
+ return v;
9250
+ }
9251
+ u4() {
9252
+ const v = this.view.getUint32(this.p, this.le);
9253
+ this.p += 4;
9254
+ return v;
9255
+ }
9256
+ r4() {
9257
+ const v = this.view.getFloat32(this.p, this.le);
9258
+ this.p += 4;
9259
+ return v;
9260
+ }
9261
+ r8() {
9262
+ const v = this.view.getFloat64(this.p, this.le);
9263
+ this.p += 8;
9264
+ return v;
9265
+ }
9266
+ };
9267
+ function readKeplerCore(r) {
9268
+ const deltaN = r.r4() * SC2RAD;
9269
+ const m0 = r.r8();
9270
+ const e = r.r8();
9271
+ const sqrtA = r.r8();
9272
+ const cic = r.r4();
9273
+ const crc = r.r4();
9274
+ const cis = r.r4();
9275
+ const crs = r.r4();
9276
+ const cuc = r.r4();
9277
+ const cus = r.r4();
9278
+ const omega0 = r.r8();
9279
+ const omega = r.r8();
9280
+ const i0 = r.r8();
9281
+ const omegaDot = r.r4() * SC2RAD;
9282
+ const idot = r.r4() * SC2RAD;
9283
+ return {
9284
+ deltaN,
9285
+ m0,
9286
+ e,
9287
+ sqrtA,
9288
+ cic,
9289
+ crc,
9290
+ cis,
9291
+ crs,
9292
+ cuc,
9293
+ cus,
9294
+ omega0,
9295
+ omega,
9296
+ i0,
9297
+ omegaDot,
9298
+ idot
9299
+ };
9300
+ }
9301
+ function decodeGpsQzss(view, p, le, sys) {
9302
+ const r = new Reader(view, p, le);
9303
+ const prnRaw = r.u1() + (sys === "G" ? 1 : 0);
9304
+ const prn = sys === "G" ? prnRaw : prnRaw - 192;
9305
+ if (sys === "G" && (prn < 1 || prn > 32)) return null;
9306
+ if (sys === "J" && (prn < 1 || prn > 10)) return null;
9307
+ const week = r.u2();
9308
+ r.i4();
9309
+ const toes = r.i4();
9310
+ const tgd = r.r4();
9311
+ r.i4();
9312
+ const af2 = r.r4();
9313
+ const af1 = r.r4();
9314
+ const af0 = r.r4();
9315
+ const iode = r.i4();
9316
+ const core = readKeplerCore(r);
9317
+ r.r4();
9318
+ const svHealth = r.u2();
9319
+ const tocDate = new Date(gpsMs4(week, toes));
9320
+ return {
9321
+ system: sys,
9322
+ prn: `${sys}${two5(prn)}`,
9323
+ toc: sowOf5(tocDate.getTime()),
9324
+ tocDate,
9325
+ af0,
9326
+ af1,
9327
+ af2,
9328
+ iode,
9329
+ ...core,
9330
+ toe: toes,
9331
+ week,
9332
+ svHealth,
9333
+ tgd
9334
+ };
9335
+ }
9336
+ function decodeGalileo(view, p, le) {
9337
+ const r = new Reader(view, p, le);
9338
+ const prn = r.u1() + 1;
9339
+ if (prn < 1 || prn > 36) return null;
9340
+ const week = r.u2();
9341
+ r.i4();
9342
+ const toes = r.i4();
9343
+ const tgd = r.r4();
9344
+ r.r4();
9345
+ const iode = r.i4();
9346
+ const af2 = r.r4();
9347
+ const af1 = r.r4();
9348
+ const af0 = r.r4();
9349
+ const core = readKeplerCore(r);
9350
+ r.r4();
9351
+ const svHealth = r.u2();
9352
+ const tocDate = new Date(gpsMs4(week, toes));
9353
+ return {
9354
+ system: "E",
9355
+ prn: `E${two5(prn)}`,
9356
+ toc: sowOf5(tocDate.getTime()),
9357
+ tocDate,
9358
+ af0,
9359
+ af1,
9360
+ af2,
9361
+ iode,
9362
+ ...core,
9363
+ toe: toes,
9364
+ week,
9365
+ svHealth,
9366
+ tgd
9367
+ };
9368
+ }
9369
+ function bdsTgd(tgd) {
9370
+ tgd &= 1023;
9371
+ return tgd & 512 ? -1e-10 * (~tgd & 511) : 1e-10 * (tgd & 511);
9372
+ }
9373
+ function decodeBeidou(view, p, le) {
9374
+ const r = new Reader(view, p, le);
9375
+ const prn = r.u1();
9376
+ if (prn < 1 || prn > 63) return null;
9377
+ const week = r.u2();
9378
+ r.i4();
9379
+ r.i4();
9380
+ const toes = r.i4();
9381
+ const af2 = r.r4();
9382
+ const af1 = r.r4();
9383
+ const af0 = r.r4();
9384
+ const core = readKeplerCore(r);
9385
+ const flag1 = r.u2();
9386
+ const flag2 = r.u4();
9387
+ const iode = flag1 >> 6 & 31;
9388
+ const svHealth = flag1 & 1;
9389
+ const tgd = bdsTgd(flag2 >> 4);
9390
+ const tocDate = new Date(BDT_EPOCH_MS4 + week * MS_PER_WEEK11 + toes * 1e3);
9391
+ return {
9392
+ system: "C",
9393
+ prn: `C${two5(prn)}`,
9394
+ toc: sowOf5(tocDate.getTime()),
9395
+ tocDate,
9396
+ af0,
9397
+ af1,
9398
+ af2,
9399
+ iode,
9400
+ ...core,
9401
+ toe: toes,
9402
+ week,
9403
+ // RINEX BDS week field is the BDT week
9404
+ svHealth,
9405
+ tgd
9406
+ };
9407
+ }
9408
+ function decodeGlonass(view, p, le) {
9409
+ const r = new Reader(view, p, le);
9410
+ const slot = r.u1() + 1;
9411
+ if (slot < 1 || slot > 27) return null;
9412
+ const day = r.u2();
9413
+ const tod = r.u4();
9414
+ const tauN = r.r8();
9415
+ const gammaN = r.r8();
9416
+ const tof = r.u4();
9417
+ const x = r.r8();
9418
+ const xDot = r.r8();
9419
+ const xAcc = r.r8();
9420
+ const y = r.r8();
9421
+ const yDot = r.r8();
9422
+ const yAcc = r.r8();
9423
+ const z = r.r8();
9424
+ const zDot = r.r8();
9425
+ const zAcc = r.r8();
9426
+ const health = r.u1() & 1;
9427
+ const freqNum = r.i1();
9428
+ const tocDate = new Date(
9429
+ GLO_DAY0_MS + (day - 1) * 864e5 + (tod - 10800) * 1e3
9430
+ );
9431
+ return {
9432
+ system: "R",
9433
+ prn: `R${two5(slot)}`,
9434
+ tocDate,
9435
+ tauN,
9436
+ gammaN,
9437
+ messageFrameTime: tof,
9438
+ x,
9439
+ y,
9440
+ z,
9441
+ xDot,
9442
+ yDot,
9443
+ zDot,
9444
+ xAcc,
9445
+ yAcc,
9446
+ zAcc,
9447
+ health,
9448
+ freqNum
9449
+ };
9450
+ }
9451
+ function decodeSbas(view, p, le) {
9452
+ const r = new Reader(view, p, le);
9453
+ const prn = r.u1();
9454
+ const week = r.u2();
9455
+ const tow = r.u4();
9456
+ const af0 = r.r8();
9457
+ const af1 = r.r4();
9458
+ const toe = r.u4();
9459
+ const x = r.r8();
9460
+ const xDot = r.r8();
9461
+ const xAcc = r.r8();
9462
+ const y = r.r8();
9463
+ const yDot = r.r8();
9464
+ const yAcc = r.r8();
9465
+ const z = r.r8();
9466
+ const zDot = r.r8();
9467
+ const zAcc = r.r8();
9468
+ const health = r.u1();
9469
+ if (prn < 120 || prn > 158) return null;
9470
+ return {
9471
+ system: "S",
9472
+ prn: `S${two5(prn - 100)}`,
9473
+ tocDate: new Date(gpsMs4(week, toe)),
9474
+ tauN: af0,
9475
+ gammaN: af1,
9476
+ messageFrameTime: tow,
9477
+ x,
9478
+ y,
9479
+ z,
9480
+ xDot,
9481
+ yDot,
9482
+ zDot,
9483
+ xAcc,
9484
+ yAcc,
9485
+ zAcc,
9486
+ health,
9487
+ freqNum: 0
9488
+ };
9489
+ }
9490
+ function decodeBinexEph(view, body, len, le) {
9491
+ const sub = view.getUint8(body);
9492
+ const p = body + 1;
9493
+ const n = len - 1;
9494
+ switch (sub) {
9495
+ case 1:
9496
+ return n >= 127 ? decodeGpsQzss(view, p, le, "G") : null;
9497
+ case 2:
9498
+ return n >= 119 ? decodeGlonass(view, p, le) : null;
9499
+ case 3:
9500
+ return n >= 98 ? decodeSbas(view, p, le) : null;
9501
+ case 4:
9502
+ return n >= 127 ? decodeGalileo(view, p, le) : null;
9503
+ case 5:
9504
+ return n >= 117 ? decodeBeidou(view, p, le) : null;
9505
+ case 6:
9506
+ return n >= 127 ? decodeGpsQzss(view, p, le, "J") : null;
9507
+ default:
9508
+ return null;
9509
+ }
9510
+ }
9511
+
9512
+ // src/binex/index.ts
9513
+ var GPS_EPOCH_MS16 = Date.UTC(1980, 0, 6);
9514
+ var CLIGHT2 = 299792458;
9515
+ var OBS_CODES = {
9516
+ 0: [
9517
+ "1C",
9518
+ "1C",
9519
+ "1P",
9520
+ "1W",
9521
+ "1Y",
9522
+ "1M",
9523
+ "1X",
9524
+ "1N",
9525
+ "",
9526
+ "",
9527
+ "2W",
9528
+ "2C",
9529
+ "2D",
9530
+ "2S",
9531
+ "2L",
9532
+ "2X",
9533
+ "2P",
9534
+ "2W",
9535
+ "2Y",
9536
+ "2M",
9537
+ "2N",
9538
+ "",
9539
+ "",
9540
+ "5X",
9541
+ "5I",
9542
+ "5Q",
9543
+ "5X"
9544
+ ],
9545
+ // GPS
9546
+ 1: [
9547
+ "1C",
9548
+ "1C",
9549
+ "1P",
9550
+ "",
9551
+ "",
9552
+ "",
9553
+ "",
9554
+ "",
9555
+ "",
9556
+ "",
9557
+ "2C",
9558
+ "2C",
9559
+ "2P",
9560
+ "3X",
9561
+ "3I",
9562
+ "3Q",
9563
+ "3X"
9564
+ ],
9565
+ // GLONASS
9566
+ 3: [
9567
+ "1C",
9568
+ "1A",
9569
+ "1B",
9570
+ "1C",
9571
+ "1X",
9572
+ "1Z",
9573
+ "5X",
9574
+ "5I",
9575
+ "5Q",
9576
+ "5X",
9577
+ "7X",
9578
+ "7I",
9579
+ "7Q",
9580
+ "7X",
9581
+ "8X",
9582
+ "8I",
9583
+ "8Q",
9584
+ "8X",
9585
+ "6X",
9586
+ "6A",
9587
+ "6B",
9588
+ "6C",
9589
+ "6X",
9590
+ "6Z"
9591
+ ],
9592
+ // Galileo
9593
+ 2: ["1C", "1C", "", "", "", "", "5X", "5I", "5Q", "5X"],
9594
+ // SBAS
9595
+ 4: [
9596
+ "2X",
9597
+ "2I",
9598
+ "2Q",
9599
+ "2X",
9600
+ "7X",
9601
+ "7I",
9602
+ "7Q",
9603
+ "7X",
9604
+ "6X",
9605
+ "6I",
9606
+ "6Q",
9607
+ "6X",
9608
+ "1X",
9609
+ "1S",
9610
+ "1L",
9611
+ "1X"
9612
+ ],
9613
+ // BeiDou
9614
+ 5: [
9615
+ "1C",
9616
+ "1C",
9617
+ "1S",
9618
+ "1L",
9619
+ "1X",
9620
+ "",
9621
+ "",
9622
+ "2X",
9623
+ "2S",
9624
+ "2L",
9625
+ "2X",
9626
+ "",
9627
+ "",
9628
+ "5X",
9629
+ "5I",
9630
+ "5Q",
9631
+ "5X",
9632
+ "",
9633
+ "",
9634
+ "6X",
9635
+ "6S",
9636
+ "6L",
9637
+ "6X",
9638
+ "",
9639
+ "",
9640
+ "",
9641
+ "",
9642
+ "",
9643
+ "",
9644
+ "",
9645
+ "1Z"
9646
+ ]
9647
+ // QZSS
9648
+ };
9649
+ var two6 = (n) => String(n).padStart(2, "0");
9650
+ function obsPrn(sys, prn) {
9651
+ switch (sys) {
9652
+ case 0:
9653
+ return prn >= 1 && prn <= 32 ? `G${two6(prn)}` : null;
9654
+ case 1:
9655
+ return prn >= 1 && prn <= 27 ? `R${two6(prn)}` : null;
9656
+ case 2:
9657
+ return prn >= 120 && prn <= 158 ? `S${two6(prn - 100)}` : null;
9658
+ case 3:
9659
+ return prn >= 1 && prn <= 36 ? `E${two6(prn)}` : null;
9660
+ case 4:
9661
+ return prn >= 1 && prn <= 63 ? `C${two6(prn)}` : null;
9662
+ case 5:
9663
+ if (prn >= 193 && prn <= 202) return `J${two6(prn - 192)}`;
9664
+ return prn >= 1 && prn <= 10 ? `J${two6(prn)}` : null;
9665
+ default:
9666
+ return null;
9667
+ }
9668
+ }
9669
+ function carrierFreq3(sys, code, fcn) {
9670
+ const band = code.charCodeAt(0) - 48;
9671
+ switch (sys) {
9672
+ case "G":
9673
+ case "J":
9674
+ if (band === 1) return 157542e4;
9675
+ if (band === 2) return 12276e5;
9676
+ if (band === 5) return 117645e4;
9677
+ if (band === 6) return 127875e4;
9678
+ return 0;
9679
+ case "R":
9680
+ if (band === 1) return fcn >= -7 ? 1602e6 + fcn * 562500 : 0;
9681
+ if (band === 2) return fcn >= -7 ? 1246e6 + fcn * 437500 : 0;
9682
+ if (band === 3) return 1202025e3;
9683
+ return 0;
9684
+ case "E":
9685
+ if (band === 1) return 157542e4;
9686
+ if (band === 5) return 117645e4;
9687
+ if (band === 6) return 127875e4;
9688
+ if (band === 7) return 120714e4;
9689
+ if (band === 8) return 1191795e3;
9690
+ return 0;
9691
+ case "C":
9692
+ if (band === 1) return 157542e4;
9693
+ if (band === 2) return 1561098e3;
9694
+ if (band === 5) return 117645e4;
9695
+ if (band === 6) return 126852e4;
9696
+ if (band === 7) return 120714e4;
9697
+ if (band === 8) return 1191795e3;
9698
+ return 0;
9699
+ case "S":
9700
+ if (band === 1) return 157542e4;
9701
+ if (band === 5) return 117645e4;
9702
+ return 0;
9703
+ default:
9704
+ return 0;
9705
+ }
9706
+ }
9707
+ var FCN_UNKNOWN = -100;
9708
+ function decodeObsSat(data, start, nobs, sys) {
9709
+ let p = start;
9710
+ let fcn = FCN_UNKNOWN;
9711
+ const obs = [];
9712
+ const block0Flags = [0, 0, 0, 0];
9713
+ let refRange = 0;
9714
+ for (let b = 0; b < nobs; b++) {
9715
+ const flags = b === 0 ? block0Flags : block0Flags.slice();
9716
+ const b0 = data[p++];
9717
+ const code = b0 & 31;
9718
+ const slip = (b0 >> 5 & 1) === 1;
9719
+ let more = b0 >> 7 & 1;
9720
+ while (more) {
9721
+ const fb = data[p++];
9722
+ flags[fb & 3] = fb & 127;
9723
+ more = fb & 128;
9724
+ }
9725
+ if (sys === 1 && flags[2] > 0 && (code === 1 || code === 2 || code === 11 || code === 12)) {
9726
+ fcn = getBitS(Uint8Array.of(flags[2]), 2, 4);
9727
+ }
9728
+ const acc = flags[0] & 32 ? 1e-4 : 2e-5;
9729
+ let cn0 = data[p++] * 0.4;
9730
+ let range;
9731
+ if (b === 0) {
9732
+ cn0 += getBitS(data, p * 8, 2) * 0.1;
9733
+ range = getBitU(data, p * 8 + 2, 38) * 1e-3;
9734
+ p += 5;
9735
+ refRange = range;
9736
+ } else if (flags[0] & 64) {
9737
+ cn0 += getBitS(data, p * 8, 2) * 0.1;
9738
+ range = refRange + getBitS(data, p * 8 + 4, 20) * 1e-3;
9739
+ p += 3;
9740
+ } else {
9741
+ range = refRange + getBitS(data, p * 8, 16) * 1e-3;
9742
+ p += 2;
9743
+ }
9744
+ let phase;
9745
+ if (flags[0] & 64) {
9746
+ phase = range + getBitS(data, p * 8, 24) * acc;
9747
+ p += 3;
9748
+ } else {
9749
+ cn0 += getBitS(data, p * 8, 2) * 0.1;
9750
+ phase = range + getBitS(data, p * 8 + 2, 22) * acc;
9751
+ p += 3;
9752
+ }
9753
+ let doppler = null;
9754
+ if (flags[0] & 4) {
9755
+ doppler = getBitS(data, p * 8, 24) / 256;
9756
+ p += 3;
9757
+ }
9758
+ if (flags[0] & 8) {
9759
+ p += flags[0] & 16 ? 2 : 1;
9760
+ }
9761
+ obs.push({ code, slip, pr: range, phase, cn0, doppler });
9762
+ }
9763
+ return { obs, fcn, next: p };
9764
+ }
9765
+ function decodeObsRecord(data, view, body, len, obsCodes) {
9766
+ let p = body + 1;
9767
+ const min = view.getUint32(p);
9768
+ p += 4;
9769
+ const msec = view.getUint16(p);
9770
+ p += 2;
9771
+ const timeMs = GPS_EPOCH_MS16 + min * 6e4 + msec;
9772
+ const flag = data[p++];
9773
+ const nsat = (flag & 63) + 1;
9774
+ if (flag & 128) p += 3;
9775
+ if (flag & 64) {
9776
+ const nsys = getBitU(data, p * 8, 4);
9777
+ p += 1;
9778
+ p += nsys * 4;
9779
+ }
9780
+ const end = body + len;
9781
+ const meas = [];
9782
+ for (let i = 0; i < nsat && p < end; i++) {
9783
+ const prn = data[p++];
9784
+ const b = data[p++];
9785
+ const nobs = b >> 4 & 7;
9786
+ const sys = b & 15;
9787
+ const sat = obsPrn(sys, prn);
9788
+ const { obs, fcn, next } = decodeObsSat(data, p, nobs, sys);
9789
+ p = next;
9790
+ if (p > end) return null;
9791
+ if (!sat) continue;
9792
+ const table = OBS_CODES[sys];
9793
+ const sysL = sat[0];
9794
+ for (const o of obs) {
9795
+ const code = table?.[o.code & 63] ?? "";
9796
+ if (!code) continue;
9797
+ const freq = carrierFreq3(sysL, code, fcn);
9798
+ meas.push({
9799
+ prn: sat,
9800
+ code,
9801
+ pr: o.pr,
9802
+ cp: freq > 0 ? o.phase * freq / CLIGHT2 : null,
9803
+ doppler: o.doppler,
9804
+ cn0: o.cn0,
9805
+ slip: o.slip
9806
+ });
9807
+ const codes = obsCodes[sysL] ??= [];
9808
+ if (!codes.includes(code)) codes.push(code);
9809
+ }
9810
+ }
9811
+ return { timeMs, meas };
9812
+ }
9813
+ function parseBinex(data) {
9814
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
9815
+ const epochs = [];
9816
+ const ephemerides = [];
9817
+ const messageCounts = {};
9818
+ const obsCodes = {};
9819
+ const stats = { badCrc: 0 };
9820
+ const lastKep = /* @__PURE__ */ new Map();
9821
+ const lastState = /* @__PURE__ */ new Map();
9822
+ const hex = (n) => `0x${n.toString(16).padStart(2, "0")}`;
9823
+ for (const rec of binexRecords(data, view, stats)) {
9824
+ const sub = rec.len > 0 ? data[rec.body] : 0;
9825
+ const key = rec.id === 1 || rec.id === 127 ? `${hex(rec.id)}-${sub.toString(16).padStart(2, "0")}` : hex(rec.id);
9826
+ messageCounts[key] = (messageCounts[key] ?? 0) + 1;
9827
+ if (rec.id === 127 && sub === 5 && rec.len >= 8 && !rec.littleEndian) {
9828
+ const epoch = decodeObsRecord(data, view, rec.body, rec.len, obsCodes);
9829
+ if (epoch) epochs.push(epoch);
9830
+ } else if (rec.id === 1 && rec.len >= 2) {
9831
+ const eph = decodeBinexEph(view, rec.body, rec.len, rec.littleEndian);
9832
+ if (!eph) continue;
9833
+ if ("iode" in eph) {
9834
+ const prev = lastKep.get(eph.prn);
9835
+ if (prev && prev.iode === eph.iode && prev.toe === eph.toe && prev.tocDate.getTime() === eph.tocDate.getTime()) {
9836
+ continue;
9837
+ }
9838
+ lastKep.set(eph.prn, eph);
9839
+ ephemerides.push(eph);
9840
+ } else {
9841
+ const prev = lastState.get(eph.prn);
9842
+ if (prev && Math.abs(prev.tocDate.getTime() - eph.tocDate.getTime()) < 1e3 && prev.health === eph.health) {
9843
+ continue;
9844
+ }
9845
+ lastState.set(eph.prn, eph);
9846
+ ephemerides.push(eph);
9847
+ }
9848
+ }
9849
+ }
9850
+ return { epochs, ephemerides, messageCounts, obsCodes, badCrc: stats.badCrc };
9851
+ }
9852
+
8683
9853
  // src/orbit/almanac.ts
8684
9854
  var GM_GPS = 3986005e8;
8685
9855
  var GM_GAL = 3986004418e5;
8686
9856
  var GM_BDS = 3986004418e5;
8687
- var GPS_EPOCH_MS13 = Date.UTC(1980, 0, 6);
8688
- var BDT_EPOCH_MS4 = Date.UTC(2006, 0, 1);
9857
+ var GPS_EPOCH_MS17 = Date.UTC(1980, 0, 6);
9858
+ var BDT_EPOCH_MS5 = Date.UTC(2006, 0, 1);
8689
9859
  var WEEK_MS = 6048e5;
8690
9860
  var BDT_MINUS_GPST_MS = 14e3;
8691
9861
  var BDS_GEO_PRNS = /* @__PURE__ */ new Set([1, 2, 3, 4, 5, 59, 60, 61, 62, 63]);
8692
9862
  function almanacEpochMs(alm) {
8693
9863
  if (alm.system === "C") {
8694
- return BDT_EPOCH_MS4 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3 + BDT_MINUS_GPST_MS;
9864
+ return BDT_EPOCH_MS5 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3 + BDT_MINUS_GPST_MS;
8695
9865
  }
8696
- return GPS_EPOCH_MS13 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3;
9866
+ return GPS_EPOCH_MS17 + alm.weekAlm * WEEK_MS + alm.toaSec * 1e3;
8697
9867
  }
8698
9868
  function almanacSatPosition(alm, timeMs) {
8699
9869
  const GM = alm.system === "E" ? GM_GAL : alm.system === "C" ? GM_BDS : GM_GPS;
@@ -9202,10 +10372,10 @@ function selectBest(ephs, timeMs) {
9202
10372
  }
9203
10373
  return best;
9204
10374
  }
9205
- var GPS_EPOCH_MS14 = START_GPS_TIME.getTime();
9206
- var MS_PER_WEEK9 = 7 * 864e5;
10375
+ var GPS_EPOCH_MS18 = START_GPS_TIME.getTime();
10376
+ var MS_PER_WEEK12 = 7 * 864e5;
9207
10377
  var BDS_EPOCH_MS = START_BDS_TIME.getTime();
9208
- var GAL_EPOCH_MS = GPS_EPOCH_MS14 + 1024 * MS_PER_WEEK9;
10378
+ var GAL_EPOCH_MS = GPS_EPOCH_MS18 + 1024 * MS_PER_WEEK12;
9209
10379
  function ephInfoToEphemeris(info) {
9210
10380
  const sys = info.prn.charAt(0);
9211
10381
  if (sys === "R") {
@@ -9256,11 +10426,11 @@ function ephInfoToEphemeris(info) {
9256
10426
  } else if (sys === "E") {
9257
10427
  epochMs = GAL_EPOCH_MS;
9258
10428
  } else {
9259
- epochMs = GPS_EPOCH_MS14;
9260
- const weeksNow = (info.lastReceived - GPS_EPOCH_MS14) / MS_PER_WEEK9;
10429
+ epochMs = GPS_EPOCH_MS18;
10430
+ const weeksNow = (info.lastReceived - GPS_EPOCH_MS18) / MS_PER_WEEK12;
9261
10431
  week += 1024 * Math.round((weeksNow - week) / 1024);
9262
10432
  }
9263
- const tocDate = new Date(epochMs + week * MS_PER_WEEK9 + tocSec * 1e3);
10433
+ const tocDate = new Date(epochMs + week * MS_PER_WEEK12 + tocSec * 1e3);
9264
10434
  return {
9265
10435
  system: sys,
9266
10436
  prn: info.prn,
@@ -13314,6 +14484,10 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
13314
14484
  analyzeQuality,
13315
14485
  applyHelmert,
13316
14486
  applyIonoDcb,
14487
+ binexCrc16,
14488
+ binexCrc32,
14489
+ binexCsum8,
14490
+ binexRecords,
13317
14491
  buildGloChannelMap,
13318
14492
  buildObsIndices,
13319
14493
  clampUnit,
@@ -13334,6 +14508,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
13334
14508
  crxDecompress,
13335
14509
  crxRepair,
13336
14510
  dateToEpoch,
14511
+ decodeBinexEph,
13337
14512
  decodeEphemeris,
13338
14513
  decodeMsmFull,
13339
14514
  deg2dms,
@@ -13355,6 +14530,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
13355
14530
  geodeticToUtm,
13356
14531
  getAer,
13357
14532
  getBdsTime,
14533
+ getBnxi,
13358
14534
  getDateFromBdsTime,
13359
14535
  getDateFromDayOfWeek,
13360
14536
  getDateFromDayOfYear,
@@ -13428,6 +14604,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
13428
14604
  padL,
13429
14605
  padR,
13430
14606
  parseAntex,
14607
+ parseBinex,
13431
14608
  parseCrxDataLine,
13432
14609
  parseIonex,
13433
14610
  parseNavFile,
@@ -13447,6 +14624,8 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
13447
14624
  parseSinexBiasDcb,
13448
14625
  parseSourcetable,
13449
14626
  parseSp3,
14627
+ parseTrimble,
14628
+ parseTrimbleNav,
13450
14629
  parseUbxCnav,
13451
14630
  parseUbxIonoUtc,
13452
14631
  parseUbxNav,
@@ -13477,6 +14656,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
13477
14656
  systemName,
13478
14657
  toRtkEpoch,
13479
14658
  transformFrame,
14659
+ trimbleFrames,
13480
14660
  ubxFrames,
13481
14661
  updateStationMeta,
13482
14662
  updateStreamStats,