@airframes/acars-decoder 1.9.3 → 1.9.5
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/bin/acars-decoder-test.js +1773 -105
- package/dist/bin/acars-decoder-test.js.map +1 -1
- package/dist/bin/acars-decoder-test.mjs +1773 -105
- package/dist/bin/acars-decoder-test.mjs.map +1 -1
- package/dist/bin/acars-decoder.js +1773 -105
- package/dist/bin/acars-decoder.js.map +1 -1
- package/dist/bin/acars-decoder.mjs +1773 -105
- package/dist/bin/acars-decoder.mjs.map +1 -1
- package/dist/index.d.mts +53 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.js +1773 -105
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1773 -105
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
|
@@ -53,8 +53,8 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
static coordinateString(coords) {
|
|
56
|
-
const latDir = coords.latitude
|
|
57
|
-
const lonDir = coords.longitude
|
|
56
|
+
const latDir = coords.latitude >= 0 ? "N" : "S";
|
|
57
|
+
const lonDir = coords.longitude >= 0 ? "E" : "W";
|
|
58
58
|
return `${Math.abs(coords.latitude).toFixed(3)} ${latDir}, ${Math.abs(coords.longitude).toFixed(3)} ${lonDir}`;
|
|
59
59
|
}
|
|
60
60
|
static getDirection(coord) {
|
|
@@ -104,16 +104,16 @@ var DateTimeUtils = class {
|
|
|
104
104
|
const h = Number(time.substring(0, 2));
|
|
105
105
|
const m = Number(time.substring(2, 4));
|
|
106
106
|
const s = Number(time.substring(4, 6));
|
|
107
|
-
const
|
|
108
|
-
return
|
|
107
|
+
const tod2 = h * 3600 + m * 60 + s;
|
|
108
|
+
return tod2;
|
|
109
109
|
}
|
|
110
110
|
static convertDayTimeToTod(time) {
|
|
111
111
|
const d = Number(time.substring(0, 2));
|
|
112
112
|
const h = Number(time.substring(2, 4));
|
|
113
113
|
const m = Number(time.substring(4, 6));
|
|
114
114
|
const s = Number(time.substring(6, 8));
|
|
115
|
-
const
|
|
116
|
-
return
|
|
115
|
+
const tod2 = d * 86400 + h * 3600 + m * 60 + s;
|
|
116
|
+
return tod2;
|
|
117
117
|
}
|
|
118
118
|
/**
|
|
119
119
|
*
|
|
@@ -389,6 +389,16 @@ var ResultFormatter = class {
|
|
|
389
389
|
value: decodeResult.raw.alternate_icao
|
|
390
390
|
});
|
|
391
391
|
}
|
|
392
|
+
/** The airport landing data is for: the destination, or the airport of a divert. */
|
|
393
|
+
static landingAirport(decodeResult, value) {
|
|
394
|
+
decodeResult.raw.landing_icao = value;
|
|
395
|
+
decodeResult.formatted.items.push({
|
|
396
|
+
type: "icao",
|
|
397
|
+
code: "LAND",
|
|
398
|
+
label: "Landing Airport",
|
|
399
|
+
value: decodeResult.raw.landing_icao
|
|
400
|
+
});
|
|
401
|
+
}
|
|
392
402
|
static eta(decodeResult, time) {
|
|
393
403
|
if (isNaN(time)) {
|
|
394
404
|
return;
|
|
@@ -579,6 +589,144 @@ var ResultFormatter = class {
|
|
|
579
589
|
value: `${decodeResult.raw.heading}`
|
|
580
590
|
});
|
|
581
591
|
}
|
|
592
|
+
static indicatedAirspeed(decodeResult, value) {
|
|
593
|
+
if (isNaN(value)) {
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
decodeResult.raw.indicated_airspeed = value;
|
|
597
|
+
decodeResult.formatted.items.push({
|
|
598
|
+
type: "indicated_airspeed",
|
|
599
|
+
code: "IAS",
|
|
600
|
+
label: "Indicated Airspeed",
|
|
601
|
+
value: `${decodeResult.raw.indicated_airspeed} knots`
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
static track(decodeResult, value) {
|
|
605
|
+
if (isNaN(value)) {
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
decodeResult.raw.track = value;
|
|
609
|
+
decodeResult.formatted.items.push({
|
|
610
|
+
type: "track",
|
|
611
|
+
code: "TRK",
|
|
612
|
+
label: "Track",
|
|
613
|
+
value: `${decodeResult.raw.track} degrees`
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
/** Wind at the aircraft; either half may be missing. */
|
|
617
|
+
static wind(decodeResult, direction, speed) {
|
|
618
|
+
const hasDirection = direction !== void 0 && !isNaN(direction);
|
|
619
|
+
const hasSpeed = speed !== void 0 && !isNaN(speed);
|
|
620
|
+
if (hasDirection) decodeResult.raw.wind_direction = direction;
|
|
621
|
+
if (hasSpeed) decodeResult.raw.wind_speed = speed;
|
|
622
|
+
if (!hasDirection && !hasSpeed) {
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
decodeResult.formatted.items.push({
|
|
626
|
+
type: "wind",
|
|
627
|
+
code: "WIND",
|
|
628
|
+
label: !hasSpeed ? "Wind Direction" : !hasDirection ? "Wind Speed" : "Wind",
|
|
629
|
+
value: [
|
|
630
|
+
hasDirection ? `${direction} degrees` : "",
|
|
631
|
+
hasSpeed ? `${speed} knots` : ""
|
|
632
|
+
].filter((s) => s !== "").join(" at ")
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
static variableWind(decodeResult, speed) {
|
|
636
|
+
if (isNaN(speed)) {
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
decodeResult.raw.wind_speed = speed;
|
|
640
|
+
decodeResult.raw.wind_variable = true;
|
|
641
|
+
decodeResult.formatted.items.push({
|
|
642
|
+
type: "wind",
|
|
643
|
+
code: "WIND",
|
|
644
|
+
label: "Wind",
|
|
645
|
+
value: `variable at ${speed} knots`
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* One point of a recorded track. The track is the route as flown, so each point is added to
|
|
650
|
+
* the route's waypoints; the item shows what the aircraft measured there as well.
|
|
651
|
+
*/
|
|
652
|
+
static trackPoint(decodeResult, point) {
|
|
653
|
+
decodeResult.raw.route = {
|
|
654
|
+
...decodeResult.raw.route,
|
|
655
|
+
waypoints: [...decodeResult.raw.route?.waypoints ?? [], point]
|
|
656
|
+
};
|
|
657
|
+
decodeResult.formatted.items.push({
|
|
658
|
+
type: "track_point",
|
|
659
|
+
code: "TRKPT",
|
|
660
|
+
label: "Track Point",
|
|
661
|
+
value: `${CoordinateUtils.coordinateString(point)} on day ${point.day} at ${DateTimeUtils.timestampToString(point.time)}, ${point.altitude} feet, ${point.temperature} C, wind ${point.windDirection} degrees at ${point.windSpeed} knots, ${point.phase}` + (point.waterVapor === void 0 ? "" : `, water vapor ${point.waterVapor} ppmv`)
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
static runwayLandingData(decodeResult, data) {
|
|
665
|
+
decodeResult.raw.landing_runways = [
|
|
666
|
+
...decodeResult.raw.landing_runways ?? [],
|
|
667
|
+
data
|
|
668
|
+
];
|
|
669
|
+
const parts = [];
|
|
670
|
+
if (data.length !== void 0) parts.push(`${data.length} feet`);
|
|
671
|
+
if (data.flaps !== void 0) parts.push(`flaps ${data.flaps}`);
|
|
672
|
+
if (data.headwind !== void 0) {
|
|
673
|
+
parts.push(
|
|
674
|
+
data.headwind < 0 ? `tailwind ${-data.headwind} knots` : `headwind ${data.headwind} knots`
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
if (data.crosswind !== void 0) {
|
|
678
|
+
const side = { L: " left", R: " right" }[data.crosswindSide ?? "L"];
|
|
679
|
+
parts.push(
|
|
680
|
+
`crosswind ${data.crosswind} knots${data.crosswindSide ? side : ""}`
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
if (data.vref !== void 0) parts.push(`VREF ${data.vref} knots`);
|
|
684
|
+
if (data.vtarget !== void 0) {
|
|
685
|
+
const add = data.additive === void 0 ? "" : ` (${data.additive < 0 ? "" : "+"}${data.additive})`;
|
|
686
|
+
parts.push(`VTGT ${data.vtarget} knots${add}`);
|
|
687
|
+
}
|
|
688
|
+
if (data.maxLandingWeight !== void 0) {
|
|
689
|
+
parts.push(`MRLW ${data.maxLandingWeight}`);
|
|
690
|
+
}
|
|
691
|
+
if (data.landingWeight !== void 0) {
|
|
692
|
+
parts.push(`LDW ${data.landingWeight} pounds`);
|
|
693
|
+
}
|
|
694
|
+
const margins = Object.entries(data.stoppingMargins).map(
|
|
695
|
+
([setting, feet]) => `${setting} ${feet} feet`
|
|
696
|
+
);
|
|
697
|
+
if (margins.length > 0) {
|
|
698
|
+
parts.push(`stopping margin ${margins.join(", ")}`);
|
|
699
|
+
}
|
|
700
|
+
parts.push(...data.notes ?? []);
|
|
701
|
+
const variant2 = data.variant === void 0 ? "" : ` (${data.variant})`;
|
|
702
|
+
decodeResult.formatted.items.push({
|
|
703
|
+
type: "runway_landing_data",
|
|
704
|
+
code: "RWYLDG",
|
|
705
|
+
label: "Runway Landing Data",
|
|
706
|
+
value: `${data.runway}${variant2}: ${parts.join(", ")}`
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
static grossWeight(decodeResult, pounds3) {
|
|
710
|
+
if (isNaN(pounds3)) {
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
decodeResult.raw.gross_weight = pounds3;
|
|
714
|
+
decodeResult.formatted.items.push({
|
|
715
|
+
type: "gross_weight",
|
|
716
|
+
code: "GWT",
|
|
717
|
+
label: "Gross Weight",
|
|
718
|
+
value: `${decodeResult.raw.gross_weight} pounds`
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
static arrivalGate(decodeResult, value) {
|
|
722
|
+
decodeResult.raw.arrival_gate = value;
|
|
723
|
+
decodeResult.formatted.items.push({
|
|
724
|
+
type: "gate",
|
|
725
|
+
code: "AGATE",
|
|
726
|
+
label: "Arrival Gate",
|
|
727
|
+
value: decodeResult.raw.arrival_gate
|
|
728
|
+
});
|
|
729
|
+
}
|
|
582
730
|
static tail(decodeResult, value) {
|
|
583
731
|
decodeResult.raw.tail = value;
|
|
584
732
|
decodeResult.formatted.items.push({
|
|
@@ -782,6 +930,9 @@ var ResultFormatter = class {
|
|
|
782
930
|
}
|
|
783
931
|
}
|
|
784
932
|
static version(decodeResult, value) {
|
|
933
|
+
if (isNaN(value)) {
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
785
936
|
decodeResult.raw.version = value;
|
|
786
937
|
decodeResult.formatted.items.push({
|
|
787
938
|
type: "version",
|
|
@@ -818,6 +969,9 @@ var ResultFormatter = class {
|
|
|
818
969
|
});
|
|
819
970
|
}
|
|
820
971
|
static desiredAltitude(decodeResult, value) {
|
|
972
|
+
if (isNaN(value)) {
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
821
975
|
decodeResult.raw.desired_alt = value;
|
|
822
976
|
decodeResult.formatted.items.push({
|
|
823
977
|
type: "desired_altitude",
|
|
@@ -892,6 +1046,14 @@ var ResultFormatter = class {
|
|
|
892
1046
|
value: decodeResult.raw.sequence_response.toString()
|
|
893
1047
|
});
|
|
894
1048
|
}
|
|
1049
|
+
/**
|
|
1050
|
+
* A field with no specific helper: `key` is its name in `raw` and its item type. `rawValue`
|
|
1051
|
+
* is stored in `raw` when it differs from the text shown (a number, for example).
|
|
1052
|
+
*/
|
|
1053
|
+
static raw(decodeResult, key, code, label, value, rawValue = value) {
|
|
1054
|
+
decodeResult.raw[key] = rawValue;
|
|
1055
|
+
decodeResult.formatted.items.push({ type: key, code, label, value });
|
|
1056
|
+
}
|
|
895
1057
|
static unknown(decodeResult, value, sep = ",") {
|
|
896
1058
|
if (!decodeResult.remaining.text) decodeResult.remaining.text = value;
|
|
897
1059
|
else decodeResult.remaining.text += sep + value;
|
|
@@ -1237,13 +1399,13 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1237
1399
|
const segments = value.split(".");
|
|
1238
1400
|
const parens_idx = segments[0].indexOf("(");
|
|
1239
1401
|
let name;
|
|
1240
|
-
let
|
|
1402
|
+
let runway2;
|
|
1241
1403
|
if (parens_idx === -1) {
|
|
1242
1404
|
name = segments[0];
|
|
1243
1405
|
} else {
|
|
1244
1406
|
name = segments[0].slice(0, parens_idx);
|
|
1245
1407
|
const close_paren_idx = segments[0].indexOf(")");
|
|
1246
|
-
|
|
1408
|
+
runway2 = segments[0].slice(
|
|
1247
1409
|
parens_idx + 1,
|
|
1248
1410
|
close_paren_idx === -1 ? void 0 : close_paren_idx
|
|
1249
1411
|
);
|
|
@@ -1254,7 +1416,7 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1254
1416
|
}
|
|
1255
1417
|
decodeResult.raw.company_route = {
|
|
1256
1418
|
name,
|
|
1257
|
-
runway,
|
|
1419
|
+
runway: runway2,
|
|
1258
1420
|
waypoints
|
|
1259
1421
|
};
|
|
1260
1422
|
decodeResult.formatted.items.push({
|
|
@@ -1392,6 +1554,9 @@ var Arinc702Helper = class _Arinc702Helper {
|
|
|
1392
1554
|
case "TD":
|
|
1393
1555
|
processTimeOfDeparture(decodeResult, data2.split(","));
|
|
1394
1556
|
break;
|
|
1557
|
+
case "TR":
|
|
1558
|
+
processTR(decodeResult, data2.split(","));
|
|
1559
|
+
break;
|
|
1395
1560
|
case "TS":
|
|
1396
1561
|
_Arinc702Helper.processTimeStamp(decodeResult, data2.split(","));
|
|
1397
1562
|
break;
|
|
@@ -1572,6 +1737,21 @@ function processLandingReport(decodeResult, data) {
|
|
|
1572
1737
|
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
1573
1738
|
}
|
|
1574
1739
|
}
|
|
1740
|
+
function processTR(decodeResult, data) {
|
|
1741
|
+
if (data.length !== 21) {
|
|
1742
|
+
ResultFormatter.unknownArr(decodeResult, data, ",");
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(0, 5), ",");
|
|
1746
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[5]));
|
|
1747
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(6, 11), ",");
|
|
1748
|
+
ResultFormatter.departureAirport(decodeResult, data[11]);
|
|
1749
|
+
ResultFormatter.arrivalAirport(decodeResult, data[12]);
|
|
1750
|
+
ResultFormatter.departureRunway(decodeResult, data[13]);
|
|
1751
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(14, 16), ",");
|
|
1752
|
+
ResultFormatter.flightNumber(decodeResult, data[16]);
|
|
1753
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(17), ",");
|
|
1754
|
+
}
|
|
1575
1755
|
function processCenterOfGravity(decodeResult, data) {
|
|
1576
1756
|
if (data.length === 1) {
|
|
1577
1757
|
if (data[0] !== void 0 && data[0] !== "") {
|
|
@@ -1632,6 +1812,8 @@ function processIMI(decodeResult, type) {
|
|
|
1632
1812
|
decodeResult.formatted.description = "Load Distribution Information";
|
|
1633
1813
|
} else if (type === "PER") {
|
|
1634
1814
|
decodeResult.formatted.description = "Performance Report";
|
|
1815
|
+
} else if (type === "PRF") {
|
|
1816
|
+
decodeResult.formatted.description = "Profile Report";
|
|
1635
1817
|
} else if (type === "POS") {
|
|
1636
1818
|
decodeResult.formatted.description = "Position Report";
|
|
1637
1819
|
} else if (type === "PRG") {
|
|
@@ -2070,7 +2252,54 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
2070
2252
|
}
|
|
2071
2253
|
};
|
|
2072
2254
|
|
|
2255
|
+
// lib/utils/swa_request.ts
|
|
2256
|
+
var AIRLINES = { "189": "Southwest" };
|
|
2257
|
+
function swaRequestHeader(decodeResult, airlineId, layout, software) {
|
|
2258
|
+
const airline = AIRLINES[airlineId];
|
|
2259
|
+
ResultFormatter.raw(
|
|
2260
|
+
decodeResult,
|
|
2261
|
+
"airline_id",
|
|
2262
|
+
"AIRLINE",
|
|
2263
|
+
"Airline ID",
|
|
2264
|
+
airline ? `${airlineId} (${airline})` : airlineId,
|
|
2265
|
+
airlineId
|
|
2266
|
+
);
|
|
2267
|
+
ResultFormatter.raw(
|
|
2268
|
+
decodeResult,
|
|
2269
|
+
"request_layout",
|
|
2270
|
+
"LAYOUT",
|
|
2271
|
+
"Request Layout",
|
|
2272
|
+
layout
|
|
2273
|
+
);
|
|
2274
|
+
ResultFormatter.raw(
|
|
2275
|
+
decodeResult,
|
|
2276
|
+
"software_version",
|
|
2277
|
+
"SWVER",
|
|
2278
|
+
"Software Version",
|
|
2279
|
+
software
|
|
2280
|
+
);
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2073
2283
|
// lib/plugins/Label_10_LDR.ts
|
|
2284
|
+
function pounds(value) {
|
|
2285
|
+
if (value.trim() === "") return void 0;
|
|
2286
|
+
const thousands = Number(value);
|
|
2287
|
+
return Number.isFinite(thousands) ? Math.round(thousands * 1e3) : void 0;
|
|
2288
|
+
}
|
|
2289
|
+
function runway(value) {
|
|
2290
|
+
const [rwy, suffix = ""] = value.trim().split("/");
|
|
2291
|
+
return suffix.trim() === "" ? rwy.trim() : `${rwy.trim()}/${suffix.trim()}`;
|
|
2292
|
+
}
|
|
2293
|
+
var RUNWAY_CONDITION = {
|
|
2294
|
+
6: "dry",
|
|
2295
|
+
5: "good",
|
|
2296
|
+
4: "good to medium",
|
|
2297
|
+
3: "medium",
|
|
2298
|
+
2: "medium to poor",
|
|
2299
|
+
1: "poor",
|
|
2300
|
+
0: "nil"
|
|
2301
|
+
};
|
|
2302
|
+
var FLAPS = { "0": 30, "1": 40, "2": 15 };
|
|
2074
2303
|
var Label_10_LDR = class extends DecoderPlugin {
|
|
2075
2304
|
name = "label-10-ldr";
|
|
2076
2305
|
qualifiers() {
|
|
@@ -2082,18 +2311,13 @@ var Label_10_LDR = class extends DecoderPlugin {
|
|
|
2082
2311
|
decode(message2, options = {}) {
|
|
2083
2312
|
const decodeResult = this.defaultResult();
|
|
2084
2313
|
decodeResult.decoder.name = this.name;
|
|
2085
|
-
decodeResult.formatted.description = "
|
|
2314
|
+
decodeResult.formatted.description = "Landing Data Request";
|
|
2086
2315
|
decodeResult.message = message2;
|
|
2087
2316
|
const parts = message2.text.split(",");
|
|
2088
|
-
if (parts.length <
|
|
2089
|
-
|
|
2090
|
-
console.log(`Decoder: Unknown 10 message: ${message2.text}`);
|
|
2091
|
-
}
|
|
2092
|
-
ResultFormatter.unknown(decodeResult, message2.text);
|
|
2093
|
-
decodeResult.decoded = false;
|
|
2094
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2095
|
-
return decodeResult;
|
|
2317
|
+
if (parts.length < 31) {
|
|
2318
|
+
return this.failUnknown(decodeResult, message2.text, options);
|
|
2096
2319
|
}
|
|
2320
|
+
swaRequestHeader(decodeResult, parts[1], parts[2], parts[3]);
|
|
2097
2321
|
const lat = parts[5];
|
|
2098
2322
|
const lon = parts[6];
|
|
2099
2323
|
const position = {
|
|
@@ -2101,25 +2325,209 @@ var Label_10_LDR = class extends DecoderPlugin {
|
|
|
2101
2325
|
longitude: (lon[0] === "E" ? 1 : -1) * Number(lon.substring(1).trim())
|
|
2102
2326
|
};
|
|
2103
2327
|
ResultFormatter.position(decodeResult, position);
|
|
2104
|
-
|
|
2328
|
+
if (parts[7].trim() !== "") {
|
|
2329
|
+
ResultFormatter.altitude(decodeResult, Number(parts[7]));
|
|
2330
|
+
}
|
|
2331
|
+
const fuel = pounds(parts[8]);
|
|
2332
|
+
if (fuel !== void 0) ResultFormatter.currentFuel(decodeResult, fuel);
|
|
2105
2333
|
ResultFormatter.departureAirport(decodeResult, parts[9]);
|
|
2106
2334
|
ResultFormatter.arrivalAirport(decodeResult, parts[10]);
|
|
2107
|
-
ResultFormatter.
|
|
2108
|
-
ResultFormatter.arrivalRunway(decodeResult, parts[12]
|
|
2109
|
-
const altRwy = [parts[13]
|
|
2335
|
+
ResultFormatter.landingAirport(decodeResult, parts[11]);
|
|
2336
|
+
ResultFormatter.arrivalRunway(decodeResult, runway(parts[12]));
|
|
2337
|
+
const altRwy = [runway(parts[13]), runway(parts[14])].filter((r) => r != "").join(",");
|
|
2110
2338
|
if (altRwy != "") {
|
|
2111
2339
|
ResultFormatter.alternateRunway(decodeResult, altRwy);
|
|
2112
2340
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2341
|
+
const unknown = [parts[4]];
|
|
2342
|
+
const condition = parts[15].trim();
|
|
2343
|
+
if (/^[1-6]$/.test(condition)) {
|
|
2344
|
+
const code = 6 - Number(condition);
|
|
2345
|
+
ResultFormatter.raw(
|
|
2346
|
+
decodeResult,
|
|
2347
|
+
"runway_condition_code",
|
|
2348
|
+
"RCC",
|
|
2349
|
+
"Runway Condition Code",
|
|
2350
|
+
`${code} (${RUNWAY_CONDITION[code]})`,
|
|
2351
|
+
code
|
|
2352
|
+
);
|
|
2353
|
+
} else if (condition !== "0") {
|
|
2354
|
+
unknown.push(parts[15]);
|
|
2355
|
+
}
|
|
2356
|
+
const flaps = FLAPS[parts[16].trim()];
|
|
2357
|
+
if (flaps !== void 0) {
|
|
2358
|
+
ResultFormatter.raw(
|
|
2359
|
+
decodeResult,
|
|
2360
|
+
"landing_flaps",
|
|
2361
|
+
"FLAPS",
|
|
2362
|
+
"Landing Flaps",
|
|
2363
|
+
`${flaps}`,
|
|
2364
|
+
flaps
|
|
2365
|
+
);
|
|
2366
|
+
} else {
|
|
2367
|
+
unknown.push(parts[16]);
|
|
2368
|
+
}
|
|
2369
|
+
const [windDir, windSpeed, gust, temp, dew, altimeter] = parts.slice(17, 23).map((field) => {
|
|
2370
|
+
const value = field.trim();
|
|
2371
|
+
if (/^-?\d{1,4}$/.test(value)) return Number(value);
|
|
2372
|
+
if (value !== "") unknown.push(field);
|
|
2373
|
+
return void 0;
|
|
2374
|
+
});
|
|
2375
|
+
if (windDir !== void 0 || windSpeed !== void 0) {
|
|
2376
|
+
ResultFormatter.wind(decodeResult, windDir, windSpeed);
|
|
2377
|
+
}
|
|
2378
|
+
if (gust !== void 0) {
|
|
2379
|
+
ResultFormatter.raw(
|
|
2380
|
+
decodeResult,
|
|
2381
|
+
"wind_gust",
|
|
2382
|
+
"GUST",
|
|
2383
|
+
"Wind Gust",
|
|
2384
|
+
`${gust} knots`,
|
|
2385
|
+
gust
|
|
2386
|
+
);
|
|
2387
|
+
}
|
|
2388
|
+
ResultFormatter.temperature(
|
|
2389
|
+
decodeResult,
|
|
2390
|
+
temp === void 0 ? "" : `${temp}`
|
|
2391
|
+
);
|
|
2392
|
+
if (dew !== void 0) {
|
|
2393
|
+
ResultFormatter.raw(
|
|
2394
|
+
decodeResult,
|
|
2395
|
+
"dew_point",
|
|
2396
|
+
"DEWPT",
|
|
2397
|
+
"Dew Point (C)",
|
|
2398
|
+
`${dew} degrees`,
|
|
2399
|
+
dew
|
|
2400
|
+
);
|
|
2401
|
+
}
|
|
2402
|
+
if (altimeter !== void 0) {
|
|
2403
|
+
const inHg = altimeter / 100;
|
|
2404
|
+
ResultFormatter.raw(
|
|
2405
|
+
decodeResult,
|
|
2406
|
+
"altimeter",
|
|
2407
|
+
"ALTIM",
|
|
2408
|
+
"Altimeter",
|
|
2409
|
+
`${inHg.toFixed(2)} inHg`,
|
|
2410
|
+
inHg
|
|
2411
|
+
);
|
|
2412
|
+
}
|
|
2413
|
+
const antiIce = parts[23].trim();
|
|
2414
|
+
if (/^[1-9]$/.test(antiIce)) {
|
|
2415
|
+
ResultFormatter.raw(
|
|
2416
|
+
decodeResult,
|
|
2417
|
+
"anti_ice",
|
|
2418
|
+
"ANTIICE",
|
|
2419
|
+
"Anti-Ice",
|
|
2420
|
+
antiIce === "1" ? "engine" : antiIce,
|
|
2421
|
+
Number(antiIce)
|
|
2422
|
+
);
|
|
2423
|
+
} else if (antiIce !== "0") {
|
|
2424
|
+
unknown.push(parts[23]);
|
|
2425
|
+
}
|
|
2426
|
+
const flags = [
|
|
2427
|
+
[parts[24], "enroute_icing", "ICING", "En Route Icing"],
|
|
2428
|
+
// the card says HGS AIII: 113 of 113 pairs, 32 requests
|
|
2429
|
+
[parts[25], "hgs_approach", "HGS", "HGS Approach"]
|
|
2430
|
+
];
|
|
2431
|
+
for (const [value, key, code, label] of flags) {
|
|
2432
|
+
if (value.trim() === "1") {
|
|
2433
|
+
ResultFormatter.raw(decodeResult, key, code, label, "yes", true);
|
|
2434
|
+
} else if (value.trim() !== "0") {
|
|
2435
|
+
unknown.push(value);
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
const nonNormal = parts[26].trim();
|
|
2439
|
+
if (/^\d+$/.test(nonNormal) && Number(nonNormal) !== 0) {
|
|
2440
|
+
ResultFormatter.raw(
|
|
2441
|
+
decodeResult,
|
|
2442
|
+
"non_normal_configuration",
|
|
2443
|
+
"NNC",
|
|
2444
|
+
"Non-Normal Configuration",
|
|
2445
|
+
`${Number(nonNormal)}`,
|
|
2446
|
+
Number(nonNormal)
|
|
2447
|
+
);
|
|
2448
|
+
} else if (!/^0+$/.test(nonNormal)) {
|
|
2449
|
+
unknown.push(parts[26]);
|
|
2450
|
+
}
|
|
2451
|
+
if (parts[27].trim() !== "") unknown.push(parts[27]);
|
|
2452
|
+
const weights = [
|
|
2453
|
+
["zero_fuel_weight", "ZFW", "Zero Fuel Weight", parts[28]],
|
|
2454
|
+
["landing_fuel", "LFUEL", "Landing Fuel", parts[29]],
|
|
2455
|
+
["landing_weight", "LDW", "Landing Weight", parts[30]]
|
|
2456
|
+
];
|
|
2457
|
+
for (const [key, code, label, value] of weights) {
|
|
2458
|
+
const amount = pounds(value);
|
|
2459
|
+
if (amount === void 0) continue;
|
|
2460
|
+
ResultFormatter.raw(
|
|
2461
|
+
decodeResult,
|
|
2462
|
+
key,
|
|
2463
|
+
code,
|
|
2464
|
+
label,
|
|
2465
|
+
`${amount} pounds`,
|
|
2466
|
+
amount
|
|
2467
|
+
);
|
|
2468
|
+
}
|
|
2469
|
+
const gradient = (parts[31] ?? "").trim();
|
|
2470
|
+
if (/^\d+$/.test(gradient)) {
|
|
2471
|
+
ResultFormatter.raw(
|
|
2472
|
+
decodeResult,
|
|
2473
|
+
"missed_approach_gradient",
|
|
2474
|
+
"MAGRAD",
|
|
2475
|
+
"Missed Approach Climb Gradient",
|
|
2476
|
+
`${Number(gradient)} feet per nautical mile`,
|
|
2477
|
+
Number(gradient)
|
|
2478
|
+
);
|
|
2479
|
+
} else if (gradient !== "" && gradient !== "----.") {
|
|
2480
|
+
unknown.push(parts[31]);
|
|
2481
|
+
}
|
|
2482
|
+
const missedAltitude = (parts[32] ?? "").trim();
|
|
2483
|
+
if (/^\d+$/.test(missedAltitude)) {
|
|
2484
|
+
ResultFormatter.raw(
|
|
2485
|
+
decodeResult,
|
|
2486
|
+
"missed_approach_altitude",
|
|
2487
|
+
"MAALT",
|
|
2488
|
+
"Missed Approach Altitude",
|
|
2489
|
+
`${Number(missedAltitude)} feet`,
|
|
2490
|
+
Number(missedAltitude)
|
|
2491
|
+
);
|
|
2492
|
+
} else if (missedAltitude !== "") {
|
|
2493
|
+
unknown.push(parts[32]);
|
|
2494
|
+
}
|
|
2495
|
+
unknown.push(...parts.slice(33).filter((field) => field.trim() !== ""));
|
|
2496
|
+
ResultFormatter.unknownArr(decodeResult, unknown);
|
|
2117
2497
|
decodeResult.decoded = true;
|
|
2118
2498
|
decodeResult.decoder.decodeLevel = "partial";
|
|
2119
2499
|
return decodeResult;
|
|
2120
2500
|
}
|
|
2121
2501
|
};
|
|
2122
2502
|
|
|
2503
|
+
// lib/plugins/Label_10_LRW.ts
|
|
2504
|
+
var Label_10_LRW = class extends DecoderPlugin {
|
|
2505
|
+
name = "label-10-lrw";
|
|
2506
|
+
qualifiers() {
|
|
2507
|
+
return {
|
|
2508
|
+
labels: ["10"],
|
|
2509
|
+
preambles: ["LRW01,"]
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
decode(message2, options = {}) {
|
|
2513
|
+
const decodeResult = this.initResult(message2, "Landing Runways Request");
|
|
2514
|
+
const parts = message2.text.split(",");
|
|
2515
|
+
if (parts.length < 8 || parts[7].trim() === "") {
|
|
2516
|
+
return this.failUnknown(decodeResult, message2.text, options);
|
|
2517
|
+
}
|
|
2518
|
+
swaRequestHeader(decodeResult, parts[1], parts[2], parts[3]);
|
|
2519
|
+
ResultFormatter.departureAirport(decodeResult, parts[6]);
|
|
2520
|
+
ResultFormatter.arrivalAirport(decodeResult, parts[7]);
|
|
2521
|
+
ResultFormatter.unknownArr(decodeResult, [
|
|
2522
|
+
parts[4],
|
|
2523
|
+
parts[5],
|
|
2524
|
+
...parts.slice(8).filter((field) => field.trim() !== "")
|
|
2525
|
+
]);
|
|
2526
|
+
this.setDecodeLevel(decodeResult, true);
|
|
2527
|
+
return decodeResult;
|
|
2528
|
+
}
|
|
2529
|
+
};
|
|
2530
|
+
|
|
2123
2531
|
// lib/plugins/Label_10_POS.ts
|
|
2124
2532
|
var Label_10_POS = class extends DecoderPlugin {
|
|
2125
2533
|
name = "label-10-pos";
|
|
@@ -2219,6 +2627,364 @@ var Label_10_Slash = class extends DecoderPlugin {
|
|
|
2219
2627
|
}
|
|
2220
2628
|
};
|
|
2221
2629
|
|
|
2630
|
+
// lib/utils/runway_utils.ts
|
|
2631
|
+
var SIDES = {
|
|
2632
|
+
N: "north",
|
|
2633
|
+
NE: "northeast",
|
|
2634
|
+
E: "east",
|
|
2635
|
+
SE: "southeast",
|
|
2636
|
+
S: "south",
|
|
2637
|
+
SW: "southwest",
|
|
2638
|
+
W: "west",
|
|
2639
|
+
NW: "northwest"
|
|
2640
|
+
};
|
|
2641
|
+
var RunwayUtils = class {
|
|
2642
|
+
/**
|
|
2643
|
+
* Describe the condition that names a runway variant in Southwest landing data, e.g.
|
|
2644
|
+
* `11/AIB -E1804F`: the runway, the variant's code and its condition.
|
|
2645
|
+
*
|
|
2646
|
+
* -E1804F is 1804 feet taken off the east end, -SWCBL the arresting cable at the southwest
|
|
2647
|
+
* end. Checked on the LRW01 runway lists of six airports, where every variant's length is
|
|
2648
|
+
* the runway's less the feet given, or less 1500 feet for a cable. LAHSO is sent as written.
|
|
2649
|
+
*
|
|
2650
|
+
* @param name - the runway as sent, with its variant
|
|
2651
|
+
* @returns a description of the condition, or undefined when the name has none
|
|
2652
|
+
*/
|
|
2653
|
+
static variantDescription(name) {
|
|
2654
|
+
const text = name.trim();
|
|
2655
|
+
const cut = text.match(/-(NE|NW|SE|SW|N|E|S|W)(\d+)F$/);
|
|
2656
|
+
if (cut) {
|
|
2657
|
+
return `${Number(cut[2])} feet off the ${SIDES[cut[1]]} end`;
|
|
2658
|
+
}
|
|
2659
|
+
const cable = text.match(/-(NE|NW|SE|SW|N|E|S|W)CBL$/);
|
|
2660
|
+
if (cable) {
|
|
2661
|
+
return `arresting cable at the ${SIDES[cable[1]]} end`;
|
|
2662
|
+
}
|
|
2663
|
+
if (/(^|\s)LAHSO$/.test(text)) {
|
|
2664
|
+
return "land and hold short";
|
|
2665
|
+
}
|
|
2666
|
+
return void 0;
|
|
2667
|
+
}
|
|
2668
|
+
};
|
|
2669
|
+
|
|
2670
|
+
// lib/plugins/Label_11_LDR.ts
|
|
2671
|
+
function tod(hours, minutes) {
|
|
2672
|
+
const h = Number(hours);
|
|
2673
|
+
const m = Number(minutes);
|
|
2674
|
+
return h <= 23 && m <= 59 ? h * 3600 + m * 60 : void 0;
|
|
2675
|
+
}
|
|
2676
|
+
function pounds2(value) {
|
|
2677
|
+
return Math.round(Number(value) * 1e3);
|
|
2678
|
+
}
|
|
2679
|
+
function variant(runway2) {
|
|
2680
|
+
const description = RunwayUtils.variantDescription(runway2);
|
|
2681
|
+
return description === void 0 ? {} : { variant: description };
|
|
2682
|
+
}
|
|
2683
|
+
var HEADER = [
|
|
2684
|
+
/^LDR01,(\w{4}) LANDING DATA,FLT(?:\s+METAR-(\d{2})(\d{2})Z)?\s*$/,
|
|
2685
|
+
/^(\d{1,4})\s+WIND\s+LDW\s*$/,
|
|
2686
|
+
/^TIME\s+(\d{3}|VRB)\/(\d{2,3})G(\d{2,3}|--)\s+(\d+\.\d)\s*$/,
|
|
2687
|
+
/^(\d{2})(\d{2})Z\s+OAT\/DEW\s*(\S*)\s*$/,
|
|
2688
|
+
/^\s+(-?\d{2,3})\/(-?\d{2,3})\s*(\S*)\s*$/,
|
|
2689
|
+
/^\s+QNH\s*(\S*)\s*$/,
|
|
2690
|
+
// QNH in inches of mercury, or hectopascals outside the US
|
|
2691
|
+
/^\s+(\d{2}\.\d{2}|\d{4})\s*(\S*)\s*$/
|
|
2692
|
+
];
|
|
2693
|
+
var RUNWAY = /^(\d{1,2}[LRC]?(?:\/\S+)?(?: -\S+)?)\s+(\d{1,5})\s*$/;
|
|
2694
|
+
var RUNWAY_START = /^\d{1,2}[LRC]?(?:\/\S+)?(?: -\S+)?(?:\s{2,}\d*)?\s*$/;
|
|
2695
|
+
var ALTERNATIVES = "--- ALTERNATIVE RWYS ---";
|
|
2696
|
+
var ALTERNATIVE = /^(?:(.+?)\s{2,})?(\d{1,2}[LRC]?(?:\/\S+)?)\s*$/;
|
|
2697
|
+
var BLOCK = [
|
|
2698
|
+
/^FLAPS (\d{2}|--)\s*$/,
|
|
2699
|
+
/^VREF\/VTGT\s+(?:(\d{2})([HT])\/(\d{2})([LR])|---\/---)\s*$/,
|
|
2700
|
+
/^\s*(?:(\d{3})\/(\d{3}) ([+-]\d+)|---\/---)\s+(AB\d)\s+(\d+|----)\s*$/,
|
|
2701
|
+
/^MRLW (\d+\.\d\/\S|-+\/-)\s+(AB\d)\s+(\d+|----)\s*$/,
|
|
2702
|
+
/^\s*LDW (\d+\.\d)\s+(ABM)\s+(\d+|----)\s*$/
|
|
2703
|
+
];
|
|
2704
|
+
var Label_11_LDR = class extends DecoderPlugin {
|
|
2705
|
+
name = "label-11-ldr";
|
|
2706
|
+
qualifiers() {
|
|
2707
|
+
return {
|
|
2708
|
+
labels: ["11"],
|
|
2709
|
+
preambles: ["LDR01,"]
|
|
2710
|
+
};
|
|
2711
|
+
}
|
|
2712
|
+
decode(message2, options = {}) {
|
|
2713
|
+
const decodeResult = this.initResult(message2, "Landing Data");
|
|
2714
|
+
const nl = message2.text.includes("\r\n") ? "\r\n" : "\n";
|
|
2715
|
+
const lines = message2.text.split(/\r?\n/);
|
|
2716
|
+
const first = lines[0].match(HEADER[0]);
|
|
2717
|
+
if (!first) {
|
|
2718
|
+
return this.failUnknown(decodeResult, message2.text, options);
|
|
2719
|
+
}
|
|
2720
|
+
const unknown = [];
|
|
2721
|
+
ResultFormatter.landingAirport(decodeResult, first[1]);
|
|
2722
|
+
const metar = first[2] === void 0 ? void 0 : tod(first[2], first[3]);
|
|
2723
|
+
if (first[2] !== void 0 && metar === void 0) {
|
|
2724
|
+
unknown.push(`METAR-${first[2]}${first[3]}Z`);
|
|
2725
|
+
}
|
|
2726
|
+
if (metar !== void 0) {
|
|
2727
|
+
ResultFormatter.raw(
|
|
2728
|
+
decodeResult,
|
|
2729
|
+
"metar_time",
|
|
2730
|
+
"METAR",
|
|
2731
|
+
"METAR Time",
|
|
2732
|
+
DateTimeUtils.timestampToString(metar),
|
|
2733
|
+
metar
|
|
2734
|
+
);
|
|
2735
|
+
}
|
|
2736
|
+
const runways = [];
|
|
2737
|
+
let i = 1;
|
|
2738
|
+
for (; i < HEADER.length && i < lines.length; i++) {
|
|
2739
|
+
const m = lines[i].match(HEADER[i]);
|
|
2740
|
+
if (!m) break;
|
|
2741
|
+
if (i === 1) {
|
|
2742
|
+
ResultFormatter.flightNumber(decodeResult, m[1]);
|
|
2743
|
+
} else if (i === 2) {
|
|
2744
|
+
if (m[1] === "VRB") {
|
|
2745
|
+
ResultFormatter.variableWind(decodeResult, Number(m[2]));
|
|
2746
|
+
} else {
|
|
2747
|
+
ResultFormatter.wind(decodeResult, Number(m[1]), Number(m[2]));
|
|
2748
|
+
}
|
|
2749
|
+
if (m[3] !== "--") {
|
|
2750
|
+
ResultFormatter.raw(
|
|
2751
|
+
decodeResult,
|
|
2752
|
+
"wind_gust",
|
|
2753
|
+
"GUST",
|
|
2754
|
+
"Wind Gust",
|
|
2755
|
+
`${Number(m[3])} knots`,
|
|
2756
|
+
Number(m[3])
|
|
2757
|
+
);
|
|
2758
|
+
}
|
|
2759
|
+
ResultFormatter.raw(
|
|
2760
|
+
decodeResult,
|
|
2761
|
+
"landing_weight",
|
|
2762
|
+
"LDW",
|
|
2763
|
+
"Landing Weight",
|
|
2764
|
+
`${pounds2(m[4])} pounds`,
|
|
2765
|
+
pounds2(m[4])
|
|
2766
|
+
);
|
|
2767
|
+
} else if (i === 3) {
|
|
2768
|
+
const time = tod(m[1], m[2]);
|
|
2769
|
+
if (time === void 0) {
|
|
2770
|
+
unknown.push(`${m[1]}${m[2]}Z`);
|
|
2771
|
+
} else {
|
|
2772
|
+
ResultFormatter.timestamp(decodeResult, time);
|
|
2773
|
+
}
|
|
2774
|
+
runways.push(m[3]);
|
|
2775
|
+
} else if (i === 4) {
|
|
2776
|
+
ResultFormatter.temperature(decodeResult, `${Number(m[1])}`);
|
|
2777
|
+
ResultFormatter.raw(
|
|
2778
|
+
decodeResult,
|
|
2779
|
+
"dew_point",
|
|
2780
|
+
"DEWPT",
|
|
2781
|
+
"Dew Point (C)",
|
|
2782
|
+
`${Number(m[2])} degrees`,
|
|
2783
|
+
Number(m[2])
|
|
2784
|
+
);
|
|
2785
|
+
runways.push(m[3]);
|
|
2786
|
+
} else if (i === 5) {
|
|
2787
|
+
runways.push(m[1]);
|
|
2788
|
+
} else {
|
|
2789
|
+
ResultFormatter.raw(
|
|
2790
|
+
decodeResult,
|
|
2791
|
+
"altimeter",
|
|
2792
|
+
"ALTIM",
|
|
2793
|
+
"Altimeter",
|
|
2794
|
+
`${m[1]} ${m[1].includes(".") ? "inHg" : "hPa"}`,
|
|
2795
|
+
Number(m[1])
|
|
2796
|
+
);
|
|
2797
|
+
runways.push(m[2]);
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
const listed = runways.filter((r) => r !== "");
|
|
2801
|
+
if (listed.length > 0) {
|
|
2802
|
+
ResultFormatter.raw(
|
|
2803
|
+
decodeResult,
|
|
2804
|
+
"runways",
|
|
2805
|
+
"RWYS",
|
|
2806
|
+
"Runways",
|
|
2807
|
+
listed.join(", "),
|
|
2808
|
+
listed
|
|
2809
|
+
);
|
|
2810
|
+
}
|
|
2811
|
+
const rest = lines.slice(i);
|
|
2812
|
+
let at = 0;
|
|
2813
|
+
const alternatives = [];
|
|
2814
|
+
if (rest[0]?.trim() === "REMARKS") {
|
|
2815
|
+
const remarks = [];
|
|
2816
|
+
for (at = 1; at < rest.length && !RUNWAY_START.test(rest[at]); at++) {
|
|
2817
|
+
if (rest[at].trim() === ALTERNATIVES) {
|
|
2818
|
+
at = this.alternatives(rest, at + 1, alternatives, unknown);
|
|
2819
|
+
break;
|
|
2820
|
+
}
|
|
2821
|
+
if (rest[at].trim() !== "") remarks.push(rest[at].trim());
|
|
2822
|
+
}
|
|
2823
|
+
if (remarks.length > 0) {
|
|
2824
|
+
ResultFormatter.raw(
|
|
2825
|
+
decodeResult,
|
|
2826
|
+
"remarks",
|
|
2827
|
+
"RMK",
|
|
2828
|
+
"Remarks",
|
|
2829
|
+
remarks.join(" ")
|
|
2830
|
+
);
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
if (alternatives.length > 0) {
|
|
2834
|
+
ResultFormatter.raw(
|
|
2835
|
+
decodeResult,
|
|
2836
|
+
"alternative_runways",
|
|
2837
|
+
"ALTRWY",
|
|
2838
|
+
"Alternative Runways",
|
|
2839
|
+
alternatives.map((a) => a.variant ? `${a.runway} (${a.variant})` : a.runway).join(", "),
|
|
2840
|
+
alternatives
|
|
2841
|
+
);
|
|
2842
|
+
}
|
|
2843
|
+
const blocks = [];
|
|
2844
|
+
while (at < rest.length) {
|
|
2845
|
+
const block = this.runwayBlock(rest.slice(at, at + 1 + BLOCK.length));
|
|
2846
|
+
if (block) {
|
|
2847
|
+
blocks.push(block);
|
|
2848
|
+
at += 1 + BLOCK.length;
|
|
2849
|
+
continue;
|
|
2850
|
+
}
|
|
2851
|
+
const line = rest[at];
|
|
2852
|
+
const head = line.match(RUNWAY);
|
|
2853
|
+
const next = rest.slice(at + 1).find((l) => l.trim() !== "");
|
|
2854
|
+
if (head && next !== void 0 && !next.startsWith("FLAPS") && // a FLAPS line cut off by the end of the block
|
|
2855
|
+
!"FLAPS".startsWith(next.trim()) && !RUNWAY_START.test(next)) {
|
|
2856
|
+
blocks.push({
|
|
2857
|
+
runway: head[1],
|
|
2858
|
+
...variant(head[1]),
|
|
2859
|
+
length: Number(head[2]),
|
|
2860
|
+
stoppingMargins: {}
|
|
2861
|
+
});
|
|
2862
|
+
at++;
|
|
2863
|
+
continue;
|
|
2864
|
+
}
|
|
2865
|
+
const last = blocks[blocks.length - 1];
|
|
2866
|
+
if (line.trim() !== "") {
|
|
2867
|
+
if (last && !RUNWAY_START.test(line)) {
|
|
2868
|
+
last.notes = [...last.notes ?? [], line.trim()];
|
|
2869
|
+
} else {
|
|
2870
|
+
unknown.push(...rest.slice(at).filter((l) => l.trim() !== ""));
|
|
2871
|
+
break;
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
at++;
|
|
2875
|
+
}
|
|
2876
|
+
for (const block of blocks) {
|
|
2877
|
+
ResultFormatter.runwayLandingData(decodeResult, block);
|
|
2878
|
+
}
|
|
2879
|
+
if (unknown.length > 0) {
|
|
2880
|
+
ResultFormatter.unknown(decodeResult, unknown.join(nl), nl);
|
|
2881
|
+
}
|
|
2882
|
+
this.setDecodeLevel(
|
|
2883
|
+
decodeResult,
|
|
2884
|
+
true,
|
|
2885
|
+
i < HEADER.length ? "partial" : void 0
|
|
2886
|
+
);
|
|
2887
|
+
return decodeResult;
|
|
2888
|
+
}
|
|
2889
|
+
/** The six lines of one runway, or undefined if they are not a whole block. */
|
|
2890
|
+
runwayBlock(lines) {
|
|
2891
|
+
const head = lines[0]?.match(RUNWAY);
|
|
2892
|
+
if (!head || lines.length < 1 + BLOCK.length) return void 0;
|
|
2893
|
+
const m = BLOCK.map((re, n) => lines[n + 1].match(re));
|
|
2894
|
+
if (m.some((x) => !x)) return void 0;
|
|
2895
|
+
const [flaps, wind, speeds, mrlw, ldw] = m;
|
|
2896
|
+
const data = {
|
|
2897
|
+
runway: head[1],
|
|
2898
|
+
...variant(head[1]),
|
|
2899
|
+
length: Number(head[2]),
|
|
2900
|
+
stoppingMargins: {}
|
|
2901
|
+
};
|
|
2902
|
+
if (flaps[1] !== "--") data.flaps = Number(flaps[1]);
|
|
2903
|
+
if (wind[1] !== void 0) {
|
|
2904
|
+
data.headwind = Number(wind[1]) * (wind[2] === "T" ? -1 : 1);
|
|
2905
|
+
data.crosswind = Number(wind[3]);
|
|
2906
|
+
data.crosswindSide = wind[4];
|
|
2907
|
+
}
|
|
2908
|
+
if (speeds[1] !== void 0) {
|
|
2909
|
+
data.vref = Number(speeds[1]);
|
|
2910
|
+
data.vtarget = Number(speeds[2]);
|
|
2911
|
+
data.additive = Number(speeds[3]);
|
|
2912
|
+
}
|
|
2913
|
+
if (!mrlw[1].startsWith("-")) data.maxLandingWeight = mrlw[1];
|
|
2914
|
+
data.landingWeight = pounds2(ldw[1]);
|
|
2915
|
+
for (const [setting, feet] of [
|
|
2916
|
+
[speeds[4], speeds[5]],
|
|
2917
|
+
[mrlw[2], mrlw[3]],
|
|
2918
|
+
[ldw[2], ldw[3]]
|
|
2919
|
+
]) {
|
|
2920
|
+
if (feet !== "----") data.stoppingMargins[setting] = Number(feet);
|
|
2921
|
+
}
|
|
2922
|
+
return data;
|
|
2923
|
+
}
|
|
2924
|
+
/**
|
|
2925
|
+
* The runways listed after ALTERNATIVE RWYS, which run to the end of the card. Returns the
|
|
2926
|
+
* index of the line after them.
|
|
2927
|
+
*/
|
|
2928
|
+
alternatives(lines, from, out, unknown) {
|
|
2929
|
+
for (let n = from; n < lines.length; n++) {
|
|
2930
|
+
const line = lines[n];
|
|
2931
|
+
if (line.trim() === "") continue;
|
|
2932
|
+
const m = line.match(ALTERNATIVE);
|
|
2933
|
+
if (!m || n === lines.length - 1) {
|
|
2934
|
+
unknown.push(line.trim());
|
|
2935
|
+
continue;
|
|
2936
|
+
}
|
|
2937
|
+
const name = m[1]?.trim();
|
|
2938
|
+
out.push({
|
|
2939
|
+
runway: m[2],
|
|
2940
|
+
...name === void 0 ? {} : { name },
|
|
2941
|
+
...variant(name ?? m[2])
|
|
2942
|
+
});
|
|
2943
|
+
}
|
|
2944
|
+
return lines.length;
|
|
2945
|
+
}
|
|
2946
|
+
};
|
|
2947
|
+
|
|
2948
|
+
// lib/plugins/Label_11_LRW.ts
|
|
2949
|
+
var RUNWAY2 = /^(\d{1,2}[LRC]?)\s?(?:\/(\S+))?\s+(?:(-\S+|LAHSO)\s+)?(\d{3,5})\s*$/;
|
|
2950
|
+
var Label_11_LRW = class extends DecoderPlugin {
|
|
2951
|
+
name = "label-11-lrw";
|
|
2952
|
+
qualifiers() {
|
|
2953
|
+
return {
|
|
2954
|
+
labels: ["11"],
|
|
2955
|
+
preambles: ["LRW01,"]
|
|
2956
|
+
};
|
|
2957
|
+
}
|
|
2958
|
+
decode(message2, options = {}) {
|
|
2959
|
+
const decodeResult = this.initResult(message2, "Landing Runways");
|
|
2960
|
+
const nl = message2.text.includes("\r\n") ? "\r\n" : "\n";
|
|
2961
|
+
const first = message2.text.match(/^LRW01,(\w{4}) LANDING RUNWAYS,/);
|
|
2962
|
+
if (!first) {
|
|
2963
|
+
return this.failUnknown(decodeResult, message2.text, options);
|
|
2964
|
+
}
|
|
2965
|
+
ResultFormatter.landingAirport(decodeResult, first[1]);
|
|
2966
|
+
const lines = message2.text.slice(first[0].length).split(/\r?\n/);
|
|
2967
|
+
for (const line of lines) {
|
|
2968
|
+
if (line.trim() === "") continue;
|
|
2969
|
+
const m = line.match(RUNWAY2);
|
|
2970
|
+
if (!m) {
|
|
2971
|
+
ResultFormatter.unknown(decodeResult, line.trim(), nl);
|
|
2972
|
+
continue;
|
|
2973
|
+
}
|
|
2974
|
+
const runway2 = [m[2] ? `${m[1]}/${m[2]}` : m[1], m[3]].filter((part) => part !== void 0).join(" ");
|
|
2975
|
+
const description = RunwayUtils.variantDescription(runway2);
|
|
2976
|
+
ResultFormatter.runwayLandingData(decodeResult, {
|
|
2977
|
+
runway: runway2,
|
|
2978
|
+
...description === void 0 ? {} : { variant: description },
|
|
2979
|
+
length: Number(m[4]),
|
|
2980
|
+
stoppingMargins: {}
|
|
2981
|
+
});
|
|
2982
|
+
}
|
|
2983
|
+
this.setDecodeLevel(decodeResult, true);
|
|
2984
|
+
return decodeResult;
|
|
2985
|
+
}
|
|
2986
|
+
};
|
|
2987
|
+
|
|
2222
2988
|
// lib/plugins/Label_12_N_Space.ts
|
|
2223
2989
|
var Label_12_N_Space = class extends DecoderPlugin {
|
|
2224
2990
|
name = "label-12-n-space";
|
|
@@ -3646,11 +4412,718 @@ var Label_30_Slash_EA = class extends DecoderPlugin {
|
|
|
3646
4412
|
}
|
|
3647
4413
|
};
|
|
3648
4414
|
|
|
3649
|
-
// lib/
|
|
3650
|
-
var
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
4415
|
+
// lib/utils/swa_compressed.ts
|
|
4416
|
+
var SWA_ALPHABET = " (),-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
4417
|
+
var SWA_UNREAD = "\xA4";
|
|
4418
|
+
var SWA_LABEL_37_TABLES = {
|
|
4419
|
+
"01": "VIK86MRN5-0PZS4UYXACEHLOTW BGD.123Q(7J9:F)/,",
|
|
4420
|
+
"02": "HG.KZL97QY15WRVTN4JA06(D ,:3MPBICU/8EOFSX)2-",
|
|
4421
|
+
"03": "4GXE/QU5FT)20P8RSJ-169AWHLB.,37MNVCYODIKZ (:",
|
|
4422
|
+
"04": "1BEHMPSUY,048DG269JLOQTWZ (-/37:ACFIKNRVX).5",
|
|
4423
|
+
"05": "3579BDFHJLNPRTVXZ(,.02468:ACEGIKMOQSUWY )-/1",
|
|
4424
|
+
"06": "AGFEDCBRQPONMLKJIH:9876543210/.-,)( ZYXWVUTS",
|
|
4425
|
+
"07": ":.02468ACEGIKMOQSUWY )-/13579BDFHJLNPRTVXZ(,",
|
|
4426
|
+
"08": "1MDS/JQ.OWZ79LNR532-6(: ,APEFTVIKYB08H)U4CXG",
|
|
4427
|
+
"09": "6LQMSR UZYVX(7:3-5KPTACB)021,894NODGJEFIHW./"
|
|
4428
|
+
};
|
|
4429
|
+
var SWA_LABEL_40_TABLES = {
|
|
4430
|
+
"01": "IRXZ2MY3NOP71-S,UVAJBLCWKD(T)E.0F4Q/6G8 H:95",
|
|
4431
|
+
"02": "GEXHZ)QC3YJ:4D0R/IBMOFSU( NA,.K9TL16V8P75W2-",
|
|
4432
|
+
"03": "XY3KAJ-5B4L 0CM7DZEIQT,1(GU:VHNOS6.892/PF)RW",
|
|
4433
|
+
"04": "HIX2JYK3 8L4Z9M5:NO(P6)Q7,RASB-TC.DU/E0VFW1G",
|
|
4434
|
+
"05": "V:WAXBYCZD E(F)G,HI-J.K/L0M1N2O3P4Q5R6S7T8U9",
|
|
4435
|
+
"06": "RQPONMLKJIHGFEDCBA /.-,)(:9876543210ZYXWVUTS",
|
|
4436
|
+
"07": "CYDZE(F)G,H-I.J/K 0L1M2N3O4P5Q6R7S8T9U:VAWBX",
|
|
4437
|
+
"08": "FDUGB0-R A:W9C4S5EHQX)JKZTN.O6(71I/8,LVM2YP3",
|
|
4438
|
+
"09": "/5GK9YZHJI8N: 6LM7DFEQTURWVSA(,OPB).-C03X421"
|
|
4439
|
+
};
|
|
4440
|
+
var PASS_37 = { "*": "*", ">": "+" };
|
|
4441
|
+
var PASS_40 = {
|
|
4442
|
+
"*": "*",
|
|
4443
|
+
"?": "?",
|
|
4444
|
+
"'": "'",
|
|
4445
|
+
"#": "#",
|
|
4446
|
+
_: "_"
|
|
4447
|
+
};
|
|
4448
|
+
function lookup(table, c) {
|
|
4449
|
+
const i = SWA_ALPHABET.indexOf(c);
|
|
4450
|
+
return i < 0 ? void 0 : table[i];
|
|
4451
|
+
}
|
|
4452
|
+
function plain(table, body, pass) {
|
|
4453
|
+
let out = "";
|
|
4454
|
+
for (const c of body) {
|
|
4455
|
+
if (c === "\n") out += "|";
|
|
4456
|
+
else out += lookup(table, c) ?? pass[c] ?? SWA_UNREAD;
|
|
4457
|
+
}
|
|
4458
|
+
return out;
|
|
4459
|
+
}
|
|
4460
|
+
function decodeSwaLabel37(body) {
|
|
4461
|
+
const b = body.replace(/\r/g, "");
|
|
4462
|
+
const table = SWA_LABEL_37_TABLES[b.substring(0, 2)];
|
|
4463
|
+
if (!table) return void 0;
|
|
4464
|
+
let nl = b.indexOf("\n");
|
|
4465
|
+
if (nl !== 7 && b.length > 7 && lookup(table, b[7]) === ",") nl = 7;
|
|
4466
|
+
if (nl < 0 || nl > 8) return void 0;
|
|
4467
|
+
let type = "";
|
|
4468
|
+
for (const c of b.substring(2, Math.min(nl, 7))) {
|
|
4469
|
+
type += lookup(table, c) ?? SWA_UNREAD;
|
|
4470
|
+
}
|
|
4471
|
+
return { type, text: plain(table, b.substring(nl + 1), PASS_37) };
|
|
4472
|
+
}
|
|
4473
|
+
function decodeSwaLabel40(body) {
|
|
4474
|
+
const b = body.replace(/\r/g, "");
|
|
4475
|
+
if (b.startsWith("POS01,")) {
|
|
4476
|
+
return { type: "POS01", text: b.trim() };
|
|
4477
|
+
}
|
|
4478
|
+
const code = b[5] === "," ? b.substring(6, 8) : "";
|
|
4479
|
+
if (code === "00") {
|
|
4480
|
+
return {
|
|
4481
|
+
type: b.substring(0, 5),
|
|
4482
|
+
text: b.substring(8).replace(/\n/g, "|")
|
|
4483
|
+
};
|
|
4484
|
+
}
|
|
4485
|
+
const table = SWA_LABEL_40_TABLES[code];
|
|
4486
|
+
if (!table) return void 0;
|
|
4487
|
+
return {
|
|
4488
|
+
type: b.substring(0, 5),
|
|
4489
|
+
text: plain(table, b.substring(8), PASS_40)
|
|
4490
|
+
};
|
|
4491
|
+
}
|
|
4492
|
+
var SWA_TYPES = {
|
|
4493
|
+
"37": /* @__PURE__ */ new Set([
|
|
4494
|
+
"ADV01",
|
|
4495
|
+
"CLB02",
|
|
4496
|
+
"DIV02",
|
|
4497
|
+
"DVC01",
|
|
4498
|
+
"ETA03",
|
|
4499
|
+
"FCM01",
|
|
4500
|
+
"FCR03",
|
|
4501
|
+
"FFD01",
|
|
4502
|
+
"FHD04",
|
|
4503
|
+
"FLI01",
|
|
4504
|
+
"FTD02",
|
|
4505
|
+
"GAM02",
|
|
4506
|
+
"GSR02",
|
|
4507
|
+
"HGD03",
|
|
4508
|
+
"HLD01",
|
|
4509
|
+
"INN03",
|
|
4510
|
+
"INR04",
|
|
4511
|
+
"MXR03",
|
|
4512
|
+
"OFF02",
|
|
4513
|
+
"OFP01",
|
|
4514
|
+
"ONN02",
|
|
4515
|
+
"OUT03",
|
|
4516
|
+
"PFR03",
|
|
4517
|
+
"PFR04",
|
|
4518
|
+
"PJS01",
|
|
4519
|
+
"PNS01",
|
|
4520
|
+
"POS01",
|
|
4521
|
+
"POS02",
|
|
4522
|
+
"PRM01",
|
|
4523
|
+
"RRR01",
|
|
4524
|
+
"RTG03",
|
|
4525
|
+
"RTG04",
|
|
4526
|
+
"RTG05",
|
|
4527
|
+
"TAR02",
|
|
4528
|
+
"TDM01",
|
|
4529
|
+
"TOD03",
|
|
4530
|
+
"TRB02",
|
|
4531
|
+
"TXI02",
|
|
4532
|
+
"VXR02"
|
|
4533
|
+
]),
|
|
4534
|
+
"40": /* @__PURE__ */ new Set([
|
|
4535
|
+
"ASR01",
|
|
4536
|
+
"DVP01",
|
|
4537
|
+
"FTX01",
|
|
4538
|
+
"GAR03",
|
|
4539
|
+
"GEN01",
|
|
4540
|
+
"PIC01",
|
|
4541
|
+
"POS01",
|
|
4542
|
+
"WFC01"
|
|
4543
|
+
])
|
|
4544
|
+
};
|
|
4545
|
+
function isSwaType(type, label) {
|
|
4546
|
+
return SWA_TYPES[label].has(type);
|
|
4547
|
+
}
|
|
4548
|
+
|
|
4549
|
+
// lib/utils/swa_fields.ts
|
|
4550
|
+
var APT = "(?:[A-Z]{4}| {4}|)";
|
|
4551
|
+
var LAT = "(?:[NS] ?\\d{1,2}\\.\\d{3}|-{4}\\.-{3}|)";
|
|
4552
|
+
var LON = "(?:[EW] ?\\d{1,3}\\.\\d{3}|-{4}\\.-{3}|)";
|
|
4553
|
+
var T4 = "(?:\\d{4}|\\*{4}|-{4})";
|
|
4554
|
+
var FOB = "(?: ?\\d{1,2}\\.\\d|\\*\\*\\.\\*)";
|
|
4555
|
+
var INT = "(?: *-? *\\d+| *|-+|\\*+)";
|
|
4556
|
+
var MACH = "\\.\\d{3}";
|
|
4557
|
+
var HMS = "\\d{6}";
|
|
4558
|
+
var OC = "[OC]";
|
|
4559
|
+
var POS = [
|
|
4560
|
+
APT,
|
|
4561
|
+
APT,
|
|
4562
|
+
LAT,
|
|
4563
|
+
LON,
|
|
4564
|
+
INT,
|
|
4565
|
+
INT,
|
|
4566
|
+
INT,
|
|
4567
|
+
MACH,
|
|
4568
|
+
FOB,
|
|
4569
|
+
T4,
|
|
4570
|
+
INT,
|
|
4571
|
+
INT,
|
|
4572
|
+
INT,
|
|
4573
|
+
INT
|
|
4574
|
+
];
|
|
4575
|
+
var ASR = " *-?\\d+(?:\\.[\\d-])?|XX\\.X";
|
|
4576
|
+
var SWA_LAYOUTS = {
|
|
4577
|
+
ASR01: [[ASR, ASR, ASR, ASR, ASR, ASR, ASR, ASR, "", ""]],
|
|
4578
|
+
CLB02: [[APT, APT, LAT, "", LON, FOB, T4]],
|
|
4579
|
+
ETA03: [[APT, APT, T4, FOB, LAT, LON]],
|
|
4580
|
+
FCM01: [["L[\\d-]", "R[\\d-]", "A[\\d-]", "B[\\d-]", "\\d+", T4]],
|
|
4581
|
+
FHD04: [
|
|
4582
|
+
[
|
|
4583
|
+
...POS,
|
|
4584
|
+
"(?:OUT|OFF|ON|IN|RET IN)",
|
|
4585
|
+
"X",
|
|
4586
|
+
INT,
|
|
4587
|
+
" *\\d*",
|
|
4588
|
+
HMS,
|
|
4589
|
+
"(?:\\d{6}|-{6})",
|
|
4590
|
+
"\\d{5}"
|
|
4591
|
+
]
|
|
4592
|
+
],
|
|
4593
|
+
FLI01: [[APT, APT, T4, FOB, LAT, LON]],
|
|
4594
|
+
GAM02: [[APT, APT, T4, LAT, LON]],
|
|
4595
|
+
GAR03: [
|
|
4596
|
+
[
|
|
4597
|
+
"[A-Z0-9]{1,4} *",
|
|
4598
|
+
"[YN]",
|
|
4599
|
+
"[YN]",
|
|
4600
|
+
"[YN]",
|
|
4601
|
+
"[YN]",
|
|
4602
|
+
"[YN]",
|
|
4603
|
+
"(?:1[23]\\d\\.\\d{1,3}|999\\.999)",
|
|
4604
|
+
"",
|
|
4605
|
+
""
|
|
4606
|
+
]
|
|
4607
|
+
],
|
|
4608
|
+
HGD03: [[...POS, INT]],
|
|
4609
|
+
INN03: [[APT, APT, T4, T4, FOB, OC, OC, OC, OC]],
|
|
4610
|
+
INR04: [[APT, APT, T4, T4, FOB, LAT, LON]],
|
|
4611
|
+
OUT03: [[APT, APT, T4, FOB, FOB, T4]],
|
|
4612
|
+
POS01: [
|
|
4613
|
+
[...POS, INT],
|
|
4614
|
+
[...POS, INT, HMS]
|
|
4615
|
+
],
|
|
4616
|
+
POS02: [[...POS, INT, HMS]],
|
|
4617
|
+
RTG04: [[APT, APT, T4, T4, T4, FOB, OC, OC, OC, OC]],
|
|
4618
|
+
RTG05: [[APT, APT, T4, T4, T4, FOB, OC, OC, OC, OC]],
|
|
4619
|
+
TDM01: [[APT, APT, LAT, LON, "(?:L1|L2|CR|SV)", OC, T4, HMS]],
|
|
4620
|
+
TXI02: [[APT, APT, T4, FOB]],
|
|
4621
|
+
VXR02: [["[A-Z]{3}"]]
|
|
4622
|
+
};
|
|
4623
|
+
var SWA_PREFIX_LAYOUTS = {
|
|
4624
|
+
MXR03: [APT, "(?:\\d{4}|)", "[0-3]"]
|
|
4625
|
+
};
|
|
4626
|
+
function swaFields(text) {
|
|
4627
|
+
return text.replace(/\|/g, ",").split(",");
|
|
4628
|
+
}
|
|
4629
|
+
function swaMatchesLayout(fields, layouts) {
|
|
4630
|
+
return layouts.some(
|
|
4631
|
+
(layout) => layout.length === fields.length && layout.every((rx, i) => new RegExp(`^(?:${rx})$`).test(fields[i]))
|
|
4632
|
+
);
|
|
4633
|
+
}
|
|
4634
|
+
var SwaFieldWriter = class {
|
|
4635
|
+
constructor(decodeResult, fields) {
|
|
4636
|
+
this.decodeResult = decodeResult;
|
|
4637
|
+
this.fields = fields;
|
|
4638
|
+
}
|
|
4639
|
+
decodeResult;
|
|
4640
|
+
fields;
|
|
4641
|
+
used = /* @__PURE__ */ new Set();
|
|
4642
|
+
take(i) {
|
|
4643
|
+
this.used.add(i);
|
|
4644
|
+
return this.fields[i] ?? "";
|
|
4645
|
+
}
|
|
4646
|
+
/** A field with no specific ResultFormatter helper; `key` is its name in `raw`. */
|
|
4647
|
+
item(i, key, code, label, value) {
|
|
4648
|
+
this.used.add(i);
|
|
4649
|
+
ResultFormatter.raw(this.decodeResult, key, code, label, value);
|
|
4650
|
+
}
|
|
4651
|
+
/** Marks a field as read without writing it (it was written together with another). */
|
|
4652
|
+
use(i) {
|
|
4653
|
+
return this.take(i);
|
|
4654
|
+
}
|
|
4655
|
+
departure(i) {
|
|
4656
|
+
const v = this.take(i);
|
|
4657
|
+
if (/^[A-Z]{4}$/.test(v))
|
|
4658
|
+
ResultFormatter.departureAirport(this.decodeResult, v);
|
|
4659
|
+
}
|
|
4660
|
+
arrival(i) {
|
|
4661
|
+
const v = this.take(i);
|
|
4662
|
+
if (/^[A-Z]{4}$/.test(v))
|
|
4663
|
+
ResultFormatter.arrivalAirport(this.decodeResult, v);
|
|
4664
|
+
}
|
|
4665
|
+
/**
|
|
4666
|
+
* Writes the position when both coordinates are present and in range. Otherwise the
|
|
4667
|
+
* placeholders are consumed and any coordinate that was sent stays for `remaining`.
|
|
4668
|
+
*/
|
|
4669
|
+
position(latIndex, lonIndex) {
|
|
4670
|
+
const lat = this.fields[latIndex] ?? "";
|
|
4671
|
+
const lon = this.fields[lonIndex] ?? "";
|
|
4672
|
+
const latitude = /^[NS] ?\d/.test(lat) ? CoordinateUtils.getDirection(lat) * Number(lat.substring(1).trim()) : NaN;
|
|
4673
|
+
const longitude = /^[EW] ?\d/.test(lon) ? CoordinateUtils.getDirection(lon) * Number(lon.substring(1).trim()) : NaN;
|
|
4674
|
+
if (Math.abs(latitude) <= 90 && Math.abs(longitude) <= 180) {
|
|
4675
|
+
this.used.add(latIndex);
|
|
4676
|
+
this.used.add(lonIndex);
|
|
4677
|
+
ResultFormatter.position(this.decodeResult, { latitude, longitude });
|
|
4678
|
+
return;
|
|
4679
|
+
}
|
|
4680
|
+
if (!/^[NS] ?\d/.test(lat)) this.used.add(latIndex);
|
|
4681
|
+
if (!/^[EW] ?\d/.test(lon)) this.used.add(lonIndex);
|
|
4682
|
+
}
|
|
4683
|
+
/** A whole number, or undefined for a placeholder. */
|
|
4684
|
+
int(i) {
|
|
4685
|
+
const v = this.take(i).replace(/ /g, "");
|
|
4686
|
+
return /^-?\d+$/.test(v) ? Number(v) : void 0;
|
|
4687
|
+
}
|
|
4688
|
+
altitude(i) {
|
|
4689
|
+
const v = this.int(i);
|
|
4690
|
+
if (v !== void 0) ResultFormatter.altitude(this.decodeResult, v);
|
|
4691
|
+
}
|
|
4692
|
+
/** Fuel on board, sent in thousands of pounds; written in pounds. */
|
|
4693
|
+
fuel(i) {
|
|
4694
|
+
const v = this.take(i).trim();
|
|
4695
|
+
if (/^\d+\.\d$/.test(v)) {
|
|
4696
|
+
ResultFormatter.currentFuel(
|
|
4697
|
+
this.decodeResult,
|
|
4698
|
+
Math.round(Number(v) * 1e3)
|
|
4699
|
+
);
|
|
4700
|
+
}
|
|
4701
|
+
}
|
|
4702
|
+
/**
|
|
4703
|
+
* HHMM or HHMMSS as seconds of the day. A placeholder is consumed; a time out of range is
|
|
4704
|
+
* left for `remaining`.
|
|
4705
|
+
*/
|
|
4706
|
+
tod(i) {
|
|
4707
|
+
const v = this.fields[i] ?? "";
|
|
4708
|
+
if (/^(?:[01]\d|2[0-3])[0-5]\d(?:[0-5]\d)?$/.test(v)) {
|
|
4709
|
+
this.used.add(i);
|
|
4710
|
+
return DateTimeUtils.convertHHMMSSToTod(v);
|
|
4711
|
+
}
|
|
4712
|
+
if (!/^\d+$/.test(v)) this.used.add(i);
|
|
4713
|
+
return void 0;
|
|
4714
|
+
}
|
|
4715
|
+
/** Writes a time through a ResultFormatter helper such as `out`, `in` or `timestamp`. */
|
|
4716
|
+
time(i, write) {
|
|
4717
|
+
const t = this.tod(i);
|
|
4718
|
+
if (t !== void 0) write(this.decodeResult, t);
|
|
4719
|
+
}
|
|
4720
|
+
/** A time with no ResultFormatter helper, written as HH:MM:SS. */
|
|
4721
|
+
timeItem(i, key, code, label) {
|
|
4722
|
+
const t = this.tod(i);
|
|
4723
|
+
if (t !== void 0) {
|
|
4724
|
+
this.item(i, key, code, label, DateTimeUtils.timestampToString(t));
|
|
4725
|
+
}
|
|
4726
|
+
}
|
|
4727
|
+
eta(i) {
|
|
4728
|
+
this.time(i, (r, t) => ResultFormatter.eta(r, t));
|
|
4729
|
+
}
|
|
4730
|
+
/** Fields not written above, non-empty, to `remaining`. */
|
|
4731
|
+
finish() {
|
|
4732
|
+
const rest = this.fields.filter(
|
|
4733
|
+
(v, i) => !this.used.has(i) && v.trim() !== ""
|
|
4734
|
+
);
|
|
4735
|
+
if (rest.length > 0) ResultFormatter.unknownArr(this.decodeResult, rest);
|
|
4736
|
+
return rest.length;
|
|
4737
|
+
}
|
|
4738
|
+
};
|
|
4739
|
+
|
|
4740
|
+
// lib/plugins/Label_37_SWA.ts
|
|
4741
|
+
var DESCRIPTIONS = {
|
|
4742
|
+
ADV01: "Ride Conditions Report",
|
|
4743
|
+
CLB02: "Climb Report",
|
|
4744
|
+
DVC01: "Divert Plan (Crew Copy)",
|
|
4745
|
+
ETA03: "ETA Report",
|
|
4746
|
+
FCM01: "Engine and Fuel State",
|
|
4747
|
+
FCR03: "Runway Condition Report",
|
|
4748
|
+
FHD04: "Frequency Handoff Report",
|
|
4749
|
+
FLI01: "Flight Initialization",
|
|
4750
|
+
FTD02: "Free Text to Dispatch",
|
|
4751
|
+
GAM02: "Gate Assignment Request",
|
|
4752
|
+
HGD03: "HowGozit Report",
|
|
4753
|
+
HLD01: "Holding Report",
|
|
4754
|
+
INN03: "In Report",
|
|
4755
|
+
INR04: "In Range Report",
|
|
4756
|
+
MXR03: "Maintenance Report",
|
|
4757
|
+
OFF02: "Off Report",
|
|
4758
|
+
ONN02: "On Report",
|
|
4759
|
+
OUT03: "Out Report",
|
|
4760
|
+
PFR03: "Post Flight Report",
|
|
4761
|
+
POS01: "Position Report",
|
|
4762
|
+
POS02: "Position Report",
|
|
4763
|
+
RRR01: "Reroute Report",
|
|
4764
|
+
RTG04: "Return to Gate Report",
|
|
4765
|
+
RTG05: "Return to Gate Report",
|
|
4766
|
+
TDM01: "Door Report",
|
|
4767
|
+
TRB02: "Turbulence Report",
|
|
4768
|
+
TXI02: "Taxi Report",
|
|
4769
|
+
VXR02: "Voice Call Request"
|
|
4770
|
+
};
|
|
4771
|
+
var DOORS = {
|
|
4772
|
+
L1: "L1 (forward entry)",
|
|
4773
|
+
L2: "L2 (aft entry)",
|
|
4774
|
+
CR: "Cargo",
|
|
4775
|
+
SV: "Service"
|
|
4776
|
+
};
|
|
4777
|
+
var MXR_CODES = {
|
|
4778
|
+
"0": "Nothing to report",
|
|
4779
|
+
"1": "Status option",
|
|
4780
|
+
"2": "Category and text",
|
|
4781
|
+
"3": "Free text"
|
|
4782
|
+
};
|
|
4783
|
+
var Label_37_SWA = class extends DecoderPlugin {
|
|
4784
|
+
name = "label-37-swa";
|
|
4785
|
+
qualifiers() {
|
|
4786
|
+
return {
|
|
4787
|
+
labels: ["37"],
|
|
4788
|
+
preambles: ["01", "02", "03", "04", "05", "06", "07", "08", "09"]
|
|
4789
|
+
};
|
|
4790
|
+
}
|
|
4791
|
+
decode(message2, options = {}) {
|
|
4792
|
+
const decodeResult = this.defaultResult();
|
|
4793
|
+
decodeResult.decoder.name = this.name;
|
|
4794
|
+
decodeResult.message = message2;
|
|
4795
|
+
const d = decodeSwaLabel37(message2.text);
|
|
4796
|
+
if (!d || !isSwaType(d.type, "37")) {
|
|
4797
|
+
if (options.debug) {
|
|
4798
|
+
console.log(`Decoder: Unknown 37 message: ${message2.text}`);
|
|
4799
|
+
}
|
|
4800
|
+
ResultFormatter.unknown(decodeResult, message2.text);
|
|
4801
|
+
decodeResult.formatted.description = "Unknown";
|
|
4802
|
+
return decodeResult;
|
|
4803
|
+
}
|
|
4804
|
+
decodeResult.decoded = true;
|
|
4805
|
+
decodeResult.formatted.description = DESCRIPTIONS[d.type] ?? "Southwest Message";
|
|
4806
|
+
decodeResult.raw.preamble = d.type;
|
|
4807
|
+
const text = d.text;
|
|
4808
|
+
const fields = swaFields(text);
|
|
4809
|
+
const layouts = SWA_LAYOUTS[d.type];
|
|
4810
|
+
const prefix = SWA_PREFIX_LAYOUTS[d.type];
|
|
4811
|
+
const clean = !text.includes(SWA_UNREAD);
|
|
4812
|
+
if (clean && layouts && swaMatchesLayout(fields, layouts)) {
|
|
4813
|
+
const rest = this.writeFields(decodeResult, d.type, fields);
|
|
4814
|
+
decodeResult.decoder.decodeLevel = rest === 0 ? "full" : "partial";
|
|
4815
|
+
return decodeResult;
|
|
4816
|
+
}
|
|
4817
|
+
if (clean && prefix && swaMatchesLayout(fields.slice(0, prefix.length), [prefix])) {
|
|
4818
|
+
const rest = this.writeMaintenance(decodeResult, text, fields);
|
|
4819
|
+
decodeResult.decoder.decodeLevel = rest === 0 ? "full" : "partial";
|
|
4820
|
+
return decodeResult;
|
|
4821
|
+
}
|
|
4822
|
+
if (clean && !layouts && !prefix) {
|
|
4823
|
+
const lines = text.split("|");
|
|
4824
|
+
const route = lines[0].match(/^([A-Z]{4}),([A-Z]{4})$/);
|
|
4825
|
+
if (route && d.type === "FTD02") {
|
|
4826
|
+
ResultFormatter.departureAirport(decodeResult, route[1]);
|
|
4827
|
+
ResultFormatter.arrivalAirport(decodeResult, route[2]);
|
|
4828
|
+
lines.shift();
|
|
4829
|
+
}
|
|
4830
|
+
ResultFormatter.text(decodeResult, lines.join("\n"));
|
|
4831
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
4832
|
+
return decodeResult;
|
|
4833
|
+
}
|
|
4834
|
+
ResultFormatter.text(decodeResult, text.split("|").join("\n"));
|
|
4835
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
4836
|
+
return decodeResult;
|
|
4837
|
+
}
|
|
4838
|
+
/** Writes a laid-out type's fields; returns how many went to `remaining`. */
|
|
4839
|
+
writeFields(decodeResult, type, fields) {
|
|
4840
|
+
const w = new SwaFieldWriter(decodeResult, fields);
|
|
4841
|
+
switch (type) {
|
|
4842
|
+
case "POS01":
|
|
4843
|
+
case "POS02":
|
|
4844
|
+
case "HGD03":
|
|
4845
|
+
case "FHD04": {
|
|
4846
|
+
w.departure(0);
|
|
4847
|
+
w.arrival(1);
|
|
4848
|
+
w.position(2, 3);
|
|
4849
|
+
w.altitude(4);
|
|
4850
|
+
const ias = w.int(5);
|
|
4851
|
+
if (ias !== void 0)
|
|
4852
|
+
ResultFormatter.indicatedAirspeed(decodeResult, ias);
|
|
4853
|
+
const tas = w.int(6);
|
|
4854
|
+
if (tas !== void 0) ResultFormatter.airspeed(decodeResult, tas);
|
|
4855
|
+
ResultFormatter.mach(decodeResult, Number(w.use(7)));
|
|
4856
|
+
w.fuel(8);
|
|
4857
|
+
w.eta(9);
|
|
4858
|
+
const track = w.int(10);
|
|
4859
|
+
if (track !== void 0) ResultFormatter.track(decodeResult, track);
|
|
4860
|
+
ResultFormatter.wind(decodeResult, w.int(11), w.int(12));
|
|
4861
|
+
const sat = w.int(13);
|
|
4862
|
+
if (sat !== void 0)
|
|
4863
|
+
ResultFormatter.temperature(decodeResult, `${sat}`);
|
|
4864
|
+
const gwIndex = type === "FHD04" ? 16 : 14;
|
|
4865
|
+
const gw = w.int(gwIndex);
|
|
4866
|
+
if (gw !== void 0) ResultFormatter.grossWeight(decodeResult, gw);
|
|
4867
|
+
if (type !== "FHD04" && fields.length === 16) {
|
|
4868
|
+
w.time(15, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4869
|
+
}
|
|
4870
|
+
if (type === "FHD04") {
|
|
4871
|
+
w.item(14, "event", "EVT", "Event", fields[14]);
|
|
4872
|
+
w.use(15);
|
|
4873
|
+
const freq = w.use(19);
|
|
4874
|
+
if (/^1\d{5}$/.test(freq)) {
|
|
4875
|
+
w.item(
|
|
4876
|
+
19,
|
|
4877
|
+
"frequency",
|
|
4878
|
+
"FREQ",
|
|
4879
|
+
"ACARS Frequency",
|
|
4880
|
+
`${freq.substring(0, 3)}.${freq.substring(3)} MHz`
|
|
4881
|
+
);
|
|
4882
|
+
}
|
|
4883
|
+
}
|
|
4884
|
+
break;
|
|
4885
|
+
}
|
|
4886
|
+
case "GAM02":
|
|
4887
|
+
w.departure(0);
|
|
4888
|
+
w.arrival(1);
|
|
4889
|
+
w.eta(2);
|
|
4890
|
+
w.position(3, 4);
|
|
4891
|
+
break;
|
|
4892
|
+
case "CLB02":
|
|
4893
|
+
w.departure(0);
|
|
4894
|
+
w.arrival(1);
|
|
4895
|
+
w.position(2, 4);
|
|
4896
|
+
w.fuel(5);
|
|
4897
|
+
w.eta(6);
|
|
4898
|
+
break;
|
|
4899
|
+
case "ETA03":
|
|
4900
|
+
w.departure(0);
|
|
4901
|
+
w.arrival(1);
|
|
4902
|
+
w.eta(2);
|
|
4903
|
+
w.fuel(3);
|
|
4904
|
+
w.position(4, 5);
|
|
4905
|
+
break;
|
|
4906
|
+
case "INR04":
|
|
4907
|
+
w.departure(0);
|
|
4908
|
+
w.arrival(1);
|
|
4909
|
+
w.eta(2);
|
|
4910
|
+
w.time(3, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4911
|
+
w.fuel(4);
|
|
4912
|
+
w.position(5, 6);
|
|
4913
|
+
break;
|
|
4914
|
+
case "FLI01":
|
|
4915
|
+
w.departure(0);
|
|
4916
|
+
w.arrival(1);
|
|
4917
|
+
w.time(2, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4918
|
+
w.fuel(3);
|
|
4919
|
+
w.position(4, 5);
|
|
4920
|
+
break;
|
|
4921
|
+
case "OUT03":
|
|
4922
|
+
w.departure(0);
|
|
4923
|
+
w.arrival(1);
|
|
4924
|
+
w.time(2, (r, t) => ResultFormatter.out(r, t));
|
|
4925
|
+
w.fuel(3);
|
|
4926
|
+
w.timeItem(5, "front_door_closed_time", "L1CLS", "Front Door Closed");
|
|
4927
|
+
break;
|
|
4928
|
+
case "TXI02":
|
|
4929
|
+
w.departure(0);
|
|
4930
|
+
w.arrival(1);
|
|
4931
|
+
w.timeItem(2, "taxi_start_time", "TAXI", "Taxi Start Time");
|
|
4932
|
+
w.fuel(3);
|
|
4933
|
+
break;
|
|
4934
|
+
case "INN03":
|
|
4935
|
+
w.departure(0);
|
|
4936
|
+
w.arrival(1);
|
|
4937
|
+
w.time(2, (r, t) => ResultFormatter.in(r, t));
|
|
4938
|
+
w.timeItem(3, "front_door_open_time", "L1OPN", "Front Door Opened");
|
|
4939
|
+
w.fuel(4);
|
|
4940
|
+
break;
|
|
4941
|
+
case "RTG04":
|
|
4942
|
+
case "RTG05":
|
|
4943
|
+
w.departure(0);
|
|
4944
|
+
w.arrival(1);
|
|
4945
|
+
w.time(2, (r, t) => ResultFormatter.out(r, t));
|
|
4946
|
+
w.time(3, (r, t) => ResultFormatter.in(r, t));
|
|
4947
|
+
w.time(4, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4948
|
+
w.fuel(5);
|
|
4949
|
+
break;
|
|
4950
|
+
case "TDM01": {
|
|
4951
|
+
w.departure(0);
|
|
4952
|
+
w.arrival(1);
|
|
4953
|
+
w.position(2, 3);
|
|
4954
|
+
ResultFormatter.door_event(
|
|
4955
|
+
decodeResult,
|
|
4956
|
+
DOORS[w.use(4)],
|
|
4957
|
+
w.use(5) === "O" ? "open" : "closed"
|
|
4958
|
+
);
|
|
4959
|
+
const md = fields[6];
|
|
4960
|
+
if (/^(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])$/.test(md)) {
|
|
4961
|
+
w.use(6);
|
|
4962
|
+
ResultFormatter.month(decodeResult, Number(md.substring(0, 2)));
|
|
4963
|
+
ResultFormatter.day(decodeResult, Number(md.substring(2)));
|
|
4964
|
+
} else if (!/^\d+$/.test(md)) {
|
|
4965
|
+
w.use(6);
|
|
4966
|
+
}
|
|
4967
|
+
w.time(7, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4968
|
+
break;
|
|
4969
|
+
}
|
|
4970
|
+
case "FCM01": {
|
|
4971
|
+
const names = {
|
|
4972
|
+
L: "Left Engine",
|
|
4973
|
+
R: "Right Engine",
|
|
4974
|
+
A: "APU"
|
|
4975
|
+
};
|
|
4976
|
+
for (let i = 0; i < 3; i++) {
|
|
4977
|
+
const v = fields[i];
|
|
4978
|
+
if (v[1] === "0" || v[1] === "1") {
|
|
4979
|
+
w.item(
|
|
4980
|
+
i,
|
|
4981
|
+
`${names[v[0]].toLowerCase().replace(" ", "_")}`,
|
|
4982
|
+
v[0],
|
|
4983
|
+
names[v[0]],
|
|
4984
|
+
v[1] === "1" ? "running" : "off"
|
|
4985
|
+
);
|
|
4986
|
+
}
|
|
4987
|
+
}
|
|
4988
|
+
ResultFormatter.currentFuel(decodeResult, Number(w.use(4)) * 100);
|
|
4989
|
+
w.time(5, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4990
|
+
break;
|
|
4991
|
+
}
|
|
4992
|
+
case "VXR02":
|
|
4993
|
+
w.item(0, "station_iata", "STN", "Station", fields[0]);
|
|
4994
|
+
break;
|
|
4995
|
+
}
|
|
4996
|
+
return w.finish();
|
|
4997
|
+
}
|
|
4998
|
+
/** MXR03: destination, ETA, code, then the category and text; returns how many header
|
|
4999
|
+
* fields went to `remaining`. */
|
|
5000
|
+
writeMaintenance(decodeResult, text, fields) {
|
|
5001
|
+
const w = new SwaFieldWriter(decodeResult, fields.slice(0, 3));
|
|
5002
|
+
w.arrival(0);
|
|
5003
|
+
w.eta(1);
|
|
5004
|
+
w.item(
|
|
5005
|
+
2,
|
|
5006
|
+
"maintenance_code",
|
|
5007
|
+
"MXCODE",
|
|
5008
|
+
"Report Code",
|
|
5009
|
+
`${fields[2]} (${MXR_CODES[fields[2]]})`
|
|
5010
|
+
);
|
|
5011
|
+
const header = text.match(/^[^,|]*[,|][^,|]*[,|][^,|]*[,|]?/);
|
|
5012
|
+
const body = text.substring(header ? header[0].length : 0);
|
|
5013
|
+
if (body.trim() !== "") {
|
|
5014
|
+
ResultFormatter.text(decodeResult, body.split("|").join("\n"));
|
|
5015
|
+
}
|
|
5016
|
+
return w.finish();
|
|
5017
|
+
}
|
|
5018
|
+
};
|
|
5019
|
+
|
|
5020
|
+
// lib/plugins/Label_40_SWA.ts
|
|
5021
|
+
var DESCRIPTIONS2 = {
|
|
5022
|
+
ASR01: "Approach Stability Report",
|
|
5023
|
+
DVP01: "Divert Plan",
|
|
5024
|
+
FTX01: "Dispatch Free Text",
|
|
5025
|
+
GAR03: "Gate Assignment Response",
|
|
5026
|
+
GEN01: "Company Message",
|
|
5027
|
+
PIC01: "Part 117 Duty Extension Request",
|
|
5028
|
+
POS01: "Position Report Request",
|
|
5029
|
+
WFC01: "Field Condition Report"
|
|
5030
|
+
};
|
|
5031
|
+
var ASR01 = [
|
|
5032
|
+
[
|
|
5033
|
+
"reverser_distance",
|
|
5034
|
+
"REVDIST",
|
|
5035
|
+
"Threshold to Thrust Reverser Deployment (feet)"
|
|
5036
|
+
],
|
|
5037
|
+
["max_ias", "MAXIAS", "Highest IAS, 1000 feet to Touchdown (knots)"],
|
|
5038
|
+
["min_ias", "MINIAS", "Lowest IAS, to Touchdown (knots)"],
|
|
5039
|
+
["touchdown_distance", "TDDIST", "Threshold to Touchdown (feet)"],
|
|
5040
|
+
["glideslope_above", "GSHIGH", "Largest Deviation Above Glideslope (dots)"],
|
|
5041
|
+
["glideslope_below", "GSLOW", "Largest Deviation Below Glideslope (dots)"],
|
|
5042
|
+
["max_pitch", "MAXPITCH", "Highest Pitch, Flare and Landing (degrees)"],
|
|
5043
|
+
["tailstrike_pitch", "TSPITCH", "Tail Strike Pitch Limit (degrees)"]
|
|
5044
|
+
];
|
|
5045
|
+
var Label_40_SWA = class extends DecoderPlugin {
|
|
5046
|
+
name = "label-40-swa";
|
|
5047
|
+
qualifiers() {
|
|
5048
|
+
return {
|
|
5049
|
+
labels: ["40"]
|
|
5050
|
+
};
|
|
5051
|
+
}
|
|
5052
|
+
decode(message2, options = {}) {
|
|
5053
|
+
const decodeResult = this.defaultResult();
|
|
5054
|
+
decodeResult.decoder.name = this.name;
|
|
5055
|
+
decodeResult.message = message2;
|
|
5056
|
+
const d = decodeSwaLabel40(message2.text);
|
|
5057
|
+
if (!d || !isSwaType(d.type, "40")) {
|
|
5058
|
+
if (options.debug) {
|
|
5059
|
+
console.log(`Decoder: Unknown 40 message: ${message2.text}`);
|
|
5060
|
+
}
|
|
5061
|
+
ResultFormatter.unknown(decodeResult, message2.text);
|
|
5062
|
+
decodeResult.formatted.description = "Unknown";
|
|
5063
|
+
return decodeResult;
|
|
5064
|
+
}
|
|
5065
|
+
decodeResult.decoded = true;
|
|
5066
|
+
decodeResult.formatted.description = DESCRIPTIONS2[d.type] ?? "Southwest Message";
|
|
5067
|
+
decodeResult.raw.preamble = d.type;
|
|
5068
|
+
if (d.type === "POS01") {
|
|
5069
|
+
const m = d.text.match(/^POS01,Y,(\d{2})$/);
|
|
5070
|
+
if (m) {
|
|
5071
|
+
ResultFormatter.raw(
|
|
5072
|
+
decodeResult,
|
|
5073
|
+
"report_interval",
|
|
5074
|
+
"RPTINT",
|
|
5075
|
+
"Position Report Interval",
|
|
5076
|
+
`${Number(m[1])} minutes`,
|
|
5077
|
+
Number(m[1])
|
|
5078
|
+
);
|
|
5079
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5080
|
+
} else {
|
|
5081
|
+
ResultFormatter.unknown(decodeResult, d.text);
|
|
5082
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5083
|
+
}
|
|
5084
|
+
return decodeResult;
|
|
5085
|
+
}
|
|
5086
|
+
const text = d.text;
|
|
5087
|
+
const fields = swaFields(text);
|
|
5088
|
+
const layouts = SWA_LAYOUTS[d.type];
|
|
5089
|
+
const clean = !text.includes(SWA_UNREAD);
|
|
5090
|
+
if (clean && layouts && swaMatchesLayout(fields, layouts)) {
|
|
5091
|
+
const w = new SwaFieldWriter(decodeResult, fields);
|
|
5092
|
+
if (d.type === "ASR01") {
|
|
5093
|
+
ASR01.forEach(([key, code, label], i) => {
|
|
5094
|
+
const v = fields[i].trim();
|
|
5095
|
+
if (v !== "XX.X") w.item(i, key, code, label, v);
|
|
5096
|
+
else w.use(i);
|
|
5097
|
+
});
|
|
5098
|
+
} else if (d.type === "GAR03") {
|
|
5099
|
+
ResultFormatter.arrivalGate(decodeResult, w.use(0).trim());
|
|
5100
|
+
if (fields[6] !== "999.999") {
|
|
5101
|
+
w.item(
|
|
5102
|
+
6,
|
|
5103
|
+
"ramp_frequency",
|
|
5104
|
+
"RAMPFREQ",
|
|
5105
|
+
"Ramp Frequency",
|
|
5106
|
+
`${fields[6]} MHz`
|
|
5107
|
+
);
|
|
5108
|
+
} else {
|
|
5109
|
+
w.use(6);
|
|
5110
|
+
}
|
|
5111
|
+
}
|
|
5112
|
+
const rest = w.finish();
|
|
5113
|
+
decodeResult.decoder.decodeLevel = rest === 0 ? "full" : "partial";
|
|
5114
|
+
return decodeResult;
|
|
5115
|
+
}
|
|
5116
|
+
ResultFormatter.text(decodeResult, text.split("|").join("\n"));
|
|
5117
|
+
decodeResult.decoder.decodeLevel = clean && !layouts ? "full" : "partial";
|
|
5118
|
+
return decodeResult;
|
|
5119
|
+
}
|
|
5120
|
+
};
|
|
5121
|
+
|
|
5122
|
+
// lib/plugins/Label_44_ETA.ts
|
|
5123
|
+
var Label_44_ETA = class extends DecoderPlugin {
|
|
5124
|
+
name = "label-44-eta";
|
|
5125
|
+
qualifiers() {
|
|
5126
|
+
return {
|
|
3654
5127
|
labels: ["44"],
|
|
3655
5128
|
preambles: ["00ETA01", "00ETA02", "00ETA03", "ETA01", "ETA02", "ETA03"]
|
|
3656
5129
|
};
|
|
@@ -4657,91 +6130,60 @@ var Label_ColonComma = class extends DecoderPlugin {
|
|
|
4657
6130
|
}
|
|
4658
6131
|
};
|
|
4659
6132
|
|
|
4660
|
-
// lib/plugins/
|
|
4661
|
-
var
|
|
4662
|
-
name = "label-
|
|
6133
|
+
// lib/plugins/Label_H1_76401.ts
|
|
6134
|
+
var Label_H1_76401 = class extends DecoderPlugin {
|
|
6135
|
+
name = "label-h1-76401";
|
|
4663
6136
|
qualifiers() {
|
|
4664
6137
|
return {
|
|
4665
|
-
labels: ["
|
|
4666
|
-
preambles: ["
|
|
6138
|
+
labels: ["H1"],
|
|
6139
|
+
preambles: ["76401\r\n"]
|
|
4667
6140
|
};
|
|
4668
6141
|
}
|
|
4669
6142
|
decode(message2, options = {}) {
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
decodeResult.message = message2;
|
|
4674
|
-
const parts = message2.text.split(" ");
|
|
4675
|
-
if (parts[parts.length - 1] !== "Q") {
|
|
4676
|
-
decodeResult.remaining.text = message2.text;
|
|
4677
|
-
decodeResult.decoded = false;
|
|
4678
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
6143
|
+
const decodeResult = this.initResult(message2, "Position Report");
|
|
6144
|
+
const lines = message2.text.split("\r\n");
|
|
6145
|
+
if (lines.length < 3) {
|
|
4679
6146
|
return decodeResult;
|
|
4680
6147
|
}
|
|
4681
|
-
|
|
4682
|
-
decodeResult.
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
const
|
|
4689
|
-
|
|
4690
|
-
|
|
6148
|
+
ResultFormatter.unknown(decodeResult, lines[0], "\r\n");
|
|
6149
|
+
ResultFormatter.unknown(decodeResult, lines[1].substring(0, 5), "\r\n");
|
|
6150
|
+
ResultFormatter.departureAirport(decodeResult, lines[1].substring(5, 9));
|
|
6151
|
+
ResultFormatter.arrivalAirport(decodeResult, lines[1].substring(9, 13));
|
|
6152
|
+
ResultFormatter.unknown(decodeResult, lines[1].substring(13), "");
|
|
6153
|
+
const waypoints = [];
|
|
6154
|
+
for (const line of lines.slice(2)) {
|
|
6155
|
+
const position = CoordinateUtils.decodeStringCoordinates(
|
|
6156
|
+
line.substring(0, 13)
|
|
6157
|
+
);
|
|
6158
|
+
if (position) {
|
|
6159
|
+
waypoints.push({
|
|
6160
|
+
name: line.substring(0, 13),
|
|
6161
|
+
latitude: position.latitude,
|
|
6162
|
+
longitude: position.longitude,
|
|
6163
|
+
time: DateTimeUtils.convertHHMMSSToTod(line.substring(13, 19))
|
|
6164
|
+
});
|
|
4691
6165
|
} else {
|
|
4692
|
-
|
|
6166
|
+
ResultFormatter.unknown(decodeResult, line.substring(0, 19), "");
|
|
4693
6167
|
}
|
|
6168
|
+
ResultFormatter.unknown(decodeResult, line.substring(19), "\r\n");
|
|
4694
6169
|
}
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
6170
|
+
ResultFormatter.route(decodeResult, { waypoints });
|
|
6171
|
+
if (waypoints.length > 0) {
|
|
6172
|
+
const lastWaypoint = waypoints[waypoints.length - 1];
|
|
6173
|
+
if (lastWaypoint.latitude !== void 0 && lastWaypoint.longitude !== void 0) {
|
|
6174
|
+
ResultFormatter.position(decodeResult, {
|
|
6175
|
+
latitude: lastWaypoint.latitude,
|
|
6176
|
+
longitude: lastWaypoint.longitude
|
|
6177
|
+
});
|
|
4700
6178
|
}
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
windData.push(wind);
|
|
4704
|
-
} else {
|
|
4705
|
-
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + part;
|
|
6179
|
+
if (lastWaypoint.time !== void 0) {
|
|
6180
|
+
ResultFormatter.timestamp(decodeResult, lastWaypoint.time);
|
|
4706
6181
|
}
|
|
4707
6182
|
}
|
|
4708
|
-
ResultFormatter.windData(decodeResult, windData);
|
|
4709
6183
|
decodeResult.decoded = true;
|
|
4710
|
-
decodeResult.decoder.decodeLevel =
|
|
6184
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
4711
6185
|
return decodeResult;
|
|
4712
6186
|
}
|
|
4713
|
-
parseWeatherReport(text) {
|
|
4714
|
-
const posString = text.substring(0, 13);
|
|
4715
|
-
const pos = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(posString);
|
|
4716
|
-
if (text.length !== 32 || !pos) {
|
|
4717
|
-
return null;
|
|
4718
|
-
}
|
|
4719
|
-
const tod = DateTimeUtils.convertHHMMSSToTod(text.substring(13, 17));
|
|
4720
|
-
const flightLevel = parseInt(text.substring(17, 20), 10);
|
|
4721
|
-
const tempSign = text[21] === "M" ? -1 : 1;
|
|
4722
|
-
const tempDegreesRaw = parseInt(text.substring(22, 25), 10);
|
|
4723
|
-
const tempDegrees = tempSign * (tempDegreesRaw / 10);
|
|
4724
|
-
const windDirection = parseInt(text.substring(25, 28), 10);
|
|
4725
|
-
const windSpeed = parseInt(text.substring(28, 31), 10);
|
|
4726
|
-
if (text[31] !== "G") {
|
|
4727
|
-
return null;
|
|
4728
|
-
}
|
|
4729
|
-
return {
|
|
4730
|
-
waypoint: {
|
|
4731
|
-
name: posString,
|
|
4732
|
-
latitude: pos.latitude,
|
|
4733
|
-
longitude: pos.longitude,
|
|
4734
|
-
time: tod
|
|
4735
|
-
},
|
|
4736
|
-
flightLevel,
|
|
4737
|
-
windDirection,
|
|
4738
|
-
windSpeed,
|
|
4739
|
-
temperature: {
|
|
4740
|
-
flightLevel,
|
|
4741
|
-
degreesC: tempDegrees
|
|
4742
|
-
}
|
|
4743
|
-
};
|
|
4744
|
-
}
|
|
4745
6187
|
};
|
|
4746
6188
|
|
|
4747
6189
|
// lib/plugins/Label_H1_ATIS.ts
|
|
@@ -4962,11 +6404,11 @@ var Label_H1_M_POS = class extends DecoderPlugin {
|
|
|
4962
6404
|
const timestamp = fields[2].trim();
|
|
4963
6405
|
if (timestamp.length === 6) {
|
|
4964
6406
|
const day = Number(timestamp.substring(0, 2));
|
|
4965
|
-
const
|
|
6407
|
+
const tod2 = DateTimeUtils.convertHHMMSSToTod(
|
|
4966
6408
|
timestamp.substring(2) + "00"
|
|
4967
6409
|
);
|
|
4968
6410
|
ResultFormatter.day(decodeResult, day);
|
|
4969
|
-
ResultFormatter.timestamp(decodeResult,
|
|
6411
|
+
ResultFormatter.timestamp(decodeResult, tod2);
|
|
4970
6412
|
}
|
|
4971
6413
|
const lat = parseFloat(fields[3].replace(/\s/g, ""));
|
|
4972
6414
|
const lon = parseFloat(fields[4].replace(/\s/g, ""));
|
|
@@ -5360,6 +6802,135 @@ var Label_H1_StarPOS = class extends DecoderPlugin {
|
|
|
5360
6802
|
}
|
|
5361
6803
|
};
|
|
5362
6804
|
|
|
6805
|
+
// lib/plugins/Label_H1_SWA_Track.ts
|
|
6806
|
+
var PHASES = {
|
|
6807
|
+
TO: "Takeoff",
|
|
6808
|
+
IC: "Initial Climb",
|
|
6809
|
+
CL: "Climb",
|
|
6810
|
+
CR: "Cruise",
|
|
6811
|
+
ER: "En Route",
|
|
6812
|
+
DC: "Descent",
|
|
6813
|
+
AP: "Approach",
|
|
6814
|
+
RO: "Rollout"
|
|
6815
|
+
};
|
|
6816
|
+
var POINT = /^([NS]\d{4})\.(\d),([EW]\d{5})\.(\d),(\d{2})(\d{2})(\d{2}),\s?(-?\d+),\s?(-?\d+\.\d),(\d{3}),(\d{3}),([A-Z]{2}),(\d{5}),([01]),$/;
|
|
6817
|
+
var Label_H1_SWA_Track = class extends DecoderPlugin {
|
|
6818
|
+
name = "label-h1-swa-track";
|
|
6819
|
+
qualifiers() {
|
|
6820
|
+
return {
|
|
6821
|
+
labels: ["H1"],
|
|
6822
|
+
preambles: ["++76502,", "++86501,", "#DFB++76502,", "#DFB++86501,"]
|
|
6823
|
+
};
|
|
6824
|
+
}
|
|
6825
|
+
decode(message2, options = {}) {
|
|
6826
|
+
const decodeResult = this.initResult(message2, "Track Report");
|
|
6827
|
+
const nl = message2.text.includes("\r\n") ? "\r\n" : "\n";
|
|
6828
|
+
const lines = message2.text.replace(/#DFB/g, "").split(/\r?\n/);
|
|
6829
|
+
const header = lines[0].replace(/^\+\+/, "").split(",");
|
|
6830
|
+
if (header.length !== 9 || !/^\d{6}$/.test(header[3])) {
|
|
6831
|
+
return this.failUnknown(decodeResult, message2.text, options);
|
|
6832
|
+
}
|
|
6833
|
+
const unknown = [];
|
|
6834
|
+
if (/^N\w+$/.test(header[1])) {
|
|
6835
|
+
ResultFormatter.tail(decodeResult, header[1]);
|
|
6836
|
+
} else if (/^\d{1,4}$/.test(header[1])) {
|
|
6837
|
+
ResultFormatter.raw(
|
|
6838
|
+
decodeResult,
|
|
6839
|
+
"ship_number",
|
|
6840
|
+
"SHIP",
|
|
6841
|
+
"Ship Number",
|
|
6842
|
+
header[1]
|
|
6843
|
+
);
|
|
6844
|
+
} else if (header[1] !== "XXX") {
|
|
6845
|
+
unknown.push(header[1]);
|
|
6846
|
+
}
|
|
6847
|
+
ResultFormatter.raw(
|
|
6848
|
+
decodeResult,
|
|
6849
|
+
"aircraft_type",
|
|
6850
|
+
"ACTYPE",
|
|
6851
|
+
"Aircraft Type",
|
|
6852
|
+
header[2]
|
|
6853
|
+
);
|
|
6854
|
+
const d = header[3];
|
|
6855
|
+
ResultFormatter.raw(
|
|
6856
|
+
decodeResult,
|
|
6857
|
+
"report_date",
|
|
6858
|
+
"DATE",
|
|
6859
|
+
"Report Date",
|
|
6860
|
+
`20${d.slice(0, 2)}-${d.slice(2, 4)}-${d.slice(4, 6)}`
|
|
6861
|
+
);
|
|
6862
|
+
ResultFormatter.flightNumber(decodeResult, header[4]);
|
|
6863
|
+
ResultFormatter.departureAirport(decodeResult, header[5]);
|
|
6864
|
+
ResultFormatter.arrivalAirport(decodeResult, header[6]);
|
|
6865
|
+
if (/^\d{1,15}$/.test(header[7])) {
|
|
6866
|
+
ResultFormatter.raw(
|
|
6867
|
+
decodeResult,
|
|
6868
|
+
"leg_counter",
|
|
6869
|
+
"LEGS",
|
|
6870
|
+
"Leg Counter",
|
|
6871
|
+
`${Number(header[7])}`,
|
|
6872
|
+
Number(header[7])
|
|
6873
|
+
);
|
|
6874
|
+
} else {
|
|
6875
|
+
unknown.push(header[7]);
|
|
6876
|
+
}
|
|
6877
|
+
ResultFormatter.raw(
|
|
6878
|
+
decodeResult,
|
|
6879
|
+
"software_version",
|
|
6880
|
+
"SWVER",
|
|
6881
|
+
"Software Version",
|
|
6882
|
+
header[8]
|
|
6883
|
+
);
|
|
6884
|
+
if (unknown.length > 0) ResultFormatter.unknownArr(decodeResult, unknown);
|
|
6885
|
+
const count = lines[1]?.match(/^(\d+),?$/)?.[1];
|
|
6886
|
+
if (lines[1] !== void 0 && count === void 0) {
|
|
6887
|
+
ResultFormatter.unknown(decodeResult, lines[1], nl);
|
|
6888
|
+
}
|
|
6889
|
+
for (const line of lines.slice(2)) {
|
|
6890
|
+
if (line === "" || line === ":") continue;
|
|
6891
|
+
const m = line.match(POINT);
|
|
6892
|
+
if (!m || !(Number(m[5]) >= 1 && Number(m[5]) <= 31) || Number(m[6]) > 23 || Number(m[7]) > 59 || Number(m[10]) > 360 || Number(m[1].slice(3)) > 59 || Number(m[3].slice(4)) > 59) {
|
|
6893
|
+
ResultFormatter.unknown(decodeResult, line, nl);
|
|
6894
|
+
continue;
|
|
6895
|
+
}
|
|
6896
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
|
|
6897
|
+
`${m[1]}${m[2]}${m[3]}${m[4]}`
|
|
6898
|
+
);
|
|
6899
|
+
if (!position || Math.abs(position.latitude) > 90 || Math.abs(position.longitude) > 180) {
|
|
6900
|
+
ResultFormatter.unknown(decodeResult, line, nl);
|
|
6901
|
+
continue;
|
|
6902
|
+
}
|
|
6903
|
+
ResultFormatter.trackPoint(decodeResult, {
|
|
6904
|
+
name: `${m[1]}.${m[2]}${m[3]}.${m[4]}`,
|
|
6905
|
+
...position,
|
|
6906
|
+
day: Number(m[5]),
|
|
6907
|
+
time: Number(m[6]) * 3600 + Number(m[7]) * 60,
|
|
6908
|
+
altitude: Number(m[8]),
|
|
6909
|
+
// -00.0 is sent; keep it as 0
|
|
6910
|
+
temperature: Number(m[9]) || 0,
|
|
6911
|
+
windDirection: Number(m[10]),
|
|
6912
|
+
windSpeed: Number(m[11]),
|
|
6913
|
+
phase: PHASES[m[12]] ?? m[12],
|
|
6914
|
+
humiditySensor: m[14] === "1",
|
|
6915
|
+
...m[14] === "1" && Number(m[13]) > 0 ? { waterVapor: Number(m[13]) } : {}
|
|
6916
|
+
});
|
|
6917
|
+
}
|
|
6918
|
+
const points = decodeResult.raw.route?.waypoints ?? [];
|
|
6919
|
+
const last = points[points.length - 1];
|
|
6920
|
+
if (last) {
|
|
6921
|
+
ResultFormatter.position(decodeResult, {
|
|
6922
|
+
latitude: last.latitude,
|
|
6923
|
+
longitude: last.longitude
|
|
6924
|
+
});
|
|
6925
|
+
ResultFormatter.altitude(decodeResult, last.altitude);
|
|
6926
|
+
ResultFormatter.timestamp(decodeResult, last.time);
|
|
6927
|
+
}
|
|
6928
|
+
const counted = count !== void 0 && Number(count) === points.length;
|
|
6929
|
+
this.setDecodeLevel(decodeResult, true, counted ? void 0 : "partial");
|
|
6930
|
+
return decodeResult;
|
|
6931
|
+
}
|
|
6932
|
+
};
|
|
6933
|
+
|
|
5363
6934
|
// lib/plugins/Label_H1_WRN.ts
|
|
5364
6935
|
var Label_H1_WRN = class extends DecoderPlugin {
|
|
5365
6936
|
name = "label-h1-wrn";
|
|
@@ -5399,6 +6970,93 @@ var Label_H1_WRN = class extends DecoderPlugin {
|
|
|
5399
6970
|
}
|
|
5400
6971
|
};
|
|
5401
6972
|
|
|
6973
|
+
// lib/plugins/Label_H2_02E.ts
|
|
6974
|
+
var Label_H2_02E = class extends DecoderPlugin {
|
|
6975
|
+
name = "label-h2-02e";
|
|
6976
|
+
qualifiers() {
|
|
6977
|
+
return {
|
|
6978
|
+
labels: ["H2"],
|
|
6979
|
+
preambles: ["02E"]
|
|
6980
|
+
};
|
|
6981
|
+
}
|
|
6982
|
+
decode(message2, options = {}) {
|
|
6983
|
+
let decodeResult = this.defaultResult();
|
|
6984
|
+
decodeResult.decoder.name = this.name;
|
|
6985
|
+
decodeResult.formatted.description = "Weather Report";
|
|
6986
|
+
decodeResult.message = message2;
|
|
6987
|
+
const parts = message2.text.split(" ");
|
|
6988
|
+
if (parts[parts.length - 1] !== "Q") {
|
|
6989
|
+
decodeResult.remaining.text = message2.text;
|
|
6990
|
+
decodeResult.decoded = false;
|
|
6991
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
6992
|
+
return decodeResult;
|
|
6993
|
+
}
|
|
6994
|
+
const windData = [];
|
|
6995
|
+
decodeResult.remaining.text = "";
|
|
6996
|
+
const header = parts[0];
|
|
6997
|
+
if (header.length === 45) {
|
|
6998
|
+
ResultFormatter.day(decodeResult, parseInt(header.substring(3, 5), 10));
|
|
6999
|
+
ResultFormatter.departureAirport(decodeResult, header.substring(5, 9));
|
|
7000
|
+
ResultFormatter.arrivalAirport(decodeResult, header.substring(9, 13));
|
|
7001
|
+
const firstWind = this.parseWeatherReport(header.substring(13));
|
|
7002
|
+
if (firstWind) {
|
|
7003
|
+
windData.push(firstWind);
|
|
7004
|
+
} else {
|
|
7005
|
+
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + header.substring(13);
|
|
7006
|
+
}
|
|
7007
|
+
}
|
|
7008
|
+
for (let i = 1; i < parts.length - 1; i++) {
|
|
7009
|
+
const part = parts[i];
|
|
7010
|
+
if (part[0] !== "Q") {
|
|
7011
|
+
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + part;
|
|
7012
|
+
continue;
|
|
7013
|
+
}
|
|
7014
|
+
const wind = this.parseWeatherReport(part.substring(1));
|
|
7015
|
+
if (wind) {
|
|
7016
|
+
windData.push(wind);
|
|
7017
|
+
} else {
|
|
7018
|
+
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + part;
|
|
7019
|
+
}
|
|
7020
|
+
}
|
|
7021
|
+
ResultFormatter.windData(decodeResult, windData);
|
|
7022
|
+
decodeResult.decoded = true;
|
|
7023
|
+
decodeResult.decoder.decodeLevel = decodeResult.remaining.text.length === 0 ? "full" : "partial";
|
|
7024
|
+
return decodeResult;
|
|
7025
|
+
}
|
|
7026
|
+
parseWeatherReport(text) {
|
|
7027
|
+
const posString = text.substring(0, 13);
|
|
7028
|
+
const pos = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(posString);
|
|
7029
|
+
if (text.length !== 32 || !pos) {
|
|
7030
|
+
return null;
|
|
7031
|
+
}
|
|
7032
|
+
const tod2 = DateTimeUtils.convertHHMMSSToTod(text.substring(13, 17));
|
|
7033
|
+
const flightLevel = parseInt(text.substring(17, 20), 10);
|
|
7034
|
+
const tempSign = text[21] === "M" ? -1 : 1;
|
|
7035
|
+
const tempDegreesRaw = parseInt(text.substring(22, 25), 10);
|
|
7036
|
+
const tempDegrees = tempSign * (tempDegreesRaw / 10);
|
|
7037
|
+
const windDirection = parseInt(text.substring(25, 28), 10);
|
|
7038
|
+
const windSpeed = parseInt(text.substring(28, 31), 10);
|
|
7039
|
+
if (text[31] !== "G") {
|
|
7040
|
+
return null;
|
|
7041
|
+
}
|
|
7042
|
+
return {
|
|
7043
|
+
waypoint: {
|
|
7044
|
+
name: posString,
|
|
7045
|
+
latitude: pos.latitude,
|
|
7046
|
+
longitude: pos.longitude,
|
|
7047
|
+
time: tod2
|
|
7048
|
+
},
|
|
7049
|
+
flightLevel,
|
|
7050
|
+
windDirection,
|
|
7051
|
+
windSpeed,
|
|
7052
|
+
temperature: {
|
|
7053
|
+
flightLevel,
|
|
7054
|
+
degreesC: tempDegrees
|
|
7055
|
+
}
|
|
7056
|
+
};
|
|
7057
|
+
}
|
|
7058
|
+
};
|
|
7059
|
+
|
|
5402
7060
|
// lib/plugins/Label_HX.ts
|
|
5403
7061
|
var Label_HX = class extends DecoderPlugin {
|
|
5404
7062
|
name = "label-hx";
|
|
@@ -5471,8 +7129,8 @@ function ascii85Decode(input) {
|
|
|
5471
7129
|
if (digit < 0 || digit > 84) return null;
|
|
5472
7130
|
value = value * 85 + digit;
|
|
5473
7131
|
}
|
|
5474
|
-
if (
|
|
5475
|
-
const v = value
|
|
7132
|
+
if (value > 4294967295) return null;
|
|
7133
|
+
const v = value;
|
|
5476
7134
|
const numBytes = chunkLen === 5 ? 4 : chunkLen - 1;
|
|
5477
7135
|
if (numBytes >= 1) output.push(v >>> 24 & 255);
|
|
5478
7136
|
if (numBytes >= 2) output.push(v >>> 16 & 255);
|
|
@@ -6694,8 +8352,11 @@ var pluginClasses = [
|
|
|
6694
8352
|
Label_ColonComma,
|
|
6695
8353
|
Label_5Z_Slash,
|
|
6696
8354
|
Label_10_LDR,
|
|
8355
|
+
Label_10_LRW,
|
|
6697
8356
|
Label_10_POS,
|
|
6698
8357
|
Label_10_Slash,
|
|
8358
|
+
Label_11_LDR,
|
|
8359
|
+
Label_11_LRW,
|
|
6699
8360
|
Label_12_N_Space,
|
|
6700
8361
|
Label_12_POS,
|
|
6701
8362
|
Label_13Through18_Slash,
|
|
@@ -6719,6 +8380,8 @@ var pluginClasses = [
|
|
|
6719
8380
|
Label_2P_FM4,
|
|
6720
8381
|
Label_2P_FM5,
|
|
6721
8382
|
Label_30_Slash_EA,
|
|
8383
|
+
Label_37_SWA,
|
|
8384
|
+
Label_40_SWA,
|
|
6722
8385
|
Label_44_ETA,
|
|
6723
8386
|
Label_44_IN,
|
|
6724
8387
|
Label_44_OFF,
|
|
@@ -6734,7 +8397,7 @@ var pluginClasses = [
|
|
|
6734
8397
|
Label_4T_AGFSR,
|
|
6735
8398
|
Label_4T_ETA,
|
|
6736
8399
|
Label_B6_Forwardslash,
|
|
6737
|
-
|
|
8400
|
+
Label_H1_76401,
|
|
6738
8401
|
Label_H1_ATIS,
|
|
6739
8402
|
Label_H1_EZF,
|
|
6740
8403
|
Label_H1_FLR,
|
|
@@ -6744,6 +8407,8 @@ var pluginClasses = [
|
|
|
6744
8407
|
Label_H1_Paren,
|
|
6745
8408
|
Label_H1_WRN,
|
|
6746
8409
|
Label_H1_StarPOS,
|
|
8410
|
+
Label_H1_SWA_Track,
|
|
8411
|
+
Label_H2_02E,
|
|
6747
8412
|
Label_HX,
|
|
6748
8413
|
Label_58,
|
|
6749
8414
|
Label_80,
|
|
@@ -6789,6 +8454,9 @@ var MessageDecoder = class {
|
|
|
6789
8454
|
this.wildcardSet.add(plugin);
|
|
6790
8455
|
const wildcardInsertIndex = this.wildcardEntries.length - 1;
|
|
6791
8456
|
for (const bucket of this.candidatesByLabel.values()) {
|
|
8457
|
+
if (bucket.some((e) => e.plugin === plugin)) {
|
|
8458
|
+
continue;
|
|
8459
|
+
}
|
|
6792
8460
|
bucket.splice(wildcardInsertIndex, 0, entry);
|
|
6793
8461
|
}
|
|
6794
8462
|
}
|