@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
|
@@ -76,8 +76,8 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
78
|
static coordinateString(coords) {
|
|
79
|
-
const latDir = coords.latitude
|
|
80
|
-
const lonDir = coords.longitude
|
|
79
|
+
const latDir = coords.latitude >= 0 ? "N" : "S";
|
|
80
|
+
const lonDir = coords.longitude >= 0 ? "E" : "W";
|
|
81
81
|
return `${Math.abs(coords.latitude).toFixed(3)} ${latDir}, ${Math.abs(coords.longitude).toFixed(3)} ${lonDir}`;
|
|
82
82
|
}
|
|
83
83
|
static getDirection(coord) {
|
|
@@ -127,16 +127,16 @@ var DateTimeUtils = class {
|
|
|
127
127
|
const h = Number(time.substring(0, 2));
|
|
128
128
|
const m = Number(time.substring(2, 4));
|
|
129
129
|
const s = Number(time.substring(4, 6));
|
|
130
|
-
const
|
|
131
|
-
return
|
|
130
|
+
const tod2 = h * 3600 + m * 60 + s;
|
|
131
|
+
return tod2;
|
|
132
132
|
}
|
|
133
133
|
static convertDayTimeToTod(time) {
|
|
134
134
|
const d = Number(time.substring(0, 2));
|
|
135
135
|
const h = Number(time.substring(2, 4));
|
|
136
136
|
const m = Number(time.substring(4, 6));
|
|
137
137
|
const s = Number(time.substring(6, 8));
|
|
138
|
-
const
|
|
139
|
-
return
|
|
138
|
+
const tod2 = d * 86400 + h * 3600 + m * 60 + s;
|
|
139
|
+
return tod2;
|
|
140
140
|
}
|
|
141
141
|
/**
|
|
142
142
|
*
|
|
@@ -412,6 +412,16 @@ var ResultFormatter = class {
|
|
|
412
412
|
value: decodeResult.raw.alternate_icao
|
|
413
413
|
});
|
|
414
414
|
}
|
|
415
|
+
/** The airport landing data is for: the destination, or the airport of a divert. */
|
|
416
|
+
static landingAirport(decodeResult, value) {
|
|
417
|
+
decodeResult.raw.landing_icao = value;
|
|
418
|
+
decodeResult.formatted.items.push({
|
|
419
|
+
type: "icao",
|
|
420
|
+
code: "LAND",
|
|
421
|
+
label: "Landing Airport",
|
|
422
|
+
value: decodeResult.raw.landing_icao
|
|
423
|
+
});
|
|
424
|
+
}
|
|
415
425
|
static eta(decodeResult, time) {
|
|
416
426
|
if (isNaN(time)) {
|
|
417
427
|
return;
|
|
@@ -602,6 +612,144 @@ var ResultFormatter = class {
|
|
|
602
612
|
value: `${decodeResult.raw.heading}`
|
|
603
613
|
});
|
|
604
614
|
}
|
|
615
|
+
static indicatedAirspeed(decodeResult, value) {
|
|
616
|
+
if (isNaN(value)) {
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
decodeResult.raw.indicated_airspeed = value;
|
|
620
|
+
decodeResult.formatted.items.push({
|
|
621
|
+
type: "indicated_airspeed",
|
|
622
|
+
code: "IAS",
|
|
623
|
+
label: "Indicated Airspeed",
|
|
624
|
+
value: `${decodeResult.raw.indicated_airspeed} knots`
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
static track(decodeResult, value) {
|
|
628
|
+
if (isNaN(value)) {
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
decodeResult.raw.track = value;
|
|
632
|
+
decodeResult.formatted.items.push({
|
|
633
|
+
type: "track",
|
|
634
|
+
code: "TRK",
|
|
635
|
+
label: "Track",
|
|
636
|
+
value: `${decodeResult.raw.track} degrees`
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
/** Wind at the aircraft; either half may be missing. */
|
|
640
|
+
static wind(decodeResult, direction, speed) {
|
|
641
|
+
const hasDirection = direction !== void 0 && !isNaN(direction);
|
|
642
|
+
const hasSpeed = speed !== void 0 && !isNaN(speed);
|
|
643
|
+
if (hasDirection) decodeResult.raw.wind_direction = direction;
|
|
644
|
+
if (hasSpeed) decodeResult.raw.wind_speed = speed;
|
|
645
|
+
if (!hasDirection && !hasSpeed) {
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
decodeResult.formatted.items.push({
|
|
649
|
+
type: "wind",
|
|
650
|
+
code: "WIND",
|
|
651
|
+
label: !hasSpeed ? "Wind Direction" : !hasDirection ? "Wind Speed" : "Wind",
|
|
652
|
+
value: [
|
|
653
|
+
hasDirection ? `${direction} degrees` : "",
|
|
654
|
+
hasSpeed ? `${speed} knots` : ""
|
|
655
|
+
].filter((s) => s !== "").join(" at ")
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
static variableWind(decodeResult, speed) {
|
|
659
|
+
if (isNaN(speed)) {
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
decodeResult.raw.wind_speed = speed;
|
|
663
|
+
decodeResult.raw.wind_variable = true;
|
|
664
|
+
decodeResult.formatted.items.push({
|
|
665
|
+
type: "wind",
|
|
666
|
+
code: "WIND",
|
|
667
|
+
label: "Wind",
|
|
668
|
+
value: `variable at ${speed} knots`
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* One point of a recorded track. The track is the route as flown, so each point is added to
|
|
673
|
+
* the route's waypoints; the item shows what the aircraft measured there as well.
|
|
674
|
+
*/
|
|
675
|
+
static trackPoint(decodeResult, point) {
|
|
676
|
+
decodeResult.raw.route = {
|
|
677
|
+
...decodeResult.raw.route,
|
|
678
|
+
waypoints: [...decodeResult.raw.route?.waypoints ?? [], point]
|
|
679
|
+
};
|
|
680
|
+
decodeResult.formatted.items.push({
|
|
681
|
+
type: "track_point",
|
|
682
|
+
code: "TRKPT",
|
|
683
|
+
label: "Track Point",
|
|
684
|
+
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`)
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
static runwayLandingData(decodeResult, data) {
|
|
688
|
+
decodeResult.raw.landing_runways = [
|
|
689
|
+
...decodeResult.raw.landing_runways ?? [],
|
|
690
|
+
data
|
|
691
|
+
];
|
|
692
|
+
const parts = [];
|
|
693
|
+
if (data.length !== void 0) parts.push(`${data.length} feet`);
|
|
694
|
+
if (data.flaps !== void 0) parts.push(`flaps ${data.flaps}`);
|
|
695
|
+
if (data.headwind !== void 0) {
|
|
696
|
+
parts.push(
|
|
697
|
+
data.headwind < 0 ? `tailwind ${-data.headwind} knots` : `headwind ${data.headwind} knots`
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
if (data.crosswind !== void 0) {
|
|
701
|
+
const side = { L: " left", R: " right" }[data.crosswindSide ?? "L"];
|
|
702
|
+
parts.push(
|
|
703
|
+
`crosswind ${data.crosswind} knots${data.crosswindSide ? side : ""}`
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
if (data.vref !== void 0) parts.push(`VREF ${data.vref} knots`);
|
|
707
|
+
if (data.vtarget !== void 0) {
|
|
708
|
+
const add = data.additive === void 0 ? "" : ` (${data.additive < 0 ? "" : "+"}${data.additive})`;
|
|
709
|
+
parts.push(`VTGT ${data.vtarget} knots${add}`);
|
|
710
|
+
}
|
|
711
|
+
if (data.maxLandingWeight !== void 0) {
|
|
712
|
+
parts.push(`MRLW ${data.maxLandingWeight}`);
|
|
713
|
+
}
|
|
714
|
+
if (data.landingWeight !== void 0) {
|
|
715
|
+
parts.push(`LDW ${data.landingWeight} pounds`);
|
|
716
|
+
}
|
|
717
|
+
const margins = Object.entries(data.stoppingMargins).map(
|
|
718
|
+
([setting, feet]) => `${setting} ${feet} feet`
|
|
719
|
+
);
|
|
720
|
+
if (margins.length > 0) {
|
|
721
|
+
parts.push(`stopping margin ${margins.join(", ")}`);
|
|
722
|
+
}
|
|
723
|
+
parts.push(...data.notes ?? []);
|
|
724
|
+
const variant2 = data.variant === void 0 ? "" : ` (${data.variant})`;
|
|
725
|
+
decodeResult.formatted.items.push({
|
|
726
|
+
type: "runway_landing_data",
|
|
727
|
+
code: "RWYLDG",
|
|
728
|
+
label: "Runway Landing Data",
|
|
729
|
+
value: `${data.runway}${variant2}: ${parts.join(", ")}`
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
static grossWeight(decodeResult, pounds3) {
|
|
733
|
+
if (isNaN(pounds3)) {
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
decodeResult.raw.gross_weight = pounds3;
|
|
737
|
+
decodeResult.formatted.items.push({
|
|
738
|
+
type: "gross_weight",
|
|
739
|
+
code: "GWT",
|
|
740
|
+
label: "Gross Weight",
|
|
741
|
+
value: `${decodeResult.raw.gross_weight} pounds`
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
static arrivalGate(decodeResult, value) {
|
|
745
|
+
decodeResult.raw.arrival_gate = value;
|
|
746
|
+
decodeResult.formatted.items.push({
|
|
747
|
+
type: "gate",
|
|
748
|
+
code: "AGATE",
|
|
749
|
+
label: "Arrival Gate",
|
|
750
|
+
value: decodeResult.raw.arrival_gate
|
|
751
|
+
});
|
|
752
|
+
}
|
|
605
753
|
static tail(decodeResult, value) {
|
|
606
754
|
decodeResult.raw.tail = value;
|
|
607
755
|
decodeResult.formatted.items.push({
|
|
@@ -805,6 +953,9 @@ var ResultFormatter = class {
|
|
|
805
953
|
}
|
|
806
954
|
}
|
|
807
955
|
static version(decodeResult, value) {
|
|
956
|
+
if (isNaN(value)) {
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
808
959
|
decodeResult.raw.version = value;
|
|
809
960
|
decodeResult.formatted.items.push({
|
|
810
961
|
type: "version",
|
|
@@ -841,6 +992,9 @@ var ResultFormatter = class {
|
|
|
841
992
|
});
|
|
842
993
|
}
|
|
843
994
|
static desiredAltitude(decodeResult, value) {
|
|
995
|
+
if (isNaN(value)) {
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
844
998
|
decodeResult.raw.desired_alt = value;
|
|
845
999
|
decodeResult.formatted.items.push({
|
|
846
1000
|
type: "desired_altitude",
|
|
@@ -915,6 +1069,14 @@ var ResultFormatter = class {
|
|
|
915
1069
|
value: decodeResult.raw.sequence_response.toString()
|
|
916
1070
|
});
|
|
917
1071
|
}
|
|
1072
|
+
/**
|
|
1073
|
+
* A field with no specific helper: `key` is its name in `raw` and its item type. `rawValue`
|
|
1074
|
+
* is stored in `raw` when it differs from the text shown (a number, for example).
|
|
1075
|
+
*/
|
|
1076
|
+
static raw(decodeResult, key, code, label, value, rawValue = value) {
|
|
1077
|
+
decodeResult.raw[key] = rawValue;
|
|
1078
|
+
decodeResult.formatted.items.push({ type: key, code, label, value });
|
|
1079
|
+
}
|
|
918
1080
|
static unknown(decodeResult, value, sep = ",") {
|
|
919
1081
|
if (!decodeResult.remaining.text) decodeResult.remaining.text = value;
|
|
920
1082
|
else decodeResult.remaining.text += sep + value;
|
|
@@ -1260,13 +1422,13 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1260
1422
|
const segments = value.split(".");
|
|
1261
1423
|
const parens_idx = segments[0].indexOf("(");
|
|
1262
1424
|
let name;
|
|
1263
|
-
let
|
|
1425
|
+
let runway2;
|
|
1264
1426
|
if (parens_idx === -1) {
|
|
1265
1427
|
name = segments[0];
|
|
1266
1428
|
} else {
|
|
1267
1429
|
name = segments[0].slice(0, parens_idx);
|
|
1268
1430
|
const close_paren_idx = segments[0].indexOf(")");
|
|
1269
|
-
|
|
1431
|
+
runway2 = segments[0].slice(
|
|
1270
1432
|
parens_idx + 1,
|
|
1271
1433
|
close_paren_idx === -1 ? void 0 : close_paren_idx
|
|
1272
1434
|
);
|
|
@@ -1277,7 +1439,7 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1277
1439
|
}
|
|
1278
1440
|
decodeResult.raw.company_route = {
|
|
1279
1441
|
name,
|
|
1280
|
-
runway,
|
|
1442
|
+
runway: runway2,
|
|
1281
1443
|
waypoints
|
|
1282
1444
|
};
|
|
1283
1445
|
decodeResult.formatted.items.push({
|
|
@@ -1415,6 +1577,9 @@ var Arinc702Helper = class _Arinc702Helper {
|
|
|
1415
1577
|
case "TD":
|
|
1416
1578
|
processTimeOfDeparture(decodeResult, data2.split(","));
|
|
1417
1579
|
break;
|
|
1580
|
+
case "TR":
|
|
1581
|
+
processTR(decodeResult, data2.split(","));
|
|
1582
|
+
break;
|
|
1418
1583
|
case "TS":
|
|
1419
1584
|
_Arinc702Helper.processTimeStamp(decodeResult, data2.split(","));
|
|
1420
1585
|
break;
|
|
@@ -1595,6 +1760,21 @@ function processLandingReport(decodeResult, data) {
|
|
|
1595
1760
|
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
1596
1761
|
}
|
|
1597
1762
|
}
|
|
1763
|
+
function processTR(decodeResult, data) {
|
|
1764
|
+
if (data.length !== 21) {
|
|
1765
|
+
ResultFormatter.unknownArr(decodeResult, data, ",");
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(0, 5), ",");
|
|
1769
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[5]));
|
|
1770
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(6, 11), ",");
|
|
1771
|
+
ResultFormatter.departureAirport(decodeResult, data[11]);
|
|
1772
|
+
ResultFormatter.arrivalAirport(decodeResult, data[12]);
|
|
1773
|
+
ResultFormatter.departureRunway(decodeResult, data[13]);
|
|
1774
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(14, 16), ",");
|
|
1775
|
+
ResultFormatter.flightNumber(decodeResult, data[16]);
|
|
1776
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(17), ",");
|
|
1777
|
+
}
|
|
1598
1778
|
function processCenterOfGravity(decodeResult, data) {
|
|
1599
1779
|
if (data.length === 1) {
|
|
1600
1780
|
if (data[0] !== void 0 && data[0] !== "") {
|
|
@@ -1655,6 +1835,8 @@ function processIMI(decodeResult, type) {
|
|
|
1655
1835
|
decodeResult.formatted.description = "Load Distribution Information";
|
|
1656
1836
|
} else if (type === "PER") {
|
|
1657
1837
|
decodeResult.formatted.description = "Performance Report";
|
|
1838
|
+
} else if (type === "PRF") {
|
|
1839
|
+
decodeResult.formatted.description = "Profile Report";
|
|
1658
1840
|
} else if (type === "POS") {
|
|
1659
1841
|
decodeResult.formatted.description = "Position Report";
|
|
1660
1842
|
} else if (type === "PRG") {
|
|
@@ -2093,7 +2275,54 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
2093
2275
|
}
|
|
2094
2276
|
};
|
|
2095
2277
|
|
|
2278
|
+
// lib/utils/swa_request.ts
|
|
2279
|
+
var AIRLINES = { "189": "Southwest" };
|
|
2280
|
+
function swaRequestHeader(decodeResult, airlineId, layout, software) {
|
|
2281
|
+
const airline = AIRLINES[airlineId];
|
|
2282
|
+
ResultFormatter.raw(
|
|
2283
|
+
decodeResult,
|
|
2284
|
+
"airline_id",
|
|
2285
|
+
"AIRLINE",
|
|
2286
|
+
"Airline ID",
|
|
2287
|
+
airline ? `${airlineId} (${airline})` : airlineId,
|
|
2288
|
+
airlineId
|
|
2289
|
+
);
|
|
2290
|
+
ResultFormatter.raw(
|
|
2291
|
+
decodeResult,
|
|
2292
|
+
"request_layout",
|
|
2293
|
+
"LAYOUT",
|
|
2294
|
+
"Request Layout",
|
|
2295
|
+
layout
|
|
2296
|
+
);
|
|
2297
|
+
ResultFormatter.raw(
|
|
2298
|
+
decodeResult,
|
|
2299
|
+
"software_version",
|
|
2300
|
+
"SWVER",
|
|
2301
|
+
"Software Version",
|
|
2302
|
+
software
|
|
2303
|
+
);
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2096
2306
|
// lib/plugins/Label_10_LDR.ts
|
|
2307
|
+
function pounds(value) {
|
|
2308
|
+
if (value.trim() === "") return void 0;
|
|
2309
|
+
const thousands = Number(value);
|
|
2310
|
+
return Number.isFinite(thousands) ? Math.round(thousands * 1e3) : void 0;
|
|
2311
|
+
}
|
|
2312
|
+
function runway(value) {
|
|
2313
|
+
const [rwy, suffix = ""] = value.trim().split("/");
|
|
2314
|
+
return suffix.trim() === "" ? rwy.trim() : `${rwy.trim()}/${suffix.trim()}`;
|
|
2315
|
+
}
|
|
2316
|
+
var RUNWAY_CONDITION = {
|
|
2317
|
+
6: "dry",
|
|
2318
|
+
5: "good",
|
|
2319
|
+
4: "good to medium",
|
|
2320
|
+
3: "medium",
|
|
2321
|
+
2: "medium to poor",
|
|
2322
|
+
1: "poor",
|
|
2323
|
+
0: "nil"
|
|
2324
|
+
};
|
|
2325
|
+
var FLAPS = { "0": 30, "1": 40, "2": 15 };
|
|
2097
2326
|
var Label_10_LDR = class extends DecoderPlugin {
|
|
2098
2327
|
name = "label-10-ldr";
|
|
2099
2328
|
qualifiers() {
|
|
@@ -2105,18 +2334,13 @@ var Label_10_LDR = class extends DecoderPlugin {
|
|
|
2105
2334
|
decode(message2, options = {}) {
|
|
2106
2335
|
const decodeResult = this.defaultResult();
|
|
2107
2336
|
decodeResult.decoder.name = this.name;
|
|
2108
|
-
decodeResult.formatted.description = "
|
|
2337
|
+
decodeResult.formatted.description = "Landing Data Request";
|
|
2109
2338
|
decodeResult.message = message2;
|
|
2110
2339
|
const parts = message2.text.split(",");
|
|
2111
|
-
if (parts.length <
|
|
2112
|
-
|
|
2113
|
-
console.log(`Decoder: Unknown 10 message: ${message2.text}`);
|
|
2114
|
-
}
|
|
2115
|
-
ResultFormatter.unknown(decodeResult, message2.text);
|
|
2116
|
-
decodeResult.decoded = false;
|
|
2117
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2118
|
-
return decodeResult;
|
|
2340
|
+
if (parts.length < 31) {
|
|
2341
|
+
return this.failUnknown(decodeResult, message2.text, options);
|
|
2119
2342
|
}
|
|
2343
|
+
swaRequestHeader(decodeResult, parts[1], parts[2], parts[3]);
|
|
2120
2344
|
const lat = parts[5];
|
|
2121
2345
|
const lon = parts[6];
|
|
2122
2346
|
const position = {
|
|
@@ -2124,25 +2348,209 @@ var Label_10_LDR = class extends DecoderPlugin {
|
|
|
2124
2348
|
longitude: (lon[0] === "E" ? 1 : -1) * Number(lon.substring(1).trim())
|
|
2125
2349
|
};
|
|
2126
2350
|
ResultFormatter.position(decodeResult, position);
|
|
2127
|
-
|
|
2351
|
+
if (parts[7].trim() !== "") {
|
|
2352
|
+
ResultFormatter.altitude(decodeResult, Number(parts[7]));
|
|
2353
|
+
}
|
|
2354
|
+
const fuel = pounds(parts[8]);
|
|
2355
|
+
if (fuel !== void 0) ResultFormatter.currentFuel(decodeResult, fuel);
|
|
2128
2356
|
ResultFormatter.departureAirport(decodeResult, parts[9]);
|
|
2129
2357
|
ResultFormatter.arrivalAirport(decodeResult, parts[10]);
|
|
2130
|
-
ResultFormatter.
|
|
2131
|
-
ResultFormatter.arrivalRunway(decodeResult, parts[12]
|
|
2132
|
-
const altRwy = [parts[13]
|
|
2358
|
+
ResultFormatter.landingAirport(decodeResult, parts[11]);
|
|
2359
|
+
ResultFormatter.arrivalRunway(decodeResult, runway(parts[12]));
|
|
2360
|
+
const altRwy = [runway(parts[13]), runway(parts[14])].filter((r) => r != "").join(",");
|
|
2133
2361
|
if (altRwy != "") {
|
|
2134
2362
|
ResultFormatter.alternateRunway(decodeResult, altRwy);
|
|
2135
2363
|
}
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2364
|
+
const unknown = [parts[4]];
|
|
2365
|
+
const condition = parts[15].trim();
|
|
2366
|
+
if (/^[1-6]$/.test(condition)) {
|
|
2367
|
+
const code = 6 - Number(condition);
|
|
2368
|
+
ResultFormatter.raw(
|
|
2369
|
+
decodeResult,
|
|
2370
|
+
"runway_condition_code",
|
|
2371
|
+
"RCC",
|
|
2372
|
+
"Runway Condition Code",
|
|
2373
|
+
`${code} (${RUNWAY_CONDITION[code]})`,
|
|
2374
|
+
code
|
|
2375
|
+
);
|
|
2376
|
+
} else if (condition !== "0") {
|
|
2377
|
+
unknown.push(parts[15]);
|
|
2378
|
+
}
|
|
2379
|
+
const flaps = FLAPS[parts[16].trim()];
|
|
2380
|
+
if (flaps !== void 0) {
|
|
2381
|
+
ResultFormatter.raw(
|
|
2382
|
+
decodeResult,
|
|
2383
|
+
"landing_flaps",
|
|
2384
|
+
"FLAPS",
|
|
2385
|
+
"Landing Flaps",
|
|
2386
|
+
`${flaps}`,
|
|
2387
|
+
flaps
|
|
2388
|
+
);
|
|
2389
|
+
} else {
|
|
2390
|
+
unknown.push(parts[16]);
|
|
2391
|
+
}
|
|
2392
|
+
const [windDir, windSpeed, gust, temp, dew, altimeter] = parts.slice(17, 23).map((field) => {
|
|
2393
|
+
const value = field.trim();
|
|
2394
|
+
if (/^-?\d{1,4}$/.test(value)) return Number(value);
|
|
2395
|
+
if (value !== "") unknown.push(field);
|
|
2396
|
+
return void 0;
|
|
2397
|
+
});
|
|
2398
|
+
if (windDir !== void 0 || windSpeed !== void 0) {
|
|
2399
|
+
ResultFormatter.wind(decodeResult, windDir, windSpeed);
|
|
2400
|
+
}
|
|
2401
|
+
if (gust !== void 0) {
|
|
2402
|
+
ResultFormatter.raw(
|
|
2403
|
+
decodeResult,
|
|
2404
|
+
"wind_gust",
|
|
2405
|
+
"GUST",
|
|
2406
|
+
"Wind Gust",
|
|
2407
|
+
`${gust} knots`,
|
|
2408
|
+
gust
|
|
2409
|
+
);
|
|
2410
|
+
}
|
|
2411
|
+
ResultFormatter.temperature(
|
|
2412
|
+
decodeResult,
|
|
2413
|
+
temp === void 0 ? "" : `${temp}`
|
|
2414
|
+
);
|
|
2415
|
+
if (dew !== void 0) {
|
|
2416
|
+
ResultFormatter.raw(
|
|
2417
|
+
decodeResult,
|
|
2418
|
+
"dew_point",
|
|
2419
|
+
"DEWPT",
|
|
2420
|
+
"Dew Point (C)",
|
|
2421
|
+
`${dew} degrees`,
|
|
2422
|
+
dew
|
|
2423
|
+
);
|
|
2424
|
+
}
|
|
2425
|
+
if (altimeter !== void 0) {
|
|
2426
|
+
const inHg = altimeter / 100;
|
|
2427
|
+
ResultFormatter.raw(
|
|
2428
|
+
decodeResult,
|
|
2429
|
+
"altimeter",
|
|
2430
|
+
"ALTIM",
|
|
2431
|
+
"Altimeter",
|
|
2432
|
+
`${inHg.toFixed(2)} inHg`,
|
|
2433
|
+
inHg
|
|
2434
|
+
);
|
|
2435
|
+
}
|
|
2436
|
+
const antiIce = parts[23].trim();
|
|
2437
|
+
if (/^[1-9]$/.test(antiIce)) {
|
|
2438
|
+
ResultFormatter.raw(
|
|
2439
|
+
decodeResult,
|
|
2440
|
+
"anti_ice",
|
|
2441
|
+
"ANTIICE",
|
|
2442
|
+
"Anti-Ice",
|
|
2443
|
+
antiIce === "1" ? "engine" : antiIce,
|
|
2444
|
+
Number(antiIce)
|
|
2445
|
+
);
|
|
2446
|
+
} else if (antiIce !== "0") {
|
|
2447
|
+
unknown.push(parts[23]);
|
|
2448
|
+
}
|
|
2449
|
+
const flags = [
|
|
2450
|
+
[parts[24], "enroute_icing", "ICING", "En Route Icing"],
|
|
2451
|
+
// the card says HGS AIII: 113 of 113 pairs, 32 requests
|
|
2452
|
+
[parts[25], "hgs_approach", "HGS", "HGS Approach"]
|
|
2453
|
+
];
|
|
2454
|
+
for (const [value, key, code, label] of flags) {
|
|
2455
|
+
if (value.trim() === "1") {
|
|
2456
|
+
ResultFormatter.raw(decodeResult, key, code, label, "yes", true);
|
|
2457
|
+
} else if (value.trim() !== "0") {
|
|
2458
|
+
unknown.push(value);
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
const nonNormal = parts[26].trim();
|
|
2462
|
+
if (/^\d+$/.test(nonNormal) && Number(nonNormal) !== 0) {
|
|
2463
|
+
ResultFormatter.raw(
|
|
2464
|
+
decodeResult,
|
|
2465
|
+
"non_normal_configuration",
|
|
2466
|
+
"NNC",
|
|
2467
|
+
"Non-Normal Configuration",
|
|
2468
|
+
`${Number(nonNormal)}`,
|
|
2469
|
+
Number(nonNormal)
|
|
2470
|
+
);
|
|
2471
|
+
} else if (!/^0+$/.test(nonNormal)) {
|
|
2472
|
+
unknown.push(parts[26]);
|
|
2473
|
+
}
|
|
2474
|
+
if (parts[27].trim() !== "") unknown.push(parts[27]);
|
|
2475
|
+
const weights = [
|
|
2476
|
+
["zero_fuel_weight", "ZFW", "Zero Fuel Weight", parts[28]],
|
|
2477
|
+
["landing_fuel", "LFUEL", "Landing Fuel", parts[29]],
|
|
2478
|
+
["landing_weight", "LDW", "Landing Weight", parts[30]]
|
|
2479
|
+
];
|
|
2480
|
+
for (const [key, code, label, value] of weights) {
|
|
2481
|
+
const amount = pounds(value);
|
|
2482
|
+
if (amount === void 0) continue;
|
|
2483
|
+
ResultFormatter.raw(
|
|
2484
|
+
decodeResult,
|
|
2485
|
+
key,
|
|
2486
|
+
code,
|
|
2487
|
+
label,
|
|
2488
|
+
`${amount} pounds`,
|
|
2489
|
+
amount
|
|
2490
|
+
);
|
|
2491
|
+
}
|
|
2492
|
+
const gradient = (parts[31] ?? "").trim();
|
|
2493
|
+
if (/^\d+$/.test(gradient)) {
|
|
2494
|
+
ResultFormatter.raw(
|
|
2495
|
+
decodeResult,
|
|
2496
|
+
"missed_approach_gradient",
|
|
2497
|
+
"MAGRAD",
|
|
2498
|
+
"Missed Approach Climb Gradient",
|
|
2499
|
+
`${Number(gradient)} feet per nautical mile`,
|
|
2500
|
+
Number(gradient)
|
|
2501
|
+
);
|
|
2502
|
+
} else if (gradient !== "" && gradient !== "----.") {
|
|
2503
|
+
unknown.push(parts[31]);
|
|
2504
|
+
}
|
|
2505
|
+
const missedAltitude = (parts[32] ?? "").trim();
|
|
2506
|
+
if (/^\d+$/.test(missedAltitude)) {
|
|
2507
|
+
ResultFormatter.raw(
|
|
2508
|
+
decodeResult,
|
|
2509
|
+
"missed_approach_altitude",
|
|
2510
|
+
"MAALT",
|
|
2511
|
+
"Missed Approach Altitude",
|
|
2512
|
+
`${Number(missedAltitude)} feet`,
|
|
2513
|
+
Number(missedAltitude)
|
|
2514
|
+
);
|
|
2515
|
+
} else if (missedAltitude !== "") {
|
|
2516
|
+
unknown.push(parts[32]);
|
|
2517
|
+
}
|
|
2518
|
+
unknown.push(...parts.slice(33).filter((field) => field.trim() !== ""));
|
|
2519
|
+
ResultFormatter.unknownArr(decodeResult, unknown);
|
|
2140
2520
|
decodeResult.decoded = true;
|
|
2141
2521
|
decodeResult.decoder.decodeLevel = "partial";
|
|
2142
2522
|
return decodeResult;
|
|
2143
2523
|
}
|
|
2144
2524
|
};
|
|
2145
2525
|
|
|
2526
|
+
// lib/plugins/Label_10_LRW.ts
|
|
2527
|
+
var Label_10_LRW = class extends DecoderPlugin {
|
|
2528
|
+
name = "label-10-lrw";
|
|
2529
|
+
qualifiers() {
|
|
2530
|
+
return {
|
|
2531
|
+
labels: ["10"],
|
|
2532
|
+
preambles: ["LRW01,"]
|
|
2533
|
+
};
|
|
2534
|
+
}
|
|
2535
|
+
decode(message2, options = {}) {
|
|
2536
|
+
const decodeResult = this.initResult(message2, "Landing Runways Request");
|
|
2537
|
+
const parts = message2.text.split(",");
|
|
2538
|
+
if (parts.length < 8 || parts[7].trim() === "") {
|
|
2539
|
+
return this.failUnknown(decodeResult, message2.text, options);
|
|
2540
|
+
}
|
|
2541
|
+
swaRequestHeader(decodeResult, parts[1], parts[2], parts[3]);
|
|
2542
|
+
ResultFormatter.departureAirport(decodeResult, parts[6]);
|
|
2543
|
+
ResultFormatter.arrivalAirport(decodeResult, parts[7]);
|
|
2544
|
+
ResultFormatter.unknownArr(decodeResult, [
|
|
2545
|
+
parts[4],
|
|
2546
|
+
parts[5],
|
|
2547
|
+
...parts.slice(8).filter((field) => field.trim() !== "")
|
|
2548
|
+
]);
|
|
2549
|
+
this.setDecodeLevel(decodeResult, true);
|
|
2550
|
+
return decodeResult;
|
|
2551
|
+
}
|
|
2552
|
+
};
|
|
2553
|
+
|
|
2146
2554
|
// lib/plugins/Label_10_POS.ts
|
|
2147
2555
|
var Label_10_POS = class extends DecoderPlugin {
|
|
2148
2556
|
name = "label-10-pos";
|
|
@@ -2242,6 +2650,364 @@ var Label_10_Slash = class extends DecoderPlugin {
|
|
|
2242
2650
|
}
|
|
2243
2651
|
};
|
|
2244
2652
|
|
|
2653
|
+
// lib/utils/runway_utils.ts
|
|
2654
|
+
var SIDES = {
|
|
2655
|
+
N: "north",
|
|
2656
|
+
NE: "northeast",
|
|
2657
|
+
E: "east",
|
|
2658
|
+
SE: "southeast",
|
|
2659
|
+
S: "south",
|
|
2660
|
+
SW: "southwest",
|
|
2661
|
+
W: "west",
|
|
2662
|
+
NW: "northwest"
|
|
2663
|
+
};
|
|
2664
|
+
var RunwayUtils = class {
|
|
2665
|
+
/**
|
|
2666
|
+
* Describe the condition that names a runway variant in Southwest landing data, e.g.
|
|
2667
|
+
* `11/AIB -E1804F`: the runway, the variant's code and its condition.
|
|
2668
|
+
*
|
|
2669
|
+
* -E1804F is 1804 feet taken off the east end, -SWCBL the arresting cable at the southwest
|
|
2670
|
+
* end. Checked on the LRW01 runway lists of six airports, where every variant's length is
|
|
2671
|
+
* the runway's less the feet given, or less 1500 feet for a cable. LAHSO is sent as written.
|
|
2672
|
+
*
|
|
2673
|
+
* @param name - the runway as sent, with its variant
|
|
2674
|
+
* @returns a description of the condition, or undefined when the name has none
|
|
2675
|
+
*/
|
|
2676
|
+
static variantDescription(name) {
|
|
2677
|
+
const text = name.trim();
|
|
2678
|
+
const cut = text.match(/-(NE|NW|SE|SW|N|E|S|W)(\d+)F$/);
|
|
2679
|
+
if (cut) {
|
|
2680
|
+
return `${Number(cut[2])} feet off the ${SIDES[cut[1]]} end`;
|
|
2681
|
+
}
|
|
2682
|
+
const cable = text.match(/-(NE|NW|SE|SW|N|E|S|W)CBL$/);
|
|
2683
|
+
if (cable) {
|
|
2684
|
+
return `arresting cable at the ${SIDES[cable[1]]} end`;
|
|
2685
|
+
}
|
|
2686
|
+
if (/(^|\s)LAHSO$/.test(text)) {
|
|
2687
|
+
return "land and hold short";
|
|
2688
|
+
}
|
|
2689
|
+
return void 0;
|
|
2690
|
+
}
|
|
2691
|
+
};
|
|
2692
|
+
|
|
2693
|
+
// lib/plugins/Label_11_LDR.ts
|
|
2694
|
+
function tod(hours, minutes) {
|
|
2695
|
+
const h = Number(hours);
|
|
2696
|
+
const m = Number(minutes);
|
|
2697
|
+
return h <= 23 && m <= 59 ? h * 3600 + m * 60 : void 0;
|
|
2698
|
+
}
|
|
2699
|
+
function pounds2(value) {
|
|
2700
|
+
return Math.round(Number(value) * 1e3);
|
|
2701
|
+
}
|
|
2702
|
+
function variant(runway2) {
|
|
2703
|
+
const description = RunwayUtils.variantDescription(runway2);
|
|
2704
|
+
return description === void 0 ? {} : { variant: description };
|
|
2705
|
+
}
|
|
2706
|
+
var HEADER = [
|
|
2707
|
+
/^LDR01,(\w{4}) LANDING DATA,FLT(?:\s+METAR-(\d{2})(\d{2})Z)?\s*$/,
|
|
2708
|
+
/^(\d{1,4})\s+WIND\s+LDW\s*$/,
|
|
2709
|
+
/^TIME\s+(\d{3}|VRB)\/(\d{2,3})G(\d{2,3}|--)\s+(\d+\.\d)\s*$/,
|
|
2710
|
+
/^(\d{2})(\d{2})Z\s+OAT\/DEW\s*(\S*)\s*$/,
|
|
2711
|
+
/^\s+(-?\d{2,3})\/(-?\d{2,3})\s*(\S*)\s*$/,
|
|
2712
|
+
/^\s+QNH\s*(\S*)\s*$/,
|
|
2713
|
+
// QNH in inches of mercury, or hectopascals outside the US
|
|
2714
|
+
/^\s+(\d{2}\.\d{2}|\d{4})\s*(\S*)\s*$/
|
|
2715
|
+
];
|
|
2716
|
+
var RUNWAY = /^(\d{1,2}[LRC]?(?:\/\S+)?(?: -\S+)?)\s+(\d{1,5})\s*$/;
|
|
2717
|
+
var RUNWAY_START = /^\d{1,2}[LRC]?(?:\/\S+)?(?: -\S+)?(?:\s{2,}\d*)?\s*$/;
|
|
2718
|
+
var ALTERNATIVES = "--- ALTERNATIVE RWYS ---";
|
|
2719
|
+
var ALTERNATIVE = /^(?:(.+?)\s{2,})?(\d{1,2}[LRC]?(?:\/\S+)?)\s*$/;
|
|
2720
|
+
var BLOCK = [
|
|
2721
|
+
/^FLAPS (\d{2}|--)\s*$/,
|
|
2722
|
+
/^VREF\/VTGT\s+(?:(\d{2})([HT])\/(\d{2})([LR])|---\/---)\s*$/,
|
|
2723
|
+
/^\s*(?:(\d{3})\/(\d{3}) ([+-]\d+)|---\/---)\s+(AB\d)\s+(\d+|----)\s*$/,
|
|
2724
|
+
/^MRLW (\d+\.\d\/\S|-+\/-)\s+(AB\d)\s+(\d+|----)\s*$/,
|
|
2725
|
+
/^\s*LDW (\d+\.\d)\s+(ABM)\s+(\d+|----)\s*$/
|
|
2726
|
+
];
|
|
2727
|
+
var Label_11_LDR = class extends DecoderPlugin {
|
|
2728
|
+
name = "label-11-ldr";
|
|
2729
|
+
qualifiers() {
|
|
2730
|
+
return {
|
|
2731
|
+
labels: ["11"],
|
|
2732
|
+
preambles: ["LDR01,"]
|
|
2733
|
+
};
|
|
2734
|
+
}
|
|
2735
|
+
decode(message2, options = {}) {
|
|
2736
|
+
const decodeResult = this.initResult(message2, "Landing Data");
|
|
2737
|
+
const nl = message2.text.includes("\r\n") ? "\r\n" : "\n";
|
|
2738
|
+
const lines = message2.text.split(/\r?\n/);
|
|
2739
|
+
const first = lines[0].match(HEADER[0]);
|
|
2740
|
+
if (!first) {
|
|
2741
|
+
return this.failUnknown(decodeResult, message2.text, options);
|
|
2742
|
+
}
|
|
2743
|
+
const unknown = [];
|
|
2744
|
+
ResultFormatter.landingAirport(decodeResult, first[1]);
|
|
2745
|
+
const metar = first[2] === void 0 ? void 0 : tod(first[2], first[3]);
|
|
2746
|
+
if (first[2] !== void 0 && metar === void 0) {
|
|
2747
|
+
unknown.push(`METAR-${first[2]}${first[3]}Z`);
|
|
2748
|
+
}
|
|
2749
|
+
if (metar !== void 0) {
|
|
2750
|
+
ResultFormatter.raw(
|
|
2751
|
+
decodeResult,
|
|
2752
|
+
"metar_time",
|
|
2753
|
+
"METAR",
|
|
2754
|
+
"METAR Time",
|
|
2755
|
+
DateTimeUtils.timestampToString(metar),
|
|
2756
|
+
metar
|
|
2757
|
+
);
|
|
2758
|
+
}
|
|
2759
|
+
const runways = [];
|
|
2760
|
+
let i = 1;
|
|
2761
|
+
for (; i < HEADER.length && i < lines.length; i++) {
|
|
2762
|
+
const m = lines[i].match(HEADER[i]);
|
|
2763
|
+
if (!m) break;
|
|
2764
|
+
if (i === 1) {
|
|
2765
|
+
ResultFormatter.flightNumber(decodeResult, m[1]);
|
|
2766
|
+
} else if (i === 2) {
|
|
2767
|
+
if (m[1] === "VRB") {
|
|
2768
|
+
ResultFormatter.variableWind(decodeResult, Number(m[2]));
|
|
2769
|
+
} else {
|
|
2770
|
+
ResultFormatter.wind(decodeResult, Number(m[1]), Number(m[2]));
|
|
2771
|
+
}
|
|
2772
|
+
if (m[3] !== "--") {
|
|
2773
|
+
ResultFormatter.raw(
|
|
2774
|
+
decodeResult,
|
|
2775
|
+
"wind_gust",
|
|
2776
|
+
"GUST",
|
|
2777
|
+
"Wind Gust",
|
|
2778
|
+
`${Number(m[3])} knots`,
|
|
2779
|
+
Number(m[3])
|
|
2780
|
+
);
|
|
2781
|
+
}
|
|
2782
|
+
ResultFormatter.raw(
|
|
2783
|
+
decodeResult,
|
|
2784
|
+
"landing_weight",
|
|
2785
|
+
"LDW",
|
|
2786
|
+
"Landing Weight",
|
|
2787
|
+
`${pounds2(m[4])} pounds`,
|
|
2788
|
+
pounds2(m[4])
|
|
2789
|
+
);
|
|
2790
|
+
} else if (i === 3) {
|
|
2791
|
+
const time = tod(m[1], m[2]);
|
|
2792
|
+
if (time === void 0) {
|
|
2793
|
+
unknown.push(`${m[1]}${m[2]}Z`);
|
|
2794
|
+
} else {
|
|
2795
|
+
ResultFormatter.timestamp(decodeResult, time);
|
|
2796
|
+
}
|
|
2797
|
+
runways.push(m[3]);
|
|
2798
|
+
} else if (i === 4) {
|
|
2799
|
+
ResultFormatter.temperature(decodeResult, `${Number(m[1])}`);
|
|
2800
|
+
ResultFormatter.raw(
|
|
2801
|
+
decodeResult,
|
|
2802
|
+
"dew_point",
|
|
2803
|
+
"DEWPT",
|
|
2804
|
+
"Dew Point (C)",
|
|
2805
|
+
`${Number(m[2])} degrees`,
|
|
2806
|
+
Number(m[2])
|
|
2807
|
+
);
|
|
2808
|
+
runways.push(m[3]);
|
|
2809
|
+
} else if (i === 5) {
|
|
2810
|
+
runways.push(m[1]);
|
|
2811
|
+
} else {
|
|
2812
|
+
ResultFormatter.raw(
|
|
2813
|
+
decodeResult,
|
|
2814
|
+
"altimeter",
|
|
2815
|
+
"ALTIM",
|
|
2816
|
+
"Altimeter",
|
|
2817
|
+
`${m[1]} ${m[1].includes(".") ? "inHg" : "hPa"}`,
|
|
2818
|
+
Number(m[1])
|
|
2819
|
+
);
|
|
2820
|
+
runways.push(m[2]);
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
const listed = runways.filter((r) => r !== "");
|
|
2824
|
+
if (listed.length > 0) {
|
|
2825
|
+
ResultFormatter.raw(
|
|
2826
|
+
decodeResult,
|
|
2827
|
+
"runways",
|
|
2828
|
+
"RWYS",
|
|
2829
|
+
"Runways",
|
|
2830
|
+
listed.join(", "),
|
|
2831
|
+
listed
|
|
2832
|
+
);
|
|
2833
|
+
}
|
|
2834
|
+
const rest = lines.slice(i);
|
|
2835
|
+
let at = 0;
|
|
2836
|
+
const alternatives = [];
|
|
2837
|
+
if (rest[0]?.trim() === "REMARKS") {
|
|
2838
|
+
const remarks = [];
|
|
2839
|
+
for (at = 1; at < rest.length && !RUNWAY_START.test(rest[at]); at++) {
|
|
2840
|
+
if (rest[at].trim() === ALTERNATIVES) {
|
|
2841
|
+
at = this.alternatives(rest, at + 1, alternatives, unknown);
|
|
2842
|
+
break;
|
|
2843
|
+
}
|
|
2844
|
+
if (rest[at].trim() !== "") remarks.push(rest[at].trim());
|
|
2845
|
+
}
|
|
2846
|
+
if (remarks.length > 0) {
|
|
2847
|
+
ResultFormatter.raw(
|
|
2848
|
+
decodeResult,
|
|
2849
|
+
"remarks",
|
|
2850
|
+
"RMK",
|
|
2851
|
+
"Remarks",
|
|
2852
|
+
remarks.join(" ")
|
|
2853
|
+
);
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
if (alternatives.length > 0) {
|
|
2857
|
+
ResultFormatter.raw(
|
|
2858
|
+
decodeResult,
|
|
2859
|
+
"alternative_runways",
|
|
2860
|
+
"ALTRWY",
|
|
2861
|
+
"Alternative Runways",
|
|
2862
|
+
alternatives.map((a) => a.variant ? `${a.runway} (${a.variant})` : a.runway).join(", "),
|
|
2863
|
+
alternatives
|
|
2864
|
+
);
|
|
2865
|
+
}
|
|
2866
|
+
const blocks = [];
|
|
2867
|
+
while (at < rest.length) {
|
|
2868
|
+
const block = this.runwayBlock(rest.slice(at, at + 1 + BLOCK.length));
|
|
2869
|
+
if (block) {
|
|
2870
|
+
blocks.push(block);
|
|
2871
|
+
at += 1 + BLOCK.length;
|
|
2872
|
+
continue;
|
|
2873
|
+
}
|
|
2874
|
+
const line = rest[at];
|
|
2875
|
+
const head = line.match(RUNWAY);
|
|
2876
|
+
const next = rest.slice(at + 1).find((l) => l.trim() !== "");
|
|
2877
|
+
if (head && next !== void 0 && !next.startsWith("FLAPS") && // a FLAPS line cut off by the end of the block
|
|
2878
|
+
!"FLAPS".startsWith(next.trim()) && !RUNWAY_START.test(next)) {
|
|
2879
|
+
blocks.push({
|
|
2880
|
+
runway: head[1],
|
|
2881
|
+
...variant(head[1]),
|
|
2882
|
+
length: Number(head[2]),
|
|
2883
|
+
stoppingMargins: {}
|
|
2884
|
+
});
|
|
2885
|
+
at++;
|
|
2886
|
+
continue;
|
|
2887
|
+
}
|
|
2888
|
+
const last = blocks[blocks.length - 1];
|
|
2889
|
+
if (line.trim() !== "") {
|
|
2890
|
+
if (last && !RUNWAY_START.test(line)) {
|
|
2891
|
+
last.notes = [...last.notes ?? [], line.trim()];
|
|
2892
|
+
} else {
|
|
2893
|
+
unknown.push(...rest.slice(at).filter((l) => l.trim() !== ""));
|
|
2894
|
+
break;
|
|
2895
|
+
}
|
|
2896
|
+
}
|
|
2897
|
+
at++;
|
|
2898
|
+
}
|
|
2899
|
+
for (const block of blocks) {
|
|
2900
|
+
ResultFormatter.runwayLandingData(decodeResult, block);
|
|
2901
|
+
}
|
|
2902
|
+
if (unknown.length > 0) {
|
|
2903
|
+
ResultFormatter.unknown(decodeResult, unknown.join(nl), nl);
|
|
2904
|
+
}
|
|
2905
|
+
this.setDecodeLevel(
|
|
2906
|
+
decodeResult,
|
|
2907
|
+
true,
|
|
2908
|
+
i < HEADER.length ? "partial" : void 0
|
|
2909
|
+
);
|
|
2910
|
+
return decodeResult;
|
|
2911
|
+
}
|
|
2912
|
+
/** The six lines of one runway, or undefined if they are not a whole block. */
|
|
2913
|
+
runwayBlock(lines) {
|
|
2914
|
+
const head = lines[0]?.match(RUNWAY);
|
|
2915
|
+
if (!head || lines.length < 1 + BLOCK.length) return void 0;
|
|
2916
|
+
const m = BLOCK.map((re, n) => lines[n + 1].match(re));
|
|
2917
|
+
if (m.some((x) => !x)) return void 0;
|
|
2918
|
+
const [flaps, wind, speeds, mrlw, ldw] = m;
|
|
2919
|
+
const data = {
|
|
2920
|
+
runway: head[1],
|
|
2921
|
+
...variant(head[1]),
|
|
2922
|
+
length: Number(head[2]),
|
|
2923
|
+
stoppingMargins: {}
|
|
2924
|
+
};
|
|
2925
|
+
if (flaps[1] !== "--") data.flaps = Number(flaps[1]);
|
|
2926
|
+
if (wind[1] !== void 0) {
|
|
2927
|
+
data.headwind = Number(wind[1]) * (wind[2] === "T" ? -1 : 1);
|
|
2928
|
+
data.crosswind = Number(wind[3]);
|
|
2929
|
+
data.crosswindSide = wind[4];
|
|
2930
|
+
}
|
|
2931
|
+
if (speeds[1] !== void 0) {
|
|
2932
|
+
data.vref = Number(speeds[1]);
|
|
2933
|
+
data.vtarget = Number(speeds[2]);
|
|
2934
|
+
data.additive = Number(speeds[3]);
|
|
2935
|
+
}
|
|
2936
|
+
if (!mrlw[1].startsWith("-")) data.maxLandingWeight = mrlw[1];
|
|
2937
|
+
data.landingWeight = pounds2(ldw[1]);
|
|
2938
|
+
for (const [setting, feet] of [
|
|
2939
|
+
[speeds[4], speeds[5]],
|
|
2940
|
+
[mrlw[2], mrlw[3]],
|
|
2941
|
+
[ldw[2], ldw[3]]
|
|
2942
|
+
]) {
|
|
2943
|
+
if (feet !== "----") data.stoppingMargins[setting] = Number(feet);
|
|
2944
|
+
}
|
|
2945
|
+
return data;
|
|
2946
|
+
}
|
|
2947
|
+
/**
|
|
2948
|
+
* The runways listed after ALTERNATIVE RWYS, which run to the end of the card. Returns the
|
|
2949
|
+
* index of the line after them.
|
|
2950
|
+
*/
|
|
2951
|
+
alternatives(lines, from, out, unknown) {
|
|
2952
|
+
for (let n = from; n < lines.length; n++) {
|
|
2953
|
+
const line = lines[n];
|
|
2954
|
+
if (line.trim() === "") continue;
|
|
2955
|
+
const m = line.match(ALTERNATIVE);
|
|
2956
|
+
if (!m || n === lines.length - 1) {
|
|
2957
|
+
unknown.push(line.trim());
|
|
2958
|
+
continue;
|
|
2959
|
+
}
|
|
2960
|
+
const name = m[1]?.trim();
|
|
2961
|
+
out.push({
|
|
2962
|
+
runway: m[2],
|
|
2963
|
+
...name === void 0 ? {} : { name },
|
|
2964
|
+
...variant(name ?? m[2])
|
|
2965
|
+
});
|
|
2966
|
+
}
|
|
2967
|
+
return lines.length;
|
|
2968
|
+
}
|
|
2969
|
+
};
|
|
2970
|
+
|
|
2971
|
+
// lib/plugins/Label_11_LRW.ts
|
|
2972
|
+
var RUNWAY2 = /^(\d{1,2}[LRC]?)\s?(?:\/(\S+))?\s+(?:(-\S+|LAHSO)\s+)?(\d{3,5})\s*$/;
|
|
2973
|
+
var Label_11_LRW = class extends DecoderPlugin {
|
|
2974
|
+
name = "label-11-lrw";
|
|
2975
|
+
qualifiers() {
|
|
2976
|
+
return {
|
|
2977
|
+
labels: ["11"],
|
|
2978
|
+
preambles: ["LRW01,"]
|
|
2979
|
+
};
|
|
2980
|
+
}
|
|
2981
|
+
decode(message2, options = {}) {
|
|
2982
|
+
const decodeResult = this.initResult(message2, "Landing Runways");
|
|
2983
|
+
const nl = message2.text.includes("\r\n") ? "\r\n" : "\n";
|
|
2984
|
+
const first = message2.text.match(/^LRW01,(\w{4}) LANDING RUNWAYS,/);
|
|
2985
|
+
if (!first) {
|
|
2986
|
+
return this.failUnknown(decodeResult, message2.text, options);
|
|
2987
|
+
}
|
|
2988
|
+
ResultFormatter.landingAirport(decodeResult, first[1]);
|
|
2989
|
+
const lines = message2.text.slice(first[0].length).split(/\r?\n/);
|
|
2990
|
+
for (const line of lines) {
|
|
2991
|
+
if (line.trim() === "") continue;
|
|
2992
|
+
const m = line.match(RUNWAY2);
|
|
2993
|
+
if (!m) {
|
|
2994
|
+
ResultFormatter.unknown(decodeResult, line.trim(), nl);
|
|
2995
|
+
continue;
|
|
2996
|
+
}
|
|
2997
|
+
const runway2 = [m[2] ? `${m[1]}/${m[2]}` : m[1], m[3]].filter((part) => part !== void 0).join(" ");
|
|
2998
|
+
const description = RunwayUtils.variantDescription(runway2);
|
|
2999
|
+
ResultFormatter.runwayLandingData(decodeResult, {
|
|
3000
|
+
runway: runway2,
|
|
3001
|
+
...description === void 0 ? {} : { variant: description },
|
|
3002
|
+
length: Number(m[4]),
|
|
3003
|
+
stoppingMargins: {}
|
|
3004
|
+
});
|
|
3005
|
+
}
|
|
3006
|
+
this.setDecodeLevel(decodeResult, true);
|
|
3007
|
+
return decodeResult;
|
|
3008
|
+
}
|
|
3009
|
+
};
|
|
3010
|
+
|
|
2245
3011
|
// lib/plugins/Label_12_N_Space.ts
|
|
2246
3012
|
var Label_12_N_Space = class extends DecoderPlugin {
|
|
2247
3013
|
name = "label-12-n-space";
|
|
@@ -3669,11 +4435,718 @@ var Label_30_Slash_EA = class extends DecoderPlugin {
|
|
|
3669
4435
|
}
|
|
3670
4436
|
};
|
|
3671
4437
|
|
|
3672
|
-
// lib/
|
|
3673
|
-
var
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
4438
|
+
// lib/utils/swa_compressed.ts
|
|
4439
|
+
var SWA_ALPHABET = " (),-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
4440
|
+
var SWA_UNREAD = "\xA4";
|
|
4441
|
+
var SWA_LABEL_37_TABLES = {
|
|
4442
|
+
"01": "VIK86MRN5-0PZS4UYXACEHLOTW BGD.123Q(7J9:F)/,",
|
|
4443
|
+
"02": "HG.KZL97QY15WRVTN4JA06(D ,:3MPBICU/8EOFSX)2-",
|
|
4444
|
+
"03": "4GXE/QU5FT)20P8RSJ-169AWHLB.,37MNVCYODIKZ (:",
|
|
4445
|
+
"04": "1BEHMPSUY,048DG269JLOQTWZ (-/37:ACFIKNRVX).5",
|
|
4446
|
+
"05": "3579BDFHJLNPRTVXZ(,.02468:ACEGIKMOQSUWY )-/1",
|
|
4447
|
+
"06": "AGFEDCBRQPONMLKJIH:9876543210/.-,)( ZYXWVUTS",
|
|
4448
|
+
"07": ":.02468ACEGIKMOQSUWY )-/13579BDFHJLNPRTVXZ(,",
|
|
4449
|
+
"08": "1MDS/JQ.OWZ79LNR532-6(: ,APEFTVIKYB08H)U4CXG",
|
|
4450
|
+
"09": "6LQMSR UZYVX(7:3-5KPTACB)021,894NODGJEFIHW./"
|
|
4451
|
+
};
|
|
4452
|
+
var SWA_LABEL_40_TABLES = {
|
|
4453
|
+
"01": "IRXZ2MY3NOP71-S,UVAJBLCWKD(T)E.0F4Q/6G8 H:95",
|
|
4454
|
+
"02": "GEXHZ)QC3YJ:4D0R/IBMOFSU( NA,.K9TL16V8P75W2-",
|
|
4455
|
+
"03": "XY3KAJ-5B4L 0CM7DZEIQT,1(GU:VHNOS6.892/PF)RW",
|
|
4456
|
+
"04": "HIX2JYK3 8L4Z9M5:NO(P6)Q7,RASB-TC.DU/E0VFW1G",
|
|
4457
|
+
"05": "V:WAXBYCZD E(F)G,HI-J.K/L0M1N2O3P4Q5R6S7T8U9",
|
|
4458
|
+
"06": "RQPONMLKJIHGFEDCBA /.-,)(:9876543210ZYXWVUTS",
|
|
4459
|
+
"07": "CYDZE(F)G,H-I.J/K 0L1M2N3O4P5Q6R7S8T9U:VAWBX",
|
|
4460
|
+
"08": "FDUGB0-R A:W9C4S5EHQX)JKZTN.O6(71I/8,LVM2YP3",
|
|
4461
|
+
"09": "/5GK9YZHJI8N: 6LM7DFEQTURWVSA(,OPB).-C03X421"
|
|
4462
|
+
};
|
|
4463
|
+
var PASS_37 = { "*": "*", ">": "+" };
|
|
4464
|
+
var PASS_40 = {
|
|
4465
|
+
"*": "*",
|
|
4466
|
+
"?": "?",
|
|
4467
|
+
"'": "'",
|
|
4468
|
+
"#": "#",
|
|
4469
|
+
_: "_"
|
|
4470
|
+
};
|
|
4471
|
+
function lookup(table, c) {
|
|
4472
|
+
const i = SWA_ALPHABET.indexOf(c);
|
|
4473
|
+
return i < 0 ? void 0 : table[i];
|
|
4474
|
+
}
|
|
4475
|
+
function plain(table, body, pass) {
|
|
4476
|
+
let out = "";
|
|
4477
|
+
for (const c of body) {
|
|
4478
|
+
if (c === "\n") out += "|";
|
|
4479
|
+
else out += lookup(table, c) ?? pass[c] ?? SWA_UNREAD;
|
|
4480
|
+
}
|
|
4481
|
+
return out;
|
|
4482
|
+
}
|
|
4483
|
+
function decodeSwaLabel37(body) {
|
|
4484
|
+
const b = body.replace(/\r/g, "");
|
|
4485
|
+
const table = SWA_LABEL_37_TABLES[b.substring(0, 2)];
|
|
4486
|
+
if (!table) return void 0;
|
|
4487
|
+
let nl = b.indexOf("\n");
|
|
4488
|
+
if (nl !== 7 && b.length > 7 && lookup(table, b[7]) === ",") nl = 7;
|
|
4489
|
+
if (nl < 0 || nl > 8) return void 0;
|
|
4490
|
+
let type = "";
|
|
4491
|
+
for (const c of b.substring(2, Math.min(nl, 7))) {
|
|
4492
|
+
type += lookup(table, c) ?? SWA_UNREAD;
|
|
4493
|
+
}
|
|
4494
|
+
return { type, text: plain(table, b.substring(nl + 1), PASS_37) };
|
|
4495
|
+
}
|
|
4496
|
+
function decodeSwaLabel40(body) {
|
|
4497
|
+
const b = body.replace(/\r/g, "");
|
|
4498
|
+
if (b.startsWith("POS01,")) {
|
|
4499
|
+
return { type: "POS01", text: b.trim() };
|
|
4500
|
+
}
|
|
4501
|
+
const code = b[5] === "," ? b.substring(6, 8) : "";
|
|
4502
|
+
if (code === "00") {
|
|
4503
|
+
return {
|
|
4504
|
+
type: b.substring(0, 5),
|
|
4505
|
+
text: b.substring(8).replace(/\n/g, "|")
|
|
4506
|
+
};
|
|
4507
|
+
}
|
|
4508
|
+
const table = SWA_LABEL_40_TABLES[code];
|
|
4509
|
+
if (!table) return void 0;
|
|
4510
|
+
return {
|
|
4511
|
+
type: b.substring(0, 5),
|
|
4512
|
+
text: plain(table, b.substring(8), PASS_40)
|
|
4513
|
+
};
|
|
4514
|
+
}
|
|
4515
|
+
var SWA_TYPES = {
|
|
4516
|
+
"37": /* @__PURE__ */ new Set([
|
|
4517
|
+
"ADV01",
|
|
4518
|
+
"CLB02",
|
|
4519
|
+
"DIV02",
|
|
4520
|
+
"DVC01",
|
|
4521
|
+
"ETA03",
|
|
4522
|
+
"FCM01",
|
|
4523
|
+
"FCR03",
|
|
4524
|
+
"FFD01",
|
|
4525
|
+
"FHD04",
|
|
4526
|
+
"FLI01",
|
|
4527
|
+
"FTD02",
|
|
4528
|
+
"GAM02",
|
|
4529
|
+
"GSR02",
|
|
4530
|
+
"HGD03",
|
|
4531
|
+
"HLD01",
|
|
4532
|
+
"INN03",
|
|
4533
|
+
"INR04",
|
|
4534
|
+
"MXR03",
|
|
4535
|
+
"OFF02",
|
|
4536
|
+
"OFP01",
|
|
4537
|
+
"ONN02",
|
|
4538
|
+
"OUT03",
|
|
4539
|
+
"PFR03",
|
|
4540
|
+
"PFR04",
|
|
4541
|
+
"PJS01",
|
|
4542
|
+
"PNS01",
|
|
4543
|
+
"POS01",
|
|
4544
|
+
"POS02",
|
|
4545
|
+
"PRM01",
|
|
4546
|
+
"RRR01",
|
|
4547
|
+
"RTG03",
|
|
4548
|
+
"RTG04",
|
|
4549
|
+
"RTG05",
|
|
4550
|
+
"TAR02",
|
|
4551
|
+
"TDM01",
|
|
4552
|
+
"TOD03",
|
|
4553
|
+
"TRB02",
|
|
4554
|
+
"TXI02",
|
|
4555
|
+
"VXR02"
|
|
4556
|
+
]),
|
|
4557
|
+
"40": /* @__PURE__ */ new Set([
|
|
4558
|
+
"ASR01",
|
|
4559
|
+
"DVP01",
|
|
4560
|
+
"FTX01",
|
|
4561
|
+
"GAR03",
|
|
4562
|
+
"GEN01",
|
|
4563
|
+
"PIC01",
|
|
4564
|
+
"POS01",
|
|
4565
|
+
"WFC01"
|
|
4566
|
+
])
|
|
4567
|
+
};
|
|
4568
|
+
function isSwaType(type, label) {
|
|
4569
|
+
return SWA_TYPES[label].has(type);
|
|
4570
|
+
}
|
|
4571
|
+
|
|
4572
|
+
// lib/utils/swa_fields.ts
|
|
4573
|
+
var APT = "(?:[A-Z]{4}| {4}|)";
|
|
4574
|
+
var LAT = "(?:[NS] ?\\d{1,2}\\.\\d{3}|-{4}\\.-{3}|)";
|
|
4575
|
+
var LON = "(?:[EW] ?\\d{1,3}\\.\\d{3}|-{4}\\.-{3}|)";
|
|
4576
|
+
var T4 = "(?:\\d{4}|\\*{4}|-{4})";
|
|
4577
|
+
var FOB = "(?: ?\\d{1,2}\\.\\d|\\*\\*\\.\\*)";
|
|
4578
|
+
var INT = "(?: *-? *\\d+| *|-+|\\*+)";
|
|
4579
|
+
var MACH = "\\.\\d{3}";
|
|
4580
|
+
var HMS = "\\d{6}";
|
|
4581
|
+
var OC = "[OC]";
|
|
4582
|
+
var POS = [
|
|
4583
|
+
APT,
|
|
4584
|
+
APT,
|
|
4585
|
+
LAT,
|
|
4586
|
+
LON,
|
|
4587
|
+
INT,
|
|
4588
|
+
INT,
|
|
4589
|
+
INT,
|
|
4590
|
+
MACH,
|
|
4591
|
+
FOB,
|
|
4592
|
+
T4,
|
|
4593
|
+
INT,
|
|
4594
|
+
INT,
|
|
4595
|
+
INT,
|
|
4596
|
+
INT
|
|
4597
|
+
];
|
|
4598
|
+
var ASR = " *-?\\d+(?:\\.[\\d-])?|XX\\.X";
|
|
4599
|
+
var SWA_LAYOUTS = {
|
|
4600
|
+
ASR01: [[ASR, ASR, ASR, ASR, ASR, ASR, ASR, ASR, "", ""]],
|
|
4601
|
+
CLB02: [[APT, APT, LAT, "", LON, FOB, T4]],
|
|
4602
|
+
ETA03: [[APT, APT, T4, FOB, LAT, LON]],
|
|
4603
|
+
FCM01: [["L[\\d-]", "R[\\d-]", "A[\\d-]", "B[\\d-]", "\\d+", T4]],
|
|
4604
|
+
FHD04: [
|
|
4605
|
+
[
|
|
4606
|
+
...POS,
|
|
4607
|
+
"(?:OUT|OFF|ON|IN|RET IN)",
|
|
4608
|
+
"X",
|
|
4609
|
+
INT,
|
|
4610
|
+
" *\\d*",
|
|
4611
|
+
HMS,
|
|
4612
|
+
"(?:\\d{6}|-{6})",
|
|
4613
|
+
"\\d{5}"
|
|
4614
|
+
]
|
|
4615
|
+
],
|
|
4616
|
+
FLI01: [[APT, APT, T4, FOB, LAT, LON]],
|
|
4617
|
+
GAM02: [[APT, APT, T4, LAT, LON]],
|
|
4618
|
+
GAR03: [
|
|
4619
|
+
[
|
|
4620
|
+
"[A-Z0-9]{1,4} *",
|
|
4621
|
+
"[YN]",
|
|
4622
|
+
"[YN]",
|
|
4623
|
+
"[YN]",
|
|
4624
|
+
"[YN]",
|
|
4625
|
+
"[YN]",
|
|
4626
|
+
"(?:1[23]\\d\\.\\d{1,3}|999\\.999)",
|
|
4627
|
+
"",
|
|
4628
|
+
""
|
|
4629
|
+
]
|
|
4630
|
+
],
|
|
4631
|
+
HGD03: [[...POS, INT]],
|
|
4632
|
+
INN03: [[APT, APT, T4, T4, FOB, OC, OC, OC, OC]],
|
|
4633
|
+
INR04: [[APT, APT, T4, T4, FOB, LAT, LON]],
|
|
4634
|
+
OUT03: [[APT, APT, T4, FOB, FOB, T4]],
|
|
4635
|
+
POS01: [
|
|
4636
|
+
[...POS, INT],
|
|
4637
|
+
[...POS, INT, HMS]
|
|
4638
|
+
],
|
|
4639
|
+
POS02: [[...POS, INT, HMS]],
|
|
4640
|
+
RTG04: [[APT, APT, T4, T4, T4, FOB, OC, OC, OC, OC]],
|
|
4641
|
+
RTG05: [[APT, APT, T4, T4, T4, FOB, OC, OC, OC, OC]],
|
|
4642
|
+
TDM01: [[APT, APT, LAT, LON, "(?:L1|L2|CR|SV)", OC, T4, HMS]],
|
|
4643
|
+
TXI02: [[APT, APT, T4, FOB]],
|
|
4644
|
+
VXR02: [["[A-Z]{3}"]]
|
|
4645
|
+
};
|
|
4646
|
+
var SWA_PREFIX_LAYOUTS = {
|
|
4647
|
+
MXR03: [APT, "(?:\\d{4}|)", "[0-3]"]
|
|
4648
|
+
};
|
|
4649
|
+
function swaFields(text) {
|
|
4650
|
+
return text.replace(/\|/g, ",").split(",");
|
|
4651
|
+
}
|
|
4652
|
+
function swaMatchesLayout(fields, layouts) {
|
|
4653
|
+
return layouts.some(
|
|
4654
|
+
(layout) => layout.length === fields.length && layout.every((rx, i) => new RegExp(`^(?:${rx})$`).test(fields[i]))
|
|
4655
|
+
);
|
|
4656
|
+
}
|
|
4657
|
+
var SwaFieldWriter = class {
|
|
4658
|
+
constructor(decodeResult, fields) {
|
|
4659
|
+
this.decodeResult = decodeResult;
|
|
4660
|
+
this.fields = fields;
|
|
4661
|
+
}
|
|
4662
|
+
decodeResult;
|
|
4663
|
+
fields;
|
|
4664
|
+
used = /* @__PURE__ */ new Set();
|
|
4665
|
+
take(i) {
|
|
4666
|
+
this.used.add(i);
|
|
4667
|
+
return this.fields[i] ?? "";
|
|
4668
|
+
}
|
|
4669
|
+
/** A field with no specific ResultFormatter helper; `key` is its name in `raw`. */
|
|
4670
|
+
item(i, key, code, label, value) {
|
|
4671
|
+
this.used.add(i);
|
|
4672
|
+
ResultFormatter.raw(this.decodeResult, key, code, label, value);
|
|
4673
|
+
}
|
|
4674
|
+
/** Marks a field as read without writing it (it was written together with another). */
|
|
4675
|
+
use(i) {
|
|
4676
|
+
return this.take(i);
|
|
4677
|
+
}
|
|
4678
|
+
departure(i) {
|
|
4679
|
+
const v = this.take(i);
|
|
4680
|
+
if (/^[A-Z]{4}$/.test(v))
|
|
4681
|
+
ResultFormatter.departureAirport(this.decodeResult, v);
|
|
4682
|
+
}
|
|
4683
|
+
arrival(i) {
|
|
4684
|
+
const v = this.take(i);
|
|
4685
|
+
if (/^[A-Z]{4}$/.test(v))
|
|
4686
|
+
ResultFormatter.arrivalAirport(this.decodeResult, v);
|
|
4687
|
+
}
|
|
4688
|
+
/**
|
|
4689
|
+
* Writes the position when both coordinates are present and in range. Otherwise the
|
|
4690
|
+
* placeholders are consumed and any coordinate that was sent stays for `remaining`.
|
|
4691
|
+
*/
|
|
4692
|
+
position(latIndex, lonIndex) {
|
|
4693
|
+
const lat = this.fields[latIndex] ?? "";
|
|
4694
|
+
const lon = this.fields[lonIndex] ?? "";
|
|
4695
|
+
const latitude = /^[NS] ?\d/.test(lat) ? CoordinateUtils.getDirection(lat) * Number(lat.substring(1).trim()) : NaN;
|
|
4696
|
+
const longitude = /^[EW] ?\d/.test(lon) ? CoordinateUtils.getDirection(lon) * Number(lon.substring(1).trim()) : NaN;
|
|
4697
|
+
if (Math.abs(latitude) <= 90 && Math.abs(longitude) <= 180) {
|
|
4698
|
+
this.used.add(latIndex);
|
|
4699
|
+
this.used.add(lonIndex);
|
|
4700
|
+
ResultFormatter.position(this.decodeResult, { latitude, longitude });
|
|
4701
|
+
return;
|
|
4702
|
+
}
|
|
4703
|
+
if (!/^[NS] ?\d/.test(lat)) this.used.add(latIndex);
|
|
4704
|
+
if (!/^[EW] ?\d/.test(lon)) this.used.add(lonIndex);
|
|
4705
|
+
}
|
|
4706
|
+
/** A whole number, or undefined for a placeholder. */
|
|
4707
|
+
int(i) {
|
|
4708
|
+
const v = this.take(i).replace(/ /g, "");
|
|
4709
|
+
return /^-?\d+$/.test(v) ? Number(v) : void 0;
|
|
4710
|
+
}
|
|
4711
|
+
altitude(i) {
|
|
4712
|
+
const v = this.int(i);
|
|
4713
|
+
if (v !== void 0) ResultFormatter.altitude(this.decodeResult, v);
|
|
4714
|
+
}
|
|
4715
|
+
/** Fuel on board, sent in thousands of pounds; written in pounds. */
|
|
4716
|
+
fuel(i) {
|
|
4717
|
+
const v = this.take(i).trim();
|
|
4718
|
+
if (/^\d+\.\d$/.test(v)) {
|
|
4719
|
+
ResultFormatter.currentFuel(
|
|
4720
|
+
this.decodeResult,
|
|
4721
|
+
Math.round(Number(v) * 1e3)
|
|
4722
|
+
);
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
4725
|
+
/**
|
|
4726
|
+
* HHMM or HHMMSS as seconds of the day. A placeholder is consumed; a time out of range is
|
|
4727
|
+
* left for `remaining`.
|
|
4728
|
+
*/
|
|
4729
|
+
tod(i) {
|
|
4730
|
+
const v = this.fields[i] ?? "";
|
|
4731
|
+
if (/^(?:[01]\d|2[0-3])[0-5]\d(?:[0-5]\d)?$/.test(v)) {
|
|
4732
|
+
this.used.add(i);
|
|
4733
|
+
return DateTimeUtils.convertHHMMSSToTod(v);
|
|
4734
|
+
}
|
|
4735
|
+
if (!/^\d+$/.test(v)) this.used.add(i);
|
|
4736
|
+
return void 0;
|
|
4737
|
+
}
|
|
4738
|
+
/** Writes a time through a ResultFormatter helper such as `out`, `in` or `timestamp`. */
|
|
4739
|
+
time(i, write) {
|
|
4740
|
+
const t = this.tod(i);
|
|
4741
|
+
if (t !== void 0) write(this.decodeResult, t);
|
|
4742
|
+
}
|
|
4743
|
+
/** A time with no ResultFormatter helper, written as HH:MM:SS. */
|
|
4744
|
+
timeItem(i, key, code, label) {
|
|
4745
|
+
const t = this.tod(i);
|
|
4746
|
+
if (t !== void 0) {
|
|
4747
|
+
this.item(i, key, code, label, DateTimeUtils.timestampToString(t));
|
|
4748
|
+
}
|
|
4749
|
+
}
|
|
4750
|
+
eta(i) {
|
|
4751
|
+
this.time(i, (r, t) => ResultFormatter.eta(r, t));
|
|
4752
|
+
}
|
|
4753
|
+
/** Fields not written above, non-empty, to `remaining`. */
|
|
4754
|
+
finish() {
|
|
4755
|
+
const rest = this.fields.filter(
|
|
4756
|
+
(v, i) => !this.used.has(i) && v.trim() !== ""
|
|
4757
|
+
);
|
|
4758
|
+
if (rest.length > 0) ResultFormatter.unknownArr(this.decodeResult, rest);
|
|
4759
|
+
return rest.length;
|
|
4760
|
+
}
|
|
4761
|
+
};
|
|
4762
|
+
|
|
4763
|
+
// lib/plugins/Label_37_SWA.ts
|
|
4764
|
+
var DESCRIPTIONS = {
|
|
4765
|
+
ADV01: "Ride Conditions Report",
|
|
4766
|
+
CLB02: "Climb Report",
|
|
4767
|
+
DVC01: "Divert Plan (Crew Copy)",
|
|
4768
|
+
ETA03: "ETA Report",
|
|
4769
|
+
FCM01: "Engine and Fuel State",
|
|
4770
|
+
FCR03: "Runway Condition Report",
|
|
4771
|
+
FHD04: "Frequency Handoff Report",
|
|
4772
|
+
FLI01: "Flight Initialization",
|
|
4773
|
+
FTD02: "Free Text to Dispatch",
|
|
4774
|
+
GAM02: "Gate Assignment Request",
|
|
4775
|
+
HGD03: "HowGozit Report",
|
|
4776
|
+
HLD01: "Holding Report",
|
|
4777
|
+
INN03: "In Report",
|
|
4778
|
+
INR04: "In Range Report",
|
|
4779
|
+
MXR03: "Maintenance Report",
|
|
4780
|
+
OFF02: "Off Report",
|
|
4781
|
+
ONN02: "On Report",
|
|
4782
|
+
OUT03: "Out Report",
|
|
4783
|
+
PFR03: "Post Flight Report",
|
|
4784
|
+
POS01: "Position Report",
|
|
4785
|
+
POS02: "Position Report",
|
|
4786
|
+
RRR01: "Reroute Report",
|
|
4787
|
+
RTG04: "Return to Gate Report",
|
|
4788
|
+
RTG05: "Return to Gate Report",
|
|
4789
|
+
TDM01: "Door Report",
|
|
4790
|
+
TRB02: "Turbulence Report",
|
|
4791
|
+
TXI02: "Taxi Report",
|
|
4792
|
+
VXR02: "Voice Call Request"
|
|
4793
|
+
};
|
|
4794
|
+
var DOORS = {
|
|
4795
|
+
L1: "L1 (forward entry)",
|
|
4796
|
+
L2: "L2 (aft entry)",
|
|
4797
|
+
CR: "Cargo",
|
|
4798
|
+
SV: "Service"
|
|
4799
|
+
};
|
|
4800
|
+
var MXR_CODES = {
|
|
4801
|
+
"0": "Nothing to report",
|
|
4802
|
+
"1": "Status option",
|
|
4803
|
+
"2": "Category and text",
|
|
4804
|
+
"3": "Free text"
|
|
4805
|
+
};
|
|
4806
|
+
var Label_37_SWA = class extends DecoderPlugin {
|
|
4807
|
+
name = "label-37-swa";
|
|
4808
|
+
qualifiers() {
|
|
4809
|
+
return {
|
|
4810
|
+
labels: ["37"],
|
|
4811
|
+
preambles: ["01", "02", "03", "04", "05", "06", "07", "08", "09"]
|
|
4812
|
+
};
|
|
4813
|
+
}
|
|
4814
|
+
decode(message2, options = {}) {
|
|
4815
|
+
const decodeResult = this.defaultResult();
|
|
4816
|
+
decodeResult.decoder.name = this.name;
|
|
4817
|
+
decodeResult.message = message2;
|
|
4818
|
+
const d = decodeSwaLabel37(message2.text);
|
|
4819
|
+
if (!d || !isSwaType(d.type, "37")) {
|
|
4820
|
+
if (options.debug) {
|
|
4821
|
+
console.log(`Decoder: Unknown 37 message: ${message2.text}`);
|
|
4822
|
+
}
|
|
4823
|
+
ResultFormatter.unknown(decodeResult, message2.text);
|
|
4824
|
+
decodeResult.formatted.description = "Unknown";
|
|
4825
|
+
return decodeResult;
|
|
4826
|
+
}
|
|
4827
|
+
decodeResult.decoded = true;
|
|
4828
|
+
decodeResult.formatted.description = DESCRIPTIONS[d.type] ?? "Southwest Message";
|
|
4829
|
+
decodeResult.raw.preamble = d.type;
|
|
4830
|
+
const text = d.text;
|
|
4831
|
+
const fields = swaFields(text);
|
|
4832
|
+
const layouts = SWA_LAYOUTS[d.type];
|
|
4833
|
+
const prefix = SWA_PREFIX_LAYOUTS[d.type];
|
|
4834
|
+
const clean = !text.includes(SWA_UNREAD);
|
|
4835
|
+
if (clean && layouts && swaMatchesLayout(fields, layouts)) {
|
|
4836
|
+
const rest = this.writeFields(decodeResult, d.type, fields);
|
|
4837
|
+
decodeResult.decoder.decodeLevel = rest === 0 ? "full" : "partial";
|
|
4838
|
+
return decodeResult;
|
|
4839
|
+
}
|
|
4840
|
+
if (clean && prefix && swaMatchesLayout(fields.slice(0, prefix.length), [prefix])) {
|
|
4841
|
+
const rest = this.writeMaintenance(decodeResult, text, fields);
|
|
4842
|
+
decodeResult.decoder.decodeLevel = rest === 0 ? "full" : "partial";
|
|
4843
|
+
return decodeResult;
|
|
4844
|
+
}
|
|
4845
|
+
if (clean && !layouts && !prefix) {
|
|
4846
|
+
const lines = text.split("|");
|
|
4847
|
+
const route = lines[0].match(/^([A-Z]{4}),([A-Z]{4})$/);
|
|
4848
|
+
if (route && d.type === "FTD02") {
|
|
4849
|
+
ResultFormatter.departureAirport(decodeResult, route[1]);
|
|
4850
|
+
ResultFormatter.arrivalAirport(decodeResult, route[2]);
|
|
4851
|
+
lines.shift();
|
|
4852
|
+
}
|
|
4853
|
+
ResultFormatter.text(decodeResult, lines.join("\n"));
|
|
4854
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
4855
|
+
return decodeResult;
|
|
4856
|
+
}
|
|
4857
|
+
ResultFormatter.text(decodeResult, text.split("|").join("\n"));
|
|
4858
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
4859
|
+
return decodeResult;
|
|
4860
|
+
}
|
|
4861
|
+
/** Writes a laid-out type's fields; returns how many went to `remaining`. */
|
|
4862
|
+
writeFields(decodeResult, type, fields) {
|
|
4863
|
+
const w = new SwaFieldWriter(decodeResult, fields);
|
|
4864
|
+
switch (type) {
|
|
4865
|
+
case "POS01":
|
|
4866
|
+
case "POS02":
|
|
4867
|
+
case "HGD03":
|
|
4868
|
+
case "FHD04": {
|
|
4869
|
+
w.departure(0);
|
|
4870
|
+
w.arrival(1);
|
|
4871
|
+
w.position(2, 3);
|
|
4872
|
+
w.altitude(4);
|
|
4873
|
+
const ias = w.int(5);
|
|
4874
|
+
if (ias !== void 0)
|
|
4875
|
+
ResultFormatter.indicatedAirspeed(decodeResult, ias);
|
|
4876
|
+
const tas = w.int(6);
|
|
4877
|
+
if (tas !== void 0) ResultFormatter.airspeed(decodeResult, tas);
|
|
4878
|
+
ResultFormatter.mach(decodeResult, Number(w.use(7)));
|
|
4879
|
+
w.fuel(8);
|
|
4880
|
+
w.eta(9);
|
|
4881
|
+
const track = w.int(10);
|
|
4882
|
+
if (track !== void 0) ResultFormatter.track(decodeResult, track);
|
|
4883
|
+
ResultFormatter.wind(decodeResult, w.int(11), w.int(12));
|
|
4884
|
+
const sat = w.int(13);
|
|
4885
|
+
if (sat !== void 0)
|
|
4886
|
+
ResultFormatter.temperature(decodeResult, `${sat}`);
|
|
4887
|
+
const gwIndex = type === "FHD04" ? 16 : 14;
|
|
4888
|
+
const gw = w.int(gwIndex);
|
|
4889
|
+
if (gw !== void 0) ResultFormatter.grossWeight(decodeResult, gw);
|
|
4890
|
+
if (type !== "FHD04" && fields.length === 16) {
|
|
4891
|
+
w.time(15, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4892
|
+
}
|
|
4893
|
+
if (type === "FHD04") {
|
|
4894
|
+
w.item(14, "event", "EVT", "Event", fields[14]);
|
|
4895
|
+
w.use(15);
|
|
4896
|
+
const freq = w.use(19);
|
|
4897
|
+
if (/^1\d{5}$/.test(freq)) {
|
|
4898
|
+
w.item(
|
|
4899
|
+
19,
|
|
4900
|
+
"frequency",
|
|
4901
|
+
"FREQ",
|
|
4902
|
+
"ACARS Frequency",
|
|
4903
|
+
`${freq.substring(0, 3)}.${freq.substring(3)} MHz`
|
|
4904
|
+
);
|
|
4905
|
+
}
|
|
4906
|
+
}
|
|
4907
|
+
break;
|
|
4908
|
+
}
|
|
4909
|
+
case "GAM02":
|
|
4910
|
+
w.departure(0);
|
|
4911
|
+
w.arrival(1);
|
|
4912
|
+
w.eta(2);
|
|
4913
|
+
w.position(3, 4);
|
|
4914
|
+
break;
|
|
4915
|
+
case "CLB02":
|
|
4916
|
+
w.departure(0);
|
|
4917
|
+
w.arrival(1);
|
|
4918
|
+
w.position(2, 4);
|
|
4919
|
+
w.fuel(5);
|
|
4920
|
+
w.eta(6);
|
|
4921
|
+
break;
|
|
4922
|
+
case "ETA03":
|
|
4923
|
+
w.departure(0);
|
|
4924
|
+
w.arrival(1);
|
|
4925
|
+
w.eta(2);
|
|
4926
|
+
w.fuel(3);
|
|
4927
|
+
w.position(4, 5);
|
|
4928
|
+
break;
|
|
4929
|
+
case "INR04":
|
|
4930
|
+
w.departure(0);
|
|
4931
|
+
w.arrival(1);
|
|
4932
|
+
w.eta(2);
|
|
4933
|
+
w.time(3, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4934
|
+
w.fuel(4);
|
|
4935
|
+
w.position(5, 6);
|
|
4936
|
+
break;
|
|
4937
|
+
case "FLI01":
|
|
4938
|
+
w.departure(0);
|
|
4939
|
+
w.arrival(1);
|
|
4940
|
+
w.time(2, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4941
|
+
w.fuel(3);
|
|
4942
|
+
w.position(4, 5);
|
|
4943
|
+
break;
|
|
4944
|
+
case "OUT03":
|
|
4945
|
+
w.departure(0);
|
|
4946
|
+
w.arrival(1);
|
|
4947
|
+
w.time(2, (r, t) => ResultFormatter.out(r, t));
|
|
4948
|
+
w.fuel(3);
|
|
4949
|
+
w.timeItem(5, "front_door_closed_time", "L1CLS", "Front Door Closed");
|
|
4950
|
+
break;
|
|
4951
|
+
case "TXI02":
|
|
4952
|
+
w.departure(0);
|
|
4953
|
+
w.arrival(1);
|
|
4954
|
+
w.timeItem(2, "taxi_start_time", "TAXI", "Taxi Start Time");
|
|
4955
|
+
w.fuel(3);
|
|
4956
|
+
break;
|
|
4957
|
+
case "INN03":
|
|
4958
|
+
w.departure(0);
|
|
4959
|
+
w.arrival(1);
|
|
4960
|
+
w.time(2, (r, t) => ResultFormatter.in(r, t));
|
|
4961
|
+
w.timeItem(3, "front_door_open_time", "L1OPN", "Front Door Opened");
|
|
4962
|
+
w.fuel(4);
|
|
4963
|
+
break;
|
|
4964
|
+
case "RTG04":
|
|
4965
|
+
case "RTG05":
|
|
4966
|
+
w.departure(0);
|
|
4967
|
+
w.arrival(1);
|
|
4968
|
+
w.time(2, (r, t) => ResultFormatter.out(r, t));
|
|
4969
|
+
w.time(3, (r, t) => ResultFormatter.in(r, t));
|
|
4970
|
+
w.time(4, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4971
|
+
w.fuel(5);
|
|
4972
|
+
break;
|
|
4973
|
+
case "TDM01": {
|
|
4974
|
+
w.departure(0);
|
|
4975
|
+
w.arrival(1);
|
|
4976
|
+
w.position(2, 3);
|
|
4977
|
+
ResultFormatter.door_event(
|
|
4978
|
+
decodeResult,
|
|
4979
|
+
DOORS[w.use(4)],
|
|
4980
|
+
w.use(5) === "O" ? "open" : "closed"
|
|
4981
|
+
);
|
|
4982
|
+
const md = fields[6];
|
|
4983
|
+
if (/^(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])$/.test(md)) {
|
|
4984
|
+
w.use(6);
|
|
4985
|
+
ResultFormatter.month(decodeResult, Number(md.substring(0, 2)));
|
|
4986
|
+
ResultFormatter.day(decodeResult, Number(md.substring(2)));
|
|
4987
|
+
} else if (!/^\d+$/.test(md)) {
|
|
4988
|
+
w.use(6);
|
|
4989
|
+
}
|
|
4990
|
+
w.time(7, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4991
|
+
break;
|
|
4992
|
+
}
|
|
4993
|
+
case "FCM01": {
|
|
4994
|
+
const names = {
|
|
4995
|
+
L: "Left Engine",
|
|
4996
|
+
R: "Right Engine",
|
|
4997
|
+
A: "APU"
|
|
4998
|
+
};
|
|
4999
|
+
for (let i = 0; i < 3; i++) {
|
|
5000
|
+
const v = fields[i];
|
|
5001
|
+
if (v[1] === "0" || v[1] === "1") {
|
|
5002
|
+
w.item(
|
|
5003
|
+
i,
|
|
5004
|
+
`${names[v[0]].toLowerCase().replace(" ", "_")}`,
|
|
5005
|
+
v[0],
|
|
5006
|
+
names[v[0]],
|
|
5007
|
+
v[1] === "1" ? "running" : "off"
|
|
5008
|
+
);
|
|
5009
|
+
}
|
|
5010
|
+
}
|
|
5011
|
+
ResultFormatter.currentFuel(decodeResult, Number(w.use(4)) * 100);
|
|
5012
|
+
w.time(5, (r, t) => ResultFormatter.timestamp(r, t));
|
|
5013
|
+
break;
|
|
5014
|
+
}
|
|
5015
|
+
case "VXR02":
|
|
5016
|
+
w.item(0, "station_iata", "STN", "Station", fields[0]);
|
|
5017
|
+
break;
|
|
5018
|
+
}
|
|
5019
|
+
return w.finish();
|
|
5020
|
+
}
|
|
5021
|
+
/** MXR03: destination, ETA, code, then the category and text; returns how many header
|
|
5022
|
+
* fields went to `remaining`. */
|
|
5023
|
+
writeMaintenance(decodeResult, text, fields) {
|
|
5024
|
+
const w = new SwaFieldWriter(decodeResult, fields.slice(0, 3));
|
|
5025
|
+
w.arrival(0);
|
|
5026
|
+
w.eta(1);
|
|
5027
|
+
w.item(
|
|
5028
|
+
2,
|
|
5029
|
+
"maintenance_code",
|
|
5030
|
+
"MXCODE",
|
|
5031
|
+
"Report Code",
|
|
5032
|
+
`${fields[2]} (${MXR_CODES[fields[2]]})`
|
|
5033
|
+
);
|
|
5034
|
+
const header = text.match(/^[^,|]*[,|][^,|]*[,|][^,|]*[,|]?/);
|
|
5035
|
+
const body = text.substring(header ? header[0].length : 0);
|
|
5036
|
+
if (body.trim() !== "") {
|
|
5037
|
+
ResultFormatter.text(decodeResult, body.split("|").join("\n"));
|
|
5038
|
+
}
|
|
5039
|
+
return w.finish();
|
|
5040
|
+
}
|
|
5041
|
+
};
|
|
5042
|
+
|
|
5043
|
+
// lib/plugins/Label_40_SWA.ts
|
|
5044
|
+
var DESCRIPTIONS2 = {
|
|
5045
|
+
ASR01: "Approach Stability Report",
|
|
5046
|
+
DVP01: "Divert Plan",
|
|
5047
|
+
FTX01: "Dispatch Free Text",
|
|
5048
|
+
GAR03: "Gate Assignment Response",
|
|
5049
|
+
GEN01: "Company Message",
|
|
5050
|
+
PIC01: "Part 117 Duty Extension Request",
|
|
5051
|
+
POS01: "Position Report Request",
|
|
5052
|
+
WFC01: "Field Condition Report"
|
|
5053
|
+
};
|
|
5054
|
+
var ASR01 = [
|
|
5055
|
+
[
|
|
5056
|
+
"reverser_distance",
|
|
5057
|
+
"REVDIST",
|
|
5058
|
+
"Threshold to Thrust Reverser Deployment (feet)"
|
|
5059
|
+
],
|
|
5060
|
+
["max_ias", "MAXIAS", "Highest IAS, 1000 feet to Touchdown (knots)"],
|
|
5061
|
+
["min_ias", "MINIAS", "Lowest IAS, to Touchdown (knots)"],
|
|
5062
|
+
["touchdown_distance", "TDDIST", "Threshold to Touchdown (feet)"],
|
|
5063
|
+
["glideslope_above", "GSHIGH", "Largest Deviation Above Glideslope (dots)"],
|
|
5064
|
+
["glideslope_below", "GSLOW", "Largest Deviation Below Glideslope (dots)"],
|
|
5065
|
+
["max_pitch", "MAXPITCH", "Highest Pitch, Flare and Landing (degrees)"],
|
|
5066
|
+
["tailstrike_pitch", "TSPITCH", "Tail Strike Pitch Limit (degrees)"]
|
|
5067
|
+
];
|
|
5068
|
+
var Label_40_SWA = class extends DecoderPlugin {
|
|
5069
|
+
name = "label-40-swa";
|
|
5070
|
+
qualifiers() {
|
|
5071
|
+
return {
|
|
5072
|
+
labels: ["40"]
|
|
5073
|
+
};
|
|
5074
|
+
}
|
|
5075
|
+
decode(message2, options = {}) {
|
|
5076
|
+
const decodeResult = this.defaultResult();
|
|
5077
|
+
decodeResult.decoder.name = this.name;
|
|
5078
|
+
decodeResult.message = message2;
|
|
5079
|
+
const d = decodeSwaLabel40(message2.text);
|
|
5080
|
+
if (!d || !isSwaType(d.type, "40")) {
|
|
5081
|
+
if (options.debug) {
|
|
5082
|
+
console.log(`Decoder: Unknown 40 message: ${message2.text}`);
|
|
5083
|
+
}
|
|
5084
|
+
ResultFormatter.unknown(decodeResult, message2.text);
|
|
5085
|
+
decodeResult.formatted.description = "Unknown";
|
|
5086
|
+
return decodeResult;
|
|
5087
|
+
}
|
|
5088
|
+
decodeResult.decoded = true;
|
|
5089
|
+
decodeResult.formatted.description = DESCRIPTIONS2[d.type] ?? "Southwest Message";
|
|
5090
|
+
decodeResult.raw.preamble = d.type;
|
|
5091
|
+
if (d.type === "POS01") {
|
|
5092
|
+
const m = d.text.match(/^POS01,Y,(\d{2})$/);
|
|
5093
|
+
if (m) {
|
|
5094
|
+
ResultFormatter.raw(
|
|
5095
|
+
decodeResult,
|
|
5096
|
+
"report_interval",
|
|
5097
|
+
"RPTINT",
|
|
5098
|
+
"Position Report Interval",
|
|
5099
|
+
`${Number(m[1])} minutes`,
|
|
5100
|
+
Number(m[1])
|
|
5101
|
+
);
|
|
5102
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5103
|
+
} else {
|
|
5104
|
+
ResultFormatter.unknown(decodeResult, d.text);
|
|
5105
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5106
|
+
}
|
|
5107
|
+
return decodeResult;
|
|
5108
|
+
}
|
|
5109
|
+
const text = d.text;
|
|
5110
|
+
const fields = swaFields(text);
|
|
5111
|
+
const layouts = SWA_LAYOUTS[d.type];
|
|
5112
|
+
const clean = !text.includes(SWA_UNREAD);
|
|
5113
|
+
if (clean && layouts && swaMatchesLayout(fields, layouts)) {
|
|
5114
|
+
const w = new SwaFieldWriter(decodeResult, fields);
|
|
5115
|
+
if (d.type === "ASR01") {
|
|
5116
|
+
ASR01.forEach(([key, code, label], i) => {
|
|
5117
|
+
const v = fields[i].trim();
|
|
5118
|
+
if (v !== "XX.X") w.item(i, key, code, label, v);
|
|
5119
|
+
else w.use(i);
|
|
5120
|
+
});
|
|
5121
|
+
} else if (d.type === "GAR03") {
|
|
5122
|
+
ResultFormatter.arrivalGate(decodeResult, w.use(0).trim());
|
|
5123
|
+
if (fields[6] !== "999.999") {
|
|
5124
|
+
w.item(
|
|
5125
|
+
6,
|
|
5126
|
+
"ramp_frequency",
|
|
5127
|
+
"RAMPFREQ",
|
|
5128
|
+
"Ramp Frequency",
|
|
5129
|
+
`${fields[6]} MHz`
|
|
5130
|
+
);
|
|
5131
|
+
} else {
|
|
5132
|
+
w.use(6);
|
|
5133
|
+
}
|
|
5134
|
+
}
|
|
5135
|
+
const rest = w.finish();
|
|
5136
|
+
decodeResult.decoder.decodeLevel = rest === 0 ? "full" : "partial";
|
|
5137
|
+
return decodeResult;
|
|
5138
|
+
}
|
|
5139
|
+
ResultFormatter.text(decodeResult, text.split("|").join("\n"));
|
|
5140
|
+
decodeResult.decoder.decodeLevel = clean && !layouts ? "full" : "partial";
|
|
5141
|
+
return decodeResult;
|
|
5142
|
+
}
|
|
5143
|
+
};
|
|
5144
|
+
|
|
5145
|
+
// lib/plugins/Label_44_ETA.ts
|
|
5146
|
+
var Label_44_ETA = class extends DecoderPlugin {
|
|
5147
|
+
name = "label-44-eta";
|
|
5148
|
+
qualifiers() {
|
|
5149
|
+
return {
|
|
3677
5150
|
labels: ["44"],
|
|
3678
5151
|
preambles: ["00ETA01", "00ETA02", "00ETA03", "ETA01", "ETA02", "ETA03"]
|
|
3679
5152
|
};
|
|
@@ -4680,91 +6153,60 @@ var Label_ColonComma = class extends DecoderPlugin {
|
|
|
4680
6153
|
}
|
|
4681
6154
|
};
|
|
4682
6155
|
|
|
4683
|
-
// lib/plugins/
|
|
4684
|
-
var
|
|
4685
|
-
name = "label-
|
|
6156
|
+
// lib/plugins/Label_H1_76401.ts
|
|
6157
|
+
var Label_H1_76401 = class extends DecoderPlugin {
|
|
6158
|
+
name = "label-h1-76401";
|
|
4686
6159
|
qualifiers() {
|
|
4687
6160
|
return {
|
|
4688
|
-
labels: ["
|
|
4689
|
-
preambles: ["
|
|
6161
|
+
labels: ["H1"],
|
|
6162
|
+
preambles: ["76401\r\n"]
|
|
4690
6163
|
};
|
|
4691
6164
|
}
|
|
4692
6165
|
decode(message2, options = {}) {
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
decodeResult.message = message2;
|
|
4697
|
-
const parts = message2.text.split(" ");
|
|
4698
|
-
if (parts[parts.length - 1] !== "Q") {
|
|
4699
|
-
decodeResult.remaining.text = message2.text;
|
|
4700
|
-
decodeResult.decoded = false;
|
|
4701
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
6166
|
+
const decodeResult = this.initResult(message2, "Position Report");
|
|
6167
|
+
const lines = message2.text.split("\r\n");
|
|
6168
|
+
if (lines.length < 3) {
|
|
4702
6169
|
return decodeResult;
|
|
4703
6170
|
}
|
|
4704
|
-
|
|
4705
|
-
decodeResult.
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
const
|
|
4712
|
-
|
|
4713
|
-
|
|
6171
|
+
ResultFormatter.unknown(decodeResult, lines[0], "\r\n");
|
|
6172
|
+
ResultFormatter.unknown(decodeResult, lines[1].substring(0, 5), "\r\n");
|
|
6173
|
+
ResultFormatter.departureAirport(decodeResult, lines[1].substring(5, 9));
|
|
6174
|
+
ResultFormatter.arrivalAirport(decodeResult, lines[1].substring(9, 13));
|
|
6175
|
+
ResultFormatter.unknown(decodeResult, lines[1].substring(13), "");
|
|
6176
|
+
const waypoints = [];
|
|
6177
|
+
for (const line of lines.slice(2)) {
|
|
6178
|
+
const position = CoordinateUtils.decodeStringCoordinates(
|
|
6179
|
+
line.substring(0, 13)
|
|
6180
|
+
);
|
|
6181
|
+
if (position) {
|
|
6182
|
+
waypoints.push({
|
|
6183
|
+
name: line.substring(0, 13),
|
|
6184
|
+
latitude: position.latitude,
|
|
6185
|
+
longitude: position.longitude,
|
|
6186
|
+
time: DateTimeUtils.convertHHMMSSToTod(line.substring(13, 19))
|
|
6187
|
+
});
|
|
4714
6188
|
} else {
|
|
4715
|
-
|
|
6189
|
+
ResultFormatter.unknown(decodeResult, line.substring(0, 19), "");
|
|
4716
6190
|
}
|
|
6191
|
+
ResultFormatter.unknown(decodeResult, line.substring(19), "\r\n");
|
|
4717
6192
|
}
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
6193
|
+
ResultFormatter.route(decodeResult, { waypoints });
|
|
6194
|
+
if (waypoints.length > 0) {
|
|
6195
|
+
const lastWaypoint = waypoints[waypoints.length - 1];
|
|
6196
|
+
if (lastWaypoint.latitude !== void 0 && lastWaypoint.longitude !== void 0) {
|
|
6197
|
+
ResultFormatter.position(decodeResult, {
|
|
6198
|
+
latitude: lastWaypoint.latitude,
|
|
6199
|
+
longitude: lastWaypoint.longitude
|
|
6200
|
+
});
|
|
4723
6201
|
}
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
windData.push(wind);
|
|
4727
|
-
} else {
|
|
4728
|
-
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + part;
|
|
6202
|
+
if (lastWaypoint.time !== void 0) {
|
|
6203
|
+
ResultFormatter.timestamp(decodeResult, lastWaypoint.time);
|
|
4729
6204
|
}
|
|
4730
6205
|
}
|
|
4731
|
-
ResultFormatter.windData(decodeResult, windData);
|
|
4732
6206
|
decodeResult.decoded = true;
|
|
4733
|
-
decodeResult.decoder.decodeLevel =
|
|
6207
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
4734
6208
|
return decodeResult;
|
|
4735
6209
|
}
|
|
4736
|
-
parseWeatherReport(text) {
|
|
4737
|
-
const posString = text.substring(0, 13);
|
|
4738
|
-
const pos = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(posString);
|
|
4739
|
-
if (text.length !== 32 || !pos) {
|
|
4740
|
-
return null;
|
|
4741
|
-
}
|
|
4742
|
-
const tod = DateTimeUtils.convertHHMMSSToTod(text.substring(13, 17));
|
|
4743
|
-
const flightLevel = parseInt(text.substring(17, 20), 10);
|
|
4744
|
-
const tempSign = text[21] === "M" ? -1 : 1;
|
|
4745
|
-
const tempDegreesRaw = parseInt(text.substring(22, 25), 10);
|
|
4746
|
-
const tempDegrees = tempSign * (tempDegreesRaw / 10);
|
|
4747
|
-
const windDirection = parseInt(text.substring(25, 28), 10);
|
|
4748
|
-
const windSpeed = parseInt(text.substring(28, 31), 10);
|
|
4749
|
-
if (text[31] !== "G") {
|
|
4750
|
-
return null;
|
|
4751
|
-
}
|
|
4752
|
-
return {
|
|
4753
|
-
waypoint: {
|
|
4754
|
-
name: posString,
|
|
4755
|
-
latitude: pos.latitude,
|
|
4756
|
-
longitude: pos.longitude,
|
|
4757
|
-
time: tod
|
|
4758
|
-
},
|
|
4759
|
-
flightLevel,
|
|
4760
|
-
windDirection,
|
|
4761
|
-
windSpeed,
|
|
4762
|
-
temperature: {
|
|
4763
|
-
flightLevel,
|
|
4764
|
-
degreesC: tempDegrees
|
|
4765
|
-
}
|
|
4766
|
-
};
|
|
4767
|
-
}
|
|
4768
6210
|
};
|
|
4769
6211
|
|
|
4770
6212
|
// lib/plugins/Label_H1_ATIS.ts
|
|
@@ -4985,11 +6427,11 @@ var Label_H1_M_POS = class extends DecoderPlugin {
|
|
|
4985
6427
|
const timestamp = fields[2].trim();
|
|
4986
6428
|
if (timestamp.length === 6) {
|
|
4987
6429
|
const day = Number(timestamp.substring(0, 2));
|
|
4988
|
-
const
|
|
6430
|
+
const tod2 = DateTimeUtils.convertHHMMSSToTod(
|
|
4989
6431
|
timestamp.substring(2) + "00"
|
|
4990
6432
|
);
|
|
4991
6433
|
ResultFormatter.day(decodeResult, day);
|
|
4992
|
-
ResultFormatter.timestamp(decodeResult,
|
|
6434
|
+
ResultFormatter.timestamp(decodeResult, tod2);
|
|
4993
6435
|
}
|
|
4994
6436
|
const lat = parseFloat(fields[3].replace(/\s/g, ""));
|
|
4995
6437
|
const lon = parseFloat(fields[4].replace(/\s/g, ""));
|
|
@@ -5383,6 +6825,135 @@ var Label_H1_StarPOS = class extends DecoderPlugin {
|
|
|
5383
6825
|
}
|
|
5384
6826
|
};
|
|
5385
6827
|
|
|
6828
|
+
// lib/plugins/Label_H1_SWA_Track.ts
|
|
6829
|
+
var PHASES = {
|
|
6830
|
+
TO: "Takeoff",
|
|
6831
|
+
IC: "Initial Climb",
|
|
6832
|
+
CL: "Climb",
|
|
6833
|
+
CR: "Cruise",
|
|
6834
|
+
ER: "En Route",
|
|
6835
|
+
DC: "Descent",
|
|
6836
|
+
AP: "Approach",
|
|
6837
|
+
RO: "Rollout"
|
|
6838
|
+
};
|
|
6839
|
+
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]),$/;
|
|
6840
|
+
var Label_H1_SWA_Track = class extends DecoderPlugin {
|
|
6841
|
+
name = "label-h1-swa-track";
|
|
6842
|
+
qualifiers() {
|
|
6843
|
+
return {
|
|
6844
|
+
labels: ["H1"],
|
|
6845
|
+
preambles: ["++76502,", "++86501,", "#DFB++76502,", "#DFB++86501,"]
|
|
6846
|
+
};
|
|
6847
|
+
}
|
|
6848
|
+
decode(message2, options = {}) {
|
|
6849
|
+
const decodeResult = this.initResult(message2, "Track Report");
|
|
6850
|
+
const nl = message2.text.includes("\r\n") ? "\r\n" : "\n";
|
|
6851
|
+
const lines = message2.text.replace(/#DFB/g, "").split(/\r?\n/);
|
|
6852
|
+
const header = lines[0].replace(/^\+\+/, "").split(",");
|
|
6853
|
+
if (header.length !== 9 || !/^\d{6}$/.test(header[3])) {
|
|
6854
|
+
return this.failUnknown(decodeResult, message2.text, options);
|
|
6855
|
+
}
|
|
6856
|
+
const unknown = [];
|
|
6857
|
+
if (/^N\w+$/.test(header[1])) {
|
|
6858
|
+
ResultFormatter.tail(decodeResult, header[1]);
|
|
6859
|
+
} else if (/^\d{1,4}$/.test(header[1])) {
|
|
6860
|
+
ResultFormatter.raw(
|
|
6861
|
+
decodeResult,
|
|
6862
|
+
"ship_number",
|
|
6863
|
+
"SHIP",
|
|
6864
|
+
"Ship Number",
|
|
6865
|
+
header[1]
|
|
6866
|
+
);
|
|
6867
|
+
} else if (header[1] !== "XXX") {
|
|
6868
|
+
unknown.push(header[1]);
|
|
6869
|
+
}
|
|
6870
|
+
ResultFormatter.raw(
|
|
6871
|
+
decodeResult,
|
|
6872
|
+
"aircraft_type",
|
|
6873
|
+
"ACTYPE",
|
|
6874
|
+
"Aircraft Type",
|
|
6875
|
+
header[2]
|
|
6876
|
+
);
|
|
6877
|
+
const d = header[3];
|
|
6878
|
+
ResultFormatter.raw(
|
|
6879
|
+
decodeResult,
|
|
6880
|
+
"report_date",
|
|
6881
|
+
"DATE",
|
|
6882
|
+
"Report Date",
|
|
6883
|
+
`20${d.slice(0, 2)}-${d.slice(2, 4)}-${d.slice(4, 6)}`
|
|
6884
|
+
);
|
|
6885
|
+
ResultFormatter.flightNumber(decodeResult, header[4]);
|
|
6886
|
+
ResultFormatter.departureAirport(decodeResult, header[5]);
|
|
6887
|
+
ResultFormatter.arrivalAirport(decodeResult, header[6]);
|
|
6888
|
+
if (/^\d{1,15}$/.test(header[7])) {
|
|
6889
|
+
ResultFormatter.raw(
|
|
6890
|
+
decodeResult,
|
|
6891
|
+
"leg_counter",
|
|
6892
|
+
"LEGS",
|
|
6893
|
+
"Leg Counter",
|
|
6894
|
+
`${Number(header[7])}`,
|
|
6895
|
+
Number(header[7])
|
|
6896
|
+
);
|
|
6897
|
+
} else {
|
|
6898
|
+
unknown.push(header[7]);
|
|
6899
|
+
}
|
|
6900
|
+
ResultFormatter.raw(
|
|
6901
|
+
decodeResult,
|
|
6902
|
+
"software_version",
|
|
6903
|
+
"SWVER",
|
|
6904
|
+
"Software Version",
|
|
6905
|
+
header[8]
|
|
6906
|
+
);
|
|
6907
|
+
if (unknown.length > 0) ResultFormatter.unknownArr(decodeResult, unknown);
|
|
6908
|
+
const count = lines[1]?.match(/^(\d+),?$/)?.[1];
|
|
6909
|
+
if (lines[1] !== void 0 && count === void 0) {
|
|
6910
|
+
ResultFormatter.unknown(decodeResult, lines[1], nl);
|
|
6911
|
+
}
|
|
6912
|
+
for (const line of lines.slice(2)) {
|
|
6913
|
+
if (line === "" || line === ":") continue;
|
|
6914
|
+
const m = line.match(POINT);
|
|
6915
|
+
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) {
|
|
6916
|
+
ResultFormatter.unknown(decodeResult, line, nl);
|
|
6917
|
+
continue;
|
|
6918
|
+
}
|
|
6919
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
|
|
6920
|
+
`${m[1]}${m[2]}${m[3]}${m[4]}`
|
|
6921
|
+
);
|
|
6922
|
+
if (!position || Math.abs(position.latitude) > 90 || Math.abs(position.longitude) > 180) {
|
|
6923
|
+
ResultFormatter.unknown(decodeResult, line, nl);
|
|
6924
|
+
continue;
|
|
6925
|
+
}
|
|
6926
|
+
ResultFormatter.trackPoint(decodeResult, {
|
|
6927
|
+
name: `${m[1]}.${m[2]}${m[3]}.${m[4]}`,
|
|
6928
|
+
...position,
|
|
6929
|
+
day: Number(m[5]),
|
|
6930
|
+
time: Number(m[6]) * 3600 + Number(m[7]) * 60,
|
|
6931
|
+
altitude: Number(m[8]),
|
|
6932
|
+
// -00.0 is sent; keep it as 0
|
|
6933
|
+
temperature: Number(m[9]) || 0,
|
|
6934
|
+
windDirection: Number(m[10]),
|
|
6935
|
+
windSpeed: Number(m[11]),
|
|
6936
|
+
phase: PHASES[m[12]] ?? m[12],
|
|
6937
|
+
humiditySensor: m[14] === "1",
|
|
6938
|
+
...m[14] === "1" && Number(m[13]) > 0 ? { waterVapor: Number(m[13]) } : {}
|
|
6939
|
+
});
|
|
6940
|
+
}
|
|
6941
|
+
const points = decodeResult.raw.route?.waypoints ?? [];
|
|
6942
|
+
const last = points[points.length - 1];
|
|
6943
|
+
if (last) {
|
|
6944
|
+
ResultFormatter.position(decodeResult, {
|
|
6945
|
+
latitude: last.latitude,
|
|
6946
|
+
longitude: last.longitude
|
|
6947
|
+
});
|
|
6948
|
+
ResultFormatter.altitude(decodeResult, last.altitude);
|
|
6949
|
+
ResultFormatter.timestamp(decodeResult, last.time);
|
|
6950
|
+
}
|
|
6951
|
+
const counted = count !== void 0 && Number(count) === points.length;
|
|
6952
|
+
this.setDecodeLevel(decodeResult, true, counted ? void 0 : "partial");
|
|
6953
|
+
return decodeResult;
|
|
6954
|
+
}
|
|
6955
|
+
};
|
|
6956
|
+
|
|
5386
6957
|
// lib/plugins/Label_H1_WRN.ts
|
|
5387
6958
|
var Label_H1_WRN = class extends DecoderPlugin {
|
|
5388
6959
|
name = "label-h1-wrn";
|
|
@@ -5422,6 +6993,93 @@ var Label_H1_WRN = class extends DecoderPlugin {
|
|
|
5422
6993
|
}
|
|
5423
6994
|
};
|
|
5424
6995
|
|
|
6996
|
+
// lib/plugins/Label_H2_02E.ts
|
|
6997
|
+
var Label_H2_02E = class extends DecoderPlugin {
|
|
6998
|
+
name = "label-h2-02e";
|
|
6999
|
+
qualifiers() {
|
|
7000
|
+
return {
|
|
7001
|
+
labels: ["H2"],
|
|
7002
|
+
preambles: ["02E"]
|
|
7003
|
+
};
|
|
7004
|
+
}
|
|
7005
|
+
decode(message2, options = {}) {
|
|
7006
|
+
let decodeResult = this.defaultResult();
|
|
7007
|
+
decodeResult.decoder.name = this.name;
|
|
7008
|
+
decodeResult.formatted.description = "Weather Report";
|
|
7009
|
+
decodeResult.message = message2;
|
|
7010
|
+
const parts = message2.text.split(" ");
|
|
7011
|
+
if (parts[parts.length - 1] !== "Q") {
|
|
7012
|
+
decodeResult.remaining.text = message2.text;
|
|
7013
|
+
decodeResult.decoded = false;
|
|
7014
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
7015
|
+
return decodeResult;
|
|
7016
|
+
}
|
|
7017
|
+
const windData = [];
|
|
7018
|
+
decodeResult.remaining.text = "";
|
|
7019
|
+
const header = parts[0];
|
|
7020
|
+
if (header.length === 45) {
|
|
7021
|
+
ResultFormatter.day(decodeResult, parseInt(header.substring(3, 5), 10));
|
|
7022
|
+
ResultFormatter.departureAirport(decodeResult, header.substring(5, 9));
|
|
7023
|
+
ResultFormatter.arrivalAirport(decodeResult, header.substring(9, 13));
|
|
7024
|
+
const firstWind = this.parseWeatherReport(header.substring(13));
|
|
7025
|
+
if (firstWind) {
|
|
7026
|
+
windData.push(firstWind);
|
|
7027
|
+
} else {
|
|
7028
|
+
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + header.substring(13);
|
|
7029
|
+
}
|
|
7030
|
+
}
|
|
7031
|
+
for (let i = 1; i < parts.length - 1; i++) {
|
|
7032
|
+
const part = parts[i];
|
|
7033
|
+
if (part[0] !== "Q") {
|
|
7034
|
+
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + part;
|
|
7035
|
+
continue;
|
|
7036
|
+
}
|
|
7037
|
+
const wind = this.parseWeatherReport(part.substring(1));
|
|
7038
|
+
if (wind) {
|
|
7039
|
+
windData.push(wind);
|
|
7040
|
+
} else {
|
|
7041
|
+
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + part;
|
|
7042
|
+
}
|
|
7043
|
+
}
|
|
7044
|
+
ResultFormatter.windData(decodeResult, windData);
|
|
7045
|
+
decodeResult.decoded = true;
|
|
7046
|
+
decodeResult.decoder.decodeLevel = decodeResult.remaining.text.length === 0 ? "full" : "partial";
|
|
7047
|
+
return decodeResult;
|
|
7048
|
+
}
|
|
7049
|
+
parseWeatherReport(text) {
|
|
7050
|
+
const posString = text.substring(0, 13);
|
|
7051
|
+
const pos = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(posString);
|
|
7052
|
+
if (text.length !== 32 || !pos) {
|
|
7053
|
+
return null;
|
|
7054
|
+
}
|
|
7055
|
+
const tod2 = DateTimeUtils.convertHHMMSSToTod(text.substring(13, 17));
|
|
7056
|
+
const flightLevel = parseInt(text.substring(17, 20), 10);
|
|
7057
|
+
const tempSign = text[21] === "M" ? -1 : 1;
|
|
7058
|
+
const tempDegreesRaw = parseInt(text.substring(22, 25), 10);
|
|
7059
|
+
const tempDegrees = tempSign * (tempDegreesRaw / 10);
|
|
7060
|
+
const windDirection = parseInt(text.substring(25, 28), 10);
|
|
7061
|
+
const windSpeed = parseInt(text.substring(28, 31), 10);
|
|
7062
|
+
if (text[31] !== "G") {
|
|
7063
|
+
return null;
|
|
7064
|
+
}
|
|
7065
|
+
return {
|
|
7066
|
+
waypoint: {
|
|
7067
|
+
name: posString,
|
|
7068
|
+
latitude: pos.latitude,
|
|
7069
|
+
longitude: pos.longitude,
|
|
7070
|
+
time: tod2
|
|
7071
|
+
},
|
|
7072
|
+
flightLevel,
|
|
7073
|
+
windDirection,
|
|
7074
|
+
windSpeed,
|
|
7075
|
+
temperature: {
|
|
7076
|
+
flightLevel,
|
|
7077
|
+
degreesC: tempDegrees
|
|
7078
|
+
}
|
|
7079
|
+
};
|
|
7080
|
+
}
|
|
7081
|
+
};
|
|
7082
|
+
|
|
5425
7083
|
// lib/plugins/Label_HX.ts
|
|
5426
7084
|
var Label_HX = class extends DecoderPlugin {
|
|
5427
7085
|
name = "label-hx";
|
|
@@ -5494,8 +7152,8 @@ function ascii85Decode(input) {
|
|
|
5494
7152
|
if (digit < 0 || digit > 84) return null;
|
|
5495
7153
|
value = value * 85 + digit;
|
|
5496
7154
|
}
|
|
5497
|
-
if (
|
|
5498
|
-
const v = value
|
|
7155
|
+
if (value > 4294967295) return null;
|
|
7156
|
+
const v = value;
|
|
5499
7157
|
const numBytes = chunkLen === 5 ? 4 : chunkLen - 1;
|
|
5500
7158
|
if (numBytes >= 1) output.push(v >>> 24 & 255);
|
|
5501
7159
|
if (numBytes >= 2) output.push(v >>> 16 & 255);
|
|
@@ -6717,8 +8375,11 @@ var pluginClasses = [
|
|
|
6717
8375
|
Label_ColonComma,
|
|
6718
8376
|
Label_5Z_Slash,
|
|
6719
8377
|
Label_10_LDR,
|
|
8378
|
+
Label_10_LRW,
|
|
6720
8379
|
Label_10_POS,
|
|
6721
8380
|
Label_10_Slash,
|
|
8381
|
+
Label_11_LDR,
|
|
8382
|
+
Label_11_LRW,
|
|
6722
8383
|
Label_12_N_Space,
|
|
6723
8384
|
Label_12_POS,
|
|
6724
8385
|
Label_13Through18_Slash,
|
|
@@ -6742,6 +8403,8 @@ var pluginClasses = [
|
|
|
6742
8403
|
Label_2P_FM4,
|
|
6743
8404
|
Label_2P_FM5,
|
|
6744
8405
|
Label_30_Slash_EA,
|
|
8406
|
+
Label_37_SWA,
|
|
8407
|
+
Label_40_SWA,
|
|
6745
8408
|
Label_44_ETA,
|
|
6746
8409
|
Label_44_IN,
|
|
6747
8410
|
Label_44_OFF,
|
|
@@ -6757,7 +8420,7 @@ var pluginClasses = [
|
|
|
6757
8420
|
Label_4T_AGFSR,
|
|
6758
8421
|
Label_4T_ETA,
|
|
6759
8422
|
Label_B6_Forwardslash,
|
|
6760
|
-
|
|
8423
|
+
Label_H1_76401,
|
|
6761
8424
|
Label_H1_ATIS,
|
|
6762
8425
|
Label_H1_EZF,
|
|
6763
8426
|
Label_H1_FLR,
|
|
@@ -6767,6 +8430,8 @@ var pluginClasses = [
|
|
|
6767
8430
|
Label_H1_Paren,
|
|
6768
8431
|
Label_H1_WRN,
|
|
6769
8432
|
Label_H1_StarPOS,
|
|
8433
|
+
Label_H1_SWA_Track,
|
|
8434
|
+
Label_H2_02E,
|
|
6770
8435
|
Label_HX,
|
|
6771
8436
|
Label_58,
|
|
6772
8437
|
Label_80,
|
|
@@ -6812,6 +8477,9 @@ var MessageDecoder = class {
|
|
|
6812
8477
|
this.wildcardSet.add(plugin);
|
|
6813
8478
|
const wildcardInsertIndex = this.wildcardEntries.length - 1;
|
|
6814
8479
|
for (const bucket of this.candidatesByLabel.values()) {
|
|
8480
|
+
if (bucket.some((e) => e.plugin === plugin)) {
|
|
8481
|
+
continue;
|
|
8482
|
+
}
|
|
6815
8483
|
bucket.splice(wildcardInsertIndex, 0, entry);
|
|
6816
8484
|
}
|
|
6817
8485
|
}
|