@airframes/acars-decoder 1.6.12 → 1.6.14
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/index.js +1501 -1262
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1501 -1262
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -129,7 +129,7 @@ var DecoderPlugin = class {
|
|
|
129
129
|
};
|
|
130
130
|
|
|
131
131
|
// lib/utils/coordinate_utils.ts
|
|
132
|
-
var CoordinateUtils = class {
|
|
132
|
+
var CoordinateUtils = class _CoordinateUtils {
|
|
133
133
|
/**
|
|
134
134
|
* Decode a string of coordinates into an object with latitude and longitude in millidegrees
|
|
135
135
|
* @param stringCoords - The string of coordinates to decode
|
|
@@ -146,8 +146,8 @@ var CoordinateUtils = class {
|
|
|
146
146
|
longitudeChars = stringCoords.substring(8, 14);
|
|
147
147
|
}
|
|
148
148
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
149
|
-
results.latitude = Number(stringCoords.substring(1, 6)) / 1e3 * (firstChar
|
|
150
|
-
results.longitude = Number(longitudeChars) / 1e3 * (middleChar
|
|
149
|
+
results.latitude = Number(stringCoords.substring(1, 6)) / 1e3 * _CoordinateUtils.getDirection(firstChar);
|
|
150
|
+
results.longitude = Number(longitudeChars) / 1e3 * _CoordinateUtils.getDirection(middleChar);
|
|
151
151
|
} else {
|
|
152
152
|
return;
|
|
153
153
|
}
|
|
@@ -173,8 +173,8 @@ var CoordinateUtils = class {
|
|
|
173
173
|
const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
|
|
174
174
|
const lonMin = Number(longitudeChars) % 1e3 / 10;
|
|
175
175
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
176
|
-
results.latitude = (latDeg + latMin / 60) * (firstChar
|
|
177
|
-
results.longitude = (lonDeg + lonMin / 60) * (middleChar
|
|
176
|
+
results.latitude = (latDeg + latMin / 60) * _CoordinateUtils.getDirection(firstChar);
|
|
177
|
+
results.longitude = (lonDeg + lonMin / 60) * _CoordinateUtils.getDirection(middleChar);
|
|
178
178
|
} else {
|
|
179
179
|
return;
|
|
180
180
|
}
|
|
@@ -281,6 +281,15 @@ var RouteUtils = class _RouteUtils {
|
|
|
281
281
|
|
|
282
282
|
// lib/utils/result_formatter.ts
|
|
283
283
|
var ResultFormatter = class {
|
|
284
|
+
static route(decodeResult, route) {
|
|
285
|
+
decodeResult.raw.route = route;
|
|
286
|
+
decodeResult.formatted.items.push({
|
|
287
|
+
type: "aircraft_route",
|
|
288
|
+
code: "ROUTE",
|
|
289
|
+
label: "Aircraft Route",
|
|
290
|
+
value: RouteUtils.routeToString(route)
|
|
291
|
+
});
|
|
292
|
+
}
|
|
284
293
|
static state_change(decodeResult, from, to) {
|
|
285
294
|
decodeResult.raw.state_change = {
|
|
286
295
|
from,
|
|
@@ -317,6 +326,9 @@ var ResultFormatter = class {
|
|
|
317
326
|
});
|
|
318
327
|
}
|
|
319
328
|
static position(decodeResult, value) {
|
|
329
|
+
if (!value || isNaN(value.latitude) || isNaN(value.longitude)) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
320
332
|
decodeResult.raw.position = value;
|
|
321
333
|
decodeResult.formatted.items.push({
|
|
322
334
|
type: "aircraft_position",
|
|
@@ -553,17 +565,50 @@ var ResultFormatter = class {
|
|
|
553
565
|
value: DateTimeUtils.timestampToString(time, "tod")
|
|
554
566
|
});
|
|
555
567
|
}
|
|
556
|
-
static
|
|
557
|
-
decodeResult.raw.
|
|
568
|
+
static day(decodeResult, day) {
|
|
569
|
+
decodeResult.raw.day_of_month = day;
|
|
570
|
+
decodeResult.formatted.items.push({
|
|
571
|
+
type: "day_of_month",
|
|
572
|
+
code: "MSG_DAY",
|
|
573
|
+
label: "Day of Month",
|
|
574
|
+
value: `${day}`
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
static departureDay(decodeResult, day) {
|
|
578
|
+
decodeResult.raw.departure_day_of_month = day;
|
|
579
|
+
decodeResult.formatted.items.push({
|
|
580
|
+
type: "day_of_month",
|
|
581
|
+
code: "DEP_DAY",
|
|
582
|
+
label: "Departure Day",
|
|
583
|
+
value: `${day}`
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
static arrivalDay(decodeResult, day) {
|
|
587
|
+
decodeResult.raw.arrival_day_of_month = day;
|
|
588
|
+
decodeResult.formatted.items.push({
|
|
589
|
+
type: "day_of_month",
|
|
590
|
+
code: "ARR_DAY",
|
|
591
|
+
label: "Arrival Day",
|
|
592
|
+
value: `${day}`
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
static text(decodeResult, text) {
|
|
596
|
+
decodeResult.raw.text = text;
|
|
558
597
|
decodeResult.formatted.items.push({
|
|
559
598
|
type: "text",
|
|
560
599
|
code: "TEXT",
|
|
561
600
|
label: "Text Message",
|
|
562
|
-
value:
|
|
601
|
+
value: text
|
|
563
602
|
});
|
|
564
603
|
}
|
|
565
|
-
static unknown(decodeResult, value) {
|
|
566
|
-
decodeResult.remaining.text
|
|
604
|
+
static unknown(decodeResult, value, sep = ",") {
|
|
605
|
+
if (!decodeResult.remaining.text)
|
|
606
|
+
decodeResult.remaining.text = value;
|
|
607
|
+
else
|
|
608
|
+
decodeResult.remaining.text += sep + value;
|
|
609
|
+
}
|
|
610
|
+
static unknownArr(decodeResult, value, sep = ",") {
|
|
611
|
+
this.unknown(decodeResult, value.join(sep), sep);
|
|
567
612
|
}
|
|
568
613
|
};
|
|
569
614
|
|
|
@@ -639,14 +684,14 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
639
684
|
decodeResult.raw.day_of_month = Number(info[3]);
|
|
640
685
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(info[4]));
|
|
641
686
|
ResultFormatter.arrivalRunway(decodeResult, info[5].slice(1));
|
|
642
|
-
decodeResult
|
|
687
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(3), "/");
|
|
643
688
|
} else if (type === "B3") {
|
|
644
689
|
ResultFormatter.departureAirport(decodeResult, header[1].substring(0, 3), "IATA");
|
|
645
690
|
ResultFormatter.arrivalAirport(decodeResult, header[1].substring(3), "IATA");
|
|
646
691
|
decodeResult.raw.day_of_month = Number(header[2]);
|
|
647
692
|
ResultFormatter.arrivalRunway(decodeResult, header[3].slice(1));
|
|
648
693
|
if (header.length > 4) {
|
|
649
|
-
decodeResult
|
|
694
|
+
ResultFormatter.unknownArr(decodeResult, header.slice(4), "/");
|
|
650
695
|
}
|
|
651
696
|
} else if (type === "C3" && data[1] === "C3 GATE REQ ") {
|
|
652
697
|
const info = data[2].split(" ");
|
|
@@ -654,7 +699,7 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
654
699
|
ResultFormatter.arrivalAirport(decodeResult, info[2]);
|
|
655
700
|
decodeResult.raw.day_of_month = Number(info[3]);
|
|
656
701
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(info[4]));
|
|
657
|
-
decodeResult
|
|
702
|
+
ResultFormatter.unknownArr(decodeResult, info.slice(5), " ");
|
|
658
703
|
} else if (type === "C3") {
|
|
659
704
|
ResultFormatter.departureAirport(decodeResult, header[1].substring(0, 3), "IATA");
|
|
660
705
|
ResultFormatter.arrivalAirport(decodeResult, header[1].substring(3), "IATA");
|
|
@@ -666,7 +711,7 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
666
711
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(airports[4]));
|
|
667
712
|
const estimates = data[3].split(" ");
|
|
668
713
|
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(estimates[1] + "00"));
|
|
669
|
-
decodeResult
|
|
714
|
+
ResultFormatter.unknown(decodeResult, estimates[2]);
|
|
670
715
|
} else {
|
|
671
716
|
if (options.debug) {
|
|
672
717
|
console.log(`Decoder: Unkown 5Z RDC format: ${message.text}`);
|
|
@@ -678,7 +723,7 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
678
723
|
if (options.debug) {
|
|
679
724
|
console.log(`Decoder: Unknown 5Z message: ${message.text}`);
|
|
680
725
|
}
|
|
681
|
-
decodeResult
|
|
726
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
682
727
|
decodeResult.decoded = false;
|
|
683
728
|
decodeResult.decoder.decodeLevel = "none";
|
|
684
729
|
}
|
|
@@ -706,7 +751,7 @@ var Label_10_LDR = class extends DecoderPlugin {
|
|
|
706
751
|
if (options.debug) {
|
|
707
752
|
console.log(`Decoder: Unknown 10 message: ${message.text}`);
|
|
708
753
|
}
|
|
709
|
-
decodeResult
|
|
754
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
710
755
|
decodeResult.decoded = false;
|
|
711
756
|
decodeResult.decoder.decodeLevel = "none";
|
|
712
757
|
return decodeResult;
|
|
@@ -727,7 +772,7 @@ var Label_10_LDR = class extends DecoderPlugin {
|
|
|
727
772
|
if (altRwy != "") {
|
|
728
773
|
ResultFormatter.alternateRunway(decodeResult, altRwy);
|
|
729
774
|
}
|
|
730
|
-
decodeResult
|
|
775
|
+
ResultFormatter.unknownArr(decodeResult, [...parts.slice(0, 5), ...parts.slice(15)]);
|
|
731
776
|
decodeResult.decoded = true;
|
|
732
777
|
decodeResult.decoder.decodeLevel = "partial";
|
|
733
778
|
return decodeResult;
|
|
@@ -754,7 +799,7 @@ var Label_10_POS = class extends DecoderPlugin {
|
|
|
754
799
|
if (options.debug) {
|
|
755
800
|
console.log(`Decoder: Unknown 10 message: ${message.text}`);
|
|
756
801
|
}
|
|
757
|
-
decodeResult
|
|
802
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
758
803
|
decodeResult.decoded = false;
|
|
759
804
|
decodeResult.decoder.decodeLevel = "none";
|
|
760
805
|
return decodeResult;
|
|
@@ -767,7 +812,7 @@ var Label_10_POS = class extends DecoderPlugin {
|
|
|
767
812
|
};
|
|
768
813
|
ResultFormatter.position(decodeResult, position);
|
|
769
814
|
ResultFormatter.altitude(decodeResult, Number(parts[7]));
|
|
770
|
-
decodeResult
|
|
815
|
+
ResultFormatter.unknownArr(decodeResult, [parts[0], ...parts.slice(3, 7), ...parts.slice(8)]);
|
|
771
816
|
decodeResult.decoded = true;
|
|
772
817
|
decodeResult.decoder.decodeLevel = "partial";
|
|
773
818
|
return decodeResult;
|
|
@@ -794,7 +839,7 @@ var Label_10_Slash = class extends DecoderPlugin {
|
|
|
794
839
|
if (options.debug) {
|
|
795
840
|
console.log(`Decoder: Unknown 10 message: ${message.text}`);
|
|
796
841
|
}
|
|
797
|
-
decodeResult
|
|
842
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
798
843
|
decodeResult.decoded = false;
|
|
799
844
|
decodeResult.decoder.decodeLevel = "none";
|
|
800
845
|
return decodeResult;
|
|
@@ -821,17 +866,11 @@ var Label_10_Slash = class extends DecoderPlugin {
|
|
|
821
866
|
time: DateTimeUtils.convertHHMMSSToTod(parts[15] + "00"),
|
|
822
867
|
timeFormat: "tod"
|
|
823
868
|
}];
|
|
824
|
-
|
|
825
|
-
decodeResult.formatted.items.push({
|
|
826
|
-
type: "aircraft_route",
|
|
827
|
-
code: "ROUTE",
|
|
828
|
-
label: "Aircraft Route",
|
|
829
|
-
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
830
|
-
});
|
|
869
|
+
ResultFormatter.route(decodeResult, { waypoints });
|
|
831
870
|
if (parts[16]) {
|
|
832
871
|
ResultFormatter.departureAirport(decodeResult, parts[16]);
|
|
833
872
|
}
|
|
834
|
-
decodeResult
|
|
873
|
+
ResultFormatter.unknownArr(decodeResult, [parts[3], parts[4], ...parts.slice(9, 11), ...parts.slice(17)], "/");
|
|
835
874
|
decodeResult.decoded = true;
|
|
836
875
|
decodeResult.decoder.decodeLevel = "partial";
|
|
837
876
|
return decodeResult;
|
|
@@ -853,35 +892,29 @@ var Label_12_N_Space = class extends DecoderPlugin {
|
|
|
853
892
|
decodeResult.formatted.description = "Position Report";
|
|
854
893
|
decodeResult.message = message;
|
|
855
894
|
const variant1Regex = /^(?<lat>[NS])\s(?<lat_coord>.*),(?<long>[EW])\s*(?<long_coord>.*),(?<alt>.*),(?<unkwn1>.*),\s*(?<unkwn2>.*),.(?<airframe>.*),(?<unkwn3>.*)$/;
|
|
856
|
-
let results;
|
|
857
|
-
if (results
|
|
895
|
+
let results = message.text.match(variant1Regex);
|
|
896
|
+
if (results?.groups) {
|
|
858
897
|
if (options.debug) {
|
|
859
898
|
console.log(`Label 12 N : results`);
|
|
860
899
|
console.log(results);
|
|
861
900
|
}
|
|
862
|
-
|
|
901
|
+
ResultFormatter.position(decodeResult, {
|
|
863
902
|
latitude: Number(results.groups.lat_coord) * (results.groups.lat == "N" ? 1 : -1),
|
|
864
903
|
longitude: Number(results.groups.long_coord) * (results.groups.long == "E" ? 1 : -1)
|
|
865
|
-
};
|
|
866
|
-
const altitude = results.groups.alt == "GRD" || results.groups.alt == "***" ? 0 : Number(results.groups.alt);
|
|
867
|
-
decodeResult.formatted.items.push({
|
|
868
|
-
type: "aircraft_position",
|
|
869
|
-
code: "POS",
|
|
870
|
-
label: "Aircraft Position",
|
|
871
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
872
904
|
});
|
|
905
|
+
const altitude = results.groups.alt == "GRD" || results.groups.alt == "***" ? 0 : Number(results.groups.alt);
|
|
873
906
|
ResultFormatter.altitude(decodeResult, altitude);
|
|
874
|
-
decodeResult
|
|
907
|
+
ResultFormatter.unknownArr(decodeResult, [results.groups.unkwn1, results.groups.unkwn2, results.groups.unkwn3]);
|
|
875
908
|
decodeResult.decoded = true;
|
|
876
909
|
decodeResult.decoder.decodeLevel = "partial";
|
|
877
|
-
|
|
878
|
-
if (options.debug) {
|
|
879
|
-
console.log(`Decoder: Unknown 12 message: ${message.text}`);
|
|
880
|
-
}
|
|
881
|
-
decodeResult.remaining.text = message.text;
|
|
882
|
-
decodeResult.decoded = false;
|
|
883
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
910
|
+
return decodeResult;
|
|
884
911
|
}
|
|
912
|
+
if (options.debug) {
|
|
913
|
+
console.log(`Decoder: Unknown 12 message: ${message.text}`);
|
|
914
|
+
}
|
|
915
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
916
|
+
decodeResult.decoded = false;
|
|
917
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
885
918
|
return decodeResult;
|
|
886
919
|
}
|
|
887
920
|
};
|
|
@@ -908,12 +941,11 @@ var Label_13Through18_Slash = class extends DecoderPlugin {
|
|
|
908
941
|
if (options?.debug) {
|
|
909
942
|
console.log(`Decoder: Unknown OOOI message: ${message.text}`);
|
|
910
943
|
}
|
|
911
|
-
decodeResult
|
|
944
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
912
945
|
decodeResult.decoded = false;
|
|
913
946
|
decodeResult.decoder.decodeLevel = "none";
|
|
914
947
|
return decodeResult;
|
|
915
948
|
}
|
|
916
|
-
decodeResult.remaining.text = "";
|
|
917
949
|
const data = parts[2].split(" ");
|
|
918
950
|
ResultFormatter.departureAirport(decodeResult, data[1]);
|
|
919
951
|
ResultFormatter.arrivalAirport(decodeResult, data[2]);
|
|
@@ -929,7 +961,7 @@ var Label_13Through18_Slash = class extends DecoderPlugin {
|
|
|
929
961
|
ResultFormatter.in(decodeResult, time);
|
|
930
962
|
}
|
|
931
963
|
if (parts.length === 7) {
|
|
932
|
-
decodeResult
|
|
964
|
+
ResultFormatter.unknownArr(decodeResult, parts.slice(4), "/");
|
|
933
965
|
}
|
|
934
966
|
for (let i = 1; i < lines.length; i++) {
|
|
935
967
|
if (lines[i].startsWith("/LOC")) {
|
|
@@ -943,11 +975,9 @@ var Label_13Through18_Slash = class extends DecoderPlugin {
|
|
|
943
975
|
longitude: CoordinateUtils.getDirection(location[1][0]) * CoordinateUtils.dmsToDecimalDegrees(Number(location[1].substring(1, 4)), Number(location[1].substring(4, 6)), Number(location[1].substring(6, 8)))
|
|
944
976
|
};
|
|
945
977
|
}
|
|
946
|
-
|
|
947
|
-
ResultFormatter.position(decodeResult, position);
|
|
948
|
-
}
|
|
978
|
+
ResultFormatter.position(decodeResult, position);
|
|
949
979
|
} else {
|
|
950
|
-
decodeResult
|
|
980
|
+
ResultFormatter.unknown(decodeResult, lines[i], "\r\n");
|
|
951
981
|
}
|
|
952
982
|
}
|
|
953
983
|
decodeResult.decoded = true;
|
|
@@ -992,16 +1022,8 @@ var Label_15 = class extends DecoderPlugin {
|
|
|
992
1022
|
decodeResult.formatted.description = "Position Report";
|
|
993
1023
|
const twoZeeRegex = /^\(2(?<between>.+)\(Z$/;
|
|
994
1024
|
const results = message.text.match(twoZeeRegex);
|
|
995
|
-
if (results) {
|
|
996
|
-
|
|
997
|
-
if (decodeResult.raw.position) {
|
|
998
|
-
decodeResult.formatted.items.push({
|
|
999
|
-
type: "position",
|
|
1000
|
-
code: "POS",
|
|
1001
|
-
label: "Position",
|
|
1002
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1003
|
-
});
|
|
1004
|
-
}
|
|
1025
|
+
if (results?.groups) {
|
|
1026
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(results.groups.between.substr(0, 13)));
|
|
1005
1027
|
}
|
|
1006
1028
|
decodeResult.decoded = true;
|
|
1007
1029
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -1025,31 +1047,23 @@ var Label_15_FST = class extends DecoderPlugin {
|
|
|
1025
1047
|
decodeResult.message = message;
|
|
1026
1048
|
const parts = message.text.split(" ");
|
|
1027
1049
|
const header = parts[0];
|
|
1028
|
-
decodeResult.raw.departure_icao = header.substring(5, 9);
|
|
1029
|
-
decodeResult.raw.arrival_icao = header.substring(9, 13);
|
|
1030
1050
|
const stringCoords = header.substring(13);
|
|
1031
1051
|
const firstChar = stringCoords.substring(0, 1);
|
|
1032
1052
|
const middleChar = stringCoords.substring(7, 8);
|
|
1033
1053
|
decodeResult.raw.position = {};
|
|
1034
1054
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
decodeResult
|
|
1055
|
+
const lat = Number(stringCoords.substring(1, 7)) / 1e4 * (firstChar === "S" ? -1 : 1);
|
|
1056
|
+
const lon = Number(stringCoords.substring(8, 15)) / 1e4 * (middleChar === "W" ? -1 : 1);
|
|
1057
|
+
ResultFormatter.position(decodeResult, { latitude: lat, longitude: lon });
|
|
1058
|
+
ResultFormatter.altitude(decodeResult, Number(stringCoords.substring(15)) * 100);
|
|
1038
1059
|
} else {
|
|
1039
1060
|
decodeResult.decoded = false;
|
|
1040
1061
|
decodeResult.decoder.decodeLevel = "none";
|
|
1041
1062
|
return decodeResult;
|
|
1042
1063
|
}
|
|
1043
|
-
decodeResult.
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
label: "Aircraft Position",
|
|
1047
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1048
|
-
});
|
|
1049
|
-
ResultFormatter.altitude(decodeResult, decodeResult.raw.altitude);
|
|
1050
|
-
ResultFormatter.departureAirport(decodeResult, decodeResult.raw.departure_icao);
|
|
1051
|
-
ResultFormatter.arrivalAirport(decodeResult, decodeResult.raw.arrival_icao);
|
|
1052
|
-
decodeResult.remaining.text = parts.slice(1).join(" ");
|
|
1064
|
+
ResultFormatter.departureAirport(decodeResult, header.substring(5, 9));
|
|
1065
|
+
ResultFormatter.arrivalAirport(decodeResult, header.substring(9, 13));
|
|
1066
|
+
ResultFormatter.unknownArr(decodeResult, parts.slice(1), " ");
|
|
1053
1067
|
decodeResult.decoded = true;
|
|
1054
1068
|
decodeResult.decoder.decodeLevel = "partial";
|
|
1055
1069
|
return decodeResult;
|
|
@@ -1072,52 +1086,45 @@ var Label_16_N_Space = class extends DecoderPlugin {
|
|
|
1072
1086
|
decodeResult.message = message;
|
|
1073
1087
|
let variant1Regex = /^(?<lat>[NS])\s(?<lat_coord>.*),(?<long>[EW])\s*(?<long_coord>.*),(?<alt>.*),(?<unkwn1>.*),\s*(?<unkwn2>.*)$/;
|
|
1074
1088
|
let variant2Regex = /^(?<lat>[NS])\s(?<lat_coord>.*)\/(?<long>[EW])\s*(?<long_coord>.*)$/;
|
|
1075
|
-
let results;
|
|
1076
|
-
if (results
|
|
1089
|
+
let results = message.text.match(variant1Regex);
|
|
1090
|
+
if (results?.groups) {
|
|
1077
1091
|
if (options.debug) {
|
|
1078
1092
|
console.log(`Label 16 N : results`);
|
|
1079
1093
|
console.log(results);
|
|
1080
1094
|
}
|
|
1081
|
-
|
|
1095
|
+
let pos = {
|
|
1082
1096
|
latitude: Number(results.groups.lat_coord) * (results.groups.lat == "N" ? 1 : -1),
|
|
1083
1097
|
longitude: Number(results.groups.long_coord) * (results.groups.long == "E" ? 1 : -1)
|
|
1084
1098
|
};
|
|
1085
1099
|
const altitude = results.groups.alt == "GRD" || results.groups.alt == "***" ? 0 : Number(results.groups.alt);
|
|
1086
|
-
|
|
1087
|
-
type: "aircraft_position",
|
|
1088
|
-
code: "POS",
|
|
1089
|
-
label: "Aircraft Position",
|
|
1090
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1091
|
-
});
|
|
1100
|
+
ResultFormatter.position(decodeResult, pos);
|
|
1092
1101
|
ResultFormatter.altitude(decodeResult, altitude);
|
|
1093
|
-
decodeResult
|
|
1102
|
+
ResultFormatter.unknownArr(decodeResult, [results.groups.unkwn1, results.groups.unkwn2]);
|
|
1094
1103
|
decodeResult.decoded = true;
|
|
1095
1104
|
decodeResult.decoder.decodeLevel = "partial";
|
|
1096
|
-
|
|
1105
|
+
return decodeResult;
|
|
1106
|
+
}
|
|
1107
|
+
results = message.text.match(variant2Regex);
|
|
1108
|
+
if (results?.groups) {
|
|
1097
1109
|
if (options.debug) {
|
|
1098
1110
|
console.log(`Label 16 N : results`);
|
|
1099
1111
|
console.log(results);
|
|
1100
1112
|
}
|
|
1101
|
-
|
|
1113
|
+
let pos = {
|
|
1102
1114
|
latitude: Number(results.groups.lat_coord) * (results.groups.lat == "N" ? 1 : -1),
|
|
1103
1115
|
longitude: Number(results.groups.long_coord) * (results.groups.long == "E" ? 1 : -1)
|
|
1104
1116
|
};
|
|
1105
|
-
|
|
1106
|
-
type: "aircraft_position",
|
|
1107
|
-
code: "POS",
|
|
1108
|
-
label: "Aircraft Position",
|
|
1109
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1110
|
-
});
|
|
1117
|
+
ResultFormatter.position(decodeResult, pos);
|
|
1111
1118
|
decodeResult.decoded = true;
|
|
1112
1119
|
decodeResult.decoder.decodeLevel = "full";
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
}
|
|
1117
|
-
decodeResult.remaining.text = message.text;
|
|
1118
|
-
decodeResult.decoded = false;
|
|
1119
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
1120
|
+
return decodeResult;
|
|
1121
|
+
}
|
|
1122
|
+
if (options.debug) {
|
|
1123
|
+
console.log(`Decoder: Unknown 16 message: ${message.text}`);
|
|
1120
1124
|
}
|
|
1125
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
1126
|
+
decodeResult.decoded = false;
|
|
1127
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1121
1128
|
return decodeResult;
|
|
1122
1129
|
}
|
|
1123
1130
|
};
|
|
@@ -1156,6 +1163,265 @@ var Label_1M_Slash = class extends DecoderPlugin {
|
|
|
1156
1163
|
}
|
|
1157
1164
|
};
|
|
1158
1165
|
|
|
1166
|
+
// lib/plugins/Label_1L_3-line.ts
|
|
1167
|
+
var Label_1L_3Line = class extends DecoderPlugin {
|
|
1168
|
+
// eslint-disable-line camelcase
|
|
1169
|
+
name = "label-1l-3-line";
|
|
1170
|
+
qualifiers() {
|
|
1171
|
+
return {
|
|
1172
|
+
labels: ["1L"]
|
|
1173
|
+
};
|
|
1174
|
+
}
|
|
1175
|
+
decode(message, options = {}) {
|
|
1176
|
+
const decodeResult = this.defaultResult();
|
|
1177
|
+
decodeResult.decoder.name = this.name;
|
|
1178
|
+
decodeResult.formatted.description = "Position Report";
|
|
1179
|
+
decodeResult.message = message;
|
|
1180
|
+
const lines = message.text.split("\r\n");
|
|
1181
|
+
if (lines.length !== 3) {
|
|
1182
|
+
if (options.debug) {
|
|
1183
|
+
console.log(`Decoder: Unknown 1L message: ${message.text}`);
|
|
1184
|
+
}
|
|
1185
|
+
decodeResult.remaining.text = message.text;
|
|
1186
|
+
decodeResult.decoded = false;
|
|
1187
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1188
|
+
return decodeResult;
|
|
1189
|
+
}
|
|
1190
|
+
const parts = message.text.replaceAll("\r\n", "/").split("/");
|
|
1191
|
+
const data = /* @__PURE__ */ new Map();
|
|
1192
|
+
data.set("", parts[0]);
|
|
1193
|
+
for (let i = 1; i < parts.length; i++) {
|
|
1194
|
+
const part = parts[i].split(" ");
|
|
1195
|
+
data.set(part[0], part.slice(1).join(" "));
|
|
1196
|
+
}
|
|
1197
|
+
const dep = data.get("DEP");
|
|
1198
|
+
if (dep) {
|
|
1199
|
+
ResultFormatter.departureAirport(decodeResult, dep);
|
|
1200
|
+
data.delete("DEP");
|
|
1201
|
+
}
|
|
1202
|
+
const des = data.get("DES");
|
|
1203
|
+
if (des) {
|
|
1204
|
+
ResultFormatter.arrivalAirport(decodeResult, des);
|
|
1205
|
+
data.delete("DES");
|
|
1206
|
+
}
|
|
1207
|
+
const eta = data.get("ETA");
|
|
1208
|
+
if (eta) {
|
|
1209
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(eta + "00"));
|
|
1210
|
+
data.delete("ETA");
|
|
1211
|
+
}
|
|
1212
|
+
const alt = data.get("ALT");
|
|
1213
|
+
if (alt) {
|
|
1214
|
+
ResultFormatter.altitude(decodeResult, Number(alt));
|
|
1215
|
+
data.delete("ALT");
|
|
1216
|
+
}
|
|
1217
|
+
const fn = data.get("FN");
|
|
1218
|
+
if (fn) {
|
|
1219
|
+
ResultFormatter.flightNumber(decodeResult, fn);
|
|
1220
|
+
data.delete("FN");
|
|
1221
|
+
}
|
|
1222
|
+
const day = data.get("DAY");
|
|
1223
|
+
const utc = data.get("UTC");
|
|
1224
|
+
if (day && utc) {
|
|
1225
|
+
decodeResult.raw.message_timestamp = Date.parse(day + " GMT+0000") / 1e3 + DateTimeUtils.convertHHMMSSToTod(utc);
|
|
1226
|
+
data.delete("DAY");
|
|
1227
|
+
data.delete("UTC");
|
|
1228
|
+
}
|
|
1229
|
+
const lat = data.get("LAT");
|
|
1230
|
+
const lon = data.get("LON");
|
|
1231
|
+
if (lat && lon) {
|
|
1232
|
+
ResultFormatter.position(decodeResult, {
|
|
1233
|
+
latitude: CoordinateUtils.getDirection(lat[0]) * Number(lat.substring(1)),
|
|
1234
|
+
longitude: CoordinateUtils.getDirection(lon[0]) * Number(lon.substring(1))
|
|
1235
|
+
});
|
|
1236
|
+
data.delete("LAT");
|
|
1237
|
+
data.delete("LON");
|
|
1238
|
+
}
|
|
1239
|
+
let remaining = "";
|
|
1240
|
+
for (const [key, value] of data.entries()) {
|
|
1241
|
+
if (key === "") {
|
|
1242
|
+
remaining += value;
|
|
1243
|
+
} else {
|
|
1244
|
+
remaining += `/${key} ${value}`;
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
decodeResult.remaining.text = remaining;
|
|
1248
|
+
decodeResult.decoded = true;
|
|
1249
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1250
|
+
return decodeResult;
|
|
1251
|
+
}
|
|
1252
|
+
};
|
|
1253
|
+
|
|
1254
|
+
// lib/plugins/Label_1L_070.ts
|
|
1255
|
+
var Label_1L_070 = class extends DecoderPlugin {
|
|
1256
|
+
// eslint-disable-line camelcase
|
|
1257
|
+
name = "label-1l-070";
|
|
1258
|
+
qualifiers() {
|
|
1259
|
+
return {
|
|
1260
|
+
labels: ["1L"],
|
|
1261
|
+
preambles: ["000000070"]
|
|
1262
|
+
};
|
|
1263
|
+
}
|
|
1264
|
+
decode(message, options = {}) {
|
|
1265
|
+
const decodeResult = this.defaultResult();
|
|
1266
|
+
decodeResult.decoder.name = this.name;
|
|
1267
|
+
decodeResult.formatted.description = "Position Report";
|
|
1268
|
+
decodeResult.message = message;
|
|
1269
|
+
if (!message.text.startsWith("000000070")) {
|
|
1270
|
+
if (options.debug) {
|
|
1271
|
+
console.log(`Decoder: Unknown 1L message: ${message.text}`);
|
|
1272
|
+
}
|
|
1273
|
+
decodeResult.remaining.text = message.text;
|
|
1274
|
+
decodeResult.decoded = false;
|
|
1275
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1276
|
+
return decodeResult;
|
|
1277
|
+
}
|
|
1278
|
+
const parts = message.text.substring(9).split(",");
|
|
1279
|
+
if (parts.length !== 7) {
|
|
1280
|
+
if (options.debug) {
|
|
1281
|
+
console.log(`Decoder: Unknown 1L message: ${message.text}`);
|
|
1282
|
+
}
|
|
1283
|
+
decodeResult.remaining.text = message.text;
|
|
1284
|
+
decodeResult.decoded = false;
|
|
1285
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1286
|
+
return decodeResult;
|
|
1287
|
+
}
|
|
1288
|
+
ResultFormatter.departureAirport(decodeResult, parts[0]);
|
|
1289
|
+
ResultFormatter.arrivalAirport(decodeResult, parts[1]);
|
|
1290
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[2] + "00"));
|
|
1291
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[3] + "00"));
|
|
1292
|
+
ResultFormatter.position(decodeResult, {
|
|
1293
|
+
latitude: CoordinateUtils.getDirection(parts[4][0]) * Number(parts[4].substring(1)),
|
|
1294
|
+
longitude: CoordinateUtils.getDirection(parts[5][0]) * Number(parts[5].substring(1))
|
|
1295
|
+
});
|
|
1296
|
+
decodeResult.remaining.text = parts[6];
|
|
1297
|
+
decodeResult.decoded = true;
|
|
1298
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1299
|
+
return decodeResult;
|
|
1300
|
+
}
|
|
1301
|
+
};
|
|
1302
|
+
|
|
1303
|
+
// lib/plugins/Label_1L_660.ts
|
|
1304
|
+
var Label_1L_660 = class extends DecoderPlugin {
|
|
1305
|
+
// eslint-disable-line camelcase
|
|
1306
|
+
name = "label-1l-660";
|
|
1307
|
+
qualifiers() {
|
|
1308
|
+
return {
|
|
1309
|
+
labels: ["1L"],
|
|
1310
|
+
preambles: ["000000660"]
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
decode(message, options = {}) {
|
|
1314
|
+
const decodeResult = this.defaultResult();
|
|
1315
|
+
decodeResult.decoder.name = this.name;
|
|
1316
|
+
decodeResult.formatted.description = "Position Report";
|
|
1317
|
+
decodeResult.message = message;
|
|
1318
|
+
if (!message.text.startsWith("000000660")) {
|
|
1319
|
+
if (options.debug) {
|
|
1320
|
+
console.log(`Decoder: Unknown 1L message: ${message.text}`);
|
|
1321
|
+
}
|
|
1322
|
+
decodeResult.remaining.text = message.text;
|
|
1323
|
+
decodeResult.decoded = false;
|
|
1324
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1325
|
+
return decodeResult;
|
|
1326
|
+
}
|
|
1327
|
+
const parts = message.text.substring(9).split(",");
|
|
1328
|
+
if (parts.length !== 5) {
|
|
1329
|
+
if (options.debug) {
|
|
1330
|
+
console.log(`Decoder: Unknown 1L message: ${message.text}`);
|
|
1331
|
+
}
|
|
1332
|
+
decodeResult.remaining.text = message.text;
|
|
1333
|
+
decodeResult.decoded = false;
|
|
1334
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1335
|
+
return decodeResult;
|
|
1336
|
+
}
|
|
1337
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(parts[0]);
|
|
1338
|
+
if (position) {
|
|
1339
|
+
ResultFormatter.position(decodeResult, position);
|
|
1340
|
+
}
|
|
1341
|
+
const hhmmss = parts[1].substring(0, 6);
|
|
1342
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(hhmmss));
|
|
1343
|
+
const fl = parts[1].substring(6, 9);
|
|
1344
|
+
ResultFormatter.altitude(decodeResult, Number(fl) * 100);
|
|
1345
|
+
const next = parts[1].substring(9);
|
|
1346
|
+
ResultFormatter.route(decodeResult, { waypoints: [{ name: next.trim() }] });
|
|
1347
|
+
decodeResult.remaining.text = parts.slice(2).join(",");
|
|
1348
|
+
decodeResult.decoded = true;
|
|
1349
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1350
|
+
return decodeResult;
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
|
|
1354
|
+
// lib/plugins/Label_1L_Slash.ts
|
|
1355
|
+
var Label_1L_Slash = class extends DecoderPlugin {
|
|
1356
|
+
// eslint-disable-line camelcase
|
|
1357
|
+
name = "label-1l-1-line";
|
|
1358
|
+
qualifiers() {
|
|
1359
|
+
return {
|
|
1360
|
+
labels: ["1L"],
|
|
1361
|
+
preambles: ["+", "-"]
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
decode(message, options = {}) {
|
|
1365
|
+
const decodeResult = this.defaultResult();
|
|
1366
|
+
decodeResult.decoder.name = this.name;
|
|
1367
|
+
decodeResult.formatted.description = "Position Report";
|
|
1368
|
+
decodeResult.message = message;
|
|
1369
|
+
const parts = message.text.split("/");
|
|
1370
|
+
if (parts.length !== 7) {
|
|
1371
|
+
if (options.debug) {
|
|
1372
|
+
console.log(`Decoder: Unknown 1L message: ${message.text}`);
|
|
1373
|
+
}
|
|
1374
|
+
decodeResult.remaining.text = message.text;
|
|
1375
|
+
decodeResult.decoded = false;
|
|
1376
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1377
|
+
return decodeResult;
|
|
1378
|
+
}
|
|
1379
|
+
const data = /* @__PURE__ */ new Map();
|
|
1380
|
+
data.set("LAT", parts[0].replaceAll(" ", ""));
|
|
1381
|
+
data.set("LON", parts[1].replaceAll(" ", ""));
|
|
1382
|
+
for (let i = 2; i < parts.length; i++) {
|
|
1383
|
+
const part = parts[i].split(" ");
|
|
1384
|
+
data.set(part[0], part.slice(1).join(" "));
|
|
1385
|
+
}
|
|
1386
|
+
console.log(data);
|
|
1387
|
+
const position = {
|
|
1388
|
+
latitude: Number(data.get("LAT")),
|
|
1389
|
+
longitude: Number(data.get("LON"))
|
|
1390
|
+
};
|
|
1391
|
+
data.delete("LAT");
|
|
1392
|
+
data.delete("LON");
|
|
1393
|
+
ResultFormatter.position(decodeResult, position);
|
|
1394
|
+
const utc = data.get("UTC");
|
|
1395
|
+
if (utc) {
|
|
1396
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(utc));
|
|
1397
|
+
data.delete("UTC");
|
|
1398
|
+
}
|
|
1399
|
+
const alt = data.get("ALT");
|
|
1400
|
+
if (alt) {
|
|
1401
|
+
ResultFormatter.altitude(decodeResult, Number(alt));
|
|
1402
|
+
data.delete("ALT");
|
|
1403
|
+
}
|
|
1404
|
+
const fob = data.get("FOB");
|
|
1405
|
+
if (fob) {
|
|
1406
|
+
ResultFormatter.currentFuel(decodeResult, Number(fob));
|
|
1407
|
+
data.delete("FOB");
|
|
1408
|
+
}
|
|
1409
|
+
const eta = data.get("ETA");
|
|
1410
|
+
if (eta) {
|
|
1411
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(eta + "00"));
|
|
1412
|
+
data.delete("ETA");
|
|
1413
|
+
}
|
|
1414
|
+
let remaining = "";
|
|
1415
|
+
for (const [key, value] of data.entries()) {
|
|
1416
|
+
remaining += `/${key} ${value}`;
|
|
1417
|
+
}
|
|
1418
|
+
decodeResult.remaining.text = remaining;
|
|
1419
|
+
decodeResult.decoded = true;
|
|
1420
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1421
|
+
return decodeResult;
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1424
|
+
|
|
1159
1425
|
// lib/plugins/Label_20_POS.ts
|
|
1160
1426
|
var Label_20_POS = class extends DecoderPlugin {
|
|
1161
1427
|
name = "label-20-pos";
|
|
@@ -1178,30 +1444,16 @@ var Label_20_POS = class extends DecoderPlugin {
|
|
|
1178
1444
|
console.log(`DEBUG: ${this.name}: Variation 1 detected`);
|
|
1179
1445
|
}
|
|
1180
1446
|
const rawCoords = fields[0];
|
|
1181
|
-
|
|
1182
|
-
if (decodeResult.raw.position) {
|
|
1183
|
-
decodeResult.formatted.items.push({
|
|
1184
|
-
type: "position",
|
|
1185
|
-
code: "POS",
|
|
1186
|
-
label: "Position",
|
|
1187
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1188
|
-
});
|
|
1189
|
-
}
|
|
1447
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(rawCoords));
|
|
1190
1448
|
decodeResult.decoded = true;
|
|
1191
1449
|
decodeResult.decoder.decodeLevel = "full";
|
|
1192
1450
|
} else if (fields.length == 5) {
|
|
1193
1451
|
if (options.debug) {
|
|
1194
1452
|
console.log(`DEBUG: ${this.name}: Variation 2 detected`);
|
|
1195
1453
|
}
|
|
1196
|
-
const
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
decodeResult.formatted.items.push({
|
|
1200
|
-
type: "position",
|
|
1201
|
-
code: "POS",
|
|
1202
|
-
label: "Position",
|
|
1203
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1204
|
-
});
|
|
1454
|
+
const position = CoordinateUtils.decodeStringCoordinates(fields[0]);
|
|
1455
|
+
if (position) {
|
|
1456
|
+
ResultFormatter.position(decodeResult, position);
|
|
1205
1457
|
}
|
|
1206
1458
|
decodeResult.decoded = true;
|
|
1207
1459
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1240,11 +1492,7 @@ var Label_21_POS = class extends DecoderPlugin {
|
|
|
1240
1492
|
ResultFormatter.temperature(decodeResult, fields[6].replace(/ /g, ""));
|
|
1241
1493
|
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[7]));
|
|
1242
1494
|
ResultFormatter.arrivalAirport(decodeResult, fields[8]);
|
|
1243
|
-
decodeResult
|
|
1244
|
-
fields[1],
|
|
1245
|
-
fields[4],
|
|
1246
|
-
fields[5]
|
|
1247
|
-
].join(",");
|
|
1495
|
+
ResultFormatter.unknownArr(decodeResult, [fields[1], fields[4], fields[5]]);
|
|
1248
1496
|
decodeResult.decoded = true;
|
|
1249
1497
|
decodeResult.decoder.decodeLevel = "partial";
|
|
1250
1498
|
} else {
|
|
@@ -1270,41 +1518,74 @@ function processPosition(decodeResult, value) {
|
|
|
1270
1518
|
ResultFormatter.position(decodeResult, position);
|
|
1271
1519
|
}
|
|
1272
1520
|
|
|
1273
|
-
// lib/plugins/
|
|
1274
|
-
var
|
|
1275
|
-
name = "label-
|
|
1521
|
+
// lib/plugins/Label_22_OFF.ts
|
|
1522
|
+
var Label_22_OFF = class extends DecoderPlugin {
|
|
1523
|
+
name = "label-22-off";
|
|
1276
1524
|
qualifiers() {
|
|
1277
1525
|
return {
|
|
1278
|
-
labels: ["
|
|
1279
|
-
preambles: ["
|
|
1526
|
+
labels: ["22"],
|
|
1527
|
+
preambles: ["OFF"]
|
|
1280
1528
|
};
|
|
1281
1529
|
}
|
|
1282
1530
|
decode(message, options = {}) {
|
|
1283
1531
|
const decodeResult = this.defaultResult();
|
|
1284
1532
|
decodeResult.decoder.name = this.name;
|
|
1285
|
-
decodeResult.formatted.description = "
|
|
1533
|
+
decodeResult.formatted.description = "Takeoff Report";
|
|
1286
1534
|
decodeResult.message = message;
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
ResultFormatter.
|
|
1301
|
-
ResultFormatter.
|
|
1302
|
-
decodeResult.
|
|
1535
|
+
if (message.text.startsWith("OFF01")) {
|
|
1536
|
+
const fields = message.text.substring(5).split("/");
|
|
1537
|
+
if (fields.length != 2) {
|
|
1538
|
+
decodeResult.decoded = false;
|
|
1539
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1540
|
+
return decodeResult;
|
|
1541
|
+
}
|
|
1542
|
+
ResultFormatter.flightNumber(decodeResult, fields[0]);
|
|
1543
|
+
ResultFormatter.departureDay(decodeResult, Number(fields[1].substring(0, 2)));
|
|
1544
|
+
ResultFormatter.arrivalDay(decodeResult, Number(fields[1].substring(2, 4)));
|
|
1545
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(4, 8) + "00"));
|
|
1546
|
+
ResultFormatter.departureAirport(decodeResult, fields[1].substring(8, 12));
|
|
1547
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[1].substring(12, 16));
|
|
1548
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 22)));
|
|
1549
|
+
ResultFormatter.unknown(decodeResult, fields[1].substring(22));
|
|
1550
|
+
decodeResult.decoded = true;
|
|
1551
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1552
|
+
} else if (message.text.startsWith("OFF02\r\n")) {
|
|
1553
|
+
const fields = message.text.substring(7).split(",");
|
|
1554
|
+
if (fields.length != 4) {
|
|
1555
|
+
decodeResult.decoded = false;
|
|
1556
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1557
|
+
return decodeResult;
|
|
1558
|
+
}
|
|
1559
|
+
ResultFormatter.departureAirport(decodeResult, fields[0]);
|
|
1560
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[1]);
|
|
1561
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2] + "00"));
|
|
1562
|
+
ResultFormatter.unknown(decodeResult, fields[3]);
|
|
1563
|
+
decodeResult.decoded = true;
|
|
1564
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1565
|
+
} else if (message.text.startsWith("OFF02")) {
|
|
1566
|
+
const fields = message.text.substring(5).split("/");
|
|
1567
|
+
if (fields.length != 2) {
|
|
1568
|
+
decodeResult.decoded = false;
|
|
1569
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1570
|
+
return decodeResult;
|
|
1571
|
+
}
|
|
1572
|
+
ResultFormatter.flightNumber(decodeResult, fields[0]);
|
|
1573
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(fields[1].substring(0, 14));
|
|
1574
|
+
if (position) {
|
|
1575
|
+
ResultFormatter.position(decodeResult, position);
|
|
1576
|
+
}
|
|
1577
|
+
ResultFormatter.day(decodeResult, Number(fields[1].substring(14, 16)));
|
|
1578
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 20) + "00"));
|
|
1579
|
+
ResultFormatter.departureAirport(decodeResult, fields[1].substring(20, 24));
|
|
1580
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[1].substring(24, 28));
|
|
1581
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(28, 32) + "00"));
|
|
1582
|
+
ResultFormatter.unknown(decodeResult, fields[1].substring(32, 36));
|
|
1583
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(36, 40) + "00"));
|
|
1303
1584
|
decodeResult.decoded = true;
|
|
1304
1585
|
decodeResult.decoder.decodeLevel = "partial";
|
|
1305
1586
|
} else {
|
|
1306
1587
|
if (options.debug) {
|
|
1307
|
-
console.log(`DEBUG: ${this.name}: Unknown variation
|
|
1588
|
+
console.log(`DEBUG: ${this.name}: Unknown variation.`);
|
|
1308
1589
|
}
|
|
1309
1590
|
decodeResult.decoded = false;
|
|
1310
1591
|
decodeResult.decoder.decodeLevel = "none";
|
|
@@ -1313,33 +1594,116 @@ var Label_24_Slash = class extends DecoderPlugin {
|
|
|
1313
1594
|
}
|
|
1314
1595
|
};
|
|
1315
1596
|
|
|
1316
|
-
// lib/plugins/
|
|
1317
|
-
var
|
|
1318
|
-
name = "label-
|
|
1597
|
+
// lib/plugins/Label_22_POS.ts
|
|
1598
|
+
var Label_22_POS = class extends DecoderPlugin {
|
|
1599
|
+
name = "label-22-pos";
|
|
1319
1600
|
qualifiers() {
|
|
1320
1601
|
return {
|
|
1321
|
-
labels: ["
|
|
1322
|
-
preambles: ["
|
|
1602
|
+
labels: ["22"],
|
|
1603
|
+
preambles: ["N", "S"]
|
|
1323
1604
|
};
|
|
1324
1605
|
}
|
|
1325
1606
|
decode(message, options = {}) {
|
|
1326
1607
|
const decodeResult = this.defaultResult();
|
|
1327
1608
|
decodeResult.decoder.name = this.name;
|
|
1328
|
-
decodeResult.formatted.description = "
|
|
1609
|
+
decodeResult.formatted.description = "Position Report";
|
|
1329
1610
|
decodeResult.message = message;
|
|
1330
|
-
const
|
|
1331
|
-
if (
|
|
1611
|
+
const fields = message.text.split(",");
|
|
1612
|
+
if (fields.length !== 11) {
|
|
1332
1613
|
if (options.debug) {
|
|
1333
|
-
console.log(`
|
|
1334
|
-
|
|
1614
|
+
console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${fields.join(",")}`);
|
|
1615
|
+
}
|
|
1616
|
+
decodeResult.decoded = false;
|
|
1617
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1618
|
+
return decodeResult;
|
|
1619
|
+
}
|
|
1620
|
+
const latStr = fields[0].substring(1, 8);
|
|
1621
|
+
const lonStr = fields[0].substring(9);
|
|
1622
|
+
const lat = Number(latStr) / 1e4;
|
|
1623
|
+
const lon = Number(lonStr) / 1e4;
|
|
1624
|
+
ResultFormatter.position(decodeResult, {
|
|
1625
|
+
latitude: CoordinateUtils.getDirection(fields[0][0]) * lat,
|
|
1626
|
+
longitude: CoordinateUtils.getDirection(fields[0][8]) * lon
|
|
1627
|
+
});
|
|
1628
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2]));
|
|
1629
|
+
ResultFormatter.altitude(decodeResult, Number(fields[3]));
|
|
1630
|
+
ResultFormatter.unknownArr(decodeResult, [fields[1], ...fields.slice(4)]);
|
|
1631
|
+
decodeResult.decoded = true;
|
|
1632
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1633
|
+
return decodeResult;
|
|
1634
|
+
}
|
|
1635
|
+
};
|
|
1636
|
+
|
|
1637
|
+
// lib/plugins/Label_24_Slash.ts
|
|
1638
|
+
var Label_24_Slash = class extends DecoderPlugin {
|
|
1639
|
+
name = "label-24-slash";
|
|
1640
|
+
qualifiers() {
|
|
1641
|
+
return {
|
|
1642
|
+
labels: ["24"],
|
|
1643
|
+
preambles: ["/"]
|
|
1644
|
+
};
|
|
1645
|
+
}
|
|
1646
|
+
decode(message, options = {}) {
|
|
1647
|
+
const decodeResult = this.defaultResult();
|
|
1648
|
+
decodeResult.decoder.name = this.name;
|
|
1649
|
+
decodeResult.formatted.description = "Position Report";
|
|
1650
|
+
decodeResult.message = message;
|
|
1651
|
+
const fields = message.text.split("/");
|
|
1652
|
+
if (fields.length == 10 && fields[0] == "" && fields[9] == "") {
|
|
1653
|
+
const mmddyy = fields[1].substring(4, 6) + fields[1].substring(2, 4) + fields[1].substring(0, 2);
|
|
1654
|
+
const hhmmss = fields[2] + "00";
|
|
1655
|
+
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(hhmmss, mmddyy);
|
|
1656
|
+
ResultFormatter.flightNumber(decodeResult, fields[3]);
|
|
1657
|
+
ResultFormatter.altitude(decodeResult, Number(fields[4]));
|
|
1658
|
+
const lat = fields[5];
|
|
1659
|
+
const lon = fields[6];
|
|
1660
|
+
const position = {
|
|
1661
|
+
latitude: (lat[0] === "N" ? 1 : -1) * Number(lat.substring(1)),
|
|
1662
|
+
longitude: (lon[0] === "E" ? 1 : -1) * Number(lon.substring(1))
|
|
1663
|
+
};
|
|
1664
|
+
ResultFormatter.position(decodeResult, position);
|
|
1665
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[8] + "00"));
|
|
1666
|
+
ResultFormatter.unknown(decodeResult, fields[7]);
|
|
1667
|
+
decodeResult.decoded = true;
|
|
1668
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1669
|
+
} else {
|
|
1670
|
+
if (options.debug) {
|
|
1671
|
+
console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}. Message: ${message.text}`);
|
|
1672
|
+
}
|
|
1673
|
+
decodeResult.decoded = false;
|
|
1674
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1675
|
+
}
|
|
1676
|
+
return decodeResult;
|
|
1677
|
+
}
|
|
1678
|
+
};
|
|
1679
|
+
|
|
1680
|
+
// lib/plugins/Label_30_Slash_EA.ts
|
|
1681
|
+
var Label_30_Slash_EA = class extends DecoderPlugin {
|
|
1682
|
+
name = "label-30-slash-ea";
|
|
1683
|
+
qualifiers() {
|
|
1684
|
+
return {
|
|
1685
|
+
labels: ["30"],
|
|
1686
|
+
preambles: ["/EA"]
|
|
1687
|
+
};
|
|
1688
|
+
}
|
|
1689
|
+
decode(message, options = {}) {
|
|
1690
|
+
const decodeResult = this.defaultResult();
|
|
1691
|
+
decodeResult.decoder.name = this.name;
|
|
1692
|
+
decodeResult.formatted.description = "ETA Report";
|
|
1693
|
+
decodeResult.message = message;
|
|
1694
|
+
const results = message.text.split(/\n|\//).slice(1);
|
|
1695
|
+
if (results) {
|
|
1696
|
+
if (options.debug) {
|
|
1697
|
+
console.log(`Label 30 EA: results`);
|
|
1698
|
+
console.log(results);
|
|
1335
1699
|
}
|
|
1336
1700
|
}
|
|
1337
1701
|
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(results[0].substr(2, 4) + "00"));
|
|
1338
1702
|
if (results[1].substring(0, 2) === "DS") {
|
|
1339
1703
|
ResultFormatter.arrivalAirport(decodeResult, results[1].substring(2, 6));
|
|
1340
|
-
decodeResult
|
|
1704
|
+
ResultFormatter.unknown(decodeResult, "/".concat(results[2]));
|
|
1341
1705
|
} else {
|
|
1342
|
-
decodeResult
|
|
1706
|
+
ResultFormatter.unknown(decodeResult, "/".concat(results[1], "/", results[2]));
|
|
1343
1707
|
}
|
|
1344
1708
|
decodeResult.decoded = true;
|
|
1345
1709
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -1363,40 +1727,20 @@ var Label_44_ETA = class extends DecoderPlugin {
|
|
|
1363
1727
|
decodeResult.message = message;
|
|
1364
1728
|
const regex = /^.*,(?<unsplit_coords>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<fuel_in_tons>.*)$/;
|
|
1365
1729
|
const results = message.text.match(regex);
|
|
1366
|
-
if (results) {
|
|
1730
|
+
if (results?.groups) {
|
|
1367
1731
|
if (options.debug) {
|
|
1368
1732
|
console.log(`Label 44 ETA Report: groups`);
|
|
1369
1733
|
console.log(results.groups);
|
|
1370
1734
|
}
|
|
1371
|
-
|
|
1372
|
-
decodeResult
|
|
1373
|
-
decodeResult
|
|
1735
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords));
|
|
1736
|
+
ResultFormatter.departureAirport(decodeResult, results.groups.departure_icao);
|
|
1737
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
1374
1738
|
decodeResult.raw.current_time = Date.parse(
|
|
1375
1739
|
(/* @__PURE__ */ new Date()).getFullYear() + "-" + results.groups.current_date.substr(0, 2) + "-" + results.groups.current_date.substr(2, 2) + "T" + results.groups.current_time.substr(0, 2) + ":" + results.groups.current_time.substr(2, 2) + ":00Z"
|
|
1376
1740
|
);
|
|
1377
1741
|
if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
|
|
1378
|
-
decodeResult
|
|
1379
|
-
}
|
|
1380
|
-
if (decodeResult.raw.position) {
|
|
1381
|
-
decodeResult.formatted.items.push({
|
|
1382
|
-
type: "position",
|
|
1383
|
-
code: "POS",
|
|
1384
|
-
label: "Position",
|
|
1385
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1386
|
-
});
|
|
1742
|
+
ResultFormatter.remainingFuel(decodeResult, Number(results.groups.fuel_in_tons));
|
|
1387
1743
|
}
|
|
1388
|
-
decodeResult.formatted.items.push({
|
|
1389
|
-
type: "origin",
|
|
1390
|
-
code: "ORG",
|
|
1391
|
-
label: "Origin",
|
|
1392
|
-
value: decodeResult.raw.departure_icao
|
|
1393
|
-
});
|
|
1394
|
-
decodeResult.formatted.items.push({
|
|
1395
|
-
type: "destination",
|
|
1396
|
-
code: "DST",
|
|
1397
|
-
label: "Destination",
|
|
1398
|
-
value: decodeResult.raw.arrival_icao
|
|
1399
|
-
});
|
|
1400
1744
|
}
|
|
1401
1745
|
decodeResult.decoded = true;
|
|
1402
1746
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1420,40 +1764,20 @@ var Label_44_IN = class extends DecoderPlugin {
|
|
|
1420
1764
|
decodeResult.message = message;
|
|
1421
1765
|
const regex = /^.*,(?<unsplit_coords>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<fuel_in_tons>.*)$/;
|
|
1422
1766
|
const results = message.text.match(regex);
|
|
1423
|
-
if (results) {
|
|
1767
|
+
if (results?.groups) {
|
|
1424
1768
|
if (options.debug) {
|
|
1425
1769
|
console.log(`Label 44 In Air Report: groups`);
|
|
1426
1770
|
console.log(results.groups);
|
|
1427
1771
|
}
|
|
1428
|
-
|
|
1429
|
-
decodeResult
|
|
1430
|
-
decodeResult
|
|
1772
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords));
|
|
1773
|
+
ResultFormatter.departureAirport(decodeResult, results.groups.departure_icao);
|
|
1774
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
1431
1775
|
decodeResult.raw.current_time = Date.parse(
|
|
1432
1776
|
(/* @__PURE__ */ new Date()).getFullYear() + "-" + results.groups.current_date.substr(0, 2) + "-" + results.groups.current_date.substr(2, 2) + "T" + results.groups.current_time.substr(0, 2) + ":" + results.groups.current_time.substr(2, 2) + ":00Z"
|
|
1433
1777
|
);
|
|
1434
1778
|
if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
|
|
1435
1779
|
decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
|
|
1436
1780
|
}
|
|
1437
|
-
if (decodeResult.raw.position) {
|
|
1438
|
-
decodeResult.formatted.items.push({
|
|
1439
|
-
type: "position",
|
|
1440
|
-
code: "POS",
|
|
1441
|
-
label: "Position",
|
|
1442
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1443
|
-
});
|
|
1444
|
-
}
|
|
1445
|
-
decodeResult.formatted.items.push({
|
|
1446
|
-
type: "origin",
|
|
1447
|
-
code: "ORG",
|
|
1448
|
-
label: "Origin",
|
|
1449
|
-
value: decodeResult.raw.departure_icao
|
|
1450
|
-
});
|
|
1451
|
-
decodeResult.formatted.items.push({
|
|
1452
|
-
type: "destination",
|
|
1453
|
-
code: "DST",
|
|
1454
|
-
label: "Destination",
|
|
1455
|
-
value: decodeResult.raw.arrival_icao
|
|
1456
|
-
});
|
|
1457
1781
|
}
|
|
1458
1782
|
decodeResult.decoded = true;
|
|
1459
1783
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1477,13 +1801,14 @@ var Label_44_OFF = class extends DecoderPlugin {
|
|
|
1477
1801
|
decodeResult.message = message;
|
|
1478
1802
|
const regex = /^.*,(?<unsplit_coords>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<eta_time>.*),(?<fuel_in_tons>.*)$/;
|
|
1479
1803
|
const results = message.text.match(regex);
|
|
1480
|
-
if (results) {
|
|
1804
|
+
if (results?.groups) {
|
|
1481
1805
|
if (options.debug) {
|
|
1482
1806
|
console.log(`Label 44 Off Runway Report: groups`);
|
|
1483
1807
|
console.log(results.groups);
|
|
1484
1808
|
}
|
|
1485
|
-
decodeResult.
|
|
1486
|
-
decodeResult
|
|
1809
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords));
|
|
1810
|
+
ResultFormatter.departureAirport(decodeResult, results.groups.departure_icao);
|
|
1811
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
1487
1812
|
decodeResult.raw.current_time = Date.parse(
|
|
1488
1813
|
(/* @__PURE__ */ new Date()).getFullYear() + "-" + results.groups.current_date.substr(0, 2) + "-" + results.groups.current_date.substr(2, 2) + "T" + results.groups.current_time.substr(0, 2) + ":" + results.groups.current_time.substr(2, 2) + ":00Z"
|
|
1489
1814
|
);
|
|
@@ -1493,27 +1818,6 @@ var Label_44_OFF = class extends DecoderPlugin {
|
|
|
1493
1818
|
if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
|
|
1494
1819
|
decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
|
|
1495
1820
|
}
|
|
1496
|
-
decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords);
|
|
1497
|
-
if (decodeResult.raw.position) {
|
|
1498
|
-
decodeResult.formatted.items.push({
|
|
1499
|
-
type: "position",
|
|
1500
|
-
code: "POS",
|
|
1501
|
-
label: "Position",
|
|
1502
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1503
|
-
});
|
|
1504
|
-
}
|
|
1505
|
-
decodeResult.formatted.items.push({
|
|
1506
|
-
type: "origin",
|
|
1507
|
-
code: "ORG",
|
|
1508
|
-
label: "Origin",
|
|
1509
|
-
value: decodeResult.raw.departure_icao
|
|
1510
|
-
});
|
|
1511
|
-
decodeResult.formatted.items.push({
|
|
1512
|
-
type: "destination",
|
|
1513
|
-
code: "DST",
|
|
1514
|
-
label: "Destination",
|
|
1515
|
-
value: decodeResult.raw.arrival_icao
|
|
1516
|
-
});
|
|
1517
1821
|
}
|
|
1518
1822
|
decodeResult.decoded = true;
|
|
1519
1823
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1537,40 +1841,20 @@ var Label_44_ON = class extends DecoderPlugin {
|
|
|
1537
1841
|
decodeResult.message = message;
|
|
1538
1842
|
const regex = /^.*,(?<unsplit_coords>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<fuel_in_tons>.*)$/;
|
|
1539
1843
|
const results = message.text.match(regex);
|
|
1540
|
-
if (results) {
|
|
1844
|
+
if (results?.groups) {
|
|
1541
1845
|
if (options.debug) {
|
|
1542
1846
|
console.log(`Label 44 On Runway Report: groups`);
|
|
1543
1847
|
console.log(results.groups);
|
|
1544
1848
|
}
|
|
1545
|
-
|
|
1546
|
-
decodeResult
|
|
1547
|
-
decodeResult
|
|
1849
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords));
|
|
1850
|
+
ResultFormatter.departureAirport(decodeResult, results.groups.departure_icao);
|
|
1851
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
1548
1852
|
decodeResult.raw.current_time = Date.parse(
|
|
1549
1853
|
(/* @__PURE__ */ new Date()).getFullYear() + "-" + results.groups.current_date.substr(0, 2) + "-" + results.groups.current_date.substr(2, 2) + "T" + results.groups.current_time.substr(0, 2) + ":" + results.groups.current_time.substr(2, 2) + ":00Z"
|
|
1550
1854
|
);
|
|
1551
1855
|
if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
|
|
1552
|
-
decodeResult
|
|
1856
|
+
ResultFormatter.remainingFuel(decodeResult, Number(results.groups.fuel_in_tons));
|
|
1553
1857
|
}
|
|
1554
|
-
if (decodeResult.raw.position) {
|
|
1555
|
-
decodeResult.formatted.items.push({
|
|
1556
|
-
type: "position",
|
|
1557
|
-
code: "POS",
|
|
1558
|
-
label: "Position",
|
|
1559
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1560
|
-
});
|
|
1561
|
-
}
|
|
1562
|
-
decodeResult.formatted.items.push({
|
|
1563
|
-
type: "origin",
|
|
1564
|
-
code: "ORG",
|
|
1565
|
-
label: "Origin",
|
|
1566
|
-
value: decodeResult.raw.departure_icao
|
|
1567
|
-
});
|
|
1568
|
-
decodeResult.formatted.items.push({
|
|
1569
|
-
type: "destination",
|
|
1570
|
-
code: "DST",
|
|
1571
|
-
label: "Destination",
|
|
1572
|
-
value: decodeResult.raw.arrival_icao
|
|
1573
|
-
});
|
|
1574
1858
|
}
|
|
1575
1859
|
decodeResult.decoded = true;
|
|
1576
1860
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1594,12 +1878,12 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
1594
1878
|
decodeResult.message = message;
|
|
1595
1879
|
const regex = /^.*,(?<unsplit_coords>.*),(?<flight_level_or_ground>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<eta_time>.*),(?<fuel_in_tons>.*)$/;
|
|
1596
1880
|
const results = message.text.match(regex);
|
|
1597
|
-
if (results) {
|
|
1881
|
+
if (results?.groups) {
|
|
1598
1882
|
if (options.debug) {
|
|
1599
1883
|
console.log(`Label 44 Position Report: groups`);
|
|
1600
1884
|
console.log(results.groups);
|
|
1601
1885
|
}
|
|
1602
|
-
|
|
1886
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinatesDecimalMinutes(results.groups.unsplit_coords));
|
|
1603
1887
|
const flight_level = results.groups.flight_level_or_ground == "GRD" || results.groups.flight_level_or_ground == "***" ? 0 : Number(results.groups.flight_level_or_ground);
|
|
1604
1888
|
decodeResult.raw.current_time = Date.parse(
|
|
1605
1889
|
(/* @__PURE__ */ new Date()).getFullYear() + "-" + results.groups.current_date.substr(0, 2) + "-" + results.groups.current_date.substr(2, 2) + "T" + results.groups.current_time.substr(0, 2) + ":" + results.groups.current_time.substr(2, 2) + ":00Z"
|
|
@@ -1610,14 +1894,6 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
1610
1894
|
if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
|
|
1611
1895
|
decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
|
|
1612
1896
|
}
|
|
1613
|
-
if (decodeResult.raw.position) {
|
|
1614
|
-
decodeResult.formatted.items.push({
|
|
1615
|
-
type: "aircraft_position",
|
|
1616
|
-
code: "POS",
|
|
1617
|
-
label: "Aircraft Position",
|
|
1618
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1619
|
-
});
|
|
1620
|
-
}
|
|
1621
1897
|
ResultFormatter.departureAirport(decodeResult, results.groups.departure_icao);
|
|
1622
1898
|
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
1623
1899
|
ResultFormatter.altitude(decodeResult, flight_level * 100);
|
|
@@ -1641,13 +1917,13 @@ var Label_4A = class extends DecoderPlugin {
|
|
|
1641
1917
|
decodeResult.decoder.name = this.name;
|
|
1642
1918
|
decodeResult.message = message;
|
|
1643
1919
|
decodeResult.formatted.description = "Latest New Format";
|
|
1644
|
-
let
|
|
1645
|
-
if (
|
|
1920
|
+
let text = message.text;
|
|
1921
|
+
if (text.match(/^M\d{2}A\w{6}/)) {
|
|
1646
1922
|
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
1647
|
-
|
|
1923
|
+
text = text.substring(10);
|
|
1648
1924
|
}
|
|
1649
1925
|
decodeResult.decoded = true;
|
|
1650
|
-
const fields =
|
|
1926
|
+
const fields = text.split(",");
|
|
1651
1927
|
if (fields.length === 11) {
|
|
1652
1928
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[0]));
|
|
1653
1929
|
ResultFormatter.tail(decodeResult, fields[2].replace(".", ""));
|
|
@@ -1655,8 +1931,8 @@ var Label_4A = class extends DecoderPlugin {
|
|
|
1655
1931
|
ResultFormatter.callsign(decodeResult, fields[3]);
|
|
1656
1932
|
ResultFormatter.departureAirport(decodeResult, fields[4]);
|
|
1657
1933
|
ResultFormatter.arrivalAirport(decodeResult, fields[5]);
|
|
1658
|
-
ResultFormatter.altitude(decodeResult,
|
|
1659
|
-
decodeResult
|
|
1934
|
+
ResultFormatter.altitude(decodeResult, Number(text.substring(48, 51)) * 100);
|
|
1935
|
+
ResultFormatter.unknownArr(decodeResult, fields.slice(8));
|
|
1660
1936
|
} else if (fields.length === 6) {
|
|
1661
1937
|
if (fields[0].match(/^[NS]/)) {
|
|
1662
1938
|
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(fields[0].substring(0, 13)));
|
|
@@ -1665,31 +1941,25 @@ var Label_4A = class extends DecoderPlugin {
|
|
|
1665
1941
|
time: DateTimeUtils.convertHHMMSSToTod(fields[1].substring(0, 6)),
|
|
1666
1942
|
timeFormat: "tod"
|
|
1667
1943
|
};
|
|
1668
|
-
ResultFormatter.altitude(decodeResult, fields[1].substring(6, 9) * 100);
|
|
1944
|
+
ResultFormatter.altitude(decodeResult, Number(fields[1].substring(6, 9)) * 100);
|
|
1669
1945
|
let wp2 = {
|
|
1670
1946
|
name: fields[1].substring(9).trim(),
|
|
1671
1947
|
time: DateTimeUtils.convertHHMMSSToTod(fields[2]),
|
|
1672
1948
|
timeFormat: "tod"
|
|
1673
1949
|
};
|
|
1674
|
-
|
|
1675
|
-
decodeResult.formatted.items.push({
|
|
1676
|
-
type: "aircraft_route",
|
|
1677
|
-
code: "ROUTE",
|
|
1678
|
-
label: "Aircraft Route",
|
|
1679
|
-
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
1680
|
-
});
|
|
1950
|
+
ResultFormatter.route(decodeResult, { waypoints: [wp1, wp2] });
|
|
1681
1951
|
ResultFormatter.temperature(decodeResult, fields[3]);
|
|
1682
|
-
decodeResult
|
|
1952
|
+
ResultFormatter.unknownArr(decodeResult, fields.slice(4));
|
|
1683
1953
|
} else {
|
|
1684
1954
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[0]));
|
|
1685
1955
|
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1]));
|
|
1686
|
-
decodeResult
|
|
1687
|
-
ResultFormatter.altitude(decodeResult, fields[3]);
|
|
1956
|
+
ResultFormatter.unknown(decodeResult, fields[2]);
|
|
1957
|
+
ResultFormatter.altitude(decodeResult, Number(fields[3]));
|
|
1688
1958
|
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates((fields[4] + fields[5]).replace(/[ \.]/g, "")));
|
|
1689
1959
|
}
|
|
1690
1960
|
} else {
|
|
1691
1961
|
decodeResult.decoded = false;
|
|
1692
|
-
decodeResult
|
|
1962
|
+
ResultFormatter.unknown(decodeResult, text);
|
|
1693
1963
|
}
|
|
1694
1964
|
if (decodeResult.decoded) {
|
|
1695
1965
|
if (!decodeResult.remaining.text)
|
|
@@ -1726,11 +1996,11 @@ var Label_4A_01 = class extends DecoderPlugin {
|
|
|
1726
1996
|
ResultFormatter.departureAirport(decodeResult, rgx[5]);
|
|
1727
1997
|
ResultFormatter.arrivalAirport(decodeResult, rgx[6]);
|
|
1728
1998
|
ResultFormatter.altitude(decodeResult, Number(rgx[7].replace(/ /g, "")));
|
|
1729
|
-
decodeResult
|
|
1999
|
+
ResultFormatter.unknown(decodeResult, rgx[8]);
|
|
1730
2000
|
ResultFormatter.temperature(decodeResult, rgx[9].replace(/ /g, ""));
|
|
1731
2001
|
} else {
|
|
1732
2002
|
decodeResult.decoded = false;
|
|
1733
|
-
decodeResult
|
|
2003
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
1734
2004
|
}
|
|
1735
2005
|
if (decodeResult.decoded) {
|
|
1736
2006
|
if (!decodeResult.remaining.text)
|
|
@@ -1796,7 +2066,7 @@ var Label_4A_DOOR = class extends DecoderPlugin {
|
|
|
1796
2066
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2] + "00"));
|
|
1797
2067
|
} else {
|
|
1798
2068
|
decodeResult.decoded = false;
|
|
1799
|
-
decodeResult.
|
|
2069
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
1800
2070
|
}
|
|
1801
2071
|
if (decodeResult.decoded) {
|
|
1802
2072
|
if (!decodeResult.remaining.text)
|
|
@@ -1826,10 +2096,10 @@ var Label_4A_Slash_01 = class extends DecoderPlugin {
|
|
|
1826
2096
|
decodeResult.formatted.description = "Latest New Format";
|
|
1827
2097
|
decodeResult.decoded = true;
|
|
1828
2098
|
if (message.text.length === 5 && message.text.substring(0, 4) === "/01-") {
|
|
1829
|
-
decodeResult
|
|
2099
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(4));
|
|
1830
2100
|
} else {
|
|
1831
2101
|
decodeResult.decoded = false;
|
|
1832
|
-
decodeResult
|
|
2102
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
1833
2103
|
}
|
|
1834
2104
|
if (decodeResult.decoded) {
|
|
1835
2105
|
if (!decodeResult.remaining.text)
|
|
@@ -1843,630 +2113,93 @@ var Label_4A_Slash_01 = class extends DecoderPlugin {
|
|
|
1843
2113
|
}
|
|
1844
2114
|
};
|
|
1845
2115
|
|
|
1846
|
-
// lib/
|
|
1847
|
-
var
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
let
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
2116
|
+
// lib/utils/flight_plan_utils.ts
|
|
2117
|
+
var FlightPlanUtils = class _FlightPlanUtils {
|
|
2118
|
+
/**
|
|
2119
|
+
* Processes flight plan data
|
|
2120
|
+
*
|
|
2121
|
+
* Expected format is [header, key1, val1, ... keyN, valN]
|
|
2122
|
+
*
|
|
2123
|
+
* @param decodeResult - results
|
|
2124
|
+
* @param data - original message split by ':'
|
|
2125
|
+
* @returns whether all fields were processed or not
|
|
2126
|
+
*/
|
|
2127
|
+
static processFlightPlan(decodeResult, data) {
|
|
2128
|
+
let allKnownFields = _FlightPlanUtils.parseHeader(decodeResult, data[0]);
|
|
2129
|
+
for (let i = 1; i < data.length; i += 2) {
|
|
2130
|
+
const key = data[i];
|
|
2131
|
+
const value = data[i + 1];
|
|
2132
|
+
switch (key) {
|
|
2133
|
+
case "A":
|
|
2134
|
+
addProcedure(decodeResult, value, "arrival");
|
|
2135
|
+
break;
|
|
2136
|
+
case "AA":
|
|
2137
|
+
addArrivalAirport(decodeResult, value);
|
|
2138
|
+
break;
|
|
2139
|
+
case "AP":
|
|
2140
|
+
addProcedure(decodeResult, value, "approach");
|
|
2141
|
+
break;
|
|
2142
|
+
case "CR":
|
|
2143
|
+
addCompanyRoute(decodeResult, value);
|
|
2144
|
+
break;
|
|
2145
|
+
case "D":
|
|
2146
|
+
addProcedure(decodeResult, value, "departure");
|
|
2147
|
+
break;
|
|
2148
|
+
case "DA":
|
|
2149
|
+
addDepartureAirport(decodeResult, value);
|
|
2150
|
+
break;
|
|
2151
|
+
case "F":
|
|
2152
|
+
addRoute(decodeResult, value);
|
|
2153
|
+
break;
|
|
2154
|
+
case "R":
|
|
2155
|
+
addRunway(decodeResult, value);
|
|
2156
|
+
break;
|
|
2157
|
+
// case 'WS': // something about routes, has altitude, so current parsing won't work
|
|
2158
|
+
// break;
|
|
2159
|
+
default:
|
|
2160
|
+
if (allKnownFields) {
|
|
2161
|
+
decodeResult.remaining.text = "";
|
|
2162
|
+
allKnownFields = false;
|
|
2163
|
+
}
|
|
2164
|
+
decodeResult.remaining.text += `:${key}:${value}`;
|
|
2165
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1878
2166
|
}
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
2167
|
+
}
|
|
2168
|
+
return allKnownFields;
|
|
2169
|
+
}
|
|
2170
|
+
static parseHeader(decodeResult, header) {
|
|
2171
|
+
let allKnownFields = true;
|
|
2172
|
+
if (header.startsWith("RF")) {
|
|
2173
|
+
decodeResult.formatted.items.push({
|
|
2174
|
+
type: "status",
|
|
2175
|
+
code: "ROUTE_STATUS",
|
|
2176
|
+
label: "Route Status",
|
|
2177
|
+
value: "Route Filed"
|
|
2178
|
+
});
|
|
2179
|
+
decodeResult.raw.route_status = "RF";
|
|
2180
|
+
if (header.length > 2) {
|
|
2181
|
+
addRoute(decodeResult, header.substring(2));
|
|
1885
2182
|
}
|
|
1886
|
-
|
|
1887
|
-
decodeResult.
|
|
2183
|
+
} else if (header.startsWith("RP")) {
|
|
2184
|
+
decodeResult.raw.route_status = "RP";
|
|
2185
|
+
decodeResult.formatted.items.push({
|
|
2186
|
+
type: "status",
|
|
2187
|
+
code: "ROUTE_STATUS",
|
|
2188
|
+
label: "Route Status",
|
|
2189
|
+
value: "Route Planned"
|
|
2190
|
+
});
|
|
2191
|
+
decodeResult.raw.route_status = header;
|
|
2192
|
+
} else if (header.startsWith("RI")) {
|
|
2193
|
+
decodeResult.raw.route_status = "RI";
|
|
2194
|
+
decodeResult.formatted.items.push({
|
|
2195
|
+
type: "status",
|
|
2196
|
+
code: "ROUTE_STATUS",
|
|
2197
|
+
label: "Route Status",
|
|
2198
|
+
value: "Route Inactive"
|
|
2199
|
+
});
|
|
1888
2200
|
} else {
|
|
1889
|
-
decodeResult.
|
|
1890
|
-
|
|
1891
|
-
}
|
|
1892
|
-
if (decodeResult.decoded) {
|
|
1893
|
-
if (!decodeResult.remaining.text)
|
|
1894
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
1895
|
-
else
|
|
1896
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1897
|
-
} else {
|
|
1898
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
1899
|
-
}
|
|
1900
|
-
return decodeResult;
|
|
1901
|
-
}
|
|
1902
|
-
};
|
|
1903
|
-
|
|
1904
|
-
// lib/plugins/Label_80.ts
|
|
1905
|
-
var Label_80 = class extends DecoderPlugin {
|
|
1906
|
-
name = "label-80";
|
|
1907
|
-
descriptions = {
|
|
1908
|
-
ALT: "Altitude",
|
|
1909
|
-
DWND: "Wind Direction",
|
|
1910
|
-
ETA: "Estimated Time of Arrival",
|
|
1911
|
-
FOB: "Fuel on Board",
|
|
1912
|
-
FL: "Flight Level",
|
|
1913
|
-
HDG: "Heading",
|
|
1914
|
-
MCH: "Aircraft Speed",
|
|
1915
|
-
NWYP: "Next Waypoint",
|
|
1916
|
-
POS: "Aircraft Position",
|
|
1917
|
-
SAT: "Static Air Temperature",
|
|
1918
|
-
SWND: "Wind Speed",
|
|
1919
|
-
TAS: "True Airspeed",
|
|
1920
|
-
WYP: "Waypoint"
|
|
1921
|
-
};
|
|
1922
|
-
qualifiers() {
|
|
1923
|
-
return {
|
|
1924
|
-
labels: ["80"],
|
|
1925
|
-
preambles: ["3N01 POSRPT"]
|
|
1926
|
-
};
|
|
1927
|
-
}
|
|
1928
|
-
decode(message, options = {}) {
|
|
1929
|
-
const decodeResult = this.defaultResult();
|
|
1930
|
-
decodeResult.decoder.name = this.name;
|
|
1931
|
-
decodeResult.formatted.description = "Airline Defined Position Report";
|
|
1932
|
-
const parts = message.text.split("\n");
|
|
1933
|
-
let posRptRegex = /^3N01 POSRPT \d\d\d\d\/\d\d (?<orig>\w+)\/(?<dest>\w+) \.(?<tail>[\w-]+)(\/(?<agate>.+) (?<sta>\w+:\w+))*/;
|
|
1934
|
-
let results = parts[0].match(posRptRegex);
|
|
1935
|
-
if (!results?.groups) {
|
|
1936
|
-
decodeResult.decoded = false;
|
|
1937
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
1938
|
-
return decodeResult;
|
|
1939
|
-
}
|
|
1940
|
-
if (results && results.length > 0) {
|
|
1941
|
-
ResultFormatter.departureAirport(decodeResult, results.groups.orig);
|
|
1942
|
-
ResultFormatter.arrivalAirport(decodeResult, results.groups.dest);
|
|
1943
|
-
ResultFormatter.tail(decodeResult, results.groups.tail);
|
|
1944
|
-
if (results.groups.agate) {
|
|
1945
|
-
decodeResult.raw.arrival_gate = results.groups.agate;
|
|
1946
|
-
decodeResult.formatted.items.push({
|
|
1947
|
-
type: "arrival_gate",
|
|
1948
|
-
code: "ARG",
|
|
1949
|
-
label: "Arrival Gate",
|
|
1950
|
-
value: `${results.groups.agate}`
|
|
1951
|
-
});
|
|
1952
|
-
decodeResult.raw.scheduled_time_of_arrival = results.groups.sta;
|
|
1953
|
-
decodeResult.formatted.items.push({
|
|
1954
|
-
type: "scheduled_time_of_arrival",
|
|
1955
|
-
code: "STA",
|
|
1956
|
-
label: "Scheduled Time of Arrival",
|
|
1957
|
-
value: `${results.groups.sta}`
|
|
1958
|
-
});
|
|
1959
|
-
}
|
|
1960
|
-
posRptRegex = /\/(?<field>\w+)\s(?<value>[\w\+\-:\.]+)\s*/gi;
|
|
1961
|
-
const remainingParts = parts.slice(1);
|
|
1962
|
-
for (const part of remainingParts) {
|
|
1963
|
-
const matches = part.matchAll(posRptRegex);
|
|
1964
|
-
for (const match of matches) {
|
|
1965
|
-
switch (match.groups?.field) {
|
|
1966
|
-
case "ALT": {
|
|
1967
|
-
ResultFormatter.altitude(decodeResult, Number(match.groups.value));
|
|
1968
|
-
break;
|
|
1969
|
-
}
|
|
1970
|
-
case "DWND": {
|
|
1971
|
-
decodeResult.raw.wind_direction = Number(match.groups.value);
|
|
1972
|
-
decodeResult.formatted.items.push({
|
|
1973
|
-
type: "wind_direction",
|
|
1974
|
-
code: "DWND",
|
|
1975
|
-
label: this.descriptions[match.groups.field],
|
|
1976
|
-
value: decodeResult.raw.wind_direction
|
|
1977
|
-
});
|
|
1978
|
-
break;
|
|
1979
|
-
}
|
|
1980
|
-
case "FL": {
|
|
1981
|
-
const flight_level = Number(match.groups.value);
|
|
1982
|
-
ResultFormatter.altitude(decodeResult, flight_level * 100);
|
|
1983
|
-
break;
|
|
1984
|
-
}
|
|
1985
|
-
case "FOB": {
|
|
1986
|
-
decodeResult.raw.fuel_on_board = match.groups.value;
|
|
1987
|
-
decodeResult.formatted.items.push({
|
|
1988
|
-
type: "fuel_on_board",
|
|
1989
|
-
code: "FOB",
|
|
1990
|
-
label: this.descriptions[match.groups.field],
|
|
1991
|
-
value: decodeResult.raw.fuel_on_board
|
|
1992
|
-
});
|
|
1993
|
-
break;
|
|
1994
|
-
}
|
|
1995
|
-
case "HDG": {
|
|
1996
|
-
decodeResult.raw.heading = Number(match.groups.value);
|
|
1997
|
-
decodeResult.formatted.items.push({
|
|
1998
|
-
type: "heading",
|
|
1999
|
-
code: "HDG",
|
|
2000
|
-
label: this.descriptions[match.groups.field],
|
|
2001
|
-
value: decodeResult.raw.heading
|
|
2002
|
-
});
|
|
2003
|
-
break;
|
|
2004
|
-
}
|
|
2005
|
-
case "MCH": {
|
|
2006
|
-
decodeResult.raw.mach = Number(match.groups.value) / 1e3;
|
|
2007
|
-
decodeResult.formatted.items.push({
|
|
2008
|
-
type: "mach",
|
|
2009
|
-
code: "MCH",
|
|
2010
|
-
label: this.descriptions[match.groups.field],
|
|
2011
|
-
value: `${decodeResult.raw.mach} Mach`
|
|
2012
|
-
});
|
|
2013
|
-
break;
|
|
2014
|
-
}
|
|
2015
|
-
case "NWYP": {
|
|
2016
|
-
decodeResult.raw.next_waypoint = match.groups.value;
|
|
2017
|
-
decodeResult.formatted.items.push({
|
|
2018
|
-
type: "next_waypoint",
|
|
2019
|
-
code: "NWYP",
|
|
2020
|
-
label: this.descriptions[match.groups.field],
|
|
2021
|
-
value: decodeResult.raw.next_waypoint
|
|
2022
|
-
});
|
|
2023
|
-
break;
|
|
2024
|
-
}
|
|
2025
|
-
case "POS": {
|
|
2026
|
-
const posRegex = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
|
|
2027
|
-
const posResult = match.groups.value.match(posRegex);
|
|
2028
|
-
const lat = Number(posResult?.groups?.lat) * (posResult?.groups?.lngd === "S" ? -1 : 1);
|
|
2029
|
-
const lon = Number(posResult?.groups?.lng) * (posResult?.groups?.lngd === "W" ? -1 : 1);
|
|
2030
|
-
const position = {
|
|
2031
|
-
latitude: Number.isInteger(lat) ? lat / 1e3 : lat / 100,
|
|
2032
|
-
longitude: Number.isInteger(lon) ? lon / 1e3 : lon / 100
|
|
2033
|
-
};
|
|
2034
|
-
ResultFormatter.position(decodeResult, position);
|
|
2035
|
-
break;
|
|
2036
|
-
}
|
|
2037
|
-
case "SWND": {
|
|
2038
|
-
decodeResult.raw.wind_speed = Number(match.groups.value);
|
|
2039
|
-
decodeResult.formatted.items.push({
|
|
2040
|
-
type: "wind_speed",
|
|
2041
|
-
code: "SWND",
|
|
2042
|
-
label: this.descriptions[match.groups.field],
|
|
2043
|
-
value: decodeResult.raw.wind_speed
|
|
2044
|
-
});
|
|
2045
|
-
break;
|
|
2046
|
-
}
|
|
2047
|
-
default: {
|
|
2048
|
-
if (match.groups?.field != void 0) {
|
|
2049
|
-
const description = this.descriptions[match.groups.field] ? this.descriptions[match.groups.field] : "Unknown";
|
|
2050
|
-
decodeResult.formatted.items.push({
|
|
2051
|
-
type: match.groups.field,
|
|
2052
|
-
code: match.groups.field,
|
|
2053
|
-
label: description || `Unknown (${match.groups.field})`,
|
|
2054
|
-
value: `${match.groups.value}`
|
|
2055
|
-
});
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
}
|
|
2059
|
-
}
|
|
2060
|
-
}
|
|
2061
|
-
decodeResult.decoded = true;
|
|
2062
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2063
|
-
}
|
|
2064
|
-
return decodeResult;
|
|
2065
|
-
}
|
|
2066
|
-
};
|
|
2067
|
-
|
|
2068
|
-
// lib/plugins/Label_83.ts
|
|
2069
|
-
var Label_83 = class extends DecoderPlugin {
|
|
2070
|
-
name = "label-83";
|
|
2071
|
-
qualifiers() {
|
|
2072
|
-
return {
|
|
2073
|
-
labels: ["83"]
|
|
2074
|
-
};
|
|
2075
|
-
}
|
|
2076
|
-
decode(message, options = {}) {
|
|
2077
|
-
const decodeResult = this.defaultResult();
|
|
2078
|
-
decodeResult.decoder.name = this.name;
|
|
2079
|
-
decodeResult.message = message;
|
|
2080
|
-
decodeResult.formatted.description = "Airline Defined";
|
|
2081
|
-
let text2 = message.text;
|
|
2082
|
-
if (text2.match(/^M\d{2}A\w{6}/)) {
|
|
2083
|
-
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
2084
|
-
text2 = text2.substring(10);
|
|
2085
|
-
}
|
|
2086
|
-
decodeResult.decoded = true;
|
|
2087
|
-
if (text2.substring(0, 10) === "4DH3 ETAT2") {
|
|
2088
|
-
const fields = text2.split(/\s+/);
|
|
2089
|
-
if (fields[2].length > 5) {
|
|
2090
|
-
decodeResult.raw.day_of_month = fields[2].substring(5);
|
|
2091
|
-
}
|
|
2092
|
-
decodeResult.remaining.text = fields[2].substring(0, 4);
|
|
2093
|
-
const subfields = fields[3].split("/");
|
|
2094
|
-
ResultFormatter.departureAirport(decodeResult, subfields[0]);
|
|
2095
|
-
ResultFormatter.arrivalAirport(decodeResult, subfields[1]);
|
|
2096
|
-
ResultFormatter.tail(decodeResult, fields[4].replace(/\./g, ""));
|
|
2097
|
-
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[6] + "00"));
|
|
2098
|
-
} else if (text2.substring(0, 5) === "001PR") {
|
|
2099
|
-
decodeResult.raw.day_of_month = text2.substring(5, 7);
|
|
2100
|
-
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(text2.substring(13, 28).replace(/\./g, ""));
|
|
2101
|
-
if (position) {
|
|
2102
|
-
ResultFormatter.position(decodeResult, position);
|
|
2103
|
-
}
|
|
2104
|
-
ResultFormatter.altitude(decodeResult, Number(text2.substring(28, 33)));
|
|
2105
|
-
decodeResult.remaining.text = text2.substring(33);
|
|
2106
|
-
} else {
|
|
2107
|
-
const fields = text2.replace(/\s/g, "").split(",");
|
|
2108
|
-
if (fields.length === 9) {
|
|
2109
|
-
ResultFormatter.departureAirport(decodeResult, fields[0]);
|
|
2110
|
-
ResultFormatter.arrivalAirport(decodeResult, fields[1]);
|
|
2111
|
-
decodeResult.raw.day_of_month = fields[2].substring(0, 2);
|
|
2112
|
-
decodeResult.raw.time = fields[2].substring(2);
|
|
2113
|
-
ResultFormatter.position(
|
|
2114
|
-
decodeResult,
|
|
2115
|
-
{
|
|
2116
|
-
latitude: Number(fields[3].replace(/\s/g, "")),
|
|
2117
|
-
longitude: Number(fields[4].replace(/\s/g, ""))
|
|
2118
|
-
}
|
|
2119
|
-
);
|
|
2120
|
-
ResultFormatter.altitude(decodeResult, Number(fields[5]));
|
|
2121
|
-
ResultFormatter.groundspeed(decodeResult, fields[6]);
|
|
2122
|
-
ResultFormatter.heading(decodeResult, fields[7]);
|
|
2123
|
-
decodeResult.remaining.text = fields[8];
|
|
2124
|
-
} else {
|
|
2125
|
-
decodeResult.decoded = false;
|
|
2126
|
-
decodeResult.remaining.text = message.text;
|
|
2127
|
-
}
|
|
2128
|
-
}
|
|
2129
|
-
if (decodeResult.decoded) {
|
|
2130
|
-
if (!decodeResult.remaining.text)
|
|
2131
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
2132
|
-
else
|
|
2133
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2134
|
-
} else {
|
|
2135
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2136
|
-
}
|
|
2137
|
-
return decodeResult;
|
|
2138
|
-
}
|
|
2139
|
-
};
|
|
2140
|
-
|
|
2141
|
-
// lib/plugins/Label_8E.ts
|
|
2142
|
-
var Label_8E = class extends DecoderPlugin {
|
|
2143
|
-
name = "label-8e";
|
|
2144
|
-
qualifiers() {
|
|
2145
|
-
return {
|
|
2146
|
-
labels: ["8E"]
|
|
2147
|
-
};
|
|
2148
|
-
}
|
|
2149
|
-
decode(message, options = {}) {
|
|
2150
|
-
const decodeResult = this.defaultResult();
|
|
2151
|
-
decodeResult.decoder.name = this.name;
|
|
2152
|
-
decodeResult.formatted.description = "ETA Report";
|
|
2153
|
-
decodeResult.message = message;
|
|
2154
|
-
const regex = /^(?<arrival_icao>\w{4}),(?<arrival_eta>\d{4})$/;
|
|
2155
|
-
const results = message.text.match(regex);
|
|
2156
|
-
if (results) {
|
|
2157
|
-
if (options.debug) {
|
|
2158
|
-
console.log(`Label 8E ETA: groups`);
|
|
2159
|
-
console.log(results.groups);
|
|
2160
|
-
}
|
|
2161
|
-
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(results.groups.arrival_eta + "00"));
|
|
2162
|
-
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
2163
|
-
}
|
|
2164
|
-
decodeResult.decoded = true;
|
|
2165
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
2166
|
-
return decodeResult;
|
|
2167
|
-
}
|
|
2168
|
-
};
|
|
2169
|
-
|
|
2170
|
-
// lib/plugins/Label_B6.ts
|
|
2171
|
-
var Label_B6_Forwardslash = class extends DecoderPlugin {
|
|
2172
|
-
name = "label-b6-forwardslash";
|
|
2173
|
-
qualifiers() {
|
|
2174
|
-
return {
|
|
2175
|
-
labels: ["B6"],
|
|
2176
|
-
preambles: ["/"]
|
|
2177
|
-
};
|
|
2178
|
-
}
|
|
2179
|
-
decode(message, options = {}) {
|
|
2180
|
-
const decodeResult = this.defaultResult();
|
|
2181
|
-
decodeResult.decoder.name = this.name;
|
|
2182
|
-
decodeResult.formatted.description = "CPDLC Message";
|
|
2183
|
-
decodeResult.message = message;
|
|
2184
|
-
if (options.debug) {
|
|
2185
|
-
console.log("CPDLC: " + message);
|
|
2186
|
-
}
|
|
2187
|
-
return decodeResult;
|
|
2188
|
-
}
|
|
2189
|
-
};
|
|
2190
|
-
|
|
2191
|
-
// lib/plugins/Label_ColonComma.ts
|
|
2192
|
-
var Label_ColonComma = class extends DecoderPlugin {
|
|
2193
|
-
name = "label-colon-comma";
|
|
2194
|
-
qualifiers() {
|
|
2195
|
-
return {
|
|
2196
|
-
labels: [":;"]
|
|
2197
|
-
};
|
|
2198
|
-
}
|
|
2199
|
-
decode(message, options = {}) {
|
|
2200
|
-
const decodeResult = this.defaultResult();
|
|
2201
|
-
decodeResult.decoder.name = this.name;
|
|
2202
|
-
decodeResult.raw.frequency = Number(message.text) / 1e3;
|
|
2203
|
-
decodeResult.formatted.description = "Aircraft Transceiver Frequency Change";
|
|
2204
|
-
decodeResult.formatted.items.push({
|
|
2205
|
-
type: "frequency",
|
|
2206
|
-
label: "Frequency",
|
|
2207
|
-
value: `${decodeResult.raw.frequency} MHz`
|
|
2208
|
-
});
|
|
2209
|
-
decodeResult.decoded = true;
|
|
2210
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
2211
|
-
return decodeResult;
|
|
2212
|
-
}
|
|
2213
|
-
};
|
|
2214
|
-
|
|
2215
|
-
// lib/plugins/Label_H1_FLR.ts
|
|
2216
|
-
var Label_H1_FLR = class extends DecoderPlugin {
|
|
2217
|
-
name = "label-h1-flr";
|
|
2218
|
-
qualifiers() {
|
|
2219
|
-
return {
|
|
2220
|
-
labels: ["H1"],
|
|
2221
|
-
preambles: ["FLR", "#CFBFLR"]
|
|
2222
|
-
};
|
|
2223
|
-
}
|
|
2224
|
-
decode(message, options = {}) {
|
|
2225
|
-
let decodeResult = this.defaultResult();
|
|
2226
|
-
decodeResult.decoder.name = this.name;
|
|
2227
|
-
decodeResult.formatted.description = "Fault Log Report";
|
|
2228
|
-
decodeResult.message = message;
|
|
2229
|
-
const parts = message.text.split("/FR");
|
|
2230
|
-
if (parts.length > 1) {
|
|
2231
|
-
decodeResult.remaining.text = "";
|
|
2232
|
-
const fields = parts[0].split("/");
|
|
2233
|
-
for (let i = 1; i < fields.length; i++) {
|
|
2234
|
-
const field = fields[i];
|
|
2235
|
-
if (field.startsWith("PN")) {
|
|
2236
|
-
processUnknown(decodeResult, "/" + field);
|
|
2237
|
-
} else {
|
|
2238
|
-
processUnknown(decodeResult, "/" + field);
|
|
2239
|
-
}
|
|
2240
|
-
}
|
|
2241
|
-
const data = parts[1].substring(0, 20);
|
|
2242
|
-
const msg = parts[1].substring(20);
|
|
2243
|
-
const datetime = data.substring(0, 12);
|
|
2244
|
-
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
2245
|
-
processUnknown(decodeResult, data.substring(12));
|
|
2246
|
-
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
2247
|
-
decodeResult.raw.fault_message = msg;
|
|
2248
|
-
decodeResult.formatted.items.push({
|
|
2249
|
-
type: "fault",
|
|
2250
|
-
code: "FR",
|
|
2251
|
-
label: "Fault Report",
|
|
2252
|
-
value: decodeResult.raw.fault_message
|
|
2253
|
-
});
|
|
2254
|
-
decodeResult.decoded = true;
|
|
2255
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2256
|
-
} else {
|
|
2257
|
-
if (options.debug) {
|
|
2258
|
-
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2259
|
-
}
|
|
2260
|
-
decodeResult.remaining.text = message.text;
|
|
2261
|
-
decodeResult.decoded = false;
|
|
2262
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2263
|
-
}
|
|
2264
|
-
return decodeResult;
|
|
2265
|
-
}
|
|
2266
|
-
};
|
|
2267
|
-
function processUnknown(decodeResult, value) {
|
|
2268
|
-
decodeResult.remaining.text += value;
|
|
2269
|
-
}
|
|
2270
|
-
|
|
2271
|
-
// lib/plugins/Label_H1_OHMA.ts
|
|
2272
|
-
import * as zlib from "minizlib";
|
|
2273
|
-
var Label_H1_OHMA = class extends DecoderPlugin {
|
|
2274
|
-
name = "label-h1-ohma";
|
|
2275
|
-
qualifiers() {
|
|
2276
|
-
return {
|
|
2277
|
-
labels: ["H1"],
|
|
2278
|
-
preambles: ["OHMA", "/RTNBOCR.OHMA", "#T1B/RTNBOCR.OHMA"]
|
|
2279
|
-
};
|
|
2280
|
-
}
|
|
2281
|
-
decode(message, options = {}) {
|
|
2282
|
-
let decodeResult = this.defaultResult();
|
|
2283
|
-
decodeResult.decoder.name = this.name;
|
|
2284
|
-
decodeResult.formatted.description = "OHMA Message";
|
|
2285
|
-
decodeResult.message = message;
|
|
2286
|
-
decodeResult.remaining.text = "";
|
|
2287
|
-
const data = message.text.split("OHMA")[1];
|
|
2288
|
-
try {
|
|
2289
|
-
const compressedBuffer = Buffer.from(data, "base64");
|
|
2290
|
-
const decompress = new zlib.Inflate({ windowBits: 15 });
|
|
2291
|
-
decompress.write(compressedBuffer);
|
|
2292
|
-
decompress.flush(zlib.constants.Z_SYNC_FLUSH);
|
|
2293
|
-
const result = decompress.read();
|
|
2294
|
-
const jsonText = result.toString();
|
|
2295
|
-
let formattedMsg;
|
|
2296
|
-
let jsonMessage;
|
|
2297
|
-
try {
|
|
2298
|
-
jsonMessage = JSON.parse(jsonText).message;
|
|
2299
|
-
} catch {
|
|
2300
|
-
jsonMessage = jsonText;
|
|
2301
|
-
}
|
|
2302
|
-
try {
|
|
2303
|
-
const ohmaMsg = JSON.parse(jsonMessage);
|
|
2304
|
-
formattedMsg = JSON.stringify(ohmaMsg, null, 2);
|
|
2305
|
-
} catch {
|
|
2306
|
-
formattedMsg = jsonMessage;
|
|
2307
|
-
}
|
|
2308
|
-
decodeResult.decoded = true;
|
|
2309
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
2310
|
-
decodeResult.raw.ohma = jsonText;
|
|
2311
|
-
decodeResult.formatted.items.push({
|
|
2312
|
-
type: "ohma",
|
|
2313
|
-
code: "OHMA",
|
|
2314
|
-
label: "OHMA Downlink",
|
|
2315
|
-
value: formattedMsg
|
|
2316
|
-
});
|
|
2317
|
-
} catch (e) {
|
|
2318
|
-
if (options.debug) {
|
|
2319
|
-
console.log(`Decoder: Unknown H1 OHMA message: ${message.text}`, e);
|
|
2320
|
-
}
|
|
2321
|
-
decodeResult.remaining.text += message.text;
|
|
2322
|
-
decodeResult.decoded = false;
|
|
2323
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2324
|
-
}
|
|
2325
|
-
return decodeResult;
|
|
2326
|
-
}
|
|
2327
|
-
};
|
|
2328
|
-
|
|
2329
|
-
// lib/plugins/Label_H1_WRN.ts
|
|
2330
|
-
var Label_H1_WRN = class extends DecoderPlugin {
|
|
2331
|
-
name = "label-h1-wrn";
|
|
2332
|
-
qualifiers() {
|
|
2333
|
-
return {
|
|
2334
|
-
labels: ["H1"],
|
|
2335
|
-
preambles: ["WRN", "#CFBWRN"]
|
|
2336
|
-
};
|
|
2337
|
-
}
|
|
2338
|
-
decode(message, options = {}) {
|
|
2339
|
-
let decodeResult = this.defaultResult();
|
|
2340
|
-
decodeResult.decoder.name = this.name;
|
|
2341
|
-
decodeResult.formatted.description = "Warning Message";
|
|
2342
|
-
decodeResult.message = message;
|
|
2343
|
-
const parts = message.text.split("/WN");
|
|
2344
|
-
if (parts.length > 1) {
|
|
2345
|
-
decodeResult.remaining.text = "";
|
|
2346
|
-
const fields = parts[0].split("/");
|
|
2347
|
-
for (let i = 1; i < fields.length; i++) {
|
|
2348
|
-
const field = fields[i];
|
|
2349
|
-
if (field.startsWith("PN")) {
|
|
2350
|
-
processUnknown2(decodeResult, "/" + field);
|
|
2351
|
-
} else {
|
|
2352
|
-
processUnknown2(decodeResult, "/" + field);
|
|
2353
|
-
}
|
|
2354
|
-
}
|
|
2355
|
-
const data = parts[1].substring(0, 20);
|
|
2356
|
-
const msg = parts[1].substring(20);
|
|
2357
|
-
const datetime = data.substring(0, 12);
|
|
2358
|
-
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
2359
|
-
processUnknown2(decodeResult, data.substring(12));
|
|
2360
|
-
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
2361
|
-
decodeResult.raw.warning_message = msg;
|
|
2362
|
-
decodeResult.formatted.items.push({
|
|
2363
|
-
type: "warning",
|
|
2364
|
-
code: "WRN",
|
|
2365
|
-
label: "Warning Message",
|
|
2366
|
-
value: decodeResult.raw.warning_message
|
|
2367
|
-
});
|
|
2368
|
-
decodeResult.decoded = true;
|
|
2369
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2370
|
-
} else {
|
|
2371
|
-
if (options.debug) {
|
|
2372
|
-
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2373
|
-
}
|
|
2374
|
-
decodeResult.remaining.text = message.text;
|
|
2375
|
-
decodeResult.decoded = false;
|
|
2376
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2377
|
-
}
|
|
2378
|
-
return decodeResult;
|
|
2379
|
-
}
|
|
2380
|
-
};
|
|
2381
|
-
function processUnknown2(decodeResult, value) {
|
|
2382
|
-
decodeResult.remaining.text += value;
|
|
2383
|
-
}
|
|
2384
|
-
|
|
2385
|
-
// lib/utils/flight_plan_utils.ts
|
|
2386
|
-
var FlightPlanUtils = class _FlightPlanUtils {
|
|
2387
|
-
/**
|
|
2388
|
-
* Processes flight plan data
|
|
2389
|
-
*
|
|
2390
|
-
* Expected format is [header, key1, val1, ... keyN, valN]
|
|
2391
|
-
*
|
|
2392
|
-
* @param decodeResult - results
|
|
2393
|
-
* @param data - original message split by ':'
|
|
2394
|
-
* @returns whether all fields were processed or not
|
|
2395
|
-
*/
|
|
2396
|
-
static processFlightPlan(decodeResult, data) {
|
|
2397
|
-
let allKnownFields = _FlightPlanUtils.parseHeader(decodeResult, data[0]);
|
|
2398
|
-
for (let i = 1; i < data.length; i += 2) {
|
|
2399
|
-
const key = data[i];
|
|
2400
|
-
const value = data[i + 1];
|
|
2401
|
-
switch (key) {
|
|
2402
|
-
case "A":
|
|
2403
|
-
addProcedure(decodeResult, value, "arrival");
|
|
2404
|
-
break;
|
|
2405
|
-
case "AA":
|
|
2406
|
-
addArrivalAirport(decodeResult, value);
|
|
2407
|
-
break;
|
|
2408
|
-
case "AP":
|
|
2409
|
-
addProcedure(decodeResult, value, "approach");
|
|
2410
|
-
break;
|
|
2411
|
-
case "CR":
|
|
2412
|
-
addCompanyRoute(decodeResult, value);
|
|
2413
|
-
break;
|
|
2414
|
-
case "D":
|
|
2415
|
-
addProcedure(decodeResult, value, "departure");
|
|
2416
|
-
break;
|
|
2417
|
-
case "DA":
|
|
2418
|
-
addDepartureAirport(decodeResult, value);
|
|
2419
|
-
break;
|
|
2420
|
-
case "F":
|
|
2421
|
-
addRoute(decodeResult, value);
|
|
2422
|
-
break;
|
|
2423
|
-
case "R":
|
|
2424
|
-
addRunway(decodeResult, value);
|
|
2425
|
-
break;
|
|
2426
|
-
default:
|
|
2427
|
-
if (allKnownFields) {
|
|
2428
|
-
decodeResult.remaining.text = "";
|
|
2429
|
-
allKnownFields = false;
|
|
2430
|
-
}
|
|
2431
|
-
decodeResult.remaining.text += `:${key}:${value}`;
|
|
2432
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2433
|
-
}
|
|
2434
|
-
}
|
|
2435
|
-
return allKnownFields;
|
|
2436
|
-
}
|
|
2437
|
-
static parseHeader(decodeResult, header) {
|
|
2438
|
-
let allKnownFields = true;
|
|
2439
|
-
if (header.startsWith("RF")) {
|
|
2440
|
-
decodeResult.formatted.items.push({
|
|
2441
|
-
type: "status",
|
|
2442
|
-
code: "ROUTE_STATUS",
|
|
2443
|
-
label: "Route Status",
|
|
2444
|
-
value: "Route Filed"
|
|
2445
|
-
});
|
|
2446
|
-
decodeResult.raw.route_status = "RF";
|
|
2447
|
-
if (header.length > 2) {
|
|
2448
|
-
addRoute(decodeResult, header.substring(2));
|
|
2449
|
-
}
|
|
2450
|
-
} else if (header.startsWith("RP")) {
|
|
2451
|
-
decodeResult.raw.route_status = "RP";
|
|
2452
|
-
decodeResult.formatted.items.push({
|
|
2453
|
-
type: "status",
|
|
2454
|
-
code: "ROUTE_STATUS",
|
|
2455
|
-
label: "Route Status",
|
|
2456
|
-
value: "Route Planned"
|
|
2457
|
-
});
|
|
2458
|
-
decodeResult.raw.route_status = header;
|
|
2459
|
-
} else if (header.startsWith("RI")) {
|
|
2460
|
-
decodeResult.raw.route_status = "RI";
|
|
2461
|
-
decodeResult.formatted.items.push({
|
|
2462
|
-
type: "status",
|
|
2463
|
-
code: "ROUTE_STATUS",
|
|
2464
|
-
label: "Route Status",
|
|
2465
|
-
value: "Route Inactive"
|
|
2466
|
-
});
|
|
2467
|
-
} else {
|
|
2468
|
-
decodeResult.remaining.text += header;
|
|
2469
|
-
allKnownFields = false;
|
|
2201
|
+
decodeResult.remaining.text += header;
|
|
2202
|
+
allKnownFields = false;
|
|
2470
2203
|
}
|
|
2471
2204
|
return allKnownFields;
|
|
2472
2205
|
}
|
|
@@ -2485,13 +2218,7 @@ function addRunway(decodeResult, value) {
|
|
|
2485
2218
|
}
|
|
2486
2219
|
function addRoute(decodeResult, value) {
|
|
2487
2220
|
const route = value.split(".");
|
|
2488
|
-
|
|
2489
|
-
decodeResult.formatted.items.push({
|
|
2490
|
-
type: "aircraft_route",
|
|
2491
|
-
code: "ROUTE",
|
|
2492
|
-
label: "Aircraft Route",
|
|
2493
|
-
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
2494
|
-
});
|
|
2221
|
+
ResultFormatter.route(decodeResult, { waypoints: route.map((leg) => RouteUtils.getWaypoint(leg)) });
|
|
2495
2222
|
}
|
|
2496
2223
|
function addProcedure(decodeResult, value, type) {
|
|
2497
2224
|
if (decodeResult.raw.procedures === void 0) {
|
|
@@ -2541,257 +2268,652 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
2541
2268
|
});
|
|
2542
2269
|
}
|
|
2543
2270
|
|
|
2544
|
-
// lib/utils/h1_helper.ts
|
|
2545
|
-
var H1Helper = class {
|
|
2546
|
-
static decodeH1Message(decodeResult, message) {
|
|
2547
|
-
const checksum = message.slice(-4);
|
|
2548
|
-
const data = message.slice(0, message.length - 4);
|
|
2549
|
-
const fields = data.split("/");
|
|
2550
|
-
parseMessageType(decodeResult, fields[0]);
|
|
2551
|
-
for (let i = 1; i < fields.length; ++i) {
|
|
2552
|
-
if (fields[i].startsWith("FN")) {
|
|
2553
|
-
decodeResult.raw.flight_number = fields[i].substring(2);
|
|
2554
|
-
} else if (fields[i].startsWith("SN")) {
|
|
2555
|
-
decodeResult.raw.serial_number = fields[i].substring(2);
|
|
2556
|
-
} else if (fields[i].startsWith("DC")) {
|
|
2557
|
-
processDC(decodeResult, fields[i].substring(2).split(","));
|
|
2558
|
-
} else if (fields[i].startsWith("TS")) {
|
|
2559
|
-
const ts = fields[i].substring(2).split(",");
|
|
2560
|
-
let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
|
|
2561
|
-
if (Number.isNaN(time)) {
|
|
2562
|
-
const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
|
|
2563
|
-
time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
|
|
2564
|
-
}
|
|
2565
|
-
decodeResult.raw.message_date = ts[1];
|
|
2566
|
-
decodeResult.raw.message_timestamp = time;
|
|
2567
|
-
} else if (fields[i].startsWith("PS")) {
|
|
2568
|
-
const pos = processPS(decodeResult, fields[i].substring(2).split(","));
|
|
2569
|
-
} else if (fields[i].startsWith("DT")) {
|
|
2570
|
-
const data2 = fields[i].substring(2).split(",");
|
|
2571
|
-
processDT(decodeResult, data2);
|
|
2572
|
-
} else if (fields[i].startsWith("ID")) {
|
|
2573
|
-
processIdentification(decodeResult, fields[i].substring(2).split(","));
|
|
2574
|
-
} else if (fields[i].startsWith("LR")) {
|
|
2575
|
-
const data2 = fields[i].substring(2).split(",");
|
|
2576
|
-
processLR(decodeResult, data2);
|
|
2577
|
-
} else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
|
|
2578
|
-
FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
|
|
2579
|
-
} else if (fields[i].startsWith("PR")) {
|
|
2580
|
-
decodeResult
|
|
2581
|
-
} else if (fields[i].startsWith("AF")) {
|
|
2582
|
-
processAirField(decodeResult, fields[i].substring(2).split(","));
|
|
2583
|
-
} else if (fields[i].startsWith("TD")) {
|
|
2584
|
-
processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
|
|
2585
|
-
} else if (fields[i].startsWith("FX")) {
|
|
2586
|
-
decodeResult
|
|
2271
|
+
// lib/utils/h1_helper.ts
|
|
2272
|
+
var H1Helper = class {
|
|
2273
|
+
static decodeH1Message(decodeResult, message) {
|
|
2274
|
+
const checksum = message.slice(-4);
|
|
2275
|
+
const data = message.slice(0, message.length - 4);
|
|
2276
|
+
const fields = data.split("/");
|
|
2277
|
+
parseMessageType(decodeResult, fields[0]);
|
|
2278
|
+
for (let i = 1; i < fields.length; ++i) {
|
|
2279
|
+
if (fields[i].startsWith("FN")) {
|
|
2280
|
+
decodeResult.raw.flight_number = fields[i].substring(2);
|
|
2281
|
+
} else if (fields[i].startsWith("SN")) {
|
|
2282
|
+
decodeResult.raw.serial_number = fields[i].substring(2);
|
|
2283
|
+
} else if (fields[i].startsWith("DC")) {
|
|
2284
|
+
processDC(decodeResult, fields[i].substring(2).split(","));
|
|
2285
|
+
} else if (fields[i].startsWith("TS")) {
|
|
2286
|
+
const ts = fields[i].substring(2).split(",");
|
|
2287
|
+
let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
|
|
2288
|
+
if (Number.isNaN(time)) {
|
|
2289
|
+
const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
|
|
2290
|
+
time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
|
|
2291
|
+
}
|
|
2292
|
+
decodeResult.raw.message_date = ts[1];
|
|
2293
|
+
decodeResult.raw.message_timestamp = time;
|
|
2294
|
+
} else if (fields[i].startsWith("PS")) {
|
|
2295
|
+
const pos = processPS(decodeResult, fields[i].substring(2).split(","));
|
|
2296
|
+
} else if (fields[i].startsWith("DT")) {
|
|
2297
|
+
const data2 = fields[i].substring(2).split(",");
|
|
2298
|
+
processDT(decodeResult, data2);
|
|
2299
|
+
} else if (fields[i].startsWith("ID")) {
|
|
2300
|
+
processIdentification(decodeResult, fields[i].substring(2).split(","));
|
|
2301
|
+
} else if (fields[i].startsWith("LR")) {
|
|
2302
|
+
const data2 = fields[i].substring(2).split(",");
|
|
2303
|
+
processLR(decodeResult, data2);
|
|
2304
|
+
} else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
|
|
2305
|
+
FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
|
|
2306
|
+
} else if (fields[i].startsWith("PR")) {
|
|
2307
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
2308
|
+
} else if (fields[i].startsWith("AF")) {
|
|
2309
|
+
processAirField(decodeResult, fields[i].substring(2).split(","));
|
|
2310
|
+
} else if (fields[i].startsWith("TD")) {
|
|
2311
|
+
processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
|
|
2312
|
+
} else if (fields[i].startsWith("FX")) {
|
|
2313
|
+
ResultFormatter.freetext(decodeResult, fields[i].substring(2));
|
|
2314
|
+
} else if (fields[i].startsWith("ET")) {
|
|
2315
|
+
if (fields[i].length === 7) {
|
|
2316
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(3) + "00"));
|
|
2317
|
+
} else if (fields[i].length === 8) {
|
|
2318
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(4) + "00"));
|
|
2319
|
+
} else {
|
|
2320
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
2321
|
+
}
|
|
2322
|
+
} else {
|
|
2323
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
if (decodeResult.formatted.items.length > 0) {
|
|
2327
|
+
ResultFormatter.checksum(decodeResult, checksum);
|
|
2328
|
+
}
|
|
2329
|
+
return true;
|
|
2330
|
+
}
|
|
2331
|
+
};
|
|
2332
|
+
function processAirField(decodeResult, data) {
|
|
2333
|
+
if (data.length === 2) {
|
|
2334
|
+
ResultFormatter.departureAirport(decodeResult, data[0]);
|
|
2335
|
+
ResultFormatter.arrivalAirport(decodeResult, data[1]);
|
|
2336
|
+
} else {
|
|
2337
|
+
ResultFormatter.unknown(decodeResult, data.join(","), "AF/");
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
function processTimeOfDeparture(decodeResult, data) {
|
|
2341
|
+
if (data.length === 2) {
|
|
2342
|
+
decodeResult.raw.plannedDepartureTime = data[0];
|
|
2343
|
+
decodeResult.formatted.items.push({
|
|
2344
|
+
type: "ptd",
|
|
2345
|
+
code: "ptd",
|
|
2346
|
+
label: "Planned Departure Time",
|
|
2347
|
+
value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
|
|
2348
|
+
});
|
|
2349
|
+
decodeResult.raw.plannedDepartureTime = data[1];
|
|
2350
|
+
decodeResult.formatted.items.push({
|
|
2351
|
+
type: "etd",
|
|
2352
|
+
code: "etd",
|
|
2353
|
+
label: "Estimated Departure Time",
|
|
2354
|
+
value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
|
|
2355
|
+
});
|
|
2356
|
+
} else {
|
|
2357
|
+
ResultFormatter.unknown(decodeResult, data.join(","), "/TD");
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
function processIdentification(decodeResult, data) {
|
|
2361
|
+
ResultFormatter.tail(decodeResult, data[0]);
|
|
2362
|
+
if (data.length > 1) {
|
|
2363
|
+
decodeResult.raw.flight_number = data[1];
|
|
2364
|
+
}
|
|
2365
|
+
if (data.length > 2) {
|
|
2366
|
+
decodeResult.raw.mission_number = data[2];
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
function processDT(decodeResult, data) {
|
|
2370
|
+
if (!decodeResult.raw.arrival_icao) {
|
|
2371
|
+
ResultFormatter.arrivalAirport(decodeResult, data[0]);
|
|
2372
|
+
} else if (decodeResult.raw.arrival_icao != data[0]) {
|
|
2373
|
+
ResultFormatter.unknownArr(decodeResult, data);
|
|
2374
|
+
}
|
|
2375
|
+
if (data.length > 1) {
|
|
2376
|
+
ResultFormatter.arrivalRunway(decodeResult, data[1]);
|
|
2377
|
+
}
|
|
2378
|
+
if (data.length > 2) {
|
|
2379
|
+
ResultFormatter.currentFuel(decodeResult, Number(data[2]));
|
|
2380
|
+
}
|
|
2381
|
+
if (data.length > 3) {
|
|
2382
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[3]));
|
|
2383
|
+
}
|
|
2384
|
+
if (data.length > 4) {
|
|
2385
|
+
ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
|
|
2386
|
+
}
|
|
2387
|
+
if (data.length > 5) {
|
|
2388
|
+
ResultFormatter.unknownArr(decodeResult, data);
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
function processLR(decodeResult, data) {
|
|
2392
|
+
if (data.length === 19) {
|
|
2393
|
+
ResultFormatter.unknown(decodeResult, data[1]);
|
|
2394
|
+
ResultFormatter.flightNumber(decodeResult, data[2]);
|
|
2395
|
+
ResultFormatter.departureAirport(decodeResult, data[3]);
|
|
2396
|
+
ResultFormatter.arrivalAirport(decodeResult, data[4]);
|
|
2397
|
+
ResultFormatter.arrivalRunway(decodeResult, data[5]);
|
|
2398
|
+
ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
|
|
2399
|
+
} else {
|
|
2400
|
+
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
function parseMessageType(decodeResult, messageType) {
|
|
2404
|
+
const parts = messageType.split("#");
|
|
2405
|
+
if (parts.length == 1) {
|
|
2406
|
+
const type = parts[0].substring(0, 3);
|
|
2407
|
+
if (type === "POS" && parts[0].length !== 3) {
|
|
2408
|
+
processPosition2(decodeResult, parts[0].substring(3).split(","));
|
|
2409
|
+
}
|
|
2410
|
+
return processMessageType(decodeResult, type);
|
|
2411
|
+
} else if (parts.length == 2) {
|
|
2412
|
+
if (parts[0].length > 0) {
|
|
2413
|
+
ResultFormatter.unknown(decodeResult, parts[0].substring(0, 3));
|
|
2414
|
+
decodeResult.raw.flight_number = parts[0].substring(3);
|
|
2415
|
+
ResultFormatter.unknown(decodeResult, parts[1].length == 5 ? parts[1].substring(0, 2) : parts[1].substring(0, 3), "#");
|
|
2416
|
+
}
|
|
2417
|
+
const type = parts[1].length == 5 ? parts[1].substring(2, 5) : parts[1].substring(3, 6);
|
|
2418
|
+
if (parts[1].substring(3, 6) === "POS" && parts[1].length > 6) {
|
|
2419
|
+
processPosition2(decodeResult, parts[1].substring(6).split(","));
|
|
2420
|
+
}
|
|
2421
|
+
processMessageType(decodeResult, type);
|
|
2422
|
+
} else {
|
|
2423
|
+
ResultFormatter.unknown(decodeResult, messageType);
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
function processMessageType(decodeResult, type) {
|
|
2427
|
+
if (type === "FPN") {
|
|
2428
|
+
decodeResult.formatted.description = "Flight Plan";
|
|
2429
|
+
} else if (type === "FTX") {
|
|
2430
|
+
decodeResult.formatted.description = "Free Text";
|
|
2431
|
+
} else if (type === "INI") {
|
|
2432
|
+
decodeResult.formatted.description = "Flight Plan Initial Report";
|
|
2433
|
+
} else if (type === "POS") {
|
|
2434
|
+
decodeResult.formatted.description = "Position Report";
|
|
2435
|
+
} else if (type === "PRG") {
|
|
2436
|
+
decodeResult.formatted.description = "Progress Report";
|
|
2437
|
+
} else {
|
|
2438
|
+
decodeResult.formatted.description = "Unknown H1 Message";
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
function processDC(decodeResult, data) {
|
|
2442
|
+
decodeResult.raw.message_date = data[0];
|
|
2443
|
+
if (data.length === 1) {
|
|
2444
|
+
} else if (data.length === 2) {
|
|
2445
|
+
const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
|
|
2446
|
+
const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
|
|
2447
|
+
decodeResult.raw.message_timestamp = time;
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
function processPS(decodeResult, data) {
|
|
2451
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
2452
|
+
if (position) {
|
|
2453
|
+
decodeResult.raw.position = position;
|
|
2454
|
+
decodeResult.formatted.items.push({
|
|
2455
|
+
type: "aircraft_position",
|
|
2456
|
+
code: "POS",
|
|
2457
|
+
label: "Aircraft Position",
|
|
2458
|
+
value: CoordinateUtils.coordinateString(position)
|
|
2459
|
+
});
|
|
2460
|
+
}
|
|
2461
|
+
if (data.length === 9) {
|
|
2462
|
+
processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
|
|
2463
|
+
ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
|
|
2464
|
+
ResultFormatter.temperature(decodeResult, data[6]);
|
|
2465
|
+
ResultFormatter.unknown(decodeResult, data[7]);
|
|
2466
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
2467
|
+
}
|
|
2468
|
+
if (data.length === 14) {
|
|
2469
|
+
ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
|
|
2470
|
+
processRoute(decodeResult, data[4], data[2], data[6], data[5], void 0);
|
|
2471
|
+
ResultFormatter.temperature(decodeResult, data[7]);
|
|
2472
|
+
ResultFormatter.groundspeed(decodeResult, Number(data[10]));
|
|
2473
|
+
ResultFormatter.unknown(decodeResult, data[1]);
|
|
2474
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
2475
|
+
ResultFormatter.unknown(decodeResult, data[9]);
|
|
2476
|
+
ResultFormatter.unknown(decodeResult, data.slice(11).join(","));
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
function processPosition2(decodeResult, data) {
|
|
2480
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
2481
|
+
if (position) {
|
|
2482
|
+
decodeResult.raw.position = position;
|
|
2483
|
+
decodeResult.formatted.items.push({
|
|
2484
|
+
type: "aircraft_position",
|
|
2485
|
+
code: "POS",
|
|
2486
|
+
label: "Aircraft Position",
|
|
2487
|
+
value: CoordinateUtils.coordinateString(position)
|
|
2488
|
+
});
|
|
2489
|
+
}
|
|
2490
|
+
if (data.length >= 10) {
|
|
2491
|
+
ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
|
|
2492
|
+
processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
|
|
2493
|
+
ResultFormatter.temperature(decodeResult, data[7]);
|
|
2494
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
2495
|
+
ResultFormatter.unknown(decodeResult, data[9]);
|
|
2496
|
+
}
|
|
2497
|
+
if (data.length >= 14) {
|
|
2498
|
+
ResultFormatter.groundspeed(decodeResult, Number(data[10]));
|
|
2499
|
+
ResultFormatter.unknown(decodeResult, data[11]);
|
|
2500
|
+
ResultFormatter.unknown(decodeResult, data[12]);
|
|
2501
|
+
ResultFormatter.unknown(decodeResult, data[13]);
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
function processRoute(decodeResult, last, time, next, eta, then, date) {
|
|
2505
|
+
const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
|
|
2506
|
+
const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
|
|
2507
|
+
const timeFormat = date ? "epoch" : "tod";
|
|
2508
|
+
const lastWaypoint = RouteUtils.getWaypoint(last);
|
|
2509
|
+
lastWaypoint.time = lastTime;
|
|
2510
|
+
lastWaypoint.timeFormat = timeFormat;
|
|
2511
|
+
const nextWaypoint = RouteUtils.getWaypoint(next);
|
|
2512
|
+
nextWaypoint.time = nextTime;
|
|
2513
|
+
nextWaypoint.timeFormat = timeFormat;
|
|
2514
|
+
const thenWaypoint = RouteUtils.getWaypoint(then || "?");
|
|
2515
|
+
const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
|
|
2516
|
+
decodeResult.raw.route = { waypoints };
|
|
2517
|
+
decodeResult.formatted.items.push({
|
|
2518
|
+
type: "aircraft_route",
|
|
2519
|
+
code: "ROUTE",
|
|
2520
|
+
label: "Aircraft Route",
|
|
2521
|
+
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
2522
|
+
});
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2525
|
+
// lib/plugins/Label_4J_POS.ts
|
|
2526
|
+
var Label_4J_POS = class extends DecoderPlugin {
|
|
2527
|
+
name = "label-4j-pos";
|
|
2528
|
+
qualifiers() {
|
|
2529
|
+
return {
|
|
2530
|
+
labels: ["4J"],
|
|
2531
|
+
preambles: ["POS/"]
|
|
2532
|
+
};
|
|
2533
|
+
}
|
|
2534
|
+
// copied from Label_H1.ts since i don't really want to have to have
|
|
2535
|
+
// something named like that decode more than 1 type
|
|
2536
|
+
// if we figure out a good name, i'll combine them
|
|
2537
|
+
decode(message, options = {}) {
|
|
2538
|
+
let decodeResult = this.defaultResult();
|
|
2539
|
+
decodeResult.decoder.name = this.name;
|
|
2540
|
+
decodeResult.message = message;
|
|
2541
|
+
const msg = message.text.replace(/\n|\r/g, "");
|
|
2542
|
+
const decoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
2543
|
+
decodeResult.decoded = decoded;
|
|
2544
|
+
decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
|
|
2545
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
2546
|
+
if (options.debug) {
|
|
2547
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2548
|
+
}
|
|
2549
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
2550
|
+
decodeResult.decoded = false;
|
|
2551
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2552
|
+
}
|
|
2553
|
+
return decodeResult;
|
|
2554
|
+
}
|
|
2555
|
+
};
|
|
2556
|
+
|
|
2557
|
+
// lib/plugins/Label_4N.ts
|
|
2558
|
+
var Label_4N = class extends DecoderPlugin {
|
|
2559
|
+
name = "label-4n";
|
|
2560
|
+
qualifiers() {
|
|
2561
|
+
return {
|
|
2562
|
+
labels: ["4N"]
|
|
2563
|
+
};
|
|
2564
|
+
}
|
|
2565
|
+
decode(message, options = {}) {
|
|
2566
|
+
const decodeResult = this.defaultResult();
|
|
2567
|
+
decodeResult.decoder.name = this.name;
|
|
2568
|
+
decodeResult.message = message;
|
|
2569
|
+
decodeResult.formatted.description = "Airline Defined";
|
|
2570
|
+
let text = message.text;
|
|
2571
|
+
if (text.match(/^M\d{2}A\w{6}/)) {
|
|
2572
|
+
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
2573
|
+
text = text.substring(10);
|
|
2574
|
+
}
|
|
2575
|
+
decodeResult.decoded = true;
|
|
2576
|
+
const fields = text.split(",");
|
|
2577
|
+
if (text.length === 51) {
|
|
2578
|
+
decodeResult.raw.day_of_month = text.substring(0, 2);
|
|
2579
|
+
ResultFormatter.departureAirport(decodeResult, text.substring(8, 11));
|
|
2580
|
+
ResultFormatter.arrivalAirport(decodeResult, text.substring(13, 16));
|
|
2581
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinatesDecimalMinutes(text.substring(30, 45).replace(/^(.)0/, "$1")));
|
|
2582
|
+
ResultFormatter.altitude(decodeResult, Number(text.substring(48, 51)) * 100);
|
|
2583
|
+
ResultFormatter.unknownArr(decodeResult, [text.substring(2, 4), text.substring(19, 29)], " ");
|
|
2584
|
+
} else if (fields.length === 33) {
|
|
2585
|
+
decodeResult.raw.date = fields[3];
|
|
2586
|
+
if (fields[1] === "B") {
|
|
2587
|
+
ResultFormatter.position(decodeResult, { latitude: Number(fields[4]), longitude: Number(fields[5]) });
|
|
2588
|
+
ResultFormatter.altitude(decodeResult, Number(fields[6]));
|
|
2589
|
+
}
|
|
2590
|
+
ResultFormatter.departureAirport(decodeResult, fields[8]);
|
|
2591
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[9]);
|
|
2592
|
+
ResultFormatter.alternateAirport(decodeResult, fields[10]);
|
|
2593
|
+
ResultFormatter.arrivalRunway(decodeResult, fields[11].split("/")[0]);
|
|
2594
|
+
if (fields[12].length > 1) {
|
|
2595
|
+
ResultFormatter.alternateRunway(decodeResult, fields[12].split("/")[0]);
|
|
2596
|
+
}
|
|
2597
|
+
ResultFormatter.checksum(decodeResult, fields[32]);
|
|
2598
|
+
ResultFormatter.unknownArr(decodeResult, [...fields.slice(1, 3), fields[7], ...fields.slice(13, 32)].filter((f) => f != ""));
|
|
2599
|
+
} else {
|
|
2600
|
+
decodeResult.decoded = false;
|
|
2601
|
+
ResultFormatter.unknown(decodeResult, text);
|
|
2602
|
+
}
|
|
2603
|
+
if (decodeResult.decoded) {
|
|
2604
|
+
if (!decodeResult.remaining.text)
|
|
2605
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2606
|
+
else
|
|
2607
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2608
|
+
} else {
|
|
2609
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2610
|
+
}
|
|
2611
|
+
return decodeResult;
|
|
2612
|
+
}
|
|
2613
|
+
};
|
|
2614
|
+
|
|
2615
|
+
// lib/plugins/Label_80.ts
|
|
2616
|
+
var Label_80 = class extends DecoderPlugin {
|
|
2617
|
+
name = "label-80";
|
|
2618
|
+
descriptions = {
|
|
2619
|
+
ALT: "Altitude",
|
|
2620
|
+
DWND: "Wind Direction",
|
|
2621
|
+
ETA: "Estimated Time of Arrival",
|
|
2622
|
+
FOB: "Fuel on Board",
|
|
2623
|
+
FL: "Flight Level",
|
|
2624
|
+
HDG: "Heading",
|
|
2625
|
+
MCH: "Aircraft Speed",
|
|
2626
|
+
NWYP: "Next Waypoint",
|
|
2627
|
+
POS: "Aircraft Position",
|
|
2628
|
+
SAT: "Static Air Temperature",
|
|
2629
|
+
SWND: "Wind Speed",
|
|
2630
|
+
TAS: "True Airspeed",
|
|
2631
|
+
WYP: "Waypoint"
|
|
2632
|
+
};
|
|
2633
|
+
qualifiers() {
|
|
2634
|
+
return {
|
|
2635
|
+
labels: ["80"],
|
|
2636
|
+
preambles: ["3N01 POSRPT"]
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
decode(message, options = {}) {
|
|
2640
|
+
const decodeResult = this.defaultResult();
|
|
2641
|
+
decodeResult.decoder.name = this.name;
|
|
2642
|
+
decodeResult.formatted.description = "Airline Defined Position Report";
|
|
2643
|
+
const parts = message.text.split("\n");
|
|
2644
|
+
let posRptRegex = /^3N01 POSRPT \d\d\d\d\/\d\d (?<orig>\w+)\/(?<dest>\w+) \.(?<tail>[\w-]+)(\/(?<agate>.+) (?<sta>\w+:\w+))*/;
|
|
2645
|
+
let results = parts[0].match(posRptRegex);
|
|
2646
|
+
if (!results?.groups) {
|
|
2647
|
+
decodeResult.decoded = false;
|
|
2648
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2649
|
+
return decodeResult;
|
|
2650
|
+
}
|
|
2651
|
+
if (results && results.length > 0) {
|
|
2652
|
+
ResultFormatter.departureAirport(decodeResult, results.groups.orig);
|
|
2653
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.dest);
|
|
2654
|
+
ResultFormatter.tail(decodeResult, results.groups.tail);
|
|
2655
|
+
if (results.groups.agate) {
|
|
2656
|
+
decodeResult.raw.arrival_gate = results.groups.agate;
|
|
2587
2657
|
decodeResult.formatted.items.push({
|
|
2588
|
-
type: "
|
|
2589
|
-
code: "
|
|
2590
|
-
label: "
|
|
2591
|
-
value:
|
|
2658
|
+
type: "arrival_gate",
|
|
2659
|
+
code: "ARG",
|
|
2660
|
+
label: "Arrival Gate",
|
|
2661
|
+
value: `${results.groups.agate}`
|
|
2662
|
+
});
|
|
2663
|
+
decodeResult.raw.scheduled_time_of_arrival = results.groups.sta;
|
|
2664
|
+
decodeResult.formatted.items.push({
|
|
2665
|
+
type: "scheduled_time_of_arrival",
|
|
2666
|
+
code: "STA",
|
|
2667
|
+
label: "Scheduled Time of Arrival",
|
|
2668
|
+
value: `${results.groups.sta}`
|
|
2592
2669
|
});
|
|
2593
|
-
} else {
|
|
2594
|
-
decodeResult.remaining.text += "/" + fields[i];
|
|
2595
2670
|
}
|
|
2671
|
+
posRptRegex = /\/(?<field>\w+)\s(?<value>[\w\+\-:\.]+)\s*/gi;
|
|
2672
|
+
const remainingParts = parts.slice(1);
|
|
2673
|
+
for (const part of remainingParts) {
|
|
2674
|
+
const matches = part.matchAll(posRptRegex);
|
|
2675
|
+
for (const match of matches) {
|
|
2676
|
+
switch (match.groups?.field) {
|
|
2677
|
+
case "ALT": {
|
|
2678
|
+
ResultFormatter.altitude(decodeResult, Number(match.groups.value));
|
|
2679
|
+
break;
|
|
2680
|
+
}
|
|
2681
|
+
case "DWND": {
|
|
2682
|
+
decodeResult.raw.wind_direction = Number(match.groups.value);
|
|
2683
|
+
decodeResult.formatted.items.push({
|
|
2684
|
+
type: "wind_direction",
|
|
2685
|
+
code: "DWND",
|
|
2686
|
+
label: this.descriptions[match.groups.field],
|
|
2687
|
+
value: decodeResult.raw.wind_direction
|
|
2688
|
+
});
|
|
2689
|
+
break;
|
|
2690
|
+
}
|
|
2691
|
+
case "FL": {
|
|
2692
|
+
const flight_level = Number(match.groups.value);
|
|
2693
|
+
ResultFormatter.altitude(decodeResult, flight_level * 100);
|
|
2694
|
+
break;
|
|
2695
|
+
}
|
|
2696
|
+
case "FOB": {
|
|
2697
|
+
const fob = Number(match.groups.value);
|
|
2698
|
+
if (!isNaN(fob)) {
|
|
2699
|
+
ResultFormatter.currentFuel(decodeResult, fob);
|
|
2700
|
+
}
|
|
2701
|
+
break;
|
|
2702
|
+
}
|
|
2703
|
+
case "HDG": {
|
|
2704
|
+
ResultFormatter.heading(decodeResult, Number(match.groups.value));
|
|
2705
|
+
break;
|
|
2706
|
+
}
|
|
2707
|
+
case "MCH": {
|
|
2708
|
+
decodeResult.raw.mach = Number(match.groups.value) / 1e3;
|
|
2709
|
+
decodeResult.formatted.items.push({
|
|
2710
|
+
type: "mach",
|
|
2711
|
+
code: "MCH",
|
|
2712
|
+
label: this.descriptions[match.groups.field],
|
|
2713
|
+
value: `${decodeResult.raw.mach} Mach`
|
|
2714
|
+
});
|
|
2715
|
+
break;
|
|
2716
|
+
}
|
|
2717
|
+
case "NWYP": {
|
|
2718
|
+
decodeResult.raw.next_waypoint = match.groups.value;
|
|
2719
|
+
decodeResult.formatted.items.push({
|
|
2720
|
+
type: "next_waypoint",
|
|
2721
|
+
code: "NWYP",
|
|
2722
|
+
label: this.descriptions[match.groups.field],
|
|
2723
|
+
value: decodeResult.raw.next_waypoint
|
|
2724
|
+
});
|
|
2725
|
+
break;
|
|
2726
|
+
}
|
|
2727
|
+
case "POS": {
|
|
2728
|
+
const posRegex = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
|
|
2729
|
+
const posResult = match.groups.value.match(posRegex);
|
|
2730
|
+
const lat = Number(posResult?.groups?.lat) * (posResult?.groups?.lngd === "S" ? -1 : 1);
|
|
2731
|
+
const lon = Number(posResult?.groups?.lng) * (posResult?.groups?.lngd === "W" ? -1 : 1);
|
|
2732
|
+
const position = {
|
|
2733
|
+
latitude: Number.isInteger(lat) ? lat / 1e3 : lat / 100,
|
|
2734
|
+
longitude: Number.isInteger(lon) ? lon / 1e3 : lon / 100
|
|
2735
|
+
};
|
|
2736
|
+
ResultFormatter.position(decodeResult, position);
|
|
2737
|
+
break;
|
|
2738
|
+
}
|
|
2739
|
+
case "SWND": {
|
|
2740
|
+
decodeResult.raw.wind_speed = Number(match.groups.value);
|
|
2741
|
+
decodeResult.formatted.items.push({
|
|
2742
|
+
type: "wind_speed",
|
|
2743
|
+
code: "SWND",
|
|
2744
|
+
label: this.descriptions[match.groups.field],
|
|
2745
|
+
value: decodeResult.raw.wind_speed
|
|
2746
|
+
});
|
|
2747
|
+
break;
|
|
2748
|
+
}
|
|
2749
|
+
default: {
|
|
2750
|
+
if (match.groups?.field != void 0) {
|
|
2751
|
+
const description = this.descriptions[match.groups.field] ? this.descriptions[match.groups.field] : "Unknown";
|
|
2752
|
+
decodeResult.formatted.items.push({
|
|
2753
|
+
type: match.groups.field,
|
|
2754
|
+
code: match.groups.field,
|
|
2755
|
+
label: description || `Unknown (${match.groups.field})`,
|
|
2756
|
+
value: `${match.groups.value}`
|
|
2757
|
+
});
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
decodeResult.decoded = true;
|
|
2764
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2596
2765
|
}
|
|
2597
|
-
|
|
2598
|
-
ResultFormatter.checksum(decodeResult, checksum);
|
|
2599
|
-
}
|
|
2600
|
-
return true;
|
|
2766
|
+
return decodeResult;
|
|
2601
2767
|
}
|
|
2602
2768
|
};
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
}
|
|
2611
|
-
function processTimeOfDeparture(decodeResult, data) {
|
|
2612
|
-
if (data.length === 2) {
|
|
2613
|
-
decodeResult.raw.plannedDepartureTime = data[0];
|
|
2614
|
-
decodeResult.formatted.items.push({
|
|
2615
|
-
type: "ptd",
|
|
2616
|
-
code: "ptd",
|
|
2617
|
-
label: "Planned Departure Time",
|
|
2618
|
-
value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
|
|
2619
|
-
});
|
|
2620
|
-
decodeResult.raw.plannedDepartureTime = data[1];
|
|
2621
|
-
decodeResult.formatted.items.push({
|
|
2622
|
-
type: "etd",
|
|
2623
|
-
code: "etd",
|
|
2624
|
-
label: "Estimated Departure Time",
|
|
2625
|
-
value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
|
|
2626
|
-
});
|
|
2627
|
-
} else {
|
|
2628
|
-
decodeResult.remaining.text += "/TD" + data.join(",");
|
|
2629
|
-
}
|
|
2630
|
-
}
|
|
2631
|
-
function processIdentification(decodeResult, data) {
|
|
2632
|
-
ResultFormatter.tail(decodeResult, data[0]);
|
|
2633
|
-
if (data.length > 1) {
|
|
2634
|
-
decodeResult.raw.flight_number = data[1];
|
|
2635
|
-
}
|
|
2636
|
-
if (data.length > 2) {
|
|
2637
|
-
decodeResult.raw.mission_number = data[2];
|
|
2638
|
-
}
|
|
2639
|
-
}
|
|
2640
|
-
function processDT(decodeResult, data) {
|
|
2641
|
-
if (!decodeResult.raw.arrival_icao) {
|
|
2642
|
-
ResultFormatter.arrivalAirport(decodeResult, data[0]);
|
|
2643
|
-
} else if (decodeResult.raw.arrival_icao != data[0]) {
|
|
2644
|
-
decodeResult.remaining.text += "/" + data;
|
|
2645
|
-
}
|
|
2646
|
-
if (data.length > 1) {
|
|
2647
|
-
ResultFormatter.arrivalRunway(decodeResult, data[1]);
|
|
2648
|
-
}
|
|
2649
|
-
if (data.length > 2) {
|
|
2650
|
-
ResultFormatter.currentFuel(decodeResult, Number(data[2]));
|
|
2651
|
-
}
|
|
2652
|
-
if (data.length > 3) {
|
|
2653
|
-
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[3]));
|
|
2654
|
-
}
|
|
2655
|
-
if (data.length > 4) {
|
|
2656
|
-
ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
|
|
2657
|
-
}
|
|
2658
|
-
if (data.length > 5) {
|
|
2659
|
-
decodeResult.remaining.text += "," + data.slice(5).join(",");
|
|
2660
|
-
}
|
|
2661
|
-
}
|
|
2662
|
-
function processLR(decodeResult, data) {
|
|
2663
|
-
if (data.length === 19) {
|
|
2664
|
-
ResultFormatter.unknown(decodeResult, data[1]);
|
|
2665
|
-
ResultFormatter.flightNumber(decodeResult, data[2]);
|
|
2666
|
-
ResultFormatter.departureAirport(decodeResult, data[3]);
|
|
2667
|
-
ResultFormatter.arrivalAirport(decodeResult, data[4]);
|
|
2668
|
-
ResultFormatter.arrivalRunway(decodeResult, data[5]);
|
|
2669
|
-
ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
|
|
2670
|
-
} else {
|
|
2671
|
-
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
2769
|
+
|
|
2770
|
+
// lib/plugins/Label_83.ts
|
|
2771
|
+
var Label_83 = class extends DecoderPlugin {
|
|
2772
|
+
name = "label-83";
|
|
2773
|
+
qualifiers() {
|
|
2774
|
+
return {
|
|
2775
|
+
labels: ["83"]
|
|
2776
|
+
};
|
|
2672
2777
|
}
|
|
2673
|
-
}
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2778
|
+
decode(message, options = {}) {
|
|
2779
|
+
const decodeResult = this.defaultResult();
|
|
2780
|
+
decodeResult.decoder.name = this.name;
|
|
2781
|
+
decodeResult.message = message;
|
|
2782
|
+
decodeResult.formatted.description = "Airline Defined";
|
|
2783
|
+
let text = message.text;
|
|
2784
|
+
if (text.match(/^M\d{2}A\w{6}/)) {
|
|
2785
|
+
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
2786
|
+
text = text.substring(10);
|
|
2680
2787
|
}
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2788
|
+
decodeResult.decoded = true;
|
|
2789
|
+
if (text.substring(0, 10) === "4DH3 ETAT2") {
|
|
2790
|
+
const fields = text.split(/\s+/);
|
|
2791
|
+
if (fields[2].length > 5) {
|
|
2792
|
+
decodeResult.raw.day_of_month = fields[2].substring(5);
|
|
2793
|
+
}
|
|
2794
|
+
ResultFormatter.unknown(decodeResult, fields[2].substring(0, 4));
|
|
2795
|
+
const subfields = fields[3].split("/");
|
|
2796
|
+
ResultFormatter.departureAirport(decodeResult, subfields[0]);
|
|
2797
|
+
ResultFormatter.arrivalAirport(decodeResult, subfields[1]);
|
|
2798
|
+
ResultFormatter.tail(decodeResult, fields[4].replace(/\./g, ""));
|
|
2799
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[6] + "00"));
|
|
2800
|
+
} else if (text.substring(0, 5) === "001PR") {
|
|
2801
|
+
decodeResult.raw.day_of_month = text.substring(5, 7);
|
|
2802
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(text.substring(13, 28).replace(/\./g, ""));
|
|
2803
|
+
if (position) {
|
|
2804
|
+
ResultFormatter.position(decodeResult, position);
|
|
2805
|
+
}
|
|
2806
|
+
ResultFormatter.altitude(decodeResult, Number(text.substring(28, 33)));
|
|
2807
|
+
ResultFormatter.unknown(decodeResult, text.substring(33));
|
|
2808
|
+
} else {
|
|
2809
|
+
const fields = text.replace(/\s/g, "").split(",");
|
|
2810
|
+
if (fields.length === 9) {
|
|
2811
|
+
ResultFormatter.departureAirport(decodeResult, fields[0]);
|
|
2812
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[1]);
|
|
2813
|
+
decodeResult.raw.day_of_month = fields[2].substring(0, 2);
|
|
2814
|
+
decodeResult.raw.time = fields[2].substring(2);
|
|
2815
|
+
ResultFormatter.position(
|
|
2816
|
+
decodeResult,
|
|
2817
|
+
{
|
|
2818
|
+
latitude: Number(fields[3].replace(/\s/g, "")),
|
|
2819
|
+
longitude: Number(fields[4].replace(/\s/g, ""))
|
|
2820
|
+
}
|
|
2821
|
+
);
|
|
2822
|
+
ResultFormatter.altitude(decodeResult, Number(fields[5]));
|
|
2823
|
+
ResultFormatter.groundspeed(decodeResult, Number(fields[6]));
|
|
2824
|
+
ResultFormatter.heading(decodeResult, Number(fields[7]));
|
|
2825
|
+
ResultFormatter.unknown(decodeResult, fields[8]);
|
|
2826
|
+
} else {
|
|
2827
|
+
decodeResult.decoded = false;
|
|
2828
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
2829
|
+
}
|
|
2687
2830
|
}
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2831
|
+
if (decodeResult.decoded) {
|
|
2832
|
+
if (!decodeResult.remaining.text)
|
|
2833
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2834
|
+
else
|
|
2835
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2836
|
+
} else {
|
|
2837
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2691
2838
|
}
|
|
2692
|
-
|
|
2693
|
-
} else {
|
|
2694
|
-
decodeResult.remaining.text += messageType;
|
|
2695
|
-
}
|
|
2696
|
-
}
|
|
2697
|
-
function processMessageType(decodeResult, type) {
|
|
2698
|
-
if (type === "FPN") {
|
|
2699
|
-
decodeResult.formatted.description = "Flight Plan";
|
|
2700
|
-
} else if (type === "FTX") {
|
|
2701
|
-
decodeResult.formatted.description = "Free Text";
|
|
2702
|
-
} else if (type === "INI") {
|
|
2703
|
-
decodeResult.formatted.description = "Flight Plan Initial Report";
|
|
2704
|
-
} else if (type === "POS") {
|
|
2705
|
-
decodeResult.formatted.description = "Position Report";
|
|
2706
|
-
} else if (type === "PRG") {
|
|
2707
|
-
decodeResult.formatted.description = "Progress Report";
|
|
2708
|
-
} else {
|
|
2709
|
-
decodeResult.formatted.description = "Unknown H1 Message";
|
|
2710
|
-
}
|
|
2711
|
-
}
|
|
2712
|
-
function processDC(decodeResult, data) {
|
|
2713
|
-
decodeResult.raw.message_date = data[0];
|
|
2714
|
-
if (data.length === 1) {
|
|
2715
|
-
} else if (data.length === 2) {
|
|
2716
|
-
const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
|
|
2717
|
-
const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
|
|
2718
|
-
decodeResult.raw.message_timestamp = time;
|
|
2839
|
+
return decodeResult;
|
|
2719
2840
|
}
|
|
2720
|
-
}
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
value: CoordinateUtils.coordinateString(position)
|
|
2730
|
-
});
|
|
2841
|
+
};
|
|
2842
|
+
|
|
2843
|
+
// lib/plugins/Label_8E.ts
|
|
2844
|
+
var Label_8E = class extends DecoderPlugin {
|
|
2845
|
+
name = "label-8e";
|
|
2846
|
+
qualifiers() {
|
|
2847
|
+
return {
|
|
2848
|
+
labels: ["8E"]
|
|
2849
|
+
};
|
|
2731
2850
|
}
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2851
|
+
decode(message, options = {}) {
|
|
2852
|
+
const decodeResult = this.defaultResult();
|
|
2853
|
+
decodeResult.decoder.name = this.name;
|
|
2854
|
+
decodeResult.formatted.description = "ETA Report";
|
|
2855
|
+
decodeResult.message = message;
|
|
2856
|
+
const regex = /^(?<arrival_icao>\w{4}),(?<arrival_eta>\d{4})$/;
|
|
2857
|
+
const results = message.text.match(regex);
|
|
2858
|
+
if (results?.groups) {
|
|
2859
|
+
if (options.debug) {
|
|
2860
|
+
console.log(`Label 8E ETA: groups`);
|
|
2861
|
+
console.log(results.groups);
|
|
2862
|
+
}
|
|
2863
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(results.groups.arrival_eta + "00"));
|
|
2864
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
2865
|
+
}
|
|
2866
|
+
decodeResult.decoded = true;
|
|
2867
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2868
|
+
return decodeResult;
|
|
2738
2869
|
}
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2870
|
+
};
|
|
2871
|
+
|
|
2872
|
+
// lib/plugins/Label_B6.ts
|
|
2873
|
+
var Label_B6_Forwardslash = class extends DecoderPlugin {
|
|
2874
|
+
name = "label-b6-forwardslash";
|
|
2875
|
+
qualifiers() {
|
|
2876
|
+
return {
|
|
2877
|
+
labels: ["B6"],
|
|
2878
|
+
preambles: ["/"]
|
|
2879
|
+
};
|
|
2748
2880
|
}
|
|
2749
|
-
}
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
decodeResult.
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
value: CoordinateUtils.coordinateString(position)
|
|
2759
|
-
});
|
|
2881
|
+
decode(message, options = {}) {
|
|
2882
|
+
const decodeResult = this.defaultResult();
|
|
2883
|
+
decodeResult.decoder.name = this.name;
|
|
2884
|
+
decodeResult.formatted.description = "CPDLC Message";
|
|
2885
|
+
decodeResult.message = message;
|
|
2886
|
+
if (options.debug) {
|
|
2887
|
+
console.log("CPDLC: " + message);
|
|
2888
|
+
}
|
|
2889
|
+
return decodeResult;
|
|
2760
2890
|
}
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2891
|
+
};
|
|
2892
|
+
|
|
2893
|
+
// lib/plugins/Label_ColonComma.ts
|
|
2894
|
+
var Label_ColonComma = class extends DecoderPlugin {
|
|
2895
|
+
name = "label-colon-comma";
|
|
2896
|
+
qualifiers() {
|
|
2897
|
+
return {
|
|
2898
|
+
labels: [":;"]
|
|
2899
|
+
};
|
|
2767
2900
|
}
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2901
|
+
decode(message, options = {}) {
|
|
2902
|
+
const decodeResult = this.defaultResult();
|
|
2903
|
+
decodeResult.decoder.name = this.name;
|
|
2904
|
+
decodeResult.raw.frequency = Number(message.text) / 1e3;
|
|
2905
|
+
decodeResult.formatted.description = "Aircraft Transceiver Frequency Change";
|
|
2906
|
+
decodeResult.formatted.items.push({
|
|
2907
|
+
type: "frequency",
|
|
2908
|
+
label: "Frequency",
|
|
2909
|
+
value: `${decodeResult.raw.frequency} MHz`,
|
|
2910
|
+
code: "FREQ"
|
|
2911
|
+
});
|
|
2912
|
+
decodeResult.decoded = true;
|
|
2913
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2914
|
+
return decodeResult;
|
|
2773
2915
|
}
|
|
2774
|
-
}
|
|
2775
|
-
function processRoute(decodeResult, last, time, next, eta, then, date) {
|
|
2776
|
-
const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
|
|
2777
|
-
const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
|
|
2778
|
-
const timeFormat = date ? "epoch" : "tod";
|
|
2779
|
-
const lastWaypoint = RouteUtils.getWaypoint(last);
|
|
2780
|
-
lastWaypoint.time = lastTime;
|
|
2781
|
-
lastWaypoint.timeFormat = timeFormat;
|
|
2782
|
-
const nextWaypoint = RouteUtils.getWaypoint(next);
|
|
2783
|
-
nextWaypoint.time = nextTime;
|
|
2784
|
-
nextWaypoint.timeFormat = timeFormat;
|
|
2785
|
-
const thenWaypoint = RouteUtils.getWaypoint(then || "?");
|
|
2786
|
-
const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
|
|
2787
|
-
decodeResult.raw.route = { waypoints };
|
|
2788
|
-
decodeResult.formatted.items.push({
|
|
2789
|
-
type: "aircraft_route",
|
|
2790
|
-
code: "ROUTE",
|
|
2791
|
-
label: "Aircraft Route",
|
|
2792
|
-
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
2793
|
-
});
|
|
2794
|
-
}
|
|
2916
|
+
};
|
|
2795
2917
|
|
|
2796
2918
|
// lib/plugins/Label_H1.ts
|
|
2797
2919
|
var Label_H1 = class extends DecoderPlugin {
|
|
@@ -2805,16 +2927,205 @@ var Label_H1 = class extends DecoderPlugin {
|
|
|
2805
2927
|
let decodeResult = this.defaultResult();
|
|
2806
2928
|
decodeResult.decoder.name = this.name;
|
|
2807
2929
|
decodeResult.message = message;
|
|
2808
|
-
decodeResult.remaining.text = "";
|
|
2809
2930
|
const msg = message.text.replace(/\n|\r/g, "");
|
|
2810
2931
|
const decoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
2811
2932
|
decodeResult.decoded = decoded;
|
|
2812
|
-
decodeResult.decoder.decodeLevel = decodeResult.remaining.text
|
|
2933
|
+
decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
|
|
2813
2934
|
if (decodeResult.formatted.items.length === 0) {
|
|
2814
2935
|
if (options.debug) {
|
|
2815
2936
|
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2816
2937
|
}
|
|
2817
|
-
decodeResult
|
|
2938
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
2939
|
+
decodeResult.decoded = false;
|
|
2940
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2941
|
+
}
|
|
2942
|
+
return decodeResult;
|
|
2943
|
+
}
|
|
2944
|
+
};
|
|
2945
|
+
|
|
2946
|
+
// lib/plugins/Label_H1_FLR.ts
|
|
2947
|
+
var Label_H1_FLR = class extends DecoderPlugin {
|
|
2948
|
+
name = "label-h1-flr";
|
|
2949
|
+
qualifiers() {
|
|
2950
|
+
return {
|
|
2951
|
+
labels: ["H1"],
|
|
2952
|
+
preambles: ["FLR", "#CFBFLR"]
|
|
2953
|
+
};
|
|
2954
|
+
}
|
|
2955
|
+
decode(message, options = {}) {
|
|
2956
|
+
let decodeResult = this.defaultResult();
|
|
2957
|
+
decodeResult.decoder.name = this.name;
|
|
2958
|
+
decodeResult.formatted.description = "Fault Log Report";
|
|
2959
|
+
decodeResult.message = message;
|
|
2960
|
+
const parts = message.text.split("/FR");
|
|
2961
|
+
if (parts.length > 1) {
|
|
2962
|
+
const fields = parts[0].split("/");
|
|
2963
|
+
for (let i = 1; i < fields.length; i++) {
|
|
2964
|
+
const field = fields[i];
|
|
2965
|
+
ResultFormatter.unknown(decodeResult, field, "/");
|
|
2966
|
+
}
|
|
2967
|
+
const data = parts[1].substring(0, 20);
|
|
2968
|
+
const msg = parts[1].substring(20);
|
|
2969
|
+
const datetime = data.substring(0, 12);
|
|
2970
|
+
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
2971
|
+
ResultFormatter.unknown(decodeResult, data.substring(12), "/");
|
|
2972
|
+
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
2973
|
+
decodeResult.raw.fault_message = msg;
|
|
2974
|
+
decodeResult.formatted.items.push({
|
|
2975
|
+
type: "fault",
|
|
2976
|
+
code: "FR",
|
|
2977
|
+
label: "Fault Report",
|
|
2978
|
+
value: decodeResult.raw.fault_message
|
|
2979
|
+
});
|
|
2980
|
+
decodeResult.decoded = true;
|
|
2981
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2982
|
+
} else {
|
|
2983
|
+
if (options.debug) {
|
|
2984
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2985
|
+
}
|
|
2986
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
2987
|
+
decodeResult.decoded = false;
|
|
2988
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2989
|
+
}
|
|
2990
|
+
return decodeResult;
|
|
2991
|
+
}
|
|
2992
|
+
};
|
|
2993
|
+
|
|
2994
|
+
// lib/plugins/Label_H1_OHMA.ts
|
|
2995
|
+
import * as zlib from "minizlib";
|
|
2996
|
+
var Label_H1_OHMA = class extends DecoderPlugin {
|
|
2997
|
+
name = "label-h1-ohma";
|
|
2998
|
+
qualifiers() {
|
|
2999
|
+
return {
|
|
3000
|
+
labels: ["H1"],
|
|
3001
|
+
preambles: ["OHMA", "/RTNBOCR.OHMA", "#T1B/RTNBOCR.OHMA"]
|
|
3002
|
+
};
|
|
3003
|
+
}
|
|
3004
|
+
decode(message, options = {}) {
|
|
3005
|
+
let decodeResult = this.defaultResult();
|
|
3006
|
+
decodeResult.decoder.name = this.name;
|
|
3007
|
+
decodeResult.formatted.description = "OHMA Message";
|
|
3008
|
+
decodeResult.message = message;
|
|
3009
|
+
const data = message.text.split("OHMA")[1];
|
|
3010
|
+
try {
|
|
3011
|
+
const compressedBuffer = Buffer.from(data, "base64");
|
|
3012
|
+
const decompress = new zlib.Inflate({ windowBits: 15 });
|
|
3013
|
+
decompress.write(compressedBuffer);
|
|
3014
|
+
decompress.flush(zlib.constants.Z_SYNC_FLUSH);
|
|
3015
|
+
const result = decompress.read();
|
|
3016
|
+
const jsonText = result.toString();
|
|
3017
|
+
let formattedMsg;
|
|
3018
|
+
let jsonMessage;
|
|
3019
|
+
try {
|
|
3020
|
+
jsonMessage = JSON.parse(jsonText).message;
|
|
3021
|
+
} catch {
|
|
3022
|
+
jsonMessage = jsonText;
|
|
3023
|
+
}
|
|
3024
|
+
try {
|
|
3025
|
+
const ohmaMsg = JSON.parse(jsonMessage);
|
|
3026
|
+
formattedMsg = JSON.stringify(ohmaMsg, null, 2);
|
|
3027
|
+
} catch {
|
|
3028
|
+
formattedMsg = jsonMessage;
|
|
3029
|
+
}
|
|
3030
|
+
decodeResult.decoded = true;
|
|
3031
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
3032
|
+
decodeResult.raw.ohma = jsonText;
|
|
3033
|
+
decodeResult.formatted.items.push({
|
|
3034
|
+
type: "ohma",
|
|
3035
|
+
code: "OHMA",
|
|
3036
|
+
label: "OHMA Downlink",
|
|
3037
|
+
value: formattedMsg
|
|
3038
|
+
});
|
|
3039
|
+
} catch (e) {
|
|
3040
|
+
if (options.debug) {
|
|
3041
|
+
console.log(`Decoder: Unknown H1 OHMA message: ${message.text}`, e);
|
|
3042
|
+
}
|
|
3043
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
3044
|
+
decodeResult.decoded = false;
|
|
3045
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
3046
|
+
}
|
|
3047
|
+
return decodeResult;
|
|
3048
|
+
}
|
|
3049
|
+
};
|
|
3050
|
+
|
|
3051
|
+
// lib/plugins/Label_H1_StarPOS.ts
|
|
3052
|
+
var Label_H1_StarPOS = class extends DecoderPlugin {
|
|
3053
|
+
name = "label-h1-star-pos";
|
|
3054
|
+
qualifiers() {
|
|
3055
|
+
return {
|
|
3056
|
+
labels: ["H1"],
|
|
3057
|
+
preambles: ["*POS"]
|
|
3058
|
+
};
|
|
3059
|
+
}
|
|
3060
|
+
decode(message, options = {}) {
|
|
3061
|
+
let decodeResult = this.defaultResult();
|
|
3062
|
+
decodeResult.decoder.name = this.name;
|
|
3063
|
+
decodeResult.formatted.description = "Position Report";
|
|
3064
|
+
decodeResult.message = message;
|
|
3065
|
+
const msg = message.text;
|
|
3066
|
+
if (msg.length !== 43 || !msg.startsWith("*POS")) {
|
|
3067
|
+
if (options.debug) {
|
|
3068
|
+
console.log(`Decoder: Unknown H1 message: ${msg}`);
|
|
3069
|
+
}
|
|
3070
|
+
ResultFormatter.unknown(decodeResult, msg);
|
|
3071
|
+
decodeResult.decoded = false;
|
|
3072
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
3073
|
+
return decodeResult;
|
|
3074
|
+
}
|
|
3075
|
+
decodeResult.raw.month = Number(msg.substring(4, 6));
|
|
3076
|
+
decodeResult.raw.day_of_month = Number(msg.substring(6, 8));
|
|
3077
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(msg.substring(8, 12) + "00"));
|
|
3078
|
+
ResultFormatter.position(decodeResult, {
|
|
3079
|
+
// Deg Min, no sec
|
|
3080
|
+
latitude: CoordinateUtils.getDirection(msg.substring(12, 13)) * (Number(msg.substring(13, 15)) + Number(msg.substring(15, 17)) / 60),
|
|
3081
|
+
longitude: CoordinateUtils.getDirection(msg.substring(17, 18)) * (Number(msg.substring(18, 21)) + Number(msg.substring(21, 23)) / 60)
|
|
3082
|
+
});
|
|
3083
|
+
ResultFormatter.altitude(decodeResult, Number(msg.substring(23, 28)));
|
|
3084
|
+
ResultFormatter.unknown(decodeResult, msg.substring(28));
|
|
3085
|
+
decodeResult.decoded = true;
|
|
3086
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
3087
|
+
return decodeResult;
|
|
3088
|
+
}
|
|
3089
|
+
};
|
|
3090
|
+
|
|
3091
|
+
// lib/plugins/Label_H1_WRN.ts
|
|
3092
|
+
var Label_H1_WRN = class extends DecoderPlugin {
|
|
3093
|
+
name = "label-h1-wrn";
|
|
3094
|
+
qualifiers() {
|
|
3095
|
+
return {
|
|
3096
|
+
labels: ["H1"],
|
|
3097
|
+
preambles: ["WRN", "#CFBWRN"]
|
|
3098
|
+
};
|
|
3099
|
+
}
|
|
3100
|
+
decode(message, options = {}) {
|
|
3101
|
+
let decodeResult = this.defaultResult();
|
|
3102
|
+
decodeResult.decoder.name = this.name;
|
|
3103
|
+
decodeResult.formatted.description = "Warning Message";
|
|
3104
|
+
decodeResult.message = message;
|
|
3105
|
+
const parts = message.text.split("/WN");
|
|
3106
|
+
if (parts.length > 1) {
|
|
3107
|
+
const fields = parts[0].split("/");
|
|
3108
|
+
ResultFormatter.unknownArr(decodeResult, fields.slice(1), "/");
|
|
3109
|
+
const data = parts[1].substring(0, 20);
|
|
3110
|
+
const msg = parts[1].substring(20);
|
|
3111
|
+
const datetime = data.substring(0, 12);
|
|
3112
|
+
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
3113
|
+
ResultFormatter.unknown(decodeResult, data.substring(12), "/");
|
|
3114
|
+
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
3115
|
+
decodeResult.raw.warning_message = msg;
|
|
3116
|
+
decodeResult.formatted.items.push({
|
|
3117
|
+
type: "warning",
|
|
3118
|
+
code: "WRN",
|
|
3119
|
+
label: "Warning Message",
|
|
3120
|
+
value: decodeResult.raw.warning_message
|
|
3121
|
+
});
|
|
3122
|
+
decodeResult.decoded = true;
|
|
3123
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
3124
|
+
} else {
|
|
3125
|
+
if (options.debug) {
|
|
3126
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
3127
|
+
}
|
|
3128
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
2818
3129
|
decodeResult.decoded = false;
|
|
2819
3130
|
decodeResult.decoder.decodeLevel = "none";
|
|
2820
3131
|
}
|
|
@@ -2845,25 +3156,18 @@ var Label_HX = class extends DecoderPlugin {
|
|
|
2845
3156
|
let londir = parts[4].substring(0, 1);
|
|
2846
3157
|
let londeg = Number(parts[4].substring(1, 4));
|
|
2847
3158
|
let lonmin = Number(parts[4].substring(4, 8));
|
|
2848
|
-
|
|
3159
|
+
let pos = {
|
|
2849
3160
|
latitude: (latdeg + latmin / 60) * (latdir === "N" ? 1 : -1),
|
|
2850
3161
|
longitude: (londeg + lonmin / 60) * (londir === "E" ? 1 : -1)
|
|
2851
3162
|
};
|
|
2852
|
-
decodeResult
|
|
3163
|
+
ResultFormatter.unknownArr(decodeResult, parts.slice(5), " ");
|
|
3164
|
+
ResultFormatter.position(decodeResult, pos);
|
|
2853
3165
|
} else if (parts[2] === "43") {
|
|
2854
3166
|
ResultFormatter.departureAirport(decodeResult, parts[3]);
|
|
2855
|
-
decodeResult
|
|
3167
|
+
ResultFormatter.unknownArr(decodeResult, parts.slice(4), " ");
|
|
2856
3168
|
} else {
|
|
2857
3169
|
decodeResult.decoded = false;
|
|
2858
3170
|
}
|
|
2859
|
-
if (decodeResult.raw.position) {
|
|
2860
|
-
decodeResult.formatted.items.push({
|
|
2861
|
-
type: "aircraft_position",
|
|
2862
|
-
code: "POS",
|
|
2863
|
-
label: "Aircraft Position",
|
|
2864
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
2865
|
-
});
|
|
2866
|
-
}
|
|
2867
3171
|
if (decodeResult.decoded) {
|
|
2868
3172
|
if (!decodeResult.remaining.text)
|
|
2869
3173
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -2893,7 +3197,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2893
3197
|
if (decodeResult.raw.version === "2") {
|
|
2894
3198
|
const regex = /0(\d)X(?<org>\w)(?<iata>\w\w\w)(?<icao>\w\w\w\w)(?<station>\d)(?<lat>\d+)(?<latd>[NS])(?<lng>\d+)(?<lngd>[EW])V(?<vfreq>\d+)\/.*/;
|
|
2895
3199
|
const result = message.text.match(regex);
|
|
2896
|
-
if (result && result.length >= 8) {
|
|
3200
|
+
if (result?.groups && result.length >= 8) {
|
|
2897
3201
|
decodeResult.raw.groundStation = {
|
|
2898
3202
|
number: result.groups.station,
|
|
2899
3203
|
iataCode: result.groups.iata,
|
|
@@ -2903,7 +3207,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2903
3207
|
longitude: Number(result.groups.lng) / 100 * (result.groups.lngd === "W" ? -1 : 1)
|
|
2904
3208
|
}
|
|
2905
3209
|
};
|
|
2906
|
-
decodeResult.raw.vdlFrequency = result.groups.vfreq / 1e3;
|
|
3210
|
+
decodeResult.raw.vdlFrequency = Number(result.groups.vfreq) / 1e3;
|
|
2907
3211
|
}
|
|
2908
3212
|
}
|
|
2909
3213
|
decodeResult.formatted.description = "Ground Station Squitter";
|
|
@@ -2994,31 +3298,11 @@ var Label_QR = class extends DecoderPlugin {
|
|
|
2994
3298
|
decode(message, options = {}) {
|
|
2995
3299
|
const decodeResult = this.defaultResult();
|
|
2996
3300
|
decodeResult.decoder.name = this.name;
|
|
2997
|
-
decodeResult.raw.origin = message.text.substring(0, 4);
|
|
2998
|
-
decodeResult.raw.destination = message.text.substring(4, 8);
|
|
2999
|
-
decodeResult.raw.wheels_on = message.text.substring(8, 12);
|
|
3000
|
-
decodeResult.remaining.text = message.text.substring(12);
|
|
3001
3301
|
decodeResult.formatted.description = "ON Report";
|
|
3002
|
-
decodeResult.
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
label: "Origin",
|
|
3007
|
-
value: decodeResult.raw.origin
|
|
3008
|
-
},
|
|
3009
|
-
{
|
|
3010
|
-
type: "destination",
|
|
3011
|
-
code: "DST",
|
|
3012
|
-
label: "Destination",
|
|
3013
|
-
value: decodeResult.raw.destination
|
|
3014
|
-
},
|
|
3015
|
-
{
|
|
3016
|
-
type: "wheels_on",
|
|
3017
|
-
code: "WON",
|
|
3018
|
-
label: "Wheels ON",
|
|
3019
|
-
value: decodeResult.raw.wheels_on
|
|
3020
|
-
}
|
|
3021
|
-
];
|
|
3302
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
3303
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
3304
|
+
ResultFormatter.on(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12) + "00"));
|
|
3305
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
3022
3306
|
decodeResult.decoded = true;
|
|
3023
3307
|
if (!decodeResult.remaining.text)
|
|
3024
3308
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -3039,31 +3323,11 @@ var Label_QP = class extends DecoderPlugin {
|
|
|
3039
3323
|
decode(message, options = {}) {
|
|
3040
3324
|
const decodeResult = this.defaultResult();
|
|
3041
3325
|
decodeResult.decoder.name = this.name;
|
|
3042
|
-
decodeResult.raw.origin = message.text.substring(0, 4);
|
|
3043
|
-
decodeResult.raw.destination = message.text.substring(4, 8);
|
|
3044
|
-
decodeResult.raw.gate_out = message.text.substring(8, 12);
|
|
3045
|
-
decodeResult.remaining.text = message.text.substring(12);
|
|
3046
3326
|
decodeResult.formatted.description = "OUT Report";
|
|
3047
|
-
decodeResult.
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
label: "Origin",
|
|
3052
|
-
value: decodeResult.raw.origin
|
|
3053
|
-
},
|
|
3054
|
-
{
|
|
3055
|
-
type: "destination",
|
|
3056
|
-
code: "DST",
|
|
3057
|
-
label: "Destination",
|
|
3058
|
-
value: decodeResult.raw.destination
|
|
3059
|
-
},
|
|
3060
|
-
{
|
|
3061
|
-
type: "gate_out",
|
|
3062
|
-
code: "GOUT",
|
|
3063
|
-
label: "Gate OUT",
|
|
3064
|
-
value: decodeResult.raw.gate_out
|
|
3065
|
-
}
|
|
3066
|
-
];
|
|
3327
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
3328
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
3329
|
+
ResultFormatter.out(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12) + "00"));
|
|
3330
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
3067
3331
|
decodeResult.decoded = true;
|
|
3068
3332
|
if (!decodeResult.remaining.text)
|
|
3069
3333
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -3084,31 +3348,11 @@ var Label_QS = class extends DecoderPlugin {
|
|
|
3084
3348
|
decode(message, options = {}) {
|
|
3085
3349
|
const decodeResult = this.defaultResult();
|
|
3086
3350
|
decodeResult.decoder.name = this.name;
|
|
3087
|
-
decodeResult.raw.origin = message.text.substring(0, 4);
|
|
3088
|
-
decodeResult.raw.destination = message.text.substring(4, 8);
|
|
3089
|
-
decodeResult.raw.gate_in = message.text.substring(8, 12);
|
|
3090
|
-
decodeResult.remaining.text = message.text.substring(12);
|
|
3091
3351
|
decodeResult.formatted.description = "IN Report";
|
|
3092
|
-
decodeResult.
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
label: "Origin",
|
|
3097
|
-
value: decodeResult.raw.origin
|
|
3098
|
-
},
|
|
3099
|
-
{
|
|
3100
|
-
type: "destination",
|
|
3101
|
-
code: "DST",
|
|
3102
|
-
label: "Destination",
|
|
3103
|
-
value: decodeResult.raw.destination
|
|
3104
|
-
},
|
|
3105
|
-
{
|
|
3106
|
-
type: "gate_in",
|
|
3107
|
-
code: "GIN",
|
|
3108
|
-
label: "Gate IN",
|
|
3109
|
-
value: decodeResult.raw.gate_in
|
|
3110
|
-
}
|
|
3111
|
-
];
|
|
3352
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
3353
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
3354
|
+
ResultFormatter.in(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12) + "00"));
|
|
3355
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
3112
3356
|
decodeResult.decoded = true;
|
|
3113
3357
|
if (!decodeResult.remaining.text)
|
|
3114
3358
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -3133,43 +3377,30 @@ var Label_QQ = class extends DecoderPlugin {
|
|
|
3133
3377
|
decodeResult.formatted.description = "OFF Report";
|
|
3134
3378
|
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
3135
3379
|
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
3136
|
-
decodeResult.raw.wheels_off = message.text.substring(8, 12);
|
|
3137
3380
|
if (message.text.substring(12, 19) === "\r\n001FE") {
|
|
3138
3381
|
decodeResult.raw.day_of_month = message.text.substring(19, 21);
|
|
3139
|
-
decodeResult.
|
|
3382
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(21, 27)));
|
|
3140
3383
|
let latdir = message.text.substring(27, 28);
|
|
3141
3384
|
let latdeg = Number(message.text.substring(28, 30));
|
|
3142
3385
|
let latmin = Number(message.text.substring(30, 34));
|
|
3143
3386
|
let londir = message.text.substring(34, 35);
|
|
3144
3387
|
let londeg = Number(message.text.substring(35, 38));
|
|
3145
3388
|
let lonmin = Number(message.text.substring(38, 42));
|
|
3146
|
-
|
|
3389
|
+
let pos = {
|
|
3147
3390
|
latitude: (latdeg + latmin / 60) * (latdir === "N" ? 1 : -1),
|
|
3148
3391
|
longitude: (londeg + lonmin / 60) * (londir === "E" ? 1 : -1)
|
|
3149
3392
|
};
|
|
3150
|
-
decodeResult
|
|
3393
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(42, 45));
|
|
3394
|
+
ResultFormatter.position(decodeResult, pos);
|
|
3151
3395
|
if (decodeResult.remaining.text !== "---") {
|
|
3152
|
-
ResultFormatter.groundspeed(decodeResult, message.text.substring(45, 48));
|
|
3396
|
+
ResultFormatter.groundspeed(decodeResult, Number(message.text.substring(45, 48)));
|
|
3153
3397
|
} else {
|
|
3154
3398
|
ResultFormatter.unknown(decodeResult, message.text.substring(45, 48));
|
|
3155
3399
|
}
|
|
3156
3400
|
ResultFormatter.unknown(decodeResult, message.text.substring(48));
|
|
3157
3401
|
} else {
|
|
3158
|
-
decodeResult.
|
|
3159
|
-
|
|
3160
|
-
decodeResult.formatted.items.push({
|
|
3161
|
-
type: "wheels_off",
|
|
3162
|
-
code: "WOFF",
|
|
3163
|
-
label: "Wheels OFF",
|
|
3164
|
-
value: decodeResult.raw.wheels_off
|
|
3165
|
-
});
|
|
3166
|
-
if (decodeResult.raw.position) {
|
|
3167
|
-
decodeResult.formatted.items.push({
|
|
3168
|
-
type: "aircraft_position",
|
|
3169
|
-
code: "POS",
|
|
3170
|
-
label: "Aircraft Position",
|
|
3171
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
3172
|
-
});
|
|
3402
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12) + "00"));
|
|
3403
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
3173
3404
|
}
|
|
3174
3405
|
decodeResult.decoded = true;
|
|
3175
3406
|
if (!decodeResult.remaining.text)
|
|
@@ -4001,8 +4232,14 @@ var MessageDecoder = class {
|
|
|
4001
4232
|
this.registerPlugin(new Label_15(this));
|
|
4002
4233
|
this.registerPlugin(new Label_15_FST(this));
|
|
4003
4234
|
this.registerPlugin(new Label_16_N_Space(this));
|
|
4235
|
+
this.registerPlugin(new Label_1L_3Line(this));
|
|
4236
|
+
this.registerPlugin(new Label_1L_070(this));
|
|
4237
|
+
this.registerPlugin(new Label_1L_660(this));
|
|
4238
|
+
this.registerPlugin(new Label_1L_Slash(this));
|
|
4004
4239
|
this.registerPlugin(new Label_20_POS(this));
|
|
4005
4240
|
this.registerPlugin(new Label_21_POS(this));
|
|
4241
|
+
this.registerPlugin(new Label_22_OFF(this));
|
|
4242
|
+
this.registerPlugin(new Label_22_POS(this));
|
|
4006
4243
|
this.registerPlugin(new Label_24_Slash(this));
|
|
4007
4244
|
this.registerPlugin(new Label_30_Slash_EA(this));
|
|
4008
4245
|
this.registerPlugin(new Label_44_ETA(this));
|
|
@@ -4015,12 +4252,14 @@ var MessageDecoder = class {
|
|
|
4015
4252
|
this.registerPlugin(new Label_4A_DIS(this));
|
|
4016
4253
|
this.registerPlugin(new Label_4A_DOOR(this));
|
|
4017
4254
|
this.registerPlugin(new Label_4A_Slash_01(this));
|
|
4255
|
+
this.registerPlugin(new Label_4J_POS(this));
|
|
4018
4256
|
this.registerPlugin(new Label_4N(this));
|
|
4019
4257
|
this.registerPlugin(new Label_B6_Forwardslash(this));
|
|
4020
4258
|
this.registerPlugin(new Label_H1_FLR(this));
|
|
4021
4259
|
this.registerPlugin(new Label_H1_OHMA(this));
|
|
4022
4260
|
this.registerPlugin(new Label_H1_WRN(this));
|
|
4023
4261
|
this.registerPlugin(new Label_H1(this));
|
|
4262
|
+
this.registerPlugin(new Label_H1_StarPOS(this));
|
|
4024
4263
|
this.registerPlugin(new Label_HX(this));
|
|
4025
4264
|
this.registerPlugin(new Label_80(this));
|
|
4026
4265
|
this.registerPlugin(new Label_83(this));
|