@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
package/dist/index.mjs
CHANGED
|
@@ -138,8 +138,8 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
138
138
|
};
|
|
139
139
|
}
|
|
140
140
|
static coordinateString(coords) {
|
|
141
|
-
const latDir = coords.latitude
|
|
142
|
-
const lonDir = coords.longitude
|
|
141
|
+
const latDir = coords.latitude >= 0 ? "N" : "S";
|
|
142
|
+
const lonDir = coords.longitude >= 0 ? "E" : "W";
|
|
143
143
|
return `${Math.abs(coords.latitude).toFixed(3)} ${latDir}, ${Math.abs(coords.longitude).toFixed(3)} ${lonDir}`;
|
|
144
144
|
}
|
|
145
145
|
static getDirection(coord) {
|
|
@@ -189,16 +189,16 @@ var DateTimeUtils = class {
|
|
|
189
189
|
const h = Number(time.substring(0, 2));
|
|
190
190
|
const m = Number(time.substring(2, 4));
|
|
191
191
|
const s = Number(time.substring(4, 6));
|
|
192
|
-
const
|
|
193
|
-
return
|
|
192
|
+
const tod2 = h * 3600 + m * 60 + s;
|
|
193
|
+
return tod2;
|
|
194
194
|
}
|
|
195
195
|
static convertDayTimeToTod(time) {
|
|
196
196
|
const d = Number(time.substring(0, 2));
|
|
197
197
|
const h = Number(time.substring(2, 4));
|
|
198
198
|
const m = Number(time.substring(4, 6));
|
|
199
199
|
const s = Number(time.substring(6, 8));
|
|
200
|
-
const
|
|
201
|
-
return
|
|
200
|
+
const tod2 = d * 86400 + h * 3600 + m * 60 + s;
|
|
201
|
+
return tod2;
|
|
202
202
|
}
|
|
203
203
|
/**
|
|
204
204
|
*
|
|
@@ -474,6 +474,16 @@ var ResultFormatter = class {
|
|
|
474
474
|
value: decodeResult.raw.alternate_icao
|
|
475
475
|
});
|
|
476
476
|
}
|
|
477
|
+
/** The airport landing data is for: the destination, or the airport of a divert. */
|
|
478
|
+
static landingAirport(decodeResult, value) {
|
|
479
|
+
decodeResult.raw.landing_icao = value;
|
|
480
|
+
decodeResult.formatted.items.push({
|
|
481
|
+
type: "icao",
|
|
482
|
+
code: "LAND",
|
|
483
|
+
label: "Landing Airport",
|
|
484
|
+
value: decodeResult.raw.landing_icao
|
|
485
|
+
});
|
|
486
|
+
}
|
|
477
487
|
static eta(decodeResult, time) {
|
|
478
488
|
if (isNaN(time)) {
|
|
479
489
|
return;
|
|
@@ -664,6 +674,144 @@ var ResultFormatter = class {
|
|
|
664
674
|
value: `${decodeResult.raw.heading}`
|
|
665
675
|
});
|
|
666
676
|
}
|
|
677
|
+
static indicatedAirspeed(decodeResult, value) {
|
|
678
|
+
if (isNaN(value)) {
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
decodeResult.raw.indicated_airspeed = value;
|
|
682
|
+
decodeResult.formatted.items.push({
|
|
683
|
+
type: "indicated_airspeed",
|
|
684
|
+
code: "IAS",
|
|
685
|
+
label: "Indicated Airspeed",
|
|
686
|
+
value: `${decodeResult.raw.indicated_airspeed} knots`
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
static track(decodeResult, value) {
|
|
690
|
+
if (isNaN(value)) {
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
decodeResult.raw.track = value;
|
|
694
|
+
decodeResult.formatted.items.push({
|
|
695
|
+
type: "track",
|
|
696
|
+
code: "TRK",
|
|
697
|
+
label: "Track",
|
|
698
|
+
value: `${decodeResult.raw.track} degrees`
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
/** Wind at the aircraft; either half may be missing. */
|
|
702
|
+
static wind(decodeResult, direction, speed) {
|
|
703
|
+
const hasDirection = direction !== void 0 && !isNaN(direction);
|
|
704
|
+
const hasSpeed = speed !== void 0 && !isNaN(speed);
|
|
705
|
+
if (hasDirection) decodeResult.raw.wind_direction = direction;
|
|
706
|
+
if (hasSpeed) decodeResult.raw.wind_speed = speed;
|
|
707
|
+
if (!hasDirection && !hasSpeed) {
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
decodeResult.formatted.items.push({
|
|
711
|
+
type: "wind",
|
|
712
|
+
code: "WIND",
|
|
713
|
+
label: !hasSpeed ? "Wind Direction" : !hasDirection ? "Wind Speed" : "Wind",
|
|
714
|
+
value: [
|
|
715
|
+
hasDirection ? `${direction} degrees` : "",
|
|
716
|
+
hasSpeed ? `${speed} knots` : ""
|
|
717
|
+
].filter((s) => s !== "").join(" at ")
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
static variableWind(decodeResult, speed) {
|
|
721
|
+
if (isNaN(speed)) {
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
decodeResult.raw.wind_speed = speed;
|
|
725
|
+
decodeResult.raw.wind_variable = true;
|
|
726
|
+
decodeResult.formatted.items.push({
|
|
727
|
+
type: "wind",
|
|
728
|
+
code: "WIND",
|
|
729
|
+
label: "Wind",
|
|
730
|
+
value: `variable at ${speed} knots`
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* One point of a recorded track. The track is the route as flown, so each point is added to
|
|
735
|
+
* the route's waypoints; the item shows what the aircraft measured there as well.
|
|
736
|
+
*/
|
|
737
|
+
static trackPoint(decodeResult, point) {
|
|
738
|
+
decodeResult.raw.route = {
|
|
739
|
+
...decodeResult.raw.route,
|
|
740
|
+
waypoints: [...decodeResult.raw.route?.waypoints ?? [], point]
|
|
741
|
+
};
|
|
742
|
+
decodeResult.formatted.items.push({
|
|
743
|
+
type: "track_point",
|
|
744
|
+
code: "TRKPT",
|
|
745
|
+
label: "Track Point",
|
|
746
|
+
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`)
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
static runwayLandingData(decodeResult, data) {
|
|
750
|
+
decodeResult.raw.landing_runways = [
|
|
751
|
+
...decodeResult.raw.landing_runways ?? [],
|
|
752
|
+
data
|
|
753
|
+
];
|
|
754
|
+
const parts = [];
|
|
755
|
+
if (data.length !== void 0) parts.push(`${data.length} feet`);
|
|
756
|
+
if (data.flaps !== void 0) parts.push(`flaps ${data.flaps}`);
|
|
757
|
+
if (data.headwind !== void 0) {
|
|
758
|
+
parts.push(
|
|
759
|
+
data.headwind < 0 ? `tailwind ${-data.headwind} knots` : `headwind ${data.headwind} knots`
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
if (data.crosswind !== void 0) {
|
|
763
|
+
const side = { L: " left", R: " right" }[data.crosswindSide ?? "L"];
|
|
764
|
+
parts.push(
|
|
765
|
+
`crosswind ${data.crosswind} knots${data.crosswindSide ? side : ""}`
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
if (data.vref !== void 0) parts.push(`VREF ${data.vref} knots`);
|
|
769
|
+
if (data.vtarget !== void 0) {
|
|
770
|
+
const add = data.additive === void 0 ? "" : ` (${data.additive < 0 ? "" : "+"}${data.additive})`;
|
|
771
|
+
parts.push(`VTGT ${data.vtarget} knots${add}`);
|
|
772
|
+
}
|
|
773
|
+
if (data.maxLandingWeight !== void 0) {
|
|
774
|
+
parts.push(`MRLW ${data.maxLandingWeight}`);
|
|
775
|
+
}
|
|
776
|
+
if (data.landingWeight !== void 0) {
|
|
777
|
+
parts.push(`LDW ${data.landingWeight} pounds`);
|
|
778
|
+
}
|
|
779
|
+
const margins = Object.entries(data.stoppingMargins).map(
|
|
780
|
+
([setting, feet]) => `${setting} ${feet} feet`
|
|
781
|
+
);
|
|
782
|
+
if (margins.length > 0) {
|
|
783
|
+
parts.push(`stopping margin ${margins.join(", ")}`);
|
|
784
|
+
}
|
|
785
|
+
parts.push(...data.notes ?? []);
|
|
786
|
+
const variant2 = data.variant === void 0 ? "" : ` (${data.variant})`;
|
|
787
|
+
decodeResult.formatted.items.push({
|
|
788
|
+
type: "runway_landing_data",
|
|
789
|
+
code: "RWYLDG",
|
|
790
|
+
label: "Runway Landing Data",
|
|
791
|
+
value: `${data.runway}${variant2}: ${parts.join(", ")}`
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
static grossWeight(decodeResult, pounds3) {
|
|
795
|
+
if (isNaN(pounds3)) {
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
decodeResult.raw.gross_weight = pounds3;
|
|
799
|
+
decodeResult.formatted.items.push({
|
|
800
|
+
type: "gross_weight",
|
|
801
|
+
code: "GWT",
|
|
802
|
+
label: "Gross Weight",
|
|
803
|
+
value: `${decodeResult.raw.gross_weight} pounds`
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
static arrivalGate(decodeResult, value) {
|
|
807
|
+
decodeResult.raw.arrival_gate = value;
|
|
808
|
+
decodeResult.formatted.items.push({
|
|
809
|
+
type: "gate",
|
|
810
|
+
code: "AGATE",
|
|
811
|
+
label: "Arrival Gate",
|
|
812
|
+
value: decodeResult.raw.arrival_gate
|
|
813
|
+
});
|
|
814
|
+
}
|
|
667
815
|
static tail(decodeResult, value) {
|
|
668
816
|
decodeResult.raw.tail = value;
|
|
669
817
|
decodeResult.formatted.items.push({
|
|
@@ -867,6 +1015,9 @@ var ResultFormatter = class {
|
|
|
867
1015
|
}
|
|
868
1016
|
}
|
|
869
1017
|
static version(decodeResult, value) {
|
|
1018
|
+
if (isNaN(value)) {
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
870
1021
|
decodeResult.raw.version = value;
|
|
871
1022
|
decodeResult.formatted.items.push({
|
|
872
1023
|
type: "version",
|
|
@@ -903,6 +1054,9 @@ var ResultFormatter = class {
|
|
|
903
1054
|
});
|
|
904
1055
|
}
|
|
905
1056
|
static desiredAltitude(decodeResult, value) {
|
|
1057
|
+
if (isNaN(value)) {
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
906
1060
|
decodeResult.raw.desired_alt = value;
|
|
907
1061
|
decodeResult.formatted.items.push({
|
|
908
1062
|
type: "desired_altitude",
|
|
@@ -977,6 +1131,14 @@ var ResultFormatter = class {
|
|
|
977
1131
|
value: decodeResult.raw.sequence_response.toString()
|
|
978
1132
|
});
|
|
979
1133
|
}
|
|
1134
|
+
/**
|
|
1135
|
+
* A field with no specific helper: `key` is its name in `raw` and its item type. `rawValue`
|
|
1136
|
+
* is stored in `raw` when it differs from the text shown (a number, for example).
|
|
1137
|
+
*/
|
|
1138
|
+
static raw(decodeResult, key, code, label, value, rawValue = value) {
|
|
1139
|
+
decodeResult.raw[key] = rawValue;
|
|
1140
|
+
decodeResult.formatted.items.push({ type: key, code, label, value });
|
|
1141
|
+
}
|
|
980
1142
|
static unknown(decodeResult, value, sep = ",") {
|
|
981
1143
|
if (!decodeResult.remaining.text) decodeResult.remaining.text = value;
|
|
982
1144
|
else decodeResult.remaining.text += sep + value;
|
|
@@ -1322,13 +1484,13 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1322
1484
|
const segments = value.split(".");
|
|
1323
1485
|
const parens_idx = segments[0].indexOf("(");
|
|
1324
1486
|
let name;
|
|
1325
|
-
let
|
|
1487
|
+
let runway2;
|
|
1326
1488
|
if (parens_idx === -1) {
|
|
1327
1489
|
name = segments[0];
|
|
1328
1490
|
} else {
|
|
1329
1491
|
name = segments[0].slice(0, parens_idx);
|
|
1330
1492
|
const close_paren_idx = segments[0].indexOf(")");
|
|
1331
|
-
|
|
1493
|
+
runway2 = segments[0].slice(
|
|
1332
1494
|
parens_idx + 1,
|
|
1333
1495
|
close_paren_idx === -1 ? void 0 : close_paren_idx
|
|
1334
1496
|
);
|
|
@@ -1339,7 +1501,7 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1339
1501
|
}
|
|
1340
1502
|
decodeResult.raw.company_route = {
|
|
1341
1503
|
name,
|
|
1342
|
-
runway,
|
|
1504
|
+
runway: runway2,
|
|
1343
1505
|
waypoints
|
|
1344
1506
|
};
|
|
1345
1507
|
decodeResult.formatted.items.push({
|
|
@@ -1477,6 +1639,9 @@ var Arinc702Helper = class _Arinc702Helper {
|
|
|
1477
1639
|
case "TD":
|
|
1478
1640
|
processTimeOfDeparture(decodeResult, data2.split(","));
|
|
1479
1641
|
break;
|
|
1642
|
+
case "TR":
|
|
1643
|
+
processTR(decodeResult, data2.split(","));
|
|
1644
|
+
break;
|
|
1480
1645
|
case "TS":
|
|
1481
1646
|
_Arinc702Helper.processTimeStamp(decodeResult, data2.split(","));
|
|
1482
1647
|
break;
|
|
@@ -1657,6 +1822,21 @@ function processLandingReport(decodeResult, data) {
|
|
|
1657
1822
|
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
1658
1823
|
}
|
|
1659
1824
|
}
|
|
1825
|
+
function processTR(decodeResult, data) {
|
|
1826
|
+
if (data.length !== 21) {
|
|
1827
|
+
ResultFormatter.unknownArr(decodeResult, data, ",");
|
|
1828
|
+
return;
|
|
1829
|
+
}
|
|
1830
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(0, 5), ",");
|
|
1831
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[5]));
|
|
1832
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(6, 11), ",");
|
|
1833
|
+
ResultFormatter.departureAirport(decodeResult, data[11]);
|
|
1834
|
+
ResultFormatter.arrivalAirport(decodeResult, data[12]);
|
|
1835
|
+
ResultFormatter.departureRunway(decodeResult, data[13]);
|
|
1836
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(14, 16), ",");
|
|
1837
|
+
ResultFormatter.flightNumber(decodeResult, data[16]);
|
|
1838
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(17), ",");
|
|
1839
|
+
}
|
|
1660
1840
|
function processCenterOfGravity(decodeResult, data) {
|
|
1661
1841
|
if (data.length === 1) {
|
|
1662
1842
|
if (data[0] !== void 0 && data[0] !== "") {
|
|
@@ -1717,6 +1897,8 @@ function processIMI(decodeResult, type) {
|
|
|
1717
1897
|
decodeResult.formatted.description = "Load Distribution Information";
|
|
1718
1898
|
} else if (type === "PER") {
|
|
1719
1899
|
decodeResult.formatted.description = "Performance Report";
|
|
1900
|
+
} else if (type === "PRF") {
|
|
1901
|
+
decodeResult.formatted.description = "Profile Report";
|
|
1720
1902
|
} else if (type === "POS") {
|
|
1721
1903
|
decodeResult.formatted.description = "Position Report";
|
|
1722
1904
|
} else if (type === "PRG") {
|
|
@@ -2155,7 +2337,54 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
2155
2337
|
}
|
|
2156
2338
|
};
|
|
2157
2339
|
|
|
2340
|
+
// lib/utils/swa_request.ts
|
|
2341
|
+
var AIRLINES = { "189": "Southwest" };
|
|
2342
|
+
function swaRequestHeader(decodeResult, airlineId, layout, software) {
|
|
2343
|
+
const airline = AIRLINES[airlineId];
|
|
2344
|
+
ResultFormatter.raw(
|
|
2345
|
+
decodeResult,
|
|
2346
|
+
"airline_id",
|
|
2347
|
+
"AIRLINE",
|
|
2348
|
+
"Airline ID",
|
|
2349
|
+
airline ? `${airlineId} (${airline})` : airlineId,
|
|
2350
|
+
airlineId
|
|
2351
|
+
);
|
|
2352
|
+
ResultFormatter.raw(
|
|
2353
|
+
decodeResult,
|
|
2354
|
+
"request_layout",
|
|
2355
|
+
"LAYOUT",
|
|
2356
|
+
"Request Layout",
|
|
2357
|
+
layout
|
|
2358
|
+
);
|
|
2359
|
+
ResultFormatter.raw(
|
|
2360
|
+
decodeResult,
|
|
2361
|
+
"software_version",
|
|
2362
|
+
"SWVER",
|
|
2363
|
+
"Software Version",
|
|
2364
|
+
software
|
|
2365
|
+
);
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2158
2368
|
// lib/plugins/Label_10_LDR.ts
|
|
2369
|
+
function pounds(value) {
|
|
2370
|
+
if (value.trim() === "") return void 0;
|
|
2371
|
+
const thousands = Number(value);
|
|
2372
|
+
return Number.isFinite(thousands) ? Math.round(thousands * 1e3) : void 0;
|
|
2373
|
+
}
|
|
2374
|
+
function runway(value) {
|
|
2375
|
+
const [rwy, suffix = ""] = value.trim().split("/");
|
|
2376
|
+
return suffix.trim() === "" ? rwy.trim() : `${rwy.trim()}/${suffix.trim()}`;
|
|
2377
|
+
}
|
|
2378
|
+
var RUNWAY_CONDITION = {
|
|
2379
|
+
6: "dry",
|
|
2380
|
+
5: "good",
|
|
2381
|
+
4: "good to medium",
|
|
2382
|
+
3: "medium",
|
|
2383
|
+
2: "medium to poor",
|
|
2384
|
+
1: "poor",
|
|
2385
|
+
0: "nil"
|
|
2386
|
+
};
|
|
2387
|
+
var FLAPS = { "0": 30, "1": 40, "2": 15 };
|
|
2159
2388
|
var Label_10_LDR = class extends DecoderPlugin {
|
|
2160
2389
|
name = "label-10-ldr";
|
|
2161
2390
|
qualifiers() {
|
|
@@ -2167,18 +2396,13 @@ var Label_10_LDR = class extends DecoderPlugin {
|
|
|
2167
2396
|
decode(message, options = {}) {
|
|
2168
2397
|
const decodeResult = this.defaultResult();
|
|
2169
2398
|
decodeResult.decoder.name = this.name;
|
|
2170
|
-
decodeResult.formatted.description = "
|
|
2399
|
+
decodeResult.formatted.description = "Landing Data Request";
|
|
2171
2400
|
decodeResult.message = message;
|
|
2172
2401
|
const parts = message.text.split(",");
|
|
2173
|
-
if (parts.length <
|
|
2174
|
-
|
|
2175
|
-
console.log(`Decoder: Unknown 10 message: ${message.text}`);
|
|
2176
|
-
}
|
|
2177
|
-
ResultFormatter.unknown(decodeResult, message.text);
|
|
2178
|
-
decodeResult.decoded = false;
|
|
2179
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2180
|
-
return decodeResult;
|
|
2402
|
+
if (parts.length < 31) {
|
|
2403
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
2181
2404
|
}
|
|
2405
|
+
swaRequestHeader(decodeResult, parts[1], parts[2], parts[3]);
|
|
2182
2406
|
const lat = parts[5];
|
|
2183
2407
|
const lon = parts[6];
|
|
2184
2408
|
const position = {
|
|
@@ -2186,25 +2410,209 @@ var Label_10_LDR = class extends DecoderPlugin {
|
|
|
2186
2410
|
longitude: (lon[0] === "E" ? 1 : -1) * Number(lon.substring(1).trim())
|
|
2187
2411
|
};
|
|
2188
2412
|
ResultFormatter.position(decodeResult, position);
|
|
2189
|
-
|
|
2413
|
+
if (parts[7].trim() !== "") {
|
|
2414
|
+
ResultFormatter.altitude(decodeResult, Number(parts[7]));
|
|
2415
|
+
}
|
|
2416
|
+
const fuel = pounds(parts[8]);
|
|
2417
|
+
if (fuel !== void 0) ResultFormatter.currentFuel(decodeResult, fuel);
|
|
2190
2418
|
ResultFormatter.departureAirport(decodeResult, parts[9]);
|
|
2191
2419
|
ResultFormatter.arrivalAirport(decodeResult, parts[10]);
|
|
2192
|
-
ResultFormatter.
|
|
2193
|
-
ResultFormatter.arrivalRunway(decodeResult, parts[12]
|
|
2194
|
-
const altRwy = [parts[13]
|
|
2420
|
+
ResultFormatter.landingAirport(decodeResult, parts[11]);
|
|
2421
|
+
ResultFormatter.arrivalRunway(decodeResult, runway(parts[12]));
|
|
2422
|
+
const altRwy = [runway(parts[13]), runway(parts[14])].filter((r) => r != "").join(",");
|
|
2195
2423
|
if (altRwy != "") {
|
|
2196
2424
|
ResultFormatter.alternateRunway(decodeResult, altRwy);
|
|
2197
2425
|
}
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2426
|
+
const unknown = [parts[4]];
|
|
2427
|
+
const condition = parts[15].trim();
|
|
2428
|
+
if (/^[1-6]$/.test(condition)) {
|
|
2429
|
+
const code = 6 - Number(condition);
|
|
2430
|
+
ResultFormatter.raw(
|
|
2431
|
+
decodeResult,
|
|
2432
|
+
"runway_condition_code",
|
|
2433
|
+
"RCC",
|
|
2434
|
+
"Runway Condition Code",
|
|
2435
|
+
`${code} (${RUNWAY_CONDITION[code]})`,
|
|
2436
|
+
code
|
|
2437
|
+
);
|
|
2438
|
+
} else if (condition !== "0") {
|
|
2439
|
+
unknown.push(parts[15]);
|
|
2440
|
+
}
|
|
2441
|
+
const flaps = FLAPS[parts[16].trim()];
|
|
2442
|
+
if (flaps !== void 0) {
|
|
2443
|
+
ResultFormatter.raw(
|
|
2444
|
+
decodeResult,
|
|
2445
|
+
"landing_flaps",
|
|
2446
|
+
"FLAPS",
|
|
2447
|
+
"Landing Flaps",
|
|
2448
|
+
`${flaps}`,
|
|
2449
|
+
flaps
|
|
2450
|
+
);
|
|
2451
|
+
} else {
|
|
2452
|
+
unknown.push(parts[16]);
|
|
2453
|
+
}
|
|
2454
|
+
const [windDir, windSpeed, gust, temp, dew, altimeter] = parts.slice(17, 23).map((field) => {
|
|
2455
|
+
const value = field.trim();
|
|
2456
|
+
if (/^-?\d{1,4}$/.test(value)) return Number(value);
|
|
2457
|
+
if (value !== "") unknown.push(field);
|
|
2458
|
+
return void 0;
|
|
2459
|
+
});
|
|
2460
|
+
if (windDir !== void 0 || windSpeed !== void 0) {
|
|
2461
|
+
ResultFormatter.wind(decodeResult, windDir, windSpeed);
|
|
2462
|
+
}
|
|
2463
|
+
if (gust !== void 0) {
|
|
2464
|
+
ResultFormatter.raw(
|
|
2465
|
+
decodeResult,
|
|
2466
|
+
"wind_gust",
|
|
2467
|
+
"GUST",
|
|
2468
|
+
"Wind Gust",
|
|
2469
|
+
`${gust} knots`,
|
|
2470
|
+
gust
|
|
2471
|
+
);
|
|
2472
|
+
}
|
|
2473
|
+
ResultFormatter.temperature(
|
|
2474
|
+
decodeResult,
|
|
2475
|
+
temp === void 0 ? "" : `${temp}`
|
|
2476
|
+
);
|
|
2477
|
+
if (dew !== void 0) {
|
|
2478
|
+
ResultFormatter.raw(
|
|
2479
|
+
decodeResult,
|
|
2480
|
+
"dew_point",
|
|
2481
|
+
"DEWPT",
|
|
2482
|
+
"Dew Point (C)",
|
|
2483
|
+
`${dew} degrees`,
|
|
2484
|
+
dew
|
|
2485
|
+
);
|
|
2486
|
+
}
|
|
2487
|
+
if (altimeter !== void 0) {
|
|
2488
|
+
const inHg = altimeter / 100;
|
|
2489
|
+
ResultFormatter.raw(
|
|
2490
|
+
decodeResult,
|
|
2491
|
+
"altimeter",
|
|
2492
|
+
"ALTIM",
|
|
2493
|
+
"Altimeter",
|
|
2494
|
+
`${inHg.toFixed(2)} inHg`,
|
|
2495
|
+
inHg
|
|
2496
|
+
);
|
|
2497
|
+
}
|
|
2498
|
+
const antiIce = parts[23].trim();
|
|
2499
|
+
if (/^[1-9]$/.test(antiIce)) {
|
|
2500
|
+
ResultFormatter.raw(
|
|
2501
|
+
decodeResult,
|
|
2502
|
+
"anti_ice",
|
|
2503
|
+
"ANTIICE",
|
|
2504
|
+
"Anti-Ice",
|
|
2505
|
+
antiIce === "1" ? "engine" : antiIce,
|
|
2506
|
+
Number(antiIce)
|
|
2507
|
+
);
|
|
2508
|
+
} else if (antiIce !== "0") {
|
|
2509
|
+
unknown.push(parts[23]);
|
|
2510
|
+
}
|
|
2511
|
+
const flags = [
|
|
2512
|
+
[parts[24], "enroute_icing", "ICING", "En Route Icing"],
|
|
2513
|
+
// the card says HGS AIII: 113 of 113 pairs, 32 requests
|
|
2514
|
+
[parts[25], "hgs_approach", "HGS", "HGS Approach"]
|
|
2515
|
+
];
|
|
2516
|
+
for (const [value, key, code, label] of flags) {
|
|
2517
|
+
if (value.trim() === "1") {
|
|
2518
|
+
ResultFormatter.raw(decodeResult, key, code, label, "yes", true);
|
|
2519
|
+
} else if (value.trim() !== "0") {
|
|
2520
|
+
unknown.push(value);
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
const nonNormal = parts[26].trim();
|
|
2524
|
+
if (/^\d+$/.test(nonNormal) && Number(nonNormal) !== 0) {
|
|
2525
|
+
ResultFormatter.raw(
|
|
2526
|
+
decodeResult,
|
|
2527
|
+
"non_normal_configuration",
|
|
2528
|
+
"NNC",
|
|
2529
|
+
"Non-Normal Configuration",
|
|
2530
|
+
`${Number(nonNormal)}`,
|
|
2531
|
+
Number(nonNormal)
|
|
2532
|
+
);
|
|
2533
|
+
} else if (!/^0+$/.test(nonNormal)) {
|
|
2534
|
+
unknown.push(parts[26]);
|
|
2535
|
+
}
|
|
2536
|
+
if (parts[27].trim() !== "") unknown.push(parts[27]);
|
|
2537
|
+
const weights = [
|
|
2538
|
+
["zero_fuel_weight", "ZFW", "Zero Fuel Weight", parts[28]],
|
|
2539
|
+
["landing_fuel", "LFUEL", "Landing Fuel", parts[29]],
|
|
2540
|
+
["landing_weight", "LDW", "Landing Weight", parts[30]]
|
|
2541
|
+
];
|
|
2542
|
+
for (const [key, code, label, value] of weights) {
|
|
2543
|
+
const amount = pounds(value);
|
|
2544
|
+
if (amount === void 0) continue;
|
|
2545
|
+
ResultFormatter.raw(
|
|
2546
|
+
decodeResult,
|
|
2547
|
+
key,
|
|
2548
|
+
code,
|
|
2549
|
+
label,
|
|
2550
|
+
`${amount} pounds`,
|
|
2551
|
+
amount
|
|
2552
|
+
);
|
|
2553
|
+
}
|
|
2554
|
+
const gradient = (parts[31] ?? "").trim();
|
|
2555
|
+
if (/^\d+$/.test(gradient)) {
|
|
2556
|
+
ResultFormatter.raw(
|
|
2557
|
+
decodeResult,
|
|
2558
|
+
"missed_approach_gradient",
|
|
2559
|
+
"MAGRAD",
|
|
2560
|
+
"Missed Approach Climb Gradient",
|
|
2561
|
+
`${Number(gradient)} feet per nautical mile`,
|
|
2562
|
+
Number(gradient)
|
|
2563
|
+
);
|
|
2564
|
+
} else if (gradient !== "" && gradient !== "----.") {
|
|
2565
|
+
unknown.push(parts[31]);
|
|
2566
|
+
}
|
|
2567
|
+
const missedAltitude = (parts[32] ?? "").trim();
|
|
2568
|
+
if (/^\d+$/.test(missedAltitude)) {
|
|
2569
|
+
ResultFormatter.raw(
|
|
2570
|
+
decodeResult,
|
|
2571
|
+
"missed_approach_altitude",
|
|
2572
|
+
"MAALT",
|
|
2573
|
+
"Missed Approach Altitude",
|
|
2574
|
+
`${Number(missedAltitude)} feet`,
|
|
2575
|
+
Number(missedAltitude)
|
|
2576
|
+
);
|
|
2577
|
+
} else if (missedAltitude !== "") {
|
|
2578
|
+
unknown.push(parts[32]);
|
|
2579
|
+
}
|
|
2580
|
+
unknown.push(...parts.slice(33).filter((field) => field.trim() !== ""));
|
|
2581
|
+
ResultFormatter.unknownArr(decodeResult, unknown);
|
|
2202
2582
|
decodeResult.decoded = true;
|
|
2203
2583
|
decodeResult.decoder.decodeLevel = "partial";
|
|
2204
2584
|
return decodeResult;
|
|
2205
2585
|
}
|
|
2206
2586
|
};
|
|
2207
2587
|
|
|
2588
|
+
// lib/plugins/Label_10_LRW.ts
|
|
2589
|
+
var Label_10_LRW = class extends DecoderPlugin {
|
|
2590
|
+
name = "label-10-lrw";
|
|
2591
|
+
qualifiers() {
|
|
2592
|
+
return {
|
|
2593
|
+
labels: ["10"],
|
|
2594
|
+
preambles: ["LRW01,"]
|
|
2595
|
+
};
|
|
2596
|
+
}
|
|
2597
|
+
decode(message, options = {}) {
|
|
2598
|
+
const decodeResult = this.initResult(message, "Landing Runways Request");
|
|
2599
|
+
const parts = message.text.split(",");
|
|
2600
|
+
if (parts.length < 8 || parts[7].trim() === "") {
|
|
2601
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
2602
|
+
}
|
|
2603
|
+
swaRequestHeader(decodeResult, parts[1], parts[2], parts[3]);
|
|
2604
|
+
ResultFormatter.departureAirport(decodeResult, parts[6]);
|
|
2605
|
+
ResultFormatter.arrivalAirport(decodeResult, parts[7]);
|
|
2606
|
+
ResultFormatter.unknownArr(decodeResult, [
|
|
2607
|
+
parts[4],
|
|
2608
|
+
parts[5],
|
|
2609
|
+
...parts.slice(8).filter((field) => field.trim() !== "")
|
|
2610
|
+
]);
|
|
2611
|
+
this.setDecodeLevel(decodeResult, true);
|
|
2612
|
+
return decodeResult;
|
|
2613
|
+
}
|
|
2614
|
+
};
|
|
2615
|
+
|
|
2208
2616
|
// lib/plugins/Label_10_POS.ts
|
|
2209
2617
|
var Label_10_POS = class extends DecoderPlugin {
|
|
2210
2618
|
name = "label-10-pos";
|
|
@@ -2304,6 +2712,364 @@ var Label_10_Slash = class extends DecoderPlugin {
|
|
|
2304
2712
|
}
|
|
2305
2713
|
};
|
|
2306
2714
|
|
|
2715
|
+
// lib/utils/runway_utils.ts
|
|
2716
|
+
var SIDES = {
|
|
2717
|
+
N: "north",
|
|
2718
|
+
NE: "northeast",
|
|
2719
|
+
E: "east",
|
|
2720
|
+
SE: "southeast",
|
|
2721
|
+
S: "south",
|
|
2722
|
+
SW: "southwest",
|
|
2723
|
+
W: "west",
|
|
2724
|
+
NW: "northwest"
|
|
2725
|
+
};
|
|
2726
|
+
var RunwayUtils = class {
|
|
2727
|
+
/**
|
|
2728
|
+
* Describe the condition that names a runway variant in Southwest landing data, e.g.
|
|
2729
|
+
* `11/AIB -E1804F`: the runway, the variant's code and its condition.
|
|
2730
|
+
*
|
|
2731
|
+
* -E1804F is 1804 feet taken off the east end, -SWCBL the arresting cable at the southwest
|
|
2732
|
+
* end. Checked on the LRW01 runway lists of six airports, where every variant's length is
|
|
2733
|
+
* the runway's less the feet given, or less 1500 feet for a cable. LAHSO is sent as written.
|
|
2734
|
+
*
|
|
2735
|
+
* @param name - the runway as sent, with its variant
|
|
2736
|
+
* @returns a description of the condition, or undefined when the name has none
|
|
2737
|
+
*/
|
|
2738
|
+
static variantDescription(name) {
|
|
2739
|
+
const text = name.trim();
|
|
2740
|
+
const cut = text.match(/-(NE|NW|SE|SW|N|E|S|W)(\d+)F$/);
|
|
2741
|
+
if (cut) {
|
|
2742
|
+
return `${Number(cut[2])} feet off the ${SIDES[cut[1]]} end`;
|
|
2743
|
+
}
|
|
2744
|
+
const cable = text.match(/-(NE|NW|SE|SW|N|E|S|W)CBL$/);
|
|
2745
|
+
if (cable) {
|
|
2746
|
+
return `arresting cable at the ${SIDES[cable[1]]} end`;
|
|
2747
|
+
}
|
|
2748
|
+
if (/(^|\s)LAHSO$/.test(text)) {
|
|
2749
|
+
return "land and hold short";
|
|
2750
|
+
}
|
|
2751
|
+
return void 0;
|
|
2752
|
+
}
|
|
2753
|
+
};
|
|
2754
|
+
|
|
2755
|
+
// lib/plugins/Label_11_LDR.ts
|
|
2756
|
+
function tod(hours, minutes) {
|
|
2757
|
+
const h = Number(hours);
|
|
2758
|
+
const m = Number(minutes);
|
|
2759
|
+
return h <= 23 && m <= 59 ? h * 3600 + m * 60 : void 0;
|
|
2760
|
+
}
|
|
2761
|
+
function pounds2(value) {
|
|
2762
|
+
return Math.round(Number(value) * 1e3);
|
|
2763
|
+
}
|
|
2764
|
+
function variant(runway2) {
|
|
2765
|
+
const description = RunwayUtils.variantDescription(runway2);
|
|
2766
|
+
return description === void 0 ? {} : { variant: description };
|
|
2767
|
+
}
|
|
2768
|
+
var HEADER = [
|
|
2769
|
+
/^LDR01,(\w{4}) LANDING DATA,FLT(?:\s+METAR-(\d{2})(\d{2})Z)?\s*$/,
|
|
2770
|
+
/^(\d{1,4})\s+WIND\s+LDW\s*$/,
|
|
2771
|
+
/^TIME\s+(\d{3}|VRB)\/(\d{2,3})G(\d{2,3}|--)\s+(\d+\.\d)\s*$/,
|
|
2772
|
+
/^(\d{2})(\d{2})Z\s+OAT\/DEW\s*(\S*)\s*$/,
|
|
2773
|
+
/^\s+(-?\d{2,3})\/(-?\d{2,3})\s*(\S*)\s*$/,
|
|
2774
|
+
/^\s+QNH\s*(\S*)\s*$/,
|
|
2775
|
+
// QNH in inches of mercury, or hectopascals outside the US
|
|
2776
|
+
/^\s+(\d{2}\.\d{2}|\d{4})\s*(\S*)\s*$/
|
|
2777
|
+
];
|
|
2778
|
+
var RUNWAY = /^(\d{1,2}[LRC]?(?:\/\S+)?(?: -\S+)?)\s+(\d{1,5})\s*$/;
|
|
2779
|
+
var RUNWAY_START = /^\d{1,2}[LRC]?(?:\/\S+)?(?: -\S+)?(?:\s{2,}\d*)?\s*$/;
|
|
2780
|
+
var ALTERNATIVES = "--- ALTERNATIVE RWYS ---";
|
|
2781
|
+
var ALTERNATIVE = /^(?:(.+?)\s{2,})?(\d{1,2}[LRC]?(?:\/\S+)?)\s*$/;
|
|
2782
|
+
var BLOCK = [
|
|
2783
|
+
/^FLAPS (\d{2}|--)\s*$/,
|
|
2784
|
+
/^VREF\/VTGT\s+(?:(\d{2})([HT])\/(\d{2})([LR])|---\/---)\s*$/,
|
|
2785
|
+
/^\s*(?:(\d{3})\/(\d{3}) ([+-]\d+)|---\/---)\s+(AB\d)\s+(\d+|----)\s*$/,
|
|
2786
|
+
/^MRLW (\d+\.\d\/\S|-+\/-)\s+(AB\d)\s+(\d+|----)\s*$/,
|
|
2787
|
+
/^\s*LDW (\d+\.\d)\s+(ABM)\s+(\d+|----)\s*$/
|
|
2788
|
+
];
|
|
2789
|
+
var Label_11_LDR = class extends DecoderPlugin {
|
|
2790
|
+
name = "label-11-ldr";
|
|
2791
|
+
qualifiers() {
|
|
2792
|
+
return {
|
|
2793
|
+
labels: ["11"],
|
|
2794
|
+
preambles: ["LDR01,"]
|
|
2795
|
+
};
|
|
2796
|
+
}
|
|
2797
|
+
decode(message, options = {}) {
|
|
2798
|
+
const decodeResult = this.initResult(message, "Landing Data");
|
|
2799
|
+
const nl = message.text.includes("\r\n") ? "\r\n" : "\n";
|
|
2800
|
+
const lines = message.text.split(/\r?\n/);
|
|
2801
|
+
const first = lines[0].match(HEADER[0]);
|
|
2802
|
+
if (!first) {
|
|
2803
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
2804
|
+
}
|
|
2805
|
+
const unknown = [];
|
|
2806
|
+
ResultFormatter.landingAirport(decodeResult, first[1]);
|
|
2807
|
+
const metar = first[2] === void 0 ? void 0 : tod(first[2], first[3]);
|
|
2808
|
+
if (first[2] !== void 0 && metar === void 0) {
|
|
2809
|
+
unknown.push(`METAR-${first[2]}${first[3]}Z`);
|
|
2810
|
+
}
|
|
2811
|
+
if (metar !== void 0) {
|
|
2812
|
+
ResultFormatter.raw(
|
|
2813
|
+
decodeResult,
|
|
2814
|
+
"metar_time",
|
|
2815
|
+
"METAR",
|
|
2816
|
+
"METAR Time",
|
|
2817
|
+
DateTimeUtils.timestampToString(metar),
|
|
2818
|
+
metar
|
|
2819
|
+
);
|
|
2820
|
+
}
|
|
2821
|
+
const runways = [];
|
|
2822
|
+
let i = 1;
|
|
2823
|
+
for (; i < HEADER.length && i < lines.length; i++) {
|
|
2824
|
+
const m = lines[i].match(HEADER[i]);
|
|
2825
|
+
if (!m) break;
|
|
2826
|
+
if (i === 1) {
|
|
2827
|
+
ResultFormatter.flightNumber(decodeResult, m[1]);
|
|
2828
|
+
} else if (i === 2) {
|
|
2829
|
+
if (m[1] === "VRB") {
|
|
2830
|
+
ResultFormatter.variableWind(decodeResult, Number(m[2]));
|
|
2831
|
+
} else {
|
|
2832
|
+
ResultFormatter.wind(decodeResult, Number(m[1]), Number(m[2]));
|
|
2833
|
+
}
|
|
2834
|
+
if (m[3] !== "--") {
|
|
2835
|
+
ResultFormatter.raw(
|
|
2836
|
+
decodeResult,
|
|
2837
|
+
"wind_gust",
|
|
2838
|
+
"GUST",
|
|
2839
|
+
"Wind Gust",
|
|
2840
|
+
`${Number(m[3])} knots`,
|
|
2841
|
+
Number(m[3])
|
|
2842
|
+
);
|
|
2843
|
+
}
|
|
2844
|
+
ResultFormatter.raw(
|
|
2845
|
+
decodeResult,
|
|
2846
|
+
"landing_weight",
|
|
2847
|
+
"LDW",
|
|
2848
|
+
"Landing Weight",
|
|
2849
|
+
`${pounds2(m[4])} pounds`,
|
|
2850
|
+
pounds2(m[4])
|
|
2851
|
+
);
|
|
2852
|
+
} else if (i === 3) {
|
|
2853
|
+
const time = tod(m[1], m[2]);
|
|
2854
|
+
if (time === void 0) {
|
|
2855
|
+
unknown.push(`${m[1]}${m[2]}Z`);
|
|
2856
|
+
} else {
|
|
2857
|
+
ResultFormatter.timestamp(decodeResult, time);
|
|
2858
|
+
}
|
|
2859
|
+
runways.push(m[3]);
|
|
2860
|
+
} else if (i === 4) {
|
|
2861
|
+
ResultFormatter.temperature(decodeResult, `${Number(m[1])}`);
|
|
2862
|
+
ResultFormatter.raw(
|
|
2863
|
+
decodeResult,
|
|
2864
|
+
"dew_point",
|
|
2865
|
+
"DEWPT",
|
|
2866
|
+
"Dew Point (C)",
|
|
2867
|
+
`${Number(m[2])} degrees`,
|
|
2868
|
+
Number(m[2])
|
|
2869
|
+
);
|
|
2870
|
+
runways.push(m[3]);
|
|
2871
|
+
} else if (i === 5) {
|
|
2872
|
+
runways.push(m[1]);
|
|
2873
|
+
} else {
|
|
2874
|
+
ResultFormatter.raw(
|
|
2875
|
+
decodeResult,
|
|
2876
|
+
"altimeter",
|
|
2877
|
+
"ALTIM",
|
|
2878
|
+
"Altimeter",
|
|
2879
|
+
`${m[1]} ${m[1].includes(".") ? "inHg" : "hPa"}`,
|
|
2880
|
+
Number(m[1])
|
|
2881
|
+
);
|
|
2882
|
+
runways.push(m[2]);
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
const listed = runways.filter((r) => r !== "");
|
|
2886
|
+
if (listed.length > 0) {
|
|
2887
|
+
ResultFormatter.raw(
|
|
2888
|
+
decodeResult,
|
|
2889
|
+
"runways",
|
|
2890
|
+
"RWYS",
|
|
2891
|
+
"Runways",
|
|
2892
|
+
listed.join(", "),
|
|
2893
|
+
listed
|
|
2894
|
+
);
|
|
2895
|
+
}
|
|
2896
|
+
const rest = lines.slice(i);
|
|
2897
|
+
let at = 0;
|
|
2898
|
+
const alternatives = [];
|
|
2899
|
+
if (rest[0]?.trim() === "REMARKS") {
|
|
2900
|
+
const remarks = [];
|
|
2901
|
+
for (at = 1; at < rest.length && !RUNWAY_START.test(rest[at]); at++) {
|
|
2902
|
+
if (rest[at].trim() === ALTERNATIVES) {
|
|
2903
|
+
at = this.alternatives(rest, at + 1, alternatives, unknown);
|
|
2904
|
+
break;
|
|
2905
|
+
}
|
|
2906
|
+
if (rest[at].trim() !== "") remarks.push(rest[at].trim());
|
|
2907
|
+
}
|
|
2908
|
+
if (remarks.length > 0) {
|
|
2909
|
+
ResultFormatter.raw(
|
|
2910
|
+
decodeResult,
|
|
2911
|
+
"remarks",
|
|
2912
|
+
"RMK",
|
|
2913
|
+
"Remarks",
|
|
2914
|
+
remarks.join(" ")
|
|
2915
|
+
);
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
if (alternatives.length > 0) {
|
|
2919
|
+
ResultFormatter.raw(
|
|
2920
|
+
decodeResult,
|
|
2921
|
+
"alternative_runways",
|
|
2922
|
+
"ALTRWY",
|
|
2923
|
+
"Alternative Runways",
|
|
2924
|
+
alternatives.map((a) => a.variant ? `${a.runway} (${a.variant})` : a.runway).join(", "),
|
|
2925
|
+
alternatives
|
|
2926
|
+
);
|
|
2927
|
+
}
|
|
2928
|
+
const blocks = [];
|
|
2929
|
+
while (at < rest.length) {
|
|
2930
|
+
const block = this.runwayBlock(rest.slice(at, at + 1 + BLOCK.length));
|
|
2931
|
+
if (block) {
|
|
2932
|
+
blocks.push(block);
|
|
2933
|
+
at += 1 + BLOCK.length;
|
|
2934
|
+
continue;
|
|
2935
|
+
}
|
|
2936
|
+
const line = rest[at];
|
|
2937
|
+
const head = line.match(RUNWAY);
|
|
2938
|
+
const next = rest.slice(at + 1).find((l) => l.trim() !== "");
|
|
2939
|
+
if (head && next !== void 0 && !next.startsWith("FLAPS") && // a FLAPS line cut off by the end of the block
|
|
2940
|
+
!"FLAPS".startsWith(next.trim()) && !RUNWAY_START.test(next)) {
|
|
2941
|
+
blocks.push({
|
|
2942
|
+
runway: head[1],
|
|
2943
|
+
...variant(head[1]),
|
|
2944
|
+
length: Number(head[2]),
|
|
2945
|
+
stoppingMargins: {}
|
|
2946
|
+
});
|
|
2947
|
+
at++;
|
|
2948
|
+
continue;
|
|
2949
|
+
}
|
|
2950
|
+
const last = blocks[blocks.length - 1];
|
|
2951
|
+
if (line.trim() !== "") {
|
|
2952
|
+
if (last && !RUNWAY_START.test(line)) {
|
|
2953
|
+
last.notes = [...last.notes ?? [], line.trim()];
|
|
2954
|
+
} else {
|
|
2955
|
+
unknown.push(...rest.slice(at).filter((l) => l.trim() !== ""));
|
|
2956
|
+
break;
|
|
2957
|
+
}
|
|
2958
|
+
}
|
|
2959
|
+
at++;
|
|
2960
|
+
}
|
|
2961
|
+
for (const block of blocks) {
|
|
2962
|
+
ResultFormatter.runwayLandingData(decodeResult, block);
|
|
2963
|
+
}
|
|
2964
|
+
if (unknown.length > 0) {
|
|
2965
|
+
ResultFormatter.unknown(decodeResult, unknown.join(nl), nl);
|
|
2966
|
+
}
|
|
2967
|
+
this.setDecodeLevel(
|
|
2968
|
+
decodeResult,
|
|
2969
|
+
true,
|
|
2970
|
+
i < HEADER.length ? "partial" : void 0
|
|
2971
|
+
);
|
|
2972
|
+
return decodeResult;
|
|
2973
|
+
}
|
|
2974
|
+
/** The six lines of one runway, or undefined if they are not a whole block. */
|
|
2975
|
+
runwayBlock(lines) {
|
|
2976
|
+
const head = lines[0]?.match(RUNWAY);
|
|
2977
|
+
if (!head || lines.length < 1 + BLOCK.length) return void 0;
|
|
2978
|
+
const m = BLOCK.map((re, n) => lines[n + 1].match(re));
|
|
2979
|
+
if (m.some((x) => !x)) return void 0;
|
|
2980
|
+
const [flaps, wind, speeds, mrlw, ldw] = m;
|
|
2981
|
+
const data = {
|
|
2982
|
+
runway: head[1],
|
|
2983
|
+
...variant(head[1]),
|
|
2984
|
+
length: Number(head[2]),
|
|
2985
|
+
stoppingMargins: {}
|
|
2986
|
+
};
|
|
2987
|
+
if (flaps[1] !== "--") data.flaps = Number(flaps[1]);
|
|
2988
|
+
if (wind[1] !== void 0) {
|
|
2989
|
+
data.headwind = Number(wind[1]) * (wind[2] === "T" ? -1 : 1);
|
|
2990
|
+
data.crosswind = Number(wind[3]);
|
|
2991
|
+
data.crosswindSide = wind[4];
|
|
2992
|
+
}
|
|
2993
|
+
if (speeds[1] !== void 0) {
|
|
2994
|
+
data.vref = Number(speeds[1]);
|
|
2995
|
+
data.vtarget = Number(speeds[2]);
|
|
2996
|
+
data.additive = Number(speeds[3]);
|
|
2997
|
+
}
|
|
2998
|
+
if (!mrlw[1].startsWith("-")) data.maxLandingWeight = mrlw[1];
|
|
2999
|
+
data.landingWeight = pounds2(ldw[1]);
|
|
3000
|
+
for (const [setting, feet] of [
|
|
3001
|
+
[speeds[4], speeds[5]],
|
|
3002
|
+
[mrlw[2], mrlw[3]],
|
|
3003
|
+
[ldw[2], ldw[3]]
|
|
3004
|
+
]) {
|
|
3005
|
+
if (feet !== "----") data.stoppingMargins[setting] = Number(feet);
|
|
3006
|
+
}
|
|
3007
|
+
return data;
|
|
3008
|
+
}
|
|
3009
|
+
/**
|
|
3010
|
+
* The runways listed after ALTERNATIVE RWYS, which run to the end of the card. Returns the
|
|
3011
|
+
* index of the line after them.
|
|
3012
|
+
*/
|
|
3013
|
+
alternatives(lines, from, out, unknown) {
|
|
3014
|
+
for (let n = from; n < lines.length; n++) {
|
|
3015
|
+
const line = lines[n];
|
|
3016
|
+
if (line.trim() === "") continue;
|
|
3017
|
+
const m = line.match(ALTERNATIVE);
|
|
3018
|
+
if (!m || n === lines.length - 1) {
|
|
3019
|
+
unknown.push(line.trim());
|
|
3020
|
+
continue;
|
|
3021
|
+
}
|
|
3022
|
+
const name = m[1]?.trim();
|
|
3023
|
+
out.push({
|
|
3024
|
+
runway: m[2],
|
|
3025
|
+
...name === void 0 ? {} : { name },
|
|
3026
|
+
...variant(name ?? m[2])
|
|
3027
|
+
});
|
|
3028
|
+
}
|
|
3029
|
+
return lines.length;
|
|
3030
|
+
}
|
|
3031
|
+
};
|
|
3032
|
+
|
|
3033
|
+
// lib/plugins/Label_11_LRW.ts
|
|
3034
|
+
var RUNWAY2 = /^(\d{1,2}[LRC]?)\s?(?:\/(\S+))?\s+(?:(-\S+|LAHSO)\s+)?(\d{3,5})\s*$/;
|
|
3035
|
+
var Label_11_LRW = class extends DecoderPlugin {
|
|
3036
|
+
name = "label-11-lrw";
|
|
3037
|
+
qualifiers() {
|
|
3038
|
+
return {
|
|
3039
|
+
labels: ["11"],
|
|
3040
|
+
preambles: ["LRW01,"]
|
|
3041
|
+
};
|
|
3042
|
+
}
|
|
3043
|
+
decode(message, options = {}) {
|
|
3044
|
+
const decodeResult = this.initResult(message, "Landing Runways");
|
|
3045
|
+
const nl = message.text.includes("\r\n") ? "\r\n" : "\n";
|
|
3046
|
+
const first = message.text.match(/^LRW01,(\w{4}) LANDING RUNWAYS,/);
|
|
3047
|
+
if (!first) {
|
|
3048
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
3049
|
+
}
|
|
3050
|
+
ResultFormatter.landingAirport(decodeResult, first[1]);
|
|
3051
|
+
const lines = message.text.slice(first[0].length).split(/\r?\n/);
|
|
3052
|
+
for (const line of lines) {
|
|
3053
|
+
if (line.trim() === "") continue;
|
|
3054
|
+
const m = line.match(RUNWAY2);
|
|
3055
|
+
if (!m) {
|
|
3056
|
+
ResultFormatter.unknown(decodeResult, line.trim(), nl);
|
|
3057
|
+
continue;
|
|
3058
|
+
}
|
|
3059
|
+
const runway2 = [m[2] ? `${m[1]}/${m[2]}` : m[1], m[3]].filter((part) => part !== void 0).join(" ");
|
|
3060
|
+
const description = RunwayUtils.variantDescription(runway2);
|
|
3061
|
+
ResultFormatter.runwayLandingData(decodeResult, {
|
|
3062
|
+
runway: runway2,
|
|
3063
|
+
...description === void 0 ? {} : { variant: description },
|
|
3064
|
+
length: Number(m[4]),
|
|
3065
|
+
stoppingMargins: {}
|
|
3066
|
+
});
|
|
3067
|
+
}
|
|
3068
|
+
this.setDecodeLevel(decodeResult, true);
|
|
3069
|
+
return decodeResult;
|
|
3070
|
+
}
|
|
3071
|
+
};
|
|
3072
|
+
|
|
2307
3073
|
// lib/plugins/Label_12_N_Space.ts
|
|
2308
3074
|
var Label_12_N_Space = class extends DecoderPlugin {
|
|
2309
3075
|
name = "label-12-n-space";
|
|
@@ -3731,11 +4497,718 @@ var Label_30_Slash_EA = class extends DecoderPlugin {
|
|
|
3731
4497
|
}
|
|
3732
4498
|
};
|
|
3733
4499
|
|
|
3734
|
-
// lib/
|
|
3735
|
-
var
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
4500
|
+
// lib/utils/swa_compressed.ts
|
|
4501
|
+
var SWA_ALPHABET = " (),-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
4502
|
+
var SWA_UNREAD = "\xA4";
|
|
4503
|
+
var SWA_LABEL_37_TABLES = {
|
|
4504
|
+
"01": "VIK86MRN5-0PZS4UYXACEHLOTW BGD.123Q(7J9:F)/,",
|
|
4505
|
+
"02": "HG.KZL97QY15WRVTN4JA06(D ,:3MPBICU/8EOFSX)2-",
|
|
4506
|
+
"03": "4GXE/QU5FT)20P8RSJ-169AWHLB.,37MNVCYODIKZ (:",
|
|
4507
|
+
"04": "1BEHMPSUY,048DG269JLOQTWZ (-/37:ACFIKNRVX).5",
|
|
4508
|
+
"05": "3579BDFHJLNPRTVXZ(,.02468:ACEGIKMOQSUWY )-/1",
|
|
4509
|
+
"06": "AGFEDCBRQPONMLKJIH:9876543210/.-,)( ZYXWVUTS",
|
|
4510
|
+
"07": ":.02468ACEGIKMOQSUWY )-/13579BDFHJLNPRTVXZ(,",
|
|
4511
|
+
"08": "1MDS/JQ.OWZ79LNR532-6(: ,APEFTVIKYB08H)U4CXG",
|
|
4512
|
+
"09": "6LQMSR UZYVX(7:3-5KPTACB)021,894NODGJEFIHW./"
|
|
4513
|
+
};
|
|
4514
|
+
var SWA_LABEL_40_TABLES = {
|
|
4515
|
+
"01": "IRXZ2MY3NOP71-S,UVAJBLCWKD(T)E.0F4Q/6G8 H:95",
|
|
4516
|
+
"02": "GEXHZ)QC3YJ:4D0R/IBMOFSU( NA,.K9TL16V8P75W2-",
|
|
4517
|
+
"03": "XY3KAJ-5B4L 0CM7DZEIQT,1(GU:VHNOS6.892/PF)RW",
|
|
4518
|
+
"04": "HIX2JYK3 8L4Z9M5:NO(P6)Q7,RASB-TC.DU/E0VFW1G",
|
|
4519
|
+
"05": "V:WAXBYCZD E(F)G,HI-J.K/L0M1N2O3P4Q5R6S7T8U9",
|
|
4520
|
+
"06": "RQPONMLKJIHGFEDCBA /.-,)(:9876543210ZYXWVUTS",
|
|
4521
|
+
"07": "CYDZE(F)G,H-I.J/K 0L1M2N3O4P5Q6R7S8T9U:VAWBX",
|
|
4522
|
+
"08": "FDUGB0-R A:W9C4S5EHQX)JKZTN.O6(71I/8,LVM2YP3",
|
|
4523
|
+
"09": "/5GK9YZHJI8N: 6LM7DFEQTURWVSA(,OPB).-C03X421"
|
|
4524
|
+
};
|
|
4525
|
+
var PASS_37 = { "*": "*", ">": "+" };
|
|
4526
|
+
var PASS_40 = {
|
|
4527
|
+
"*": "*",
|
|
4528
|
+
"?": "?",
|
|
4529
|
+
"'": "'",
|
|
4530
|
+
"#": "#",
|
|
4531
|
+
_: "_"
|
|
4532
|
+
};
|
|
4533
|
+
function lookup(table, c) {
|
|
4534
|
+
const i = SWA_ALPHABET.indexOf(c);
|
|
4535
|
+
return i < 0 ? void 0 : table[i];
|
|
4536
|
+
}
|
|
4537
|
+
function plain(table, body, pass) {
|
|
4538
|
+
let out = "";
|
|
4539
|
+
for (const c of body) {
|
|
4540
|
+
if (c === "\n") out += "|";
|
|
4541
|
+
else out += lookup(table, c) ?? pass[c] ?? SWA_UNREAD;
|
|
4542
|
+
}
|
|
4543
|
+
return out;
|
|
4544
|
+
}
|
|
4545
|
+
function decodeSwaLabel37(body) {
|
|
4546
|
+
const b = body.replace(/\r/g, "");
|
|
4547
|
+
const table = SWA_LABEL_37_TABLES[b.substring(0, 2)];
|
|
4548
|
+
if (!table) return void 0;
|
|
4549
|
+
let nl = b.indexOf("\n");
|
|
4550
|
+
if (nl !== 7 && b.length > 7 && lookup(table, b[7]) === ",") nl = 7;
|
|
4551
|
+
if (nl < 0 || nl > 8) return void 0;
|
|
4552
|
+
let type = "";
|
|
4553
|
+
for (const c of b.substring(2, Math.min(nl, 7))) {
|
|
4554
|
+
type += lookup(table, c) ?? SWA_UNREAD;
|
|
4555
|
+
}
|
|
4556
|
+
return { type, text: plain(table, b.substring(nl + 1), PASS_37) };
|
|
4557
|
+
}
|
|
4558
|
+
function decodeSwaLabel40(body) {
|
|
4559
|
+
const b = body.replace(/\r/g, "");
|
|
4560
|
+
if (b.startsWith("POS01,")) {
|
|
4561
|
+
return { type: "POS01", text: b.trim() };
|
|
4562
|
+
}
|
|
4563
|
+
const code = b[5] === "," ? b.substring(6, 8) : "";
|
|
4564
|
+
if (code === "00") {
|
|
4565
|
+
return {
|
|
4566
|
+
type: b.substring(0, 5),
|
|
4567
|
+
text: b.substring(8).replace(/\n/g, "|")
|
|
4568
|
+
};
|
|
4569
|
+
}
|
|
4570
|
+
const table = SWA_LABEL_40_TABLES[code];
|
|
4571
|
+
if (!table) return void 0;
|
|
4572
|
+
return {
|
|
4573
|
+
type: b.substring(0, 5),
|
|
4574
|
+
text: plain(table, b.substring(8), PASS_40)
|
|
4575
|
+
};
|
|
4576
|
+
}
|
|
4577
|
+
var SWA_TYPES = {
|
|
4578
|
+
"37": /* @__PURE__ */ new Set([
|
|
4579
|
+
"ADV01",
|
|
4580
|
+
"CLB02",
|
|
4581
|
+
"DIV02",
|
|
4582
|
+
"DVC01",
|
|
4583
|
+
"ETA03",
|
|
4584
|
+
"FCM01",
|
|
4585
|
+
"FCR03",
|
|
4586
|
+
"FFD01",
|
|
4587
|
+
"FHD04",
|
|
4588
|
+
"FLI01",
|
|
4589
|
+
"FTD02",
|
|
4590
|
+
"GAM02",
|
|
4591
|
+
"GSR02",
|
|
4592
|
+
"HGD03",
|
|
4593
|
+
"HLD01",
|
|
4594
|
+
"INN03",
|
|
4595
|
+
"INR04",
|
|
4596
|
+
"MXR03",
|
|
4597
|
+
"OFF02",
|
|
4598
|
+
"OFP01",
|
|
4599
|
+
"ONN02",
|
|
4600
|
+
"OUT03",
|
|
4601
|
+
"PFR03",
|
|
4602
|
+
"PFR04",
|
|
4603
|
+
"PJS01",
|
|
4604
|
+
"PNS01",
|
|
4605
|
+
"POS01",
|
|
4606
|
+
"POS02",
|
|
4607
|
+
"PRM01",
|
|
4608
|
+
"RRR01",
|
|
4609
|
+
"RTG03",
|
|
4610
|
+
"RTG04",
|
|
4611
|
+
"RTG05",
|
|
4612
|
+
"TAR02",
|
|
4613
|
+
"TDM01",
|
|
4614
|
+
"TOD03",
|
|
4615
|
+
"TRB02",
|
|
4616
|
+
"TXI02",
|
|
4617
|
+
"VXR02"
|
|
4618
|
+
]),
|
|
4619
|
+
"40": /* @__PURE__ */ new Set([
|
|
4620
|
+
"ASR01",
|
|
4621
|
+
"DVP01",
|
|
4622
|
+
"FTX01",
|
|
4623
|
+
"GAR03",
|
|
4624
|
+
"GEN01",
|
|
4625
|
+
"PIC01",
|
|
4626
|
+
"POS01",
|
|
4627
|
+
"WFC01"
|
|
4628
|
+
])
|
|
4629
|
+
};
|
|
4630
|
+
function isSwaType(type, label) {
|
|
4631
|
+
return SWA_TYPES[label].has(type);
|
|
4632
|
+
}
|
|
4633
|
+
|
|
4634
|
+
// lib/utils/swa_fields.ts
|
|
4635
|
+
var APT = "(?:[A-Z]{4}| {4}|)";
|
|
4636
|
+
var LAT = "(?:[NS] ?\\d{1,2}\\.\\d{3}|-{4}\\.-{3}|)";
|
|
4637
|
+
var LON = "(?:[EW] ?\\d{1,3}\\.\\d{3}|-{4}\\.-{3}|)";
|
|
4638
|
+
var T4 = "(?:\\d{4}|\\*{4}|-{4})";
|
|
4639
|
+
var FOB = "(?: ?\\d{1,2}\\.\\d|\\*\\*\\.\\*)";
|
|
4640
|
+
var INT = "(?: *-? *\\d+| *|-+|\\*+)";
|
|
4641
|
+
var MACH = "\\.\\d{3}";
|
|
4642
|
+
var HMS = "\\d{6}";
|
|
4643
|
+
var OC = "[OC]";
|
|
4644
|
+
var POS = [
|
|
4645
|
+
APT,
|
|
4646
|
+
APT,
|
|
4647
|
+
LAT,
|
|
4648
|
+
LON,
|
|
4649
|
+
INT,
|
|
4650
|
+
INT,
|
|
4651
|
+
INT,
|
|
4652
|
+
MACH,
|
|
4653
|
+
FOB,
|
|
4654
|
+
T4,
|
|
4655
|
+
INT,
|
|
4656
|
+
INT,
|
|
4657
|
+
INT,
|
|
4658
|
+
INT
|
|
4659
|
+
];
|
|
4660
|
+
var ASR = " *-?\\d+(?:\\.[\\d-])?|XX\\.X";
|
|
4661
|
+
var SWA_LAYOUTS = {
|
|
4662
|
+
ASR01: [[ASR, ASR, ASR, ASR, ASR, ASR, ASR, ASR, "", ""]],
|
|
4663
|
+
CLB02: [[APT, APT, LAT, "", LON, FOB, T4]],
|
|
4664
|
+
ETA03: [[APT, APT, T4, FOB, LAT, LON]],
|
|
4665
|
+
FCM01: [["L[\\d-]", "R[\\d-]", "A[\\d-]", "B[\\d-]", "\\d+", T4]],
|
|
4666
|
+
FHD04: [
|
|
4667
|
+
[
|
|
4668
|
+
...POS,
|
|
4669
|
+
"(?:OUT|OFF|ON|IN|RET IN)",
|
|
4670
|
+
"X",
|
|
4671
|
+
INT,
|
|
4672
|
+
" *\\d*",
|
|
4673
|
+
HMS,
|
|
4674
|
+
"(?:\\d{6}|-{6})",
|
|
4675
|
+
"\\d{5}"
|
|
4676
|
+
]
|
|
4677
|
+
],
|
|
4678
|
+
FLI01: [[APT, APT, T4, FOB, LAT, LON]],
|
|
4679
|
+
GAM02: [[APT, APT, T4, LAT, LON]],
|
|
4680
|
+
GAR03: [
|
|
4681
|
+
[
|
|
4682
|
+
"[A-Z0-9]{1,4} *",
|
|
4683
|
+
"[YN]",
|
|
4684
|
+
"[YN]",
|
|
4685
|
+
"[YN]",
|
|
4686
|
+
"[YN]",
|
|
4687
|
+
"[YN]",
|
|
4688
|
+
"(?:1[23]\\d\\.\\d{1,3}|999\\.999)",
|
|
4689
|
+
"",
|
|
4690
|
+
""
|
|
4691
|
+
]
|
|
4692
|
+
],
|
|
4693
|
+
HGD03: [[...POS, INT]],
|
|
4694
|
+
INN03: [[APT, APT, T4, T4, FOB, OC, OC, OC, OC]],
|
|
4695
|
+
INR04: [[APT, APT, T4, T4, FOB, LAT, LON]],
|
|
4696
|
+
OUT03: [[APT, APT, T4, FOB, FOB, T4]],
|
|
4697
|
+
POS01: [
|
|
4698
|
+
[...POS, INT],
|
|
4699
|
+
[...POS, INT, HMS]
|
|
4700
|
+
],
|
|
4701
|
+
POS02: [[...POS, INT, HMS]],
|
|
4702
|
+
RTG04: [[APT, APT, T4, T4, T4, FOB, OC, OC, OC, OC]],
|
|
4703
|
+
RTG05: [[APT, APT, T4, T4, T4, FOB, OC, OC, OC, OC]],
|
|
4704
|
+
TDM01: [[APT, APT, LAT, LON, "(?:L1|L2|CR|SV)", OC, T4, HMS]],
|
|
4705
|
+
TXI02: [[APT, APT, T4, FOB]],
|
|
4706
|
+
VXR02: [["[A-Z]{3}"]]
|
|
4707
|
+
};
|
|
4708
|
+
var SWA_PREFIX_LAYOUTS = {
|
|
4709
|
+
MXR03: [APT, "(?:\\d{4}|)", "[0-3]"]
|
|
4710
|
+
};
|
|
4711
|
+
function swaFields(text) {
|
|
4712
|
+
return text.replace(/\|/g, ",").split(",");
|
|
4713
|
+
}
|
|
4714
|
+
function swaMatchesLayout(fields, layouts) {
|
|
4715
|
+
return layouts.some(
|
|
4716
|
+
(layout) => layout.length === fields.length && layout.every((rx, i) => new RegExp(`^(?:${rx})$`).test(fields[i]))
|
|
4717
|
+
);
|
|
4718
|
+
}
|
|
4719
|
+
var SwaFieldWriter = class {
|
|
4720
|
+
constructor(decodeResult, fields) {
|
|
4721
|
+
this.decodeResult = decodeResult;
|
|
4722
|
+
this.fields = fields;
|
|
4723
|
+
}
|
|
4724
|
+
decodeResult;
|
|
4725
|
+
fields;
|
|
4726
|
+
used = /* @__PURE__ */ new Set();
|
|
4727
|
+
take(i) {
|
|
4728
|
+
this.used.add(i);
|
|
4729
|
+
return this.fields[i] ?? "";
|
|
4730
|
+
}
|
|
4731
|
+
/** A field with no specific ResultFormatter helper; `key` is its name in `raw`. */
|
|
4732
|
+
item(i, key, code, label, value) {
|
|
4733
|
+
this.used.add(i);
|
|
4734
|
+
ResultFormatter.raw(this.decodeResult, key, code, label, value);
|
|
4735
|
+
}
|
|
4736
|
+
/** Marks a field as read without writing it (it was written together with another). */
|
|
4737
|
+
use(i) {
|
|
4738
|
+
return this.take(i);
|
|
4739
|
+
}
|
|
4740
|
+
departure(i) {
|
|
4741
|
+
const v = this.take(i);
|
|
4742
|
+
if (/^[A-Z]{4}$/.test(v))
|
|
4743
|
+
ResultFormatter.departureAirport(this.decodeResult, v);
|
|
4744
|
+
}
|
|
4745
|
+
arrival(i) {
|
|
4746
|
+
const v = this.take(i);
|
|
4747
|
+
if (/^[A-Z]{4}$/.test(v))
|
|
4748
|
+
ResultFormatter.arrivalAirport(this.decodeResult, v);
|
|
4749
|
+
}
|
|
4750
|
+
/**
|
|
4751
|
+
* Writes the position when both coordinates are present and in range. Otherwise the
|
|
4752
|
+
* placeholders are consumed and any coordinate that was sent stays for `remaining`.
|
|
4753
|
+
*/
|
|
4754
|
+
position(latIndex, lonIndex) {
|
|
4755
|
+
const lat = this.fields[latIndex] ?? "";
|
|
4756
|
+
const lon = this.fields[lonIndex] ?? "";
|
|
4757
|
+
const latitude = /^[NS] ?\d/.test(lat) ? CoordinateUtils.getDirection(lat) * Number(lat.substring(1).trim()) : NaN;
|
|
4758
|
+
const longitude = /^[EW] ?\d/.test(lon) ? CoordinateUtils.getDirection(lon) * Number(lon.substring(1).trim()) : NaN;
|
|
4759
|
+
if (Math.abs(latitude) <= 90 && Math.abs(longitude) <= 180) {
|
|
4760
|
+
this.used.add(latIndex);
|
|
4761
|
+
this.used.add(lonIndex);
|
|
4762
|
+
ResultFormatter.position(this.decodeResult, { latitude, longitude });
|
|
4763
|
+
return;
|
|
4764
|
+
}
|
|
4765
|
+
if (!/^[NS] ?\d/.test(lat)) this.used.add(latIndex);
|
|
4766
|
+
if (!/^[EW] ?\d/.test(lon)) this.used.add(lonIndex);
|
|
4767
|
+
}
|
|
4768
|
+
/** A whole number, or undefined for a placeholder. */
|
|
4769
|
+
int(i) {
|
|
4770
|
+
const v = this.take(i).replace(/ /g, "");
|
|
4771
|
+
return /^-?\d+$/.test(v) ? Number(v) : void 0;
|
|
4772
|
+
}
|
|
4773
|
+
altitude(i) {
|
|
4774
|
+
const v = this.int(i);
|
|
4775
|
+
if (v !== void 0) ResultFormatter.altitude(this.decodeResult, v);
|
|
4776
|
+
}
|
|
4777
|
+
/** Fuel on board, sent in thousands of pounds; written in pounds. */
|
|
4778
|
+
fuel(i) {
|
|
4779
|
+
const v = this.take(i).trim();
|
|
4780
|
+
if (/^\d+\.\d$/.test(v)) {
|
|
4781
|
+
ResultFormatter.currentFuel(
|
|
4782
|
+
this.decodeResult,
|
|
4783
|
+
Math.round(Number(v) * 1e3)
|
|
4784
|
+
);
|
|
4785
|
+
}
|
|
4786
|
+
}
|
|
4787
|
+
/**
|
|
4788
|
+
* HHMM or HHMMSS as seconds of the day. A placeholder is consumed; a time out of range is
|
|
4789
|
+
* left for `remaining`.
|
|
4790
|
+
*/
|
|
4791
|
+
tod(i) {
|
|
4792
|
+
const v = this.fields[i] ?? "";
|
|
4793
|
+
if (/^(?:[01]\d|2[0-3])[0-5]\d(?:[0-5]\d)?$/.test(v)) {
|
|
4794
|
+
this.used.add(i);
|
|
4795
|
+
return DateTimeUtils.convertHHMMSSToTod(v);
|
|
4796
|
+
}
|
|
4797
|
+
if (!/^\d+$/.test(v)) this.used.add(i);
|
|
4798
|
+
return void 0;
|
|
4799
|
+
}
|
|
4800
|
+
/** Writes a time through a ResultFormatter helper such as `out`, `in` or `timestamp`. */
|
|
4801
|
+
time(i, write) {
|
|
4802
|
+
const t = this.tod(i);
|
|
4803
|
+
if (t !== void 0) write(this.decodeResult, t);
|
|
4804
|
+
}
|
|
4805
|
+
/** A time with no ResultFormatter helper, written as HH:MM:SS. */
|
|
4806
|
+
timeItem(i, key, code, label) {
|
|
4807
|
+
const t = this.tod(i);
|
|
4808
|
+
if (t !== void 0) {
|
|
4809
|
+
this.item(i, key, code, label, DateTimeUtils.timestampToString(t));
|
|
4810
|
+
}
|
|
4811
|
+
}
|
|
4812
|
+
eta(i) {
|
|
4813
|
+
this.time(i, (r, t) => ResultFormatter.eta(r, t));
|
|
4814
|
+
}
|
|
4815
|
+
/** Fields not written above, non-empty, to `remaining`. */
|
|
4816
|
+
finish() {
|
|
4817
|
+
const rest = this.fields.filter(
|
|
4818
|
+
(v, i) => !this.used.has(i) && v.trim() !== ""
|
|
4819
|
+
);
|
|
4820
|
+
if (rest.length > 0) ResultFormatter.unknownArr(this.decodeResult, rest);
|
|
4821
|
+
return rest.length;
|
|
4822
|
+
}
|
|
4823
|
+
};
|
|
4824
|
+
|
|
4825
|
+
// lib/plugins/Label_37_SWA.ts
|
|
4826
|
+
var DESCRIPTIONS = {
|
|
4827
|
+
ADV01: "Ride Conditions Report",
|
|
4828
|
+
CLB02: "Climb Report",
|
|
4829
|
+
DVC01: "Divert Plan (Crew Copy)",
|
|
4830
|
+
ETA03: "ETA Report",
|
|
4831
|
+
FCM01: "Engine and Fuel State",
|
|
4832
|
+
FCR03: "Runway Condition Report",
|
|
4833
|
+
FHD04: "Frequency Handoff Report",
|
|
4834
|
+
FLI01: "Flight Initialization",
|
|
4835
|
+
FTD02: "Free Text to Dispatch",
|
|
4836
|
+
GAM02: "Gate Assignment Request",
|
|
4837
|
+
HGD03: "HowGozit Report",
|
|
4838
|
+
HLD01: "Holding Report",
|
|
4839
|
+
INN03: "In Report",
|
|
4840
|
+
INR04: "In Range Report",
|
|
4841
|
+
MXR03: "Maintenance Report",
|
|
4842
|
+
OFF02: "Off Report",
|
|
4843
|
+
ONN02: "On Report",
|
|
4844
|
+
OUT03: "Out Report",
|
|
4845
|
+
PFR03: "Post Flight Report",
|
|
4846
|
+
POS01: "Position Report",
|
|
4847
|
+
POS02: "Position Report",
|
|
4848
|
+
RRR01: "Reroute Report",
|
|
4849
|
+
RTG04: "Return to Gate Report",
|
|
4850
|
+
RTG05: "Return to Gate Report",
|
|
4851
|
+
TDM01: "Door Report",
|
|
4852
|
+
TRB02: "Turbulence Report",
|
|
4853
|
+
TXI02: "Taxi Report",
|
|
4854
|
+
VXR02: "Voice Call Request"
|
|
4855
|
+
};
|
|
4856
|
+
var DOORS = {
|
|
4857
|
+
L1: "L1 (forward entry)",
|
|
4858
|
+
L2: "L2 (aft entry)",
|
|
4859
|
+
CR: "Cargo",
|
|
4860
|
+
SV: "Service"
|
|
4861
|
+
};
|
|
4862
|
+
var MXR_CODES = {
|
|
4863
|
+
"0": "Nothing to report",
|
|
4864
|
+
"1": "Status option",
|
|
4865
|
+
"2": "Category and text",
|
|
4866
|
+
"3": "Free text"
|
|
4867
|
+
};
|
|
4868
|
+
var Label_37_SWA = class extends DecoderPlugin {
|
|
4869
|
+
name = "label-37-swa";
|
|
4870
|
+
qualifiers() {
|
|
4871
|
+
return {
|
|
4872
|
+
labels: ["37"],
|
|
4873
|
+
preambles: ["01", "02", "03", "04", "05", "06", "07", "08", "09"]
|
|
4874
|
+
};
|
|
4875
|
+
}
|
|
4876
|
+
decode(message, options = {}) {
|
|
4877
|
+
const decodeResult = this.defaultResult();
|
|
4878
|
+
decodeResult.decoder.name = this.name;
|
|
4879
|
+
decodeResult.message = message;
|
|
4880
|
+
const d = decodeSwaLabel37(message.text);
|
|
4881
|
+
if (!d || !isSwaType(d.type, "37")) {
|
|
4882
|
+
if (options.debug) {
|
|
4883
|
+
console.log(`Decoder: Unknown 37 message: ${message.text}`);
|
|
4884
|
+
}
|
|
4885
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
4886
|
+
decodeResult.formatted.description = "Unknown";
|
|
4887
|
+
return decodeResult;
|
|
4888
|
+
}
|
|
4889
|
+
decodeResult.decoded = true;
|
|
4890
|
+
decodeResult.formatted.description = DESCRIPTIONS[d.type] ?? "Southwest Message";
|
|
4891
|
+
decodeResult.raw.preamble = d.type;
|
|
4892
|
+
const text = d.text;
|
|
4893
|
+
const fields = swaFields(text);
|
|
4894
|
+
const layouts = SWA_LAYOUTS[d.type];
|
|
4895
|
+
const prefix = SWA_PREFIX_LAYOUTS[d.type];
|
|
4896
|
+
const clean = !text.includes(SWA_UNREAD);
|
|
4897
|
+
if (clean && layouts && swaMatchesLayout(fields, layouts)) {
|
|
4898
|
+
const rest = this.writeFields(decodeResult, d.type, fields);
|
|
4899
|
+
decodeResult.decoder.decodeLevel = rest === 0 ? "full" : "partial";
|
|
4900
|
+
return decodeResult;
|
|
4901
|
+
}
|
|
4902
|
+
if (clean && prefix && swaMatchesLayout(fields.slice(0, prefix.length), [prefix])) {
|
|
4903
|
+
const rest = this.writeMaintenance(decodeResult, text, fields);
|
|
4904
|
+
decodeResult.decoder.decodeLevel = rest === 0 ? "full" : "partial";
|
|
4905
|
+
return decodeResult;
|
|
4906
|
+
}
|
|
4907
|
+
if (clean && !layouts && !prefix) {
|
|
4908
|
+
const lines = text.split("|");
|
|
4909
|
+
const route = lines[0].match(/^([A-Z]{4}),([A-Z]{4})$/);
|
|
4910
|
+
if (route && d.type === "FTD02") {
|
|
4911
|
+
ResultFormatter.departureAirport(decodeResult, route[1]);
|
|
4912
|
+
ResultFormatter.arrivalAirport(decodeResult, route[2]);
|
|
4913
|
+
lines.shift();
|
|
4914
|
+
}
|
|
4915
|
+
ResultFormatter.text(decodeResult, lines.join("\n"));
|
|
4916
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
4917
|
+
return decodeResult;
|
|
4918
|
+
}
|
|
4919
|
+
ResultFormatter.text(decodeResult, text.split("|").join("\n"));
|
|
4920
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
4921
|
+
return decodeResult;
|
|
4922
|
+
}
|
|
4923
|
+
/** Writes a laid-out type's fields; returns how many went to `remaining`. */
|
|
4924
|
+
writeFields(decodeResult, type, fields) {
|
|
4925
|
+
const w = new SwaFieldWriter(decodeResult, fields);
|
|
4926
|
+
switch (type) {
|
|
4927
|
+
case "POS01":
|
|
4928
|
+
case "POS02":
|
|
4929
|
+
case "HGD03":
|
|
4930
|
+
case "FHD04": {
|
|
4931
|
+
w.departure(0);
|
|
4932
|
+
w.arrival(1);
|
|
4933
|
+
w.position(2, 3);
|
|
4934
|
+
w.altitude(4);
|
|
4935
|
+
const ias = w.int(5);
|
|
4936
|
+
if (ias !== void 0)
|
|
4937
|
+
ResultFormatter.indicatedAirspeed(decodeResult, ias);
|
|
4938
|
+
const tas = w.int(6);
|
|
4939
|
+
if (tas !== void 0) ResultFormatter.airspeed(decodeResult, tas);
|
|
4940
|
+
ResultFormatter.mach(decodeResult, Number(w.use(7)));
|
|
4941
|
+
w.fuel(8);
|
|
4942
|
+
w.eta(9);
|
|
4943
|
+
const track = w.int(10);
|
|
4944
|
+
if (track !== void 0) ResultFormatter.track(decodeResult, track);
|
|
4945
|
+
ResultFormatter.wind(decodeResult, w.int(11), w.int(12));
|
|
4946
|
+
const sat = w.int(13);
|
|
4947
|
+
if (sat !== void 0)
|
|
4948
|
+
ResultFormatter.temperature(decodeResult, `${sat}`);
|
|
4949
|
+
const gwIndex = type === "FHD04" ? 16 : 14;
|
|
4950
|
+
const gw = w.int(gwIndex);
|
|
4951
|
+
if (gw !== void 0) ResultFormatter.grossWeight(decodeResult, gw);
|
|
4952
|
+
if (type !== "FHD04" && fields.length === 16) {
|
|
4953
|
+
w.time(15, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4954
|
+
}
|
|
4955
|
+
if (type === "FHD04") {
|
|
4956
|
+
w.item(14, "event", "EVT", "Event", fields[14]);
|
|
4957
|
+
w.use(15);
|
|
4958
|
+
const freq = w.use(19);
|
|
4959
|
+
if (/^1\d{5}$/.test(freq)) {
|
|
4960
|
+
w.item(
|
|
4961
|
+
19,
|
|
4962
|
+
"frequency",
|
|
4963
|
+
"FREQ",
|
|
4964
|
+
"ACARS Frequency",
|
|
4965
|
+
`${freq.substring(0, 3)}.${freq.substring(3)} MHz`
|
|
4966
|
+
);
|
|
4967
|
+
}
|
|
4968
|
+
}
|
|
4969
|
+
break;
|
|
4970
|
+
}
|
|
4971
|
+
case "GAM02":
|
|
4972
|
+
w.departure(0);
|
|
4973
|
+
w.arrival(1);
|
|
4974
|
+
w.eta(2);
|
|
4975
|
+
w.position(3, 4);
|
|
4976
|
+
break;
|
|
4977
|
+
case "CLB02":
|
|
4978
|
+
w.departure(0);
|
|
4979
|
+
w.arrival(1);
|
|
4980
|
+
w.position(2, 4);
|
|
4981
|
+
w.fuel(5);
|
|
4982
|
+
w.eta(6);
|
|
4983
|
+
break;
|
|
4984
|
+
case "ETA03":
|
|
4985
|
+
w.departure(0);
|
|
4986
|
+
w.arrival(1);
|
|
4987
|
+
w.eta(2);
|
|
4988
|
+
w.fuel(3);
|
|
4989
|
+
w.position(4, 5);
|
|
4990
|
+
break;
|
|
4991
|
+
case "INR04":
|
|
4992
|
+
w.departure(0);
|
|
4993
|
+
w.arrival(1);
|
|
4994
|
+
w.eta(2);
|
|
4995
|
+
w.time(3, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4996
|
+
w.fuel(4);
|
|
4997
|
+
w.position(5, 6);
|
|
4998
|
+
break;
|
|
4999
|
+
case "FLI01":
|
|
5000
|
+
w.departure(0);
|
|
5001
|
+
w.arrival(1);
|
|
5002
|
+
w.time(2, (r, t) => ResultFormatter.timestamp(r, t));
|
|
5003
|
+
w.fuel(3);
|
|
5004
|
+
w.position(4, 5);
|
|
5005
|
+
break;
|
|
5006
|
+
case "OUT03":
|
|
5007
|
+
w.departure(0);
|
|
5008
|
+
w.arrival(1);
|
|
5009
|
+
w.time(2, (r, t) => ResultFormatter.out(r, t));
|
|
5010
|
+
w.fuel(3);
|
|
5011
|
+
w.timeItem(5, "front_door_closed_time", "L1CLS", "Front Door Closed");
|
|
5012
|
+
break;
|
|
5013
|
+
case "TXI02":
|
|
5014
|
+
w.departure(0);
|
|
5015
|
+
w.arrival(1);
|
|
5016
|
+
w.timeItem(2, "taxi_start_time", "TAXI", "Taxi Start Time");
|
|
5017
|
+
w.fuel(3);
|
|
5018
|
+
break;
|
|
5019
|
+
case "INN03":
|
|
5020
|
+
w.departure(0);
|
|
5021
|
+
w.arrival(1);
|
|
5022
|
+
w.time(2, (r, t) => ResultFormatter.in(r, t));
|
|
5023
|
+
w.timeItem(3, "front_door_open_time", "L1OPN", "Front Door Opened");
|
|
5024
|
+
w.fuel(4);
|
|
5025
|
+
break;
|
|
5026
|
+
case "RTG04":
|
|
5027
|
+
case "RTG05":
|
|
5028
|
+
w.departure(0);
|
|
5029
|
+
w.arrival(1);
|
|
5030
|
+
w.time(2, (r, t) => ResultFormatter.out(r, t));
|
|
5031
|
+
w.time(3, (r, t) => ResultFormatter.in(r, t));
|
|
5032
|
+
w.time(4, (r, t) => ResultFormatter.timestamp(r, t));
|
|
5033
|
+
w.fuel(5);
|
|
5034
|
+
break;
|
|
5035
|
+
case "TDM01": {
|
|
5036
|
+
w.departure(0);
|
|
5037
|
+
w.arrival(1);
|
|
5038
|
+
w.position(2, 3);
|
|
5039
|
+
ResultFormatter.door_event(
|
|
5040
|
+
decodeResult,
|
|
5041
|
+
DOORS[w.use(4)],
|
|
5042
|
+
w.use(5) === "O" ? "open" : "closed"
|
|
5043
|
+
);
|
|
5044
|
+
const md = fields[6];
|
|
5045
|
+
if (/^(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])$/.test(md)) {
|
|
5046
|
+
w.use(6);
|
|
5047
|
+
ResultFormatter.month(decodeResult, Number(md.substring(0, 2)));
|
|
5048
|
+
ResultFormatter.day(decodeResult, Number(md.substring(2)));
|
|
5049
|
+
} else if (!/^\d+$/.test(md)) {
|
|
5050
|
+
w.use(6);
|
|
5051
|
+
}
|
|
5052
|
+
w.time(7, (r, t) => ResultFormatter.timestamp(r, t));
|
|
5053
|
+
break;
|
|
5054
|
+
}
|
|
5055
|
+
case "FCM01": {
|
|
5056
|
+
const names = {
|
|
5057
|
+
L: "Left Engine",
|
|
5058
|
+
R: "Right Engine",
|
|
5059
|
+
A: "APU"
|
|
5060
|
+
};
|
|
5061
|
+
for (let i = 0; i < 3; i++) {
|
|
5062
|
+
const v = fields[i];
|
|
5063
|
+
if (v[1] === "0" || v[1] === "1") {
|
|
5064
|
+
w.item(
|
|
5065
|
+
i,
|
|
5066
|
+
`${names[v[0]].toLowerCase().replace(" ", "_")}`,
|
|
5067
|
+
v[0],
|
|
5068
|
+
names[v[0]],
|
|
5069
|
+
v[1] === "1" ? "running" : "off"
|
|
5070
|
+
);
|
|
5071
|
+
}
|
|
5072
|
+
}
|
|
5073
|
+
ResultFormatter.currentFuel(decodeResult, Number(w.use(4)) * 100);
|
|
5074
|
+
w.time(5, (r, t) => ResultFormatter.timestamp(r, t));
|
|
5075
|
+
break;
|
|
5076
|
+
}
|
|
5077
|
+
case "VXR02":
|
|
5078
|
+
w.item(0, "station_iata", "STN", "Station", fields[0]);
|
|
5079
|
+
break;
|
|
5080
|
+
}
|
|
5081
|
+
return w.finish();
|
|
5082
|
+
}
|
|
5083
|
+
/** MXR03: destination, ETA, code, then the category and text; returns how many header
|
|
5084
|
+
* fields went to `remaining`. */
|
|
5085
|
+
writeMaintenance(decodeResult, text, fields) {
|
|
5086
|
+
const w = new SwaFieldWriter(decodeResult, fields.slice(0, 3));
|
|
5087
|
+
w.arrival(0);
|
|
5088
|
+
w.eta(1);
|
|
5089
|
+
w.item(
|
|
5090
|
+
2,
|
|
5091
|
+
"maintenance_code",
|
|
5092
|
+
"MXCODE",
|
|
5093
|
+
"Report Code",
|
|
5094
|
+
`${fields[2]} (${MXR_CODES[fields[2]]})`
|
|
5095
|
+
);
|
|
5096
|
+
const header = text.match(/^[^,|]*[,|][^,|]*[,|][^,|]*[,|]?/);
|
|
5097
|
+
const body = text.substring(header ? header[0].length : 0);
|
|
5098
|
+
if (body.trim() !== "") {
|
|
5099
|
+
ResultFormatter.text(decodeResult, body.split("|").join("\n"));
|
|
5100
|
+
}
|
|
5101
|
+
return w.finish();
|
|
5102
|
+
}
|
|
5103
|
+
};
|
|
5104
|
+
|
|
5105
|
+
// lib/plugins/Label_40_SWA.ts
|
|
5106
|
+
var DESCRIPTIONS2 = {
|
|
5107
|
+
ASR01: "Approach Stability Report",
|
|
5108
|
+
DVP01: "Divert Plan",
|
|
5109
|
+
FTX01: "Dispatch Free Text",
|
|
5110
|
+
GAR03: "Gate Assignment Response",
|
|
5111
|
+
GEN01: "Company Message",
|
|
5112
|
+
PIC01: "Part 117 Duty Extension Request",
|
|
5113
|
+
POS01: "Position Report Request",
|
|
5114
|
+
WFC01: "Field Condition Report"
|
|
5115
|
+
};
|
|
5116
|
+
var ASR01 = [
|
|
5117
|
+
[
|
|
5118
|
+
"reverser_distance",
|
|
5119
|
+
"REVDIST",
|
|
5120
|
+
"Threshold to Thrust Reverser Deployment (feet)"
|
|
5121
|
+
],
|
|
5122
|
+
["max_ias", "MAXIAS", "Highest IAS, 1000 feet to Touchdown (knots)"],
|
|
5123
|
+
["min_ias", "MINIAS", "Lowest IAS, to Touchdown (knots)"],
|
|
5124
|
+
["touchdown_distance", "TDDIST", "Threshold to Touchdown (feet)"],
|
|
5125
|
+
["glideslope_above", "GSHIGH", "Largest Deviation Above Glideslope (dots)"],
|
|
5126
|
+
["glideslope_below", "GSLOW", "Largest Deviation Below Glideslope (dots)"],
|
|
5127
|
+
["max_pitch", "MAXPITCH", "Highest Pitch, Flare and Landing (degrees)"],
|
|
5128
|
+
["tailstrike_pitch", "TSPITCH", "Tail Strike Pitch Limit (degrees)"]
|
|
5129
|
+
];
|
|
5130
|
+
var Label_40_SWA = class extends DecoderPlugin {
|
|
5131
|
+
name = "label-40-swa";
|
|
5132
|
+
qualifiers() {
|
|
5133
|
+
return {
|
|
5134
|
+
labels: ["40"]
|
|
5135
|
+
};
|
|
5136
|
+
}
|
|
5137
|
+
decode(message, options = {}) {
|
|
5138
|
+
const decodeResult = this.defaultResult();
|
|
5139
|
+
decodeResult.decoder.name = this.name;
|
|
5140
|
+
decodeResult.message = message;
|
|
5141
|
+
const d = decodeSwaLabel40(message.text);
|
|
5142
|
+
if (!d || !isSwaType(d.type, "40")) {
|
|
5143
|
+
if (options.debug) {
|
|
5144
|
+
console.log(`Decoder: Unknown 40 message: ${message.text}`);
|
|
5145
|
+
}
|
|
5146
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
5147
|
+
decodeResult.formatted.description = "Unknown";
|
|
5148
|
+
return decodeResult;
|
|
5149
|
+
}
|
|
5150
|
+
decodeResult.decoded = true;
|
|
5151
|
+
decodeResult.formatted.description = DESCRIPTIONS2[d.type] ?? "Southwest Message";
|
|
5152
|
+
decodeResult.raw.preamble = d.type;
|
|
5153
|
+
if (d.type === "POS01") {
|
|
5154
|
+
const m = d.text.match(/^POS01,Y,(\d{2})$/);
|
|
5155
|
+
if (m) {
|
|
5156
|
+
ResultFormatter.raw(
|
|
5157
|
+
decodeResult,
|
|
5158
|
+
"report_interval",
|
|
5159
|
+
"RPTINT",
|
|
5160
|
+
"Position Report Interval",
|
|
5161
|
+
`${Number(m[1])} minutes`,
|
|
5162
|
+
Number(m[1])
|
|
5163
|
+
);
|
|
5164
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5165
|
+
} else {
|
|
5166
|
+
ResultFormatter.unknown(decodeResult, d.text);
|
|
5167
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5168
|
+
}
|
|
5169
|
+
return decodeResult;
|
|
5170
|
+
}
|
|
5171
|
+
const text = d.text;
|
|
5172
|
+
const fields = swaFields(text);
|
|
5173
|
+
const layouts = SWA_LAYOUTS[d.type];
|
|
5174
|
+
const clean = !text.includes(SWA_UNREAD);
|
|
5175
|
+
if (clean && layouts && swaMatchesLayout(fields, layouts)) {
|
|
5176
|
+
const w = new SwaFieldWriter(decodeResult, fields);
|
|
5177
|
+
if (d.type === "ASR01") {
|
|
5178
|
+
ASR01.forEach(([key, code, label], i) => {
|
|
5179
|
+
const v = fields[i].trim();
|
|
5180
|
+
if (v !== "XX.X") w.item(i, key, code, label, v);
|
|
5181
|
+
else w.use(i);
|
|
5182
|
+
});
|
|
5183
|
+
} else if (d.type === "GAR03") {
|
|
5184
|
+
ResultFormatter.arrivalGate(decodeResult, w.use(0).trim());
|
|
5185
|
+
if (fields[6] !== "999.999") {
|
|
5186
|
+
w.item(
|
|
5187
|
+
6,
|
|
5188
|
+
"ramp_frequency",
|
|
5189
|
+
"RAMPFREQ",
|
|
5190
|
+
"Ramp Frequency",
|
|
5191
|
+
`${fields[6]} MHz`
|
|
5192
|
+
);
|
|
5193
|
+
} else {
|
|
5194
|
+
w.use(6);
|
|
5195
|
+
}
|
|
5196
|
+
}
|
|
5197
|
+
const rest = w.finish();
|
|
5198
|
+
decodeResult.decoder.decodeLevel = rest === 0 ? "full" : "partial";
|
|
5199
|
+
return decodeResult;
|
|
5200
|
+
}
|
|
5201
|
+
ResultFormatter.text(decodeResult, text.split("|").join("\n"));
|
|
5202
|
+
decodeResult.decoder.decodeLevel = clean && !layouts ? "full" : "partial";
|
|
5203
|
+
return decodeResult;
|
|
5204
|
+
}
|
|
5205
|
+
};
|
|
5206
|
+
|
|
5207
|
+
// lib/plugins/Label_44_ETA.ts
|
|
5208
|
+
var Label_44_ETA = class extends DecoderPlugin {
|
|
5209
|
+
name = "label-44-eta";
|
|
5210
|
+
qualifiers() {
|
|
5211
|
+
return {
|
|
3739
5212
|
labels: ["44"],
|
|
3740
5213
|
preambles: ["00ETA01", "00ETA02", "00ETA03", "ETA01", "ETA02", "ETA03"]
|
|
3741
5214
|
};
|
|
@@ -4742,91 +6215,60 @@ var Label_ColonComma = class extends DecoderPlugin {
|
|
|
4742
6215
|
}
|
|
4743
6216
|
};
|
|
4744
6217
|
|
|
4745
|
-
// lib/plugins/
|
|
4746
|
-
var
|
|
4747
|
-
name = "label-
|
|
6218
|
+
// lib/plugins/Label_H1_76401.ts
|
|
6219
|
+
var Label_H1_76401 = class extends DecoderPlugin {
|
|
6220
|
+
name = "label-h1-76401";
|
|
4748
6221
|
qualifiers() {
|
|
4749
6222
|
return {
|
|
4750
|
-
labels: ["
|
|
4751
|
-
preambles: ["
|
|
6223
|
+
labels: ["H1"],
|
|
6224
|
+
preambles: ["76401\r\n"]
|
|
4752
6225
|
};
|
|
4753
6226
|
}
|
|
4754
6227
|
decode(message, options = {}) {
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
decodeResult.message = message;
|
|
4759
|
-
const parts = message.text.split(" ");
|
|
4760
|
-
if (parts[parts.length - 1] !== "Q") {
|
|
4761
|
-
decodeResult.remaining.text = message.text;
|
|
4762
|
-
decodeResult.decoded = false;
|
|
4763
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
6228
|
+
const decodeResult = this.initResult(message, "Position Report");
|
|
6229
|
+
const lines = message.text.split("\r\n");
|
|
6230
|
+
if (lines.length < 3) {
|
|
4764
6231
|
return decodeResult;
|
|
4765
6232
|
}
|
|
4766
|
-
|
|
4767
|
-
decodeResult.
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
const
|
|
4774
|
-
|
|
4775
|
-
|
|
6233
|
+
ResultFormatter.unknown(decodeResult, lines[0], "\r\n");
|
|
6234
|
+
ResultFormatter.unknown(decodeResult, lines[1].substring(0, 5), "\r\n");
|
|
6235
|
+
ResultFormatter.departureAirport(decodeResult, lines[1].substring(5, 9));
|
|
6236
|
+
ResultFormatter.arrivalAirport(decodeResult, lines[1].substring(9, 13));
|
|
6237
|
+
ResultFormatter.unknown(decodeResult, lines[1].substring(13), "");
|
|
6238
|
+
const waypoints = [];
|
|
6239
|
+
for (const line of lines.slice(2)) {
|
|
6240
|
+
const position = CoordinateUtils.decodeStringCoordinates(
|
|
6241
|
+
line.substring(0, 13)
|
|
6242
|
+
);
|
|
6243
|
+
if (position) {
|
|
6244
|
+
waypoints.push({
|
|
6245
|
+
name: line.substring(0, 13),
|
|
6246
|
+
latitude: position.latitude,
|
|
6247
|
+
longitude: position.longitude,
|
|
6248
|
+
time: DateTimeUtils.convertHHMMSSToTod(line.substring(13, 19))
|
|
6249
|
+
});
|
|
4776
6250
|
} else {
|
|
4777
|
-
|
|
6251
|
+
ResultFormatter.unknown(decodeResult, line.substring(0, 19), "");
|
|
4778
6252
|
}
|
|
6253
|
+
ResultFormatter.unknown(decodeResult, line.substring(19), "\r\n");
|
|
4779
6254
|
}
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
6255
|
+
ResultFormatter.route(decodeResult, { waypoints });
|
|
6256
|
+
if (waypoints.length > 0) {
|
|
6257
|
+
const lastWaypoint = waypoints[waypoints.length - 1];
|
|
6258
|
+
if (lastWaypoint.latitude !== void 0 && lastWaypoint.longitude !== void 0) {
|
|
6259
|
+
ResultFormatter.position(decodeResult, {
|
|
6260
|
+
latitude: lastWaypoint.latitude,
|
|
6261
|
+
longitude: lastWaypoint.longitude
|
|
6262
|
+
});
|
|
4785
6263
|
}
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
windData.push(wind);
|
|
4789
|
-
} else {
|
|
4790
|
-
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + part;
|
|
6264
|
+
if (lastWaypoint.time !== void 0) {
|
|
6265
|
+
ResultFormatter.timestamp(decodeResult, lastWaypoint.time);
|
|
4791
6266
|
}
|
|
4792
6267
|
}
|
|
4793
|
-
ResultFormatter.windData(decodeResult, windData);
|
|
4794
6268
|
decodeResult.decoded = true;
|
|
4795
|
-
decodeResult.decoder.decodeLevel =
|
|
6269
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
4796
6270
|
return decodeResult;
|
|
4797
6271
|
}
|
|
4798
|
-
parseWeatherReport(text) {
|
|
4799
|
-
const posString = text.substring(0, 13);
|
|
4800
|
-
const pos = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(posString);
|
|
4801
|
-
if (text.length !== 32 || !pos) {
|
|
4802
|
-
return null;
|
|
4803
|
-
}
|
|
4804
|
-
const tod = DateTimeUtils.convertHHMMSSToTod(text.substring(13, 17));
|
|
4805
|
-
const flightLevel = parseInt(text.substring(17, 20), 10);
|
|
4806
|
-
const tempSign = text[21] === "M" ? -1 : 1;
|
|
4807
|
-
const tempDegreesRaw = parseInt(text.substring(22, 25), 10);
|
|
4808
|
-
const tempDegrees = tempSign * (tempDegreesRaw / 10);
|
|
4809
|
-
const windDirection = parseInt(text.substring(25, 28), 10);
|
|
4810
|
-
const windSpeed = parseInt(text.substring(28, 31), 10);
|
|
4811
|
-
if (text[31] !== "G") {
|
|
4812
|
-
return null;
|
|
4813
|
-
}
|
|
4814
|
-
return {
|
|
4815
|
-
waypoint: {
|
|
4816
|
-
name: posString,
|
|
4817
|
-
latitude: pos.latitude,
|
|
4818
|
-
longitude: pos.longitude,
|
|
4819
|
-
time: tod
|
|
4820
|
-
},
|
|
4821
|
-
flightLevel,
|
|
4822
|
-
windDirection,
|
|
4823
|
-
windSpeed,
|
|
4824
|
-
temperature: {
|
|
4825
|
-
flightLevel,
|
|
4826
|
-
degreesC: tempDegrees
|
|
4827
|
-
}
|
|
4828
|
-
};
|
|
4829
|
-
}
|
|
4830
6272
|
};
|
|
4831
6273
|
|
|
4832
6274
|
// lib/plugins/Label_H1_ATIS.ts
|
|
@@ -5047,11 +6489,11 @@ var Label_H1_M_POS = class extends DecoderPlugin {
|
|
|
5047
6489
|
const timestamp = fields[2].trim();
|
|
5048
6490
|
if (timestamp.length === 6) {
|
|
5049
6491
|
const day = Number(timestamp.substring(0, 2));
|
|
5050
|
-
const
|
|
6492
|
+
const tod2 = DateTimeUtils.convertHHMMSSToTod(
|
|
5051
6493
|
timestamp.substring(2) + "00"
|
|
5052
6494
|
);
|
|
5053
6495
|
ResultFormatter.day(decodeResult, day);
|
|
5054
|
-
ResultFormatter.timestamp(decodeResult,
|
|
6496
|
+
ResultFormatter.timestamp(decodeResult, tod2);
|
|
5055
6497
|
}
|
|
5056
6498
|
const lat = parseFloat(fields[3].replace(/\s/g, ""));
|
|
5057
6499
|
const lon = parseFloat(fields[4].replace(/\s/g, ""));
|
|
@@ -5445,6 +6887,135 @@ var Label_H1_StarPOS = class extends DecoderPlugin {
|
|
|
5445
6887
|
}
|
|
5446
6888
|
};
|
|
5447
6889
|
|
|
6890
|
+
// lib/plugins/Label_H1_SWA_Track.ts
|
|
6891
|
+
var PHASES = {
|
|
6892
|
+
TO: "Takeoff",
|
|
6893
|
+
IC: "Initial Climb",
|
|
6894
|
+
CL: "Climb",
|
|
6895
|
+
CR: "Cruise",
|
|
6896
|
+
ER: "En Route",
|
|
6897
|
+
DC: "Descent",
|
|
6898
|
+
AP: "Approach",
|
|
6899
|
+
RO: "Rollout"
|
|
6900
|
+
};
|
|
6901
|
+
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]),$/;
|
|
6902
|
+
var Label_H1_SWA_Track = class extends DecoderPlugin {
|
|
6903
|
+
name = "label-h1-swa-track";
|
|
6904
|
+
qualifiers() {
|
|
6905
|
+
return {
|
|
6906
|
+
labels: ["H1"],
|
|
6907
|
+
preambles: ["++76502,", "++86501,", "#DFB++76502,", "#DFB++86501,"]
|
|
6908
|
+
};
|
|
6909
|
+
}
|
|
6910
|
+
decode(message, options = {}) {
|
|
6911
|
+
const decodeResult = this.initResult(message, "Track Report");
|
|
6912
|
+
const nl = message.text.includes("\r\n") ? "\r\n" : "\n";
|
|
6913
|
+
const lines = message.text.replace(/#DFB/g, "").split(/\r?\n/);
|
|
6914
|
+
const header = lines[0].replace(/^\+\+/, "").split(",");
|
|
6915
|
+
if (header.length !== 9 || !/^\d{6}$/.test(header[3])) {
|
|
6916
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
6917
|
+
}
|
|
6918
|
+
const unknown = [];
|
|
6919
|
+
if (/^N\w+$/.test(header[1])) {
|
|
6920
|
+
ResultFormatter.tail(decodeResult, header[1]);
|
|
6921
|
+
} else if (/^\d{1,4}$/.test(header[1])) {
|
|
6922
|
+
ResultFormatter.raw(
|
|
6923
|
+
decodeResult,
|
|
6924
|
+
"ship_number",
|
|
6925
|
+
"SHIP",
|
|
6926
|
+
"Ship Number",
|
|
6927
|
+
header[1]
|
|
6928
|
+
);
|
|
6929
|
+
} else if (header[1] !== "XXX") {
|
|
6930
|
+
unknown.push(header[1]);
|
|
6931
|
+
}
|
|
6932
|
+
ResultFormatter.raw(
|
|
6933
|
+
decodeResult,
|
|
6934
|
+
"aircraft_type",
|
|
6935
|
+
"ACTYPE",
|
|
6936
|
+
"Aircraft Type",
|
|
6937
|
+
header[2]
|
|
6938
|
+
);
|
|
6939
|
+
const d = header[3];
|
|
6940
|
+
ResultFormatter.raw(
|
|
6941
|
+
decodeResult,
|
|
6942
|
+
"report_date",
|
|
6943
|
+
"DATE",
|
|
6944
|
+
"Report Date",
|
|
6945
|
+
`20${d.slice(0, 2)}-${d.slice(2, 4)}-${d.slice(4, 6)}`
|
|
6946
|
+
);
|
|
6947
|
+
ResultFormatter.flightNumber(decodeResult, header[4]);
|
|
6948
|
+
ResultFormatter.departureAirport(decodeResult, header[5]);
|
|
6949
|
+
ResultFormatter.arrivalAirport(decodeResult, header[6]);
|
|
6950
|
+
if (/^\d{1,15}$/.test(header[7])) {
|
|
6951
|
+
ResultFormatter.raw(
|
|
6952
|
+
decodeResult,
|
|
6953
|
+
"leg_counter",
|
|
6954
|
+
"LEGS",
|
|
6955
|
+
"Leg Counter",
|
|
6956
|
+
`${Number(header[7])}`,
|
|
6957
|
+
Number(header[7])
|
|
6958
|
+
);
|
|
6959
|
+
} else {
|
|
6960
|
+
unknown.push(header[7]);
|
|
6961
|
+
}
|
|
6962
|
+
ResultFormatter.raw(
|
|
6963
|
+
decodeResult,
|
|
6964
|
+
"software_version",
|
|
6965
|
+
"SWVER",
|
|
6966
|
+
"Software Version",
|
|
6967
|
+
header[8]
|
|
6968
|
+
);
|
|
6969
|
+
if (unknown.length > 0) ResultFormatter.unknownArr(decodeResult, unknown);
|
|
6970
|
+
const count = lines[1]?.match(/^(\d+),?$/)?.[1];
|
|
6971
|
+
if (lines[1] !== void 0 && count === void 0) {
|
|
6972
|
+
ResultFormatter.unknown(decodeResult, lines[1], nl);
|
|
6973
|
+
}
|
|
6974
|
+
for (const line of lines.slice(2)) {
|
|
6975
|
+
if (line === "" || line === ":") continue;
|
|
6976
|
+
const m = line.match(POINT);
|
|
6977
|
+
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) {
|
|
6978
|
+
ResultFormatter.unknown(decodeResult, line, nl);
|
|
6979
|
+
continue;
|
|
6980
|
+
}
|
|
6981
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
|
|
6982
|
+
`${m[1]}${m[2]}${m[3]}${m[4]}`
|
|
6983
|
+
);
|
|
6984
|
+
if (!position || Math.abs(position.latitude) > 90 || Math.abs(position.longitude) > 180) {
|
|
6985
|
+
ResultFormatter.unknown(decodeResult, line, nl);
|
|
6986
|
+
continue;
|
|
6987
|
+
}
|
|
6988
|
+
ResultFormatter.trackPoint(decodeResult, {
|
|
6989
|
+
name: `${m[1]}.${m[2]}${m[3]}.${m[4]}`,
|
|
6990
|
+
...position,
|
|
6991
|
+
day: Number(m[5]),
|
|
6992
|
+
time: Number(m[6]) * 3600 + Number(m[7]) * 60,
|
|
6993
|
+
altitude: Number(m[8]),
|
|
6994
|
+
// -00.0 is sent; keep it as 0
|
|
6995
|
+
temperature: Number(m[9]) || 0,
|
|
6996
|
+
windDirection: Number(m[10]),
|
|
6997
|
+
windSpeed: Number(m[11]),
|
|
6998
|
+
phase: PHASES[m[12]] ?? m[12],
|
|
6999
|
+
humiditySensor: m[14] === "1",
|
|
7000
|
+
...m[14] === "1" && Number(m[13]) > 0 ? { waterVapor: Number(m[13]) } : {}
|
|
7001
|
+
});
|
|
7002
|
+
}
|
|
7003
|
+
const points = decodeResult.raw.route?.waypoints ?? [];
|
|
7004
|
+
const last = points[points.length - 1];
|
|
7005
|
+
if (last) {
|
|
7006
|
+
ResultFormatter.position(decodeResult, {
|
|
7007
|
+
latitude: last.latitude,
|
|
7008
|
+
longitude: last.longitude
|
|
7009
|
+
});
|
|
7010
|
+
ResultFormatter.altitude(decodeResult, last.altitude);
|
|
7011
|
+
ResultFormatter.timestamp(decodeResult, last.time);
|
|
7012
|
+
}
|
|
7013
|
+
const counted = count !== void 0 && Number(count) === points.length;
|
|
7014
|
+
this.setDecodeLevel(decodeResult, true, counted ? void 0 : "partial");
|
|
7015
|
+
return decodeResult;
|
|
7016
|
+
}
|
|
7017
|
+
};
|
|
7018
|
+
|
|
5448
7019
|
// lib/plugins/Label_H1_WRN.ts
|
|
5449
7020
|
var Label_H1_WRN = class extends DecoderPlugin {
|
|
5450
7021
|
name = "label-h1-wrn";
|
|
@@ -5484,6 +7055,93 @@ var Label_H1_WRN = class extends DecoderPlugin {
|
|
|
5484
7055
|
}
|
|
5485
7056
|
};
|
|
5486
7057
|
|
|
7058
|
+
// lib/plugins/Label_H2_02E.ts
|
|
7059
|
+
var Label_H2_02E = class extends DecoderPlugin {
|
|
7060
|
+
name = "label-h2-02e";
|
|
7061
|
+
qualifiers() {
|
|
7062
|
+
return {
|
|
7063
|
+
labels: ["H2"],
|
|
7064
|
+
preambles: ["02E"]
|
|
7065
|
+
};
|
|
7066
|
+
}
|
|
7067
|
+
decode(message, options = {}) {
|
|
7068
|
+
let decodeResult = this.defaultResult();
|
|
7069
|
+
decodeResult.decoder.name = this.name;
|
|
7070
|
+
decodeResult.formatted.description = "Weather Report";
|
|
7071
|
+
decodeResult.message = message;
|
|
7072
|
+
const parts = message.text.split(" ");
|
|
7073
|
+
if (parts[parts.length - 1] !== "Q") {
|
|
7074
|
+
decodeResult.remaining.text = message.text;
|
|
7075
|
+
decodeResult.decoded = false;
|
|
7076
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
7077
|
+
return decodeResult;
|
|
7078
|
+
}
|
|
7079
|
+
const windData = [];
|
|
7080
|
+
decodeResult.remaining.text = "";
|
|
7081
|
+
const header = parts[0];
|
|
7082
|
+
if (header.length === 45) {
|
|
7083
|
+
ResultFormatter.day(decodeResult, parseInt(header.substring(3, 5), 10));
|
|
7084
|
+
ResultFormatter.departureAirport(decodeResult, header.substring(5, 9));
|
|
7085
|
+
ResultFormatter.arrivalAirport(decodeResult, header.substring(9, 13));
|
|
7086
|
+
const firstWind = this.parseWeatherReport(header.substring(13));
|
|
7087
|
+
if (firstWind) {
|
|
7088
|
+
windData.push(firstWind);
|
|
7089
|
+
} else {
|
|
7090
|
+
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + header.substring(13);
|
|
7091
|
+
}
|
|
7092
|
+
}
|
|
7093
|
+
for (let i = 1; i < parts.length - 1; i++) {
|
|
7094
|
+
const part = parts[i];
|
|
7095
|
+
if (part[0] !== "Q") {
|
|
7096
|
+
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + part;
|
|
7097
|
+
continue;
|
|
7098
|
+
}
|
|
7099
|
+
const wind = this.parseWeatherReport(part.substring(1));
|
|
7100
|
+
if (wind) {
|
|
7101
|
+
windData.push(wind);
|
|
7102
|
+
} else {
|
|
7103
|
+
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + part;
|
|
7104
|
+
}
|
|
7105
|
+
}
|
|
7106
|
+
ResultFormatter.windData(decodeResult, windData);
|
|
7107
|
+
decodeResult.decoded = true;
|
|
7108
|
+
decodeResult.decoder.decodeLevel = decodeResult.remaining.text.length === 0 ? "full" : "partial";
|
|
7109
|
+
return decodeResult;
|
|
7110
|
+
}
|
|
7111
|
+
parseWeatherReport(text) {
|
|
7112
|
+
const posString = text.substring(0, 13);
|
|
7113
|
+
const pos = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(posString);
|
|
7114
|
+
if (text.length !== 32 || !pos) {
|
|
7115
|
+
return null;
|
|
7116
|
+
}
|
|
7117
|
+
const tod2 = DateTimeUtils.convertHHMMSSToTod(text.substring(13, 17));
|
|
7118
|
+
const flightLevel = parseInt(text.substring(17, 20), 10);
|
|
7119
|
+
const tempSign = text[21] === "M" ? -1 : 1;
|
|
7120
|
+
const tempDegreesRaw = parseInt(text.substring(22, 25), 10);
|
|
7121
|
+
const tempDegrees = tempSign * (tempDegreesRaw / 10);
|
|
7122
|
+
const windDirection = parseInt(text.substring(25, 28), 10);
|
|
7123
|
+
const windSpeed = parseInt(text.substring(28, 31), 10);
|
|
7124
|
+
if (text[31] !== "G") {
|
|
7125
|
+
return null;
|
|
7126
|
+
}
|
|
7127
|
+
return {
|
|
7128
|
+
waypoint: {
|
|
7129
|
+
name: posString,
|
|
7130
|
+
latitude: pos.latitude,
|
|
7131
|
+
longitude: pos.longitude,
|
|
7132
|
+
time: tod2
|
|
7133
|
+
},
|
|
7134
|
+
flightLevel,
|
|
7135
|
+
windDirection,
|
|
7136
|
+
windSpeed,
|
|
7137
|
+
temperature: {
|
|
7138
|
+
flightLevel,
|
|
7139
|
+
degreesC: tempDegrees
|
|
7140
|
+
}
|
|
7141
|
+
};
|
|
7142
|
+
}
|
|
7143
|
+
};
|
|
7144
|
+
|
|
5487
7145
|
// lib/plugins/Label_HX.ts
|
|
5488
7146
|
var Label_HX = class extends DecoderPlugin {
|
|
5489
7147
|
name = "label-hx";
|
|
@@ -5556,8 +7214,8 @@ function ascii85Decode(input) {
|
|
|
5556
7214
|
if (digit < 0 || digit > 84) return null;
|
|
5557
7215
|
value = value * 85 + digit;
|
|
5558
7216
|
}
|
|
5559
|
-
if (
|
|
5560
|
-
const v = value
|
|
7217
|
+
if (value > 4294967295) return null;
|
|
7218
|
+
const v = value;
|
|
5561
7219
|
const numBytes = chunkLen === 5 ? 4 : chunkLen - 1;
|
|
5562
7220
|
if (numBytes >= 1) output.push(v >>> 24 & 255);
|
|
5563
7221
|
if (numBytes >= 2) output.push(v >>> 16 & 255);
|
|
@@ -6779,8 +8437,11 @@ var pluginClasses = [
|
|
|
6779
8437
|
Label_ColonComma,
|
|
6780
8438
|
Label_5Z_Slash,
|
|
6781
8439
|
Label_10_LDR,
|
|
8440
|
+
Label_10_LRW,
|
|
6782
8441
|
Label_10_POS,
|
|
6783
8442
|
Label_10_Slash,
|
|
8443
|
+
Label_11_LDR,
|
|
8444
|
+
Label_11_LRW,
|
|
6784
8445
|
Label_12_N_Space,
|
|
6785
8446
|
Label_12_POS,
|
|
6786
8447
|
Label_13Through18_Slash,
|
|
@@ -6804,6 +8465,8 @@ var pluginClasses = [
|
|
|
6804
8465
|
Label_2P_FM4,
|
|
6805
8466
|
Label_2P_FM5,
|
|
6806
8467
|
Label_30_Slash_EA,
|
|
8468
|
+
Label_37_SWA,
|
|
8469
|
+
Label_40_SWA,
|
|
6807
8470
|
Label_44_ETA,
|
|
6808
8471
|
Label_44_IN,
|
|
6809
8472
|
Label_44_OFF,
|
|
@@ -6819,7 +8482,7 @@ var pluginClasses = [
|
|
|
6819
8482
|
Label_4T_AGFSR,
|
|
6820
8483
|
Label_4T_ETA,
|
|
6821
8484
|
Label_B6_Forwardslash,
|
|
6822
|
-
|
|
8485
|
+
Label_H1_76401,
|
|
6823
8486
|
Label_H1_ATIS,
|
|
6824
8487
|
Label_H1_EZF,
|
|
6825
8488
|
Label_H1_FLR,
|
|
@@ -6829,6 +8492,8 @@ var pluginClasses = [
|
|
|
6829
8492
|
Label_H1_Paren,
|
|
6830
8493
|
Label_H1_WRN,
|
|
6831
8494
|
Label_H1_StarPOS,
|
|
8495
|
+
Label_H1_SWA_Track,
|
|
8496
|
+
Label_H2_02E,
|
|
6832
8497
|
Label_HX,
|
|
6833
8498
|
Label_58,
|
|
6834
8499
|
Label_80,
|
|
@@ -6874,6 +8539,9 @@ var MessageDecoder = class {
|
|
|
6874
8539
|
this.wildcardSet.add(plugin);
|
|
6875
8540
|
const wildcardInsertIndex = this.wildcardEntries.length - 1;
|
|
6876
8541
|
for (const bucket of this.candidatesByLabel.values()) {
|
|
8542
|
+
if (bucket.some((e) => e.plugin === plugin)) {
|
|
8543
|
+
continue;
|
|
8544
|
+
}
|
|
6877
8545
|
bucket.splice(wildcardInsertIndex, 0, entry);
|
|
6878
8546
|
}
|
|
6879
8547
|
}
|