gnss-js 1.16.0 → 1.18.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/{chunk-R33A2VA7.js → chunk-2IM5VXNI.js} +193 -12
- package/dist/{chunk-YPOVPXNK.js → chunk-CG7SF45F.js} +75 -0
- package/dist/{chunk-6CX6EXRK.js → chunk-FEGLXNWA.js} +97 -23
- package/dist/{chunk-4LVD4DYL.js → chunk-IQ5OIMQD.js} +2 -0
- package/dist/chunk-Y5IWUPJQ.js +206 -0
- package/dist/cnav-CRns0ECn.d.cts +96 -0
- package/dist/cnav-CRns0ECn.d.ts +96 -0
- package/dist/index.cjs +577 -56
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +13 -4
- package/dist/novatel.cjs +192 -11
- package/dist/novatel.d.cts +36 -13
- package/dist/novatel.d.ts +36 -13
- package/dist/novatel.js +2 -2
- package/dist/sbf.cjs +288 -2
- package/dist/sbf.d.cts +82 -1
- package/dist/sbf.d.ts +82 -1
- package/dist/sbf.js +7 -1
- package/dist/ubx.cjs +291 -24
- package/dist/ubx.d.cts +73 -2
- package/dist/ubx.d.ts +73 -2
- package/dist/ubx.js +7 -2
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
decodeGpsLnavFrame
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-IQ5OIMQD.js";
|
|
4
4
|
import {
|
|
5
5
|
getUtcDate
|
|
6
6
|
} from "./chunk-HVXYFUCB.js";
|
|
@@ -50,11 +50,27 @@ function* oem4Frames(data, view, stats) {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
// src/novatel/nav.ts
|
|
53
|
+
var ID_IONUTC = 8;
|
|
53
54
|
var ID_RAWEPHEM = 41;
|
|
54
55
|
var ID_GLOEPHEMERIS = 723;
|
|
56
|
+
var ID_GALEPHEMERIS = 1122;
|
|
57
|
+
var ID_QZSSEPHEMERIS = 1336;
|
|
58
|
+
var ID_GPSEPHEM = 7;
|
|
59
|
+
var ID_BDSEPHEMERIS = 1696;
|
|
55
60
|
var GPS_EPOCH_MS = Date.UTC(1980, 0, 6);
|
|
61
|
+
var BDT_EPOCH_MS = Date.UTC(2006, 0, 1);
|
|
56
62
|
var SEC_PER_WEEK = 7 * 86400;
|
|
57
63
|
var SEC_PER_DAY = 86400;
|
|
64
|
+
var MS_PER_WEEK = SEC_PER_WEEK * 1e3;
|
|
65
|
+
var gpsMs = (week, sec) => GPS_EPOCH_MS + week * MS_PER_WEEK + sec * 1e3;
|
|
66
|
+
var sowOf = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK;
|
|
67
|
+
function nearWeekMs(refMs, sow) {
|
|
68
|
+
const refWeek = Math.floor((refMs - GPS_EPOCH_MS) / MS_PER_WEEK);
|
|
69
|
+
let ms = gpsMs(refWeek, sow);
|
|
70
|
+
if (ms < refMs - MS_PER_WEEK / 2) ms += MS_PER_WEEK;
|
|
71
|
+
else if (ms > refMs + MS_PER_WEEK / 2) ms -= MS_PER_WEEK;
|
|
72
|
+
return ms;
|
|
73
|
+
}
|
|
58
74
|
function decodeRawEphem(data, view, p) {
|
|
59
75
|
const prn = view.getUint32(p, true);
|
|
60
76
|
if (prn < 1 || prn > 32) return null;
|
|
@@ -100,23 +116,188 @@ function decodeGloEphemeris(view, p) {
|
|
|
100
116
|
freqNum
|
|
101
117
|
};
|
|
102
118
|
}
|
|
119
|
+
function decodeGalEphemeris(view, p, headerMs) {
|
|
120
|
+
const prn = view.getUint32(p, true);
|
|
121
|
+
if (prn < 1 || prn > 36) return null;
|
|
122
|
+
const fnav = (view.getUint32(p + 4, true) & 1) !== 0;
|
|
123
|
+
const svhE1b = view.getUint8(p + 12) & 3;
|
|
124
|
+
const svhE5a = view.getUint8(p + 13) & 3;
|
|
125
|
+
const svhE5b = view.getUint8(p + 14) & 3;
|
|
126
|
+
const dvsE1b = view.getUint8(p + 15) & 1;
|
|
127
|
+
const dvsE5a = view.getUint8(p + 16) & 1;
|
|
128
|
+
const dvsE5b = view.getUint8(p + 17) & 1;
|
|
129
|
+
const iodNav = view.getUint32(p + 20, true);
|
|
130
|
+
const toes = view.getUint32(p + 24, true);
|
|
131
|
+
const c = fnav ? p + 148 : p + 176;
|
|
132
|
+
const tocs = view.getUint32(c, true);
|
|
133
|
+
const toeMs = nearWeekMs(headerMs, toes);
|
|
134
|
+
const tocDate = new Date(nearWeekMs(headerMs, tocs));
|
|
135
|
+
return {
|
|
136
|
+
fnav,
|
|
137
|
+
eph: {
|
|
138
|
+
system: "E",
|
|
139
|
+
prn: `E${String(prn).padStart(2, "0")}`,
|
|
140
|
+
toc: sowOf(tocDate.getTime()),
|
|
141
|
+
tocDate,
|
|
142
|
+
af0: view.getFloat64(c + 4, true),
|
|
143
|
+
af1: view.getFloat64(c + 12, true),
|
|
144
|
+
af2: view.getFloat64(c + 20, true),
|
|
145
|
+
iode: iodNav,
|
|
146
|
+
crs: view.getFloat64(p + 92, true),
|
|
147
|
+
deltaN: view.getFloat64(p + 36, true),
|
|
148
|
+
m0: view.getFloat64(p + 44, true),
|
|
149
|
+
cuc: view.getFloat64(p + 68, true),
|
|
150
|
+
e: view.getFloat64(p + 52, true),
|
|
151
|
+
cus: view.getFloat64(p + 76, true),
|
|
152
|
+
sqrtA: view.getFloat64(p + 28, true),
|
|
153
|
+
toe: toes,
|
|
154
|
+
cic: view.getFloat64(p + 100, true),
|
|
155
|
+
omega0: view.getFloat64(p + 132, true),
|
|
156
|
+
cis: view.getFloat64(p + 108, true),
|
|
157
|
+
i0: view.getFloat64(p + 116, true),
|
|
158
|
+
crc: view.getFloat64(p + 84, true),
|
|
159
|
+
omega: view.getFloat64(p + 60, true),
|
|
160
|
+
omegaDot: view.getFloat64(p + 140, true),
|
|
161
|
+
idot: view.getFloat64(p + 124, true),
|
|
162
|
+
week: Math.floor((toeMs - GPS_EPOCH_MS) / MS_PER_WEEK),
|
|
163
|
+
// RINEX Galileo SVH bit layout (E1B DVS/HS in bits 0-2, E5a in
|
|
164
|
+
// 3-5, E5b in 6-8) — same packing as RTKLIB.
|
|
165
|
+
svHealth: svhE5b << 7 | dvsE5b << 6 | svhE5a << 4 | dvsE5a << 3 | svhE1b << 1 | dvsE1b,
|
|
166
|
+
tgd: view.getFloat64(p + 204, true)
|
|
167
|
+
// BGD E5a/E1 (RINEX slot)
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function decodeBdsEphemeris(view, p) {
|
|
172
|
+
const prn = view.getUint32(p, true);
|
|
173
|
+
if (prn < 1 || prn > 63) return null;
|
|
174
|
+
const week = view.getUint32(p + 4, true);
|
|
175
|
+
const health = view.getUint32(p + 16, true) & 1;
|
|
176
|
+
const tgd1 = view.getFloat64(p + 20, true);
|
|
177
|
+
const tocs = view.getUint32(p + 40, true);
|
|
178
|
+
const toes = view.getUint32(p + 72, true);
|
|
179
|
+
const tocDate = new Date(BDT_EPOCH_MS + week * MS_PER_WEEK + tocs * 1e3);
|
|
180
|
+
return {
|
|
181
|
+
system: "C",
|
|
182
|
+
prn: `C${String(prn).padStart(2, "0")}`,
|
|
183
|
+
toc: sowOf(tocDate.getTime()),
|
|
184
|
+
tocDate,
|
|
185
|
+
af0: view.getFloat64(p + 44, true),
|
|
186
|
+
af1: view.getFloat64(p + 52, true),
|
|
187
|
+
af2: view.getFloat64(p + 60, true),
|
|
188
|
+
iode: view.getUint32(p + 68, true),
|
|
189
|
+
// AODE
|
|
190
|
+
crs: view.getFloat64(p + 172, true),
|
|
191
|
+
deltaN: view.getFloat64(p + 100, true),
|
|
192
|
+
m0: view.getFloat64(p + 108, true),
|
|
193
|
+
cuc: view.getFloat64(p + 148, true),
|
|
194
|
+
e: view.getFloat64(p + 84, true),
|
|
195
|
+
cus: view.getFloat64(p + 156, true),
|
|
196
|
+
sqrtA: view.getFloat64(p + 76, true),
|
|
197
|
+
toe: toes,
|
|
198
|
+
cic: view.getFloat64(p + 180, true),
|
|
199
|
+
omega0: view.getFloat64(p + 116, true),
|
|
200
|
+
cis: view.getFloat64(p + 188, true),
|
|
201
|
+
i0: view.getFloat64(p + 132, true),
|
|
202
|
+
crc: view.getFloat64(p + 164, true),
|
|
203
|
+
omega: view.getFloat64(p + 92, true),
|
|
204
|
+
omegaDot: view.getFloat64(p + 124, true),
|
|
205
|
+
idot: view.getFloat64(p + 140, true),
|
|
206
|
+
week,
|
|
207
|
+
// RINEX BDS week field is the BDT week
|
|
208
|
+
svHealth: health,
|
|
209
|
+
tgd: tgd1
|
|
210
|
+
// TGD1 (B1) — RINEX slot
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function decodeGpsQzssEphemeris(view, p, sys) {
|
|
214
|
+
const prn = view.getUint32(p, true);
|
|
215
|
+
if (sys === "G" && (prn < 1 || prn > 32)) return null;
|
|
216
|
+
if (sys === "J" && (prn < 193 || prn > 202)) return null;
|
|
217
|
+
const health = view.getUint32(p + 12, true) & 63;
|
|
218
|
+
const iode1 = view.getUint32(p + 16, true);
|
|
219
|
+
const week = view.getUint32(p + 24, true);
|
|
220
|
+
const toes = view.getFloat64(p + 32, true);
|
|
221
|
+
const toeMs = gpsMs(week, toes);
|
|
222
|
+
const tocs = view.getFloat64(p + 164, true);
|
|
223
|
+
const tocDate = new Date(nearWeekMs(toeMs, tocs));
|
|
224
|
+
return {
|
|
225
|
+
system: sys,
|
|
226
|
+
prn: `${sys}${String(sys === "J" ? prn - 192 : prn).padStart(2, "0")}`,
|
|
227
|
+
toc: sowOf(tocDate.getTime()),
|
|
228
|
+
tocDate,
|
|
229
|
+
af0: view.getFloat64(p + 180, true),
|
|
230
|
+
af1: view.getFloat64(p + 188, true),
|
|
231
|
+
af2: view.getFloat64(p + 196, true),
|
|
232
|
+
iode: iode1,
|
|
233
|
+
crs: view.getFloat64(p + 104, true),
|
|
234
|
+
deltaN: view.getFloat64(p + 48, true),
|
|
235
|
+
m0: view.getFloat64(p + 56, true),
|
|
236
|
+
cuc: view.getFloat64(p + 80, true),
|
|
237
|
+
e: view.getFloat64(p + 64, true),
|
|
238
|
+
cus: view.getFloat64(p + 88, true),
|
|
239
|
+
sqrtA: Math.sqrt(view.getFloat64(p + 40, true)),
|
|
240
|
+
toe: toes,
|
|
241
|
+
cic: view.getFloat64(p + 112, true),
|
|
242
|
+
omega0: view.getFloat64(p + 144, true),
|
|
243
|
+
cis: view.getFloat64(p + 120, true),
|
|
244
|
+
i0: view.getFloat64(p + 128, true),
|
|
245
|
+
crc: view.getFloat64(p + 96, true),
|
|
246
|
+
omega: view.getFloat64(p + 72, true),
|
|
247
|
+
omegaDot: view.getFloat64(p + 152, true),
|
|
248
|
+
idot: view.getFloat64(p + 136, true),
|
|
249
|
+
week,
|
|
250
|
+
svHealth: health,
|
|
251
|
+
tgd: view.getFloat64(p + 172, true)
|
|
252
|
+
};
|
|
253
|
+
}
|
|
103
254
|
function parseNovatelNav(data) {
|
|
104
255
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
105
256
|
const stats = { badCrc: 0 };
|
|
106
257
|
const ephemerides = [];
|
|
107
|
-
const
|
|
258
|
+
const ionoCorrections = {};
|
|
259
|
+
let leapSeconds = null;
|
|
260
|
+
const lastKep = /* @__PURE__ */ new Map();
|
|
108
261
|
const lastGlo = /* @__PURE__ */ new Map();
|
|
262
|
+
const pushKepler = (key, eph) => {
|
|
263
|
+
const prev = lastKep.get(key);
|
|
264
|
+
if (prev && prev.iode === eph.iode && prev.toe === eph.toe && prev.tocDate.getTime() === eph.tocDate.getTime()) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
lastKep.set(key, eph);
|
|
268
|
+
ephemerides.push(eph);
|
|
269
|
+
};
|
|
109
270
|
for (const frame of oem4Frames(data, view, stats)) {
|
|
110
271
|
if (!frame.binary) continue;
|
|
111
272
|
if (frame.id === ID_RAWEPHEM && frame.msgLen >= 102) {
|
|
112
273
|
const eph = decodeRawEphem(data, view, frame.payload);
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
|
|
274
|
+
if (eph) pushKepler(eph.prn, eph);
|
|
275
|
+
} else if (frame.id === ID_GALEPHEMERIS && frame.msgLen >= 220) {
|
|
276
|
+
if (frame.week === 0) continue;
|
|
277
|
+
const headerMs = gpsMs(frame.week, frame.towMs / 1e3);
|
|
278
|
+
const dec = decodeGalEphemeris(view, frame.payload, headerMs);
|
|
279
|
+
if (dec)
|
|
280
|
+
pushKepler(`${dec.eph.prn}:${dec.fnav ? "fnav" : "inav"}`, dec.eph);
|
|
281
|
+
} else if (frame.id === ID_BDSEPHEMERIS && frame.msgLen >= 196) {
|
|
282
|
+
const eph = decodeBdsEphemeris(view, frame.payload);
|
|
283
|
+
if (eph) pushKepler(eph.prn, eph);
|
|
284
|
+
} else if (frame.id === ID_GPSEPHEM && frame.msgLen >= 204) {
|
|
285
|
+
const eph = decodeGpsQzssEphemeris(view, frame.payload, "G");
|
|
286
|
+
if (eph) pushKepler(eph.prn, eph);
|
|
287
|
+
} else if (frame.id === ID_QZSSEPHEMERIS && frame.msgLen >= 204) {
|
|
288
|
+
const eph = decodeGpsQzssEphemeris(view, frame.payload, "J");
|
|
289
|
+
if (eph) pushKepler(eph.prn, eph);
|
|
290
|
+
} else if (frame.id === ID_IONUTC && frame.msgLen >= 108) {
|
|
291
|
+
const p = frame.payload;
|
|
292
|
+
const alpha = [];
|
|
293
|
+
const beta = [];
|
|
294
|
+
for (let i = 0; i < 4; i++) {
|
|
295
|
+
alpha.push(view.getFloat64(p + i * 8, true));
|
|
296
|
+
beta.push(view.getFloat64(p + 32 + i * 8, true));
|
|
117
297
|
}
|
|
118
|
-
|
|
119
|
-
|
|
298
|
+
ionoCorrections["GPSA"] = alpha;
|
|
299
|
+
ionoCorrections["GPSB"] = beta;
|
|
300
|
+
leapSeconds = view.getInt32(p + 96, true);
|
|
120
301
|
} else if (frame.id === ID_GLOEPHEMERIS && frame.msgLen >= 144) {
|
|
121
302
|
const eph = decodeGloEphemeris(view, frame.payload);
|
|
122
303
|
if (!eph) continue;
|
|
@@ -128,12 +309,12 @@ function parseNovatelNav(data) {
|
|
|
128
309
|
ephemerides.push(eph);
|
|
129
310
|
}
|
|
130
311
|
}
|
|
131
|
-
return { ephemerides, badCrc: stats.badCrc };
|
|
312
|
+
return { ephemerides, ionoCorrections, leapSeconds, badCrc: stats.badCrc };
|
|
132
313
|
}
|
|
133
314
|
|
|
134
315
|
// src/novatel/index.ts
|
|
135
316
|
var GPS_EPOCH_MS2 = Date.UTC(1980, 0, 6);
|
|
136
|
-
var
|
|
317
|
+
var MS_PER_WEEK2 = 7 * 864e5;
|
|
137
318
|
var HDR = 28;
|
|
138
319
|
var ID_RANGE = 43;
|
|
139
320
|
var ID_RANGECMP = 140;
|
|
@@ -302,7 +483,7 @@ function parseNovatelRange(data) {
|
|
|
302
483
|
if (!codes.includes(code)) codes.push(code);
|
|
303
484
|
}
|
|
304
485
|
epochs.push({
|
|
305
|
-
timeMs: GPS_EPOCH_MS2 + week *
|
|
486
|
+
timeMs: GPS_EPOCH_MS2 + week * MS_PER_WEEK2 + towMs,
|
|
306
487
|
meas
|
|
307
488
|
});
|
|
308
489
|
}
|
|
@@ -354,7 +535,7 @@ function parseNovatelRange(data) {
|
|
|
354
535
|
if (!codes.includes(code)) codes.push(code);
|
|
355
536
|
}
|
|
356
537
|
epochs.push({
|
|
357
|
-
timeMs: GPS_EPOCH_MS2 + week *
|
|
538
|
+
timeMs: GPS_EPOCH_MS2 + week * MS_PER_WEEK2 + towMs,
|
|
358
539
|
meas
|
|
359
540
|
});
|
|
360
541
|
}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CnavAssembler,
|
|
3
|
+
cnavCrcOk
|
|
4
|
+
} from "./chunk-Y5IWUPJQ.js";
|
|
1
5
|
import {
|
|
2
6
|
getGpsLeap
|
|
3
7
|
} from "./chunk-HVXYFUCB.js";
|
|
@@ -371,6 +375,75 @@ function parseSbfAlmanac(data) {
|
|
|
371
375
|
return { almanacs, badCrc };
|
|
372
376
|
}
|
|
373
377
|
|
|
378
|
+
// src/sbf/iono.ts
|
|
379
|
+
var F4_DNU2 = -2e10;
|
|
380
|
+
function parseSbfIonoUtc(data) {
|
|
381
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
382
|
+
const ionoCorrections = {};
|
|
383
|
+
let leapSeconds = null;
|
|
384
|
+
const f4s = (b, n) => {
|
|
385
|
+
const out = [];
|
|
386
|
+
for (let k = 0; k < n; k++) {
|
|
387
|
+
const v = view.getFloat32(b + 4 * k, true);
|
|
388
|
+
if (v === F4_DNU2) return null;
|
|
389
|
+
out.push(v);
|
|
390
|
+
}
|
|
391
|
+
return out;
|
|
392
|
+
};
|
|
393
|
+
scanSbfFrames(data, view, (id, b, len) => {
|
|
394
|
+
if ((id === 5893 || id === 4120) && len >= 48) {
|
|
395
|
+
const alpha = f4s(b + 16, 4);
|
|
396
|
+
const beta = f4s(b + 32, 4);
|
|
397
|
+
if (!alpha || !beta) return;
|
|
398
|
+
const sys = id === 5893 ? "GPS" : "BDS";
|
|
399
|
+
ionoCorrections[`${sys}A`] = alpha;
|
|
400
|
+
ionoCorrections[`${sys}B`] = beta;
|
|
401
|
+
} else if (id === 4030 && len >= 28) {
|
|
402
|
+
const ai = f4s(b + 16, 3);
|
|
403
|
+
if (ai) ionoCorrections["GAL"] = ai;
|
|
404
|
+
} else if (id === 5894 && len >= 37) {
|
|
405
|
+
leapSeconds = view.getInt8(b + 33);
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
return { ionoCorrections, leapSeconds };
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// src/sbf/rawnav.ts
|
|
412
|
+
var SIGNAL_OF_BLOCK = {
|
|
413
|
+
4018: "L2C",
|
|
414
|
+
4019: "L5"
|
|
415
|
+
};
|
|
416
|
+
function parseSbfCnav(data) {
|
|
417
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
418
|
+
const ephemerides = [];
|
|
419
|
+
const assemblers = {
|
|
420
|
+
L2C: new CnavAssembler(),
|
|
421
|
+
L5: new CnavAssembler()
|
|
422
|
+
};
|
|
423
|
+
let badCrc = 0;
|
|
424
|
+
let messages = 0;
|
|
425
|
+
scanSbfFrames(data, view, (id, b, len) => {
|
|
426
|
+
const signal = SIGNAL_OF_BLOCK[id];
|
|
427
|
+
if (!signal || len < 60) return;
|
|
428
|
+
messages++;
|
|
429
|
+
const msg = new Uint8Array(40);
|
|
430
|
+
for (let k = 0; k < 10; k++) {
|
|
431
|
+
const w = view.getUint32(b + 20 + 4 * k, true);
|
|
432
|
+
msg[4 * k] = w >>> 24;
|
|
433
|
+
msg[4 * k + 1] = w >>> 16 & 255;
|
|
434
|
+
msg[4 * k + 2] = w >>> 8 & 255;
|
|
435
|
+
msg[4 * k + 3] = w & 255;
|
|
436
|
+
}
|
|
437
|
+
if (!cnavCrcOk(msg)) {
|
|
438
|
+
badCrc++;
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
const eph = assemblers[signal].push(msg);
|
|
442
|
+
if (eph) ephemerides.push({ ...eph, signal });
|
|
443
|
+
});
|
|
444
|
+
return { ephemerides, badCrc, messages };
|
|
445
|
+
}
|
|
446
|
+
|
|
374
447
|
// src/sbf/index.ts
|
|
375
448
|
var CLIGHT = 299792458;
|
|
376
449
|
var GPS_EPOCH_MS2 = Date.UTC(1980, 0, 6);
|
|
@@ -1044,5 +1117,7 @@ export {
|
|
|
1044
1117
|
scanSbfFrames,
|
|
1045
1118
|
parseSbfNav,
|
|
1046
1119
|
parseSbfAlmanac,
|
|
1120
|
+
parseSbfIonoUtc,
|
|
1121
|
+
parseSbfCnav,
|
|
1047
1122
|
parseSbfMeas
|
|
1048
1123
|
};
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CnavAssembler,
|
|
3
|
+
cnavCrcOk
|
|
4
|
+
} from "./chunk-Y5IWUPJQ.js";
|
|
1
5
|
import {
|
|
2
6
|
decodeGpsLnavFrame,
|
|
7
|
+
getBitS,
|
|
3
8
|
getBitU,
|
|
4
9
|
setBitU
|
|
5
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IQ5OIMQD.js";
|
|
6
11
|
|
|
7
12
|
// src/ubx/frame.ts
|
|
8
13
|
function* ubxFrames(data, stats = { badChecksums: 0 }) {
|
|
@@ -38,6 +43,30 @@ function* ubxFrames(data, stats = { badChecksums: 0 }) {
|
|
|
38
43
|
|
|
39
44
|
// src/ubx/nav.ts
|
|
40
45
|
var PREAMB_CNAV = 139;
|
|
46
|
+
function readLnavSubframe(view, f) {
|
|
47
|
+
const p = f.payload;
|
|
48
|
+
if (p.length < 8) return null;
|
|
49
|
+
const gnssId = p[0];
|
|
50
|
+
const svId = p[1];
|
|
51
|
+
let prn;
|
|
52
|
+
if (gnssId === 0 && svId >= 1 && svId <= 32) {
|
|
53
|
+
prn = `G${String(svId).padStart(2, "0")}`;
|
|
54
|
+
} else if (gnssId === 5 && svId >= 1 && svId <= 10) {
|
|
55
|
+
if (p.length === 44) return null;
|
|
56
|
+
prn = `J${String(svId).padStart(2, "0")}`;
|
|
57
|
+
} else {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
if (p.length < 8 + 40) return null;
|
|
61
|
+
const base = f.payloadStart + 8;
|
|
62
|
+
if (view.getUint32(base, true) >>> 24 === PREAMB_CNAV) return null;
|
|
63
|
+
const buff = new Uint8Array(30);
|
|
64
|
+
for (let k = 0; k < 10; k++) {
|
|
65
|
+
const dwrd = view.getUint32(base + 4 * k, true);
|
|
66
|
+
setBitU(buff, 24 * k, 24, dwrd >>> 6 & 16777215);
|
|
67
|
+
}
|
|
68
|
+
return { prn, gnssId, svId, buff, id: getBitU(buff, 43, 3) };
|
|
69
|
+
}
|
|
41
70
|
function parseUbxNav(data, opts = {}) {
|
|
42
71
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
43
72
|
const ephemerides = [];
|
|
@@ -59,28 +88,9 @@ function parseUbxNav(data, opts = {}) {
|
|
|
59
88
|
const last = /* @__PURE__ */ new Map();
|
|
60
89
|
for (const f of ubxFrames(data)) {
|
|
61
90
|
if (f.msgClass !== 2 || f.msgId !== 19) continue;
|
|
62
|
-
const
|
|
63
|
-
if (
|
|
64
|
-
const gnssId =
|
|
65
|
-
const svId = p[1];
|
|
66
|
-
let prn;
|
|
67
|
-
if (gnssId === 0 && svId >= 1 && svId <= 32) {
|
|
68
|
-
prn = `G${String(svId).padStart(2, "0")}`;
|
|
69
|
-
} else if (gnssId === 5 && svId >= 1 && svId <= 10) {
|
|
70
|
-
if (p.length === 44) continue;
|
|
71
|
-
prn = `J${String(svId).padStart(2, "0")}`;
|
|
72
|
-
} else {
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
if (p.length < 8 + 40) continue;
|
|
76
|
-
const base = f.payloadStart + 8;
|
|
77
|
-
if (view.getUint32(base, true) >>> 24 === PREAMB_CNAV) continue;
|
|
78
|
-
const buff = new Uint8Array(30);
|
|
79
|
-
for (let k = 0; k < 10; k++) {
|
|
80
|
-
const dwrd = view.getUint32(base + 4 * k, true);
|
|
81
|
-
setBitU(buff, 24 * k, 24, dwrd >>> 6 & 16777215);
|
|
82
|
-
}
|
|
83
|
-
const id = getBitU(buff, 43, 3);
|
|
91
|
+
const lnav = readLnavSubframe(view, f);
|
|
92
|
+
if (!lnav) continue;
|
|
93
|
+
const { prn, gnssId, svId, buff, id } = lnav;
|
|
84
94
|
if (id < 1 || id > 5) {
|
|
85
95
|
badParity++;
|
|
86
96
|
continue;
|
|
@@ -110,6 +120,68 @@ function parseUbxNav(data, opts = {}) {
|
|
|
110
120
|
return { ephemerides, badParity };
|
|
111
121
|
}
|
|
112
122
|
|
|
123
|
+
// src/ubx/iono.ts
|
|
124
|
+
function parseUbxIonoUtc(data) {
|
|
125
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
126
|
+
const ionoCorrections = {};
|
|
127
|
+
let leapSeconds = null;
|
|
128
|
+
for (const f of ubxFrames(data)) {
|
|
129
|
+
if (f.msgClass !== 2 || f.msgId !== 19) continue;
|
|
130
|
+
const sf = readLnavSubframe(view, f);
|
|
131
|
+
if (!sf || sf.gnssId !== 0 || sf.id !== 4) continue;
|
|
132
|
+
const b = sf.buff;
|
|
133
|
+
if (getBitU(b, 48, 2) !== 1 || getBitU(b, 50, 6) !== 56) continue;
|
|
134
|
+
ionoCorrections["GPSA"] = [
|
|
135
|
+
getBitS(b, 56, 8) * 2 ** -30,
|
|
136
|
+
getBitS(b, 64, 8) * 2 ** -27,
|
|
137
|
+
getBitS(b, 72, 8) * 2 ** -24,
|
|
138
|
+
getBitS(b, 80, 8) * 2 ** -24
|
|
139
|
+
];
|
|
140
|
+
ionoCorrections["GPSB"] = [
|
|
141
|
+
getBitS(b, 88, 8) * 2 ** 11,
|
|
142
|
+
getBitS(b, 96, 8) * 2 ** 14,
|
|
143
|
+
getBitS(b, 104, 8) * 2 ** 16,
|
|
144
|
+
getBitS(b, 112, 8) * 2 ** 16
|
|
145
|
+
];
|
|
146
|
+
leapSeconds = getBitS(b, 192, 8);
|
|
147
|
+
}
|
|
148
|
+
return { ionoCorrections, leapSeconds };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/ubx/cnav.ts
|
|
152
|
+
function parseUbxCnav(data) {
|
|
153
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
154
|
+
const assembler = new CnavAssembler();
|
|
155
|
+
const ephemerides = [];
|
|
156
|
+
let badCrc = 0;
|
|
157
|
+
let messages = 0;
|
|
158
|
+
for (const f of ubxFrames(data)) {
|
|
159
|
+
if (f.msgClass !== 2 || f.msgId !== 19) continue;
|
|
160
|
+
const p = f.payload;
|
|
161
|
+
if (p.length < 8 + 40) continue;
|
|
162
|
+
if (p[0] !== 0 || p[2] !== 3 && p[2] !== 4) continue;
|
|
163
|
+
const svId = p[1];
|
|
164
|
+
if (svId < 1 || svId > 32) continue;
|
|
165
|
+
messages++;
|
|
166
|
+
const msg = new Uint8Array(40);
|
|
167
|
+
const base = f.payloadStart + 8;
|
|
168
|
+
for (let k = 0; k < 10; k++) {
|
|
169
|
+
const w = view.getUint32(base + 4 * k, true);
|
|
170
|
+
msg[4 * k] = w >>> 24;
|
|
171
|
+
msg[4 * k + 1] = w >>> 16 & 255;
|
|
172
|
+
msg[4 * k + 2] = w >>> 8 & 255;
|
|
173
|
+
msg[4 * k + 3] = w & 255;
|
|
174
|
+
}
|
|
175
|
+
if (!cnavCrcOk(msg)) {
|
|
176
|
+
badCrc++;
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
const eph = assembler.push(msg);
|
|
180
|
+
if (eph) ephemerides.push(eph);
|
|
181
|
+
}
|
|
182
|
+
return { ephemerides, badCrc, messages };
|
|
183
|
+
}
|
|
184
|
+
|
|
113
185
|
// src/ubx/index.ts
|
|
114
186
|
var GPS_EPOCH_MS = Date.UTC(1980, 0, 6);
|
|
115
187
|
var MS_PER_WEEK = 7 * 864e5;
|
|
@@ -206,5 +278,7 @@ function parseUbxRawx(data) {
|
|
|
206
278
|
export {
|
|
207
279
|
ubxFrames,
|
|
208
280
|
parseUbxNav,
|
|
281
|
+
parseUbxIonoUtc,
|
|
282
|
+
parseUbxCnav,
|
|
209
283
|
parseUbxRawx
|
|
210
284
|
};
|