gnss-js 2.4.0 → 2.6.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-WW3DKCDN.js → chunk-74IVYOQV.js} +187 -6
- package/dist/{chunk-XPQ4BU6W.js → chunk-7GNRNKBR.js} +66 -0
- package/dist/{chunk-B2XWO4RP.js → chunk-BWLLHLLS.js} +158 -0
- package/dist/index.cjs +455 -48
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +11 -3
- package/dist/positioning.cjs +180 -0
- package/dist/positioning.d.cts +56 -1
- package/dist/positioning.d.ts +56 -1
- package/dist/positioning.js +3 -1
- package/dist/rtcm3.cjs +66 -0
- package/dist/rtcm3.js +1 -1
- package/dist/sbf.cjs +206 -23
- package/dist/sbf.d.cts +62 -1
- package/dist/sbf.d.ts +62 -1
- package/dist/sbf.js +7 -1
- package/package.json +1 -1
package/dist/sbf.cjs
CHANGED
|
@@ -23,8 +23,10 @@ __export(sbf_exports, {
|
|
|
23
23
|
SBAS_L5_MT_NAMES: () => SBAS_L5_MT_NAMES,
|
|
24
24
|
SBAS_L5_PREAMBLE_UW: () => SBAS_L5_PREAMBLE_UW,
|
|
25
25
|
decodeSbfNavigation: () => decodeSbfNavigation,
|
|
26
|
+
extractSbfNavicSubframe: () => extractSbfNavicSubframe,
|
|
26
27
|
feedGeoBlock: () => feedGeoBlock,
|
|
27
28
|
feedGeoL5Block: () => feedGeoL5Block,
|
|
29
|
+
feedNavicBlock: () => feedNavicBlock,
|
|
28
30
|
isSbasL1Preamble: () => isSbasL1Preamble,
|
|
29
31
|
isSbasL5Correction: () => isSbasL5Correction,
|
|
30
32
|
parseSbfAlmanac: () => parseSbfAlmanac,
|
|
@@ -39,6 +41,7 @@ __export(sbf_exports, {
|
|
|
39
41
|
parseSbfIonoUtc: () => parseSbfIonoUtc,
|
|
40
42
|
parseSbfMeas: () => parseSbfMeas,
|
|
41
43
|
parseSbfNav: () => parseSbfNav,
|
|
44
|
+
parseSbfNavic: () => parseSbfNavic,
|
|
42
45
|
parseSbfPvt: () => parseSbfPvt,
|
|
43
46
|
parseSbfReceiverSetup: () => parseSbfReceiverSetup,
|
|
44
47
|
sbasL5MessageName: () => sbasL5MessageName,
|
|
@@ -1068,6 +1071,173 @@ var CnavAssembler = class {
|
|
|
1068
1071
|
}
|
|
1069
1072
|
};
|
|
1070
1073
|
|
|
1074
|
+
// src/navbits/navic.ts
|
|
1075
|
+
var GPS_EPOCH_MS5 = Date.UTC(1980, 0, 6);
|
|
1076
|
+
var SEC_PER_WEEK4 = 604800;
|
|
1077
|
+
var DATA = 30;
|
|
1078
|
+
function navicSubframeCrcOk(sf) {
|
|
1079
|
+
return crc24q(sf, 262) === getBitU(sf, 262, 24);
|
|
1080
|
+
}
|
|
1081
|
+
function navicSubframeId(sf) {
|
|
1082
|
+
return getBitU(sf, 27, 2) + 1;
|
|
1083
|
+
}
|
|
1084
|
+
function decodeNavicSubframes(sf1, sf2, opts = {}) {
|
|
1085
|
+
let i = DATA;
|
|
1086
|
+
getBitU(sf1, i, 10);
|
|
1087
|
+
i += 10;
|
|
1088
|
+
const af0 = getBitS(sf1, i, 22) * 2 ** -31;
|
|
1089
|
+
i += 22;
|
|
1090
|
+
const af1 = getBitS(sf1, i, 16) * 2 ** -43;
|
|
1091
|
+
i += 16;
|
|
1092
|
+
const af2 = getBitS(sf1, i, 8) * 2 ** -55;
|
|
1093
|
+
i += 8;
|
|
1094
|
+
i += 4;
|
|
1095
|
+
const tocSec = getBitU(sf1, i, 16) * 16;
|
|
1096
|
+
i += 16;
|
|
1097
|
+
const tgd = getBitS(sf1, i, 8) * 2 ** -31;
|
|
1098
|
+
i += 8;
|
|
1099
|
+
const deltaN = getBitS(sf1, i, 22) * 2 ** -41 * GPS_PI;
|
|
1100
|
+
i += 22;
|
|
1101
|
+
const iode = getBitU(sf1, i, 8);
|
|
1102
|
+
i += 8;
|
|
1103
|
+
i += 10;
|
|
1104
|
+
const l5Health = getBitU(sf1, i, 1);
|
|
1105
|
+
i += 1;
|
|
1106
|
+
const sHealth = getBitU(sf1, i, 1);
|
|
1107
|
+
i += 1;
|
|
1108
|
+
const cuc = getBitS(sf1, i, 15) * 2 ** -28;
|
|
1109
|
+
i += 15;
|
|
1110
|
+
const cus = getBitS(sf1, i, 15) * 2 ** -28;
|
|
1111
|
+
i += 15;
|
|
1112
|
+
const cic = getBitS(sf1, i, 15) * 2 ** -28;
|
|
1113
|
+
i += 15;
|
|
1114
|
+
const cis = getBitS(sf1, i, 15) * 2 ** -28;
|
|
1115
|
+
i += 15;
|
|
1116
|
+
const crc = getBitS(sf1, i, 15) * 2 ** -4;
|
|
1117
|
+
i += 15;
|
|
1118
|
+
const crs = getBitS(sf1, i, 15) * 2 ** -4;
|
|
1119
|
+
i += 15;
|
|
1120
|
+
const idot = getBitS(sf1, i, 14) * 2 ** -43 * GPS_PI;
|
|
1121
|
+
let j = DATA;
|
|
1122
|
+
const m0 = getBitS(sf2, j, 32) * 2 ** -31 * GPS_PI;
|
|
1123
|
+
j += 32;
|
|
1124
|
+
const toeSec = getBitU(sf2, j, 16) * 16;
|
|
1125
|
+
j += 16;
|
|
1126
|
+
const e = getBitU(sf2, j, 32) * 2 ** -33;
|
|
1127
|
+
j += 32;
|
|
1128
|
+
const sqrtA = getBitU(sf2, j, 32) * 2 ** -19;
|
|
1129
|
+
j += 32;
|
|
1130
|
+
const omega0 = getBitS(sf2, j, 32) * 2 ** -31 * GPS_PI;
|
|
1131
|
+
j += 32;
|
|
1132
|
+
const omega = getBitS(sf2, j, 32) * 2 ** -31 * GPS_PI;
|
|
1133
|
+
j += 32;
|
|
1134
|
+
const omegaDot = getBitS(sf2, j, 22) * 2 ** -41 * GPS_PI;
|
|
1135
|
+
j += 22;
|
|
1136
|
+
const i0 = getBitS(sf2, j, 32) * 2 ** -31 * GPS_PI;
|
|
1137
|
+
if (sqrtA <= 0 || e >= 1) return null;
|
|
1138
|
+
const week = opts.refWeek ?? Math.floor((Date.now() - GPS_EPOCH_MS5) / 1e3 / SEC_PER_WEEK4);
|
|
1139
|
+
const prn = opts.prn ?? "I00";
|
|
1140
|
+
const tocDate = new Date(
|
|
1141
|
+
GPS_EPOCH_MS5 + (week * SEC_PER_WEEK4 + tocSec) * 1e3
|
|
1142
|
+
);
|
|
1143
|
+
return {
|
|
1144
|
+
system: "I",
|
|
1145
|
+
prn,
|
|
1146
|
+
tocDate,
|
|
1147
|
+
toc: tocDate.getTime() / 1e3 % SEC_PER_WEEK4,
|
|
1148
|
+
af0,
|
|
1149
|
+
af1,
|
|
1150
|
+
af2,
|
|
1151
|
+
iode,
|
|
1152
|
+
crs,
|
|
1153
|
+
deltaN,
|
|
1154
|
+
m0,
|
|
1155
|
+
cuc,
|
|
1156
|
+
e,
|
|
1157
|
+
cus,
|
|
1158
|
+
sqrtA,
|
|
1159
|
+
toe: toeSec,
|
|
1160
|
+
cic,
|
|
1161
|
+
omega0,
|
|
1162
|
+
cis,
|
|
1163
|
+
i0,
|
|
1164
|
+
crc,
|
|
1165
|
+
omega,
|
|
1166
|
+
omegaDot,
|
|
1167
|
+
idot,
|
|
1168
|
+
week,
|
|
1169
|
+
svHealth: l5Health << 1 | sHealth,
|
|
1170
|
+
tgd
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1173
|
+
var NavicAssembler = class {
|
|
1174
|
+
sf1 = /* @__PURE__ */ new Map();
|
|
1175
|
+
last = /* @__PURE__ */ new Map();
|
|
1176
|
+
/**
|
|
1177
|
+
* Push one CRC-valid subframe. Subframe 1 opens a master frame (subframe 2
|
|
1178
|
+
* immediately follows it in the NavIC frame order), so an ephemeris is only
|
|
1179
|
+
* emitted when a subframe 2 pairs with the subframe 1 that opened the *same*
|
|
1180
|
+
* frame — never a stale subframe 1 left over across CRC drops.
|
|
1181
|
+
*/
|
|
1182
|
+
push(prn, subframe, refWeek) {
|
|
1183
|
+
if (getBitU(subframe, 25, 1)) return null;
|
|
1184
|
+
const id = navicSubframeId(subframe);
|
|
1185
|
+
if (id === 1) {
|
|
1186
|
+
this.sf1.set(prn, subframe);
|
|
1187
|
+
return null;
|
|
1188
|
+
}
|
|
1189
|
+
if (id !== 2) return null;
|
|
1190
|
+
const a = this.sf1.get(prn);
|
|
1191
|
+
if (!a) return null;
|
|
1192
|
+
this.sf1.delete(prn);
|
|
1193
|
+
const eph = decodeNavicSubframes(a, subframe, { prn, refWeek });
|
|
1194
|
+
if (!eph) return null;
|
|
1195
|
+
const key = `${eph.toc}|${eph.iode}`;
|
|
1196
|
+
if (this.last.get(prn) === key) return null;
|
|
1197
|
+
this.last.set(prn, key);
|
|
1198
|
+
return eph;
|
|
1199
|
+
}
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1202
|
+
// src/sbf/rawnav-navic.ts
|
|
1203
|
+
var WNC_DNU2 = 65535;
|
|
1204
|
+
function extractSbfNavicSubframe(view, b) {
|
|
1205
|
+
const sf = new Uint8Array(40);
|
|
1206
|
+
for (let k = 0; k < 10; k++) {
|
|
1207
|
+
const w = view.getUint32(b + 20 + 4 * k, true);
|
|
1208
|
+
sf[4 * k] = w >>> 24;
|
|
1209
|
+
sf[4 * k + 1] = w >>> 16 & 255;
|
|
1210
|
+
sf[4 * k + 2] = w >>> 8 & 255;
|
|
1211
|
+
sf[4 * k + 3] = w & 255;
|
|
1212
|
+
}
|
|
1213
|
+
return sf;
|
|
1214
|
+
}
|
|
1215
|
+
function feedNavicBlock(view, b, assembler) {
|
|
1216
|
+
const prn = svidToPrn(view.getUint8(b + 14));
|
|
1217
|
+
if (!prn || prn[0] !== "I") return {};
|
|
1218
|
+
const wnc = view.getUint16(b + 12, true);
|
|
1219
|
+
if (wnc === WNC_DNU2) return {};
|
|
1220
|
+
const sf = extractSbfNavicSubframe(view, b);
|
|
1221
|
+
if (!navicSubframeCrcOk(sf)) return { badCrc: true };
|
|
1222
|
+
const eph = assembler.push(prn, sf, wnc);
|
|
1223
|
+
return eph ? { eph } : {};
|
|
1224
|
+
}
|
|
1225
|
+
function parseSbfNavic(data) {
|
|
1226
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
1227
|
+
const ephemerides = [];
|
|
1228
|
+
const assembler = new NavicAssembler();
|
|
1229
|
+
let badCrc = 0;
|
|
1230
|
+
let messages = 0;
|
|
1231
|
+
scanSbfFrames(data, view, (id, b, len) => {
|
|
1232
|
+
if (id !== 4093 || len < 60) return;
|
|
1233
|
+
messages++;
|
|
1234
|
+
const r = feedNavicBlock(view, b, assembler);
|
|
1235
|
+
if (r.eph) ephemerides.push(r.eph);
|
|
1236
|
+
else if (r.badCrc) badCrc++;
|
|
1237
|
+
});
|
|
1238
|
+
return { ephemerides, badCrc, messages };
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1071
1241
|
// src/sbf/rawnav.ts
|
|
1072
1242
|
var CNAV_SIGNAL_OF_BLOCK = {
|
|
1073
1243
|
4018: "L2C",
|
|
@@ -1108,8 +1278,8 @@ function parseSbfCnav(data) {
|
|
|
1108
1278
|
}
|
|
1109
1279
|
|
|
1110
1280
|
// src/navbits/gal.ts
|
|
1111
|
-
var
|
|
1112
|
-
var
|
|
1281
|
+
var GPS_EPOCH_MS6 = Date.UTC(1980, 0, 6);
|
|
1282
|
+
var SEC_PER_WEEK5 = 7 * 86400;
|
|
1113
1283
|
var HALF_WEEK2 = 302400;
|
|
1114
1284
|
var GST_GPS_WEEK_OFFSET = 1024;
|
|
1115
1285
|
function galInavPageCrcOk(page) {
|
|
@@ -1121,7 +1291,7 @@ function galFnavPageCrcOk(page) {
|
|
|
1121
1291
|
return crc24q(page, 214) === getBitU(page, 214, 24);
|
|
1122
1292
|
}
|
|
1123
1293
|
function gpsDate2(week, sec) {
|
|
1124
|
-
return new Date(
|
|
1294
|
+
return new Date(GPS_EPOCH_MS6 + (week * SEC_PER_WEEK5 + sec) * 1e3);
|
|
1125
1295
|
}
|
|
1126
1296
|
function weekOfToe(week, tow, toe) {
|
|
1127
1297
|
if (toe - tow > HALF_WEEK2) return week - 1;
|
|
@@ -1217,7 +1387,7 @@ function decodeGalInavWords(words) {
|
|
|
1217
1387
|
return {
|
|
1218
1388
|
system: "E",
|
|
1219
1389
|
prn: `E${two2(svid)}`,
|
|
1220
|
-
toc: tocDate.getTime() / 1e3 %
|
|
1390
|
+
toc: tocDate.getTime() / 1e3 % SEC_PER_WEEK5,
|
|
1221
1391
|
tocDate,
|
|
1222
1392
|
af0,
|
|
1223
1393
|
af1,
|
|
@@ -1325,7 +1495,7 @@ function decodeGalFnavPages(pages) {
|
|
|
1325
1495
|
return {
|
|
1326
1496
|
system: "E",
|
|
1327
1497
|
prn: `E${two2(svid)}`,
|
|
1328
|
-
toc: tocDate.getTime() / 1e3 %
|
|
1498
|
+
toc: tocDate.getTime() / 1e3 % SEC_PER_WEEK5,
|
|
1329
1499
|
tocDate,
|
|
1330
1500
|
af0,
|
|
1331
1501
|
af1,
|
|
@@ -1475,10 +1645,10 @@ function isFnavDummy(page) {
|
|
|
1475
1645
|
|
|
1476
1646
|
// src/navbits/bds.ts
|
|
1477
1647
|
var BDT_EPOCH_MS2 = Date.UTC(2006, 0, 1);
|
|
1478
|
-
var
|
|
1479
|
-
var MS_PER_WEEK2 =
|
|
1648
|
+
var SEC_PER_WEEK6 = 7 * 86400;
|
|
1649
|
+
var MS_PER_WEEK2 = SEC_PER_WEEK6 * 1e3;
|
|
1480
1650
|
var HALF_WEEK3 = 302400;
|
|
1481
|
-
var sowOf2 = (dateMs) => dateMs / 1e3 %
|
|
1651
|
+
var sowOf2 = (dateMs) => dateMs / 1e3 % SEC_PER_WEEK6;
|
|
1482
1652
|
var BDS_SUBFRAME_BYTES = 38;
|
|
1483
1653
|
function getBitU22(b, p1, l1, p2, l2) {
|
|
1484
1654
|
return getBitU(b, p1, l1) * 2 ** l2 + getBitU(b, p2, l2);
|
|
@@ -1752,8 +1922,8 @@ var BdsAssembler = class {
|
|
|
1752
1922
|
};
|
|
1753
1923
|
|
|
1754
1924
|
// src/navbits/glo.ts
|
|
1755
|
-
var
|
|
1756
|
-
var
|
|
1925
|
+
var GPS_EPOCH_MS7 = Date.UTC(1980, 0, 6);
|
|
1926
|
+
var SEC_PER_WEEK7 = 7 * 86400;
|
|
1757
1927
|
var SEC_PER_DAY = 86400;
|
|
1758
1928
|
var GLO_STRING_BYTES = 10;
|
|
1759
1929
|
function getBitG(b, pos, len) {
|
|
@@ -1846,9 +2016,9 @@ function decodeGloStrings(strings, refDate, opts = {}) {
|
|
|
1846
2016
|
const slot = getBitU(b, i, 5);
|
|
1847
2017
|
if (frn1 !== 1 || frn2 !== 2 || frn3 !== 3 || frn4 !== 4) return null;
|
|
1848
2018
|
if (slot < 1 || slot > 27) return null;
|
|
1849
|
-
const utcSec = (getUtcDate(refDate).getTime() -
|
|
1850
|
-
const week = Math.floor(utcSec /
|
|
1851
|
-
let tow = utcSec - week *
|
|
2019
|
+
const utcSec = (getUtcDate(refDate).getTime() - GPS_EPOCH_MS7) / 1e3;
|
|
2020
|
+
const week = Math.floor(utcSec / SEC_PER_WEEK7);
|
|
2021
|
+
let tow = utcSec - week * SEC_PER_WEEK7;
|
|
1852
2022
|
const tod = tow % SEC_PER_DAY;
|
|
1853
2023
|
tow -= tod;
|
|
1854
2024
|
let tof = tkH * 3600 + tkM * 60 + tkS - 10800;
|
|
@@ -1861,12 +2031,12 @@ function decodeGloStrings(strings, refDate, opts = {}) {
|
|
|
1861
2031
|
system: "R",
|
|
1862
2032
|
prn: `R${String(slot).padStart(2, "0")}`,
|
|
1863
2033
|
// RINEX GLONASS epochs are UTC: build the UTC toe Date directly.
|
|
1864
|
-
tocDate: new Date(
|
|
2034
|
+
tocDate: new Date(GPS_EPOCH_MS7 + (week * SEC_PER_WEEK7 + tow + toe) * 1e3),
|
|
1865
2035
|
tauN: -tauN,
|
|
1866
2036
|
// RINEX stores −τn; the SIS carries τn (ICD sign)
|
|
1867
2037
|
gammaN,
|
|
1868
2038
|
// v3 message frame time: seconds of the UTC week (RTKLIB tof).
|
|
1869
|
-
messageFrameTime: ((tow + tof) %
|
|
2039
|
+
messageFrameTime: ((tow + tof) % SEC_PER_WEEK7 + SEC_PER_WEEK7) % SEC_PER_WEEK7,
|
|
1870
2040
|
x,
|
|
1871
2041
|
xDot,
|
|
1872
2042
|
xAcc,
|
|
@@ -1915,10 +2085,10 @@ var GloStringAssembler = class {
|
|
|
1915
2085
|
};
|
|
1916
2086
|
|
|
1917
2087
|
// src/sbf/rawnav-bds.ts
|
|
1918
|
-
var
|
|
2088
|
+
var GPS_EPOCH_MS8 = Date.UTC(1980, 0, 6);
|
|
1919
2089
|
var MS_PER_WEEK3 = 7 * 86400 * 1e3;
|
|
1920
2090
|
var TOW_DNU = 4294967295;
|
|
1921
|
-
var
|
|
2091
|
+
var WNC_DNU3 = 65535;
|
|
1922
2092
|
function feedBdsBlock(view, b, assembler) {
|
|
1923
2093
|
const prn = svidToPrn(view.getUint8(b + 14));
|
|
1924
2094
|
if (!prn || prn[0] !== "C") return {};
|
|
@@ -1958,7 +2128,7 @@ function feedGloBlock(view, b, assembler) {
|
|
|
1958
2128
|
if (!prn || prn[0] !== "R") return {};
|
|
1959
2129
|
const towMs = view.getUint32(b + 8, true);
|
|
1960
2130
|
const wnc = view.getUint16(b + 12, true);
|
|
1961
|
-
if (towMs === TOW_DNU || wnc ===
|
|
2131
|
+
if (towMs === TOW_DNU || wnc === WNC_DNU3) return {};
|
|
1962
2132
|
const str2 = new Uint8Array(11);
|
|
1963
2133
|
for (let k = 0; k < 3; k++) {
|
|
1964
2134
|
const w = view.getUint32(b + 20 + 4 * k, true);
|
|
@@ -1976,7 +2146,7 @@ function feedGloBlock(view, b, assembler) {
|
|
|
1976
2146
|
const eph = assembler.push(
|
|
1977
2147
|
prn,
|
|
1978
2148
|
str2,
|
|
1979
|
-
new Date(
|
|
2149
|
+
new Date(GPS_EPOCH_MS8 + wnc * MS_PER_WEEK3 + towMs),
|
|
1980
2150
|
view.getUint8(b + 18) - 8
|
|
1981
2151
|
// FreqNr, offset by 8
|
|
1982
2152
|
);
|
|
@@ -1999,7 +2169,7 @@ function parseSbfGloNav(data) {
|
|
|
1999
2169
|
}
|
|
2000
2170
|
|
|
2001
2171
|
// src/navbits/sbas.ts
|
|
2002
|
-
var
|
|
2172
|
+
var GPS_EPOCH_MS9 = Date.UTC(1980, 0, 6);
|
|
2003
2173
|
var MS_PER_WEEK4 = 7 * 86400 * 1e3;
|
|
2004
2174
|
var two3 = (n) => String(n).padStart(2, "0");
|
|
2005
2175
|
var SBAS_MT_GEO_NAV = 9;
|
|
@@ -2021,7 +2191,7 @@ function decodeSbasGeoNav(msg, prn, week, tow) {
|
|
|
2021
2191
|
return {
|
|
2022
2192
|
system: "S",
|
|
2023
2193
|
prn: `S${two3(prn - 100)}`,
|
|
2024
|
-
tocDate: new Date(
|
|
2194
|
+
tocDate: new Date(GPS_EPOCH_MS9 + week * MS_PER_WEEK4 + t0Sec * 1e3),
|
|
2025
2195
|
tauN: getBitS(msg, 206, 12) * 2 ** -31,
|
|
2026
2196
|
// a_Gf0, clock offset (s)
|
|
2027
2197
|
gammaN: getBitS(msg, 218, 8) * 2 ** -39 / 2,
|
|
@@ -2194,6 +2364,7 @@ function decodeSbfNavigation(data, opts = {}) {
|
|
|
2194
2364
|
bdsRaw: 0,
|
|
2195
2365
|
sbasRaw: 0,
|
|
2196
2366
|
sbasL5Raw: 0,
|
|
2367
|
+
navicRaw: 0,
|
|
2197
2368
|
badFrames: 0
|
|
2198
2369
|
};
|
|
2199
2370
|
const dfmcByType = {};
|
|
@@ -2203,6 +2374,7 @@ function decodeSbfNavigation(data, opts = {}) {
|
|
|
2203
2374
|
const gloAsm = new GloStringAssembler();
|
|
2204
2375
|
const bdsAsm = new BdsAssembler();
|
|
2205
2376
|
const lnavAsm = new GpsLnavAssembler();
|
|
2377
|
+
const navicAsm = new NavicAssembler();
|
|
2206
2378
|
const addEph = (e) => {
|
|
2207
2379
|
if (!e) return;
|
|
2208
2380
|
const key = ephKey(e);
|
|
@@ -2263,6 +2435,14 @@ function decodeSbfNavigation(data, opts = {}) {
|
|
|
2263
2435
|
else if (r.badParity) counts.badFrames++;
|
|
2264
2436
|
return;
|
|
2265
2437
|
}
|
|
2438
|
+
case 4093: {
|
|
2439
|
+
if (len < 60) return;
|
|
2440
|
+
counts.navicRaw++;
|
|
2441
|
+
const r = feedNavicBlock(view, b, navicAsm);
|
|
2442
|
+
if (r.eph) addEph(r.eph);
|
|
2443
|
+
else if (r.badCrc) counts.badFrames++;
|
|
2444
|
+
return;
|
|
2445
|
+
}
|
|
2266
2446
|
case 4018:
|
|
2267
2447
|
// GPSRawL2C
|
|
2268
2448
|
case 4019: {
|
|
@@ -2883,7 +3063,7 @@ function parseSbfHas(data) {
|
|
|
2883
3063
|
|
|
2884
3064
|
// src/sbf/index.ts
|
|
2885
3065
|
var CLIGHT = 299792458;
|
|
2886
|
-
var
|
|
3066
|
+
var GPS_EPOCH_MS10 = Date.UTC(1980, 0, 6);
|
|
2887
3067
|
var MS_PER_WEEK5 = 7 * 864e5;
|
|
2888
3068
|
var M3_SYS = ["G", "R", "E", "C", "S", "J", "I"];
|
|
2889
3069
|
var M3_PR_BASE = [19e6, 19e6, 22e6, 2e7, 34e6, 34e6, 34e6];
|
|
@@ -3537,7 +3717,7 @@ function parseSbfMeas(data) {
|
|
|
3537
3717
|
const tow = view.getUint32(i + 8, true);
|
|
3538
3718
|
const wnc = view.getUint16(i + 12, true);
|
|
3539
3719
|
if (tow !== 4294967295 && wnc !== 65535) {
|
|
3540
|
-
ensureEpoch(
|
|
3720
|
+
ensureEpoch(GPS_EPOCH_MS10 + wnc * MS_PER_WEEK5 + tow);
|
|
3541
3721
|
if (id === 4109) decodeMeas3Ranges(i, tow);
|
|
3542
3722
|
else if (id === 4110) decodeMeas3CN0(i, len);
|
|
3543
3723
|
else if (id === 4111) decodeMeas3Doppler(i, len);
|
|
@@ -3553,8 +3733,10 @@ function parseSbfMeas(data) {
|
|
|
3553
3733
|
SBAS_L5_MT_NAMES,
|
|
3554
3734
|
SBAS_L5_PREAMBLE_UW,
|
|
3555
3735
|
decodeSbfNavigation,
|
|
3736
|
+
extractSbfNavicSubframe,
|
|
3556
3737
|
feedGeoBlock,
|
|
3557
3738
|
feedGeoL5Block,
|
|
3739
|
+
feedNavicBlock,
|
|
3558
3740
|
isSbasL1Preamble,
|
|
3559
3741
|
isSbasL5Correction,
|
|
3560
3742
|
parseSbfAlmanac,
|
|
@@ -3569,6 +3751,7 @@ function parseSbfMeas(data) {
|
|
|
3569
3751
|
parseSbfIonoUtc,
|
|
3570
3752
|
parseSbfMeas,
|
|
3571
3753
|
parseSbfNav,
|
|
3754
|
+
parseSbfNavic,
|
|
3572
3755
|
parseSbfPvt,
|
|
3573
3756
|
parseSbfReceiverSetup,
|
|
3574
3757
|
sbasL5MessageName,
|
package/dist/sbf.d.cts
CHANGED
|
@@ -174,6 +174,65 @@ interface SbfGpsNavResult {
|
|
|
174
174
|
*/
|
|
175
175
|
declare function parseSbfGpsNav(data: Uint8Array): SbfGpsNavResult;
|
|
176
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Streaming assembler: feed 292-bit NavIC subframes per PRN; emits a fresh
|
|
179
|
+
* ephemeris once a satellite's subframe 1 and 2 are both in hand (deduped by
|
|
180
|
+
* toc + IODEC). Mirrors {@link GpsLnavAssembler} for the raw-frame formats.
|
|
181
|
+
*/
|
|
182
|
+
declare class NavicAssembler {
|
|
183
|
+
private readonly sf1;
|
|
184
|
+
private readonly last;
|
|
185
|
+
/**
|
|
186
|
+
* Push one CRC-valid subframe. Subframe 1 opens a master frame (subframe 2
|
|
187
|
+
* immediately follows it in the NavIC frame order), so an ephemeris is only
|
|
188
|
+
* emitted when a subframe 2 pairs with the subframe 1 that opened the *same*
|
|
189
|
+
* frame — never a stale subframe 1 left over across CRC drops.
|
|
190
|
+
*/
|
|
191
|
+
push(prn: string, subframe: Uint8Array, refWeek: number): KeplerEphemeris | null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Septentrio SBF NAVICRaw (4093) blocks: each carries one 292-bit NavIC L5/S
|
|
196
|
+
* SPS subframe. Subframes 1 & 2 are assembled per satellite into a Keplerian
|
|
197
|
+
* ephemeris by the shared {@link NavicAssembler}.
|
|
198
|
+
*
|
|
199
|
+
* Block layout (mosaic-X5 reference guide §4): after the 8-byte SBF header,
|
|
200
|
+
* TOW u4 + WNc u2 (full GPS week), SVID u1, CRCPassed u1, ViterbiCnt u1,
|
|
201
|
+
* Source u1, FreqNr u1, RxChannel u1, then NAVBits as u4[10] — the first
|
|
202
|
+
* received bit is the MSB of NAVBits[0] (each u4 little-endian in the stream,
|
|
203
|
+
* message bits MSB-first within the word). Only the first 292 bits are used.
|
|
204
|
+
*
|
|
205
|
+
* The receiver's own CRCPassed flag is ignored in favour of re-running CRC-24Q
|
|
206
|
+
* on the transported bits, so `badCrc` counts exactly what this library rejects.
|
|
207
|
+
*/
|
|
208
|
+
|
|
209
|
+
interface SbfNavicResult {
|
|
210
|
+
/** Assembled NavIC ephemerides in stream order, repeats suppressed. */
|
|
211
|
+
ephemerides: KeplerEphemeris[];
|
|
212
|
+
/** Subframes whose CRC-24Q check failed (dropped). */
|
|
213
|
+
badCrc: number;
|
|
214
|
+
/** Total NAVICRaw blocks seen (with valid SBF framing). */
|
|
215
|
+
messages: number;
|
|
216
|
+
}
|
|
217
|
+
/** Extract the 292-bit NavIC subframe (MSB-first) from a NAVICRaw block. */
|
|
218
|
+
declare function extractSbfNavicSubframe(view: DataView, b: number): Uint8Array;
|
|
219
|
+
/**
|
|
220
|
+
* Process one NAVICRaw (4093) block at frame offset `b`: map SVID → NavIC PRN,
|
|
221
|
+
* extract + CRC-24Q gate the subframe, and push it to the shared assembler
|
|
222
|
+
* with the block's full WNc week. Returns a fresh ephemeris, `{ badCrc: true }`
|
|
223
|
+
* on a failed CRC, or `{}`. Shared by {@link parseSbfNavic} and the one-pass
|
|
224
|
+
* {@link decodeSbfNavigation}.
|
|
225
|
+
*/
|
|
226
|
+
declare function feedNavicBlock(view: DataView, b: number, assembler: NavicAssembler): {
|
|
227
|
+
eph?: KeplerEphemeris;
|
|
228
|
+
badCrc?: boolean;
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* Decode every NAVICRaw (4093) block in an SBF byte stream and assemble the
|
|
232
|
+
* carried subframes into NavIC ephemerides (`system` 'I').
|
|
233
|
+
*/
|
|
234
|
+
declare function parseSbfNavic(data: Uint8Array): SbfNavicResult;
|
|
235
|
+
|
|
177
236
|
/**
|
|
178
237
|
* Septentrio SBF raw CNAV navigation-bit blocks: GPSRawL2C (4018) and
|
|
179
238
|
* GPSRawL5 (4019) each carry one 300-bit GPS CNAV message.
|
|
@@ -339,6 +398,8 @@ interface SbfNavCounts {
|
|
|
339
398
|
sbasRaw: number;
|
|
340
399
|
/** Raw SBAS L5 GEO message blocks (GEORawL5) — DO-229-on-L5 + native DFMC. */
|
|
341
400
|
sbasL5Raw: number;
|
|
401
|
+
/** Raw NavIC L5/S SPS subframe blocks (NAVICRaw). */
|
|
402
|
+
navicRaw: number;
|
|
342
403
|
/** Frames dropped by a CRC/parity check across all raw decoders. */
|
|
343
404
|
badFrames: number;
|
|
344
405
|
}
|
|
@@ -610,4 +671,4 @@ interface SbfParseResult {
|
|
|
610
671
|
*/
|
|
611
672
|
declare function parseSbfMeas(data: Uint8Array): SbfParseResult;
|
|
612
673
|
|
|
613
|
-
export { CnavEphemeris, type DfmcCensus, type DfmcMessageCb, type GeoL5Result, HasMessage, ReceiverPvt, SBAS_L5_MT_NAMES, SBAS_L5_PREAMBLE_UW, type SbasMessageCb, type SbfBdsNavResult, type SbfCnavEphemeris, type SbfCnavResult, type SbfGalEphemeris, type SbfGalNavResult, type SbfGeoL5Result, 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, feedGeoL5Block, isSbasL1Preamble, isSbasL5Correction, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoL5, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, sbasL5MessageName, sbasL5MessageType, crc16 as sbfCrc16, scanSbfFrames };
|
|
674
|
+
export { CnavEphemeris, type DfmcCensus, type DfmcMessageCb, type GeoL5Result, HasMessage, ReceiverPvt, SBAS_L5_MT_NAMES, SBAS_L5_PREAMBLE_UW, type SbasMessageCb, type SbfBdsNavResult, type SbfCnavEphemeris, type SbfCnavResult, type SbfGalEphemeris, type SbfGalNavResult, type SbfGeoL5Result, type SbfGeoNavResult, type SbfGloNavResult, type SbfGpsNavResult, type SbfHasMessage, type SbfHasResult, type SbfIonoUtcResult, type SbfMeasEpoch, type SbfMeasurement, type SbfNavCounts, type SbfNavicResult, type SbfNavigation, type SbfParseResult, type SbfPvt, type SbfPvtResult, type SbfReceiverSetup, decodeSbfNavigation, extractSbfNavicSubframe, feedGeoBlock, feedGeoL5Block, feedNavicBlock, isSbasL1Preamble, isSbasL5Correction, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoL5, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfNavic, parseSbfPvt, parseSbfReceiverSetup, sbasL5MessageName, sbasL5MessageType, crc16 as sbfCrc16, scanSbfFrames };
|
package/dist/sbf.d.ts
CHANGED
|
@@ -174,6 +174,65 @@ interface SbfGpsNavResult {
|
|
|
174
174
|
*/
|
|
175
175
|
declare function parseSbfGpsNav(data: Uint8Array): SbfGpsNavResult;
|
|
176
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Streaming assembler: feed 292-bit NavIC subframes per PRN; emits a fresh
|
|
179
|
+
* ephemeris once a satellite's subframe 1 and 2 are both in hand (deduped by
|
|
180
|
+
* toc + IODEC). Mirrors {@link GpsLnavAssembler} for the raw-frame formats.
|
|
181
|
+
*/
|
|
182
|
+
declare class NavicAssembler {
|
|
183
|
+
private readonly sf1;
|
|
184
|
+
private readonly last;
|
|
185
|
+
/**
|
|
186
|
+
* Push one CRC-valid subframe. Subframe 1 opens a master frame (subframe 2
|
|
187
|
+
* immediately follows it in the NavIC frame order), so an ephemeris is only
|
|
188
|
+
* emitted when a subframe 2 pairs with the subframe 1 that opened the *same*
|
|
189
|
+
* frame — never a stale subframe 1 left over across CRC drops.
|
|
190
|
+
*/
|
|
191
|
+
push(prn: string, subframe: Uint8Array, refWeek: number): KeplerEphemeris | null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Septentrio SBF NAVICRaw (4093) blocks: each carries one 292-bit NavIC L5/S
|
|
196
|
+
* SPS subframe. Subframes 1 & 2 are assembled per satellite into a Keplerian
|
|
197
|
+
* ephemeris by the shared {@link NavicAssembler}.
|
|
198
|
+
*
|
|
199
|
+
* Block layout (mosaic-X5 reference guide §4): after the 8-byte SBF header,
|
|
200
|
+
* TOW u4 + WNc u2 (full GPS week), SVID u1, CRCPassed u1, ViterbiCnt u1,
|
|
201
|
+
* Source u1, FreqNr u1, RxChannel u1, then NAVBits as u4[10] — the first
|
|
202
|
+
* received bit is the MSB of NAVBits[0] (each u4 little-endian in the stream,
|
|
203
|
+
* message bits MSB-first within the word). Only the first 292 bits are used.
|
|
204
|
+
*
|
|
205
|
+
* The receiver's own CRCPassed flag is ignored in favour of re-running CRC-24Q
|
|
206
|
+
* on the transported bits, so `badCrc` counts exactly what this library rejects.
|
|
207
|
+
*/
|
|
208
|
+
|
|
209
|
+
interface SbfNavicResult {
|
|
210
|
+
/** Assembled NavIC ephemerides in stream order, repeats suppressed. */
|
|
211
|
+
ephemerides: KeplerEphemeris[];
|
|
212
|
+
/** Subframes whose CRC-24Q check failed (dropped). */
|
|
213
|
+
badCrc: number;
|
|
214
|
+
/** Total NAVICRaw blocks seen (with valid SBF framing). */
|
|
215
|
+
messages: number;
|
|
216
|
+
}
|
|
217
|
+
/** Extract the 292-bit NavIC subframe (MSB-first) from a NAVICRaw block. */
|
|
218
|
+
declare function extractSbfNavicSubframe(view: DataView, b: number): Uint8Array;
|
|
219
|
+
/**
|
|
220
|
+
* Process one NAVICRaw (4093) block at frame offset `b`: map SVID → NavIC PRN,
|
|
221
|
+
* extract + CRC-24Q gate the subframe, and push it to the shared assembler
|
|
222
|
+
* with the block's full WNc week. Returns a fresh ephemeris, `{ badCrc: true }`
|
|
223
|
+
* on a failed CRC, or `{}`. Shared by {@link parseSbfNavic} and the one-pass
|
|
224
|
+
* {@link decodeSbfNavigation}.
|
|
225
|
+
*/
|
|
226
|
+
declare function feedNavicBlock(view: DataView, b: number, assembler: NavicAssembler): {
|
|
227
|
+
eph?: KeplerEphemeris;
|
|
228
|
+
badCrc?: boolean;
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* Decode every NAVICRaw (4093) block in an SBF byte stream and assemble the
|
|
232
|
+
* carried subframes into NavIC ephemerides (`system` 'I').
|
|
233
|
+
*/
|
|
234
|
+
declare function parseSbfNavic(data: Uint8Array): SbfNavicResult;
|
|
235
|
+
|
|
177
236
|
/**
|
|
178
237
|
* Septentrio SBF raw CNAV navigation-bit blocks: GPSRawL2C (4018) and
|
|
179
238
|
* GPSRawL5 (4019) each carry one 300-bit GPS CNAV message.
|
|
@@ -339,6 +398,8 @@ interface SbfNavCounts {
|
|
|
339
398
|
sbasRaw: number;
|
|
340
399
|
/** Raw SBAS L5 GEO message blocks (GEORawL5) — DO-229-on-L5 + native DFMC. */
|
|
341
400
|
sbasL5Raw: number;
|
|
401
|
+
/** Raw NavIC L5/S SPS subframe blocks (NAVICRaw). */
|
|
402
|
+
navicRaw: number;
|
|
342
403
|
/** Frames dropped by a CRC/parity check across all raw decoders. */
|
|
343
404
|
badFrames: number;
|
|
344
405
|
}
|
|
@@ -610,4 +671,4 @@ interface SbfParseResult {
|
|
|
610
671
|
*/
|
|
611
672
|
declare function parseSbfMeas(data: Uint8Array): SbfParseResult;
|
|
612
673
|
|
|
613
|
-
export { CnavEphemeris, type DfmcCensus, type DfmcMessageCb, type GeoL5Result, HasMessage, ReceiverPvt, SBAS_L5_MT_NAMES, SBAS_L5_PREAMBLE_UW, type SbasMessageCb, type SbfBdsNavResult, type SbfCnavEphemeris, type SbfCnavResult, type SbfGalEphemeris, type SbfGalNavResult, type SbfGeoL5Result, 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, feedGeoL5Block, isSbasL1Preamble, isSbasL5Correction, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoL5, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfPvt, parseSbfReceiverSetup, sbasL5MessageName, sbasL5MessageType, crc16 as sbfCrc16, scanSbfFrames };
|
|
674
|
+
export { CnavEphemeris, type DfmcCensus, type DfmcMessageCb, type GeoL5Result, HasMessage, ReceiverPvt, SBAS_L5_MT_NAMES, SBAS_L5_PREAMBLE_UW, type SbasMessageCb, type SbfBdsNavResult, type SbfCnavEphemeris, type SbfCnavResult, type SbfGalEphemeris, type SbfGalNavResult, type SbfGeoL5Result, type SbfGeoNavResult, type SbfGloNavResult, type SbfGpsNavResult, type SbfHasMessage, type SbfHasResult, type SbfIonoUtcResult, type SbfMeasEpoch, type SbfMeasurement, type SbfNavCounts, type SbfNavicResult, type SbfNavigation, type SbfParseResult, type SbfPvt, type SbfPvtResult, type SbfReceiverSetup, decodeSbfNavigation, extractSbfNavicSubframe, feedGeoBlock, feedGeoL5Block, feedNavicBlock, isSbasL1Preamble, isSbasL5Correction, parseSbfBdsNav, parseSbfCnav, parseSbfGalNav, parseSbfGeoL5, parseSbfGeoNav, parseSbfGloNav, parseSbfGpsNav, parseSbfHas, parseSbfIonoUtc, parseSbfMeas, parseSbfNavic, parseSbfPvt, parseSbfReceiverSetup, sbasL5MessageName, sbasL5MessageType, crc16 as sbfCrc16, scanSbfFrames };
|
package/dist/sbf.js
CHANGED
|
@@ -3,8 +3,10 @@ import {
|
|
|
3
3
|
SBAS_L5_PREAMBLE_UW,
|
|
4
4
|
crc16,
|
|
5
5
|
decodeSbfNavigation,
|
|
6
|
+
extractSbfNavicSubframe,
|
|
6
7
|
feedGeoBlock,
|
|
7
8
|
feedGeoL5Block,
|
|
9
|
+
feedNavicBlock,
|
|
8
10
|
isSbasL1Preamble,
|
|
9
11
|
isSbasL5Correction,
|
|
10
12
|
parseSbfAlmanac,
|
|
@@ -19,12 +21,13 @@ import {
|
|
|
19
21
|
parseSbfIonoUtc,
|
|
20
22
|
parseSbfMeas,
|
|
21
23
|
parseSbfNav,
|
|
24
|
+
parseSbfNavic,
|
|
22
25
|
parseSbfPvt,
|
|
23
26
|
parseSbfReceiverSetup,
|
|
24
27
|
sbasL5MessageName,
|
|
25
28
|
sbasL5MessageType,
|
|
26
29
|
scanSbfFrames
|
|
27
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-74IVYOQV.js";
|
|
28
31
|
import "./chunk-3KSDL3CO.js";
|
|
29
32
|
import "./chunk-WQX354KD.js";
|
|
30
33
|
import "./chunk-HVXYFUCB.js";
|
|
@@ -37,8 +40,10 @@ export {
|
|
|
37
40
|
SBAS_L5_MT_NAMES,
|
|
38
41
|
SBAS_L5_PREAMBLE_UW,
|
|
39
42
|
decodeSbfNavigation,
|
|
43
|
+
extractSbfNavicSubframe,
|
|
40
44
|
feedGeoBlock,
|
|
41
45
|
feedGeoL5Block,
|
|
46
|
+
feedNavicBlock,
|
|
42
47
|
isSbasL1Preamble,
|
|
43
48
|
isSbasL5Correction,
|
|
44
49
|
parseSbfAlmanac,
|
|
@@ -53,6 +58,7 @@ export {
|
|
|
53
58
|
parseSbfIonoUtc,
|
|
54
59
|
parseSbfMeas,
|
|
55
60
|
parseSbfNav,
|
|
61
|
+
parseSbfNavic,
|
|
56
62
|
parseSbfPvt,
|
|
57
63
|
parseSbfReceiverSetup,
|
|
58
64
|
sbasL5MessageName,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gnss-js",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.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,
|