@airframes/acars-decoder 1.8.14 → 1.9.1
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/License.md +21 -0
- package/README.md +8 -11
- package/dist/index.d.mts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +398 -167
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +398 -167
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -94,11 +94,11 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
94
94
|
* @returns An object with latitude and longitude properties
|
|
95
95
|
*/
|
|
96
96
|
static decodeStringCoordinates(stringCoords) {
|
|
97
|
-
const firstChar = stringCoords.
|
|
98
|
-
let middleChar = stringCoords.
|
|
97
|
+
const firstChar = stringCoords.charAt(0);
|
|
98
|
+
let middleChar = stringCoords.charAt(6);
|
|
99
99
|
let longitudeChars = stringCoords.substring(7, 13);
|
|
100
|
-
if (middleChar
|
|
101
|
-
middleChar = stringCoords.
|
|
100
|
+
if (middleChar === " ") {
|
|
101
|
+
middleChar = stringCoords.charAt(7);
|
|
102
102
|
longitudeChars = stringCoords.substring(8, 14);
|
|
103
103
|
}
|
|
104
104
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
@@ -116,24 +116,26 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
116
116
|
* @returns An object with latitude and longitude properties
|
|
117
117
|
*/
|
|
118
118
|
static decodeStringCoordinatesDecimalMinutes(stringCoords) {
|
|
119
|
-
const firstChar = stringCoords.
|
|
120
|
-
let middleChar = stringCoords.
|
|
119
|
+
const firstChar = stringCoords.charAt(0);
|
|
120
|
+
let middleChar = stringCoords.charAt(6);
|
|
121
121
|
let longitudeChars = stringCoords.substring(7, 13);
|
|
122
|
-
if (middleChar
|
|
123
|
-
middleChar = stringCoords.
|
|
122
|
+
if (middleChar === " ") {
|
|
123
|
+
middleChar = stringCoords.charAt(7);
|
|
124
124
|
longitudeChars = stringCoords.substring(8, 14);
|
|
125
125
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
|
|
129
|
-
const lonMin = Number(longitudeChars) % 1e3 / 10;
|
|
130
|
-
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
131
|
-
return {
|
|
132
|
-
latitude: (latDeg + latMin / 60) * _CoordinateUtils.getDirection(firstChar),
|
|
133
|
-
longitude: (lonDeg + lonMin / 60) * _CoordinateUtils.getDirection(middleChar)
|
|
134
|
-
};
|
|
126
|
+
if (firstChar !== "N" && firstChar !== "S" || middleChar !== "W" && middleChar !== "E") {
|
|
127
|
+
return void 0;
|
|
135
128
|
}
|
|
136
|
-
|
|
129
|
+
const latRaw = Number(stringCoords.substring(1, 6));
|
|
130
|
+
const lonRaw = Number(longitudeChars);
|
|
131
|
+
const latDeg = Math.trunc(latRaw / 1e3);
|
|
132
|
+
const latMin = latRaw % 1e3 / 10;
|
|
133
|
+
const lonDeg = Math.trunc(lonRaw / 1e3);
|
|
134
|
+
const lonMin = lonRaw % 1e3 / 10;
|
|
135
|
+
return {
|
|
136
|
+
latitude: (latDeg + latMin / 60) * _CoordinateUtils.getDirection(firstChar),
|
|
137
|
+
longitude: (lonDeg + lonMin / 60) * _CoordinateUtils.getDirection(middleChar)
|
|
138
|
+
};
|
|
137
139
|
}
|
|
138
140
|
static coordinateString(coords) {
|
|
139
141
|
const latDir = coords.latitude > 0 ? "N" : "S";
|
|
@@ -164,25 +166,13 @@ var DateTimeUtils = class {
|
|
|
164
166
|
// Expects a six digit date string and a four digit UTC time string
|
|
165
167
|
// (DDMMYY) (HHMM)
|
|
166
168
|
static UTCDateTimeToString(dateString, timeString) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
utcDate.setUTCHours(
|
|
175
|
-
+timeString.substr(0, 2),
|
|
176
|
-
+timeString.substr(2, 2),
|
|
177
|
-
+timeString.substr(4, 2)
|
|
178
|
-
);
|
|
179
|
-
} else {
|
|
180
|
-
utcDate.setUTCHours(
|
|
181
|
-
+timeString.substr(0, 2),
|
|
182
|
-
+timeString.substr(2, 2),
|
|
183
|
-
0
|
|
184
|
-
);
|
|
185
|
-
}
|
|
169
|
+
const day = +dateString.substr(0, 2);
|
|
170
|
+
const month = +dateString.substr(2, 2) - 1;
|
|
171
|
+
const year = dateString.length === 6 ? 2e3 + +dateString.substr(4, 2) : (/* @__PURE__ */ new Date()).getUTCFullYear();
|
|
172
|
+
const hours = +timeString.substr(0, 2);
|
|
173
|
+
const minutes = +timeString.substr(2, 2);
|
|
174
|
+
const seconds = timeString.length === 6 ? +timeString.substr(4, 2) : 0;
|
|
175
|
+
const utcDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
|
|
186
176
|
return utcDate.toUTCString();
|
|
187
177
|
}
|
|
188
178
|
/**
|
|
@@ -527,7 +517,7 @@ var ResultFormatter = class {
|
|
|
527
517
|
decodeResult.raw.fuel_remaining = value;
|
|
528
518
|
decodeResult.formatted.items.push({
|
|
529
519
|
type: "fuel_remaining",
|
|
530
|
-
code: "
|
|
520
|
+
code: "FUEL_REM",
|
|
531
521
|
label: "Fuel Remaining",
|
|
532
522
|
value: decodeResult.raw.fuel_remaining.toString()
|
|
533
523
|
});
|
|
@@ -586,7 +576,7 @@ var ResultFormatter = class {
|
|
|
586
576
|
type: "message_checksum",
|
|
587
577
|
code: "CHECKSUM",
|
|
588
578
|
label: "Message Checksum",
|
|
589
|
-
value: "0x" + (
|
|
579
|
+
value: "0x" + (decodeResult.raw.checksum >>> 0).toString(16).padStart(4, "0")
|
|
590
580
|
});
|
|
591
581
|
}
|
|
592
582
|
static groundspeed(decodeResult, value) {
|
|
@@ -921,7 +911,7 @@ var ResultFormatter = class {
|
|
|
921
911
|
type: "sequence",
|
|
922
912
|
code: "SEQ",
|
|
923
913
|
label: "Sequence Number",
|
|
924
|
-
value: decodeResult.raw.sequence_number
|
|
914
|
+
value: decodeResult.raw.sequence_number.toString()
|
|
925
915
|
});
|
|
926
916
|
}
|
|
927
917
|
static sequenceResponse(decodeResult, value) {
|
|
@@ -930,7 +920,7 @@ var ResultFormatter = class {
|
|
|
930
920
|
type: "sequence",
|
|
931
921
|
code: "SEQ_RESP",
|
|
932
922
|
label: "Sequence Response",
|
|
933
|
-
value: decodeResult.raw.sequence_response
|
|
923
|
+
value: decodeResult.raw.sequence_response.toString()
|
|
934
924
|
});
|
|
935
925
|
}
|
|
936
926
|
static unknown(decodeResult, value, sep = ",") {
|
|
@@ -1036,6 +1026,7 @@ var DecoderPlugin = class {
|
|
|
1036
1026
|
};
|
|
1037
1027
|
|
|
1038
1028
|
// lib/plugins/CBand.ts
|
|
1029
|
+
var CBAND_HEADER = /^(?<msgno>[A-Z]\d{2}[A-Z])(?<airline>[A-Z0-9]{2})(?<number>[0-9]{4})/;
|
|
1039
1030
|
var CBand = class extends DecoderPlugin {
|
|
1040
1031
|
name = "c-band";
|
|
1041
1032
|
qualifiers() {
|
|
@@ -1044,35 +1035,43 @@ var CBand = class extends DecoderPlugin {
|
|
|
1044
1035
|
};
|
|
1045
1036
|
}
|
|
1046
1037
|
decode(message, options = {}) {
|
|
1047
|
-
|
|
1038
|
+
const text = message.text;
|
|
1039
|
+
if (text.length < 10) {
|
|
1040
|
+
const result = this.defaultResult();
|
|
1041
|
+
result.decoder.name = this.name;
|
|
1042
|
+
result.message = message;
|
|
1043
|
+
return result;
|
|
1044
|
+
}
|
|
1045
|
+
const cband = CBAND_HEADER.exec(text);
|
|
1046
|
+
if (!cband?.groups) {
|
|
1047
|
+
const result = this.defaultResult();
|
|
1048
|
+
result.decoder.name = this.name;
|
|
1049
|
+
result.message = message;
|
|
1050
|
+
return result;
|
|
1051
|
+
}
|
|
1052
|
+
const decoded = this.decoder.decode(
|
|
1053
|
+
{
|
|
1054
|
+
label: message.label,
|
|
1055
|
+
sublabel: message.sublabel,
|
|
1056
|
+
text: text.substring(10)
|
|
1057
|
+
},
|
|
1058
|
+
options
|
|
1059
|
+
);
|
|
1060
|
+
const decodeResult = this.defaultResult();
|
|
1048
1061
|
decodeResult.decoder.name = this.name;
|
|
1049
1062
|
decodeResult.message = message;
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
const messageText = message.text.substring(10);
|
|
1055
|
-
const decoded = this.decoder.decode(
|
|
1056
|
-
{
|
|
1057
|
-
label: message.label,
|
|
1058
|
-
sublabel: message.sublabel,
|
|
1059
|
-
text: messageText
|
|
1060
|
-
},
|
|
1061
|
-
options
|
|
1063
|
+
if (decoded.decoded) {
|
|
1064
|
+
ResultFormatter.flightNumber(
|
|
1065
|
+
decodeResult,
|
|
1066
|
+
cband.groups.airline + Number(cband.groups.number)
|
|
1062
1067
|
);
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
decodeResult.decoder.name = this.name + "-" + decoded.decoder.name;
|
|
1071
|
-
decodeResult.raw = { ...decodeResult.raw, ...decoded.raw };
|
|
1072
|
-
decodeResult.formatted.description = decoded.formatted.description;
|
|
1073
|
-
decodeResult.formatted.items.push(...decoded.formatted.items);
|
|
1074
|
-
decodeResult.remaining = decoded.remaining;
|
|
1075
|
-
}
|
|
1068
|
+
decodeResult.decoded = true;
|
|
1069
|
+
decodeResult.decoder.decodeLevel = decoded.decoder.decodeLevel;
|
|
1070
|
+
decodeResult.decoder.name = this.name + "-" + decoded.decoder.name;
|
|
1071
|
+
decodeResult.raw = { ...decodeResult.raw, ...decoded.raw };
|
|
1072
|
+
decodeResult.formatted.description = decoded.formatted.description;
|
|
1073
|
+
decodeResult.formatted.items.push(...decoded.formatted.items);
|
|
1074
|
+
decodeResult.remaining = decoded.remaining;
|
|
1076
1075
|
}
|
|
1077
1076
|
return decodeResult;
|
|
1078
1077
|
}
|
|
@@ -1157,7 +1156,9 @@ var FlightPlanUtils = class _FlightPlanUtils {
|
|
|
1157
1156
|
label: "Route Status",
|
|
1158
1157
|
value: "Route Planned"
|
|
1159
1158
|
});
|
|
1160
|
-
|
|
1159
|
+
if (header.length > 2) {
|
|
1160
|
+
addRoute(decodeResult, header.substring(2));
|
|
1161
|
+
}
|
|
1161
1162
|
} else if (header.startsWith("RI")) {
|
|
1162
1163
|
decodeResult.raw.route_status = "RI";
|
|
1163
1164
|
decodeResult.formatted.items.push({
|
|
@@ -1235,7 +1236,11 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1235
1236
|
name = segments[0];
|
|
1236
1237
|
} else {
|
|
1237
1238
|
name = segments[0].slice(0, parens_idx);
|
|
1238
|
-
|
|
1239
|
+
const close_paren_idx = segments[0].indexOf(")");
|
|
1240
|
+
runway = segments[0].slice(
|
|
1241
|
+
parens_idx + 1,
|
|
1242
|
+
close_paren_idx === -1 ? void 0 : close_paren_idx
|
|
1243
|
+
);
|
|
1239
1244
|
}
|
|
1240
1245
|
let waypoints;
|
|
1241
1246
|
if (segments.length > 1) {
|
|
@@ -1255,6 +1260,11 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1255
1260
|
}
|
|
1256
1261
|
|
|
1257
1262
|
// lib/utils/arinc_702_helper.ts
|
|
1263
|
+
function asciiStringToBytes(data) {
|
|
1264
|
+
const bytes = new Uint8Array(data.length);
|
|
1265
|
+
for (let i = 0; i < data.length; i++) bytes[i] = data.charCodeAt(i) & 255;
|
|
1266
|
+
return bytes;
|
|
1267
|
+
}
|
|
1258
1268
|
var Arinc702Helper = class _Arinc702Helper {
|
|
1259
1269
|
/**
|
|
1260
1270
|
* Decodes an ARINC 702 message
|
|
@@ -1773,7 +1783,7 @@ function processSummary(decodeResult, data) {
|
|
|
1773
1783
|
}
|
|
1774
1784
|
function crc16IbmSdlcRev(data) {
|
|
1775
1785
|
let crc = 65535;
|
|
1776
|
-
const bytes =
|
|
1786
|
+
const bytes = asciiStringToBytes(data);
|
|
1777
1787
|
for (const byte of bytes) {
|
|
1778
1788
|
crc ^= byte;
|
|
1779
1789
|
for (let i = 0; i < 8; i++) {
|
|
@@ -1794,7 +1804,7 @@ function crc16IbmSdlcRev(data) {
|
|
|
1794
1804
|
function crc16Genibus(data) {
|
|
1795
1805
|
let crc = 65535;
|
|
1796
1806
|
const polynomial = 4129;
|
|
1797
|
-
const bytes =
|
|
1807
|
+
const bytes = asciiStringToBytes(data);
|
|
1798
1808
|
for (const byte of bytes) {
|
|
1799
1809
|
crc ^= byte << 8;
|
|
1800
1810
|
for (let i = 0; i < 8; i++) {
|
|
@@ -1819,6 +1829,7 @@ function processMessageReference(decodeResult, data) {
|
|
|
1819
1829
|
}
|
|
1820
1830
|
|
|
1821
1831
|
// lib/plugins/ARINC_702.ts
|
|
1832
|
+
var NEWLINE_REGEX = /[\n\r]/g;
|
|
1822
1833
|
var Arinc702 = class extends DecoderPlugin {
|
|
1823
1834
|
name = "arinc-702";
|
|
1824
1835
|
qualifiers() {
|
|
@@ -1830,7 +1841,7 @@ var Arinc702 = class extends DecoderPlugin {
|
|
|
1830
1841
|
let decodeResult = this.defaultResult();
|
|
1831
1842
|
decodeResult.decoder.name = this.name;
|
|
1832
1843
|
decodeResult.message = message;
|
|
1833
|
-
const msg = message.text.replace(
|
|
1844
|
+
const msg = message.text.replace(NEWLINE_REGEX, "");
|
|
1834
1845
|
let decoded = false;
|
|
1835
1846
|
decoded = Arinc702Helper.decodeH1Message(decodeResult, msg);
|
|
1836
1847
|
if (decoded) {
|
|
@@ -1897,6 +1908,12 @@ var Arinc702 = class extends DecoderPlugin {
|
|
|
1897
1908
|
}
|
|
1898
1909
|
};
|
|
1899
1910
|
|
|
1911
|
+
// lib/utils/acars_free_text.ts
|
|
1912
|
+
function formatAcarsFreeText(text) {
|
|
1913
|
+
if (!text) return "";
|
|
1914
|
+
return text.trim().replace(/\s+/g, " ");
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1900
1917
|
// lib/plugins/Label_5Z_Slash.ts
|
|
1901
1918
|
var Label_5Z_Slash = class extends DecoderPlugin {
|
|
1902
1919
|
name = "label-5z-slash";
|
|
@@ -1938,7 +1955,10 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
1938
1955
|
decodeResult.formatted.description = "Airline Designated Downlink";
|
|
1939
1956
|
const lines = message.text.split("\r\n");
|
|
1940
1957
|
if (lines[0] === "/TXT") {
|
|
1941
|
-
ResultFormatter.text(
|
|
1958
|
+
ResultFormatter.text(
|
|
1959
|
+
decodeResult,
|
|
1960
|
+
formatAcarsFreeText(lines.slice(1).join("\r\n"))
|
|
1961
|
+
);
|
|
1942
1962
|
decodeResult.decoded = true;
|
|
1943
1963
|
decodeResult.decoder.decodeLevel = "full";
|
|
1944
1964
|
return decodeResult;
|
|
@@ -2480,6 +2500,111 @@ var Label_15_FST = class extends DecoderPlugin {
|
|
|
2480
2500
|
}
|
|
2481
2501
|
};
|
|
2482
2502
|
|
|
2503
|
+
// lib/plugins/Label_16_AUTPOS.ts
|
|
2504
|
+
var Label_16_AUTPOS = class extends DecoderPlugin {
|
|
2505
|
+
name = "label-16-autpos";
|
|
2506
|
+
qualifiers() {
|
|
2507
|
+
return {
|
|
2508
|
+
labels: ["16"],
|
|
2509
|
+
preambles: [""]
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
decode(message) {
|
|
2513
|
+
let decodeResult = this.defaultResult();
|
|
2514
|
+
decodeResult.decoder.name = this.name;
|
|
2515
|
+
decodeResult.message = message;
|
|
2516
|
+
const regex = /^(\d{6})\/AUTPOS\/LLD (N|S)(\d{2})(\d{2})(\d{2}) (E|W)(\d{3})(\d{2})(\d{2})\s*\r?\n\/ALT (\d+)\/SAT ([*\-\d]{4})\r?\n\/WND ([*\d]{3})([\*\d]{3})\/TAT ([*\-\d]{4})\/TAS ([*\d]{3,4})\/CRZ ([*\d]{3,4})\r?\n\/FOB (\d{6})\r?\n\/DAT (\d{6})\/TIM (\d{6})/;
|
|
2517
|
+
const match = regex.exec(message.text);
|
|
2518
|
+
if (!match) {
|
|
2519
|
+
decodeResult.decoded = false;
|
|
2520
|
+
return decodeResult;
|
|
2521
|
+
}
|
|
2522
|
+
decodeResult.decoded = true;
|
|
2523
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2524
|
+
decodeResult.formatted.description = "Position Report";
|
|
2525
|
+
const [
|
|
2526
|
+
,
|
|
2527
|
+
flight,
|
|
2528
|
+
latHem,
|
|
2529
|
+
latDeg,
|
|
2530
|
+
latMin,
|
|
2531
|
+
latSec,
|
|
2532
|
+
lonHem,
|
|
2533
|
+
lonDeg,
|
|
2534
|
+
lonMin,
|
|
2535
|
+
lonSec,
|
|
2536
|
+
altitude,
|
|
2537
|
+
sat,
|
|
2538
|
+
windDir,
|
|
2539
|
+
windSpd,
|
|
2540
|
+
tat,
|
|
2541
|
+
tas,
|
|
2542
|
+
crz,
|
|
2543
|
+
fob,
|
|
2544
|
+
dat,
|
|
2545
|
+
tim
|
|
2546
|
+
] = match;
|
|
2547
|
+
ResultFormatter.day(decodeResult, parseInt(flight.slice(0, 2), 10));
|
|
2548
|
+
ResultFormatter.flightNumber(decodeResult, flight.slice(2));
|
|
2549
|
+
let latitude = CoordinateUtils.dmsToDecimalDegrees(
|
|
2550
|
+
parseInt(latDeg, 10),
|
|
2551
|
+
parseInt(latMin, 10),
|
|
2552
|
+
parseInt(latSec, 10)
|
|
2553
|
+
);
|
|
2554
|
+
if (latHem === "S") latitude = -latitude;
|
|
2555
|
+
let longitude = CoordinateUtils.dmsToDecimalDegrees(
|
|
2556
|
+
parseInt(lonDeg, 10),
|
|
2557
|
+
parseInt(lonMin, 10),
|
|
2558
|
+
parseInt(lonSec, 10)
|
|
2559
|
+
);
|
|
2560
|
+
if (lonHem === "W") longitude = -longitude;
|
|
2561
|
+
ResultFormatter.position(decodeResult, {
|
|
2562
|
+
latitude,
|
|
2563
|
+
longitude
|
|
2564
|
+
});
|
|
2565
|
+
const alt = parseInt(altitude, 10);
|
|
2566
|
+
ResultFormatter.altitude(decodeResult, alt);
|
|
2567
|
+
if (!windSpd.includes("*") && !windDir.includes("*")) {
|
|
2568
|
+
ResultFormatter.windData(decodeResult, [
|
|
2569
|
+
{
|
|
2570
|
+
waypoint: {
|
|
2571
|
+
name: "POSITION"
|
|
2572
|
+
},
|
|
2573
|
+
flightLevel: Math.round(alt / 100),
|
|
2574
|
+
windDirection: parseInt(windDir, 10),
|
|
2575
|
+
windSpeed: parseInt(windSpd, 10)
|
|
2576
|
+
}
|
|
2577
|
+
]);
|
|
2578
|
+
}
|
|
2579
|
+
if (!tat.includes("*")) {
|
|
2580
|
+
ResultFormatter.totalAirTemp(decodeResult, tat);
|
|
2581
|
+
}
|
|
2582
|
+
if (!tas.includes("*")) {
|
|
2583
|
+
ResultFormatter.airspeed(decodeResult, parseInt(tas, 10));
|
|
2584
|
+
}
|
|
2585
|
+
if (!sat.includes("*")) {
|
|
2586
|
+
ResultFormatter.temperature(decodeResult, sat);
|
|
2587
|
+
}
|
|
2588
|
+
if (!crz.includes("*")) {
|
|
2589
|
+
ResultFormatter.mach(decodeResult, parseInt(crz, 10) / 1e3);
|
|
2590
|
+
}
|
|
2591
|
+
if (!fob.includes("*")) {
|
|
2592
|
+
ResultFormatter.currentFuel(decodeResult, parseInt(fob, 10));
|
|
2593
|
+
}
|
|
2594
|
+
if (!dat.includes("*") && !tim.includes("*")) {
|
|
2595
|
+
const yy = dat.slice(0, 2);
|
|
2596
|
+
const mm = dat.slice(2, 4);
|
|
2597
|
+
const dd = dat.slice(4, 6);
|
|
2598
|
+
const ddmmyy = `${dd}${mm}${yy}`;
|
|
2599
|
+
ResultFormatter.timestamp(
|
|
2600
|
+
decodeResult,
|
|
2601
|
+
DateTimeUtils.convertDateTimeToEpoch(tim, ddmmyy)
|
|
2602
|
+
);
|
|
2603
|
+
}
|
|
2604
|
+
return decodeResult;
|
|
2605
|
+
}
|
|
2606
|
+
};
|
|
2607
|
+
|
|
2483
2608
|
// lib/plugins/Label_16_Honeywell.ts
|
|
2484
2609
|
var Label_16_Honeywell = class extends DecoderPlugin {
|
|
2485
2610
|
name = "label-16-honeywell";
|
|
@@ -3254,7 +3379,7 @@ var Label_2P_FM3 = class extends DecoderPlugin {
|
|
|
3254
3379
|
const parts = message.text.split(",");
|
|
3255
3380
|
if (parts.length === 7) {
|
|
3256
3381
|
const header = parts[0].split("FM3 ");
|
|
3257
|
-
if (header.length
|
|
3382
|
+
if (header.length < 2) {
|
|
3258
3383
|
ResultFormatter.unknown(decodeResult, message.text);
|
|
3259
3384
|
decodeResult.decoded = false;
|
|
3260
3385
|
decodeResult.decoder.decodeLevel = "none";
|
|
@@ -3325,7 +3450,7 @@ var Label_2P_FM4 = class extends DecoderPlugin {
|
|
|
3325
3450
|
const parts = message.text.split(",");
|
|
3326
3451
|
if (parts.length === 10) {
|
|
3327
3452
|
const header = parts[0].split("FM4");
|
|
3328
|
-
if (header.length
|
|
3453
|
+
if (header.length < 2) {
|
|
3329
3454
|
ResultFormatter.unknown(decodeResult, message.text);
|
|
3330
3455
|
decodeResult.decoded = false;
|
|
3331
3456
|
decodeResult.decoder.decodeLevel = "none";
|
|
@@ -3384,7 +3509,7 @@ var Label_2P_FM5 = class extends DecoderPlugin {
|
|
|
3384
3509
|
const parts = message.text.split(",");
|
|
3385
3510
|
if (parts.length === 12) {
|
|
3386
3511
|
const header = parts[0].split("FM5 ");
|
|
3387
|
-
if (header.length
|
|
3512
|
+
if (header.length < 2) {
|
|
3388
3513
|
ResultFormatter.unknown(decodeResult, message.text);
|
|
3389
3514
|
decodeResult.decoded = false;
|
|
3390
3515
|
decodeResult.decoder.decodeLevel = "none";
|
|
@@ -3807,7 +3932,8 @@ var Label_4A = class extends DecoderPlugin {
|
|
|
3807
3932
|
ResultFormatter.arrivalAirport(decodeResult, fields[5]);
|
|
3808
3933
|
ResultFormatter.unknownArr(decodeResult, fields.slice(8));
|
|
3809
3934
|
} else if (fields.length === 6) {
|
|
3810
|
-
|
|
3935
|
+
const f0 = fields[0];
|
|
3936
|
+
if (f0.length > 0 && (f0[0] === "N" || f0[0] === "S")) {
|
|
3811
3937
|
ResultFormatter.position(
|
|
3812
3938
|
decodeResult,
|
|
3813
3939
|
CoordinateUtils.decodeStringCoordinates(fields[0].substring(0, 13))
|
|
@@ -4188,6 +4314,9 @@ var Label_4T_ETA = class extends DecoderPlugin {
|
|
|
4188
4314
|
};
|
|
4189
4315
|
|
|
4190
4316
|
// lib/plugins/Label_80.ts
|
|
4317
|
+
var POS_REGEX = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
|
|
4318
|
+
var WS_REGEX = /\s+/;
|
|
4319
|
+
var NEWLINE_REGEX2 = /\r?\n/;
|
|
4191
4320
|
var Label_80 = class extends DecoderPlugin {
|
|
4192
4321
|
name = "label-80";
|
|
4193
4322
|
qualifiers() {
|
|
@@ -4201,7 +4330,7 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4201
4330
|
message,
|
|
4202
4331
|
"Airline Defined Position Report"
|
|
4203
4332
|
);
|
|
4204
|
-
const lines = message.text.split(
|
|
4333
|
+
const lines = message.text.split(NEWLINE_REGEX2);
|
|
4205
4334
|
if (lines.length === 1 && lines[0].includes(",")) {
|
|
4206
4335
|
this.parseCsvFormat(lines[0], decodeResult);
|
|
4207
4336
|
} else {
|
|
@@ -4236,7 +4365,7 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4236
4365
|
ResultFormatter.unknown(results, header, "/");
|
|
4237
4366
|
return;
|
|
4238
4367
|
}
|
|
4239
|
-
const msgInfo = fields[0].split(
|
|
4368
|
+
const msgInfo = fields[0].split(WS_REGEX);
|
|
4240
4369
|
if (msgInfo.length === 3) {
|
|
4241
4370
|
ResultFormatter.unknownArr(results, msgInfo.slice(0, 2), " ");
|
|
4242
4371
|
ResultFormatter.flightNumber(results, msgInfo[2]);
|
|
@@ -4244,14 +4373,14 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4244
4373
|
ResultFormatter.unknown(results, header, "/");
|
|
4245
4374
|
return;
|
|
4246
4375
|
}
|
|
4247
|
-
const otherInfo1 = fields[1].split(
|
|
4376
|
+
const otherInfo1 = fields[1].split(WS_REGEX);
|
|
4248
4377
|
if (otherInfo1.length === 2) {
|
|
4249
4378
|
ResultFormatter.day(results, parseInt(otherInfo1[0], 10));
|
|
4250
4379
|
ResultFormatter.departureAirport(results, otherInfo1[1]);
|
|
4251
4380
|
} else {
|
|
4252
4381
|
ResultFormatter.unknownArr(results, otherInfo1, " ");
|
|
4253
4382
|
}
|
|
4254
|
-
const otherInfo2 = fields[2].split(
|
|
4383
|
+
const otherInfo2 = fields[2].split(WS_REGEX);
|
|
4255
4384
|
if (otherInfo2.length === 2) {
|
|
4256
4385
|
ResultFormatter.arrivalAirport(results, otherInfo2[0]);
|
|
4257
4386
|
ResultFormatter.tail(results, otherInfo2[1].replace(".", ""));
|
|
@@ -4263,7 +4392,7 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4263
4392
|
}
|
|
4264
4393
|
}
|
|
4265
4394
|
parseTags(part, results) {
|
|
4266
|
-
const kvPair = part.split(
|
|
4395
|
+
const kvPair = part.split(WS_REGEX);
|
|
4267
4396
|
if (kvPair.length < 2) {
|
|
4268
4397
|
ResultFormatter.unknown(results, part, "/");
|
|
4269
4398
|
return;
|
|
@@ -4271,9 +4400,8 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4271
4400
|
const tag = kvPair[0];
|
|
4272
4401
|
const val = kvPair.slice(1).join(" ");
|
|
4273
4402
|
switch (tag) {
|
|
4274
|
-
case "POS":
|
|
4275
|
-
const
|
|
4276
|
-
const posResult = val.match(posRegex);
|
|
4403
|
+
case "POS": {
|
|
4404
|
+
const posResult = POS_REGEX.exec(val);
|
|
4277
4405
|
const lat = Number(posResult?.groups?.lat) * (posResult?.groups?.latd === "S" ? -1 : 1);
|
|
4278
4406
|
const lon = Number(posResult?.groups?.lng) * (posResult?.groups?.lngd === "W" ? -1 : 1);
|
|
4279
4407
|
const position = {
|
|
@@ -4282,6 +4410,7 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4282
4410
|
};
|
|
4283
4411
|
ResultFormatter.position(results, position);
|
|
4284
4412
|
break;
|
|
4413
|
+
}
|
|
4285
4414
|
case "ALT":
|
|
4286
4415
|
ResultFormatter.altitude(results, parseInt(val.replace("+", ""), 10));
|
|
4287
4416
|
break;
|
|
@@ -4314,10 +4443,11 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4314
4443
|
DateTimeUtils.convertHHMMSSToTod(val)
|
|
4315
4444
|
);
|
|
4316
4445
|
break;
|
|
4317
|
-
case "ETA":
|
|
4446
|
+
case "ETA": {
|
|
4318
4447
|
const hhmm = val.split(".")[0].replace(":", "");
|
|
4319
4448
|
ResultFormatter.eta(results, DateTimeUtils.convertHHMMSSToTod(hhmm));
|
|
4320
4449
|
break;
|
|
4450
|
+
}
|
|
4321
4451
|
case "HDG":
|
|
4322
4452
|
ResultFormatter.heading(results, parseInt(val, 10));
|
|
4323
4453
|
break;
|
|
@@ -4341,7 +4471,7 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4341
4471
|
if (csvParts.length !== 9) {
|
|
4342
4472
|
return;
|
|
4343
4473
|
}
|
|
4344
|
-
const header = csvParts[0].trim().split(
|
|
4474
|
+
const header = csvParts[0].trim().split(WS_REGEX);
|
|
4345
4475
|
ResultFormatter.unknown(results, header[0], " ");
|
|
4346
4476
|
ResultFormatter.unknown(results, header[1], " ");
|
|
4347
4477
|
ResultFormatter.position(
|
|
@@ -4364,6 +4494,9 @@ var Label_80 = class extends DecoderPlugin {
|
|
|
4364
4494
|
};
|
|
4365
4495
|
|
|
4366
4496
|
// lib/plugins/Label_83.ts
|
|
4497
|
+
var WS_REGEX2 = /\s+/;
|
|
4498
|
+
var ALL_WS_REGEX = /\s/g;
|
|
4499
|
+
var ALL_DOTS_REGEX = /\./g;
|
|
4367
4500
|
var Label_83 = class extends DecoderPlugin {
|
|
4368
4501
|
name = "label-83";
|
|
4369
4502
|
qualifiers() {
|
|
@@ -4378,8 +4511,8 @@ var Label_83 = class extends DecoderPlugin {
|
|
|
4378
4511
|
decodeResult.formatted.description = "Airline Defined";
|
|
4379
4512
|
decodeResult.decoded = true;
|
|
4380
4513
|
const text = message.text;
|
|
4381
|
-
if (text.
|
|
4382
|
-
const fields = text.split(
|
|
4514
|
+
if (text.startsWith("4DH3 ETAT2")) {
|
|
4515
|
+
const fields = text.split(WS_REGEX2);
|
|
4383
4516
|
if (fields[2].length > 5) {
|
|
4384
4517
|
decodeResult.raw.day = fields[2].substring(5);
|
|
4385
4518
|
}
|
|
@@ -4387,15 +4520,15 @@ var Label_83 = class extends DecoderPlugin {
|
|
|
4387
4520
|
const subfields = fields[3].split("/");
|
|
4388
4521
|
ResultFormatter.departureAirport(decodeResult, subfields[0]);
|
|
4389
4522
|
ResultFormatter.arrivalAirport(decodeResult, subfields[1]);
|
|
4390
|
-
ResultFormatter.tail(decodeResult, fields[4].replace(
|
|
4523
|
+
ResultFormatter.tail(decodeResult, fields[4].replace(ALL_DOTS_REGEX, ""));
|
|
4391
4524
|
ResultFormatter.eta(
|
|
4392
4525
|
decodeResult,
|
|
4393
4526
|
DateTimeUtils.convertHHMMSSToTod(fields[6] + "00")
|
|
4394
4527
|
);
|
|
4395
|
-
} else if (text.
|
|
4528
|
+
} else if (text.startsWith("001PR")) {
|
|
4396
4529
|
decodeResult.raw.day = text.substring(5, 7);
|
|
4397
4530
|
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
|
|
4398
|
-
text.substring(13, 28).replace(
|
|
4531
|
+
text.substring(13, 28).replace(ALL_DOTS_REGEX, "")
|
|
4399
4532
|
);
|
|
4400
4533
|
if (position) {
|
|
4401
4534
|
ResultFormatter.position(decodeResult, position);
|
|
@@ -4403,15 +4536,15 @@ var Label_83 = class extends DecoderPlugin {
|
|
|
4403
4536
|
ResultFormatter.altitude(decodeResult, Number(text.substring(28, 33)));
|
|
4404
4537
|
ResultFormatter.unknown(decodeResult, text.substring(33));
|
|
4405
4538
|
} else {
|
|
4406
|
-
const fields = text.replace(
|
|
4539
|
+
const fields = text.replace(ALL_WS_REGEX, "").split(",");
|
|
4407
4540
|
if (fields.length === 9) {
|
|
4408
4541
|
ResultFormatter.departureAirport(decodeResult, fields[0]);
|
|
4409
4542
|
ResultFormatter.arrivalAirport(decodeResult, fields[1]);
|
|
4410
4543
|
decodeResult.raw.day = fields[2].substring(0, 2);
|
|
4411
4544
|
decodeResult.raw.time = fields[2].substring(2);
|
|
4412
4545
|
ResultFormatter.position(decodeResult, {
|
|
4413
|
-
latitude: Number(fields[3]
|
|
4414
|
-
longitude: Number(fields[4]
|
|
4546
|
+
latitude: Number(fields[3]),
|
|
4547
|
+
longitude: Number(fields[4])
|
|
4415
4548
|
});
|
|
4416
4549
|
ResultFormatter.altitude(decodeResult, Number(fields[5]));
|
|
4417
4550
|
ResultFormatter.groundspeed(decodeResult, Number(fields[6]));
|
|
@@ -4475,13 +4608,15 @@ var Label_B6_Forwardslash = class extends DecoderPlugin {
|
|
|
4475
4608
|
};
|
|
4476
4609
|
}
|
|
4477
4610
|
decode(message, options = {}) {
|
|
4478
|
-
const decodeResult = this.
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4611
|
+
const decodeResult = this.initResult(message, "CPDLC Message");
|
|
4612
|
+
const body = message.text.substring(1);
|
|
4613
|
+
if (body.length > 0) {
|
|
4614
|
+
ResultFormatter.text(decodeResult, body);
|
|
4615
|
+
this.setDecodeLevel(decodeResult, true, "partial");
|
|
4616
|
+
} else {
|
|
4617
|
+
this.setDecodeLevel(decodeResult, false);
|
|
4484
4618
|
}
|
|
4619
|
+
this.debug(options, "CPDLC body:", body);
|
|
4485
4620
|
return decodeResult;
|
|
4486
4621
|
}
|
|
4487
4622
|
};
|
|
@@ -4631,6 +4766,7 @@ var Label_H1_ATIS = class extends DecoderPlugin {
|
|
|
4631
4766
|
const checksum = match[6];
|
|
4632
4767
|
ResultFormatter.flightNumber(decodeResult, flight);
|
|
4633
4768
|
ResultFormatter.arrivalAirport(decodeResult, facility);
|
|
4769
|
+
ResultFormatter.sequenceNumber(decodeResult, parseInt(seq, 10));
|
|
4634
4770
|
decodeResult.raw.atis_code = code;
|
|
4635
4771
|
decodeResult.formatted.items.push({
|
|
4636
4772
|
type: "atis",
|
|
@@ -4840,9 +4976,39 @@ var Label_H1_M_POS = class extends DecoderPlugin {
|
|
|
4840
4976
|
}
|
|
4841
4977
|
};
|
|
4842
4978
|
|
|
4979
|
+
// lib/utils/compression.ts
|
|
4980
|
+
import * as pako from "pako";
|
|
4981
|
+
function inflateData(data, raw) {
|
|
4982
|
+
const chunks = [];
|
|
4983
|
+
const inflator = new pako.Inflate({ windowBits: raw ? -15 : 15 });
|
|
4984
|
+
inflator.onData = (chunk) => {
|
|
4985
|
+
chunks.push(chunk);
|
|
4986
|
+
};
|
|
4987
|
+
inflator.push(data, 2);
|
|
4988
|
+
if (chunks.length === 0) return void 0;
|
|
4989
|
+
if (chunks.length === 1) return chunks[0];
|
|
4990
|
+
const totalLen = chunks.reduce((sum, c) => sum + c.length, 0);
|
|
4991
|
+
const result = new Uint8Array(totalLen);
|
|
4992
|
+
let offset = 0;
|
|
4993
|
+
for (const chunk of chunks) {
|
|
4994
|
+
result.set(chunk, offset);
|
|
4995
|
+
offset += chunk.length;
|
|
4996
|
+
}
|
|
4997
|
+
return result;
|
|
4998
|
+
}
|
|
4999
|
+
function base64ToUint8Array(base64) {
|
|
5000
|
+
const cleaned = base64.replace(/-/g, "+").replace(/_/g, "/").replace(/[^A-Za-z0-9+/]/g, "");
|
|
5001
|
+
const padded = cleaned + "=".repeat((4 - cleaned.length % 4) % 4);
|
|
5002
|
+
const binary = atob(padded);
|
|
5003
|
+
const bytes = new Uint8Array(binary.length);
|
|
5004
|
+
for (let i = 0; i < binary.length; i++) {
|
|
5005
|
+
bytes[i] = binary.charCodeAt(i);
|
|
5006
|
+
}
|
|
5007
|
+
return bytes;
|
|
5008
|
+
}
|
|
5009
|
+
|
|
4843
5010
|
// lib/plugins/Label_H1_OHMA.ts
|
|
4844
|
-
|
|
4845
|
-
import { Buffer as Buffer2 } from "buffer";
|
|
5011
|
+
var textDecoder = new TextDecoder();
|
|
4846
5012
|
var Label_H1_OHMA = class extends DecoderPlugin {
|
|
4847
5013
|
name = "label-h1-ohma";
|
|
4848
5014
|
qualifiers() {
|
|
@@ -4858,12 +5024,12 @@ var Label_H1_OHMA = class extends DecoderPlugin {
|
|
|
4858
5024
|
decodeResult.message = message;
|
|
4859
5025
|
const data = message.text.split("OHMA")[1];
|
|
4860
5026
|
try {
|
|
4861
|
-
const compressedBuffer =
|
|
4862
|
-
const
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
const jsonText = result
|
|
5027
|
+
const compressedBuffer = base64ToUint8Array(data);
|
|
5028
|
+
const result = inflateData(compressedBuffer, false);
|
|
5029
|
+
if (!result || result.length === 0) {
|
|
5030
|
+
throw new Error("Decompression produced no output");
|
|
5031
|
+
}
|
|
5032
|
+
const jsonText = textDecoder.decode(result);
|
|
4867
5033
|
let formattedMsg;
|
|
4868
5034
|
let jsonMessage;
|
|
4869
5035
|
try {
|
|
@@ -5268,10 +5434,47 @@ var Label_HX = class extends DecoderPlugin {
|
|
|
5268
5434
|
}
|
|
5269
5435
|
};
|
|
5270
5436
|
|
|
5437
|
+
// lib/utils/ascii85.ts
|
|
5438
|
+
function ascii85Decode(input) {
|
|
5439
|
+
let str = input;
|
|
5440
|
+
if (str.startsWith("<~")) str = str.slice(2);
|
|
5441
|
+
if (str.endsWith("~>")) str = str.slice(0, -2);
|
|
5442
|
+
str = str.replace(/\s/g, "");
|
|
5443
|
+
if (str.length === 0) return new Uint8Array(0);
|
|
5444
|
+
const output = [];
|
|
5445
|
+
let i = 0;
|
|
5446
|
+
while (i < str.length) {
|
|
5447
|
+
if (str[i] === "z") {
|
|
5448
|
+
output.push(0, 0, 0, 0);
|
|
5449
|
+
i++;
|
|
5450
|
+
continue;
|
|
5451
|
+
}
|
|
5452
|
+
const remaining = str.length - i;
|
|
5453
|
+
const chunkLen = Math.min(5, remaining);
|
|
5454
|
+
if (chunkLen === 1) break;
|
|
5455
|
+
let padded = str.slice(i, i + chunkLen);
|
|
5456
|
+
while (padded.length < 5) padded += "u";
|
|
5457
|
+
let value = 0;
|
|
5458
|
+
for (let j = 0; j < 5; j++) {
|
|
5459
|
+
const digit = padded.charCodeAt(j) - 33;
|
|
5460
|
+
if (digit < 0 || digit > 84) return null;
|
|
5461
|
+
value = value * 85 + digit;
|
|
5462
|
+
}
|
|
5463
|
+
if (chunkLen === 5 && value > 4294967295) return null;
|
|
5464
|
+
const v = value >>> 0;
|
|
5465
|
+
const numBytes = chunkLen === 5 ? 4 : chunkLen - 1;
|
|
5466
|
+
if (numBytes >= 1) output.push(v >>> 24 & 255);
|
|
5467
|
+
if (numBytes >= 2) output.push(v >>> 16 & 255);
|
|
5468
|
+
if (numBytes >= 3) output.push(v >>> 8 & 255);
|
|
5469
|
+
if (numBytes >= 4) output.push(v & 255);
|
|
5470
|
+
i += chunkLen;
|
|
5471
|
+
}
|
|
5472
|
+
return new Uint8Array(output);
|
|
5473
|
+
}
|
|
5474
|
+
|
|
5271
5475
|
// lib/utils/miam.ts
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
import { Buffer as Buffer3 } from "buffer";
|
|
5476
|
+
var textDecoder2 = new TextDecoder();
|
|
5477
|
+
var textEncoder = new TextEncoder();
|
|
5275
5478
|
var MIAMVersion = /* @__PURE__ */ ((MIAMVersion2) => {
|
|
5276
5479
|
MIAMVersion2[MIAMVersion2["V1"] = 1] = "V1";
|
|
5277
5480
|
MIAMVersion2[MIAMVersion2["V2"] = 2] = "V2";
|
|
@@ -5358,7 +5561,7 @@ var MIAMCoreUtils = class {
|
|
|
5358
5561
|
error: "Empty MIAM message header"
|
|
5359
5562
|
};
|
|
5360
5563
|
}
|
|
5361
|
-
let hdr =
|
|
5564
|
+
let hdr = ascii85Decode("<~" + rawHdr + "~>");
|
|
5362
5565
|
if (!hdr || hdr.length < hpad) {
|
|
5363
5566
|
return {
|
|
5364
5567
|
decoded: false,
|
|
@@ -5370,17 +5573,24 @@ var MIAMCoreUtils = class {
|
|
|
5370
5573
|
if (rawBody.length > 0) {
|
|
5371
5574
|
if ("0123".indexOf(bpad) >= 0) {
|
|
5372
5575
|
const bpadValue = parseInt(bpad);
|
|
5373
|
-
|
|
5374
|
-
if (
|
|
5576
|
+
const decoded = ascii85Decode("<~" + rawBody + "~>");
|
|
5577
|
+
if (decoded === null) {
|
|
5578
|
+
return {
|
|
5579
|
+
decoded: false,
|
|
5580
|
+
error: "Ascii85 decode failed for MIAM message body"
|
|
5581
|
+
};
|
|
5582
|
+
}
|
|
5583
|
+
body = decoded;
|
|
5584
|
+
if (body.length >= bpadValue) {
|
|
5375
5585
|
body = body.subarray(0, body.length - bpadValue);
|
|
5376
5586
|
}
|
|
5377
5587
|
} else if (bpad === "-") {
|
|
5378
|
-
body =
|
|
5588
|
+
body = textEncoder.encode(rawBody);
|
|
5379
5589
|
}
|
|
5380
5590
|
}
|
|
5381
5591
|
hdr = hdr.subarray(0, hdr.length - hpad);
|
|
5382
|
-
const version = hdr
|
|
5383
|
-
const pduType = hdr
|
|
5592
|
+
const version = hdr[0] & 15;
|
|
5593
|
+
const pduType = hdr[0] >> 4 & 15;
|
|
5384
5594
|
if (isMIAMVersion(version) && isMIAMCorePdu(pduType)) {
|
|
5385
5595
|
const versionPduHandler = this.VersionPduHandlerTable[version][pduType];
|
|
5386
5596
|
return versionPduHandler(hdr, body);
|
|
@@ -5677,7 +5887,7 @@ var MIAMCoreUtils = class {
|
|
|
5677
5887
|
];
|
|
5678
5888
|
let crc = (seed || 0) & 65535;
|
|
5679
5889
|
for (let i = 0; i < buf.length; i++) {
|
|
5680
|
-
crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 8 ^ buf
|
|
5890
|
+
crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 8 ^ buf[i]) >>> 0 & 255]) >>> 0;
|
|
5681
5891
|
}
|
|
5682
5892
|
return crc & 65535;
|
|
5683
5893
|
}
|
|
@@ -5942,7 +6152,7 @@ var MIAMCoreUtils = class {
|
|
|
5942
6152
|
];
|
|
5943
6153
|
let crc = seed || 0;
|
|
5944
6154
|
for (let i = 0; i < buf.length; i++) {
|
|
5945
|
-
crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 24 ^ buf
|
|
6155
|
+
crc = (crc << 8 >>> 0 ^ crctable[(crc >>> 24 ^ buf[i]) >>> 0]) >>> 0;
|
|
5946
6156
|
}
|
|
5947
6157
|
return crc;
|
|
5948
6158
|
}
|
|
@@ -5979,7 +6189,7 @@ var MIAMCoreUtils = class {
|
|
|
5979
6189
|
let msgNum = 0;
|
|
5980
6190
|
let ackOptions = 0;
|
|
5981
6191
|
if (version === 1 /* V1 */) {
|
|
5982
|
-
pduSize = hdr
|
|
6192
|
+
pduSize = hdr[1] << 16 | hdr[2] << 8 | hdr[3];
|
|
5983
6193
|
const msgSize = hdr.length + (body === void 0 ? 0 : body.length);
|
|
5984
6194
|
if (pduSize > msgSize) {
|
|
5985
6195
|
pduIsComplete = false;
|
|
@@ -5988,17 +6198,17 @@ var MIAMCoreUtils = class {
|
|
|
5988
6198
|
);
|
|
5989
6199
|
}
|
|
5990
6200
|
hdr = hdr.subarray(4);
|
|
5991
|
-
tail = hdr.subarray(0, 7)
|
|
6201
|
+
tail = textDecoder2.decode(hdr.subarray(0, 7));
|
|
5992
6202
|
hdr = hdr.subarray(7);
|
|
5993
6203
|
} else if (version === 2 /* V2 */) {
|
|
5994
6204
|
hdr = hdr.subarray(1);
|
|
5995
6205
|
}
|
|
5996
|
-
msgNum = hdr
|
|
5997
|
-
ackOptions = hdr
|
|
6206
|
+
msgNum = hdr[0] >> 1 & 127;
|
|
6207
|
+
ackOptions = hdr[0] & 1;
|
|
5998
6208
|
hdr = hdr.subarray(1);
|
|
5999
|
-
pduCompression = (hdr
|
|
6000
|
-
pduEncoding = hdr
|
|
6001
|
-
pduAppType = hdr
|
|
6209
|
+
pduCompression = (hdr[0] << 2 | hdr[1] >> 6 & 3) & 7;
|
|
6210
|
+
pduEncoding = hdr[1] >> 4 & 3;
|
|
6211
|
+
pduAppType = hdr[1] & 15;
|
|
6002
6212
|
hdr = hdr.subarray(2);
|
|
6003
6213
|
let appIdLen;
|
|
6004
6214
|
if (isMIAMCoreApp(pduAppType)) {
|
|
@@ -6024,12 +6234,12 @@ var MIAMCoreUtils = class {
|
|
|
6024
6234
|
error: "Header too short for v" + version + " appType: " + pduAppType
|
|
6025
6235
|
};
|
|
6026
6236
|
}
|
|
6027
|
-
pduAppId = hdr.subarray(0, appIdLen)
|
|
6237
|
+
pduAppId = textDecoder2.decode(hdr.subarray(0, appIdLen));
|
|
6028
6238
|
hdr = hdr.subarray(appIdLen);
|
|
6029
6239
|
if (crcLen === 4) {
|
|
6030
|
-
pduCrc = hdr
|
|
6240
|
+
pduCrc = hdr[0] << 24 | hdr[1] << 16 | hdr[2] << 8 | hdr[3];
|
|
6031
6241
|
} else if (crcLen === 2) {
|
|
6032
|
-
pduCrc = hdr
|
|
6242
|
+
pduCrc = hdr[0] << 8 | hdr[1];
|
|
6033
6243
|
}
|
|
6034
6244
|
hdr = hdr.subarray(crcLen);
|
|
6035
6245
|
if (body !== void 0 && body.length > 0) {
|
|
@@ -6037,10 +6247,12 @@ var MIAMCoreUtils = class {
|
|
|
6037
6247
|
pduCompression
|
|
6038
6248
|
) >= 0) {
|
|
6039
6249
|
try {
|
|
6040
|
-
const
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6250
|
+
const inflated = inflateData(body, true);
|
|
6251
|
+
if (inflated === void 0) {
|
|
6252
|
+
pduErrors.push("Inflation produced no output for body");
|
|
6253
|
+
} else {
|
|
6254
|
+
pduData = inflated;
|
|
6255
|
+
}
|
|
6044
6256
|
} catch (e) {
|
|
6045
6257
|
pduErrors.push("Inflation failed for body: " + e);
|
|
6046
6258
|
}
|
|
@@ -6098,12 +6310,12 @@ var MIAMCoreUtils = class {
|
|
|
6098
6310
|
label,
|
|
6099
6311
|
...sublabel ? { sublabel } : {},
|
|
6100
6312
|
...mfi ? { mfi } : {},
|
|
6101
|
-
...pduData ? { text:
|
|
6313
|
+
...pduData ? { text: textDecoder2.decode(pduData) } : {}
|
|
6102
6314
|
};
|
|
6103
6315
|
} else {
|
|
6104
6316
|
pdu.non_acars = {
|
|
6105
6317
|
appId: pduAppId,
|
|
6106
|
-
...pduData ? { text:
|
|
6318
|
+
...pduData ? { text: textDecoder2.decode(pduData) } : {}
|
|
6107
6319
|
};
|
|
6108
6320
|
}
|
|
6109
6321
|
return {
|
|
@@ -6479,6 +6691,7 @@ var pluginClasses = [
|
|
|
6479
6691
|
Label_13Through18_Slash,
|
|
6480
6692
|
Label_15,
|
|
6481
6693
|
Label_15_FST,
|
|
6694
|
+
Label_16_AUTPOS,
|
|
6482
6695
|
Label_16_Honeywell,
|
|
6483
6696
|
Label_16_N_Space,
|
|
6484
6697
|
Label_16_POSA1,
|
|
@@ -6538,10 +6751,12 @@ var MessageDecoder = class {
|
|
|
6538
6751
|
name;
|
|
6539
6752
|
plugins;
|
|
6540
6753
|
debug;
|
|
6541
|
-
/** Maps a label string to the
|
|
6542
|
-
|
|
6543
|
-
/**
|
|
6544
|
-
|
|
6754
|
+
/** Maps a label string to the candidate entries (wildcard + label-specific) in registration order. */
|
|
6755
|
+
candidatesByLabel = /* @__PURE__ */ new Map();
|
|
6756
|
+
/** Wildcard entries (plugins that register the '*' label). */
|
|
6757
|
+
wildcardEntries = [];
|
|
6758
|
+
/** Membership set for wildcard entries to dedupe when a plugin also registers a specific label. */
|
|
6759
|
+
wildcardSet = /* @__PURE__ */ new Set();
|
|
6545
6760
|
constructor() {
|
|
6546
6761
|
this.name = "acars-decoder-typescript";
|
|
6547
6762
|
this.plugins = [];
|
|
@@ -6553,40 +6768,41 @@ var MessageDecoder = class {
|
|
|
6553
6768
|
registerPlugin(plugin) {
|
|
6554
6769
|
this.plugins.push(plugin);
|
|
6555
6770
|
const qualifiers = plugin.qualifiers();
|
|
6771
|
+
const entry = {
|
|
6772
|
+
plugin,
|
|
6773
|
+
preambles: qualifiers.preambles && qualifiers.preambles.length > 0 ? qualifiers.preambles : void 0
|
|
6774
|
+
};
|
|
6556
6775
|
for (const label of qualifiers.labels) {
|
|
6557
6776
|
if (label === "*") {
|
|
6558
|
-
this.
|
|
6777
|
+
if (!this.wildcardSet.has(plugin)) {
|
|
6778
|
+
this.wildcardEntries.push(entry);
|
|
6779
|
+
this.wildcardSet.add(plugin);
|
|
6780
|
+
const wildcardInsertIndex = this.wildcardEntries.length - 1;
|
|
6781
|
+
for (const bucket of this.candidatesByLabel.values()) {
|
|
6782
|
+
bucket.splice(wildcardInsertIndex, 0, entry);
|
|
6783
|
+
}
|
|
6784
|
+
}
|
|
6559
6785
|
} else {
|
|
6560
|
-
let bucket = this.
|
|
6786
|
+
let bucket = this.candidatesByLabel.get(label);
|
|
6561
6787
|
if (!bucket) {
|
|
6562
|
-
bucket =
|
|
6563
|
-
this.
|
|
6788
|
+
bucket = this.wildcardEntries.slice();
|
|
6789
|
+
this.candidatesByLabel.set(label, bucket);
|
|
6790
|
+
}
|
|
6791
|
+
if (!this.wildcardSet.has(plugin)) {
|
|
6792
|
+
bucket.push(entry);
|
|
6564
6793
|
}
|
|
6565
|
-
bucket.push(plugin);
|
|
6566
6794
|
}
|
|
6567
6795
|
}
|
|
6568
6796
|
return true;
|
|
6569
6797
|
}
|
|
6570
6798
|
decode(message, options = {}) {
|
|
6571
|
-
const
|
|
6572
|
-
const
|
|
6573
|
-
const candidates = [];
|
|
6574
|
-
for (const plugin of [...this.wildcardPlugins, ...labelPlugins]) {
|
|
6575
|
-
if (!seen.has(plugin)) {
|
|
6576
|
-
seen.add(plugin);
|
|
6577
|
-
candidates.push(plugin);
|
|
6578
|
-
}
|
|
6579
|
-
}
|
|
6580
|
-
const usablePlugins = candidates.filter((plugin) => {
|
|
6581
|
-
const preambles = plugin.qualifiers().preambles;
|
|
6582
|
-
if (!preambles || preambles.length === 0) {
|
|
6583
|
-
return true;
|
|
6584
|
-
}
|
|
6585
|
-
return preambles.some((p) => message.text.startsWith(p));
|
|
6586
|
-
});
|
|
6799
|
+
const text = message.text;
|
|
6800
|
+
const candidates = this.candidatesByLabel.get(message.label) ?? this.wildcardEntries;
|
|
6587
6801
|
if (options.debug) {
|
|
6588
6802
|
console.log("Usable plugins");
|
|
6589
|
-
console.log(
|
|
6803
|
+
console.log(
|
|
6804
|
+
candidates.filter((e) => this.matchesPreambles(text, e.preambles)).map((e) => e.plugin)
|
|
6805
|
+
);
|
|
6590
6806
|
}
|
|
6591
6807
|
let result = {
|
|
6592
6808
|
decoded: false,
|
|
@@ -6598,7 +6814,7 @@ var MessageDecoder = class {
|
|
|
6598
6814
|
},
|
|
6599
6815
|
message,
|
|
6600
6816
|
remaining: {
|
|
6601
|
-
text
|
|
6817
|
+
text
|
|
6602
6818
|
},
|
|
6603
6819
|
raw: {},
|
|
6604
6820
|
formatted: {
|
|
@@ -6606,10 +6822,14 @@ var MessageDecoder = class {
|
|
|
6606
6822
|
items: []
|
|
6607
6823
|
}
|
|
6608
6824
|
};
|
|
6609
|
-
for (let i = 0; i <
|
|
6610
|
-
const
|
|
6611
|
-
|
|
6612
|
-
|
|
6825
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
6826
|
+
const entry = candidates[i];
|
|
6827
|
+
if (!this.matchesPreambles(text, entry.preambles)) {
|
|
6828
|
+
continue;
|
|
6829
|
+
}
|
|
6830
|
+
const pluginResult = entry.plugin.decode(message, options);
|
|
6831
|
+
if (pluginResult.decoded) {
|
|
6832
|
+
result = pluginResult;
|
|
6613
6833
|
break;
|
|
6614
6834
|
}
|
|
6615
6835
|
}
|
|
@@ -6619,6 +6839,17 @@ var MessageDecoder = class {
|
|
|
6619
6839
|
}
|
|
6620
6840
|
return result;
|
|
6621
6841
|
}
|
|
6842
|
+
matchesPreambles(text, preambles) {
|
|
6843
|
+
if (!preambles) {
|
|
6844
|
+
return true;
|
|
6845
|
+
}
|
|
6846
|
+
for (let i = 0; i < preambles.length; i++) {
|
|
6847
|
+
if (text.startsWith(preambles[i])) {
|
|
6848
|
+
return true;
|
|
6849
|
+
}
|
|
6850
|
+
}
|
|
6851
|
+
return false;
|
|
6852
|
+
}
|
|
6622
6853
|
};
|
|
6623
6854
|
export {
|
|
6624
6855
|
IcaoDecoder,
|