@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.js
CHANGED
|
@@ -175,8 +175,8 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
175
175
|
};
|
|
176
176
|
}
|
|
177
177
|
static coordinateString(coords) {
|
|
178
|
-
const latDir = coords.latitude
|
|
179
|
-
const lonDir = coords.longitude
|
|
178
|
+
const latDir = coords.latitude >= 0 ? "N" : "S";
|
|
179
|
+
const lonDir = coords.longitude >= 0 ? "E" : "W";
|
|
180
180
|
return `${Math.abs(coords.latitude).toFixed(3)} ${latDir}, ${Math.abs(coords.longitude).toFixed(3)} ${lonDir}`;
|
|
181
181
|
}
|
|
182
182
|
static getDirection(coord) {
|
|
@@ -226,16 +226,16 @@ var DateTimeUtils = class {
|
|
|
226
226
|
const h = Number(time.substring(0, 2));
|
|
227
227
|
const m = Number(time.substring(2, 4));
|
|
228
228
|
const s = Number(time.substring(4, 6));
|
|
229
|
-
const
|
|
230
|
-
return
|
|
229
|
+
const tod2 = h * 3600 + m * 60 + s;
|
|
230
|
+
return tod2;
|
|
231
231
|
}
|
|
232
232
|
static convertDayTimeToTod(time) {
|
|
233
233
|
const d = Number(time.substring(0, 2));
|
|
234
234
|
const h = Number(time.substring(2, 4));
|
|
235
235
|
const m = Number(time.substring(4, 6));
|
|
236
236
|
const s = Number(time.substring(6, 8));
|
|
237
|
-
const
|
|
238
|
-
return
|
|
237
|
+
const tod2 = d * 86400 + h * 3600 + m * 60 + s;
|
|
238
|
+
return tod2;
|
|
239
239
|
}
|
|
240
240
|
/**
|
|
241
241
|
*
|
|
@@ -511,6 +511,16 @@ var ResultFormatter = class {
|
|
|
511
511
|
value: decodeResult.raw.alternate_icao
|
|
512
512
|
});
|
|
513
513
|
}
|
|
514
|
+
/** The airport landing data is for: the destination, or the airport of a divert. */
|
|
515
|
+
static landingAirport(decodeResult, value) {
|
|
516
|
+
decodeResult.raw.landing_icao = value;
|
|
517
|
+
decodeResult.formatted.items.push({
|
|
518
|
+
type: "icao",
|
|
519
|
+
code: "LAND",
|
|
520
|
+
label: "Landing Airport",
|
|
521
|
+
value: decodeResult.raw.landing_icao
|
|
522
|
+
});
|
|
523
|
+
}
|
|
514
524
|
static eta(decodeResult, time) {
|
|
515
525
|
if (isNaN(time)) {
|
|
516
526
|
return;
|
|
@@ -701,6 +711,144 @@ var ResultFormatter = class {
|
|
|
701
711
|
value: `${decodeResult.raw.heading}`
|
|
702
712
|
});
|
|
703
713
|
}
|
|
714
|
+
static indicatedAirspeed(decodeResult, value) {
|
|
715
|
+
if (isNaN(value)) {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
decodeResult.raw.indicated_airspeed = value;
|
|
719
|
+
decodeResult.formatted.items.push({
|
|
720
|
+
type: "indicated_airspeed",
|
|
721
|
+
code: "IAS",
|
|
722
|
+
label: "Indicated Airspeed",
|
|
723
|
+
value: `${decodeResult.raw.indicated_airspeed} knots`
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
static track(decodeResult, value) {
|
|
727
|
+
if (isNaN(value)) {
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
decodeResult.raw.track = value;
|
|
731
|
+
decodeResult.formatted.items.push({
|
|
732
|
+
type: "track",
|
|
733
|
+
code: "TRK",
|
|
734
|
+
label: "Track",
|
|
735
|
+
value: `${decodeResult.raw.track} degrees`
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
/** Wind at the aircraft; either half may be missing. */
|
|
739
|
+
static wind(decodeResult, direction, speed) {
|
|
740
|
+
const hasDirection = direction !== void 0 && !isNaN(direction);
|
|
741
|
+
const hasSpeed = speed !== void 0 && !isNaN(speed);
|
|
742
|
+
if (hasDirection) decodeResult.raw.wind_direction = direction;
|
|
743
|
+
if (hasSpeed) decodeResult.raw.wind_speed = speed;
|
|
744
|
+
if (!hasDirection && !hasSpeed) {
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
decodeResult.formatted.items.push({
|
|
748
|
+
type: "wind",
|
|
749
|
+
code: "WIND",
|
|
750
|
+
label: !hasSpeed ? "Wind Direction" : !hasDirection ? "Wind Speed" : "Wind",
|
|
751
|
+
value: [
|
|
752
|
+
hasDirection ? `${direction} degrees` : "",
|
|
753
|
+
hasSpeed ? `${speed} knots` : ""
|
|
754
|
+
].filter((s) => s !== "").join(" at ")
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
static variableWind(decodeResult, speed) {
|
|
758
|
+
if (isNaN(speed)) {
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
decodeResult.raw.wind_speed = speed;
|
|
762
|
+
decodeResult.raw.wind_variable = true;
|
|
763
|
+
decodeResult.formatted.items.push({
|
|
764
|
+
type: "wind",
|
|
765
|
+
code: "WIND",
|
|
766
|
+
label: "Wind",
|
|
767
|
+
value: `variable at ${speed} knots`
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* One point of a recorded track. The track is the route as flown, so each point is added to
|
|
772
|
+
* the route's waypoints; the item shows what the aircraft measured there as well.
|
|
773
|
+
*/
|
|
774
|
+
static trackPoint(decodeResult, point) {
|
|
775
|
+
decodeResult.raw.route = {
|
|
776
|
+
...decodeResult.raw.route,
|
|
777
|
+
waypoints: [...decodeResult.raw.route?.waypoints ?? [], point]
|
|
778
|
+
};
|
|
779
|
+
decodeResult.formatted.items.push({
|
|
780
|
+
type: "track_point",
|
|
781
|
+
code: "TRKPT",
|
|
782
|
+
label: "Track Point",
|
|
783
|
+
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`)
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
static runwayLandingData(decodeResult, data) {
|
|
787
|
+
decodeResult.raw.landing_runways = [
|
|
788
|
+
...decodeResult.raw.landing_runways ?? [],
|
|
789
|
+
data
|
|
790
|
+
];
|
|
791
|
+
const parts = [];
|
|
792
|
+
if (data.length !== void 0) parts.push(`${data.length} feet`);
|
|
793
|
+
if (data.flaps !== void 0) parts.push(`flaps ${data.flaps}`);
|
|
794
|
+
if (data.headwind !== void 0) {
|
|
795
|
+
parts.push(
|
|
796
|
+
data.headwind < 0 ? `tailwind ${-data.headwind} knots` : `headwind ${data.headwind} knots`
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
if (data.crosswind !== void 0) {
|
|
800
|
+
const side = { L: " left", R: " right" }[data.crosswindSide ?? "L"];
|
|
801
|
+
parts.push(
|
|
802
|
+
`crosswind ${data.crosswind} knots${data.crosswindSide ? side : ""}`
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
if (data.vref !== void 0) parts.push(`VREF ${data.vref} knots`);
|
|
806
|
+
if (data.vtarget !== void 0) {
|
|
807
|
+
const add = data.additive === void 0 ? "" : ` (${data.additive < 0 ? "" : "+"}${data.additive})`;
|
|
808
|
+
parts.push(`VTGT ${data.vtarget} knots${add}`);
|
|
809
|
+
}
|
|
810
|
+
if (data.maxLandingWeight !== void 0) {
|
|
811
|
+
parts.push(`MRLW ${data.maxLandingWeight}`);
|
|
812
|
+
}
|
|
813
|
+
if (data.landingWeight !== void 0) {
|
|
814
|
+
parts.push(`LDW ${data.landingWeight} pounds`);
|
|
815
|
+
}
|
|
816
|
+
const margins = Object.entries(data.stoppingMargins).map(
|
|
817
|
+
([setting, feet]) => `${setting} ${feet} feet`
|
|
818
|
+
);
|
|
819
|
+
if (margins.length > 0) {
|
|
820
|
+
parts.push(`stopping margin ${margins.join(", ")}`);
|
|
821
|
+
}
|
|
822
|
+
parts.push(...data.notes ?? []);
|
|
823
|
+
const variant2 = data.variant === void 0 ? "" : ` (${data.variant})`;
|
|
824
|
+
decodeResult.formatted.items.push({
|
|
825
|
+
type: "runway_landing_data",
|
|
826
|
+
code: "RWYLDG",
|
|
827
|
+
label: "Runway Landing Data",
|
|
828
|
+
value: `${data.runway}${variant2}: ${parts.join(", ")}`
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
static grossWeight(decodeResult, pounds3) {
|
|
832
|
+
if (isNaN(pounds3)) {
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
decodeResult.raw.gross_weight = pounds3;
|
|
836
|
+
decodeResult.formatted.items.push({
|
|
837
|
+
type: "gross_weight",
|
|
838
|
+
code: "GWT",
|
|
839
|
+
label: "Gross Weight",
|
|
840
|
+
value: `${decodeResult.raw.gross_weight} pounds`
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
static arrivalGate(decodeResult, value) {
|
|
844
|
+
decodeResult.raw.arrival_gate = value;
|
|
845
|
+
decodeResult.formatted.items.push({
|
|
846
|
+
type: "gate",
|
|
847
|
+
code: "AGATE",
|
|
848
|
+
label: "Arrival Gate",
|
|
849
|
+
value: decodeResult.raw.arrival_gate
|
|
850
|
+
});
|
|
851
|
+
}
|
|
704
852
|
static tail(decodeResult, value) {
|
|
705
853
|
decodeResult.raw.tail = value;
|
|
706
854
|
decodeResult.formatted.items.push({
|
|
@@ -904,6 +1052,9 @@ var ResultFormatter = class {
|
|
|
904
1052
|
}
|
|
905
1053
|
}
|
|
906
1054
|
static version(decodeResult, value) {
|
|
1055
|
+
if (isNaN(value)) {
|
|
1056
|
+
return;
|
|
1057
|
+
}
|
|
907
1058
|
decodeResult.raw.version = value;
|
|
908
1059
|
decodeResult.formatted.items.push({
|
|
909
1060
|
type: "version",
|
|
@@ -940,6 +1091,9 @@ var ResultFormatter = class {
|
|
|
940
1091
|
});
|
|
941
1092
|
}
|
|
942
1093
|
static desiredAltitude(decodeResult, value) {
|
|
1094
|
+
if (isNaN(value)) {
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
943
1097
|
decodeResult.raw.desired_alt = value;
|
|
944
1098
|
decodeResult.formatted.items.push({
|
|
945
1099
|
type: "desired_altitude",
|
|
@@ -1014,6 +1168,14 @@ var ResultFormatter = class {
|
|
|
1014
1168
|
value: decodeResult.raw.sequence_response.toString()
|
|
1015
1169
|
});
|
|
1016
1170
|
}
|
|
1171
|
+
/**
|
|
1172
|
+
* A field with no specific helper: `key` is its name in `raw` and its item type. `rawValue`
|
|
1173
|
+
* is stored in `raw` when it differs from the text shown (a number, for example).
|
|
1174
|
+
*/
|
|
1175
|
+
static raw(decodeResult, key, code, label, value, rawValue = value) {
|
|
1176
|
+
decodeResult.raw[key] = rawValue;
|
|
1177
|
+
decodeResult.formatted.items.push({ type: key, code, label, value });
|
|
1178
|
+
}
|
|
1017
1179
|
static unknown(decodeResult, value, sep = ",") {
|
|
1018
1180
|
if (!decodeResult.remaining.text) decodeResult.remaining.text = value;
|
|
1019
1181
|
else decodeResult.remaining.text += sep + value;
|
|
@@ -1359,13 +1521,13 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1359
1521
|
const segments = value.split(".");
|
|
1360
1522
|
const parens_idx = segments[0].indexOf("(");
|
|
1361
1523
|
let name;
|
|
1362
|
-
let
|
|
1524
|
+
let runway2;
|
|
1363
1525
|
if (parens_idx === -1) {
|
|
1364
1526
|
name = segments[0];
|
|
1365
1527
|
} else {
|
|
1366
1528
|
name = segments[0].slice(0, parens_idx);
|
|
1367
1529
|
const close_paren_idx = segments[0].indexOf(")");
|
|
1368
|
-
|
|
1530
|
+
runway2 = segments[0].slice(
|
|
1369
1531
|
parens_idx + 1,
|
|
1370
1532
|
close_paren_idx === -1 ? void 0 : close_paren_idx
|
|
1371
1533
|
);
|
|
@@ -1376,7 +1538,7 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
1376
1538
|
}
|
|
1377
1539
|
decodeResult.raw.company_route = {
|
|
1378
1540
|
name,
|
|
1379
|
-
runway,
|
|
1541
|
+
runway: runway2,
|
|
1380
1542
|
waypoints
|
|
1381
1543
|
};
|
|
1382
1544
|
decodeResult.formatted.items.push({
|
|
@@ -1514,6 +1676,9 @@ var Arinc702Helper = class _Arinc702Helper {
|
|
|
1514
1676
|
case "TD":
|
|
1515
1677
|
processTimeOfDeparture(decodeResult, data2.split(","));
|
|
1516
1678
|
break;
|
|
1679
|
+
case "TR":
|
|
1680
|
+
processTR(decodeResult, data2.split(","));
|
|
1681
|
+
break;
|
|
1517
1682
|
case "TS":
|
|
1518
1683
|
_Arinc702Helper.processTimeStamp(decodeResult, data2.split(","));
|
|
1519
1684
|
break;
|
|
@@ -1694,6 +1859,21 @@ function processLandingReport(decodeResult, data) {
|
|
|
1694
1859
|
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
1695
1860
|
}
|
|
1696
1861
|
}
|
|
1862
|
+
function processTR(decodeResult, data) {
|
|
1863
|
+
if (data.length !== 21) {
|
|
1864
|
+
ResultFormatter.unknownArr(decodeResult, data, ",");
|
|
1865
|
+
return;
|
|
1866
|
+
}
|
|
1867
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(0, 5), ",");
|
|
1868
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[5]));
|
|
1869
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(6, 11), ",");
|
|
1870
|
+
ResultFormatter.departureAirport(decodeResult, data[11]);
|
|
1871
|
+
ResultFormatter.arrivalAirport(decodeResult, data[12]);
|
|
1872
|
+
ResultFormatter.departureRunway(decodeResult, data[13]);
|
|
1873
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(14, 16), ",");
|
|
1874
|
+
ResultFormatter.flightNumber(decodeResult, data[16]);
|
|
1875
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(17), ",");
|
|
1876
|
+
}
|
|
1697
1877
|
function processCenterOfGravity(decodeResult, data) {
|
|
1698
1878
|
if (data.length === 1) {
|
|
1699
1879
|
if (data[0] !== void 0 && data[0] !== "") {
|
|
@@ -1754,6 +1934,8 @@ function processIMI(decodeResult, type) {
|
|
|
1754
1934
|
decodeResult.formatted.description = "Load Distribution Information";
|
|
1755
1935
|
} else if (type === "PER") {
|
|
1756
1936
|
decodeResult.formatted.description = "Performance Report";
|
|
1937
|
+
} else if (type === "PRF") {
|
|
1938
|
+
decodeResult.formatted.description = "Profile Report";
|
|
1757
1939
|
} else if (type === "POS") {
|
|
1758
1940
|
decodeResult.formatted.description = "Position Report";
|
|
1759
1941
|
} else if (type === "PRG") {
|
|
@@ -2192,7 +2374,54 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
2192
2374
|
}
|
|
2193
2375
|
};
|
|
2194
2376
|
|
|
2377
|
+
// lib/utils/swa_request.ts
|
|
2378
|
+
var AIRLINES = { "189": "Southwest" };
|
|
2379
|
+
function swaRequestHeader(decodeResult, airlineId, layout, software) {
|
|
2380
|
+
const airline = AIRLINES[airlineId];
|
|
2381
|
+
ResultFormatter.raw(
|
|
2382
|
+
decodeResult,
|
|
2383
|
+
"airline_id",
|
|
2384
|
+
"AIRLINE",
|
|
2385
|
+
"Airline ID",
|
|
2386
|
+
airline ? `${airlineId} (${airline})` : airlineId,
|
|
2387
|
+
airlineId
|
|
2388
|
+
);
|
|
2389
|
+
ResultFormatter.raw(
|
|
2390
|
+
decodeResult,
|
|
2391
|
+
"request_layout",
|
|
2392
|
+
"LAYOUT",
|
|
2393
|
+
"Request Layout",
|
|
2394
|
+
layout
|
|
2395
|
+
);
|
|
2396
|
+
ResultFormatter.raw(
|
|
2397
|
+
decodeResult,
|
|
2398
|
+
"software_version",
|
|
2399
|
+
"SWVER",
|
|
2400
|
+
"Software Version",
|
|
2401
|
+
software
|
|
2402
|
+
);
|
|
2403
|
+
}
|
|
2404
|
+
|
|
2195
2405
|
// lib/plugins/Label_10_LDR.ts
|
|
2406
|
+
function pounds(value) {
|
|
2407
|
+
if (value.trim() === "") return void 0;
|
|
2408
|
+
const thousands = Number(value);
|
|
2409
|
+
return Number.isFinite(thousands) ? Math.round(thousands * 1e3) : void 0;
|
|
2410
|
+
}
|
|
2411
|
+
function runway(value) {
|
|
2412
|
+
const [rwy, suffix = ""] = value.trim().split("/");
|
|
2413
|
+
return suffix.trim() === "" ? rwy.trim() : `${rwy.trim()}/${suffix.trim()}`;
|
|
2414
|
+
}
|
|
2415
|
+
var RUNWAY_CONDITION = {
|
|
2416
|
+
6: "dry",
|
|
2417
|
+
5: "good",
|
|
2418
|
+
4: "good to medium",
|
|
2419
|
+
3: "medium",
|
|
2420
|
+
2: "medium to poor",
|
|
2421
|
+
1: "poor",
|
|
2422
|
+
0: "nil"
|
|
2423
|
+
};
|
|
2424
|
+
var FLAPS = { "0": 30, "1": 40, "2": 15 };
|
|
2196
2425
|
var Label_10_LDR = class extends DecoderPlugin {
|
|
2197
2426
|
name = "label-10-ldr";
|
|
2198
2427
|
qualifiers() {
|
|
@@ -2204,18 +2433,13 @@ var Label_10_LDR = class extends DecoderPlugin {
|
|
|
2204
2433
|
decode(message, options = {}) {
|
|
2205
2434
|
const decodeResult = this.defaultResult();
|
|
2206
2435
|
decodeResult.decoder.name = this.name;
|
|
2207
|
-
decodeResult.formatted.description = "
|
|
2436
|
+
decodeResult.formatted.description = "Landing Data Request";
|
|
2208
2437
|
decodeResult.message = message;
|
|
2209
2438
|
const parts = message.text.split(",");
|
|
2210
|
-
if (parts.length <
|
|
2211
|
-
|
|
2212
|
-
console.log(`Decoder: Unknown 10 message: ${message.text}`);
|
|
2213
|
-
}
|
|
2214
|
-
ResultFormatter.unknown(decodeResult, message.text);
|
|
2215
|
-
decodeResult.decoded = false;
|
|
2216
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2217
|
-
return decodeResult;
|
|
2439
|
+
if (parts.length < 31) {
|
|
2440
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
2218
2441
|
}
|
|
2442
|
+
swaRequestHeader(decodeResult, parts[1], parts[2], parts[3]);
|
|
2219
2443
|
const lat = parts[5];
|
|
2220
2444
|
const lon = parts[6];
|
|
2221
2445
|
const position = {
|
|
@@ -2223,25 +2447,209 @@ var Label_10_LDR = class extends DecoderPlugin {
|
|
|
2223
2447
|
longitude: (lon[0] === "E" ? 1 : -1) * Number(lon.substring(1).trim())
|
|
2224
2448
|
};
|
|
2225
2449
|
ResultFormatter.position(decodeResult, position);
|
|
2226
|
-
|
|
2450
|
+
if (parts[7].trim() !== "") {
|
|
2451
|
+
ResultFormatter.altitude(decodeResult, Number(parts[7]));
|
|
2452
|
+
}
|
|
2453
|
+
const fuel = pounds(parts[8]);
|
|
2454
|
+
if (fuel !== void 0) ResultFormatter.currentFuel(decodeResult, fuel);
|
|
2227
2455
|
ResultFormatter.departureAirport(decodeResult, parts[9]);
|
|
2228
2456
|
ResultFormatter.arrivalAirport(decodeResult, parts[10]);
|
|
2229
|
-
ResultFormatter.
|
|
2230
|
-
ResultFormatter.arrivalRunway(decodeResult, parts[12]
|
|
2231
|
-
const altRwy = [parts[13]
|
|
2457
|
+
ResultFormatter.landingAirport(decodeResult, parts[11]);
|
|
2458
|
+
ResultFormatter.arrivalRunway(decodeResult, runway(parts[12]));
|
|
2459
|
+
const altRwy = [runway(parts[13]), runway(parts[14])].filter((r) => r != "").join(",");
|
|
2232
2460
|
if (altRwy != "") {
|
|
2233
2461
|
ResultFormatter.alternateRunway(decodeResult, altRwy);
|
|
2234
2462
|
}
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2463
|
+
const unknown = [parts[4]];
|
|
2464
|
+
const condition = parts[15].trim();
|
|
2465
|
+
if (/^[1-6]$/.test(condition)) {
|
|
2466
|
+
const code = 6 - Number(condition);
|
|
2467
|
+
ResultFormatter.raw(
|
|
2468
|
+
decodeResult,
|
|
2469
|
+
"runway_condition_code",
|
|
2470
|
+
"RCC",
|
|
2471
|
+
"Runway Condition Code",
|
|
2472
|
+
`${code} (${RUNWAY_CONDITION[code]})`,
|
|
2473
|
+
code
|
|
2474
|
+
);
|
|
2475
|
+
} else if (condition !== "0") {
|
|
2476
|
+
unknown.push(parts[15]);
|
|
2477
|
+
}
|
|
2478
|
+
const flaps = FLAPS[parts[16].trim()];
|
|
2479
|
+
if (flaps !== void 0) {
|
|
2480
|
+
ResultFormatter.raw(
|
|
2481
|
+
decodeResult,
|
|
2482
|
+
"landing_flaps",
|
|
2483
|
+
"FLAPS",
|
|
2484
|
+
"Landing Flaps",
|
|
2485
|
+
`${flaps}`,
|
|
2486
|
+
flaps
|
|
2487
|
+
);
|
|
2488
|
+
} else {
|
|
2489
|
+
unknown.push(parts[16]);
|
|
2490
|
+
}
|
|
2491
|
+
const [windDir, windSpeed, gust, temp, dew, altimeter] = parts.slice(17, 23).map((field) => {
|
|
2492
|
+
const value = field.trim();
|
|
2493
|
+
if (/^-?\d{1,4}$/.test(value)) return Number(value);
|
|
2494
|
+
if (value !== "") unknown.push(field);
|
|
2495
|
+
return void 0;
|
|
2496
|
+
});
|
|
2497
|
+
if (windDir !== void 0 || windSpeed !== void 0) {
|
|
2498
|
+
ResultFormatter.wind(decodeResult, windDir, windSpeed);
|
|
2499
|
+
}
|
|
2500
|
+
if (gust !== void 0) {
|
|
2501
|
+
ResultFormatter.raw(
|
|
2502
|
+
decodeResult,
|
|
2503
|
+
"wind_gust",
|
|
2504
|
+
"GUST",
|
|
2505
|
+
"Wind Gust",
|
|
2506
|
+
`${gust} knots`,
|
|
2507
|
+
gust
|
|
2508
|
+
);
|
|
2509
|
+
}
|
|
2510
|
+
ResultFormatter.temperature(
|
|
2511
|
+
decodeResult,
|
|
2512
|
+
temp === void 0 ? "" : `${temp}`
|
|
2513
|
+
);
|
|
2514
|
+
if (dew !== void 0) {
|
|
2515
|
+
ResultFormatter.raw(
|
|
2516
|
+
decodeResult,
|
|
2517
|
+
"dew_point",
|
|
2518
|
+
"DEWPT",
|
|
2519
|
+
"Dew Point (C)",
|
|
2520
|
+
`${dew} degrees`,
|
|
2521
|
+
dew
|
|
2522
|
+
);
|
|
2523
|
+
}
|
|
2524
|
+
if (altimeter !== void 0) {
|
|
2525
|
+
const inHg = altimeter / 100;
|
|
2526
|
+
ResultFormatter.raw(
|
|
2527
|
+
decodeResult,
|
|
2528
|
+
"altimeter",
|
|
2529
|
+
"ALTIM",
|
|
2530
|
+
"Altimeter",
|
|
2531
|
+
`${inHg.toFixed(2)} inHg`,
|
|
2532
|
+
inHg
|
|
2533
|
+
);
|
|
2534
|
+
}
|
|
2535
|
+
const antiIce = parts[23].trim();
|
|
2536
|
+
if (/^[1-9]$/.test(antiIce)) {
|
|
2537
|
+
ResultFormatter.raw(
|
|
2538
|
+
decodeResult,
|
|
2539
|
+
"anti_ice",
|
|
2540
|
+
"ANTIICE",
|
|
2541
|
+
"Anti-Ice",
|
|
2542
|
+
antiIce === "1" ? "engine" : antiIce,
|
|
2543
|
+
Number(antiIce)
|
|
2544
|
+
);
|
|
2545
|
+
} else if (antiIce !== "0") {
|
|
2546
|
+
unknown.push(parts[23]);
|
|
2547
|
+
}
|
|
2548
|
+
const flags = [
|
|
2549
|
+
[parts[24], "enroute_icing", "ICING", "En Route Icing"],
|
|
2550
|
+
// the card says HGS AIII: 113 of 113 pairs, 32 requests
|
|
2551
|
+
[parts[25], "hgs_approach", "HGS", "HGS Approach"]
|
|
2552
|
+
];
|
|
2553
|
+
for (const [value, key, code, label] of flags) {
|
|
2554
|
+
if (value.trim() === "1") {
|
|
2555
|
+
ResultFormatter.raw(decodeResult, key, code, label, "yes", true);
|
|
2556
|
+
} else if (value.trim() !== "0") {
|
|
2557
|
+
unknown.push(value);
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
const nonNormal = parts[26].trim();
|
|
2561
|
+
if (/^\d+$/.test(nonNormal) && Number(nonNormal) !== 0) {
|
|
2562
|
+
ResultFormatter.raw(
|
|
2563
|
+
decodeResult,
|
|
2564
|
+
"non_normal_configuration",
|
|
2565
|
+
"NNC",
|
|
2566
|
+
"Non-Normal Configuration",
|
|
2567
|
+
`${Number(nonNormal)}`,
|
|
2568
|
+
Number(nonNormal)
|
|
2569
|
+
);
|
|
2570
|
+
} else if (!/^0+$/.test(nonNormal)) {
|
|
2571
|
+
unknown.push(parts[26]);
|
|
2572
|
+
}
|
|
2573
|
+
if (parts[27].trim() !== "") unknown.push(parts[27]);
|
|
2574
|
+
const weights = [
|
|
2575
|
+
["zero_fuel_weight", "ZFW", "Zero Fuel Weight", parts[28]],
|
|
2576
|
+
["landing_fuel", "LFUEL", "Landing Fuel", parts[29]],
|
|
2577
|
+
["landing_weight", "LDW", "Landing Weight", parts[30]]
|
|
2578
|
+
];
|
|
2579
|
+
for (const [key, code, label, value] of weights) {
|
|
2580
|
+
const amount = pounds(value);
|
|
2581
|
+
if (amount === void 0) continue;
|
|
2582
|
+
ResultFormatter.raw(
|
|
2583
|
+
decodeResult,
|
|
2584
|
+
key,
|
|
2585
|
+
code,
|
|
2586
|
+
label,
|
|
2587
|
+
`${amount} pounds`,
|
|
2588
|
+
amount
|
|
2589
|
+
);
|
|
2590
|
+
}
|
|
2591
|
+
const gradient = (parts[31] ?? "").trim();
|
|
2592
|
+
if (/^\d+$/.test(gradient)) {
|
|
2593
|
+
ResultFormatter.raw(
|
|
2594
|
+
decodeResult,
|
|
2595
|
+
"missed_approach_gradient",
|
|
2596
|
+
"MAGRAD",
|
|
2597
|
+
"Missed Approach Climb Gradient",
|
|
2598
|
+
`${Number(gradient)} feet per nautical mile`,
|
|
2599
|
+
Number(gradient)
|
|
2600
|
+
);
|
|
2601
|
+
} else if (gradient !== "" && gradient !== "----.") {
|
|
2602
|
+
unknown.push(parts[31]);
|
|
2603
|
+
}
|
|
2604
|
+
const missedAltitude = (parts[32] ?? "").trim();
|
|
2605
|
+
if (/^\d+$/.test(missedAltitude)) {
|
|
2606
|
+
ResultFormatter.raw(
|
|
2607
|
+
decodeResult,
|
|
2608
|
+
"missed_approach_altitude",
|
|
2609
|
+
"MAALT",
|
|
2610
|
+
"Missed Approach Altitude",
|
|
2611
|
+
`${Number(missedAltitude)} feet`,
|
|
2612
|
+
Number(missedAltitude)
|
|
2613
|
+
);
|
|
2614
|
+
} else if (missedAltitude !== "") {
|
|
2615
|
+
unknown.push(parts[32]);
|
|
2616
|
+
}
|
|
2617
|
+
unknown.push(...parts.slice(33).filter((field) => field.trim() !== ""));
|
|
2618
|
+
ResultFormatter.unknownArr(decodeResult, unknown);
|
|
2239
2619
|
decodeResult.decoded = true;
|
|
2240
2620
|
decodeResult.decoder.decodeLevel = "partial";
|
|
2241
2621
|
return decodeResult;
|
|
2242
2622
|
}
|
|
2243
2623
|
};
|
|
2244
2624
|
|
|
2625
|
+
// lib/plugins/Label_10_LRW.ts
|
|
2626
|
+
var Label_10_LRW = class extends DecoderPlugin {
|
|
2627
|
+
name = "label-10-lrw";
|
|
2628
|
+
qualifiers() {
|
|
2629
|
+
return {
|
|
2630
|
+
labels: ["10"],
|
|
2631
|
+
preambles: ["LRW01,"]
|
|
2632
|
+
};
|
|
2633
|
+
}
|
|
2634
|
+
decode(message, options = {}) {
|
|
2635
|
+
const decodeResult = this.initResult(message, "Landing Runways Request");
|
|
2636
|
+
const parts = message.text.split(",");
|
|
2637
|
+
if (parts.length < 8 || parts[7].trim() === "") {
|
|
2638
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
2639
|
+
}
|
|
2640
|
+
swaRequestHeader(decodeResult, parts[1], parts[2], parts[3]);
|
|
2641
|
+
ResultFormatter.departureAirport(decodeResult, parts[6]);
|
|
2642
|
+
ResultFormatter.arrivalAirport(decodeResult, parts[7]);
|
|
2643
|
+
ResultFormatter.unknownArr(decodeResult, [
|
|
2644
|
+
parts[4],
|
|
2645
|
+
parts[5],
|
|
2646
|
+
...parts.slice(8).filter((field) => field.trim() !== "")
|
|
2647
|
+
]);
|
|
2648
|
+
this.setDecodeLevel(decodeResult, true);
|
|
2649
|
+
return decodeResult;
|
|
2650
|
+
}
|
|
2651
|
+
};
|
|
2652
|
+
|
|
2245
2653
|
// lib/plugins/Label_10_POS.ts
|
|
2246
2654
|
var Label_10_POS = class extends DecoderPlugin {
|
|
2247
2655
|
name = "label-10-pos";
|
|
@@ -2341,6 +2749,364 @@ var Label_10_Slash = class extends DecoderPlugin {
|
|
|
2341
2749
|
}
|
|
2342
2750
|
};
|
|
2343
2751
|
|
|
2752
|
+
// lib/utils/runway_utils.ts
|
|
2753
|
+
var SIDES = {
|
|
2754
|
+
N: "north",
|
|
2755
|
+
NE: "northeast",
|
|
2756
|
+
E: "east",
|
|
2757
|
+
SE: "southeast",
|
|
2758
|
+
S: "south",
|
|
2759
|
+
SW: "southwest",
|
|
2760
|
+
W: "west",
|
|
2761
|
+
NW: "northwest"
|
|
2762
|
+
};
|
|
2763
|
+
var RunwayUtils = class {
|
|
2764
|
+
/**
|
|
2765
|
+
* Describe the condition that names a runway variant in Southwest landing data, e.g.
|
|
2766
|
+
* `11/AIB -E1804F`: the runway, the variant's code and its condition.
|
|
2767
|
+
*
|
|
2768
|
+
* -E1804F is 1804 feet taken off the east end, -SWCBL the arresting cable at the southwest
|
|
2769
|
+
* end. Checked on the LRW01 runway lists of six airports, where every variant's length is
|
|
2770
|
+
* the runway's less the feet given, or less 1500 feet for a cable. LAHSO is sent as written.
|
|
2771
|
+
*
|
|
2772
|
+
* @param name - the runway as sent, with its variant
|
|
2773
|
+
* @returns a description of the condition, or undefined when the name has none
|
|
2774
|
+
*/
|
|
2775
|
+
static variantDescription(name) {
|
|
2776
|
+
const text = name.trim();
|
|
2777
|
+
const cut = text.match(/-(NE|NW|SE|SW|N|E|S|W)(\d+)F$/);
|
|
2778
|
+
if (cut) {
|
|
2779
|
+
return `${Number(cut[2])} feet off the ${SIDES[cut[1]]} end`;
|
|
2780
|
+
}
|
|
2781
|
+
const cable = text.match(/-(NE|NW|SE|SW|N|E|S|W)CBL$/);
|
|
2782
|
+
if (cable) {
|
|
2783
|
+
return `arresting cable at the ${SIDES[cable[1]]} end`;
|
|
2784
|
+
}
|
|
2785
|
+
if (/(^|\s)LAHSO$/.test(text)) {
|
|
2786
|
+
return "land and hold short";
|
|
2787
|
+
}
|
|
2788
|
+
return void 0;
|
|
2789
|
+
}
|
|
2790
|
+
};
|
|
2791
|
+
|
|
2792
|
+
// lib/plugins/Label_11_LDR.ts
|
|
2793
|
+
function tod(hours, minutes) {
|
|
2794
|
+
const h = Number(hours);
|
|
2795
|
+
const m = Number(minutes);
|
|
2796
|
+
return h <= 23 && m <= 59 ? h * 3600 + m * 60 : void 0;
|
|
2797
|
+
}
|
|
2798
|
+
function pounds2(value) {
|
|
2799
|
+
return Math.round(Number(value) * 1e3);
|
|
2800
|
+
}
|
|
2801
|
+
function variant(runway2) {
|
|
2802
|
+
const description = RunwayUtils.variantDescription(runway2);
|
|
2803
|
+
return description === void 0 ? {} : { variant: description };
|
|
2804
|
+
}
|
|
2805
|
+
var HEADER = [
|
|
2806
|
+
/^LDR01,(\w{4}) LANDING DATA,FLT(?:\s+METAR-(\d{2})(\d{2})Z)?\s*$/,
|
|
2807
|
+
/^(\d{1,4})\s+WIND\s+LDW\s*$/,
|
|
2808
|
+
/^TIME\s+(\d{3}|VRB)\/(\d{2,3})G(\d{2,3}|--)\s+(\d+\.\d)\s*$/,
|
|
2809
|
+
/^(\d{2})(\d{2})Z\s+OAT\/DEW\s*(\S*)\s*$/,
|
|
2810
|
+
/^\s+(-?\d{2,3})\/(-?\d{2,3})\s*(\S*)\s*$/,
|
|
2811
|
+
/^\s+QNH\s*(\S*)\s*$/,
|
|
2812
|
+
// QNH in inches of mercury, or hectopascals outside the US
|
|
2813
|
+
/^\s+(\d{2}\.\d{2}|\d{4})\s*(\S*)\s*$/
|
|
2814
|
+
];
|
|
2815
|
+
var RUNWAY = /^(\d{1,2}[LRC]?(?:\/\S+)?(?: -\S+)?)\s+(\d{1,5})\s*$/;
|
|
2816
|
+
var RUNWAY_START = /^\d{1,2}[LRC]?(?:\/\S+)?(?: -\S+)?(?:\s{2,}\d*)?\s*$/;
|
|
2817
|
+
var ALTERNATIVES = "--- ALTERNATIVE RWYS ---";
|
|
2818
|
+
var ALTERNATIVE = /^(?:(.+?)\s{2,})?(\d{1,2}[LRC]?(?:\/\S+)?)\s*$/;
|
|
2819
|
+
var BLOCK = [
|
|
2820
|
+
/^FLAPS (\d{2}|--)\s*$/,
|
|
2821
|
+
/^VREF\/VTGT\s+(?:(\d{2})([HT])\/(\d{2})([LR])|---\/---)\s*$/,
|
|
2822
|
+
/^\s*(?:(\d{3})\/(\d{3}) ([+-]\d+)|---\/---)\s+(AB\d)\s+(\d+|----)\s*$/,
|
|
2823
|
+
/^MRLW (\d+\.\d\/\S|-+\/-)\s+(AB\d)\s+(\d+|----)\s*$/,
|
|
2824
|
+
/^\s*LDW (\d+\.\d)\s+(ABM)\s+(\d+|----)\s*$/
|
|
2825
|
+
];
|
|
2826
|
+
var Label_11_LDR = class extends DecoderPlugin {
|
|
2827
|
+
name = "label-11-ldr";
|
|
2828
|
+
qualifiers() {
|
|
2829
|
+
return {
|
|
2830
|
+
labels: ["11"],
|
|
2831
|
+
preambles: ["LDR01,"]
|
|
2832
|
+
};
|
|
2833
|
+
}
|
|
2834
|
+
decode(message, options = {}) {
|
|
2835
|
+
const decodeResult = this.initResult(message, "Landing Data");
|
|
2836
|
+
const nl = message.text.includes("\r\n") ? "\r\n" : "\n";
|
|
2837
|
+
const lines = message.text.split(/\r?\n/);
|
|
2838
|
+
const first = lines[0].match(HEADER[0]);
|
|
2839
|
+
if (!first) {
|
|
2840
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
2841
|
+
}
|
|
2842
|
+
const unknown = [];
|
|
2843
|
+
ResultFormatter.landingAirport(decodeResult, first[1]);
|
|
2844
|
+
const metar = first[2] === void 0 ? void 0 : tod(first[2], first[3]);
|
|
2845
|
+
if (first[2] !== void 0 && metar === void 0) {
|
|
2846
|
+
unknown.push(`METAR-${first[2]}${first[3]}Z`);
|
|
2847
|
+
}
|
|
2848
|
+
if (metar !== void 0) {
|
|
2849
|
+
ResultFormatter.raw(
|
|
2850
|
+
decodeResult,
|
|
2851
|
+
"metar_time",
|
|
2852
|
+
"METAR",
|
|
2853
|
+
"METAR Time",
|
|
2854
|
+
DateTimeUtils.timestampToString(metar),
|
|
2855
|
+
metar
|
|
2856
|
+
);
|
|
2857
|
+
}
|
|
2858
|
+
const runways = [];
|
|
2859
|
+
let i = 1;
|
|
2860
|
+
for (; i < HEADER.length && i < lines.length; i++) {
|
|
2861
|
+
const m = lines[i].match(HEADER[i]);
|
|
2862
|
+
if (!m) break;
|
|
2863
|
+
if (i === 1) {
|
|
2864
|
+
ResultFormatter.flightNumber(decodeResult, m[1]);
|
|
2865
|
+
} else if (i === 2) {
|
|
2866
|
+
if (m[1] === "VRB") {
|
|
2867
|
+
ResultFormatter.variableWind(decodeResult, Number(m[2]));
|
|
2868
|
+
} else {
|
|
2869
|
+
ResultFormatter.wind(decodeResult, Number(m[1]), Number(m[2]));
|
|
2870
|
+
}
|
|
2871
|
+
if (m[3] !== "--") {
|
|
2872
|
+
ResultFormatter.raw(
|
|
2873
|
+
decodeResult,
|
|
2874
|
+
"wind_gust",
|
|
2875
|
+
"GUST",
|
|
2876
|
+
"Wind Gust",
|
|
2877
|
+
`${Number(m[3])} knots`,
|
|
2878
|
+
Number(m[3])
|
|
2879
|
+
);
|
|
2880
|
+
}
|
|
2881
|
+
ResultFormatter.raw(
|
|
2882
|
+
decodeResult,
|
|
2883
|
+
"landing_weight",
|
|
2884
|
+
"LDW",
|
|
2885
|
+
"Landing Weight",
|
|
2886
|
+
`${pounds2(m[4])} pounds`,
|
|
2887
|
+
pounds2(m[4])
|
|
2888
|
+
);
|
|
2889
|
+
} else if (i === 3) {
|
|
2890
|
+
const time = tod(m[1], m[2]);
|
|
2891
|
+
if (time === void 0) {
|
|
2892
|
+
unknown.push(`${m[1]}${m[2]}Z`);
|
|
2893
|
+
} else {
|
|
2894
|
+
ResultFormatter.timestamp(decodeResult, time);
|
|
2895
|
+
}
|
|
2896
|
+
runways.push(m[3]);
|
|
2897
|
+
} else if (i === 4) {
|
|
2898
|
+
ResultFormatter.temperature(decodeResult, `${Number(m[1])}`);
|
|
2899
|
+
ResultFormatter.raw(
|
|
2900
|
+
decodeResult,
|
|
2901
|
+
"dew_point",
|
|
2902
|
+
"DEWPT",
|
|
2903
|
+
"Dew Point (C)",
|
|
2904
|
+
`${Number(m[2])} degrees`,
|
|
2905
|
+
Number(m[2])
|
|
2906
|
+
);
|
|
2907
|
+
runways.push(m[3]);
|
|
2908
|
+
} else if (i === 5) {
|
|
2909
|
+
runways.push(m[1]);
|
|
2910
|
+
} else {
|
|
2911
|
+
ResultFormatter.raw(
|
|
2912
|
+
decodeResult,
|
|
2913
|
+
"altimeter",
|
|
2914
|
+
"ALTIM",
|
|
2915
|
+
"Altimeter",
|
|
2916
|
+
`${m[1]} ${m[1].includes(".") ? "inHg" : "hPa"}`,
|
|
2917
|
+
Number(m[1])
|
|
2918
|
+
);
|
|
2919
|
+
runways.push(m[2]);
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
const listed = runways.filter((r) => r !== "");
|
|
2923
|
+
if (listed.length > 0) {
|
|
2924
|
+
ResultFormatter.raw(
|
|
2925
|
+
decodeResult,
|
|
2926
|
+
"runways",
|
|
2927
|
+
"RWYS",
|
|
2928
|
+
"Runways",
|
|
2929
|
+
listed.join(", "),
|
|
2930
|
+
listed
|
|
2931
|
+
);
|
|
2932
|
+
}
|
|
2933
|
+
const rest = lines.slice(i);
|
|
2934
|
+
let at = 0;
|
|
2935
|
+
const alternatives = [];
|
|
2936
|
+
if (rest[0]?.trim() === "REMARKS") {
|
|
2937
|
+
const remarks = [];
|
|
2938
|
+
for (at = 1; at < rest.length && !RUNWAY_START.test(rest[at]); at++) {
|
|
2939
|
+
if (rest[at].trim() === ALTERNATIVES) {
|
|
2940
|
+
at = this.alternatives(rest, at + 1, alternatives, unknown);
|
|
2941
|
+
break;
|
|
2942
|
+
}
|
|
2943
|
+
if (rest[at].trim() !== "") remarks.push(rest[at].trim());
|
|
2944
|
+
}
|
|
2945
|
+
if (remarks.length > 0) {
|
|
2946
|
+
ResultFormatter.raw(
|
|
2947
|
+
decodeResult,
|
|
2948
|
+
"remarks",
|
|
2949
|
+
"RMK",
|
|
2950
|
+
"Remarks",
|
|
2951
|
+
remarks.join(" ")
|
|
2952
|
+
);
|
|
2953
|
+
}
|
|
2954
|
+
}
|
|
2955
|
+
if (alternatives.length > 0) {
|
|
2956
|
+
ResultFormatter.raw(
|
|
2957
|
+
decodeResult,
|
|
2958
|
+
"alternative_runways",
|
|
2959
|
+
"ALTRWY",
|
|
2960
|
+
"Alternative Runways",
|
|
2961
|
+
alternatives.map((a) => a.variant ? `${a.runway} (${a.variant})` : a.runway).join(", "),
|
|
2962
|
+
alternatives
|
|
2963
|
+
);
|
|
2964
|
+
}
|
|
2965
|
+
const blocks = [];
|
|
2966
|
+
while (at < rest.length) {
|
|
2967
|
+
const block = this.runwayBlock(rest.slice(at, at + 1 + BLOCK.length));
|
|
2968
|
+
if (block) {
|
|
2969
|
+
blocks.push(block);
|
|
2970
|
+
at += 1 + BLOCK.length;
|
|
2971
|
+
continue;
|
|
2972
|
+
}
|
|
2973
|
+
const line = rest[at];
|
|
2974
|
+
const head = line.match(RUNWAY);
|
|
2975
|
+
const next = rest.slice(at + 1).find((l) => l.trim() !== "");
|
|
2976
|
+
if (head && next !== void 0 && !next.startsWith("FLAPS") && // a FLAPS line cut off by the end of the block
|
|
2977
|
+
!"FLAPS".startsWith(next.trim()) && !RUNWAY_START.test(next)) {
|
|
2978
|
+
blocks.push({
|
|
2979
|
+
runway: head[1],
|
|
2980
|
+
...variant(head[1]),
|
|
2981
|
+
length: Number(head[2]),
|
|
2982
|
+
stoppingMargins: {}
|
|
2983
|
+
});
|
|
2984
|
+
at++;
|
|
2985
|
+
continue;
|
|
2986
|
+
}
|
|
2987
|
+
const last = blocks[blocks.length - 1];
|
|
2988
|
+
if (line.trim() !== "") {
|
|
2989
|
+
if (last && !RUNWAY_START.test(line)) {
|
|
2990
|
+
last.notes = [...last.notes ?? [], line.trim()];
|
|
2991
|
+
} else {
|
|
2992
|
+
unknown.push(...rest.slice(at).filter((l) => l.trim() !== ""));
|
|
2993
|
+
break;
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
at++;
|
|
2997
|
+
}
|
|
2998
|
+
for (const block of blocks) {
|
|
2999
|
+
ResultFormatter.runwayLandingData(decodeResult, block);
|
|
3000
|
+
}
|
|
3001
|
+
if (unknown.length > 0) {
|
|
3002
|
+
ResultFormatter.unknown(decodeResult, unknown.join(nl), nl);
|
|
3003
|
+
}
|
|
3004
|
+
this.setDecodeLevel(
|
|
3005
|
+
decodeResult,
|
|
3006
|
+
true,
|
|
3007
|
+
i < HEADER.length ? "partial" : void 0
|
|
3008
|
+
);
|
|
3009
|
+
return decodeResult;
|
|
3010
|
+
}
|
|
3011
|
+
/** The six lines of one runway, or undefined if they are not a whole block. */
|
|
3012
|
+
runwayBlock(lines) {
|
|
3013
|
+
const head = lines[0]?.match(RUNWAY);
|
|
3014
|
+
if (!head || lines.length < 1 + BLOCK.length) return void 0;
|
|
3015
|
+
const m = BLOCK.map((re, n) => lines[n + 1].match(re));
|
|
3016
|
+
if (m.some((x) => !x)) return void 0;
|
|
3017
|
+
const [flaps, wind, speeds, mrlw, ldw] = m;
|
|
3018
|
+
const data = {
|
|
3019
|
+
runway: head[1],
|
|
3020
|
+
...variant(head[1]),
|
|
3021
|
+
length: Number(head[2]),
|
|
3022
|
+
stoppingMargins: {}
|
|
3023
|
+
};
|
|
3024
|
+
if (flaps[1] !== "--") data.flaps = Number(flaps[1]);
|
|
3025
|
+
if (wind[1] !== void 0) {
|
|
3026
|
+
data.headwind = Number(wind[1]) * (wind[2] === "T" ? -1 : 1);
|
|
3027
|
+
data.crosswind = Number(wind[3]);
|
|
3028
|
+
data.crosswindSide = wind[4];
|
|
3029
|
+
}
|
|
3030
|
+
if (speeds[1] !== void 0) {
|
|
3031
|
+
data.vref = Number(speeds[1]);
|
|
3032
|
+
data.vtarget = Number(speeds[2]);
|
|
3033
|
+
data.additive = Number(speeds[3]);
|
|
3034
|
+
}
|
|
3035
|
+
if (!mrlw[1].startsWith("-")) data.maxLandingWeight = mrlw[1];
|
|
3036
|
+
data.landingWeight = pounds2(ldw[1]);
|
|
3037
|
+
for (const [setting, feet] of [
|
|
3038
|
+
[speeds[4], speeds[5]],
|
|
3039
|
+
[mrlw[2], mrlw[3]],
|
|
3040
|
+
[ldw[2], ldw[3]]
|
|
3041
|
+
]) {
|
|
3042
|
+
if (feet !== "----") data.stoppingMargins[setting] = Number(feet);
|
|
3043
|
+
}
|
|
3044
|
+
return data;
|
|
3045
|
+
}
|
|
3046
|
+
/**
|
|
3047
|
+
* The runways listed after ALTERNATIVE RWYS, which run to the end of the card. Returns the
|
|
3048
|
+
* index of the line after them.
|
|
3049
|
+
*/
|
|
3050
|
+
alternatives(lines, from, out, unknown) {
|
|
3051
|
+
for (let n = from; n < lines.length; n++) {
|
|
3052
|
+
const line = lines[n];
|
|
3053
|
+
if (line.trim() === "") continue;
|
|
3054
|
+
const m = line.match(ALTERNATIVE);
|
|
3055
|
+
if (!m || n === lines.length - 1) {
|
|
3056
|
+
unknown.push(line.trim());
|
|
3057
|
+
continue;
|
|
3058
|
+
}
|
|
3059
|
+
const name = m[1]?.trim();
|
|
3060
|
+
out.push({
|
|
3061
|
+
runway: m[2],
|
|
3062
|
+
...name === void 0 ? {} : { name },
|
|
3063
|
+
...variant(name ?? m[2])
|
|
3064
|
+
});
|
|
3065
|
+
}
|
|
3066
|
+
return lines.length;
|
|
3067
|
+
}
|
|
3068
|
+
};
|
|
3069
|
+
|
|
3070
|
+
// lib/plugins/Label_11_LRW.ts
|
|
3071
|
+
var RUNWAY2 = /^(\d{1,2}[LRC]?)\s?(?:\/(\S+))?\s+(?:(-\S+|LAHSO)\s+)?(\d{3,5})\s*$/;
|
|
3072
|
+
var Label_11_LRW = class extends DecoderPlugin {
|
|
3073
|
+
name = "label-11-lrw";
|
|
3074
|
+
qualifiers() {
|
|
3075
|
+
return {
|
|
3076
|
+
labels: ["11"],
|
|
3077
|
+
preambles: ["LRW01,"]
|
|
3078
|
+
};
|
|
3079
|
+
}
|
|
3080
|
+
decode(message, options = {}) {
|
|
3081
|
+
const decodeResult = this.initResult(message, "Landing Runways");
|
|
3082
|
+
const nl = message.text.includes("\r\n") ? "\r\n" : "\n";
|
|
3083
|
+
const first = message.text.match(/^LRW01,(\w{4}) LANDING RUNWAYS,/);
|
|
3084
|
+
if (!first) {
|
|
3085
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
3086
|
+
}
|
|
3087
|
+
ResultFormatter.landingAirport(decodeResult, first[1]);
|
|
3088
|
+
const lines = message.text.slice(first[0].length).split(/\r?\n/);
|
|
3089
|
+
for (const line of lines) {
|
|
3090
|
+
if (line.trim() === "") continue;
|
|
3091
|
+
const m = line.match(RUNWAY2);
|
|
3092
|
+
if (!m) {
|
|
3093
|
+
ResultFormatter.unknown(decodeResult, line.trim(), nl);
|
|
3094
|
+
continue;
|
|
3095
|
+
}
|
|
3096
|
+
const runway2 = [m[2] ? `${m[1]}/${m[2]}` : m[1], m[3]].filter((part) => part !== void 0).join(" ");
|
|
3097
|
+
const description = RunwayUtils.variantDescription(runway2);
|
|
3098
|
+
ResultFormatter.runwayLandingData(decodeResult, {
|
|
3099
|
+
runway: runway2,
|
|
3100
|
+
...description === void 0 ? {} : { variant: description },
|
|
3101
|
+
length: Number(m[4]),
|
|
3102
|
+
stoppingMargins: {}
|
|
3103
|
+
});
|
|
3104
|
+
}
|
|
3105
|
+
this.setDecodeLevel(decodeResult, true);
|
|
3106
|
+
return decodeResult;
|
|
3107
|
+
}
|
|
3108
|
+
};
|
|
3109
|
+
|
|
2344
3110
|
// lib/plugins/Label_12_N_Space.ts
|
|
2345
3111
|
var Label_12_N_Space = class extends DecoderPlugin {
|
|
2346
3112
|
name = "label-12-n-space";
|
|
@@ -3768,11 +4534,718 @@ var Label_30_Slash_EA = class extends DecoderPlugin {
|
|
|
3768
4534
|
}
|
|
3769
4535
|
};
|
|
3770
4536
|
|
|
3771
|
-
// lib/
|
|
3772
|
-
var
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
4537
|
+
// lib/utils/swa_compressed.ts
|
|
4538
|
+
var SWA_ALPHABET = " (),-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
4539
|
+
var SWA_UNREAD = "\xA4";
|
|
4540
|
+
var SWA_LABEL_37_TABLES = {
|
|
4541
|
+
"01": "VIK86MRN5-0PZS4UYXACEHLOTW BGD.123Q(7J9:F)/,",
|
|
4542
|
+
"02": "HG.KZL97QY15WRVTN4JA06(D ,:3MPBICU/8EOFSX)2-",
|
|
4543
|
+
"03": "4GXE/QU5FT)20P8RSJ-169AWHLB.,37MNVCYODIKZ (:",
|
|
4544
|
+
"04": "1BEHMPSUY,048DG269JLOQTWZ (-/37:ACFIKNRVX).5",
|
|
4545
|
+
"05": "3579BDFHJLNPRTVXZ(,.02468:ACEGIKMOQSUWY )-/1",
|
|
4546
|
+
"06": "AGFEDCBRQPONMLKJIH:9876543210/.-,)( ZYXWVUTS",
|
|
4547
|
+
"07": ":.02468ACEGIKMOQSUWY )-/13579BDFHJLNPRTVXZ(,",
|
|
4548
|
+
"08": "1MDS/JQ.OWZ79LNR532-6(: ,APEFTVIKYB08H)U4CXG",
|
|
4549
|
+
"09": "6LQMSR UZYVX(7:3-5KPTACB)021,894NODGJEFIHW./"
|
|
4550
|
+
};
|
|
4551
|
+
var SWA_LABEL_40_TABLES = {
|
|
4552
|
+
"01": "IRXZ2MY3NOP71-S,UVAJBLCWKD(T)E.0F4Q/6G8 H:95",
|
|
4553
|
+
"02": "GEXHZ)QC3YJ:4D0R/IBMOFSU( NA,.K9TL16V8P75W2-",
|
|
4554
|
+
"03": "XY3KAJ-5B4L 0CM7DZEIQT,1(GU:VHNOS6.892/PF)RW",
|
|
4555
|
+
"04": "HIX2JYK3 8L4Z9M5:NO(P6)Q7,RASB-TC.DU/E0VFW1G",
|
|
4556
|
+
"05": "V:WAXBYCZD E(F)G,HI-J.K/L0M1N2O3P4Q5R6S7T8U9",
|
|
4557
|
+
"06": "RQPONMLKJIHGFEDCBA /.-,)(:9876543210ZYXWVUTS",
|
|
4558
|
+
"07": "CYDZE(F)G,H-I.J/K 0L1M2N3O4P5Q6R7S8T9U:VAWBX",
|
|
4559
|
+
"08": "FDUGB0-R A:W9C4S5EHQX)JKZTN.O6(71I/8,LVM2YP3",
|
|
4560
|
+
"09": "/5GK9YZHJI8N: 6LM7DFEQTURWVSA(,OPB).-C03X421"
|
|
4561
|
+
};
|
|
4562
|
+
var PASS_37 = { "*": "*", ">": "+" };
|
|
4563
|
+
var PASS_40 = {
|
|
4564
|
+
"*": "*",
|
|
4565
|
+
"?": "?",
|
|
4566
|
+
"'": "'",
|
|
4567
|
+
"#": "#",
|
|
4568
|
+
_: "_"
|
|
4569
|
+
};
|
|
4570
|
+
function lookup(table, c) {
|
|
4571
|
+
const i = SWA_ALPHABET.indexOf(c);
|
|
4572
|
+
return i < 0 ? void 0 : table[i];
|
|
4573
|
+
}
|
|
4574
|
+
function plain(table, body, pass) {
|
|
4575
|
+
let out = "";
|
|
4576
|
+
for (const c of body) {
|
|
4577
|
+
if (c === "\n") out += "|";
|
|
4578
|
+
else out += lookup(table, c) ?? pass[c] ?? SWA_UNREAD;
|
|
4579
|
+
}
|
|
4580
|
+
return out;
|
|
4581
|
+
}
|
|
4582
|
+
function decodeSwaLabel37(body) {
|
|
4583
|
+
const b = body.replace(/\r/g, "");
|
|
4584
|
+
const table = SWA_LABEL_37_TABLES[b.substring(0, 2)];
|
|
4585
|
+
if (!table) return void 0;
|
|
4586
|
+
let nl = b.indexOf("\n");
|
|
4587
|
+
if (nl !== 7 && b.length > 7 && lookup(table, b[7]) === ",") nl = 7;
|
|
4588
|
+
if (nl < 0 || nl > 8) return void 0;
|
|
4589
|
+
let type = "";
|
|
4590
|
+
for (const c of b.substring(2, Math.min(nl, 7))) {
|
|
4591
|
+
type += lookup(table, c) ?? SWA_UNREAD;
|
|
4592
|
+
}
|
|
4593
|
+
return { type, text: plain(table, b.substring(nl + 1), PASS_37) };
|
|
4594
|
+
}
|
|
4595
|
+
function decodeSwaLabel40(body) {
|
|
4596
|
+
const b = body.replace(/\r/g, "");
|
|
4597
|
+
if (b.startsWith("POS01,")) {
|
|
4598
|
+
return { type: "POS01", text: b.trim() };
|
|
4599
|
+
}
|
|
4600
|
+
const code = b[5] === "," ? b.substring(6, 8) : "";
|
|
4601
|
+
if (code === "00") {
|
|
4602
|
+
return {
|
|
4603
|
+
type: b.substring(0, 5),
|
|
4604
|
+
text: b.substring(8).replace(/\n/g, "|")
|
|
4605
|
+
};
|
|
4606
|
+
}
|
|
4607
|
+
const table = SWA_LABEL_40_TABLES[code];
|
|
4608
|
+
if (!table) return void 0;
|
|
4609
|
+
return {
|
|
4610
|
+
type: b.substring(0, 5),
|
|
4611
|
+
text: plain(table, b.substring(8), PASS_40)
|
|
4612
|
+
};
|
|
4613
|
+
}
|
|
4614
|
+
var SWA_TYPES = {
|
|
4615
|
+
"37": /* @__PURE__ */ new Set([
|
|
4616
|
+
"ADV01",
|
|
4617
|
+
"CLB02",
|
|
4618
|
+
"DIV02",
|
|
4619
|
+
"DVC01",
|
|
4620
|
+
"ETA03",
|
|
4621
|
+
"FCM01",
|
|
4622
|
+
"FCR03",
|
|
4623
|
+
"FFD01",
|
|
4624
|
+
"FHD04",
|
|
4625
|
+
"FLI01",
|
|
4626
|
+
"FTD02",
|
|
4627
|
+
"GAM02",
|
|
4628
|
+
"GSR02",
|
|
4629
|
+
"HGD03",
|
|
4630
|
+
"HLD01",
|
|
4631
|
+
"INN03",
|
|
4632
|
+
"INR04",
|
|
4633
|
+
"MXR03",
|
|
4634
|
+
"OFF02",
|
|
4635
|
+
"OFP01",
|
|
4636
|
+
"ONN02",
|
|
4637
|
+
"OUT03",
|
|
4638
|
+
"PFR03",
|
|
4639
|
+
"PFR04",
|
|
4640
|
+
"PJS01",
|
|
4641
|
+
"PNS01",
|
|
4642
|
+
"POS01",
|
|
4643
|
+
"POS02",
|
|
4644
|
+
"PRM01",
|
|
4645
|
+
"RRR01",
|
|
4646
|
+
"RTG03",
|
|
4647
|
+
"RTG04",
|
|
4648
|
+
"RTG05",
|
|
4649
|
+
"TAR02",
|
|
4650
|
+
"TDM01",
|
|
4651
|
+
"TOD03",
|
|
4652
|
+
"TRB02",
|
|
4653
|
+
"TXI02",
|
|
4654
|
+
"VXR02"
|
|
4655
|
+
]),
|
|
4656
|
+
"40": /* @__PURE__ */ new Set([
|
|
4657
|
+
"ASR01",
|
|
4658
|
+
"DVP01",
|
|
4659
|
+
"FTX01",
|
|
4660
|
+
"GAR03",
|
|
4661
|
+
"GEN01",
|
|
4662
|
+
"PIC01",
|
|
4663
|
+
"POS01",
|
|
4664
|
+
"WFC01"
|
|
4665
|
+
])
|
|
4666
|
+
};
|
|
4667
|
+
function isSwaType(type, label) {
|
|
4668
|
+
return SWA_TYPES[label].has(type);
|
|
4669
|
+
}
|
|
4670
|
+
|
|
4671
|
+
// lib/utils/swa_fields.ts
|
|
4672
|
+
var APT = "(?:[A-Z]{4}| {4}|)";
|
|
4673
|
+
var LAT = "(?:[NS] ?\\d{1,2}\\.\\d{3}|-{4}\\.-{3}|)";
|
|
4674
|
+
var LON = "(?:[EW] ?\\d{1,3}\\.\\d{3}|-{4}\\.-{3}|)";
|
|
4675
|
+
var T4 = "(?:\\d{4}|\\*{4}|-{4})";
|
|
4676
|
+
var FOB = "(?: ?\\d{1,2}\\.\\d|\\*\\*\\.\\*)";
|
|
4677
|
+
var INT = "(?: *-? *\\d+| *|-+|\\*+)";
|
|
4678
|
+
var MACH = "\\.\\d{3}";
|
|
4679
|
+
var HMS = "\\d{6}";
|
|
4680
|
+
var OC = "[OC]";
|
|
4681
|
+
var POS = [
|
|
4682
|
+
APT,
|
|
4683
|
+
APT,
|
|
4684
|
+
LAT,
|
|
4685
|
+
LON,
|
|
4686
|
+
INT,
|
|
4687
|
+
INT,
|
|
4688
|
+
INT,
|
|
4689
|
+
MACH,
|
|
4690
|
+
FOB,
|
|
4691
|
+
T4,
|
|
4692
|
+
INT,
|
|
4693
|
+
INT,
|
|
4694
|
+
INT,
|
|
4695
|
+
INT
|
|
4696
|
+
];
|
|
4697
|
+
var ASR = " *-?\\d+(?:\\.[\\d-])?|XX\\.X";
|
|
4698
|
+
var SWA_LAYOUTS = {
|
|
4699
|
+
ASR01: [[ASR, ASR, ASR, ASR, ASR, ASR, ASR, ASR, "", ""]],
|
|
4700
|
+
CLB02: [[APT, APT, LAT, "", LON, FOB, T4]],
|
|
4701
|
+
ETA03: [[APT, APT, T4, FOB, LAT, LON]],
|
|
4702
|
+
FCM01: [["L[\\d-]", "R[\\d-]", "A[\\d-]", "B[\\d-]", "\\d+", T4]],
|
|
4703
|
+
FHD04: [
|
|
4704
|
+
[
|
|
4705
|
+
...POS,
|
|
4706
|
+
"(?:OUT|OFF|ON|IN|RET IN)",
|
|
4707
|
+
"X",
|
|
4708
|
+
INT,
|
|
4709
|
+
" *\\d*",
|
|
4710
|
+
HMS,
|
|
4711
|
+
"(?:\\d{6}|-{6})",
|
|
4712
|
+
"\\d{5}"
|
|
4713
|
+
]
|
|
4714
|
+
],
|
|
4715
|
+
FLI01: [[APT, APT, T4, FOB, LAT, LON]],
|
|
4716
|
+
GAM02: [[APT, APT, T4, LAT, LON]],
|
|
4717
|
+
GAR03: [
|
|
4718
|
+
[
|
|
4719
|
+
"[A-Z0-9]{1,4} *",
|
|
4720
|
+
"[YN]",
|
|
4721
|
+
"[YN]",
|
|
4722
|
+
"[YN]",
|
|
4723
|
+
"[YN]",
|
|
4724
|
+
"[YN]",
|
|
4725
|
+
"(?:1[23]\\d\\.\\d{1,3}|999\\.999)",
|
|
4726
|
+
"",
|
|
4727
|
+
""
|
|
4728
|
+
]
|
|
4729
|
+
],
|
|
4730
|
+
HGD03: [[...POS, INT]],
|
|
4731
|
+
INN03: [[APT, APT, T4, T4, FOB, OC, OC, OC, OC]],
|
|
4732
|
+
INR04: [[APT, APT, T4, T4, FOB, LAT, LON]],
|
|
4733
|
+
OUT03: [[APT, APT, T4, FOB, FOB, T4]],
|
|
4734
|
+
POS01: [
|
|
4735
|
+
[...POS, INT],
|
|
4736
|
+
[...POS, INT, HMS]
|
|
4737
|
+
],
|
|
4738
|
+
POS02: [[...POS, INT, HMS]],
|
|
4739
|
+
RTG04: [[APT, APT, T4, T4, T4, FOB, OC, OC, OC, OC]],
|
|
4740
|
+
RTG05: [[APT, APT, T4, T4, T4, FOB, OC, OC, OC, OC]],
|
|
4741
|
+
TDM01: [[APT, APT, LAT, LON, "(?:L1|L2|CR|SV)", OC, T4, HMS]],
|
|
4742
|
+
TXI02: [[APT, APT, T4, FOB]],
|
|
4743
|
+
VXR02: [["[A-Z]{3}"]]
|
|
4744
|
+
};
|
|
4745
|
+
var SWA_PREFIX_LAYOUTS = {
|
|
4746
|
+
MXR03: [APT, "(?:\\d{4}|)", "[0-3]"]
|
|
4747
|
+
};
|
|
4748
|
+
function swaFields(text) {
|
|
4749
|
+
return text.replace(/\|/g, ",").split(",");
|
|
4750
|
+
}
|
|
4751
|
+
function swaMatchesLayout(fields, layouts) {
|
|
4752
|
+
return layouts.some(
|
|
4753
|
+
(layout) => layout.length === fields.length && layout.every((rx, i) => new RegExp(`^(?:${rx})$`).test(fields[i]))
|
|
4754
|
+
);
|
|
4755
|
+
}
|
|
4756
|
+
var SwaFieldWriter = class {
|
|
4757
|
+
constructor(decodeResult, fields) {
|
|
4758
|
+
this.decodeResult = decodeResult;
|
|
4759
|
+
this.fields = fields;
|
|
4760
|
+
}
|
|
4761
|
+
decodeResult;
|
|
4762
|
+
fields;
|
|
4763
|
+
used = /* @__PURE__ */ new Set();
|
|
4764
|
+
take(i) {
|
|
4765
|
+
this.used.add(i);
|
|
4766
|
+
return this.fields[i] ?? "";
|
|
4767
|
+
}
|
|
4768
|
+
/** A field with no specific ResultFormatter helper; `key` is its name in `raw`. */
|
|
4769
|
+
item(i, key, code, label, value) {
|
|
4770
|
+
this.used.add(i);
|
|
4771
|
+
ResultFormatter.raw(this.decodeResult, key, code, label, value);
|
|
4772
|
+
}
|
|
4773
|
+
/** Marks a field as read without writing it (it was written together with another). */
|
|
4774
|
+
use(i) {
|
|
4775
|
+
return this.take(i);
|
|
4776
|
+
}
|
|
4777
|
+
departure(i) {
|
|
4778
|
+
const v = this.take(i);
|
|
4779
|
+
if (/^[A-Z]{4}$/.test(v))
|
|
4780
|
+
ResultFormatter.departureAirport(this.decodeResult, v);
|
|
4781
|
+
}
|
|
4782
|
+
arrival(i) {
|
|
4783
|
+
const v = this.take(i);
|
|
4784
|
+
if (/^[A-Z]{4}$/.test(v))
|
|
4785
|
+
ResultFormatter.arrivalAirport(this.decodeResult, v);
|
|
4786
|
+
}
|
|
4787
|
+
/**
|
|
4788
|
+
* Writes the position when both coordinates are present and in range. Otherwise the
|
|
4789
|
+
* placeholders are consumed and any coordinate that was sent stays for `remaining`.
|
|
4790
|
+
*/
|
|
4791
|
+
position(latIndex, lonIndex) {
|
|
4792
|
+
const lat = this.fields[latIndex] ?? "";
|
|
4793
|
+
const lon = this.fields[lonIndex] ?? "";
|
|
4794
|
+
const latitude = /^[NS] ?\d/.test(lat) ? CoordinateUtils.getDirection(lat) * Number(lat.substring(1).trim()) : NaN;
|
|
4795
|
+
const longitude = /^[EW] ?\d/.test(lon) ? CoordinateUtils.getDirection(lon) * Number(lon.substring(1).trim()) : NaN;
|
|
4796
|
+
if (Math.abs(latitude) <= 90 && Math.abs(longitude) <= 180) {
|
|
4797
|
+
this.used.add(latIndex);
|
|
4798
|
+
this.used.add(lonIndex);
|
|
4799
|
+
ResultFormatter.position(this.decodeResult, { latitude, longitude });
|
|
4800
|
+
return;
|
|
4801
|
+
}
|
|
4802
|
+
if (!/^[NS] ?\d/.test(lat)) this.used.add(latIndex);
|
|
4803
|
+
if (!/^[EW] ?\d/.test(lon)) this.used.add(lonIndex);
|
|
4804
|
+
}
|
|
4805
|
+
/** A whole number, or undefined for a placeholder. */
|
|
4806
|
+
int(i) {
|
|
4807
|
+
const v = this.take(i).replace(/ /g, "");
|
|
4808
|
+
return /^-?\d+$/.test(v) ? Number(v) : void 0;
|
|
4809
|
+
}
|
|
4810
|
+
altitude(i) {
|
|
4811
|
+
const v = this.int(i);
|
|
4812
|
+
if (v !== void 0) ResultFormatter.altitude(this.decodeResult, v);
|
|
4813
|
+
}
|
|
4814
|
+
/** Fuel on board, sent in thousands of pounds; written in pounds. */
|
|
4815
|
+
fuel(i) {
|
|
4816
|
+
const v = this.take(i).trim();
|
|
4817
|
+
if (/^\d+\.\d$/.test(v)) {
|
|
4818
|
+
ResultFormatter.currentFuel(
|
|
4819
|
+
this.decodeResult,
|
|
4820
|
+
Math.round(Number(v) * 1e3)
|
|
4821
|
+
);
|
|
4822
|
+
}
|
|
4823
|
+
}
|
|
4824
|
+
/**
|
|
4825
|
+
* HHMM or HHMMSS as seconds of the day. A placeholder is consumed; a time out of range is
|
|
4826
|
+
* left for `remaining`.
|
|
4827
|
+
*/
|
|
4828
|
+
tod(i) {
|
|
4829
|
+
const v = this.fields[i] ?? "";
|
|
4830
|
+
if (/^(?:[01]\d|2[0-3])[0-5]\d(?:[0-5]\d)?$/.test(v)) {
|
|
4831
|
+
this.used.add(i);
|
|
4832
|
+
return DateTimeUtils.convertHHMMSSToTod(v);
|
|
4833
|
+
}
|
|
4834
|
+
if (!/^\d+$/.test(v)) this.used.add(i);
|
|
4835
|
+
return void 0;
|
|
4836
|
+
}
|
|
4837
|
+
/** Writes a time through a ResultFormatter helper such as `out`, `in` or `timestamp`. */
|
|
4838
|
+
time(i, write) {
|
|
4839
|
+
const t = this.tod(i);
|
|
4840
|
+
if (t !== void 0) write(this.decodeResult, t);
|
|
4841
|
+
}
|
|
4842
|
+
/** A time with no ResultFormatter helper, written as HH:MM:SS. */
|
|
4843
|
+
timeItem(i, key, code, label) {
|
|
4844
|
+
const t = this.tod(i);
|
|
4845
|
+
if (t !== void 0) {
|
|
4846
|
+
this.item(i, key, code, label, DateTimeUtils.timestampToString(t));
|
|
4847
|
+
}
|
|
4848
|
+
}
|
|
4849
|
+
eta(i) {
|
|
4850
|
+
this.time(i, (r, t) => ResultFormatter.eta(r, t));
|
|
4851
|
+
}
|
|
4852
|
+
/** Fields not written above, non-empty, to `remaining`. */
|
|
4853
|
+
finish() {
|
|
4854
|
+
const rest = this.fields.filter(
|
|
4855
|
+
(v, i) => !this.used.has(i) && v.trim() !== ""
|
|
4856
|
+
);
|
|
4857
|
+
if (rest.length > 0) ResultFormatter.unknownArr(this.decodeResult, rest);
|
|
4858
|
+
return rest.length;
|
|
4859
|
+
}
|
|
4860
|
+
};
|
|
4861
|
+
|
|
4862
|
+
// lib/plugins/Label_37_SWA.ts
|
|
4863
|
+
var DESCRIPTIONS = {
|
|
4864
|
+
ADV01: "Ride Conditions Report",
|
|
4865
|
+
CLB02: "Climb Report",
|
|
4866
|
+
DVC01: "Divert Plan (Crew Copy)",
|
|
4867
|
+
ETA03: "ETA Report",
|
|
4868
|
+
FCM01: "Engine and Fuel State",
|
|
4869
|
+
FCR03: "Runway Condition Report",
|
|
4870
|
+
FHD04: "Frequency Handoff Report",
|
|
4871
|
+
FLI01: "Flight Initialization",
|
|
4872
|
+
FTD02: "Free Text to Dispatch",
|
|
4873
|
+
GAM02: "Gate Assignment Request",
|
|
4874
|
+
HGD03: "HowGozit Report",
|
|
4875
|
+
HLD01: "Holding Report",
|
|
4876
|
+
INN03: "In Report",
|
|
4877
|
+
INR04: "In Range Report",
|
|
4878
|
+
MXR03: "Maintenance Report",
|
|
4879
|
+
OFF02: "Off Report",
|
|
4880
|
+
ONN02: "On Report",
|
|
4881
|
+
OUT03: "Out Report",
|
|
4882
|
+
PFR03: "Post Flight Report",
|
|
4883
|
+
POS01: "Position Report",
|
|
4884
|
+
POS02: "Position Report",
|
|
4885
|
+
RRR01: "Reroute Report",
|
|
4886
|
+
RTG04: "Return to Gate Report",
|
|
4887
|
+
RTG05: "Return to Gate Report",
|
|
4888
|
+
TDM01: "Door Report",
|
|
4889
|
+
TRB02: "Turbulence Report",
|
|
4890
|
+
TXI02: "Taxi Report",
|
|
4891
|
+
VXR02: "Voice Call Request"
|
|
4892
|
+
};
|
|
4893
|
+
var DOORS = {
|
|
4894
|
+
L1: "L1 (forward entry)",
|
|
4895
|
+
L2: "L2 (aft entry)",
|
|
4896
|
+
CR: "Cargo",
|
|
4897
|
+
SV: "Service"
|
|
4898
|
+
};
|
|
4899
|
+
var MXR_CODES = {
|
|
4900
|
+
"0": "Nothing to report",
|
|
4901
|
+
"1": "Status option",
|
|
4902
|
+
"2": "Category and text",
|
|
4903
|
+
"3": "Free text"
|
|
4904
|
+
};
|
|
4905
|
+
var Label_37_SWA = class extends DecoderPlugin {
|
|
4906
|
+
name = "label-37-swa";
|
|
4907
|
+
qualifiers() {
|
|
4908
|
+
return {
|
|
4909
|
+
labels: ["37"],
|
|
4910
|
+
preambles: ["01", "02", "03", "04", "05", "06", "07", "08", "09"]
|
|
4911
|
+
};
|
|
4912
|
+
}
|
|
4913
|
+
decode(message, options = {}) {
|
|
4914
|
+
const decodeResult = this.defaultResult();
|
|
4915
|
+
decodeResult.decoder.name = this.name;
|
|
4916
|
+
decodeResult.message = message;
|
|
4917
|
+
const d = decodeSwaLabel37(message.text);
|
|
4918
|
+
if (!d || !isSwaType(d.type, "37")) {
|
|
4919
|
+
if (options.debug) {
|
|
4920
|
+
console.log(`Decoder: Unknown 37 message: ${message.text}`);
|
|
4921
|
+
}
|
|
4922
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
4923
|
+
decodeResult.formatted.description = "Unknown";
|
|
4924
|
+
return decodeResult;
|
|
4925
|
+
}
|
|
4926
|
+
decodeResult.decoded = true;
|
|
4927
|
+
decodeResult.formatted.description = DESCRIPTIONS[d.type] ?? "Southwest Message";
|
|
4928
|
+
decodeResult.raw.preamble = d.type;
|
|
4929
|
+
const text = d.text;
|
|
4930
|
+
const fields = swaFields(text);
|
|
4931
|
+
const layouts = SWA_LAYOUTS[d.type];
|
|
4932
|
+
const prefix = SWA_PREFIX_LAYOUTS[d.type];
|
|
4933
|
+
const clean = !text.includes(SWA_UNREAD);
|
|
4934
|
+
if (clean && layouts && swaMatchesLayout(fields, layouts)) {
|
|
4935
|
+
const rest = this.writeFields(decodeResult, d.type, fields);
|
|
4936
|
+
decodeResult.decoder.decodeLevel = rest === 0 ? "full" : "partial";
|
|
4937
|
+
return decodeResult;
|
|
4938
|
+
}
|
|
4939
|
+
if (clean && prefix && swaMatchesLayout(fields.slice(0, prefix.length), [prefix])) {
|
|
4940
|
+
const rest = this.writeMaintenance(decodeResult, text, fields);
|
|
4941
|
+
decodeResult.decoder.decodeLevel = rest === 0 ? "full" : "partial";
|
|
4942
|
+
return decodeResult;
|
|
4943
|
+
}
|
|
4944
|
+
if (clean && !layouts && !prefix) {
|
|
4945
|
+
const lines = text.split("|");
|
|
4946
|
+
const route = lines[0].match(/^([A-Z]{4}),([A-Z]{4})$/);
|
|
4947
|
+
if (route && d.type === "FTD02") {
|
|
4948
|
+
ResultFormatter.departureAirport(decodeResult, route[1]);
|
|
4949
|
+
ResultFormatter.arrivalAirport(decodeResult, route[2]);
|
|
4950
|
+
lines.shift();
|
|
4951
|
+
}
|
|
4952
|
+
ResultFormatter.text(decodeResult, lines.join("\n"));
|
|
4953
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
4954
|
+
return decodeResult;
|
|
4955
|
+
}
|
|
4956
|
+
ResultFormatter.text(decodeResult, text.split("|").join("\n"));
|
|
4957
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
4958
|
+
return decodeResult;
|
|
4959
|
+
}
|
|
4960
|
+
/** Writes a laid-out type's fields; returns how many went to `remaining`. */
|
|
4961
|
+
writeFields(decodeResult, type, fields) {
|
|
4962
|
+
const w = new SwaFieldWriter(decodeResult, fields);
|
|
4963
|
+
switch (type) {
|
|
4964
|
+
case "POS01":
|
|
4965
|
+
case "POS02":
|
|
4966
|
+
case "HGD03":
|
|
4967
|
+
case "FHD04": {
|
|
4968
|
+
w.departure(0);
|
|
4969
|
+
w.arrival(1);
|
|
4970
|
+
w.position(2, 3);
|
|
4971
|
+
w.altitude(4);
|
|
4972
|
+
const ias = w.int(5);
|
|
4973
|
+
if (ias !== void 0)
|
|
4974
|
+
ResultFormatter.indicatedAirspeed(decodeResult, ias);
|
|
4975
|
+
const tas = w.int(6);
|
|
4976
|
+
if (tas !== void 0) ResultFormatter.airspeed(decodeResult, tas);
|
|
4977
|
+
ResultFormatter.mach(decodeResult, Number(w.use(7)));
|
|
4978
|
+
w.fuel(8);
|
|
4979
|
+
w.eta(9);
|
|
4980
|
+
const track = w.int(10);
|
|
4981
|
+
if (track !== void 0) ResultFormatter.track(decodeResult, track);
|
|
4982
|
+
ResultFormatter.wind(decodeResult, w.int(11), w.int(12));
|
|
4983
|
+
const sat = w.int(13);
|
|
4984
|
+
if (sat !== void 0)
|
|
4985
|
+
ResultFormatter.temperature(decodeResult, `${sat}`);
|
|
4986
|
+
const gwIndex = type === "FHD04" ? 16 : 14;
|
|
4987
|
+
const gw = w.int(gwIndex);
|
|
4988
|
+
if (gw !== void 0) ResultFormatter.grossWeight(decodeResult, gw);
|
|
4989
|
+
if (type !== "FHD04" && fields.length === 16) {
|
|
4990
|
+
w.time(15, (r, t) => ResultFormatter.timestamp(r, t));
|
|
4991
|
+
}
|
|
4992
|
+
if (type === "FHD04") {
|
|
4993
|
+
w.item(14, "event", "EVT", "Event", fields[14]);
|
|
4994
|
+
w.use(15);
|
|
4995
|
+
const freq = w.use(19);
|
|
4996
|
+
if (/^1\d{5}$/.test(freq)) {
|
|
4997
|
+
w.item(
|
|
4998
|
+
19,
|
|
4999
|
+
"frequency",
|
|
5000
|
+
"FREQ",
|
|
5001
|
+
"ACARS Frequency",
|
|
5002
|
+
`${freq.substring(0, 3)}.${freq.substring(3)} MHz`
|
|
5003
|
+
);
|
|
5004
|
+
}
|
|
5005
|
+
}
|
|
5006
|
+
break;
|
|
5007
|
+
}
|
|
5008
|
+
case "GAM02":
|
|
5009
|
+
w.departure(0);
|
|
5010
|
+
w.arrival(1);
|
|
5011
|
+
w.eta(2);
|
|
5012
|
+
w.position(3, 4);
|
|
5013
|
+
break;
|
|
5014
|
+
case "CLB02":
|
|
5015
|
+
w.departure(0);
|
|
5016
|
+
w.arrival(1);
|
|
5017
|
+
w.position(2, 4);
|
|
5018
|
+
w.fuel(5);
|
|
5019
|
+
w.eta(6);
|
|
5020
|
+
break;
|
|
5021
|
+
case "ETA03":
|
|
5022
|
+
w.departure(0);
|
|
5023
|
+
w.arrival(1);
|
|
5024
|
+
w.eta(2);
|
|
5025
|
+
w.fuel(3);
|
|
5026
|
+
w.position(4, 5);
|
|
5027
|
+
break;
|
|
5028
|
+
case "INR04":
|
|
5029
|
+
w.departure(0);
|
|
5030
|
+
w.arrival(1);
|
|
5031
|
+
w.eta(2);
|
|
5032
|
+
w.time(3, (r, t) => ResultFormatter.timestamp(r, t));
|
|
5033
|
+
w.fuel(4);
|
|
5034
|
+
w.position(5, 6);
|
|
5035
|
+
break;
|
|
5036
|
+
case "FLI01":
|
|
5037
|
+
w.departure(0);
|
|
5038
|
+
w.arrival(1);
|
|
5039
|
+
w.time(2, (r, t) => ResultFormatter.timestamp(r, t));
|
|
5040
|
+
w.fuel(3);
|
|
5041
|
+
w.position(4, 5);
|
|
5042
|
+
break;
|
|
5043
|
+
case "OUT03":
|
|
5044
|
+
w.departure(0);
|
|
5045
|
+
w.arrival(1);
|
|
5046
|
+
w.time(2, (r, t) => ResultFormatter.out(r, t));
|
|
5047
|
+
w.fuel(3);
|
|
5048
|
+
w.timeItem(5, "front_door_closed_time", "L1CLS", "Front Door Closed");
|
|
5049
|
+
break;
|
|
5050
|
+
case "TXI02":
|
|
5051
|
+
w.departure(0);
|
|
5052
|
+
w.arrival(1);
|
|
5053
|
+
w.timeItem(2, "taxi_start_time", "TAXI", "Taxi Start Time");
|
|
5054
|
+
w.fuel(3);
|
|
5055
|
+
break;
|
|
5056
|
+
case "INN03":
|
|
5057
|
+
w.departure(0);
|
|
5058
|
+
w.arrival(1);
|
|
5059
|
+
w.time(2, (r, t) => ResultFormatter.in(r, t));
|
|
5060
|
+
w.timeItem(3, "front_door_open_time", "L1OPN", "Front Door Opened");
|
|
5061
|
+
w.fuel(4);
|
|
5062
|
+
break;
|
|
5063
|
+
case "RTG04":
|
|
5064
|
+
case "RTG05":
|
|
5065
|
+
w.departure(0);
|
|
5066
|
+
w.arrival(1);
|
|
5067
|
+
w.time(2, (r, t) => ResultFormatter.out(r, t));
|
|
5068
|
+
w.time(3, (r, t) => ResultFormatter.in(r, t));
|
|
5069
|
+
w.time(4, (r, t) => ResultFormatter.timestamp(r, t));
|
|
5070
|
+
w.fuel(5);
|
|
5071
|
+
break;
|
|
5072
|
+
case "TDM01": {
|
|
5073
|
+
w.departure(0);
|
|
5074
|
+
w.arrival(1);
|
|
5075
|
+
w.position(2, 3);
|
|
5076
|
+
ResultFormatter.door_event(
|
|
5077
|
+
decodeResult,
|
|
5078
|
+
DOORS[w.use(4)],
|
|
5079
|
+
w.use(5) === "O" ? "open" : "closed"
|
|
5080
|
+
);
|
|
5081
|
+
const md = fields[6];
|
|
5082
|
+
if (/^(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])$/.test(md)) {
|
|
5083
|
+
w.use(6);
|
|
5084
|
+
ResultFormatter.month(decodeResult, Number(md.substring(0, 2)));
|
|
5085
|
+
ResultFormatter.day(decodeResult, Number(md.substring(2)));
|
|
5086
|
+
} else if (!/^\d+$/.test(md)) {
|
|
5087
|
+
w.use(6);
|
|
5088
|
+
}
|
|
5089
|
+
w.time(7, (r, t) => ResultFormatter.timestamp(r, t));
|
|
5090
|
+
break;
|
|
5091
|
+
}
|
|
5092
|
+
case "FCM01": {
|
|
5093
|
+
const names = {
|
|
5094
|
+
L: "Left Engine",
|
|
5095
|
+
R: "Right Engine",
|
|
5096
|
+
A: "APU"
|
|
5097
|
+
};
|
|
5098
|
+
for (let i = 0; i < 3; i++) {
|
|
5099
|
+
const v = fields[i];
|
|
5100
|
+
if (v[1] === "0" || v[1] === "1") {
|
|
5101
|
+
w.item(
|
|
5102
|
+
i,
|
|
5103
|
+
`${names[v[0]].toLowerCase().replace(" ", "_")}`,
|
|
5104
|
+
v[0],
|
|
5105
|
+
names[v[0]],
|
|
5106
|
+
v[1] === "1" ? "running" : "off"
|
|
5107
|
+
);
|
|
5108
|
+
}
|
|
5109
|
+
}
|
|
5110
|
+
ResultFormatter.currentFuel(decodeResult, Number(w.use(4)) * 100);
|
|
5111
|
+
w.time(5, (r, t) => ResultFormatter.timestamp(r, t));
|
|
5112
|
+
break;
|
|
5113
|
+
}
|
|
5114
|
+
case "VXR02":
|
|
5115
|
+
w.item(0, "station_iata", "STN", "Station", fields[0]);
|
|
5116
|
+
break;
|
|
5117
|
+
}
|
|
5118
|
+
return w.finish();
|
|
5119
|
+
}
|
|
5120
|
+
/** MXR03: destination, ETA, code, then the category and text; returns how many header
|
|
5121
|
+
* fields went to `remaining`. */
|
|
5122
|
+
writeMaintenance(decodeResult, text, fields) {
|
|
5123
|
+
const w = new SwaFieldWriter(decodeResult, fields.slice(0, 3));
|
|
5124
|
+
w.arrival(0);
|
|
5125
|
+
w.eta(1);
|
|
5126
|
+
w.item(
|
|
5127
|
+
2,
|
|
5128
|
+
"maintenance_code",
|
|
5129
|
+
"MXCODE",
|
|
5130
|
+
"Report Code",
|
|
5131
|
+
`${fields[2]} (${MXR_CODES[fields[2]]})`
|
|
5132
|
+
);
|
|
5133
|
+
const header = text.match(/^[^,|]*[,|][^,|]*[,|][^,|]*[,|]?/);
|
|
5134
|
+
const body = text.substring(header ? header[0].length : 0);
|
|
5135
|
+
if (body.trim() !== "") {
|
|
5136
|
+
ResultFormatter.text(decodeResult, body.split("|").join("\n"));
|
|
5137
|
+
}
|
|
5138
|
+
return w.finish();
|
|
5139
|
+
}
|
|
5140
|
+
};
|
|
5141
|
+
|
|
5142
|
+
// lib/plugins/Label_40_SWA.ts
|
|
5143
|
+
var DESCRIPTIONS2 = {
|
|
5144
|
+
ASR01: "Approach Stability Report",
|
|
5145
|
+
DVP01: "Divert Plan",
|
|
5146
|
+
FTX01: "Dispatch Free Text",
|
|
5147
|
+
GAR03: "Gate Assignment Response",
|
|
5148
|
+
GEN01: "Company Message",
|
|
5149
|
+
PIC01: "Part 117 Duty Extension Request",
|
|
5150
|
+
POS01: "Position Report Request",
|
|
5151
|
+
WFC01: "Field Condition Report"
|
|
5152
|
+
};
|
|
5153
|
+
var ASR01 = [
|
|
5154
|
+
[
|
|
5155
|
+
"reverser_distance",
|
|
5156
|
+
"REVDIST",
|
|
5157
|
+
"Threshold to Thrust Reverser Deployment (feet)"
|
|
5158
|
+
],
|
|
5159
|
+
["max_ias", "MAXIAS", "Highest IAS, 1000 feet to Touchdown (knots)"],
|
|
5160
|
+
["min_ias", "MINIAS", "Lowest IAS, to Touchdown (knots)"],
|
|
5161
|
+
["touchdown_distance", "TDDIST", "Threshold to Touchdown (feet)"],
|
|
5162
|
+
["glideslope_above", "GSHIGH", "Largest Deviation Above Glideslope (dots)"],
|
|
5163
|
+
["glideslope_below", "GSLOW", "Largest Deviation Below Glideslope (dots)"],
|
|
5164
|
+
["max_pitch", "MAXPITCH", "Highest Pitch, Flare and Landing (degrees)"],
|
|
5165
|
+
["tailstrike_pitch", "TSPITCH", "Tail Strike Pitch Limit (degrees)"]
|
|
5166
|
+
];
|
|
5167
|
+
var Label_40_SWA = class extends DecoderPlugin {
|
|
5168
|
+
name = "label-40-swa";
|
|
5169
|
+
qualifiers() {
|
|
5170
|
+
return {
|
|
5171
|
+
labels: ["40"]
|
|
5172
|
+
};
|
|
5173
|
+
}
|
|
5174
|
+
decode(message, options = {}) {
|
|
5175
|
+
const decodeResult = this.defaultResult();
|
|
5176
|
+
decodeResult.decoder.name = this.name;
|
|
5177
|
+
decodeResult.message = message;
|
|
5178
|
+
const d = decodeSwaLabel40(message.text);
|
|
5179
|
+
if (!d || !isSwaType(d.type, "40")) {
|
|
5180
|
+
if (options.debug) {
|
|
5181
|
+
console.log(`Decoder: Unknown 40 message: ${message.text}`);
|
|
5182
|
+
}
|
|
5183
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
5184
|
+
decodeResult.formatted.description = "Unknown";
|
|
5185
|
+
return decodeResult;
|
|
5186
|
+
}
|
|
5187
|
+
decodeResult.decoded = true;
|
|
5188
|
+
decodeResult.formatted.description = DESCRIPTIONS2[d.type] ?? "Southwest Message";
|
|
5189
|
+
decodeResult.raw.preamble = d.type;
|
|
5190
|
+
if (d.type === "POS01") {
|
|
5191
|
+
const m = d.text.match(/^POS01,Y,(\d{2})$/);
|
|
5192
|
+
if (m) {
|
|
5193
|
+
ResultFormatter.raw(
|
|
5194
|
+
decodeResult,
|
|
5195
|
+
"report_interval",
|
|
5196
|
+
"RPTINT",
|
|
5197
|
+
"Position Report Interval",
|
|
5198
|
+
`${Number(m[1])} minutes`,
|
|
5199
|
+
Number(m[1])
|
|
5200
|
+
);
|
|
5201
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5202
|
+
} else {
|
|
5203
|
+
ResultFormatter.unknown(decodeResult, d.text);
|
|
5204
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5205
|
+
}
|
|
5206
|
+
return decodeResult;
|
|
5207
|
+
}
|
|
5208
|
+
const text = d.text;
|
|
5209
|
+
const fields = swaFields(text);
|
|
5210
|
+
const layouts = SWA_LAYOUTS[d.type];
|
|
5211
|
+
const clean = !text.includes(SWA_UNREAD);
|
|
5212
|
+
if (clean && layouts && swaMatchesLayout(fields, layouts)) {
|
|
5213
|
+
const w = new SwaFieldWriter(decodeResult, fields);
|
|
5214
|
+
if (d.type === "ASR01") {
|
|
5215
|
+
ASR01.forEach(([key, code, label], i) => {
|
|
5216
|
+
const v = fields[i].trim();
|
|
5217
|
+
if (v !== "XX.X") w.item(i, key, code, label, v);
|
|
5218
|
+
else w.use(i);
|
|
5219
|
+
});
|
|
5220
|
+
} else if (d.type === "GAR03") {
|
|
5221
|
+
ResultFormatter.arrivalGate(decodeResult, w.use(0).trim());
|
|
5222
|
+
if (fields[6] !== "999.999") {
|
|
5223
|
+
w.item(
|
|
5224
|
+
6,
|
|
5225
|
+
"ramp_frequency",
|
|
5226
|
+
"RAMPFREQ",
|
|
5227
|
+
"Ramp Frequency",
|
|
5228
|
+
`${fields[6]} MHz`
|
|
5229
|
+
);
|
|
5230
|
+
} else {
|
|
5231
|
+
w.use(6);
|
|
5232
|
+
}
|
|
5233
|
+
}
|
|
5234
|
+
const rest = w.finish();
|
|
5235
|
+
decodeResult.decoder.decodeLevel = rest === 0 ? "full" : "partial";
|
|
5236
|
+
return decodeResult;
|
|
5237
|
+
}
|
|
5238
|
+
ResultFormatter.text(decodeResult, text.split("|").join("\n"));
|
|
5239
|
+
decodeResult.decoder.decodeLevel = clean && !layouts ? "full" : "partial";
|
|
5240
|
+
return decodeResult;
|
|
5241
|
+
}
|
|
5242
|
+
};
|
|
5243
|
+
|
|
5244
|
+
// lib/plugins/Label_44_ETA.ts
|
|
5245
|
+
var Label_44_ETA = class extends DecoderPlugin {
|
|
5246
|
+
name = "label-44-eta";
|
|
5247
|
+
qualifiers() {
|
|
5248
|
+
return {
|
|
3776
5249
|
labels: ["44"],
|
|
3777
5250
|
preambles: ["00ETA01", "00ETA02", "00ETA03", "ETA01", "ETA02", "ETA03"]
|
|
3778
5251
|
};
|
|
@@ -4779,91 +6252,60 @@ var Label_ColonComma = class extends DecoderPlugin {
|
|
|
4779
6252
|
}
|
|
4780
6253
|
};
|
|
4781
6254
|
|
|
4782
|
-
// lib/plugins/
|
|
4783
|
-
var
|
|
4784
|
-
name = "label-
|
|
6255
|
+
// lib/plugins/Label_H1_76401.ts
|
|
6256
|
+
var Label_H1_76401 = class extends DecoderPlugin {
|
|
6257
|
+
name = "label-h1-76401";
|
|
4785
6258
|
qualifiers() {
|
|
4786
6259
|
return {
|
|
4787
|
-
labels: ["
|
|
4788
|
-
preambles: ["
|
|
6260
|
+
labels: ["H1"],
|
|
6261
|
+
preambles: ["76401\r\n"]
|
|
4789
6262
|
};
|
|
4790
6263
|
}
|
|
4791
6264
|
decode(message, options = {}) {
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
decodeResult.message = message;
|
|
4796
|
-
const parts = message.text.split(" ");
|
|
4797
|
-
if (parts[parts.length - 1] !== "Q") {
|
|
4798
|
-
decodeResult.remaining.text = message.text;
|
|
4799
|
-
decodeResult.decoded = false;
|
|
4800
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
6265
|
+
const decodeResult = this.initResult(message, "Position Report");
|
|
6266
|
+
const lines = message.text.split("\r\n");
|
|
6267
|
+
if (lines.length < 3) {
|
|
4801
6268
|
return decodeResult;
|
|
4802
6269
|
}
|
|
4803
|
-
|
|
4804
|
-
decodeResult.
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
const
|
|
4811
|
-
|
|
4812
|
-
|
|
6270
|
+
ResultFormatter.unknown(decodeResult, lines[0], "\r\n");
|
|
6271
|
+
ResultFormatter.unknown(decodeResult, lines[1].substring(0, 5), "\r\n");
|
|
6272
|
+
ResultFormatter.departureAirport(decodeResult, lines[1].substring(5, 9));
|
|
6273
|
+
ResultFormatter.arrivalAirport(decodeResult, lines[1].substring(9, 13));
|
|
6274
|
+
ResultFormatter.unknown(decodeResult, lines[1].substring(13), "");
|
|
6275
|
+
const waypoints = [];
|
|
6276
|
+
for (const line of lines.slice(2)) {
|
|
6277
|
+
const position = CoordinateUtils.decodeStringCoordinates(
|
|
6278
|
+
line.substring(0, 13)
|
|
6279
|
+
);
|
|
6280
|
+
if (position) {
|
|
6281
|
+
waypoints.push({
|
|
6282
|
+
name: line.substring(0, 13),
|
|
6283
|
+
latitude: position.latitude,
|
|
6284
|
+
longitude: position.longitude,
|
|
6285
|
+
time: DateTimeUtils.convertHHMMSSToTod(line.substring(13, 19))
|
|
6286
|
+
});
|
|
4813
6287
|
} else {
|
|
4814
|
-
|
|
6288
|
+
ResultFormatter.unknown(decodeResult, line.substring(0, 19), "");
|
|
4815
6289
|
}
|
|
6290
|
+
ResultFormatter.unknown(decodeResult, line.substring(19), "\r\n");
|
|
4816
6291
|
}
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
6292
|
+
ResultFormatter.route(decodeResult, { waypoints });
|
|
6293
|
+
if (waypoints.length > 0) {
|
|
6294
|
+
const lastWaypoint = waypoints[waypoints.length - 1];
|
|
6295
|
+
if (lastWaypoint.latitude !== void 0 && lastWaypoint.longitude !== void 0) {
|
|
6296
|
+
ResultFormatter.position(decodeResult, {
|
|
6297
|
+
latitude: lastWaypoint.latitude,
|
|
6298
|
+
longitude: lastWaypoint.longitude
|
|
6299
|
+
});
|
|
4822
6300
|
}
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
windData.push(wind);
|
|
4826
|
-
} else {
|
|
4827
|
-
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + part;
|
|
6301
|
+
if (lastWaypoint.time !== void 0) {
|
|
6302
|
+
ResultFormatter.timestamp(decodeResult, lastWaypoint.time);
|
|
4828
6303
|
}
|
|
4829
6304
|
}
|
|
4830
|
-
ResultFormatter.windData(decodeResult, windData);
|
|
4831
6305
|
decodeResult.decoded = true;
|
|
4832
|
-
decodeResult.decoder.decodeLevel =
|
|
6306
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
4833
6307
|
return decodeResult;
|
|
4834
6308
|
}
|
|
4835
|
-
parseWeatherReport(text) {
|
|
4836
|
-
const posString = text.substring(0, 13);
|
|
4837
|
-
const pos = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(posString);
|
|
4838
|
-
if (text.length !== 32 || !pos) {
|
|
4839
|
-
return null;
|
|
4840
|
-
}
|
|
4841
|
-
const tod = DateTimeUtils.convertHHMMSSToTod(text.substring(13, 17));
|
|
4842
|
-
const flightLevel = parseInt(text.substring(17, 20), 10);
|
|
4843
|
-
const tempSign = text[21] === "M" ? -1 : 1;
|
|
4844
|
-
const tempDegreesRaw = parseInt(text.substring(22, 25), 10);
|
|
4845
|
-
const tempDegrees = tempSign * (tempDegreesRaw / 10);
|
|
4846
|
-
const windDirection = parseInt(text.substring(25, 28), 10);
|
|
4847
|
-
const windSpeed = parseInt(text.substring(28, 31), 10);
|
|
4848
|
-
if (text[31] !== "G") {
|
|
4849
|
-
return null;
|
|
4850
|
-
}
|
|
4851
|
-
return {
|
|
4852
|
-
waypoint: {
|
|
4853
|
-
name: posString,
|
|
4854
|
-
latitude: pos.latitude,
|
|
4855
|
-
longitude: pos.longitude,
|
|
4856
|
-
time: tod
|
|
4857
|
-
},
|
|
4858
|
-
flightLevel,
|
|
4859
|
-
windDirection,
|
|
4860
|
-
windSpeed,
|
|
4861
|
-
temperature: {
|
|
4862
|
-
flightLevel,
|
|
4863
|
-
degreesC: tempDegrees
|
|
4864
|
-
}
|
|
4865
|
-
};
|
|
4866
|
-
}
|
|
4867
6309
|
};
|
|
4868
6310
|
|
|
4869
6311
|
// lib/plugins/Label_H1_ATIS.ts
|
|
@@ -5084,11 +6526,11 @@ var Label_H1_M_POS = class extends DecoderPlugin {
|
|
|
5084
6526
|
const timestamp = fields[2].trim();
|
|
5085
6527
|
if (timestamp.length === 6) {
|
|
5086
6528
|
const day = Number(timestamp.substring(0, 2));
|
|
5087
|
-
const
|
|
6529
|
+
const tod2 = DateTimeUtils.convertHHMMSSToTod(
|
|
5088
6530
|
timestamp.substring(2) + "00"
|
|
5089
6531
|
);
|
|
5090
6532
|
ResultFormatter.day(decodeResult, day);
|
|
5091
|
-
ResultFormatter.timestamp(decodeResult,
|
|
6533
|
+
ResultFormatter.timestamp(decodeResult, tod2);
|
|
5092
6534
|
}
|
|
5093
6535
|
const lat = parseFloat(fields[3].replace(/\s/g, ""));
|
|
5094
6536
|
const lon = parseFloat(fields[4].replace(/\s/g, ""));
|
|
@@ -5482,6 +6924,135 @@ var Label_H1_StarPOS = class extends DecoderPlugin {
|
|
|
5482
6924
|
}
|
|
5483
6925
|
};
|
|
5484
6926
|
|
|
6927
|
+
// lib/plugins/Label_H1_SWA_Track.ts
|
|
6928
|
+
var PHASES = {
|
|
6929
|
+
TO: "Takeoff",
|
|
6930
|
+
IC: "Initial Climb",
|
|
6931
|
+
CL: "Climb",
|
|
6932
|
+
CR: "Cruise",
|
|
6933
|
+
ER: "En Route",
|
|
6934
|
+
DC: "Descent",
|
|
6935
|
+
AP: "Approach",
|
|
6936
|
+
RO: "Rollout"
|
|
6937
|
+
};
|
|
6938
|
+
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]),$/;
|
|
6939
|
+
var Label_H1_SWA_Track = class extends DecoderPlugin {
|
|
6940
|
+
name = "label-h1-swa-track";
|
|
6941
|
+
qualifiers() {
|
|
6942
|
+
return {
|
|
6943
|
+
labels: ["H1"],
|
|
6944
|
+
preambles: ["++76502,", "++86501,", "#DFB++76502,", "#DFB++86501,"]
|
|
6945
|
+
};
|
|
6946
|
+
}
|
|
6947
|
+
decode(message, options = {}) {
|
|
6948
|
+
const decodeResult = this.initResult(message, "Track Report");
|
|
6949
|
+
const nl = message.text.includes("\r\n") ? "\r\n" : "\n";
|
|
6950
|
+
const lines = message.text.replace(/#DFB/g, "").split(/\r?\n/);
|
|
6951
|
+
const header = lines[0].replace(/^\+\+/, "").split(",");
|
|
6952
|
+
if (header.length !== 9 || !/^\d{6}$/.test(header[3])) {
|
|
6953
|
+
return this.failUnknown(decodeResult, message.text, options);
|
|
6954
|
+
}
|
|
6955
|
+
const unknown = [];
|
|
6956
|
+
if (/^N\w+$/.test(header[1])) {
|
|
6957
|
+
ResultFormatter.tail(decodeResult, header[1]);
|
|
6958
|
+
} else if (/^\d{1,4}$/.test(header[1])) {
|
|
6959
|
+
ResultFormatter.raw(
|
|
6960
|
+
decodeResult,
|
|
6961
|
+
"ship_number",
|
|
6962
|
+
"SHIP",
|
|
6963
|
+
"Ship Number",
|
|
6964
|
+
header[1]
|
|
6965
|
+
);
|
|
6966
|
+
} else if (header[1] !== "XXX") {
|
|
6967
|
+
unknown.push(header[1]);
|
|
6968
|
+
}
|
|
6969
|
+
ResultFormatter.raw(
|
|
6970
|
+
decodeResult,
|
|
6971
|
+
"aircraft_type",
|
|
6972
|
+
"ACTYPE",
|
|
6973
|
+
"Aircraft Type",
|
|
6974
|
+
header[2]
|
|
6975
|
+
);
|
|
6976
|
+
const d = header[3];
|
|
6977
|
+
ResultFormatter.raw(
|
|
6978
|
+
decodeResult,
|
|
6979
|
+
"report_date",
|
|
6980
|
+
"DATE",
|
|
6981
|
+
"Report Date",
|
|
6982
|
+
`20${d.slice(0, 2)}-${d.slice(2, 4)}-${d.slice(4, 6)}`
|
|
6983
|
+
);
|
|
6984
|
+
ResultFormatter.flightNumber(decodeResult, header[4]);
|
|
6985
|
+
ResultFormatter.departureAirport(decodeResult, header[5]);
|
|
6986
|
+
ResultFormatter.arrivalAirport(decodeResult, header[6]);
|
|
6987
|
+
if (/^\d{1,15}$/.test(header[7])) {
|
|
6988
|
+
ResultFormatter.raw(
|
|
6989
|
+
decodeResult,
|
|
6990
|
+
"leg_counter",
|
|
6991
|
+
"LEGS",
|
|
6992
|
+
"Leg Counter",
|
|
6993
|
+
`${Number(header[7])}`,
|
|
6994
|
+
Number(header[7])
|
|
6995
|
+
);
|
|
6996
|
+
} else {
|
|
6997
|
+
unknown.push(header[7]);
|
|
6998
|
+
}
|
|
6999
|
+
ResultFormatter.raw(
|
|
7000
|
+
decodeResult,
|
|
7001
|
+
"software_version",
|
|
7002
|
+
"SWVER",
|
|
7003
|
+
"Software Version",
|
|
7004
|
+
header[8]
|
|
7005
|
+
);
|
|
7006
|
+
if (unknown.length > 0) ResultFormatter.unknownArr(decodeResult, unknown);
|
|
7007
|
+
const count = lines[1]?.match(/^(\d+),?$/)?.[1];
|
|
7008
|
+
if (lines[1] !== void 0 && count === void 0) {
|
|
7009
|
+
ResultFormatter.unknown(decodeResult, lines[1], nl);
|
|
7010
|
+
}
|
|
7011
|
+
for (const line of lines.slice(2)) {
|
|
7012
|
+
if (line === "" || line === ":") continue;
|
|
7013
|
+
const m = line.match(POINT);
|
|
7014
|
+
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) {
|
|
7015
|
+
ResultFormatter.unknown(decodeResult, line, nl);
|
|
7016
|
+
continue;
|
|
7017
|
+
}
|
|
7018
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(
|
|
7019
|
+
`${m[1]}${m[2]}${m[3]}${m[4]}`
|
|
7020
|
+
);
|
|
7021
|
+
if (!position || Math.abs(position.latitude) > 90 || Math.abs(position.longitude) > 180) {
|
|
7022
|
+
ResultFormatter.unknown(decodeResult, line, nl);
|
|
7023
|
+
continue;
|
|
7024
|
+
}
|
|
7025
|
+
ResultFormatter.trackPoint(decodeResult, {
|
|
7026
|
+
name: `${m[1]}.${m[2]}${m[3]}.${m[4]}`,
|
|
7027
|
+
...position,
|
|
7028
|
+
day: Number(m[5]),
|
|
7029
|
+
time: Number(m[6]) * 3600 + Number(m[7]) * 60,
|
|
7030
|
+
altitude: Number(m[8]),
|
|
7031
|
+
// -00.0 is sent; keep it as 0
|
|
7032
|
+
temperature: Number(m[9]) || 0,
|
|
7033
|
+
windDirection: Number(m[10]),
|
|
7034
|
+
windSpeed: Number(m[11]),
|
|
7035
|
+
phase: PHASES[m[12]] ?? m[12],
|
|
7036
|
+
humiditySensor: m[14] === "1",
|
|
7037
|
+
...m[14] === "1" && Number(m[13]) > 0 ? { waterVapor: Number(m[13]) } : {}
|
|
7038
|
+
});
|
|
7039
|
+
}
|
|
7040
|
+
const points = decodeResult.raw.route?.waypoints ?? [];
|
|
7041
|
+
const last = points[points.length - 1];
|
|
7042
|
+
if (last) {
|
|
7043
|
+
ResultFormatter.position(decodeResult, {
|
|
7044
|
+
latitude: last.latitude,
|
|
7045
|
+
longitude: last.longitude
|
|
7046
|
+
});
|
|
7047
|
+
ResultFormatter.altitude(decodeResult, last.altitude);
|
|
7048
|
+
ResultFormatter.timestamp(decodeResult, last.time);
|
|
7049
|
+
}
|
|
7050
|
+
const counted = count !== void 0 && Number(count) === points.length;
|
|
7051
|
+
this.setDecodeLevel(decodeResult, true, counted ? void 0 : "partial");
|
|
7052
|
+
return decodeResult;
|
|
7053
|
+
}
|
|
7054
|
+
};
|
|
7055
|
+
|
|
5485
7056
|
// lib/plugins/Label_H1_WRN.ts
|
|
5486
7057
|
var Label_H1_WRN = class extends DecoderPlugin {
|
|
5487
7058
|
name = "label-h1-wrn";
|
|
@@ -5521,6 +7092,93 @@ var Label_H1_WRN = class extends DecoderPlugin {
|
|
|
5521
7092
|
}
|
|
5522
7093
|
};
|
|
5523
7094
|
|
|
7095
|
+
// lib/plugins/Label_H2_02E.ts
|
|
7096
|
+
var Label_H2_02E = class extends DecoderPlugin {
|
|
7097
|
+
name = "label-h2-02e";
|
|
7098
|
+
qualifiers() {
|
|
7099
|
+
return {
|
|
7100
|
+
labels: ["H2"],
|
|
7101
|
+
preambles: ["02E"]
|
|
7102
|
+
};
|
|
7103
|
+
}
|
|
7104
|
+
decode(message, options = {}) {
|
|
7105
|
+
let decodeResult = this.defaultResult();
|
|
7106
|
+
decodeResult.decoder.name = this.name;
|
|
7107
|
+
decodeResult.formatted.description = "Weather Report";
|
|
7108
|
+
decodeResult.message = message;
|
|
7109
|
+
const parts = message.text.split(" ");
|
|
7110
|
+
if (parts[parts.length - 1] !== "Q") {
|
|
7111
|
+
decodeResult.remaining.text = message.text;
|
|
7112
|
+
decodeResult.decoded = false;
|
|
7113
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
7114
|
+
return decodeResult;
|
|
7115
|
+
}
|
|
7116
|
+
const windData = [];
|
|
7117
|
+
decodeResult.remaining.text = "";
|
|
7118
|
+
const header = parts[0];
|
|
7119
|
+
if (header.length === 45) {
|
|
7120
|
+
ResultFormatter.day(decodeResult, parseInt(header.substring(3, 5), 10));
|
|
7121
|
+
ResultFormatter.departureAirport(decodeResult, header.substring(5, 9));
|
|
7122
|
+
ResultFormatter.arrivalAirport(decodeResult, header.substring(9, 13));
|
|
7123
|
+
const firstWind = this.parseWeatherReport(header.substring(13));
|
|
7124
|
+
if (firstWind) {
|
|
7125
|
+
windData.push(firstWind);
|
|
7126
|
+
} else {
|
|
7127
|
+
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + header.substring(13);
|
|
7128
|
+
}
|
|
7129
|
+
}
|
|
7130
|
+
for (let i = 1; i < parts.length - 1; i++) {
|
|
7131
|
+
const part = parts[i];
|
|
7132
|
+
if (part[0] !== "Q") {
|
|
7133
|
+
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + part;
|
|
7134
|
+
continue;
|
|
7135
|
+
}
|
|
7136
|
+
const wind = this.parseWeatherReport(part.substring(1));
|
|
7137
|
+
if (wind) {
|
|
7138
|
+
windData.push(wind);
|
|
7139
|
+
} else {
|
|
7140
|
+
decodeResult.remaining.text += (decodeResult.remaining.text ? " " : "") + part;
|
|
7141
|
+
}
|
|
7142
|
+
}
|
|
7143
|
+
ResultFormatter.windData(decodeResult, windData);
|
|
7144
|
+
decodeResult.decoded = true;
|
|
7145
|
+
decodeResult.decoder.decodeLevel = decodeResult.remaining.text.length === 0 ? "full" : "partial";
|
|
7146
|
+
return decodeResult;
|
|
7147
|
+
}
|
|
7148
|
+
parseWeatherReport(text) {
|
|
7149
|
+
const posString = text.substring(0, 13);
|
|
7150
|
+
const pos = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(posString);
|
|
7151
|
+
if (text.length !== 32 || !pos) {
|
|
7152
|
+
return null;
|
|
7153
|
+
}
|
|
7154
|
+
const tod2 = DateTimeUtils.convertHHMMSSToTod(text.substring(13, 17));
|
|
7155
|
+
const flightLevel = parseInt(text.substring(17, 20), 10);
|
|
7156
|
+
const tempSign = text[21] === "M" ? -1 : 1;
|
|
7157
|
+
const tempDegreesRaw = parseInt(text.substring(22, 25), 10);
|
|
7158
|
+
const tempDegrees = tempSign * (tempDegreesRaw / 10);
|
|
7159
|
+
const windDirection = parseInt(text.substring(25, 28), 10);
|
|
7160
|
+
const windSpeed = parseInt(text.substring(28, 31), 10);
|
|
7161
|
+
if (text[31] !== "G") {
|
|
7162
|
+
return null;
|
|
7163
|
+
}
|
|
7164
|
+
return {
|
|
7165
|
+
waypoint: {
|
|
7166
|
+
name: posString,
|
|
7167
|
+
latitude: pos.latitude,
|
|
7168
|
+
longitude: pos.longitude,
|
|
7169
|
+
time: tod2
|
|
7170
|
+
},
|
|
7171
|
+
flightLevel,
|
|
7172
|
+
windDirection,
|
|
7173
|
+
windSpeed,
|
|
7174
|
+
temperature: {
|
|
7175
|
+
flightLevel,
|
|
7176
|
+
degreesC: tempDegrees
|
|
7177
|
+
}
|
|
7178
|
+
};
|
|
7179
|
+
}
|
|
7180
|
+
};
|
|
7181
|
+
|
|
5524
7182
|
// lib/plugins/Label_HX.ts
|
|
5525
7183
|
var Label_HX = class extends DecoderPlugin {
|
|
5526
7184
|
name = "label-hx";
|
|
@@ -5593,8 +7251,8 @@ function ascii85Decode(input) {
|
|
|
5593
7251
|
if (digit < 0 || digit > 84) return null;
|
|
5594
7252
|
value = value * 85 + digit;
|
|
5595
7253
|
}
|
|
5596
|
-
if (
|
|
5597
|
-
const v = value
|
|
7254
|
+
if (value > 4294967295) return null;
|
|
7255
|
+
const v = value;
|
|
5598
7256
|
const numBytes = chunkLen === 5 ? 4 : chunkLen - 1;
|
|
5599
7257
|
if (numBytes >= 1) output.push(v >>> 24 & 255);
|
|
5600
7258
|
if (numBytes >= 2) output.push(v >>> 16 & 255);
|
|
@@ -6816,8 +8474,11 @@ var pluginClasses = [
|
|
|
6816
8474
|
Label_ColonComma,
|
|
6817
8475
|
Label_5Z_Slash,
|
|
6818
8476
|
Label_10_LDR,
|
|
8477
|
+
Label_10_LRW,
|
|
6819
8478
|
Label_10_POS,
|
|
6820
8479
|
Label_10_Slash,
|
|
8480
|
+
Label_11_LDR,
|
|
8481
|
+
Label_11_LRW,
|
|
6821
8482
|
Label_12_N_Space,
|
|
6822
8483
|
Label_12_POS,
|
|
6823
8484
|
Label_13Through18_Slash,
|
|
@@ -6841,6 +8502,8 @@ var pluginClasses = [
|
|
|
6841
8502
|
Label_2P_FM4,
|
|
6842
8503
|
Label_2P_FM5,
|
|
6843
8504
|
Label_30_Slash_EA,
|
|
8505
|
+
Label_37_SWA,
|
|
8506
|
+
Label_40_SWA,
|
|
6844
8507
|
Label_44_ETA,
|
|
6845
8508
|
Label_44_IN,
|
|
6846
8509
|
Label_44_OFF,
|
|
@@ -6856,7 +8519,7 @@ var pluginClasses = [
|
|
|
6856
8519
|
Label_4T_AGFSR,
|
|
6857
8520
|
Label_4T_ETA,
|
|
6858
8521
|
Label_B6_Forwardslash,
|
|
6859
|
-
|
|
8522
|
+
Label_H1_76401,
|
|
6860
8523
|
Label_H1_ATIS,
|
|
6861
8524
|
Label_H1_EZF,
|
|
6862
8525
|
Label_H1_FLR,
|
|
@@ -6866,6 +8529,8 @@ var pluginClasses = [
|
|
|
6866
8529
|
Label_H1_Paren,
|
|
6867
8530
|
Label_H1_WRN,
|
|
6868
8531
|
Label_H1_StarPOS,
|
|
8532
|
+
Label_H1_SWA_Track,
|
|
8533
|
+
Label_H2_02E,
|
|
6869
8534
|
Label_HX,
|
|
6870
8535
|
Label_58,
|
|
6871
8536
|
Label_80,
|
|
@@ -6911,6 +8576,9 @@ var MessageDecoder = class {
|
|
|
6911
8576
|
this.wildcardSet.add(plugin);
|
|
6912
8577
|
const wildcardInsertIndex = this.wildcardEntries.length - 1;
|
|
6913
8578
|
for (const bucket of this.candidatesByLabel.values()) {
|
|
8579
|
+
if (bucket.some((e) => e.plugin === plugin)) {
|
|
8580
|
+
continue;
|
|
8581
|
+
}
|
|
6914
8582
|
bucket.splice(wildcardInsertIndex, 0, entry);
|
|
6915
8583
|
}
|
|
6916
8584
|
}
|