gnss-js 1.20.0 → 1.22.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-DLXTTHRK.js → chunk-MCAVU3XL.js} +118 -9
- package/dist/{chunk-VJEPOC76.js → chunk-PZNVFCKJ.js} +549 -766
- package/dist/chunk-VTX3VCL4.js +769 -0
- package/dist/index.cjs +1654 -1027
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -2
- package/dist/sbf.cjs +525 -0
- package/dist/sbf.d.cts +173 -1
- package/dist/sbf.d.ts +173 -1
- package/dist/sbf.js +4 -1
- package/dist/ubx.cjs +809 -10
- package/dist/ubx.d.cts +111 -1
- package/dist/ubx.d.ts +111 -1
- package/dist/ubx.js +6 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -9,8 +9,8 @@ export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResul
|
|
|
9
9
|
export { C as CnavEphemeris, E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, R as RinexCnavEphemeris, p as parseNavFile } from './nav-DImXUdbp.cjs';
|
|
10
10
|
export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.cjs';
|
|
11
11
|
export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.cjs';
|
|
12
|
-
export { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxRawx, ubxFrames } from './ubx.cjs';
|
|
13
|
-
export { SbfBdsNavResult, SbfCnavEphemeris, SbfCnavResult, SbfGalEphemeris, SbfGalNavResult, SbfGloNavResult, SbfIonoUtcResult, SbfMeasEpoch, SbfMeasurement, SbfParseResult, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGloNav, parseSbfIonoUtc, parseSbfMeas, sbfCrc16, scanSbfFrames } from './sbf.cjs';
|
|
12
|
+
export { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxRawNavOptions, UbxRawNavResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxRawNav, parseUbxRawx, ubxFrames } from './ubx.cjs';
|
|
13
|
+
export { HasMessage, SbfBdsNavResult, SbfCnavEphemeris, SbfCnavResult, SbfGalEphemeris, SbfGalNavResult, SbfGloNavResult, SbfHasMessage, SbfHasResult, SbfIonoUtcResult, SbfMeasEpoch, SbfMeasurement, SbfParseResult, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGloNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, sbfCrc16, scanSbfFrames } from './sbf.cjs';
|
|
14
14
|
export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelRange } from './novatel.cjs';
|
|
15
15
|
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';
|
|
16
16
|
export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -9,8 +9,8 @@ export { E as EpochSummary, P as ParseOptions, R as RinexHeader, a as RinexResul
|
|
|
9
9
|
export { C as CnavEphemeris, E as Ephemeris, G as GlonassEphemeris, K as KeplerEphemeris, N as NavHeader, a as NavResult, R as RinexCnavEphemeris, p as parseNavFile } from './nav-DImXUdbp.js';
|
|
10
10
|
export { B as BitReader, E as EphemerisInfo, R as Rtcm3DebugHandler, a as Rtcm3Decoder, b as Rtcm3Frame, d as decodeEphemeris, r as readString, c as reportDecodeError, s as setRtcm3DebugHandler } from './ephemeris-Ohl6NAfw.js';
|
|
11
11
|
export { MessageTypeStats, MsmEpoch, MsmSatObs, MsmSignal, RTCM3_MESSAGE_NAMES, SatCn0, SignalCn0, StationMeta, StreamStats, createStationMeta, createStreamStats, decodeMsmFull, msmEpochToDate, resetGloFreqCache, rtcm3Constellation, setGloFreqNumber, updateStationMeta, updateStreamStats } from './rtcm3.js';
|
|
12
|
-
export { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxRawx, ubxFrames } from './ubx.js';
|
|
13
|
-
export { SbfBdsNavResult, SbfCnavEphemeris, SbfCnavResult, SbfGalEphemeris, SbfGalNavResult, SbfGloNavResult, SbfIonoUtcResult, SbfMeasEpoch, SbfMeasurement, SbfParseResult, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGloNav, parseSbfIonoUtc, parseSbfMeas, sbfCrc16, scanSbfFrames } from './sbf.js';
|
|
12
|
+
export { UbxCnavResult, UbxFrame, UbxIonoUtcResult, UbxMeasurement, UbxNavOptions, UbxNavResult, UbxParseResult, UbxRawNavOptions, UbxRawNavResult, UbxRawxEpoch, parseUbxCnav, parseUbxIonoUtc, parseUbxNav, parseUbxRawNav, parseUbxRawx, ubxFrames } from './ubx.js';
|
|
13
|
+
export { HasMessage, SbfBdsNavResult, SbfCnavEphemeris, SbfCnavResult, SbfGalEphemeris, SbfGalNavResult, SbfGloNavResult, SbfHasMessage, SbfHasResult, SbfIonoUtcResult, SbfMeasEpoch, SbfMeasurement, SbfParseResult, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGloNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, sbfCrc16, scanSbfFrames } from './sbf.js';
|
|
14
14
|
export { NovatelEpoch, NovatelMeasurement, NovatelNavResult, NovatelParseResult, OEM4_HLEN, Oem4Frame, crc32, oem4Frames, parseNovatelNav, parseNovatelRange } from './novatel.js';
|
|
15
15
|
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';
|
|
16
16
|
export { Helmert14, REFERENCE_FRAMES, ReferenceFrame, applyHelmert, dateToEpoch, transformFrame } from './frames.js';
|
package/dist/index.js
CHANGED
|
@@ -37,9 +37,10 @@ import {
|
|
|
37
37
|
parseUbxCnav,
|
|
38
38
|
parseUbxIonoUtc,
|
|
39
39
|
parseUbxNav,
|
|
40
|
+
parseUbxRawNav,
|
|
40
41
|
parseUbxRawx,
|
|
41
42
|
ubxFrames
|
|
42
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-MCAVU3XL.js";
|
|
43
44
|
import {
|
|
44
45
|
crc16,
|
|
45
46
|
parseSbfAlmanac,
|
|
@@ -47,11 +48,13 @@ import {
|
|
|
47
48
|
parseSbfCnav,
|
|
48
49
|
parseSbfGalNav,
|
|
49
50
|
parseSbfGloNav,
|
|
51
|
+
parseSbfHas,
|
|
50
52
|
parseSbfIonoUtc,
|
|
51
53
|
parseSbfMeas,
|
|
52
54
|
parseSbfNav,
|
|
53
55
|
scanSbfFrames
|
|
54
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-PZNVFCKJ.js";
|
|
57
|
+
import "./chunk-VTX3VCL4.js";
|
|
55
58
|
import {
|
|
56
59
|
OEM4_HLEN,
|
|
57
60
|
crc32,
|
|
@@ -509,6 +512,7 @@ export {
|
|
|
509
512
|
parseSbfCnav,
|
|
510
513
|
parseSbfGalNav,
|
|
511
514
|
parseSbfGloNav,
|
|
515
|
+
parseSbfHas,
|
|
512
516
|
parseSbfIonoUtc,
|
|
513
517
|
parseSbfMeas,
|
|
514
518
|
parseSbfNav,
|
|
@@ -518,6 +522,7 @@ export {
|
|
|
518
522
|
parseUbxCnav,
|
|
519
523
|
parseUbxIonoUtc,
|
|
520
524
|
parseUbxNav,
|
|
525
|
+
parseUbxRawNav,
|
|
521
526
|
parseUbxRawx,
|
|
522
527
|
phiAltBOC,
|
|
523
528
|
phiBOCc,
|
package/dist/sbf.cjs
CHANGED
|
@@ -25,6 +25,7 @@ __export(sbf_exports, {
|
|
|
25
25
|
parseSbfCnav: () => parseSbfCnav,
|
|
26
26
|
parseSbfGalNav: () => parseSbfGalNav,
|
|
27
27
|
parseSbfGloNav: () => parseSbfGloNav,
|
|
28
|
+
parseSbfHas: () => parseSbfHas,
|
|
28
29
|
parseSbfIonoUtc: () => parseSbfIonoUtc,
|
|
29
30
|
parseSbfMeas: () => parseSbfMeas,
|
|
30
31
|
parseSbfNav: () => parseSbfNav,
|
|
@@ -1662,6 +1663,529 @@ function parseSbfGloNav(data) {
|
|
|
1662
1663
|
return { ephemerides, badCrc, messages };
|
|
1663
1664
|
}
|
|
1664
1665
|
|
|
1666
|
+
// src/navbits/rs255.ts
|
|
1667
|
+
var RS255_N = 255;
|
|
1668
|
+
var RS255_K = 32;
|
|
1669
|
+
var EXP = new Uint8Array(510);
|
|
1670
|
+
var LOG = new Int16Array(256).fill(-1);
|
|
1671
|
+
{
|
|
1672
|
+
let x = 1;
|
|
1673
|
+
for (let i = 0; i < 255; i++) {
|
|
1674
|
+
EXP[i] = x;
|
|
1675
|
+
LOG[x] = i;
|
|
1676
|
+
x <<= 1;
|
|
1677
|
+
if (x & 256) x ^= 285;
|
|
1678
|
+
}
|
|
1679
|
+
for (let i = 255; i < 510; i++) EXP[i] = EXP[i - 255];
|
|
1680
|
+
}
|
|
1681
|
+
var gfMul = (a, b) => a === 0 || b === 0 ? 0 : EXP[LOG[a] + LOG[b]];
|
|
1682
|
+
var gfInv = (a) => EXP[255 - LOG[a]];
|
|
1683
|
+
var GEN_POLY = (() => {
|
|
1684
|
+
let g = new Uint8Array([1]);
|
|
1685
|
+
for (let i = 1; i <= 223; i++) {
|
|
1686
|
+
const root = EXP[i];
|
|
1687
|
+
const next = new Uint8Array(g.length + 1);
|
|
1688
|
+
for (let j = 0; j < g.length; j++) {
|
|
1689
|
+
next[j] ^= g[j];
|
|
1690
|
+
next[j + 1] ^= gfMul(g[j], root);
|
|
1691
|
+
}
|
|
1692
|
+
g = next;
|
|
1693
|
+
}
|
|
1694
|
+
return g;
|
|
1695
|
+
})();
|
|
1696
|
+
function rs255Encode(info) {
|
|
1697
|
+
if (info.length > RS255_K)
|
|
1698
|
+
throw new RangeError(`rs255Encode: info length ${info.length} > 32`);
|
|
1699
|
+
const cw = new Uint8Array(RS255_N);
|
|
1700
|
+
cw.set(info, 0);
|
|
1701
|
+
const work = new Uint8Array(RS255_N);
|
|
1702
|
+
work.set(info, 0);
|
|
1703
|
+
for (let i = 0; i < RS255_K; i++) {
|
|
1704
|
+
const coef = work[i];
|
|
1705
|
+
if (coef === 0) continue;
|
|
1706
|
+
for (let j = 1; j < GEN_POLY.length; j++)
|
|
1707
|
+
work[i + j] ^= gfMul(GEN_POLY[j], coef);
|
|
1708
|
+
}
|
|
1709
|
+
cw.set(work.subarray(RS255_K), RS255_K);
|
|
1710
|
+
return cw;
|
|
1711
|
+
}
|
|
1712
|
+
var genMatrix = null;
|
|
1713
|
+
function generatorMatrix() {
|
|
1714
|
+
if (genMatrix) return genMatrix;
|
|
1715
|
+
const rows = [];
|
|
1716
|
+
for (let r = 0; r < RS255_N; r++) rows.push(new Uint8Array(RS255_K));
|
|
1717
|
+
for (let c = 0; c < RS255_K; c++) {
|
|
1718
|
+
const e = new Uint8Array(RS255_K);
|
|
1719
|
+
e[c] = 1;
|
|
1720
|
+
const cw = rs255Encode(e);
|
|
1721
|
+
for (let r = 0; r < RS255_N; r++) rows[r][c] = cw[r];
|
|
1722
|
+
}
|
|
1723
|
+
genMatrix = rows;
|
|
1724
|
+
return rows;
|
|
1725
|
+
}
|
|
1726
|
+
function rs255DecodeErasures(pages, k) {
|
|
1727
|
+
if (k < 1 || k > RS255_K) return null;
|
|
1728
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1729
|
+
const use = [];
|
|
1730
|
+
for (const p of pages) {
|
|
1731
|
+
if (p.pageId < 1 || p.pageId > RS255_N || seen.has(p.pageId)) continue;
|
|
1732
|
+
seen.add(p.pageId);
|
|
1733
|
+
use.push(p);
|
|
1734
|
+
if (use.length === k) break;
|
|
1735
|
+
}
|
|
1736
|
+
if (use.length < k) return null;
|
|
1737
|
+
const width = use[0].octets.length;
|
|
1738
|
+
if (use.some((p) => p.octets.length !== width)) return null;
|
|
1739
|
+
const G = generatorMatrix();
|
|
1740
|
+
const a = use.map((p) => G[p.pageId - 1].slice(0, k));
|
|
1741
|
+
const inv = use.map((_, r) => {
|
|
1742
|
+
const row = new Uint8Array(k);
|
|
1743
|
+
row[r] = 1;
|
|
1744
|
+
return row;
|
|
1745
|
+
});
|
|
1746
|
+
for (let c = 0; c < k; c++) {
|
|
1747
|
+
let pivot = -1;
|
|
1748
|
+
for (let r = c; r < k; r++)
|
|
1749
|
+
if (a[r][c] !== 0) {
|
|
1750
|
+
pivot = r;
|
|
1751
|
+
break;
|
|
1752
|
+
}
|
|
1753
|
+
if (pivot < 0) return null;
|
|
1754
|
+
[a[c], a[pivot]] = [a[pivot], a[c]];
|
|
1755
|
+
[inv[c], inv[pivot]] = [inv[pivot], inv[c]];
|
|
1756
|
+
const s = gfInv(a[c][c]);
|
|
1757
|
+
for (let j = 0; j < k; j++) {
|
|
1758
|
+
a[c][j] = gfMul(a[c][j], s);
|
|
1759
|
+
inv[c][j] = gfMul(inv[c][j], s);
|
|
1760
|
+
}
|
|
1761
|
+
for (let r = 0; r < k; r++) {
|
|
1762
|
+
if (r === c || a[r][c] === 0) continue;
|
|
1763
|
+
const f = a[r][c];
|
|
1764
|
+
for (let j = 0; j < k; j++) {
|
|
1765
|
+
a[r][j] ^= gfMul(a[c][j], f);
|
|
1766
|
+
inv[r][j] ^= gfMul(inv[c][j], f);
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
const out = new Uint8Array(k * width);
|
|
1771
|
+
for (let r = 0; r < k; r++)
|
|
1772
|
+
for (let c = 0; c < width; c++) {
|
|
1773
|
+
let v = 0;
|
|
1774
|
+
for (let j = 0; j < k; j++) v ^= gfMul(inv[r][j], use[j].octets[c]);
|
|
1775
|
+
out[r * width + c] = v;
|
|
1776
|
+
}
|
|
1777
|
+
return out;
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
// src/navbits/has.ts
|
|
1781
|
+
var HAS_DUMMY_HEADER = 11484099;
|
|
1782
|
+
var HAS_VALIDITY_SECONDS = [
|
|
1783
|
+
5,
|
|
1784
|
+
10,
|
|
1785
|
+
15,
|
|
1786
|
+
20,
|
|
1787
|
+
30,
|
|
1788
|
+
60,
|
|
1789
|
+
90,
|
|
1790
|
+
120,
|
|
1791
|
+
180,
|
|
1792
|
+
240,
|
|
1793
|
+
300,
|
|
1794
|
+
600,
|
|
1795
|
+
900,
|
|
1796
|
+
1800,
|
|
1797
|
+
3600,
|
|
1798
|
+
null
|
|
1799
|
+
];
|
|
1800
|
+
var HAS_GPS_SIGNALS = [
|
|
1801
|
+
"L1 C/A",
|
|
1802
|
+
"Reserved",
|
|
1803
|
+
"Reserved",
|
|
1804
|
+
"L1C(D)",
|
|
1805
|
+
"L1C(P)",
|
|
1806
|
+
"L1C(D+P)",
|
|
1807
|
+
"L2 CM",
|
|
1808
|
+
"L2 CL",
|
|
1809
|
+
"L2 CM+CL",
|
|
1810
|
+
"L2 P",
|
|
1811
|
+
"Reserved",
|
|
1812
|
+
"L5 I",
|
|
1813
|
+
"L5 Q",
|
|
1814
|
+
"L5 I+Q",
|
|
1815
|
+
"Reserved",
|
|
1816
|
+
"Reserved"
|
|
1817
|
+
];
|
|
1818
|
+
var HAS_GALILEO_SIGNALS = [
|
|
1819
|
+
"E1-B",
|
|
1820
|
+
"E1-C",
|
|
1821
|
+
"E1-B+E1-C",
|
|
1822
|
+
"E5a-I",
|
|
1823
|
+
"E5a-Q",
|
|
1824
|
+
"E5a-I+E5a-Q",
|
|
1825
|
+
"E5b-I",
|
|
1826
|
+
"E5b-Q",
|
|
1827
|
+
"E5b-I+E5b-Q",
|
|
1828
|
+
"E5-I",
|
|
1829
|
+
"E5-Q",
|
|
1830
|
+
"E5-I+E5-Q",
|
|
1831
|
+
"E6-B",
|
|
1832
|
+
"E6-C",
|
|
1833
|
+
"E6-B+E6-C",
|
|
1834
|
+
"Reserved"
|
|
1835
|
+
];
|
|
1836
|
+
var SYSTEM_OF_GNSS_ID = { 0: "G", 2: "E" };
|
|
1837
|
+
var IOD_BITS = { G: 8, E: 10 };
|
|
1838
|
+
function hasPageCrcOk(page) {
|
|
1839
|
+
if (page.length < 61) return false;
|
|
1840
|
+
return crc24q(page, 462) === getBitU(page, 462, 24);
|
|
1841
|
+
}
|
|
1842
|
+
function parseHasPage(page) {
|
|
1843
|
+
if (getBitU(page, 14, 24) === HAS_DUMMY_HEADER) return null;
|
|
1844
|
+
const body = new Uint8Array(53);
|
|
1845
|
+
for (let i = 0; i < 53; i++) body[i] = getBitU(page, 38 + 8 * i, 8);
|
|
1846
|
+
return {
|
|
1847
|
+
status: getBitU(page, 14, 2),
|
|
1848
|
+
messageType: getBitU(page, 18, 2),
|
|
1849
|
+
messageId: getBitU(page, 20, 5),
|
|
1850
|
+
messageSize: getBitU(page, 25, 5) + 1,
|
|
1851
|
+
pageId: getBitU(page, 30, 8),
|
|
1852
|
+
body
|
|
1853
|
+
};
|
|
1854
|
+
}
|
|
1855
|
+
var Cursor = class {
|
|
1856
|
+
constructor(buf, bits) {
|
|
1857
|
+
this.buf = buf;
|
|
1858
|
+
this.bits = bits;
|
|
1859
|
+
}
|
|
1860
|
+
pos = 0;
|
|
1861
|
+
u(len) {
|
|
1862
|
+
if (this.pos + len > this.bits) throw new RangeError("truncated");
|
|
1863
|
+
const v = getBitU(this.buf, this.pos, len);
|
|
1864
|
+
this.pos += len;
|
|
1865
|
+
return v;
|
|
1866
|
+
}
|
|
1867
|
+
s(len) {
|
|
1868
|
+
if (this.pos + len > this.bits) throw new RangeError("truncated");
|
|
1869
|
+
const v = getBitS(this.buf, this.pos, len);
|
|
1870
|
+
this.pos += len;
|
|
1871
|
+
return v;
|
|
1872
|
+
}
|
|
1873
|
+
};
|
|
1874
|
+
var prnOf = (system, idx) => `${system}${String(idx + 1).padStart(2, "0")}`;
|
|
1875
|
+
function parseMaskBlock(c, maskId) {
|
|
1876
|
+
const nSys = c.u(4);
|
|
1877
|
+
const systems = [];
|
|
1878
|
+
for (let s = 0; s < nSys; s++) {
|
|
1879
|
+
const gnssId = c.u(4);
|
|
1880
|
+
const system = SYSTEM_OF_GNSS_ID[gnssId];
|
|
1881
|
+
if (system === void 0) throw new RangeError(`unknown GNSS ID ${gnssId}`);
|
|
1882
|
+
const prns = [];
|
|
1883
|
+
for (let b = 0; b < 40; b++) if (c.u(1)) prns.push(prnOf(system, b));
|
|
1884
|
+
const signalIndices = [];
|
|
1885
|
+
for (let b = 0; b < 16; b++) if (c.u(1)) signalIndices.push(b);
|
|
1886
|
+
const signalNames = system === "G" ? HAS_GPS_SIGNALS : HAS_GALILEO_SIGNALS;
|
|
1887
|
+
let cellMask = null;
|
|
1888
|
+
if (c.u(1)) {
|
|
1889
|
+
cellMask = prns.map(() => signalIndices.map(() => c.u(1) === 1));
|
|
1890
|
+
}
|
|
1891
|
+
systems.push({
|
|
1892
|
+
gnssId,
|
|
1893
|
+
system,
|
|
1894
|
+
prns,
|
|
1895
|
+
signalIndices,
|
|
1896
|
+
signals: signalIndices.map((i) => signalNames[i]),
|
|
1897
|
+
cellMask,
|
|
1898
|
+
navMessage: c.u(3)
|
|
1899
|
+
});
|
|
1900
|
+
}
|
|
1901
|
+
c.u(6);
|
|
1902
|
+
return { maskId, systems };
|
|
1903
|
+
}
|
|
1904
|
+
function parseOrbitBlock(c, masks) {
|
|
1905
|
+
const validityIndex = c.u(4);
|
|
1906
|
+
const corrections = [];
|
|
1907
|
+
for (const sys of masks.systems) {
|
|
1908
|
+
for (const prn of sys.prns) {
|
|
1909
|
+
const gnssIod = c.u(IOD_BITS[sys.system]);
|
|
1910
|
+
const rad = c.s(13);
|
|
1911
|
+
const inT = c.s(12);
|
|
1912
|
+
const cross = c.s(12);
|
|
1913
|
+
corrections.push({
|
|
1914
|
+
system: sys.system,
|
|
1915
|
+
prn,
|
|
1916
|
+
gnssIod,
|
|
1917
|
+
deltaRadial: rad === -4096 ? null : rad * 25e-4,
|
|
1918
|
+
deltaInTrack: inT === -2048 ? null : inT * 8e-3,
|
|
1919
|
+
deltaCrossTrack: cross === -2048 ? null : cross * 8e-3
|
|
1920
|
+
});
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
return {
|
|
1924
|
+
validityIndex,
|
|
1925
|
+
validitySeconds: HAS_VALIDITY_SECONDS[validityIndex],
|
|
1926
|
+
corrections
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1929
|
+
function clockValue(c, system, prn, multiplier) {
|
|
1930
|
+
const raw = c.s(13);
|
|
1931
|
+
return {
|
|
1932
|
+
system,
|
|
1933
|
+
prn,
|
|
1934
|
+
deltaClock: raw === -4096 || raw === 4095 ? null : raw * 25e-4 * multiplier,
|
|
1935
|
+
notUsable: raw === 4095
|
|
1936
|
+
};
|
|
1937
|
+
}
|
|
1938
|
+
function parseClockFullBlock(c, masks) {
|
|
1939
|
+
const validityIndex = c.u(4);
|
|
1940
|
+
const multipliers = masks.systems.map((sys) => ({
|
|
1941
|
+
system: sys.system,
|
|
1942
|
+
multiplier: c.u(2) + 1
|
|
1943
|
+
}));
|
|
1944
|
+
const corrections = [];
|
|
1945
|
+
for (let s = 0; s < masks.systems.length; s++) {
|
|
1946
|
+
const sys = masks.systems[s];
|
|
1947
|
+
for (const prn of sys.prns)
|
|
1948
|
+
corrections.push(
|
|
1949
|
+
clockValue(c, sys.system, prn, multipliers[s].multiplier)
|
|
1950
|
+
);
|
|
1951
|
+
}
|
|
1952
|
+
return {
|
|
1953
|
+
validityIndex,
|
|
1954
|
+
validitySeconds: HAS_VALIDITY_SECONDS[validityIndex],
|
|
1955
|
+
multipliers,
|
|
1956
|
+
corrections
|
|
1957
|
+
};
|
|
1958
|
+
}
|
|
1959
|
+
function parseClockSubsetBlock(c, masks) {
|
|
1960
|
+
const validityIndex = c.u(4);
|
|
1961
|
+
const nSys = c.u(4);
|
|
1962
|
+
const multipliers = [];
|
|
1963
|
+
const corrections = [];
|
|
1964
|
+
for (let s = 0; s < nSys; s++) {
|
|
1965
|
+
const gnssId = c.u(4);
|
|
1966
|
+
const sys = masks.systems.find((m) => m.gnssId === gnssId);
|
|
1967
|
+
if (!sys) throw new RangeError(`subset GNSS ID ${gnssId} not in mask`);
|
|
1968
|
+
const multiplier = c.u(2) + 1;
|
|
1969
|
+
multipliers.push({ system: sys.system, multiplier });
|
|
1970
|
+
const selected = [];
|
|
1971
|
+
for (const prn of sys.prns) if (c.u(1)) selected.push(prn);
|
|
1972
|
+
for (const prn of selected)
|
|
1973
|
+
corrections.push(clockValue(c, sys.system, prn, multiplier));
|
|
1974
|
+
}
|
|
1975
|
+
return {
|
|
1976
|
+
validityIndex,
|
|
1977
|
+
validitySeconds: HAS_VALIDITY_SECONDS[validityIndex],
|
|
1978
|
+
multipliers,
|
|
1979
|
+
corrections
|
|
1980
|
+
};
|
|
1981
|
+
}
|
|
1982
|
+
function parseBiasBlock(c, masks, kind) {
|
|
1983
|
+
const validityIndex = c.u(4);
|
|
1984
|
+
const biases = [];
|
|
1985
|
+
for (const sys of masks.systems) {
|
|
1986
|
+
for (let s = 0; s < sys.prns.length; s++) {
|
|
1987
|
+
for (let g = 0; g < sys.signalIndices.length; g++) {
|
|
1988
|
+
if (sys.cellMask && !sys.cellMask[s][g]) continue;
|
|
1989
|
+
const raw = c.s(11);
|
|
1990
|
+
const entry = {
|
|
1991
|
+
system: sys.system,
|
|
1992
|
+
prn: sys.prns[s],
|
|
1993
|
+
signalIndex: sys.signalIndices[g],
|
|
1994
|
+
signal: sys.signals[g],
|
|
1995
|
+
bias: raw === -1024 ? null : raw * (kind === "code" ? 0.02 : 0.01)
|
|
1996
|
+
};
|
|
1997
|
+
if (kind === "phase") entry.discontinuity = c.u(2);
|
|
1998
|
+
biases.push(entry);
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
return {
|
|
2003
|
+
validityIndex,
|
|
2004
|
+
validitySeconds: HAS_VALIDITY_SECONDS[validityIndex],
|
|
2005
|
+
biases
|
|
2006
|
+
};
|
|
2007
|
+
}
|
|
2008
|
+
function parseHasMt1(payload, header, cachedMasks) {
|
|
2009
|
+
const c = new Cursor(payload, payload.length * 8);
|
|
2010
|
+
const toh = c.u(12);
|
|
2011
|
+
const flags = {
|
|
2012
|
+
mask: c.u(1) === 1,
|
|
2013
|
+
orbit: c.u(1) === 1,
|
|
2014
|
+
clockFullSet: c.u(1) === 1,
|
|
2015
|
+
clockSubset: c.u(1) === 1,
|
|
2016
|
+
codeBias: c.u(1) === 1,
|
|
2017
|
+
phaseBias: c.u(1) === 1
|
|
2018
|
+
};
|
|
2019
|
+
c.u(4);
|
|
2020
|
+
const maskId = c.u(5);
|
|
2021
|
+
const iodSetId = c.u(5);
|
|
2022
|
+
const msg = {
|
|
2023
|
+
...header,
|
|
2024
|
+
toh,
|
|
2025
|
+
maskId,
|
|
2026
|
+
iodSetId,
|
|
2027
|
+
flags,
|
|
2028
|
+
maskFromCache: false,
|
|
2029
|
+
parseError: null
|
|
2030
|
+
};
|
|
2031
|
+
try {
|
|
2032
|
+
let masks;
|
|
2033
|
+
if (flags.mask) {
|
|
2034
|
+
masks = parseMaskBlock(c, maskId);
|
|
2035
|
+
} else if (cachedMasks) {
|
|
2036
|
+
masks = cachedMasks;
|
|
2037
|
+
msg.maskFromCache = true;
|
|
2038
|
+
} else {
|
|
2039
|
+
msg.parseError = "mask-unavailable";
|
|
2040
|
+
return msg;
|
|
2041
|
+
}
|
|
2042
|
+
msg.masks = masks;
|
|
2043
|
+
if (flags.orbit) msg.orbit = parseOrbitBlock(c, masks);
|
|
2044
|
+
if (flags.clockFullSet) msg.clockFullSet = parseClockFullBlock(c, masks);
|
|
2045
|
+
if (flags.clockSubset) msg.clockSubset = parseClockSubsetBlock(c, masks);
|
|
2046
|
+
if (flags.codeBias) msg.codeBias = parseBiasBlock(c, masks, "code");
|
|
2047
|
+
if (flags.phaseBias) msg.phaseBias = parseBiasBlock(c, masks, "phase");
|
|
2048
|
+
} catch (e) {
|
|
2049
|
+
msg.parseError = e instanceof Error ? e.message : String(e);
|
|
2050
|
+
}
|
|
2051
|
+
return msg;
|
|
2052
|
+
}
|
|
2053
|
+
var HasAssembler = class {
|
|
2054
|
+
slots = /* @__PURE__ */ new Map();
|
|
2055
|
+
lastMessageId = -1;
|
|
2056
|
+
maskCache = /* @__PURE__ */ new Map();
|
|
2057
|
+
/** Pages a message may span before its slot is restarted (s). */
|
|
2058
|
+
timeoutSec;
|
|
2059
|
+
stats = {
|
|
2060
|
+
pages: 0,
|
|
2061
|
+
dummyPages: 0,
|
|
2062
|
+
skippedPages: 0,
|
|
2063
|
+
duplicatePages: 0,
|
|
2064
|
+
resets: 0,
|
|
2065
|
+
messages: 0,
|
|
2066
|
+
parseErrors: 0
|
|
2067
|
+
};
|
|
2068
|
+
constructor(opts = {}) {
|
|
2069
|
+
this.timeoutSec = opts.timeoutSec ?? 30;
|
|
2070
|
+
}
|
|
2071
|
+
/**
|
|
2072
|
+
* Push one 492-bit C/NAV page (≥ 61 bytes; check the CRC first with
|
|
2073
|
+
* `hasPageCrcOk`). `tow` — a receiver time of week in seconds, any
|
|
2074
|
+
* origin as long as it is common to all pages — enables the slot
|
|
2075
|
+
* timeout and is stamped on completed messages.
|
|
2076
|
+
*/
|
|
2077
|
+
push(page, tow) {
|
|
2078
|
+
const p = parseHasPage(page);
|
|
2079
|
+
if (!p) {
|
|
2080
|
+
this.stats.dummyPages++;
|
|
2081
|
+
return null;
|
|
2082
|
+
}
|
|
2083
|
+
this.stats.pages++;
|
|
2084
|
+
if (p.messageType !== 1 || p.status > 1 || p.pageId === 0) {
|
|
2085
|
+
this.stats.skippedPages++;
|
|
2086
|
+
return null;
|
|
2087
|
+
}
|
|
2088
|
+
if (p.messageId === this.lastMessageId) return null;
|
|
2089
|
+
let slot = this.slots.get(p.messageId);
|
|
2090
|
+
const timedOut = slot?.firstTow !== void 0 && tow !== void 0 && tow - slot.firstTow > this.timeoutSec;
|
|
2091
|
+
if (slot && (slot.messageSize !== p.messageSize || timedOut)) {
|
|
2092
|
+
this.stats.resets++;
|
|
2093
|
+
slot = void 0;
|
|
2094
|
+
}
|
|
2095
|
+
if (!slot) {
|
|
2096
|
+
slot = {
|
|
2097
|
+
messageSize: p.messageSize,
|
|
2098
|
+
status: p.status,
|
|
2099
|
+
pages: [],
|
|
2100
|
+
bodies: /* @__PURE__ */ new Map(),
|
|
2101
|
+
firstTow: tow
|
|
2102
|
+
};
|
|
2103
|
+
this.slots.set(p.messageId, slot);
|
|
2104
|
+
}
|
|
2105
|
+
const bodyKey = Array.from(
|
|
2106
|
+
p.body,
|
|
2107
|
+
(b) => b.toString(16).padStart(2, "0")
|
|
2108
|
+
).join("");
|
|
2109
|
+
const existing = slot.bodies.get(p.pageId);
|
|
2110
|
+
if (existing !== void 0) {
|
|
2111
|
+
if (existing === bodyKey) {
|
|
2112
|
+
this.stats.duplicatePages++;
|
|
2113
|
+
return null;
|
|
2114
|
+
}
|
|
2115
|
+
this.stats.resets++;
|
|
2116
|
+
slot.pages = [];
|
|
2117
|
+
slot.bodies.clear();
|
|
2118
|
+
slot.firstTow = tow;
|
|
2119
|
+
}
|
|
2120
|
+
slot.bodies.set(p.pageId, bodyKey);
|
|
2121
|
+
slot.pages.push({ pageId: p.pageId, octets: p.body });
|
|
2122
|
+
if (slot.pages.length < slot.messageSize) return null;
|
|
2123
|
+
const payload = rs255DecodeErasures(slot.pages, slot.messageSize);
|
|
2124
|
+
if (!payload) return null;
|
|
2125
|
+
this.slots.delete(p.messageId);
|
|
2126
|
+
this.lastMessageId = p.messageId;
|
|
2127
|
+
const msg = parseHasMt1(
|
|
2128
|
+
payload,
|
|
2129
|
+
{
|
|
2130
|
+
status: slot.status,
|
|
2131
|
+
messageId: p.messageId,
|
|
2132
|
+
messageSize: slot.messageSize
|
|
2133
|
+
},
|
|
2134
|
+
void 0
|
|
2135
|
+
);
|
|
2136
|
+
const resolved = msg.parseError === "mask-unavailable" && this.maskCache.has(msg.maskId) ? parseHasMt1(
|
|
2137
|
+
payload,
|
|
2138
|
+
{
|
|
2139
|
+
status: slot.status,
|
|
2140
|
+
messageId: p.messageId,
|
|
2141
|
+
messageSize: slot.messageSize
|
|
2142
|
+
},
|
|
2143
|
+
this.maskCache.get(msg.maskId)
|
|
2144
|
+
) : msg;
|
|
2145
|
+
if (resolved.flags.mask && resolved.masks)
|
|
2146
|
+
this.maskCache.set(resolved.maskId, resolved.masks);
|
|
2147
|
+
if (tow !== void 0) resolved.tow = tow;
|
|
2148
|
+
this.stats.messages++;
|
|
2149
|
+
if (resolved.parseError !== null) this.stats.parseErrors++;
|
|
2150
|
+
return resolved;
|
|
2151
|
+
}
|
|
2152
|
+
};
|
|
2153
|
+
|
|
2154
|
+
// src/sbf/rawnav-has.ts
|
|
2155
|
+
function parseSbfHas(data) {
|
|
2156
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
2157
|
+
const assembler = new HasAssembler();
|
|
2158
|
+
const messages = [];
|
|
2159
|
+
let pagesSeen = 0;
|
|
2160
|
+
let pagesBadCrc = 0;
|
|
2161
|
+
scanSbfFrames(data, view, (id, b, len) => {
|
|
2162
|
+
if (id !== 4024 || len < 84) return;
|
|
2163
|
+
pagesSeen++;
|
|
2164
|
+
const page = new Uint8Array(64);
|
|
2165
|
+
for (let k = 0; k < 16; k++) {
|
|
2166
|
+
const w = view.getUint32(b + 20 + 4 * k, true);
|
|
2167
|
+
page[4 * k] = w >>> 24;
|
|
2168
|
+
page[4 * k + 1] = w >>> 16 & 255;
|
|
2169
|
+
page[4 * k + 2] = w >>> 8 & 255;
|
|
2170
|
+
page[4 * k + 3] = w & 255;
|
|
2171
|
+
}
|
|
2172
|
+
if (!hasPageCrcOk(page)) {
|
|
2173
|
+
pagesBadCrc++;
|
|
2174
|
+
return;
|
|
2175
|
+
}
|
|
2176
|
+
const tow = view.getUint32(b + 8, true) / 1e3;
|
|
2177
|
+
const msg = assembler.push(page, tow);
|
|
2178
|
+
if (msg) messages.push({ ...msg, tow, wnc: view.getUint16(b + 12, true) });
|
|
2179
|
+
});
|
|
2180
|
+
return {
|
|
2181
|
+
messages,
|
|
2182
|
+
pagesSeen,
|
|
2183
|
+
pagesBadCrc,
|
|
2184
|
+
pagesDummy: assembler.stats.dummyPages,
|
|
2185
|
+
pagesHas: assembler.stats.pages
|
|
2186
|
+
};
|
|
2187
|
+
}
|
|
2188
|
+
|
|
1665
2189
|
// src/sbf/index.ts
|
|
1666
2190
|
var CLIGHT = 299792458;
|
|
1667
2191
|
var GPS_EPOCH_MS7 = Date.UTC(1980, 0, 6);
|
|
@@ -2336,6 +2860,7 @@ function parseSbfMeas(data) {
|
|
|
2336
2860
|
parseSbfCnav,
|
|
2337
2861
|
parseSbfGalNav,
|
|
2338
2862
|
parseSbfGloNav,
|
|
2863
|
+
parseSbfHas,
|
|
2339
2864
|
parseSbfIonoUtc,
|
|
2340
2865
|
parseSbfMeas,
|
|
2341
2866
|
parseSbfNav,
|