@aeroswarm/codec 0.1.10 → 0.1.12
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.js +144 -48
- package/dist/surveillance/asterix/cat062.test.d.ts +2 -0
- package/dist/surveillance/asterix/cat062.test.d.ts.map +1 -0
- package/dist/surveillance/asterix/decoder.d.ts +14 -4
- package/dist/surveillance/asterix/decoder.d.ts.map +1 -1
- package/dist/surveillance/asterix/index.d.ts +2 -1
- package/dist/surveillance/asterix/index.d.ts.map +1 -1
- package/dist/surveillance/asterix/parser.d.ts +18 -1
- package/dist/surveillance/asterix/parser.d.ts.map +1 -1
- package/dist/surveillance/asterix/repetitive.test.d.ts +2 -0
- package/dist/surveillance/asterix/repetitive.test.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -116,11 +116,15 @@ function parseBits(s) {
|
|
|
116
116
|
}
|
|
117
117
|
return out;
|
|
118
118
|
}
|
|
119
|
+
function repetitionBytes(body, fallback) {
|
|
120
|
+
if (/<BDS[\s/>]/.test(body)) return 8;
|
|
121
|
+
const m = body.match(/<Fixed\s+length="(\d+)"/);
|
|
122
|
+
return m ? parseInt(m[1]) : fallback;
|
|
123
|
+
}
|
|
119
124
|
function parseRepetitive(s) {
|
|
120
125
|
const inner = firstContent(s, "Repetitive");
|
|
121
126
|
const repAttr = inner.match(/<Repetitive\s+rep="(\d+)"/);
|
|
122
|
-
|
|
123
|
-
return { type: "repetitive", repBytes: repAttr ? parseInt(repAttr[1]) : 1, itemBytes: m ? parseInt(m[1]) : 0 };
|
|
127
|
+
return { type: "repetitive", repBytes: repAttr ? parseInt(repAttr[1]) : 1, itemBytes: repetitionBytes(inner, 0) };
|
|
124
128
|
}
|
|
125
129
|
function parseCompound(s) {
|
|
126
130
|
const inner = firstContent(s, "Compound");
|
|
@@ -130,27 +134,47 @@ function parseCompound(s) {
|
|
|
130
134
|
const varEnd = inner.indexOf("</Variable>");
|
|
131
135
|
const afterVar = varEnd >= 0 ? inner.slice(varEnd + "</Variable>".length) : "";
|
|
132
136
|
const subs = [];
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const rest = afterVar.slice(sm.index);
|
|
138
|
-
if (tag === "Fixed") {
|
|
139
|
-
const lm = rest.match(/<Fixed\s+length="(\d+)"/);
|
|
137
|
+
for (const child of topLevelChildren(afterVar)) {
|
|
138
|
+
const first = child.body.match(/<Fixed\s+length="(\d+)"/);
|
|
139
|
+
if (child.tag === "Fixed") {
|
|
140
|
+
const lm = child.open.match(/length="(\d+)"/);
|
|
140
141
|
if (lm) subs.push({ type: "fixed", bytes: parseInt(lm[1]) });
|
|
141
|
-
} else if (tag === "Variable") {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const lm = rest.match(/<Fixed\s+length="(\d+)"/);
|
|
147
|
-
subs.push({ type: "repetitive", repBytes: repAttr ? parseInt(repAttr[1]) : 1, itemBytes: lm ? parseInt(lm[1]) : 1 });
|
|
142
|
+
} else if (child.tag === "Variable") {
|
|
143
|
+
subs.push({ type: "variable", chunkBytes: first ? parseInt(first[1]) : 1 });
|
|
144
|
+
} else if (child.tag === "Repetitive") {
|
|
145
|
+
const repAttr = child.open.match(/rep="(\d+)"/);
|
|
146
|
+
subs.push({ type: "repetitive", repBytes: repAttr ? parseInt(repAttr[1]) : 1, itemBytes: repetitionBytes(child.body, 1) });
|
|
148
147
|
} else {
|
|
149
148
|
subs.push({ type: "explicit" });
|
|
150
149
|
}
|
|
151
150
|
}
|
|
152
151
|
return { type: "compound", indicatorChunk, subs };
|
|
153
152
|
}
|
|
153
|
+
function topLevelChildren(s) {
|
|
154
|
+
const out = [];
|
|
155
|
+
const re = /<(\/?)(Fixed|Variable|Repetitive|Explicit|Compound)\b([^>]*?)(\/?)>/g;
|
|
156
|
+
let depth = 0;
|
|
157
|
+
let current = null;
|
|
158
|
+
let m;
|
|
159
|
+
while ((m = re.exec(s)) !== null) {
|
|
160
|
+
const closing = m[1] === "/";
|
|
161
|
+
const selfClosing = m[4] === "/";
|
|
162
|
+
if (!closing) {
|
|
163
|
+
if (depth === 0) {
|
|
164
|
+
if (selfClosing) out.push({ tag: m[2], open: m[0], body: "" });
|
|
165
|
+
else current = { tag: m[2], open: m[0], start: m.index + m[0].length };
|
|
166
|
+
}
|
|
167
|
+
if (!selfClosing) depth++;
|
|
168
|
+
} else {
|
|
169
|
+
depth--;
|
|
170
|
+
if (depth === 0 && current) {
|
|
171
|
+
out.push({ tag: current.tag, open: current.open, body: s.slice(current.start, m.index) });
|
|
172
|
+
current = null;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
154
178
|
function firstContent(s, tag) {
|
|
155
179
|
return s.match(new RegExp(`<${tag}[^>]*>([\\s\\S]*?)<\\/${tag}>`))?.[1] ?? "";
|
|
156
180
|
}
|
|
@@ -168,23 +192,23 @@ function parseFspec(buf, start = 0) {
|
|
|
168
192
|
return { bits, end: i };
|
|
169
193
|
}
|
|
170
194
|
function skipItem(buf, off, def) {
|
|
171
|
-
if (off >= buf.length) return buf.length;
|
|
195
|
+
if (off >= buf.length) return buf.length + 1;
|
|
172
196
|
switch (def.type) {
|
|
173
197
|
case "fixed":
|
|
174
|
-
return
|
|
198
|
+
return off + def.bytes;
|
|
175
199
|
case "variable": {
|
|
176
200
|
while (off + def.chunkBytes <= buf.length) {
|
|
177
201
|
const last = buf[off + def.chunkBytes - 1];
|
|
178
202
|
off += def.chunkBytes;
|
|
179
203
|
if ((last & 1) === 0) break;
|
|
180
204
|
}
|
|
181
|
-
return
|
|
205
|
+
return off;
|
|
182
206
|
}
|
|
183
207
|
case "repetitive": {
|
|
184
|
-
if (off + def.repBytes > buf.length) return buf.length;
|
|
208
|
+
if (off + def.repBytes > buf.length) return buf.length + 1;
|
|
185
209
|
let rep = 0;
|
|
186
210
|
for (let i = 0; i < def.repBytes; i++) rep = rep << 8 | buf[off + i];
|
|
187
|
-
return
|
|
211
|
+
return off + def.repBytes + rep * def.itemBytes;
|
|
188
212
|
}
|
|
189
213
|
case "compound": {
|
|
190
214
|
const presentIdxs = [];
|
|
@@ -202,13 +226,12 @@ function skipItem(buf, off, def) {
|
|
|
202
226
|
if (idx >= def.subs.length) break;
|
|
203
227
|
off = skipItem(buf, off, def.subs[idx]);
|
|
204
228
|
}
|
|
205
|
-
return
|
|
229
|
+
return off;
|
|
206
230
|
}
|
|
207
231
|
case "explicit": {
|
|
208
|
-
if (off >= buf.length) return
|
|
232
|
+
if (off >= buf.length) return buf.length + 1;
|
|
209
233
|
const len = buf[off];
|
|
210
|
-
off
|
|
211
|
-
return Math.min(off + len - 1, buf.length);
|
|
234
|
+
return off + Math.max(len, 1);
|
|
212
235
|
}
|
|
213
236
|
}
|
|
214
237
|
}
|
|
@@ -218,16 +241,18 @@ function decodeBlock(block, def, onField) {
|
|
|
218
241
|
const uapMap = new Map(def.uap.map((e) => [e.bit, e.id]));
|
|
219
242
|
for (let i = 0; i < bits.length; i++) {
|
|
220
243
|
if (!bits[i]) continue;
|
|
221
|
-
if (off >= block.length)
|
|
244
|
+
if (off >= block.length) return { end: block.length, complete: true, overrun: true };
|
|
222
245
|
const uapPos = i + Math.floor(i / 7);
|
|
223
246
|
const id = uapMap.get(uapPos);
|
|
224
|
-
if (id === void 0)
|
|
247
|
+
if (id === void 0) return { end: off, complete: false, overrun: false };
|
|
225
248
|
const itemDef = def.items.get(id);
|
|
226
|
-
if (!itemDef)
|
|
249
|
+
if (!itemDef) return { end: off, complete: false, overrun: false };
|
|
227
250
|
const start = off;
|
|
228
251
|
off = skipItem(block, off, itemDef);
|
|
229
|
-
onField(id, block.slice(start, off), itemDef);
|
|
252
|
+
onField(id, block.slice(start, Math.min(off, block.length)), itemDef);
|
|
253
|
+
if (off > block.length) return { end: block.length, complete: true, overrun: true };
|
|
230
254
|
}
|
|
255
|
+
return { end: off, complete: true, overrun: false };
|
|
231
256
|
}
|
|
232
257
|
|
|
233
258
|
// src/surveillance/asterix/fields.ts
|
|
@@ -616,6 +641,19 @@ function cat010(id, d, out, raw) {
|
|
|
616
641
|
}
|
|
617
642
|
}
|
|
618
643
|
var MS_TO_KT = 1 / 0.514444;
|
|
644
|
+
function flightPlanCallsign(d) {
|
|
645
|
+
let indicators = 0;
|
|
646
|
+
while (indicators < d.length) {
|
|
647
|
+
indicators++;
|
|
648
|
+
if ((d[indicators - 1] & 1) === 0) break;
|
|
649
|
+
}
|
|
650
|
+
const first = d[0] ?? 0;
|
|
651
|
+
if ((first & 64) === 0) return void 0;
|
|
652
|
+
const at = indicators + ((first & 128) !== 0 ? 2 : 0);
|
|
653
|
+
if (d.length < at + 7) return void 0;
|
|
654
|
+
const text = d.subarray(at, at + 7).toString("latin1").trim();
|
|
655
|
+
return text.length > 0 && /^[A-Z0-9 ]+$/.test(text) ? text : void 0;
|
|
656
|
+
}
|
|
619
657
|
function cat062(id, d, out, raw) {
|
|
620
658
|
switch (id) {
|
|
621
659
|
case "080":
|
|
@@ -667,14 +705,33 @@ function cat062(id, d, out, raw) {
|
|
|
667
705
|
out.targetType = "vehicle";
|
|
668
706
|
break;
|
|
669
707
|
}
|
|
708
|
+
case "245": {
|
|
709
|
+
const cs = str(raw, "TId");
|
|
710
|
+
const text = cs !== void 0 ? cs : d.length >= 7 ? readCallsign(d.subarray(1)) : "";
|
|
711
|
+
if (text) out.callsign = text;
|
|
712
|
+
break;
|
|
713
|
+
}
|
|
714
|
+
case "390": {
|
|
715
|
+
if (out.callsign === void 0) {
|
|
716
|
+
const csn = flightPlanCallsign(d);
|
|
717
|
+
if (csn) out.callsign = csn;
|
|
718
|
+
}
|
|
719
|
+
break;
|
|
720
|
+
}
|
|
670
721
|
case "380": {
|
|
671
722
|
let fsLen = 0;
|
|
672
723
|
while (fsLen < d.length) {
|
|
673
724
|
fsLen++;
|
|
674
725
|
if ((d[fsLen - 1] & 1) === 0) break;
|
|
675
726
|
}
|
|
676
|
-
|
|
677
|
-
|
|
727
|
+
let at = fsLen;
|
|
728
|
+
if (fsLen < d.length && (d[0] & 128) !== 0 && d.length >= at + 3) {
|
|
729
|
+
out.icao24 = d.readUIntBE(at, 3).toString(16).padStart(6, "0");
|
|
730
|
+
at += 3;
|
|
731
|
+
}
|
|
732
|
+
if (fsLen < d.length && (d[0] & 64) !== 0 && d.length >= at + 6 && out.callsign === void 0) {
|
|
733
|
+
const id2 = readCallsign(d.subarray(at, at + 6));
|
|
734
|
+
if (id2) out.callsign = id2;
|
|
678
735
|
}
|
|
679
736
|
break;
|
|
680
737
|
}
|
|
@@ -863,6 +920,14 @@ var EDITIONS = {
|
|
|
863
920
|
};
|
|
864
921
|
function parseAsterix(buf, defaultEdition) {
|
|
865
922
|
const records = [];
|
|
923
|
+
for (const block of parseAsterixBlocks(buf, defaultEdition)) {
|
|
924
|
+
if (block.edition === null) continue;
|
|
925
|
+
for (const fields of block.records) records.push({ category: block.category, edition: block.edition, fields });
|
|
926
|
+
}
|
|
927
|
+
return records;
|
|
928
|
+
}
|
|
929
|
+
function parseAsterixBlocks(buf, defaultEdition) {
|
|
930
|
+
const blocks = [];
|
|
866
931
|
let offset = 0;
|
|
867
932
|
while (offset + 3 <= buf.length) {
|
|
868
933
|
const cat = buf[offset];
|
|
@@ -875,26 +940,56 @@ function parseAsterix(buf, defaultEdition) {
|
|
|
875
940
|
for (const edition of toTry) {
|
|
876
941
|
const def = loadDef(cat, edition);
|
|
877
942
|
if (!def) continue;
|
|
878
|
-
const
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
decodeKnownField(cat, id, data, fields, raw);
|
|
885
|
-
});
|
|
886
|
-
} catch {
|
|
887
|
-
continue;
|
|
888
|
-
}
|
|
889
|
-
if (!isPlausible(fields)) continue;
|
|
890
|
-
const score = plausibilityScore(fields);
|
|
891
|
-
if (!best || score > best.score) {
|
|
892
|
-
best = { edition, fields, score };
|
|
943
|
+
const { all, consumed, full } = decodeRecords(block, def, cat);
|
|
944
|
+
const first = all[0];
|
|
945
|
+
if (!first) continue;
|
|
946
|
+
const score = plausibilityScore(first);
|
|
947
|
+
if (!best || full && !best.full || full === best.full && score > best.score) {
|
|
948
|
+
best = { edition, all, consumed, score, full };
|
|
893
949
|
}
|
|
894
950
|
}
|
|
895
|
-
|
|
951
|
+
blocks.push({
|
|
952
|
+
category: cat,
|
|
953
|
+
edition: best?.edition ?? null,
|
|
954
|
+
length: block.length,
|
|
955
|
+
consumed: best?.consumed ?? 0,
|
|
956
|
+
clean: best?.full ?? false,
|
|
957
|
+
records: best?.all ?? []
|
|
958
|
+
});
|
|
896
959
|
}
|
|
897
|
-
return
|
|
960
|
+
return blocks;
|
|
961
|
+
}
|
|
962
|
+
function decodeRecords(block, def, cat) {
|
|
963
|
+
const records = [];
|
|
964
|
+
let pos = 0;
|
|
965
|
+
let clean = false;
|
|
966
|
+
while (pos < block.length) {
|
|
967
|
+
const fields = {};
|
|
968
|
+
let result;
|
|
969
|
+
try {
|
|
970
|
+
result = decodeBlock(block.subarray(pos), def, (id, data, itemDef) => {
|
|
971
|
+
const bits = itemDef.type === "fixed" || itemDef.type === "variable" ? itemDef.bits : void 0;
|
|
972
|
+
const bitData = itemDef.type === "variable" ? data.subarray(0, itemDef.chunkBytes) : data;
|
|
973
|
+
const raw = bits?.length ? extractBitFields(bitData, bits) : {};
|
|
974
|
+
decodeKnownField(cat, id, data, fields, raw);
|
|
975
|
+
});
|
|
976
|
+
} catch {
|
|
977
|
+
break;
|
|
978
|
+
}
|
|
979
|
+
if (!isPlausible(fields)) break;
|
|
980
|
+
if (result.overrun && records.length > 0) break;
|
|
981
|
+
records.push({ fields, end: pos + result.end });
|
|
982
|
+
if (!result.complete || result.end <= 0 || result.overrun) break;
|
|
983
|
+
pos += result.end;
|
|
984
|
+
clean = pos >= block.length;
|
|
985
|
+
}
|
|
986
|
+
if (clean) {
|
|
987
|
+
const kept = records.filter((r, i) => i === 0 || Object.keys(r.fields).length > 0).map((r) => r.fields);
|
|
988
|
+
return { all: kept, consumed: block.length, full: true };
|
|
989
|
+
}
|
|
990
|
+
const firstEmpty = records.findIndex((r, i) => i > 0 && Object.keys(r.fields).length === 0);
|
|
991
|
+
const usable = firstEmpty === -1 ? records : records.slice(0, firstEmpty);
|
|
992
|
+
return { all: usable.map((r) => r.fields), consumed: usable.length > 0 ? usable[usable.length - 1].end : 0, full: false };
|
|
898
993
|
}
|
|
899
994
|
function isPlausible(f) {
|
|
900
995
|
if (f.lat !== void 0 && (f.lat < -90 || f.lat > 90)) return false;
|
|
@@ -1249,6 +1344,7 @@ export {
|
|
|
1249
1344
|
decodeMlatFrame,
|
|
1250
1345
|
parseAftn,
|
|
1251
1346
|
parseAsterix,
|
|
1347
|
+
parseAsterixBlocks,
|
|
1252
1348
|
resolveAsterixAltitudeFt,
|
|
1253
1349
|
resolveAsterixPosition,
|
|
1254
1350
|
splitAftnStream
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cat062.test.d.ts","sourceRoot":"","sources":["../../../src/surveillance/asterix/cat062.test.ts"],"names":[],"mappings":""}
|
|
@@ -4,11 +4,21 @@ export declare function parseFspec(buf: Buffer, start?: number): {
|
|
|
4
4
|
bits: boolean[];
|
|
5
5
|
end: number;
|
|
6
6
|
};
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Advance offset past one DataItem, returning new offset. The result is NOT clamped to the buffer: an offset past
|
|
9
|
+
* `buf.length` means the item needs more octets than there are (an overrun), which `decodeBlock` reports.
|
|
10
|
+
*/
|
|
8
11
|
export declare function skipItem(buf: Buffer, off: number, def: ItemDef): number;
|
|
9
12
|
/**
|
|
10
|
-
* Decode
|
|
11
|
-
* Calls `onField(id, bytes, itemDef)` for each present DataItem.
|
|
13
|
+
* Decode ONE record at the start of `block` (a data block can carry many records back to back, each with its own
|
|
14
|
+
* FSPEC). Calls `onField(id, bytes, itemDef)` for each present DataItem. Returns where the record ended, so the caller
|
|
15
|
+
* can go on with the next one, and whether that position can be trusted: `complete` is false when an item the
|
|
16
|
+
* definition does not know stopped the decode (the length of what follows is then unknown); `overrun` is true when an
|
|
17
|
+
* item needed more octets than the block has (the record is cut short or an item was sized wrongly).
|
|
12
18
|
*/
|
|
13
|
-
export declare function decodeBlock(block: Buffer, def: AsterixDef, onField: (id: string, data: Buffer, itemDef: ItemDef) => void):
|
|
19
|
+
export declare function decodeBlock(block: Buffer, def: AsterixDef, onField: (id: string, data: Buffer, itemDef: ItemDef) => void): {
|
|
20
|
+
end: number;
|
|
21
|
+
complete: boolean;
|
|
22
|
+
overrun: boolean;
|
|
23
|
+
};
|
|
14
24
|
//# sourceMappingURL=decoder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../../src/surveillance/asterix/decoder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAI3D,sFAAsF;AACtF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG;IAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAUnF;AAID
|
|
1
|
+
{"version":3,"file":"decoder.d.ts","sourceRoot":"","sources":["../../../src/surveillance/asterix/decoder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAI3D,sFAAsF;AACtF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG;IAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAUnF;AAID;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,CAiDvE;AAID;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GAC5D;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CA2BtD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { parseAsterix } from './parser.js';
|
|
1
|
+
export { parseAsterix, parseAsterixBlocks } from './parser.js';
|
|
2
|
+
export type { AsterixBlockInfo } from './parser.js';
|
|
2
3
|
export { resolveAsterixPosition, resolveAsterixAltitudeFt } from './resolvers.js';
|
|
3
4
|
export type { RadarSite } from './resolvers.js';
|
|
4
5
|
export type { AsterixRecord, AsterixFields } from './types.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/surveillance/asterix/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/surveillance/asterix/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAClF,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AsterixRecord } from './types.js';
|
|
1
|
+
import type { AsterixRecord, AsterixFields } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Parse raw ASTERIX UDP datagram into structured records.
|
|
4
4
|
*
|
|
@@ -13,4 +13,21 @@ import type { AsterixRecord } from './types.js';
|
|
|
13
13
|
* Use when you know the sender's edition for certainty.
|
|
14
14
|
*/
|
|
15
15
|
export declare function parseAsterix(buf: Buffer, defaultEdition?: Record<number, string>): AsterixRecord[];
|
|
16
|
+
/** What became of one data block: the edition that fit (null = none, the block is dropped), its records, and how much of the block they used. */
|
|
17
|
+
export interface AsterixBlockInfo {
|
|
18
|
+
category: number;
|
|
19
|
+
edition: string | null;
|
|
20
|
+
/** Octets of the block after its 3-octet header. */
|
|
21
|
+
length: number;
|
|
22
|
+
/** Octets taken up by the decoded records. */
|
|
23
|
+
consumed: number;
|
|
24
|
+
/** The records tile the block exactly: no octets left over, none missing, no item that ran past the end. False points at an item sized wrongly or a tail that was not understood. */
|
|
25
|
+
clean: boolean;
|
|
26
|
+
records: AsterixFields[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Same decoding as `parseAsterix`, block by block, with the facts needed to judge it (see `AsterixBlockInfo`). For tools
|
|
30
|
+
* that check a decoder against a capture; `parseAsterix` is built on it.
|
|
31
|
+
*/
|
|
32
|
+
export declare function parseAsterixBlocks(buf: Buffer, defaultEdition?: Record<number, string>): AsterixBlockInfo[];
|
|
16
33
|
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/surveillance/asterix/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/surveillance/asterix/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAsB/D;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,aAAa,EAAE,CAOjB;AAED,iJAAiJ;AACjJ,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,qLAAqL;IACrL,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,gBAAgB,EAAE,CA2CpB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repetitive.test.d.ts","sourceRoot":"","sources":["../../../src/surveillance/asterix/repetitive.test.ts"],"names":[],"mappings":""}
|