@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.js
CHANGED
|
@@ -166,7 +166,7 @@ var DecoderPlugin = class {
|
|
|
166
166
|
};
|
|
167
167
|
|
|
168
168
|
// lib/utils/coordinate_utils.ts
|
|
169
|
-
var CoordinateUtils = class {
|
|
169
|
+
var CoordinateUtils = class _CoordinateUtils {
|
|
170
170
|
/**
|
|
171
171
|
* Decode a string of coordinates into an object with latitude and longitude in millidegrees
|
|
172
172
|
* @param stringCoords - The string of coordinates to decode
|
|
@@ -183,8 +183,8 @@ var CoordinateUtils = class {
|
|
|
183
183
|
longitudeChars = stringCoords.substring(8, 14);
|
|
184
184
|
}
|
|
185
185
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
186
|
-
results.latitude = Number(stringCoords.substring(1, 6)) / 1e3 * (firstChar
|
|
187
|
-
results.longitude = Number(longitudeChars) / 1e3 * (middleChar
|
|
186
|
+
results.latitude = Number(stringCoords.substring(1, 6)) / 1e3 * _CoordinateUtils.getDirection(firstChar);
|
|
187
|
+
results.longitude = Number(longitudeChars) / 1e3 * _CoordinateUtils.getDirection(middleChar);
|
|
188
188
|
} else {
|
|
189
189
|
return;
|
|
190
190
|
}
|
|
@@ -210,8 +210,8 @@ var CoordinateUtils = class {
|
|
|
210
210
|
const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
|
|
211
211
|
const lonMin = Number(longitudeChars) % 1e3 / 10;
|
|
212
212
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
213
|
-
results.latitude = (latDeg + latMin / 60) * (firstChar
|
|
214
|
-
results.longitude = (lonDeg + lonMin / 60) * (middleChar
|
|
213
|
+
results.latitude = (latDeg + latMin / 60) * _CoordinateUtils.getDirection(firstChar);
|
|
214
|
+
results.longitude = (lonDeg + lonMin / 60) * _CoordinateUtils.getDirection(middleChar);
|
|
215
215
|
} else {
|
|
216
216
|
return;
|
|
217
217
|
}
|
|
@@ -318,6 +318,15 @@ var RouteUtils = class _RouteUtils {
|
|
|
318
318
|
|
|
319
319
|
// lib/utils/result_formatter.ts
|
|
320
320
|
var ResultFormatter = class {
|
|
321
|
+
static route(decodeResult, route) {
|
|
322
|
+
decodeResult.raw.route = route;
|
|
323
|
+
decodeResult.formatted.items.push({
|
|
324
|
+
type: "aircraft_route",
|
|
325
|
+
code: "ROUTE",
|
|
326
|
+
label: "Aircraft Route",
|
|
327
|
+
value: RouteUtils.routeToString(route)
|
|
328
|
+
});
|
|
329
|
+
}
|
|
321
330
|
static state_change(decodeResult, from, to) {
|
|
322
331
|
decodeResult.raw.state_change = {
|
|
323
332
|
from,
|
|
@@ -354,6 +363,9 @@ var ResultFormatter = class {
|
|
|
354
363
|
});
|
|
355
364
|
}
|
|
356
365
|
static position(decodeResult, value) {
|
|
366
|
+
if (!value || isNaN(value.latitude) || isNaN(value.longitude)) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
357
369
|
decodeResult.raw.position = value;
|
|
358
370
|
decodeResult.formatted.items.push({
|
|
359
371
|
type: "aircraft_position",
|
|
@@ -590,17 +602,50 @@ var ResultFormatter = class {
|
|
|
590
602
|
value: DateTimeUtils.timestampToString(time, "tod")
|
|
591
603
|
});
|
|
592
604
|
}
|
|
593
|
-
static
|
|
594
|
-
decodeResult.raw.
|
|
605
|
+
static day(decodeResult, day) {
|
|
606
|
+
decodeResult.raw.day_of_month = day;
|
|
607
|
+
decodeResult.formatted.items.push({
|
|
608
|
+
type: "day_of_month",
|
|
609
|
+
code: "MSG_DAY",
|
|
610
|
+
label: "Day of Month",
|
|
611
|
+
value: `${day}`
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
static departureDay(decodeResult, day) {
|
|
615
|
+
decodeResult.raw.departure_day_of_month = day;
|
|
616
|
+
decodeResult.formatted.items.push({
|
|
617
|
+
type: "day_of_month",
|
|
618
|
+
code: "DEP_DAY",
|
|
619
|
+
label: "Departure Day",
|
|
620
|
+
value: `${day}`
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
static arrivalDay(decodeResult, day) {
|
|
624
|
+
decodeResult.raw.arrival_day_of_month = day;
|
|
625
|
+
decodeResult.formatted.items.push({
|
|
626
|
+
type: "day_of_month",
|
|
627
|
+
code: "ARR_DAY",
|
|
628
|
+
label: "Arrival Day",
|
|
629
|
+
value: `${day}`
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
static text(decodeResult, text) {
|
|
633
|
+
decodeResult.raw.text = text;
|
|
595
634
|
decodeResult.formatted.items.push({
|
|
596
635
|
type: "text",
|
|
597
636
|
code: "TEXT",
|
|
598
637
|
label: "Text Message",
|
|
599
|
-
value:
|
|
638
|
+
value: text
|
|
600
639
|
});
|
|
601
640
|
}
|
|
602
|
-
static unknown(decodeResult, value) {
|
|
603
|
-
decodeResult.remaining.text
|
|
641
|
+
static unknown(decodeResult, value, sep = ",") {
|
|
642
|
+
if (!decodeResult.remaining.text)
|
|
643
|
+
decodeResult.remaining.text = value;
|
|
644
|
+
else
|
|
645
|
+
decodeResult.remaining.text += sep + value;
|
|
646
|
+
}
|
|
647
|
+
static unknownArr(decodeResult, value, sep = ",") {
|
|
648
|
+
this.unknown(decodeResult, value.join(sep), sep);
|
|
604
649
|
}
|
|
605
650
|
};
|
|
606
651
|
|
|
@@ -676,14 +721,14 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
676
721
|
decodeResult.raw.day_of_month = Number(info[3]);
|
|
677
722
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(info[4]));
|
|
678
723
|
ResultFormatter.arrivalRunway(decodeResult, info[5].slice(1));
|
|
679
|
-
decodeResult
|
|
724
|
+
ResultFormatter.unknownArr(decodeResult, data.slice(3), "/");
|
|
680
725
|
} else if (type === "B3") {
|
|
681
726
|
ResultFormatter.departureAirport(decodeResult, header[1].substring(0, 3), "IATA");
|
|
682
727
|
ResultFormatter.arrivalAirport(decodeResult, header[1].substring(3), "IATA");
|
|
683
728
|
decodeResult.raw.day_of_month = Number(header[2]);
|
|
684
729
|
ResultFormatter.arrivalRunway(decodeResult, header[3].slice(1));
|
|
685
730
|
if (header.length > 4) {
|
|
686
|
-
decodeResult
|
|
731
|
+
ResultFormatter.unknownArr(decodeResult, header.slice(4), "/");
|
|
687
732
|
}
|
|
688
733
|
} else if (type === "C3" && data[1] === "C3 GATE REQ ") {
|
|
689
734
|
const info = data[2].split(" ");
|
|
@@ -691,7 +736,7 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
691
736
|
ResultFormatter.arrivalAirport(decodeResult, info[2]);
|
|
692
737
|
decodeResult.raw.day_of_month = Number(info[3]);
|
|
693
738
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(info[4]));
|
|
694
|
-
decodeResult
|
|
739
|
+
ResultFormatter.unknownArr(decodeResult, info.slice(5), " ");
|
|
695
740
|
} else if (type === "C3") {
|
|
696
741
|
ResultFormatter.departureAirport(decodeResult, header[1].substring(0, 3), "IATA");
|
|
697
742
|
ResultFormatter.arrivalAirport(decodeResult, header[1].substring(3), "IATA");
|
|
@@ -703,7 +748,7 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
703
748
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(airports[4]));
|
|
704
749
|
const estimates = data[3].split(" ");
|
|
705
750
|
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(estimates[1] + "00"));
|
|
706
|
-
decodeResult
|
|
751
|
+
ResultFormatter.unknown(decodeResult, estimates[2]);
|
|
707
752
|
} else {
|
|
708
753
|
if (options.debug) {
|
|
709
754
|
console.log(`Decoder: Unkown 5Z RDC format: ${message.text}`);
|
|
@@ -715,7 +760,7 @@ var Label_5Z_Slash = class extends DecoderPlugin {
|
|
|
715
760
|
if (options.debug) {
|
|
716
761
|
console.log(`Decoder: Unknown 5Z message: ${message.text}`);
|
|
717
762
|
}
|
|
718
|
-
decodeResult
|
|
763
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
719
764
|
decodeResult.decoded = false;
|
|
720
765
|
decodeResult.decoder.decodeLevel = "none";
|
|
721
766
|
}
|
|
@@ -743,7 +788,7 @@ var Label_10_LDR = class extends DecoderPlugin {
|
|
|
743
788
|
if (options.debug) {
|
|
744
789
|
console.log(`Decoder: Unknown 10 message: ${message.text}`);
|
|
745
790
|
}
|
|
746
|
-
decodeResult
|
|
791
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
747
792
|
decodeResult.decoded = false;
|
|
748
793
|
decodeResult.decoder.decodeLevel = "none";
|
|
749
794
|
return decodeResult;
|
|
@@ -764,7 +809,7 @@ var Label_10_LDR = class extends DecoderPlugin {
|
|
|
764
809
|
if (altRwy != "") {
|
|
765
810
|
ResultFormatter.alternateRunway(decodeResult, altRwy);
|
|
766
811
|
}
|
|
767
|
-
decodeResult
|
|
812
|
+
ResultFormatter.unknownArr(decodeResult, [...parts.slice(0, 5), ...parts.slice(15)]);
|
|
768
813
|
decodeResult.decoded = true;
|
|
769
814
|
decodeResult.decoder.decodeLevel = "partial";
|
|
770
815
|
return decodeResult;
|
|
@@ -791,7 +836,7 @@ var Label_10_POS = class extends DecoderPlugin {
|
|
|
791
836
|
if (options.debug) {
|
|
792
837
|
console.log(`Decoder: Unknown 10 message: ${message.text}`);
|
|
793
838
|
}
|
|
794
|
-
decodeResult
|
|
839
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
795
840
|
decodeResult.decoded = false;
|
|
796
841
|
decodeResult.decoder.decodeLevel = "none";
|
|
797
842
|
return decodeResult;
|
|
@@ -804,7 +849,7 @@ var Label_10_POS = class extends DecoderPlugin {
|
|
|
804
849
|
};
|
|
805
850
|
ResultFormatter.position(decodeResult, position);
|
|
806
851
|
ResultFormatter.altitude(decodeResult, Number(parts[7]));
|
|
807
|
-
decodeResult
|
|
852
|
+
ResultFormatter.unknownArr(decodeResult, [parts[0], ...parts.slice(3, 7), ...parts.slice(8)]);
|
|
808
853
|
decodeResult.decoded = true;
|
|
809
854
|
decodeResult.decoder.decodeLevel = "partial";
|
|
810
855
|
return decodeResult;
|
|
@@ -831,7 +876,7 @@ var Label_10_Slash = class extends DecoderPlugin {
|
|
|
831
876
|
if (options.debug) {
|
|
832
877
|
console.log(`Decoder: Unknown 10 message: ${message.text}`);
|
|
833
878
|
}
|
|
834
|
-
decodeResult
|
|
879
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
835
880
|
decodeResult.decoded = false;
|
|
836
881
|
decodeResult.decoder.decodeLevel = "none";
|
|
837
882
|
return decodeResult;
|
|
@@ -858,17 +903,11 @@ var Label_10_Slash = class extends DecoderPlugin {
|
|
|
858
903
|
time: DateTimeUtils.convertHHMMSSToTod(parts[15] + "00"),
|
|
859
904
|
timeFormat: "tod"
|
|
860
905
|
}];
|
|
861
|
-
|
|
862
|
-
decodeResult.formatted.items.push({
|
|
863
|
-
type: "aircraft_route",
|
|
864
|
-
code: "ROUTE",
|
|
865
|
-
label: "Aircraft Route",
|
|
866
|
-
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
867
|
-
});
|
|
906
|
+
ResultFormatter.route(decodeResult, { waypoints });
|
|
868
907
|
if (parts[16]) {
|
|
869
908
|
ResultFormatter.departureAirport(decodeResult, parts[16]);
|
|
870
909
|
}
|
|
871
|
-
decodeResult
|
|
910
|
+
ResultFormatter.unknownArr(decodeResult, [parts[3], parts[4], ...parts.slice(9, 11), ...parts.slice(17)], "/");
|
|
872
911
|
decodeResult.decoded = true;
|
|
873
912
|
decodeResult.decoder.decodeLevel = "partial";
|
|
874
913
|
return decodeResult;
|
|
@@ -890,35 +929,29 @@ var Label_12_N_Space = class extends DecoderPlugin {
|
|
|
890
929
|
decodeResult.formatted.description = "Position Report";
|
|
891
930
|
decodeResult.message = message;
|
|
892
931
|
const variant1Regex = /^(?<lat>[NS])\s(?<lat_coord>.*),(?<long>[EW])\s*(?<long_coord>.*),(?<alt>.*),(?<unkwn1>.*),\s*(?<unkwn2>.*),.(?<airframe>.*),(?<unkwn3>.*)$/;
|
|
893
|
-
let results;
|
|
894
|
-
if (results
|
|
932
|
+
let results = message.text.match(variant1Regex);
|
|
933
|
+
if (results?.groups) {
|
|
895
934
|
if (options.debug) {
|
|
896
935
|
console.log(`Label 12 N : results`);
|
|
897
936
|
console.log(results);
|
|
898
937
|
}
|
|
899
|
-
|
|
938
|
+
ResultFormatter.position(decodeResult, {
|
|
900
939
|
latitude: Number(results.groups.lat_coord) * (results.groups.lat == "N" ? 1 : -1),
|
|
901
940
|
longitude: Number(results.groups.long_coord) * (results.groups.long == "E" ? 1 : -1)
|
|
902
|
-
};
|
|
903
|
-
const altitude = results.groups.alt == "GRD" || results.groups.alt == "***" ? 0 : Number(results.groups.alt);
|
|
904
|
-
decodeResult.formatted.items.push({
|
|
905
|
-
type: "aircraft_position",
|
|
906
|
-
code: "POS",
|
|
907
|
-
label: "Aircraft Position",
|
|
908
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
909
941
|
});
|
|
942
|
+
const altitude = results.groups.alt == "GRD" || results.groups.alt == "***" ? 0 : Number(results.groups.alt);
|
|
910
943
|
ResultFormatter.altitude(decodeResult, altitude);
|
|
911
|
-
decodeResult
|
|
944
|
+
ResultFormatter.unknownArr(decodeResult, [results.groups.unkwn1, results.groups.unkwn2, results.groups.unkwn3]);
|
|
912
945
|
decodeResult.decoded = true;
|
|
913
946
|
decodeResult.decoder.decodeLevel = "partial";
|
|
914
|
-
|
|
915
|
-
if (options.debug) {
|
|
916
|
-
console.log(`Decoder: Unknown 12 message: ${message.text}`);
|
|
917
|
-
}
|
|
918
|
-
decodeResult.remaining.text = message.text;
|
|
919
|
-
decodeResult.decoded = false;
|
|
920
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
947
|
+
return decodeResult;
|
|
921
948
|
}
|
|
949
|
+
if (options.debug) {
|
|
950
|
+
console.log(`Decoder: Unknown 12 message: ${message.text}`);
|
|
951
|
+
}
|
|
952
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
953
|
+
decodeResult.decoded = false;
|
|
954
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
922
955
|
return decodeResult;
|
|
923
956
|
}
|
|
924
957
|
};
|
|
@@ -945,12 +978,11 @@ var Label_13Through18_Slash = class extends DecoderPlugin {
|
|
|
945
978
|
if (options?.debug) {
|
|
946
979
|
console.log(`Decoder: Unknown OOOI message: ${message.text}`);
|
|
947
980
|
}
|
|
948
|
-
decodeResult
|
|
981
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
949
982
|
decodeResult.decoded = false;
|
|
950
983
|
decodeResult.decoder.decodeLevel = "none";
|
|
951
984
|
return decodeResult;
|
|
952
985
|
}
|
|
953
|
-
decodeResult.remaining.text = "";
|
|
954
986
|
const data = parts[2].split(" ");
|
|
955
987
|
ResultFormatter.departureAirport(decodeResult, data[1]);
|
|
956
988
|
ResultFormatter.arrivalAirport(decodeResult, data[2]);
|
|
@@ -966,7 +998,7 @@ var Label_13Through18_Slash = class extends DecoderPlugin {
|
|
|
966
998
|
ResultFormatter.in(decodeResult, time);
|
|
967
999
|
}
|
|
968
1000
|
if (parts.length === 7) {
|
|
969
|
-
decodeResult
|
|
1001
|
+
ResultFormatter.unknownArr(decodeResult, parts.slice(4), "/");
|
|
970
1002
|
}
|
|
971
1003
|
for (let i = 1; i < lines.length; i++) {
|
|
972
1004
|
if (lines[i].startsWith("/LOC")) {
|
|
@@ -980,11 +1012,9 @@ var Label_13Through18_Slash = class extends DecoderPlugin {
|
|
|
980
1012
|
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)))
|
|
981
1013
|
};
|
|
982
1014
|
}
|
|
983
|
-
|
|
984
|
-
ResultFormatter.position(decodeResult, position);
|
|
985
|
-
}
|
|
1015
|
+
ResultFormatter.position(decodeResult, position);
|
|
986
1016
|
} else {
|
|
987
|
-
decodeResult
|
|
1017
|
+
ResultFormatter.unknown(decodeResult, lines[i], "\r\n");
|
|
988
1018
|
}
|
|
989
1019
|
}
|
|
990
1020
|
decodeResult.decoded = true;
|
|
@@ -1029,16 +1059,8 @@ var Label_15 = class extends DecoderPlugin {
|
|
|
1029
1059
|
decodeResult.formatted.description = "Position Report";
|
|
1030
1060
|
const twoZeeRegex = /^\(2(?<between>.+)\(Z$/;
|
|
1031
1061
|
const results = message.text.match(twoZeeRegex);
|
|
1032
|
-
if (results) {
|
|
1033
|
-
|
|
1034
|
-
if (decodeResult.raw.position) {
|
|
1035
|
-
decodeResult.formatted.items.push({
|
|
1036
|
-
type: "position",
|
|
1037
|
-
code: "POS",
|
|
1038
|
-
label: "Position",
|
|
1039
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1040
|
-
});
|
|
1041
|
-
}
|
|
1062
|
+
if (results?.groups) {
|
|
1063
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(results.groups.between.substr(0, 13)));
|
|
1042
1064
|
}
|
|
1043
1065
|
decodeResult.decoded = true;
|
|
1044
1066
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -1062,31 +1084,23 @@ var Label_15_FST = class extends DecoderPlugin {
|
|
|
1062
1084
|
decodeResult.message = message;
|
|
1063
1085
|
const parts = message.text.split(" ");
|
|
1064
1086
|
const header = parts[0];
|
|
1065
|
-
decodeResult.raw.departure_icao = header.substring(5, 9);
|
|
1066
|
-
decodeResult.raw.arrival_icao = header.substring(9, 13);
|
|
1067
1087
|
const stringCoords = header.substring(13);
|
|
1068
1088
|
const firstChar = stringCoords.substring(0, 1);
|
|
1069
1089
|
const middleChar = stringCoords.substring(7, 8);
|
|
1070
1090
|
decodeResult.raw.position = {};
|
|
1071
1091
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
decodeResult
|
|
1092
|
+
const lat = Number(stringCoords.substring(1, 7)) / 1e4 * (firstChar === "S" ? -1 : 1);
|
|
1093
|
+
const lon = Number(stringCoords.substring(8, 15)) / 1e4 * (middleChar === "W" ? -1 : 1);
|
|
1094
|
+
ResultFormatter.position(decodeResult, { latitude: lat, longitude: lon });
|
|
1095
|
+
ResultFormatter.altitude(decodeResult, Number(stringCoords.substring(15)) * 100);
|
|
1075
1096
|
} else {
|
|
1076
1097
|
decodeResult.decoded = false;
|
|
1077
1098
|
decodeResult.decoder.decodeLevel = "none";
|
|
1078
1099
|
return decodeResult;
|
|
1079
1100
|
}
|
|
1080
|
-
decodeResult.
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
label: "Aircraft Position",
|
|
1084
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1085
|
-
});
|
|
1086
|
-
ResultFormatter.altitude(decodeResult, decodeResult.raw.altitude);
|
|
1087
|
-
ResultFormatter.departureAirport(decodeResult, decodeResult.raw.departure_icao);
|
|
1088
|
-
ResultFormatter.arrivalAirport(decodeResult, decodeResult.raw.arrival_icao);
|
|
1089
|
-
decodeResult.remaining.text = parts.slice(1).join(" ");
|
|
1101
|
+
ResultFormatter.departureAirport(decodeResult, header.substring(5, 9));
|
|
1102
|
+
ResultFormatter.arrivalAirport(decodeResult, header.substring(9, 13));
|
|
1103
|
+
ResultFormatter.unknownArr(decodeResult, parts.slice(1), " ");
|
|
1090
1104
|
decodeResult.decoded = true;
|
|
1091
1105
|
decodeResult.decoder.decodeLevel = "partial";
|
|
1092
1106
|
return decodeResult;
|
|
@@ -1109,52 +1123,45 @@ var Label_16_N_Space = class extends DecoderPlugin {
|
|
|
1109
1123
|
decodeResult.message = message;
|
|
1110
1124
|
let variant1Regex = /^(?<lat>[NS])\s(?<lat_coord>.*),(?<long>[EW])\s*(?<long_coord>.*),(?<alt>.*),(?<unkwn1>.*),\s*(?<unkwn2>.*)$/;
|
|
1111
1125
|
let variant2Regex = /^(?<lat>[NS])\s(?<lat_coord>.*)\/(?<long>[EW])\s*(?<long_coord>.*)$/;
|
|
1112
|
-
let results;
|
|
1113
|
-
if (results
|
|
1126
|
+
let results = message.text.match(variant1Regex);
|
|
1127
|
+
if (results?.groups) {
|
|
1114
1128
|
if (options.debug) {
|
|
1115
1129
|
console.log(`Label 16 N : results`);
|
|
1116
1130
|
console.log(results);
|
|
1117
1131
|
}
|
|
1118
|
-
|
|
1132
|
+
let pos = {
|
|
1119
1133
|
latitude: Number(results.groups.lat_coord) * (results.groups.lat == "N" ? 1 : -1),
|
|
1120
1134
|
longitude: Number(results.groups.long_coord) * (results.groups.long == "E" ? 1 : -1)
|
|
1121
1135
|
};
|
|
1122
1136
|
const altitude = results.groups.alt == "GRD" || results.groups.alt == "***" ? 0 : Number(results.groups.alt);
|
|
1123
|
-
|
|
1124
|
-
type: "aircraft_position",
|
|
1125
|
-
code: "POS",
|
|
1126
|
-
label: "Aircraft Position",
|
|
1127
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1128
|
-
});
|
|
1137
|
+
ResultFormatter.position(decodeResult, pos);
|
|
1129
1138
|
ResultFormatter.altitude(decodeResult, altitude);
|
|
1130
|
-
decodeResult
|
|
1139
|
+
ResultFormatter.unknownArr(decodeResult, [results.groups.unkwn1, results.groups.unkwn2]);
|
|
1131
1140
|
decodeResult.decoded = true;
|
|
1132
1141
|
decodeResult.decoder.decodeLevel = "partial";
|
|
1133
|
-
|
|
1142
|
+
return decodeResult;
|
|
1143
|
+
}
|
|
1144
|
+
results = message.text.match(variant2Regex);
|
|
1145
|
+
if (results?.groups) {
|
|
1134
1146
|
if (options.debug) {
|
|
1135
1147
|
console.log(`Label 16 N : results`);
|
|
1136
1148
|
console.log(results);
|
|
1137
1149
|
}
|
|
1138
|
-
|
|
1150
|
+
let pos = {
|
|
1139
1151
|
latitude: Number(results.groups.lat_coord) * (results.groups.lat == "N" ? 1 : -1),
|
|
1140
1152
|
longitude: Number(results.groups.long_coord) * (results.groups.long == "E" ? 1 : -1)
|
|
1141
1153
|
};
|
|
1142
|
-
|
|
1143
|
-
type: "aircraft_position",
|
|
1144
|
-
code: "POS",
|
|
1145
|
-
label: "Aircraft Position",
|
|
1146
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1147
|
-
});
|
|
1154
|
+
ResultFormatter.position(decodeResult, pos);
|
|
1148
1155
|
decodeResult.decoded = true;
|
|
1149
1156
|
decodeResult.decoder.decodeLevel = "full";
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
}
|
|
1154
|
-
decodeResult.remaining.text = message.text;
|
|
1155
|
-
decodeResult.decoded = false;
|
|
1156
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
1157
|
+
return decodeResult;
|
|
1158
|
+
}
|
|
1159
|
+
if (options.debug) {
|
|
1160
|
+
console.log(`Decoder: Unknown 16 message: ${message.text}`);
|
|
1157
1161
|
}
|
|
1162
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
1163
|
+
decodeResult.decoded = false;
|
|
1164
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1158
1165
|
return decodeResult;
|
|
1159
1166
|
}
|
|
1160
1167
|
};
|
|
@@ -1193,6 +1200,265 @@ var Label_1M_Slash = class extends DecoderPlugin {
|
|
|
1193
1200
|
}
|
|
1194
1201
|
};
|
|
1195
1202
|
|
|
1203
|
+
// lib/plugins/Label_1L_3-line.ts
|
|
1204
|
+
var Label_1L_3Line = class extends DecoderPlugin {
|
|
1205
|
+
// eslint-disable-line camelcase
|
|
1206
|
+
name = "label-1l-3-line";
|
|
1207
|
+
qualifiers() {
|
|
1208
|
+
return {
|
|
1209
|
+
labels: ["1L"]
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
decode(message, options = {}) {
|
|
1213
|
+
const decodeResult = this.defaultResult();
|
|
1214
|
+
decodeResult.decoder.name = this.name;
|
|
1215
|
+
decodeResult.formatted.description = "Position Report";
|
|
1216
|
+
decodeResult.message = message;
|
|
1217
|
+
const lines = message.text.split("\r\n");
|
|
1218
|
+
if (lines.length !== 3) {
|
|
1219
|
+
if (options.debug) {
|
|
1220
|
+
console.log(`Decoder: Unknown 1L message: ${message.text}`);
|
|
1221
|
+
}
|
|
1222
|
+
decodeResult.remaining.text = message.text;
|
|
1223
|
+
decodeResult.decoded = false;
|
|
1224
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1225
|
+
return decodeResult;
|
|
1226
|
+
}
|
|
1227
|
+
const parts = message.text.replaceAll("\r\n", "/").split("/");
|
|
1228
|
+
const data = /* @__PURE__ */ new Map();
|
|
1229
|
+
data.set("", parts[0]);
|
|
1230
|
+
for (let i = 1; i < parts.length; i++) {
|
|
1231
|
+
const part = parts[i].split(" ");
|
|
1232
|
+
data.set(part[0], part.slice(1).join(" "));
|
|
1233
|
+
}
|
|
1234
|
+
const dep = data.get("DEP");
|
|
1235
|
+
if (dep) {
|
|
1236
|
+
ResultFormatter.departureAirport(decodeResult, dep);
|
|
1237
|
+
data.delete("DEP");
|
|
1238
|
+
}
|
|
1239
|
+
const des = data.get("DES");
|
|
1240
|
+
if (des) {
|
|
1241
|
+
ResultFormatter.arrivalAirport(decodeResult, des);
|
|
1242
|
+
data.delete("DES");
|
|
1243
|
+
}
|
|
1244
|
+
const eta = data.get("ETA");
|
|
1245
|
+
if (eta) {
|
|
1246
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(eta + "00"));
|
|
1247
|
+
data.delete("ETA");
|
|
1248
|
+
}
|
|
1249
|
+
const alt = data.get("ALT");
|
|
1250
|
+
if (alt) {
|
|
1251
|
+
ResultFormatter.altitude(decodeResult, Number(alt));
|
|
1252
|
+
data.delete("ALT");
|
|
1253
|
+
}
|
|
1254
|
+
const fn = data.get("FN");
|
|
1255
|
+
if (fn) {
|
|
1256
|
+
ResultFormatter.flightNumber(decodeResult, fn);
|
|
1257
|
+
data.delete("FN");
|
|
1258
|
+
}
|
|
1259
|
+
const day = data.get("DAY");
|
|
1260
|
+
const utc = data.get("UTC");
|
|
1261
|
+
if (day && utc) {
|
|
1262
|
+
decodeResult.raw.message_timestamp = Date.parse(day + " GMT+0000") / 1e3 + DateTimeUtils.convertHHMMSSToTod(utc);
|
|
1263
|
+
data.delete("DAY");
|
|
1264
|
+
data.delete("UTC");
|
|
1265
|
+
}
|
|
1266
|
+
const lat = data.get("LAT");
|
|
1267
|
+
const lon = data.get("LON");
|
|
1268
|
+
if (lat && lon) {
|
|
1269
|
+
ResultFormatter.position(decodeResult, {
|
|
1270
|
+
latitude: CoordinateUtils.getDirection(lat[0]) * Number(lat.substring(1)),
|
|
1271
|
+
longitude: CoordinateUtils.getDirection(lon[0]) * Number(lon.substring(1))
|
|
1272
|
+
});
|
|
1273
|
+
data.delete("LAT");
|
|
1274
|
+
data.delete("LON");
|
|
1275
|
+
}
|
|
1276
|
+
let remaining = "";
|
|
1277
|
+
for (const [key, value] of data.entries()) {
|
|
1278
|
+
if (key === "") {
|
|
1279
|
+
remaining += value;
|
|
1280
|
+
} else {
|
|
1281
|
+
remaining += `/${key} ${value}`;
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
decodeResult.remaining.text = remaining;
|
|
1285
|
+
decodeResult.decoded = true;
|
|
1286
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1287
|
+
return decodeResult;
|
|
1288
|
+
}
|
|
1289
|
+
};
|
|
1290
|
+
|
|
1291
|
+
// lib/plugins/Label_1L_070.ts
|
|
1292
|
+
var Label_1L_070 = class extends DecoderPlugin {
|
|
1293
|
+
// eslint-disable-line camelcase
|
|
1294
|
+
name = "label-1l-070";
|
|
1295
|
+
qualifiers() {
|
|
1296
|
+
return {
|
|
1297
|
+
labels: ["1L"],
|
|
1298
|
+
preambles: ["000000070"]
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
decode(message, options = {}) {
|
|
1302
|
+
const decodeResult = this.defaultResult();
|
|
1303
|
+
decodeResult.decoder.name = this.name;
|
|
1304
|
+
decodeResult.formatted.description = "Position Report";
|
|
1305
|
+
decodeResult.message = message;
|
|
1306
|
+
if (!message.text.startsWith("000000070")) {
|
|
1307
|
+
if (options.debug) {
|
|
1308
|
+
console.log(`Decoder: Unknown 1L message: ${message.text}`);
|
|
1309
|
+
}
|
|
1310
|
+
decodeResult.remaining.text = message.text;
|
|
1311
|
+
decodeResult.decoded = false;
|
|
1312
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1313
|
+
return decodeResult;
|
|
1314
|
+
}
|
|
1315
|
+
const parts = message.text.substring(9).split(",");
|
|
1316
|
+
if (parts.length !== 7) {
|
|
1317
|
+
if (options.debug) {
|
|
1318
|
+
console.log(`Decoder: Unknown 1L message: ${message.text}`);
|
|
1319
|
+
}
|
|
1320
|
+
decodeResult.remaining.text = message.text;
|
|
1321
|
+
decodeResult.decoded = false;
|
|
1322
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1323
|
+
return decodeResult;
|
|
1324
|
+
}
|
|
1325
|
+
ResultFormatter.departureAirport(decodeResult, parts[0]);
|
|
1326
|
+
ResultFormatter.arrivalAirport(decodeResult, parts[1]);
|
|
1327
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[2] + "00"));
|
|
1328
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(parts[3] + "00"));
|
|
1329
|
+
ResultFormatter.position(decodeResult, {
|
|
1330
|
+
latitude: CoordinateUtils.getDirection(parts[4][0]) * Number(parts[4].substring(1)),
|
|
1331
|
+
longitude: CoordinateUtils.getDirection(parts[5][0]) * Number(parts[5].substring(1))
|
|
1332
|
+
});
|
|
1333
|
+
decodeResult.remaining.text = parts[6];
|
|
1334
|
+
decodeResult.decoded = true;
|
|
1335
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1336
|
+
return decodeResult;
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
|
|
1340
|
+
// lib/plugins/Label_1L_660.ts
|
|
1341
|
+
var Label_1L_660 = class extends DecoderPlugin {
|
|
1342
|
+
// eslint-disable-line camelcase
|
|
1343
|
+
name = "label-1l-660";
|
|
1344
|
+
qualifiers() {
|
|
1345
|
+
return {
|
|
1346
|
+
labels: ["1L"],
|
|
1347
|
+
preambles: ["000000660"]
|
|
1348
|
+
};
|
|
1349
|
+
}
|
|
1350
|
+
decode(message, options = {}) {
|
|
1351
|
+
const decodeResult = this.defaultResult();
|
|
1352
|
+
decodeResult.decoder.name = this.name;
|
|
1353
|
+
decodeResult.formatted.description = "Position Report";
|
|
1354
|
+
decodeResult.message = message;
|
|
1355
|
+
if (!message.text.startsWith("000000660")) {
|
|
1356
|
+
if (options.debug) {
|
|
1357
|
+
console.log(`Decoder: Unknown 1L message: ${message.text}`);
|
|
1358
|
+
}
|
|
1359
|
+
decodeResult.remaining.text = message.text;
|
|
1360
|
+
decodeResult.decoded = false;
|
|
1361
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1362
|
+
return decodeResult;
|
|
1363
|
+
}
|
|
1364
|
+
const parts = message.text.substring(9).split(",");
|
|
1365
|
+
if (parts.length !== 5) {
|
|
1366
|
+
if (options.debug) {
|
|
1367
|
+
console.log(`Decoder: Unknown 1L message: ${message.text}`);
|
|
1368
|
+
}
|
|
1369
|
+
decodeResult.remaining.text = message.text;
|
|
1370
|
+
decodeResult.decoded = false;
|
|
1371
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1372
|
+
return decodeResult;
|
|
1373
|
+
}
|
|
1374
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(parts[0]);
|
|
1375
|
+
if (position) {
|
|
1376
|
+
ResultFormatter.position(decodeResult, position);
|
|
1377
|
+
}
|
|
1378
|
+
const hhmmss = parts[1].substring(0, 6);
|
|
1379
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(hhmmss));
|
|
1380
|
+
const fl = parts[1].substring(6, 9);
|
|
1381
|
+
ResultFormatter.altitude(decodeResult, Number(fl) * 100);
|
|
1382
|
+
const next = parts[1].substring(9);
|
|
1383
|
+
ResultFormatter.route(decodeResult, { waypoints: [{ name: next.trim() }] });
|
|
1384
|
+
decodeResult.remaining.text = parts.slice(2).join(",");
|
|
1385
|
+
decodeResult.decoded = true;
|
|
1386
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1387
|
+
return decodeResult;
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1390
|
+
|
|
1391
|
+
// lib/plugins/Label_1L_Slash.ts
|
|
1392
|
+
var Label_1L_Slash = class extends DecoderPlugin {
|
|
1393
|
+
// eslint-disable-line camelcase
|
|
1394
|
+
name = "label-1l-1-line";
|
|
1395
|
+
qualifiers() {
|
|
1396
|
+
return {
|
|
1397
|
+
labels: ["1L"],
|
|
1398
|
+
preambles: ["+", "-"]
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1401
|
+
decode(message, options = {}) {
|
|
1402
|
+
const decodeResult = this.defaultResult();
|
|
1403
|
+
decodeResult.decoder.name = this.name;
|
|
1404
|
+
decodeResult.formatted.description = "Position Report";
|
|
1405
|
+
decodeResult.message = message;
|
|
1406
|
+
const parts = message.text.split("/");
|
|
1407
|
+
if (parts.length !== 7) {
|
|
1408
|
+
if (options.debug) {
|
|
1409
|
+
console.log(`Decoder: Unknown 1L message: ${message.text}`);
|
|
1410
|
+
}
|
|
1411
|
+
decodeResult.remaining.text = message.text;
|
|
1412
|
+
decodeResult.decoded = false;
|
|
1413
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1414
|
+
return decodeResult;
|
|
1415
|
+
}
|
|
1416
|
+
const data = /* @__PURE__ */ new Map();
|
|
1417
|
+
data.set("LAT", parts[0].replaceAll(" ", ""));
|
|
1418
|
+
data.set("LON", parts[1].replaceAll(" ", ""));
|
|
1419
|
+
for (let i = 2; i < parts.length; i++) {
|
|
1420
|
+
const part = parts[i].split(" ");
|
|
1421
|
+
data.set(part[0], part.slice(1).join(" "));
|
|
1422
|
+
}
|
|
1423
|
+
console.log(data);
|
|
1424
|
+
const position = {
|
|
1425
|
+
latitude: Number(data.get("LAT")),
|
|
1426
|
+
longitude: Number(data.get("LON"))
|
|
1427
|
+
};
|
|
1428
|
+
data.delete("LAT");
|
|
1429
|
+
data.delete("LON");
|
|
1430
|
+
ResultFormatter.position(decodeResult, position);
|
|
1431
|
+
const utc = data.get("UTC");
|
|
1432
|
+
if (utc) {
|
|
1433
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(utc));
|
|
1434
|
+
data.delete("UTC");
|
|
1435
|
+
}
|
|
1436
|
+
const alt = data.get("ALT");
|
|
1437
|
+
if (alt) {
|
|
1438
|
+
ResultFormatter.altitude(decodeResult, Number(alt));
|
|
1439
|
+
data.delete("ALT");
|
|
1440
|
+
}
|
|
1441
|
+
const fob = data.get("FOB");
|
|
1442
|
+
if (fob) {
|
|
1443
|
+
ResultFormatter.currentFuel(decodeResult, Number(fob));
|
|
1444
|
+
data.delete("FOB");
|
|
1445
|
+
}
|
|
1446
|
+
const eta = data.get("ETA");
|
|
1447
|
+
if (eta) {
|
|
1448
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(eta + "00"));
|
|
1449
|
+
data.delete("ETA");
|
|
1450
|
+
}
|
|
1451
|
+
let remaining = "";
|
|
1452
|
+
for (const [key, value] of data.entries()) {
|
|
1453
|
+
remaining += `/${key} ${value}`;
|
|
1454
|
+
}
|
|
1455
|
+
decodeResult.remaining.text = remaining;
|
|
1456
|
+
decodeResult.decoded = true;
|
|
1457
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1458
|
+
return decodeResult;
|
|
1459
|
+
}
|
|
1460
|
+
};
|
|
1461
|
+
|
|
1196
1462
|
// lib/plugins/Label_20_POS.ts
|
|
1197
1463
|
var Label_20_POS = class extends DecoderPlugin {
|
|
1198
1464
|
name = "label-20-pos";
|
|
@@ -1215,30 +1481,16 @@ var Label_20_POS = class extends DecoderPlugin {
|
|
|
1215
1481
|
console.log(`DEBUG: ${this.name}: Variation 1 detected`);
|
|
1216
1482
|
}
|
|
1217
1483
|
const rawCoords = fields[0];
|
|
1218
|
-
|
|
1219
|
-
if (decodeResult.raw.position) {
|
|
1220
|
-
decodeResult.formatted.items.push({
|
|
1221
|
-
type: "position",
|
|
1222
|
-
code: "POS",
|
|
1223
|
-
label: "Position",
|
|
1224
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1225
|
-
});
|
|
1226
|
-
}
|
|
1484
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(rawCoords));
|
|
1227
1485
|
decodeResult.decoded = true;
|
|
1228
1486
|
decodeResult.decoder.decodeLevel = "full";
|
|
1229
1487
|
} else if (fields.length == 5) {
|
|
1230
1488
|
if (options.debug) {
|
|
1231
1489
|
console.log(`DEBUG: ${this.name}: Variation 2 detected`);
|
|
1232
1490
|
}
|
|
1233
|
-
const
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
decodeResult.formatted.items.push({
|
|
1237
|
-
type: "position",
|
|
1238
|
-
code: "POS",
|
|
1239
|
-
label: "Position",
|
|
1240
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1241
|
-
});
|
|
1491
|
+
const position = CoordinateUtils.decodeStringCoordinates(fields[0]);
|
|
1492
|
+
if (position) {
|
|
1493
|
+
ResultFormatter.position(decodeResult, position);
|
|
1242
1494
|
}
|
|
1243
1495
|
decodeResult.decoded = true;
|
|
1244
1496
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1277,11 +1529,7 @@ var Label_21_POS = class extends DecoderPlugin {
|
|
|
1277
1529
|
ResultFormatter.temperature(decodeResult, fields[6].replace(/ /g, ""));
|
|
1278
1530
|
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[7]));
|
|
1279
1531
|
ResultFormatter.arrivalAirport(decodeResult, fields[8]);
|
|
1280
|
-
decodeResult
|
|
1281
|
-
fields[1],
|
|
1282
|
-
fields[4],
|
|
1283
|
-
fields[5]
|
|
1284
|
-
].join(",");
|
|
1532
|
+
ResultFormatter.unknownArr(decodeResult, [fields[1], fields[4], fields[5]]);
|
|
1285
1533
|
decodeResult.decoded = true;
|
|
1286
1534
|
decodeResult.decoder.decodeLevel = "partial";
|
|
1287
1535
|
} else {
|
|
@@ -1307,41 +1555,74 @@ function processPosition(decodeResult, value) {
|
|
|
1307
1555
|
ResultFormatter.position(decodeResult, position);
|
|
1308
1556
|
}
|
|
1309
1557
|
|
|
1310
|
-
// lib/plugins/
|
|
1311
|
-
var
|
|
1312
|
-
name = "label-
|
|
1558
|
+
// lib/plugins/Label_22_OFF.ts
|
|
1559
|
+
var Label_22_OFF = class extends DecoderPlugin {
|
|
1560
|
+
name = "label-22-off";
|
|
1313
1561
|
qualifiers() {
|
|
1314
1562
|
return {
|
|
1315
|
-
labels: ["
|
|
1316
|
-
preambles: ["
|
|
1563
|
+
labels: ["22"],
|
|
1564
|
+
preambles: ["OFF"]
|
|
1317
1565
|
};
|
|
1318
1566
|
}
|
|
1319
1567
|
decode(message, options = {}) {
|
|
1320
1568
|
const decodeResult = this.defaultResult();
|
|
1321
1569
|
decodeResult.decoder.name = this.name;
|
|
1322
|
-
decodeResult.formatted.description = "
|
|
1570
|
+
decodeResult.formatted.description = "Takeoff Report";
|
|
1323
1571
|
decodeResult.message = message;
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
ResultFormatter.
|
|
1338
|
-
ResultFormatter.
|
|
1339
|
-
decodeResult.
|
|
1572
|
+
if (message.text.startsWith("OFF01")) {
|
|
1573
|
+
const fields = message.text.substring(5).split("/");
|
|
1574
|
+
if (fields.length != 2) {
|
|
1575
|
+
decodeResult.decoded = false;
|
|
1576
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1577
|
+
return decodeResult;
|
|
1578
|
+
}
|
|
1579
|
+
ResultFormatter.flightNumber(decodeResult, fields[0]);
|
|
1580
|
+
ResultFormatter.departureDay(decodeResult, Number(fields[1].substring(0, 2)));
|
|
1581
|
+
ResultFormatter.arrivalDay(decodeResult, Number(fields[1].substring(2, 4)));
|
|
1582
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(4, 8) + "00"));
|
|
1583
|
+
ResultFormatter.departureAirport(decodeResult, fields[1].substring(8, 12));
|
|
1584
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[1].substring(12, 16));
|
|
1585
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 22)));
|
|
1586
|
+
ResultFormatter.unknown(decodeResult, fields[1].substring(22));
|
|
1587
|
+
decodeResult.decoded = true;
|
|
1588
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1589
|
+
} else if (message.text.startsWith("OFF02\r\n")) {
|
|
1590
|
+
const fields = message.text.substring(7).split(",");
|
|
1591
|
+
if (fields.length != 4) {
|
|
1592
|
+
decodeResult.decoded = false;
|
|
1593
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1594
|
+
return decodeResult;
|
|
1595
|
+
}
|
|
1596
|
+
ResultFormatter.departureAirport(decodeResult, fields[0]);
|
|
1597
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[1]);
|
|
1598
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2] + "00"));
|
|
1599
|
+
ResultFormatter.unknown(decodeResult, fields[3]);
|
|
1600
|
+
decodeResult.decoded = true;
|
|
1601
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1602
|
+
} else if (message.text.startsWith("OFF02")) {
|
|
1603
|
+
const fields = message.text.substring(5).split("/");
|
|
1604
|
+
if (fields.length != 2) {
|
|
1605
|
+
decodeResult.decoded = false;
|
|
1606
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1607
|
+
return decodeResult;
|
|
1608
|
+
}
|
|
1609
|
+
ResultFormatter.flightNumber(decodeResult, fields[0]);
|
|
1610
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(fields[1].substring(0, 14));
|
|
1611
|
+
if (position) {
|
|
1612
|
+
ResultFormatter.position(decodeResult, position);
|
|
1613
|
+
}
|
|
1614
|
+
ResultFormatter.day(decodeResult, Number(fields[1].substring(14, 16)));
|
|
1615
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(16, 20) + "00"));
|
|
1616
|
+
ResultFormatter.departureAirport(decodeResult, fields[1].substring(20, 24));
|
|
1617
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[1].substring(24, 28));
|
|
1618
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(28, 32) + "00"));
|
|
1619
|
+
ResultFormatter.unknown(decodeResult, fields[1].substring(32, 36));
|
|
1620
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1].substring(36, 40) + "00"));
|
|
1340
1621
|
decodeResult.decoded = true;
|
|
1341
1622
|
decodeResult.decoder.decodeLevel = "partial";
|
|
1342
1623
|
} else {
|
|
1343
1624
|
if (options.debug) {
|
|
1344
|
-
console.log(`DEBUG: ${this.name}: Unknown variation
|
|
1625
|
+
console.log(`DEBUG: ${this.name}: Unknown variation.`);
|
|
1345
1626
|
}
|
|
1346
1627
|
decodeResult.decoded = false;
|
|
1347
1628
|
decodeResult.decoder.decodeLevel = "none";
|
|
@@ -1350,33 +1631,116 @@ var Label_24_Slash = class extends DecoderPlugin {
|
|
|
1350
1631
|
}
|
|
1351
1632
|
};
|
|
1352
1633
|
|
|
1353
|
-
// lib/plugins/
|
|
1354
|
-
var
|
|
1355
|
-
name = "label-
|
|
1634
|
+
// lib/plugins/Label_22_POS.ts
|
|
1635
|
+
var Label_22_POS = class extends DecoderPlugin {
|
|
1636
|
+
name = "label-22-pos";
|
|
1356
1637
|
qualifiers() {
|
|
1357
1638
|
return {
|
|
1358
|
-
labels: ["
|
|
1359
|
-
preambles: ["
|
|
1639
|
+
labels: ["22"],
|
|
1640
|
+
preambles: ["N", "S"]
|
|
1360
1641
|
};
|
|
1361
1642
|
}
|
|
1362
1643
|
decode(message, options = {}) {
|
|
1363
1644
|
const decodeResult = this.defaultResult();
|
|
1364
1645
|
decodeResult.decoder.name = this.name;
|
|
1365
|
-
decodeResult.formatted.description = "
|
|
1646
|
+
decodeResult.formatted.description = "Position Report";
|
|
1366
1647
|
decodeResult.message = message;
|
|
1367
|
-
const
|
|
1368
|
-
if (
|
|
1648
|
+
const fields = message.text.split(",");
|
|
1649
|
+
if (fields.length !== 11) {
|
|
1369
1650
|
if (options.debug) {
|
|
1370
|
-
console.log(`
|
|
1371
|
-
|
|
1651
|
+
console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}, content: ${fields.join(",")}`);
|
|
1652
|
+
}
|
|
1653
|
+
decodeResult.decoded = false;
|
|
1654
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1655
|
+
return decodeResult;
|
|
1656
|
+
}
|
|
1657
|
+
const latStr = fields[0].substring(1, 8);
|
|
1658
|
+
const lonStr = fields[0].substring(9);
|
|
1659
|
+
const lat = Number(latStr) / 1e4;
|
|
1660
|
+
const lon = Number(lonStr) / 1e4;
|
|
1661
|
+
ResultFormatter.position(decodeResult, {
|
|
1662
|
+
latitude: CoordinateUtils.getDirection(fields[0][0]) * lat,
|
|
1663
|
+
longitude: CoordinateUtils.getDirection(fields[0][8]) * lon
|
|
1664
|
+
});
|
|
1665
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2]));
|
|
1666
|
+
ResultFormatter.altitude(decodeResult, Number(fields[3]));
|
|
1667
|
+
ResultFormatter.unknownArr(decodeResult, [fields[1], ...fields.slice(4)]);
|
|
1668
|
+
decodeResult.decoded = true;
|
|
1669
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1670
|
+
return decodeResult;
|
|
1671
|
+
}
|
|
1672
|
+
};
|
|
1673
|
+
|
|
1674
|
+
// lib/plugins/Label_24_Slash.ts
|
|
1675
|
+
var Label_24_Slash = class extends DecoderPlugin {
|
|
1676
|
+
name = "label-24-slash";
|
|
1677
|
+
qualifiers() {
|
|
1678
|
+
return {
|
|
1679
|
+
labels: ["24"],
|
|
1680
|
+
preambles: ["/"]
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
decode(message, options = {}) {
|
|
1684
|
+
const decodeResult = this.defaultResult();
|
|
1685
|
+
decodeResult.decoder.name = this.name;
|
|
1686
|
+
decodeResult.formatted.description = "Position Report";
|
|
1687
|
+
decodeResult.message = message;
|
|
1688
|
+
const fields = message.text.split("/");
|
|
1689
|
+
if (fields.length == 10 && fields[0] == "" && fields[9] == "") {
|
|
1690
|
+
const mmddyy = fields[1].substring(4, 6) + fields[1].substring(2, 4) + fields[1].substring(0, 2);
|
|
1691
|
+
const hhmmss = fields[2] + "00";
|
|
1692
|
+
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(hhmmss, mmddyy);
|
|
1693
|
+
ResultFormatter.flightNumber(decodeResult, fields[3]);
|
|
1694
|
+
ResultFormatter.altitude(decodeResult, Number(fields[4]));
|
|
1695
|
+
const lat = fields[5];
|
|
1696
|
+
const lon = fields[6];
|
|
1697
|
+
const position = {
|
|
1698
|
+
latitude: (lat[0] === "N" ? 1 : -1) * Number(lat.substring(1)),
|
|
1699
|
+
longitude: (lon[0] === "E" ? 1 : -1) * Number(lon.substring(1))
|
|
1700
|
+
};
|
|
1701
|
+
ResultFormatter.position(decodeResult, position);
|
|
1702
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[8] + "00"));
|
|
1703
|
+
ResultFormatter.unknown(decodeResult, fields[7]);
|
|
1704
|
+
decodeResult.decoded = true;
|
|
1705
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1706
|
+
} else {
|
|
1707
|
+
if (options.debug) {
|
|
1708
|
+
console.log(`DEBUG: ${this.name}: Unknown variation. Field count: ${fields.length}. Message: ${message.text}`);
|
|
1709
|
+
}
|
|
1710
|
+
decodeResult.decoded = false;
|
|
1711
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1712
|
+
}
|
|
1713
|
+
return decodeResult;
|
|
1714
|
+
}
|
|
1715
|
+
};
|
|
1716
|
+
|
|
1717
|
+
// lib/plugins/Label_30_Slash_EA.ts
|
|
1718
|
+
var Label_30_Slash_EA = class extends DecoderPlugin {
|
|
1719
|
+
name = "label-30-slash-ea";
|
|
1720
|
+
qualifiers() {
|
|
1721
|
+
return {
|
|
1722
|
+
labels: ["30"],
|
|
1723
|
+
preambles: ["/EA"]
|
|
1724
|
+
};
|
|
1725
|
+
}
|
|
1726
|
+
decode(message, options = {}) {
|
|
1727
|
+
const decodeResult = this.defaultResult();
|
|
1728
|
+
decodeResult.decoder.name = this.name;
|
|
1729
|
+
decodeResult.formatted.description = "ETA Report";
|
|
1730
|
+
decodeResult.message = message;
|
|
1731
|
+
const results = message.text.split(/\n|\//).slice(1);
|
|
1732
|
+
if (results) {
|
|
1733
|
+
if (options.debug) {
|
|
1734
|
+
console.log(`Label 30 EA: results`);
|
|
1735
|
+
console.log(results);
|
|
1372
1736
|
}
|
|
1373
1737
|
}
|
|
1374
1738
|
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(results[0].substr(2, 4) + "00"));
|
|
1375
1739
|
if (results[1].substring(0, 2) === "DS") {
|
|
1376
1740
|
ResultFormatter.arrivalAirport(decodeResult, results[1].substring(2, 6));
|
|
1377
|
-
decodeResult
|
|
1741
|
+
ResultFormatter.unknown(decodeResult, "/".concat(results[2]));
|
|
1378
1742
|
} else {
|
|
1379
|
-
decodeResult
|
|
1743
|
+
ResultFormatter.unknown(decodeResult, "/".concat(results[1], "/", results[2]));
|
|
1380
1744
|
}
|
|
1381
1745
|
decodeResult.decoded = true;
|
|
1382
1746
|
decodeResult.decoder.decodeLevel = "partial";
|
|
@@ -1400,40 +1764,20 @@ var Label_44_ETA = class extends DecoderPlugin {
|
|
|
1400
1764
|
decodeResult.message = message;
|
|
1401
1765
|
const regex = /^.*,(?<unsplit_coords>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<fuel_in_tons>.*)$/;
|
|
1402
1766
|
const results = message.text.match(regex);
|
|
1403
|
-
if (results) {
|
|
1767
|
+
if (results?.groups) {
|
|
1404
1768
|
if (options.debug) {
|
|
1405
1769
|
console.log(`Label 44 ETA Report: groups`);
|
|
1406
1770
|
console.log(results.groups);
|
|
1407
1771
|
}
|
|
1408
|
-
|
|
1409
|
-
decodeResult
|
|
1410
|
-
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);
|
|
1411
1775
|
decodeResult.raw.current_time = Date.parse(
|
|
1412
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"
|
|
1413
1777
|
);
|
|
1414
1778
|
if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
|
|
1415
|
-
decodeResult
|
|
1416
|
-
}
|
|
1417
|
-
if (decodeResult.raw.position) {
|
|
1418
|
-
decodeResult.formatted.items.push({
|
|
1419
|
-
type: "position",
|
|
1420
|
-
code: "POS",
|
|
1421
|
-
label: "Position",
|
|
1422
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1423
|
-
});
|
|
1779
|
+
ResultFormatter.remainingFuel(decodeResult, Number(results.groups.fuel_in_tons));
|
|
1424
1780
|
}
|
|
1425
|
-
decodeResult.formatted.items.push({
|
|
1426
|
-
type: "origin",
|
|
1427
|
-
code: "ORG",
|
|
1428
|
-
label: "Origin",
|
|
1429
|
-
value: decodeResult.raw.departure_icao
|
|
1430
|
-
});
|
|
1431
|
-
decodeResult.formatted.items.push({
|
|
1432
|
-
type: "destination",
|
|
1433
|
-
code: "DST",
|
|
1434
|
-
label: "Destination",
|
|
1435
|
-
value: decodeResult.raw.arrival_icao
|
|
1436
|
-
});
|
|
1437
1781
|
}
|
|
1438
1782
|
decodeResult.decoded = true;
|
|
1439
1783
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1457,40 +1801,20 @@ var Label_44_IN = class extends DecoderPlugin {
|
|
|
1457
1801
|
decodeResult.message = message;
|
|
1458
1802
|
const regex = /^.*,(?<unsplit_coords>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<fuel_in_tons>.*)$/;
|
|
1459
1803
|
const results = message.text.match(regex);
|
|
1460
|
-
if (results) {
|
|
1804
|
+
if (results?.groups) {
|
|
1461
1805
|
if (options.debug) {
|
|
1462
1806
|
console.log(`Label 44 In Air Report: groups`);
|
|
1463
1807
|
console.log(results.groups);
|
|
1464
1808
|
}
|
|
1465
|
-
|
|
1466
|
-
decodeResult
|
|
1467
|
-
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);
|
|
1468
1812
|
decodeResult.raw.current_time = Date.parse(
|
|
1469
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"
|
|
1470
1814
|
);
|
|
1471
1815
|
if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
|
|
1472
1816
|
decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
|
|
1473
1817
|
}
|
|
1474
|
-
if (decodeResult.raw.position) {
|
|
1475
|
-
decodeResult.formatted.items.push({
|
|
1476
|
-
type: "position",
|
|
1477
|
-
code: "POS",
|
|
1478
|
-
label: "Position",
|
|
1479
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1480
|
-
});
|
|
1481
|
-
}
|
|
1482
|
-
decodeResult.formatted.items.push({
|
|
1483
|
-
type: "origin",
|
|
1484
|
-
code: "ORG",
|
|
1485
|
-
label: "Origin",
|
|
1486
|
-
value: decodeResult.raw.departure_icao
|
|
1487
|
-
});
|
|
1488
|
-
decodeResult.formatted.items.push({
|
|
1489
|
-
type: "destination",
|
|
1490
|
-
code: "DST",
|
|
1491
|
-
label: "Destination",
|
|
1492
|
-
value: decodeResult.raw.arrival_icao
|
|
1493
|
-
});
|
|
1494
1818
|
}
|
|
1495
1819
|
decodeResult.decoded = true;
|
|
1496
1820
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1514,13 +1838,14 @@ var Label_44_OFF = class extends DecoderPlugin {
|
|
|
1514
1838
|
decodeResult.message = message;
|
|
1515
1839
|
const regex = /^.*,(?<unsplit_coords>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<eta_time>.*),(?<fuel_in_tons>.*)$/;
|
|
1516
1840
|
const results = message.text.match(regex);
|
|
1517
|
-
if (results) {
|
|
1841
|
+
if (results?.groups) {
|
|
1518
1842
|
if (options.debug) {
|
|
1519
1843
|
console.log(`Label 44 Off Runway Report: groups`);
|
|
1520
1844
|
console.log(results.groups);
|
|
1521
1845
|
}
|
|
1522
|
-
decodeResult.
|
|
1523
|
-
decodeResult
|
|
1846
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords));
|
|
1847
|
+
ResultFormatter.departureAirport(decodeResult, results.groups.departure_icao);
|
|
1848
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
1524
1849
|
decodeResult.raw.current_time = Date.parse(
|
|
1525
1850
|
(/* @__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"
|
|
1526
1851
|
);
|
|
@@ -1530,27 +1855,6 @@ var Label_44_OFF = class extends DecoderPlugin {
|
|
|
1530
1855
|
if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
|
|
1531
1856
|
decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
|
|
1532
1857
|
}
|
|
1533
|
-
decodeResult.raw.position = CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords);
|
|
1534
|
-
if (decodeResult.raw.position) {
|
|
1535
|
-
decodeResult.formatted.items.push({
|
|
1536
|
-
type: "position",
|
|
1537
|
-
code: "POS",
|
|
1538
|
-
label: "Position",
|
|
1539
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1540
|
-
});
|
|
1541
|
-
}
|
|
1542
|
-
decodeResult.formatted.items.push({
|
|
1543
|
-
type: "origin",
|
|
1544
|
-
code: "ORG",
|
|
1545
|
-
label: "Origin",
|
|
1546
|
-
value: decodeResult.raw.departure_icao
|
|
1547
|
-
});
|
|
1548
|
-
decodeResult.formatted.items.push({
|
|
1549
|
-
type: "destination",
|
|
1550
|
-
code: "DST",
|
|
1551
|
-
label: "Destination",
|
|
1552
|
-
value: decodeResult.raw.arrival_icao
|
|
1553
|
-
});
|
|
1554
1858
|
}
|
|
1555
1859
|
decodeResult.decoded = true;
|
|
1556
1860
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1574,40 +1878,20 @@ var Label_44_ON = class extends DecoderPlugin {
|
|
|
1574
1878
|
decodeResult.message = message;
|
|
1575
1879
|
const regex = /^.*,(?<unsplit_coords>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<fuel_in_tons>.*)$/;
|
|
1576
1880
|
const results = message.text.match(regex);
|
|
1577
|
-
if (results) {
|
|
1881
|
+
if (results?.groups) {
|
|
1578
1882
|
if (options.debug) {
|
|
1579
1883
|
console.log(`Label 44 On Runway Report: groups`);
|
|
1580
1884
|
console.log(results.groups);
|
|
1581
1885
|
}
|
|
1582
|
-
|
|
1583
|
-
decodeResult
|
|
1584
|
-
decodeResult
|
|
1886
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(results.groups.unsplit_coords));
|
|
1887
|
+
ResultFormatter.departureAirport(decodeResult, results.groups.departure_icao);
|
|
1888
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
1585
1889
|
decodeResult.raw.current_time = Date.parse(
|
|
1586
1890
|
(/* @__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"
|
|
1587
1891
|
);
|
|
1588
1892
|
if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
|
|
1589
|
-
decodeResult
|
|
1893
|
+
ResultFormatter.remainingFuel(decodeResult, Number(results.groups.fuel_in_tons));
|
|
1590
1894
|
}
|
|
1591
|
-
if (decodeResult.raw.position) {
|
|
1592
|
-
decodeResult.formatted.items.push({
|
|
1593
|
-
type: "position",
|
|
1594
|
-
code: "POS",
|
|
1595
|
-
label: "Position",
|
|
1596
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1597
|
-
});
|
|
1598
|
-
}
|
|
1599
|
-
decodeResult.formatted.items.push({
|
|
1600
|
-
type: "origin",
|
|
1601
|
-
code: "ORG",
|
|
1602
|
-
label: "Origin",
|
|
1603
|
-
value: decodeResult.raw.departure_icao
|
|
1604
|
-
});
|
|
1605
|
-
decodeResult.formatted.items.push({
|
|
1606
|
-
type: "destination",
|
|
1607
|
-
code: "DST",
|
|
1608
|
-
label: "Destination",
|
|
1609
|
-
value: decodeResult.raw.arrival_icao
|
|
1610
|
-
});
|
|
1611
1895
|
}
|
|
1612
1896
|
decodeResult.decoded = true;
|
|
1613
1897
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -1631,12 +1915,12 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
1631
1915
|
decodeResult.message = message;
|
|
1632
1916
|
const regex = /^.*,(?<unsplit_coords>.*),(?<flight_level_or_ground>.*),(?<departure_icao>.*),(?<arrival_icao>.*),(?<current_date>.*),(?<current_time>.*),(?<eta_time>.*),(?<fuel_in_tons>.*)$/;
|
|
1633
1917
|
const results = message.text.match(regex);
|
|
1634
|
-
if (results) {
|
|
1918
|
+
if (results?.groups) {
|
|
1635
1919
|
if (options.debug) {
|
|
1636
1920
|
console.log(`Label 44 Position Report: groups`);
|
|
1637
1921
|
console.log(results.groups);
|
|
1638
1922
|
}
|
|
1639
|
-
|
|
1923
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinatesDecimalMinutes(results.groups.unsplit_coords));
|
|
1640
1924
|
const flight_level = results.groups.flight_level_or_ground == "GRD" || results.groups.flight_level_or_ground == "***" ? 0 : Number(results.groups.flight_level_or_ground);
|
|
1641
1925
|
decodeResult.raw.current_time = Date.parse(
|
|
1642
1926
|
(/* @__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"
|
|
@@ -1647,14 +1931,6 @@ var Label_44_POS = class extends DecoderPlugin {
|
|
|
1647
1931
|
if (results.groups.fuel_in_tons != "***" && results.groups.fuel_in_tons != "****") {
|
|
1648
1932
|
decodeResult.raw.fuel_in_tons = Number(results.groups.fuel_in_tons);
|
|
1649
1933
|
}
|
|
1650
|
-
if (decodeResult.raw.position) {
|
|
1651
|
-
decodeResult.formatted.items.push({
|
|
1652
|
-
type: "aircraft_position",
|
|
1653
|
-
code: "POS",
|
|
1654
|
-
label: "Aircraft Position",
|
|
1655
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
1656
|
-
});
|
|
1657
|
-
}
|
|
1658
1934
|
ResultFormatter.departureAirport(decodeResult, results.groups.departure_icao);
|
|
1659
1935
|
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
1660
1936
|
ResultFormatter.altitude(decodeResult, flight_level * 100);
|
|
@@ -1678,13 +1954,13 @@ var Label_4A = class extends DecoderPlugin {
|
|
|
1678
1954
|
decodeResult.decoder.name = this.name;
|
|
1679
1955
|
decodeResult.message = message;
|
|
1680
1956
|
decodeResult.formatted.description = "Latest New Format";
|
|
1681
|
-
let
|
|
1682
|
-
if (
|
|
1957
|
+
let text = message.text;
|
|
1958
|
+
if (text.match(/^M\d{2}A\w{6}/)) {
|
|
1683
1959
|
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
1684
|
-
|
|
1960
|
+
text = text.substring(10);
|
|
1685
1961
|
}
|
|
1686
1962
|
decodeResult.decoded = true;
|
|
1687
|
-
const fields =
|
|
1963
|
+
const fields = text.split(",");
|
|
1688
1964
|
if (fields.length === 11) {
|
|
1689
1965
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[0]));
|
|
1690
1966
|
ResultFormatter.tail(decodeResult, fields[2].replace(".", ""));
|
|
@@ -1692,8 +1968,8 @@ var Label_4A = class extends DecoderPlugin {
|
|
|
1692
1968
|
ResultFormatter.callsign(decodeResult, fields[3]);
|
|
1693
1969
|
ResultFormatter.departureAirport(decodeResult, fields[4]);
|
|
1694
1970
|
ResultFormatter.arrivalAirport(decodeResult, fields[5]);
|
|
1695
|
-
ResultFormatter.altitude(decodeResult,
|
|
1696
|
-
decodeResult
|
|
1971
|
+
ResultFormatter.altitude(decodeResult, Number(text.substring(48, 51)) * 100);
|
|
1972
|
+
ResultFormatter.unknownArr(decodeResult, fields.slice(8));
|
|
1697
1973
|
} else if (fields.length === 6) {
|
|
1698
1974
|
if (fields[0].match(/^[NS]/)) {
|
|
1699
1975
|
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates(fields[0].substring(0, 13)));
|
|
@@ -1702,31 +1978,25 @@ var Label_4A = class extends DecoderPlugin {
|
|
|
1702
1978
|
time: DateTimeUtils.convertHHMMSSToTod(fields[1].substring(0, 6)),
|
|
1703
1979
|
timeFormat: "tod"
|
|
1704
1980
|
};
|
|
1705
|
-
ResultFormatter.altitude(decodeResult, fields[1].substring(6, 9) * 100);
|
|
1981
|
+
ResultFormatter.altitude(decodeResult, Number(fields[1].substring(6, 9)) * 100);
|
|
1706
1982
|
let wp2 = {
|
|
1707
1983
|
name: fields[1].substring(9).trim(),
|
|
1708
1984
|
time: DateTimeUtils.convertHHMMSSToTod(fields[2]),
|
|
1709
1985
|
timeFormat: "tod"
|
|
1710
1986
|
};
|
|
1711
|
-
|
|
1712
|
-
decodeResult.formatted.items.push({
|
|
1713
|
-
type: "aircraft_route",
|
|
1714
|
-
code: "ROUTE",
|
|
1715
|
-
label: "Aircraft Route",
|
|
1716
|
-
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
1717
|
-
});
|
|
1987
|
+
ResultFormatter.route(decodeResult, { waypoints: [wp1, wp2] });
|
|
1718
1988
|
ResultFormatter.temperature(decodeResult, fields[3]);
|
|
1719
|
-
decodeResult
|
|
1989
|
+
ResultFormatter.unknownArr(decodeResult, fields.slice(4));
|
|
1720
1990
|
} else {
|
|
1721
1991
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[0]));
|
|
1722
1992
|
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[1]));
|
|
1723
|
-
decodeResult
|
|
1724
|
-
ResultFormatter.altitude(decodeResult, fields[3]);
|
|
1993
|
+
ResultFormatter.unknown(decodeResult, fields[2]);
|
|
1994
|
+
ResultFormatter.altitude(decodeResult, Number(fields[3]));
|
|
1725
1995
|
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinates((fields[4] + fields[5]).replace(/[ \.]/g, "")));
|
|
1726
1996
|
}
|
|
1727
1997
|
} else {
|
|
1728
1998
|
decodeResult.decoded = false;
|
|
1729
|
-
decodeResult
|
|
1999
|
+
ResultFormatter.unknown(decodeResult, text);
|
|
1730
2000
|
}
|
|
1731
2001
|
if (decodeResult.decoded) {
|
|
1732
2002
|
if (!decodeResult.remaining.text)
|
|
@@ -1763,11 +2033,11 @@ var Label_4A_01 = class extends DecoderPlugin {
|
|
|
1763
2033
|
ResultFormatter.departureAirport(decodeResult, rgx[5]);
|
|
1764
2034
|
ResultFormatter.arrivalAirport(decodeResult, rgx[6]);
|
|
1765
2035
|
ResultFormatter.altitude(decodeResult, Number(rgx[7].replace(/ /g, "")));
|
|
1766
|
-
decodeResult
|
|
2036
|
+
ResultFormatter.unknown(decodeResult, rgx[8]);
|
|
1767
2037
|
ResultFormatter.temperature(decodeResult, rgx[9].replace(/ /g, ""));
|
|
1768
2038
|
} else {
|
|
1769
2039
|
decodeResult.decoded = false;
|
|
1770
|
-
decodeResult
|
|
2040
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
1771
2041
|
}
|
|
1772
2042
|
if (decodeResult.decoded) {
|
|
1773
2043
|
if (!decodeResult.remaining.text)
|
|
@@ -1833,7 +2103,7 @@ var Label_4A_DOOR = class extends DecoderPlugin {
|
|
|
1833
2103
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[2] + "00"));
|
|
1834
2104
|
} else {
|
|
1835
2105
|
decodeResult.decoded = false;
|
|
1836
|
-
decodeResult.
|
|
2106
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
1837
2107
|
}
|
|
1838
2108
|
if (decodeResult.decoded) {
|
|
1839
2109
|
if (!decodeResult.remaining.text)
|
|
@@ -1863,10 +2133,10 @@ var Label_4A_Slash_01 = class extends DecoderPlugin {
|
|
|
1863
2133
|
decodeResult.formatted.description = "Latest New Format";
|
|
1864
2134
|
decodeResult.decoded = true;
|
|
1865
2135
|
if (message.text.length === 5 && message.text.substring(0, 4) === "/01-") {
|
|
1866
|
-
decodeResult
|
|
2136
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(4));
|
|
1867
2137
|
} else {
|
|
1868
2138
|
decodeResult.decoded = false;
|
|
1869
|
-
decodeResult
|
|
2139
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
1870
2140
|
}
|
|
1871
2141
|
if (decodeResult.decoded) {
|
|
1872
2142
|
if (!decodeResult.remaining.text)
|
|
@@ -1880,630 +2150,93 @@ var Label_4A_Slash_01 = class extends DecoderPlugin {
|
|
|
1880
2150
|
}
|
|
1881
2151
|
};
|
|
1882
2152
|
|
|
1883
|
-
// lib/
|
|
1884
|
-
var
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
let
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
2153
|
+
// lib/utils/flight_plan_utils.ts
|
|
2154
|
+
var FlightPlanUtils = class _FlightPlanUtils {
|
|
2155
|
+
/**
|
|
2156
|
+
* Processes flight plan data
|
|
2157
|
+
*
|
|
2158
|
+
* Expected format is [header, key1, val1, ... keyN, valN]
|
|
2159
|
+
*
|
|
2160
|
+
* @param decodeResult - results
|
|
2161
|
+
* @param data - original message split by ':'
|
|
2162
|
+
* @returns whether all fields were processed or not
|
|
2163
|
+
*/
|
|
2164
|
+
static processFlightPlan(decodeResult, data) {
|
|
2165
|
+
let allKnownFields = _FlightPlanUtils.parseHeader(decodeResult, data[0]);
|
|
2166
|
+
for (let i = 1; i < data.length; i += 2) {
|
|
2167
|
+
const key = data[i];
|
|
2168
|
+
const value = data[i + 1];
|
|
2169
|
+
switch (key) {
|
|
2170
|
+
case "A":
|
|
2171
|
+
addProcedure(decodeResult, value, "arrival");
|
|
2172
|
+
break;
|
|
2173
|
+
case "AA":
|
|
2174
|
+
addArrivalAirport(decodeResult, value);
|
|
2175
|
+
break;
|
|
2176
|
+
case "AP":
|
|
2177
|
+
addProcedure(decodeResult, value, "approach");
|
|
2178
|
+
break;
|
|
2179
|
+
case "CR":
|
|
2180
|
+
addCompanyRoute(decodeResult, value);
|
|
2181
|
+
break;
|
|
2182
|
+
case "D":
|
|
2183
|
+
addProcedure(decodeResult, value, "departure");
|
|
2184
|
+
break;
|
|
2185
|
+
case "DA":
|
|
2186
|
+
addDepartureAirport(decodeResult, value);
|
|
2187
|
+
break;
|
|
2188
|
+
case "F":
|
|
2189
|
+
addRoute(decodeResult, value);
|
|
2190
|
+
break;
|
|
2191
|
+
case "R":
|
|
2192
|
+
addRunway(decodeResult, value);
|
|
2193
|
+
break;
|
|
2194
|
+
// case 'WS': // something about routes, has altitude, so current parsing won't work
|
|
2195
|
+
// break;
|
|
2196
|
+
default:
|
|
2197
|
+
if (allKnownFields) {
|
|
2198
|
+
decodeResult.remaining.text = "";
|
|
2199
|
+
allKnownFields = false;
|
|
2200
|
+
}
|
|
2201
|
+
decodeResult.remaining.text += `:${key}:${value}`;
|
|
2202
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
1915
2203
|
}
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
2204
|
+
}
|
|
2205
|
+
return allKnownFields;
|
|
2206
|
+
}
|
|
2207
|
+
static parseHeader(decodeResult, header) {
|
|
2208
|
+
let allKnownFields = true;
|
|
2209
|
+
if (header.startsWith("RF")) {
|
|
2210
|
+
decodeResult.formatted.items.push({
|
|
2211
|
+
type: "status",
|
|
2212
|
+
code: "ROUTE_STATUS",
|
|
2213
|
+
label: "Route Status",
|
|
2214
|
+
value: "Route Filed"
|
|
2215
|
+
});
|
|
2216
|
+
decodeResult.raw.route_status = "RF";
|
|
2217
|
+
if (header.length > 2) {
|
|
2218
|
+
addRoute(decodeResult, header.substring(2));
|
|
1922
2219
|
}
|
|
1923
|
-
|
|
1924
|
-
decodeResult.
|
|
2220
|
+
} else if (header.startsWith("RP")) {
|
|
2221
|
+
decodeResult.raw.route_status = "RP";
|
|
2222
|
+
decodeResult.formatted.items.push({
|
|
2223
|
+
type: "status",
|
|
2224
|
+
code: "ROUTE_STATUS",
|
|
2225
|
+
label: "Route Status",
|
|
2226
|
+
value: "Route Planned"
|
|
2227
|
+
});
|
|
2228
|
+
decodeResult.raw.route_status = header;
|
|
2229
|
+
} else if (header.startsWith("RI")) {
|
|
2230
|
+
decodeResult.raw.route_status = "RI";
|
|
2231
|
+
decodeResult.formatted.items.push({
|
|
2232
|
+
type: "status",
|
|
2233
|
+
code: "ROUTE_STATUS",
|
|
2234
|
+
label: "Route Status",
|
|
2235
|
+
value: "Route Inactive"
|
|
2236
|
+
});
|
|
1925
2237
|
} else {
|
|
1926
|
-
decodeResult.
|
|
1927
|
-
|
|
1928
|
-
}
|
|
1929
|
-
if (decodeResult.decoded) {
|
|
1930
|
-
if (!decodeResult.remaining.text)
|
|
1931
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
1932
|
-
else
|
|
1933
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
1934
|
-
} else {
|
|
1935
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
1936
|
-
}
|
|
1937
|
-
return decodeResult;
|
|
1938
|
-
}
|
|
1939
|
-
};
|
|
1940
|
-
|
|
1941
|
-
// lib/plugins/Label_80.ts
|
|
1942
|
-
var Label_80 = class extends DecoderPlugin {
|
|
1943
|
-
name = "label-80";
|
|
1944
|
-
descriptions = {
|
|
1945
|
-
ALT: "Altitude",
|
|
1946
|
-
DWND: "Wind Direction",
|
|
1947
|
-
ETA: "Estimated Time of Arrival",
|
|
1948
|
-
FOB: "Fuel on Board",
|
|
1949
|
-
FL: "Flight Level",
|
|
1950
|
-
HDG: "Heading",
|
|
1951
|
-
MCH: "Aircraft Speed",
|
|
1952
|
-
NWYP: "Next Waypoint",
|
|
1953
|
-
POS: "Aircraft Position",
|
|
1954
|
-
SAT: "Static Air Temperature",
|
|
1955
|
-
SWND: "Wind Speed",
|
|
1956
|
-
TAS: "True Airspeed",
|
|
1957
|
-
WYP: "Waypoint"
|
|
1958
|
-
};
|
|
1959
|
-
qualifiers() {
|
|
1960
|
-
return {
|
|
1961
|
-
labels: ["80"],
|
|
1962
|
-
preambles: ["3N01 POSRPT"]
|
|
1963
|
-
};
|
|
1964
|
-
}
|
|
1965
|
-
decode(message, options = {}) {
|
|
1966
|
-
const decodeResult = this.defaultResult();
|
|
1967
|
-
decodeResult.decoder.name = this.name;
|
|
1968
|
-
decodeResult.formatted.description = "Airline Defined Position Report";
|
|
1969
|
-
const parts = message.text.split("\n");
|
|
1970
|
-
let posRptRegex = /^3N01 POSRPT \d\d\d\d\/\d\d (?<orig>\w+)\/(?<dest>\w+) \.(?<tail>[\w-]+)(\/(?<agate>.+) (?<sta>\w+:\w+))*/;
|
|
1971
|
-
let results = parts[0].match(posRptRegex);
|
|
1972
|
-
if (!results?.groups) {
|
|
1973
|
-
decodeResult.decoded = false;
|
|
1974
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
1975
|
-
return decodeResult;
|
|
1976
|
-
}
|
|
1977
|
-
if (results && results.length > 0) {
|
|
1978
|
-
ResultFormatter.departureAirport(decodeResult, results.groups.orig);
|
|
1979
|
-
ResultFormatter.arrivalAirport(decodeResult, results.groups.dest);
|
|
1980
|
-
ResultFormatter.tail(decodeResult, results.groups.tail);
|
|
1981
|
-
if (results.groups.agate) {
|
|
1982
|
-
decodeResult.raw.arrival_gate = results.groups.agate;
|
|
1983
|
-
decodeResult.formatted.items.push({
|
|
1984
|
-
type: "arrival_gate",
|
|
1985
|
-
code: "ARG",
|
|
1986
|
-
label: "Arrival Gate",
|
|
1987
|
-
value: `${results.groups.agate}`
|
|
1988
|
-
});
|
|
1989
|
-
decodeResult.raw.scheduled_time_of_arrival = results.groups.sta;
|
|
1990
|
-
decodeResult.formatted.items.push({
|
|
1991
|
-
type: "scheduled_time_of_arrival",
|
|
1992
|
-
code: "STA",
|
|
1993
|
-
label: "Scheduled Time of Arrival",
|
|
1994
|
-
value: `${results.groups.sta}`
|
|
1995
|
-
});
|
|
1996
|
-
}
|
|
1997
|
-
posRptRegex = /\/(?<field>\w+)\s(?<value>[\w\+\-:\.]+)\s*/gi;
|
|
1998
|
-
const remainingParts = parts.slice(1);
|
|
1999
|
-
for (const part of remainingParts) {
|
|
2000
|
-
const matches = part.matchAll(posRptRegex);
|
|
2001
|
-
for (const match of matches) {
|
|
2002
|
-
switch (match.groups?.field) {
|
|
2003
|
-
case "ALT": {
|
|
2004
|
-
ResultFormatter.altitude(decodeResult, Number(match.groups.value));
|
|
2005
|
-
break;
|
|
2006
|
-
}
|
|
2007
|
-
case "DWND": {
|
|
2008
|
-
decodeResult.raw.wind_direction = Number(match.groups.value);
|
|
2009
|
-
decodeResult.formatted.items.push({
|
|
2010
|
-
type: "wind_direction",
|
|
2011
|
-
code: "DWND",
|
|
2012
|
-
label: this.descriptions[match.groups.field],
|
|
2013
|
-
value: decodeResult.raw.wind_direction
|
|
2014
|
-
});
|
|
2015
|
-
break;
|
|
2016
|
-
}
|
|
2017
|
-
case "FL": {
|
|
2018
|
-
const flight_level = Number(match.groups.value);
|
|
2019
|
-
ResultFormatter.altitude(decodeResult, flight_level * 100);
|
|
2020
|
-
break;
|
|
2021
|
-
}
|
|
2022
|
-
case "FOB": {
|
|
2023
|
-
decodeResult.raw.fuel_on_board = match.groups.value;
|
|
2024
|
-
decodeResult.formatted.items.push({
|
|
2025
|
-
type: "fuel_on_board",
|
|
2026
|
-
code: "FOB",
|
|
2027
|
-
label: this.descriptions[match.groups.field],
|
|
2028
|
-
value: decodeResult.raw.fuel_on_board
|
|
2029
|
-
});
|
|
2030
|
-
break;
|
|
2031
|
-
}
|
|
2032
|
-
case "HDG": {
|
|
2033
|
-
decodeResult.raw.heading = Number(match.groups.value);
|
|
2034
|
-
decodeResult.formatted.items.push({
|
|
2035
|
-
type: "heading",
|
|
2036
|
-
code: "HDG",
|
|
2037
|
-
label: this.descriptions[match.groups.field],
|
|
2038
|
-
value: decodeResult.raw.heading
|
|
2039
|
-
});
|
|
2040
|
-
break;
|
|
2041
|
-
}
|
|
2042
|
-
case "MCH": {
|
|
2043
|
-
decodeResult.raw.mach = Number(match.groups.value) / 1e3;
|
|
2044
|
-
decodeResult.formatted.items.push({
|
|
2045
|
-
type: "mach",
|
|
2046
|
-
code: "MCH",
|
|
2047
|
-
label: this.descriptions[match.groups.field],
|
|
2048
|
-
value: `${decodeResult.raw.mach} Mach`
|
|
2049
|
-
});
|
|
2050
|
-
break;
|
|
2051
|
-
}
|
|
2052
|
-
case "NWYP": {
|
|
2053
|
-
decodeResult.raw.next_waypoint = match.groups.value;
|
|
2054
|
-
decodeResult.formatted.items.push({
|
|
2055
|
-
type: "next_waypoint",
|
|
2056
|
-
code: "NWYP",
|
|
2057
|
-
label: this.descriptions[match.groups.field],
|
|
2058
|
-
value: decodeResult.raw.next_waypoint
|
|
2059
|
-
});
|
|
2060
|
-
break;
|
|
2061
|
-
}
|
|
2062
|
-
case "POS": {
|
|
2063
|
-
const posRegex = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
|
|
2064
|
-
const posResult = match.groups.value.match(posRegex);
|
|
2065
|
-
const lat = Number(posResult?.groups?.lat) * (posResult?.groups?.lngd === "S" ? -1 : 1);
|
|
2066
|
-
const lon = Number(posResult?.groups?.lng) * (posResult?.groups?.lngd === "W" ? -1 : 1);
|
|
2067
|
-
const position = {
|
|
2068
|
-
latitude: Number.isInteger(lat) ? lat / 1e3 : lat / 100,
|
|
2069
|
-
longitude: Number.isInteger(lon) ? lon / 1e3 : lon / 100
|
|
2070
|
-
};
|
|
2071
|
-
ResultFormatter.position(decodeResult, position);
|
|
2072
|
-
break;
|
|
2073
|
-
}
|
|
2074
|
-
case "SWND": {
|
|
2075
|
-
decodeResult.raw.wind_speed = Number(match.groups.value);
|
|
2076
|
-
decodeResult.formatted.items.push({
|
|
2077
|
-
type: "wind_speed",
|
|
2078
|
-
code: "SWND",
|
|
2079
|
-
label: this.descriptions[match.groups.field],
|
|
2080
|
-
value: decodeResult.raw.wind_speed
|
|
2081
|
-
});
|
|
2082
|
-
break;
|
|
2083
|
-
}
|
|
2084
|
-
default: {
|
|
2085
|
-
if (match.groups?.field != void 0) {
|
|
2086
|
-
const description = this.descriptions[match.groups.field] ? this.descriptions[match.groups.field] : "Unknown";
|
|
2087
|
-
decodeResult.formatted.items.push({
|
|
2088
|
-
type: match.groups.field,
|
|
2089
|
-
code: match.groups.field,
|
|
2090
|
-
label: description || `Unknown (${match.groups.field})`,
|
|
2091
|
-
value: `${match.groups.value}`
|
|
2092
|
-
});
|
|
2093
|
-
}
|
|
2094
|
-
}
|
|
2095
|
-
}
|
|
2096
|
-
}
|
|
2097
|
-
}
|
|
2098
|
-
decodeResult.decoded = true;
|
|
2099
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2100
|
-
}
|
|
2101
|
-
return decodeResult;
|
|
2102
|
-
}
|
|
2103
|
-
};
|
|
2104
|
-
|
|
2105
|
-
// lib/plugins/Label_83.ts
|
|
2106
|
-
var Label_83 = class extends DecoderPlugin {
|
|
2107
|
-
name = "label-83";
|
|
2108
|
-
qualifiers() {
|
|
2109
|
-
return {
|
|
2110
|
-
labels: ["83"]
|
|
2111
|
-
};
|
|
2112
|
-
}
|
|
2113
|
-
decode(message, options = {}) {
|
|
2114
|
-
const decodeResult = this.defaultResult();
|
|
2115
|
-
decodeResult.decoder.name = this.name;
|
|
2116
|
-
decodeResult.message = message;
|
|
2117
|
-
decodeResult.formatted.description = "Airline Defined";
|
|
2118
|
-
let text2 = message.text;
|
|
2119
|
-
if (text2.match(/^M\d{2}A\w{6}/)) {
|
|
2120
|
-
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
2121
|
-
text2 = text2.substring(10);
|
|
2122
|
-
}
|
|
2123
|
-
decodeResult.decoded = true;
|
|
2124
|
-
if (text2.substring(0, 10) === "4DH3 ETAT2") {
|
|
2125
|
-
const fields = text2.split(/\s+/);
|
|
2126
|
-
if (fields[2].length > 5) {
|
|
2127
|
-
decodeResult.raw.day_of_month = fields[2].substring(5);
|
|
2128
|
-
}
|
|
2129
|
-
decodeResult.remaining.text = fields[2].substring(0, 4);
|
|
2130
|
-
const subfields = fields[3].split("/");
|
|
2131
|
-
ResultFormatter.departureAirport(decodeResult, subfields[0]);
|
|
2132
|
-
ResultFormatter.arrivalAirport(decodeResult, subfields[1]);
|
|
2133
|
-
ResultFormatter.tail(decodeResult, fields[4].replace(/\./g, ""));
|
|
2134
|
-
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[6] + "00"));
|
|
2135
|
-
} else if (text2.substring(0, 5) === "001PR") {
|
|
2136
|
-
decodeResult.raw.day_of_month = text2.substring(5, 7);
|
|
2137
|
-
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(text2.substring(13, 28).replace(/\./g, ""));
|
|
2138
|
-
if (position) {
|
|
2139
|
-
ResultFormatter.position(decodeResult, position);
|
|
2140
|
-
}
|
|
2141
|
-
ResultFormatter.altitude(decodeResult, Number(text2.substring(28, 33)));
|
|
2142
|
-
decodeResult.remaining.text = text2.substring(33);
|
|
2143
|
-
} else {
|
|
2144
|
-
const fields = text2.replace(/\s/g, "").split(",");
|
|
2145
|
-
if (fields.length === 9) {
|
|
2146
|
-
ResultFormatter.departureAirport(decodeResult, fields[0]);
|
|
2147
|
-
ResultFormatter.arrivalAirport(decodeResult, fields[1]);
|
|
2148
|
-
decodeResult.raw.day_of_month = fields[2].substring(0, 2);
|
|
2149
|
-
decodeResult.raw.time = fields[2].substring(2);
|
|
2150
|
-
ResultFormatter.position(
|
|
2151
|
-
decodeResult,
|
|
2152
|
-
{
|
|
2153
|
-
latitude: Number(fields[3].replace(/\s/g, "")),
|
|
2154
|
-
longitude: Number(fields[4].replace(/\s/g, ""))
|
|
2155
|
-
}
|
|
2156
|
-
);
|
|
2157
|
-
ResultFormatter.altitude(decodeResult, Number(fields[5]));
|
|
2158
|
-
ResultFormatter.groundspeed(decodeResult, fields[6]);
|
|
2159
|
-
ResultFormatter.heading(decodeResult, fields[7]);
|
|
2160
|
-
decodeResult.remaining.text = fields[8];
|
|
2161
|
-
} else {
|
|
2162
|
-
decodeResult.decoded = false;
|
|
2163
|
-
decodeResult.remaining.text = message.text;
|
|
2164
|
-
}
|
|
2165
|
-
}
|
|
2166
|
-
if (decodeResult.decoded) {
|
|
2167
|
-
if (!decodeResult.remaining.text)
|
|
2168
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
2169
|
-
else
|
|
2170
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2171
|
-
} else {
|
|
2172
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2173
|
-
}
|
|
2174
|
-
return decodeResult;
|
|
2175
|
-
}
|
|
2176
|
-
};
|
|
2177
|
-
|
|
2178
|
-
// lib/plugins/Label_8E.ts
|
|
2179
|
-
var Label_8E = class extends DecoderPlugin {
|
|
2180
|
-
name = "label-8e";
|
|
2181
|
-
qualifiers() {
|
|
2182
|
-
return {
|
|
2183
|
-
labels: ["8E"]
|
|
2184
|
-
};
|
|
2185
|
-
}
|
|
2186
|
-
decode(message, options = {}) {
|
|
2187
|
-
const decodeResult = this.defaultResult();
|
|
2188
|
-
decodeResult.decoder.name = this.name;
|
|
2189
|
-
decodeResult.formatted.description = "ETA Report";
|
|
2190
|
-
decodeResult.message = message;
|
|
2191
|
-
const regex = /^(?<arrival_icao>\w{4}),(?<arrival_eta>\d{4})$/;
|
|
2192
|
-
const results = message.text.match(regex);
|
|
2193
|
-
if (results) {
|
|
2194
|
-
if (options.debug) {
|
|
2195
|
-
console.log(`Label 8E ETA: groups`);
|
|
2196
|
-
console.log(results.groups);
|
|
2197
|
-
}
|
|
2198
|
-
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(results.groups.arrival_eta + "00"));
|
|
2199
|
-
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
2200
|
-
}
|
|
2201
|
-
decodeResult.decoded = true;
|
|
2202
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
2203
|
-
return decodeResult;
|
|
2204
|
-
}
|
|
2205
|
-
};
|
|
2206
|
-
|
|
2207
|
-
// lib/plugins/Label_B6.ts
|
|
2208
|
-
var Label_B6_Forwardslash = class extends DecoderPlugin {
|
|
2209
|
-
name = "label-b6-forwardslash";
|
|
2210
|
-
qualifiers() {
|
|
2211
|
-
return {
|
|
2212
|
-
labels: ["B6"],
|
|
2213
|
-
preambles: ["/"]
|
|
2214
|
-
};
|
|
2215
|
-
}
|
|
2216
|
-
decode(message, options = {}) {
|
|
2217
|
-
const decodeResult = this.defaultResult();
|
|
2218
|
-
decodeResult.decoder.name = this.name;
|
|
2219
|
-
decodeResult.formatted.description = "CPDLC Message";
|
|
2220
|
-
decodeResult.message = message;
|
|
2221
|
-
if (options.debug) {
|
|
2222
|
-
console.log("CPDLC: " + message);
|
|
2223
|
-
}
|
|
2224
|
-
return decodeResult;
|
|
2225
|
-
}
|
|
2226
|
-
};
|
|
2227
|
-
|
|
2228
|
-
// lib/plugins/Label_ColonComma.ts
|
|
2229
|
-
var Label_ColonComma = class extends DecoderPlugin {
|
|
2230
|
-
name = "label-colon-comma";
|
|
2231
|
-
qualifiers() {
|
|
2232
|
-
return {
|
|
2233
|
-
labels: [":;"]
|
|
2234
|
-
};
|
|
2235
|
-
}
|
|
2236
|
-
decode(message, options = {}) {
|
|
2237
|
-
const decodeResult = this.defaultResult();
|
|
2238
|
-
decodeResult.decoder.name = this.name;
|
|
2239
|
-
decodeResult.raw.frequency = Number(message.text) / 1e3;
|
|
2240
|
-
decodeResult.formatted.description = "Aircraft Transceiver Frequency Change";
|
|
2241
|
-
decodeResult.formatted.items.push({
|
|
2242
|
-
type: "frequency",
|
|
2243
|
-
label: "Frequency",
|
|
2244
|
-
value: `${decodeResult.raw.frequency} MHz`
|
|
2245
|
-
});
|
|
2246
|
-
decodeResult.decoded = true;
|
|
2247
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
2248
|
-
return decodeResult;
|
|
2249
|
-
}
|
|
2250
|
-
};
|
|
2251
|
-
|
|
2252
|
-
// lib/plugins/Label_H1_FLR.ts
|
|
2253
|
-
var Label_H1_FLR = class extends DecoderPlugin {
|
|
2254
|
-
name = "label-h1-flr";
|
|
2255
|
-
qualifiers() {
|
|
2256
|
-
return {
|
|
2257
|
-
labels: ["H1"],
|
|
2258
|
-
preambles: ["FLR", "#CFBFLR"]
|
|
2259
|
-
};
|
|
2260
|
-
}
|
|
2261
|
-
decode(message, options = {}) {
|
|
2262
|
-
let decodeResult = this.defaultResult();
|
|
2263
|
-
decodeResult.decoder.name = this.name;
|
|
2264
|
-
decodeResult.formatted.description = "Fault Log Report";
|
|
2265
|
-
decodeResult.message = message;
|
|
2266
|
-
const parts = message.text.split("/FR");
|
|
2267
|
-
if (parts.length > 1) {
|
|
2268
|
-
decodeResult.remaining.text = "";
|
|
2269
|
-
const fields = parts[0].split("/");
|
|
2270
|
-
for (let i = 1; i < fields.length; i++) {
|
|
2271
|
-
const field = fields[i];
|
|
2272
|
-
if (field.startsWith("PN")) {
|
|
2273
|
-
processUnknown(decodeResult, "/" + field);
|
|
2274
|
-
} else {
|
|
2275
|
-
processUnknown(decodeResult, "/" + field);
|
|
2276
|
-
}
|
|
2277
|
-
}
|
|
2278
|
-
const data = parts[1].substring(0, 20);
|
|
2279
|
-
const msg = parts[1].substring(20);
|
|
2280
|
-
const datetime = data.substring(0, 12);
|
|
2281
|
-
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
2282
|
-
processUnknown(decodeResult, data.substring(12));
|
|
2283
|
-
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
2284
|
-
decodeResult.raw.fault_message = msg;
|
|
2285
|
-
decodeResult.formatted.items.push({
|
|
2286
|
-
type: "fault",
|
|
2287
|
-
code: "FR",
|
|
2288
|
-
label: "Fault Report",
|
|
2289
|
-
value: decodeResult.raw.fault_message
|
|
2290
|
-
});
|
|
2291
|
-
decodeResult.decoded = true;
|
|
2292
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2293
|
-
} else {
|
|
2294
|
-
if (options.debug) {
|
|
2295
|
-
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2296
|
-
}
|
|
2297
|
-
decodeResult.remaining.text = message.text;
|
|
2298
|
-
decodeResult.decoded = false;
|
|
2299
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2300
|
-
}
|
|
2301
|
-
return decodeResult;
|
|
2302
|
-
}
|
|
2303
|
-
};
|
|
2304
|
-
function processUnknown(decodeResult, value) {
|
|
2305
|
-
decodeResult.remaining.text += value;
|
|
2306
|
-
}
|
|
2307
|
-
|
|
2308
|
-
// lib/plugins/Label_H1_OHMA.ts
|
|
2309
|
-
var zlib = __toESM(require("minizlib"));
|
|
2310
|
-
var Label_H1_OHMA = class extends DecoderPlugin {
|
|
2311
|
-
name = "label-h1-ohma";
|
|
2312
|
-
qualifiers() {
|
|
2313
|
-
return {
|
|
2314
|
-
labels: ["H1"],
|
|
2315
|
-
preambles: ["OHMA", "/RTNBOCR.OHMA", "#T1B/RTNBOCR.OHMA"]
|
|
2316
|
-
};
|
|
2317
|
-
}
|
|
2318
|
-
decode(message, options = {}) {
|
|
2319
|
-
let decodeResult = this.defaultResult();
|
|
2320
|
-
decodeResult.decoder.name = this.name;
|
|
2321
|
-
decodeResult.formatted.description = "OHMA Message";
|
|
2322
|
-
decodeResult.message = message;
|
|
2323
|
-
decodeResult.remaining.text = "";
|
|
2324
|
-
const data = message.text.split("OHMA")[1];
|
|
2325
|
-
try {
|
|
2326
|
-
const compressedBuffer = Buffer.from(data, "base64");
|
|
2327
|
-
const decompress = new zlib.Inflate({ windowBits: 15 });
|
|
2328
|
-
decompress.write(compressedBuffer);
|
|
2329
|
-
decompress.flush(zlib.constants.Z_SYNC_FLUSH);
|
|
2330
|
-
const result = decompress.read();
|
|
2331
|
-
const jsonText = result.toString();
|
|
2332
|
-
let formattedMsg;
|
|
2333
|
-
let jsonMessage;
|
|
2334
|
-
try {
|
|
2335
|
-
jsonMessage = JSON.parse(jsonText).message;
|
|
2336
|
-
} catch {
|
|
2337
|
-
jsonMessage = jsonText;
|
|
2338
|
-
}
|
|
2339
|
-
try {
|
|
2340
|
-
const ohmaMsg = JSON.parse(jsonMessage);
|
|
2341
|
-
formattedMsg = JSON.stringify(ohmaMsg, null, 2);
|
|
2342
|
-
} catch {
|
|
2343
|
-
formattedMsg = jsonMessage;
|
|
2344
|
-
}
|
|
2345
|
-
decodeResult.decoded = true;
|
|
2346
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
2347
|
-
decodeResult.raw.ohma = jsonText;
|
|
2348
|
-
decodeResult.formatted.items.push({
|
|
2349
|
-
type: "ohma",
|
|
2350
|
-
code: "OHMA",
|
|
2351
|
-
label: "OHMA Downlink",
|
|
2352
|
-
value: formattedMsg
|
|
2353
|
-
});
|
|
2354
|
-
} catch (e) {
|
|
2355
|
-
if (options.debug) {
|
|
2356
|
-
console.log(`Decoder: Unknown H1 OHMA message: ${message.text}`, e);
|
|
2357
|
-
}
|
|
2358
|
-
decodeResult.remaining.text += message.text;
|
|
2359
|
-
decodeResult.decoded = false;
|
|
2360
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2361
|
-
}
|
|
2362
|
-
return decodeResult;
|
|
2363
|
-
}
|
|
2364
|
-
};
|
|
2365
|
-
|
|
2366
|
-
// lib/plugins/Label_H1_WRN.ts
|
|
2367
|
-
var Label_H1_WRN = class extends DecoderPlugin {
|
|
2368
|
-
name = "label-h1-wrn";
|
|
2369
|
-
qualifiers() {
|
|
2370
|
-
return {
|
|
2371
|
-
labels: ["H1"],
|
|
2372
|
-
preambles: ["WRN", "#CFBWRN"]
|
|
2373
|
-
};
|
|
2374
|
-
}
|
|
2375
|
-
decode(message, options = {}) {
|
|
2376
|
-
let decodeResult = this.defaultResult();
|
|
2377
|
-
decodeResult.decoder.name = this.name;
|
|
2378
|
-
decodeResult.formatted.description = "Warning Message";
|
|
2379
|
-
decodeResult.message = message;
|
|
2380
|
-
const parts = message.text.split("/WN");
|
|
2381
|
-
if (parts.length > 1) {
|
|
2382
|
-
decodeResult.remaining.text = "";
|
|
2383
|
-
const fields = parts[0].split("/");
|
|
2384
|
-
for (let i = 1; i < fields.length; i++) {
|
|
2385
|
-
const field = fields[i];
|
|
2386
|
-
if (field.startsWith("PN")) {
|
|
2387
|
-
processUnknown2(decodeResult, "/" + field);
|
|
2388
|
-
} else {
|
|
2389
|
-
processUnknown2(decodeResult, "/" + field);
|
|
2390
|
-
}
|
|
2391
|
-
}
|
|
2392
|
-
const data = parts[1].substring(0, 20);
|
|
2393
|
-
const msg = parts[1].substring(20);
|
|
2394
|
-
const datetime = data.substring(0, 12);
|
|
2395
|
-
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
2396
|
-
processUnknown2(decodeResult, data.substring(12));
|
|
2397
|
-
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
2398
|
-
decodeResult.raw.warning_message = msg;
|
|
2399
|
-
decodeResult.formatted.items.push({
|
|
2400
|
-
type: "warning",
|
|
2401
|
-
code: "WRN",
|
|
2402
|
-
label: "Warning Message",
|
|
2403
|
-
value: decodeResult.raw.warning_message
|
|
2404
|
-
});
|
|
2405
|
-
decodeResult.decoded = true;
|
|
2406
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2407
|
-
} else {
|
|
2408
|
-
if (options.debug) {
|
|
2409
|
-
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2410
|
-
}
|
|
2411
|
-
decodeResult.remaining.text = message.text;
|
|
2412
|
-
decodeResult.decoded = false;
|
|
2413
|
-
decodeResult.decoder.decodeLevel = "none";
|
|
2414
|
-
}
|
|
2415
|
-
return decodeResult;
|
|
2416
|
-
}
|
|
2417
|
-
};
|
|
2418
|
-
function processUnknown2(decodeResult, value) {
|
|
2419
|
-
decodeResult.remaining.text += value;
|
|
2420
|
-
}
|
|
2421
|
-
|
|
2422
|
-
// lib/utils/flight_plan_utils.ts
|
|
2423
|
-
var FlightPlanUtils = class _FlightPlanUtils {
|
|
2424
|
-
/**
|
|
2425
|
-
* Processes flight plan data
|
|
2426
|
-
*
|
|
2427
|
-
* Expected format is [header, key1, val1, ... keyN, valN]
|
|
2428
|
-
*
|
|
2429
|
-
* @param decodeResult - results
|
|
2430
|
-
* @param data - original message split by ':'
|
|
2431
|
-
* @returns whether all fields were processed or not
|
|
2432
|
-
*/
|
|
2433
|
-
static processFlightPlan(decodeResult, data) {
|
|
2434
|
-
let allKnownFields = _FlightPlanUtils.parseHeader(decodeResult, data[0]);
|
|
2435
|
-
for (let i = 1; i < data.length; i += 2) {
|
|
2436
|
-
const key = data[i];
|
|
2437
|
-
const value = data[i + 1];
|
|
2438
|
-
switch (key) {
|
|
2439
|
-
case "A":
|
|
2440
|
-
addProcedure(decodeResult, value, "arrival");
|
|
2441
|
-
break;
|
|
2442
|
-
case "AA":
|
|
2443
|
-
addArrivalAirport(decodeResult, value);
|
|
2444
|
-
break;
|
|
2445
|
-
case "AP":
|
|
2446
|
-
addProcedure(decodeResult, value, "approach");
|
|
2447
|
-
break;
|
|
2448
|
-
case "CR":
|
|
2449
|
-
addCompanyRoute(decodeResult, value);
|
|
2450
|
-
break;
|
|
2451
|
-
case "D":
|
|
2452
|
-
addProcedure(decodeResult, value, "departure");
|
|
2453
|
-
break;
|
|
2454
|
-
case "DA":
|
|
2455
|
-
addDepartureAirport(decodeResult, value);
|
|
2456
|
-
break;
|
|
2457
|
-
case "F":
|
|
2458
|
-
addRoute(decodeResult, value);
|
|
2459
|
-
break;
|
|
2460
|
-
case "R":
|
|
2461
|
-
addRunway(decodeResult, value);
|
|
2462
|
-
break;
|
|
2463
|
-
default:
|
|
2464
|
-
if (allKnownFields) {
|
|
2465
|
-
decodeResult.remaining.text = "";
|
|
2466
|
-
allKnownFields = false;
|
|
2467
|
-
}
|
|
2468
|
-
decodeResult.remaining.text += `:${key}:${value}`;
|
|
2469
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
2470
|
-
}
|
|
2471
|
-
}
|
|
2472
|
-
return allKnownFields;
|
|
2473
|
-
}
|
|
2474
|
-
static parseHeader(decodeResult, header) {
|
|
2475
|
-
let allKnownFields = true;
|
|
2476
|
-
if (header.startsWith("RF")) {
|
|
2477
|
-
decodeResult.formatted.items.push({
|
|
2478
|
-
type: "status",
|
|
2479
|
-
code: "ROUTE_STATUS",
|
|
2480
|
-
label: "Route Status",
|
|
2481
|
-
value: "Route Filed"
|
|
2482
|
-
});
|
|
2483
|
-
decodeResult.raw.route_status = "RF";
|
|
2484
|
-
if (header.length > 2) {
|
|
2485
|
-
addRoute(decodeResult, header.substring(2));
|
|
2486
|
-
}
|
|
2487
|
-
} else if (header.startsWith("RP")) {
|
|
2488
|
-
decodeResult.raw.route_status = "RP";
|
|
2489
|
-
decodeResult.formatted.items.push({
|
|
2490
|
-
type: "status",
|
|
2491
|
-
code: "ROUTE_STATUS",
|
|
2492
|
-
label: "Route Status",
|
|
2493
|
-
value: "Route Planned"
|
|
2494
|
-
});
|
|
2495
|
-
decodeResult.raw.route_status = header;
|
|
2496
|
-
} else if (header.startsWith("RI")) {
|
|
2497
|
-
decodeResult.raw.route_status = "RI";
|
|
2498
|
-
decodeResult.formatted.items.push({
|
|
2499
|
-
type: "status",
|
|
2500
|
-
code: "ROUTE_STATUS",
|
|
2501
|
-
label: "Route Status",
|
|
2502
|
-
value: "Route Inactive"
|
|
2503
|
-
});
|
|
2504
|
-
} else {
|
|
2505
|
-
decodeResult.remaining.text += header;
|
|
2506
|
-
allKnownFields = false;
|
|
2238
|
+
decodeResult.remaining.text += header;
|
|
2239
|
+
allKnownFields = false;
|
|
2507
2240
|
}
|
|
2508
2241
|
return allKnownFields;
|
|
2509
2242
|
}
|
|
@@ -2522,13 +2255,7 @@ function addRunway(decodeResult, value) {
|
|
|
2522
2255
|
}
|
|
2523
2256
|
function addRoute(decodeResult, value) {
|
|
2524
2257
|
const route = value.split(".");
|
|
2525
|
-
|
|
2526
|
-
decodeResult.formatted.items.push({
|
|
2527
|
-
type: "aircraft_route",
|
|
2528
|
-
code: "ROUTE",
|
|
2529
|
-
label: "Aircraft Route",
|
|
2530
|
-
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
2531
|
-
});
|
|
2258
|
+
ResultFormatter.route(decodeResult, { waypoints: route.map((leg) => RouteUtils.getWaypoint(leg)) });
|
|
2532
2259
|
}
|
|
2533
2260
|
function addProcedure(decodeResult, value, type) {
|
|
2534
2261
|
if (decodeResult.raw.procedures === void 0) {
|
|
@@ -2578,257 +2305,652 @@ function addCompanyRoute(decodeResult, value) {
|
|
|
2578
2305
|
});
|
|
2579
2306
|
}
|
|
2580
2307
|
|
|
2581
|
-
// lib/utils/h1_helper.ts
|
|
2582
|
-
var H1Helper = class {
|
|
2583
|
-
static decodeH1Message(decodeResult, message) {
|
|
2584
|
-
const checksum = message.slice(-4);
|
|
2585
|
-
const data = message.slice(0, message.length - 4);
|
|
2586
|
-
const fields = data.split("/");
|
|
2587
|
-
parseMessageType(decodeResult, fields[0]);
|
|
2588
|
-
for (let i = 1; i < fields.length; ++i) {
|
|
2589
|
-
if (fields[i].startsWith("FN")) {
|
|
2590
|
-
decodeResult.raw.flight_number = fields[i].substring(2);
|
|
2591
|
-
} else if (fields[i].startsWith("SN")) {
|
|
2592
|
-
decodeResult.raw.serial_number = fields[i].substring(2);
|
|
2593
|
-
} else if (fields[i].startsWith("DC")) {
|
|
2594
|
-
processDC(decodeResult, fields[i].substring(2).split(","));
|
|
2595
|
-
} else if (fields[i].startsWith("TS")) {
|
|
2596
|
-
const ts = fields[i].substring(2).split(",");
|
|
2597
|
-
let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
|
|
2598
|
-
if (Number.isNaN(time)) {
|
|
2599
|
-
const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
|
|
2600
|
-
time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
|
|
2601
|
-
}
|
|
2602
|
-
decodeResult.raw.message_date = ts[1];
|
|
2603
|
-
decodeResult.raw.message_timestamp = time;
|
|
2604
|
-
} else if (fields[i].startsWith("PS")) {
|
|
2605
|
-
const pos = processPS(decodeResult, fields[i].substring(2).split(","));
|
|
2606
|
-
} else if (fields[i].startsWith("DT")) {
|
|
2607
|
-
const data2 = fields[i].substring(2).split(",");
|
|
2608
|
-
processDT(decodeResult, data2);
|
|
2609
|
-
} else if (fields[i].startsWith("ID")) {
|
|
2610
|
-
processIdentification(decodeResult, fields[i].substring(2).split(","));
|
|
2611
|
-
} else if (fields[i].startsWith("LR")) {
|
|
2612
|
-
const data2 = fields[i].substring(2).split(",");
|
|
2613
|
-
processLR(decodeResult, data2);
|
|
2614
|
-
} else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
|
|
2615
|
-
FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
|
|
2616
|
-
} else if (fields[i].startsWith("PR")) {
|
|
2617
|
-
decodeResult
|
|
2618
|
-
} else if (fields[i].startsWith("AF")) {
|
|
2619
|
-
processAirField(decodeResult, fields[i].substring(2).split(","));
|
|
2620
|
-
} else if (fields[i].startsWith("TD")) {
|
|
2621
|
-
processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
|
|
2622
|
-
} else if (fields[i].startsWith("FX")) {
|
|
2623
|
-
decodeResult
|
|
2308
|
+
// lib/utils/h1_helper.ts
|
|
2309
|
+
var H1Helper = class {
|
|
2310
|
+
static decodeH1Message(decodeResult, message) {
|
|
2311
|
+
const checksum = message.slice(-4);
|
|
2312
|
+
const data = message.slice(0, message.length - 4);
|
|
2313
|
+
const fields = data.split("/");
|
|
2314
|
+
parseMessageType(decodeResult, fields[0]);
|
|
2315
|
+
for (let i = 1; i < fields.length; ++i) {
|
|
2316
|
+
if (fields[i].startsWith("FN")) {
|
|
2317
|
+
decodeResult.raw.flight_number = fields[i].substring(2);
|
|
2318
|
+
} else if (fields[i].startsWith("SN")) {
|
|
2319
|
+
decodeResult.raw.serial_number = fields[i].substring(2);
|
|
2320
|
+
} else if (fields[i].startsWith("DC")) {
|
|
2321
|
+
processDC(decodeResult, fields[i].substring(2).split(","));
|
|
2322
|
+
} else if (fields[i].startsWith("TS")) {
|
|
2323
|
+
const ts = fields[i].substring(2).split(",");
|
|
2324
|
+
let time = DateTimeUtils.convertDateTimeToEpoch(ts[0], ts[1]);
|
|
2325
|
+
if (Number.isNaN(time)) {
|
|
2326
|
+
const date = ts[1].substring(2, 4) + ts[1].substring(0, 2) + ts[1].substring(4, 6);
|
|
2327
|
+
time = DateTimeUtils.convertDateTimeToEpoch(ts[0], date);
|
|
2328
|
+
}
|
|
2329
|
+
decodeResult.raw.message_date = ts[1];
|
|
2330
|
+
decodeResult.raw.message_timestamp = time;
|
|
2331
|
+
} else if (fields[i].startsWith("PS")) {
|
|
2332
|
+
const pos = processPS(decodeResult, fields[i].substring(2).split(","));
|
|
2333
|
+
} else if (fields[i].startsWith("DT")) {
|
|
2334
|
+
const data2 = fields[i].substring(2).split(",");
|
|
2335
|
+
processDT(decodeResult, data2);
|
|
2336
|
+
} else if (fields[i].startsWith("ID")) {
|
|
2337
|
+
processIdentification(decodeResult, fields[i].substring(2).split(","));
|
|
2338
|
+
} else if (fields[i].startsWith("LR")) {
|
|
2339
|
+
const data2 = fields[i].substring(2).split(",");
|
|
2340
|
+
processLR(decodeResult, data2);
|
|
2341
|
+
} else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
|
|
2342
|
+
FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
|
|
2343
|
+
} else if (fields[i].startsWith("PR")) {
|
|
2344
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
2345
|
+
} else if (fields[i].startsWith("AF")) {
|
|
2346
|
+
processAirField(decodeResult, fields[i].substring(2).split(","));
|
|
2347
|
+
} else if (fields[i].startsWith("TD")) {
|
|
2348
|
+
processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
|
|
2349
|
+
} else if (fields[i].startsWith("FX")) {
|
|
2350
|
+
ResultFormatter.freetext(decodeResult, fields[i].substring(2));
|
|
2351
|
+
} else if (fields[i].startsWith("ET")) {
|
|
2352
|
+
if (fields[i].length === 7) {
|
|
2353
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(3) + "00"));
|
|
2354
|
+
} else if (fields[i].length === 8) {
|
|
2355
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(4) + "00"));
|
|
2356
|
+
} else {
|
|
2357
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
2358
|
+
}
|
|
2359
|
+
} else {
|
|
2360
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
if (decodeResult.formatted.items.length > 0) {
|
|
2364
|
+
ResultFormatter.checksum(decodeResult, checksum);
|
|
2365
|
+
}
|
|
2366
|
+
return true;
|
|
2367
|
+
}
|
|
2368
|
+
};
|
|
2369
|
+
function processAirField(decodeResult, data) {
|
|
2370
|
+
if (data.length === 2) {
|
|
2371
|
+
ResultFormatter.departureAirport(decodeResult, data[0]);
|
|
2372
|
+
ResultFormatter.arrivalAirport(decodeResult, data[1]);
|
|
2373
|
+
} else {
|
|
2374
|
+
ResultFormatter.unknown(decodeResult, data.join(","), "AF/");
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
function processTimeOfDeparture(decodeResult, data) {
|
|
2378
|
+
if (data.length === 2) {
|
|
2379
|
+
decodeResult.raw.plannedDepartureTime = data[0];
|
|
2380
|
+
decodeResult.formatted.items.push({
|
|
2381
|
+
type: "ptd",
|
|
2382
|
+
code: "ptd",
|
|
2383
|
+
label: "Planned Departure Time",
|
|
2384
|
+
value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
|
|
2385
|
+
});
|
|
2386
|
+
decodeResult.raw.plannedDepartureTime = data[1];
|
|
2387
|
+
decodeResult.formatted.items.push({
|
|
2388
|
+
type: "etd",
|
|
2389
|
+
code: "etd",
|
|
2390
|
+
label: "Estimated Departure Time",
|
|
2391
|
+
value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
|
|
2392
|
+
});
|
|
2393
|
+
} else {
|
|
2394
|
+
ResultFormatter.unknown(decodeResult, data.join(","), "/TD");
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
function processIdentification(decodeResult, data) {
|
|
2398
|
+
ResultFormatter.tail(decodeResult, data[0]);
|
|
2399
|
+
if (data.length > 1) {
|
|
2400
|
+
decodeResult.raw.flight_number = data[1];
|
|
2401
|
+
}
|
|
2402
|
+
if (data.length > 2) {
|
|
2403
|
+
decodeResult.raw.mission_number = data[2];
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
function processDT(decodeResult, data) {
|
|
2407
|
+
if (!decodeResult.raw.arrival_icao) {
|
|
2408
|
+
ResultFormatter.arrivalAirport(decodeResult, data[0]);
|
|
2409
|
+
} else if (decodeResult.raw.arrival_icao != data[0]) {
|
|
2410
|
+
ResultFormatter.unknownArr(decodeResult, data);
|
|
2411
|
+
}
|
|
2412
|
+
if (data.length > 1) {
|
|
2413
|
+
ResultFormatter.arrivalRunway(decodeResult, data[1]);
|
|
2414
|
+
}
|
|
2415
|
+
if (data.length > 2) {
|
|
2416
|
+
ResultFormatter.currentFuel(decodeResult, Number(data[2]));
|
|
2417
|
+
}
|
|
2418
|
+
if (data.length > 3) {
|
|
2419
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[3]));
|
|
2420
|
+
}
|
|
2421
|
+
if (data.length > 4) {
|
|
2422
|
+
ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
|
|
2423
|
+
}
|
|
2424
|
+
if (data.length > 5) {
|
|
2425
|
+
ResultFormatter.unknownArr(decodeResult, data);
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
function processLR(decodeResult, data) {
|
|
2429
|
+
if (data.length === 19) {
|
|
2430
|
+
ResultFormatter.unknown(decodeResult, data[1]);
|
|
2431
|
+
ResultFormatter.flightNumber(decodeResult, data[2]);
|
|
2432
|
+
ResultFormatter.departureAirport(decodeResult, data[3]);
|
|
2433
|
+
ResultFormatter.arrivalAirport(decodeResult, data[4]);
|
|
2434
|
+
ResultFormatter.arrivalRunway(decodeResult, data[5]);
|
|
2435
|
+
ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
|
|
2436
|
+
} else {
|
|
2437
|
+
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
function parseMessageType(decodeResult, messageType) {
|
|
2441
|
+
const parts = messageType.split("#");
|
|
2442
|
+
if (parts.length == 1) {
|
|
2443
|
+
const type = parts[0].substring(0, 3);
|
|
2444
|
+
if (type === "POS" && parts[0].length !== 3) {
|
|
2445
|
+
processPosition2(decodeResult, parts[0].substring(3).split(","));
|
|
2446
|
+
}
|
|
2447
|
+
return processMessageType(decodeResult, type);
|
|
2448
|
+
} else if (parts.length == 2) {
|
|
2449
|
+
if (parts[0].length > 0) {
|
|
2450
|
+
ResultFormatter.unknown(decodeResult, parts[0].substring(0, 3));
|
|
2451
|
+
decodeResult.raw.flight_number = parts[0].substring(3);
|
|
2452
|
+
ResultFormatter.unknown(decodeResult, parts[1].length == 5 ? parts[1].substring(0, 2) : parts[1].substring(0, 3), "#");
|
|
2453
|
+
}
|
|
2454
|
+
const type = parts[1].length == 5 ? parts[1].substring(2, 5) : parts[1].substring(3, 6);
|
|
2455
|
+
if (parts[1].substring(3, 6) === "POS" && parts[1].length > 6) {
|
|
2456
|
+
processPosition2(decodeResult, parts[1].substring(6).split(","));
|
|
2457
|
+
}
|
|
2458
|
+
processMessageType(decodeResult, type);
|
|
2459
|
+
} else {
|
|
2460
|
+
ResultFormatter.unknown(decodeResult, messageType);
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
function processMessageType(decodeResult, type) {
|
|
2464
|
+
if (type === "FPN") {
|
|
2465
|
+
decodeResult.formatted.description = "Flight Plan";
|
|
2466
|
+
} else if (type === "FTX") {
|
|
2467
|
+
decodeResult.formatted.description = "Free Text";
|
|
2468
|
+
} else if (type === "INI") {
|
|
2469
|
+
decodeResult.formatted.description = "Flight Plan Initial Report";
|
|
2470
|
+
} else if (type === "POS") {
|
|
2471
|
+
decodeResult.formatted.description = "Position Report";
|
|
2472
|
+
} else if (type === "PRG") {
|
|
2473
|
+
decodeResult.formatted.description = "Progress Report";
|
|
2474
|
+
} else {
|
|
2475
|
+
decodeResult.formatted.description = "Unknown H1 Message";
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
function processDC(decodeResult, data) {
|
|
2479
|
+
decodeResult.raw.message_date = data[0];
|
|
2480
|
+
if (data.length === 1) {
|
|
2481
|
+
} else if (data.length === 2) {
|
|
2482
|
+
const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
|
|
2483
|
+
const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
|
|
2484
|
+
decodeResult.raw.message_timestamp = time;
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
function processPS(decodeResult, data) {
|
|
2488
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
2489
|
+
if (position) {
|
|
2490
|
+
decodeResult.raw.position = position;
|
|
2491
|
+
decodeResult.formatted.items.push({
|
|
2492
|
+
type: "aircraft_position",
|
|
2493
|
+
code: "POS",
|
|
2494
|
+
label: "Aircraft Position",
|
|
2495
|
+
value: CoordinateUtils.coordinateString(position)
|
|
2496
|
+
});
|
|
2497
|
+
}
|
|
2498
|
+
if (data.length === 9) {
|
|
2499
|
+
processRoute(decodeResult, data[3], data[1], data[5], data[4], void 0);
|
|
2500
|
+
ResultFormatter.altitude(decodeResult, Number(data[2]) * 100);
|
|
2501
|
+
ResultFormatter.temperature(decodeResult, data[6]);
|
|
2502
|
+
ResultFormatter.unknown(decodeResult, data[7]);
|
|
2503
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
2504
|
+
}
|
|
2505
|
+
if (data.length === 14) {
|
|
2506
|
+
ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
|
|
2507
|
+
processRoute(decodeResult, data[4], data[2], data[6], data[5], void 0);
|
|
2508
|
+
ResultFormatter.temperature(decodeResult, data[7]);
|
|
2509
|
+
ResultFormatter.groundspeed(decodeResult, Number(data[10]));
|
|
2510
|
+
ResultFormatter.unknown(decodeResult, data[1]);
|
|
2511
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
2512
|
+
ResultFormatter.unknown(decodeResult, data[9]);
|
|
2513
|
+
ResultFormatter.unknown(decodeResult, data.slice(11).join(","));
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
function processPosition2(decodeResult, data) {
|
|
2517
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(data[0]);
|
|
2518
|
+
if (position) {
|
|
2519
|
+
decodeResult.raw.position = position;
|
|
2520
|
+
decodeResult.formatted.items.push({
|
|
2521
|
+
type: "aircraft_position",
|
|
2522
|
+
code: "POS",
|
|
2523
|
+
label: "Aircraft Position",
|
|
2524
|
+
value: CoordinateUtils.coordinateString(position)
|
|
2525
|
+
});
|
|
2526
|
+
}
|
|
2527
|
+
if (data.length >= 10) {
|
|
2528
|
+
ResultFormatter.altitude(decodeResult, Number(data[3]) * 100);
|
|
2529
|
+
processRoute(decodeResult, data[1], data[2], data[4], data[5], data[6]);
|
|
2530
|
+
ResultFormatter.temperature(decodeResult, data[7]);
|
|
2531
|
+
ResultFormatter.unknown(decodeResult, data[8]);
|
|
2532
|
+
ResultFormatter.unknown(decodeResult, data[9]);
|
|
2533
|
+
}
|
|
2534
|
+
if (data.length >= 14) {
|
|
2535
|
+
ResultFormatter.groundspeed(decodeResult, Number(data[10]));
|
|
2536
|
+
ResultFormatter.unknown(decodeResult, data[11]);
|
|
2537
|
+
ResultFormatter.unknown(decodeResult, data[12]);
|
|
2538
|
+
ResultFormatter.unknown(decodeResult, data[13]);
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
function processRoute(decodeResult, last, time, next, eta, then, date) {
|
|
2542
|
+
const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
|
|
2543
|
+
const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
|
|
2544
|
+
const timeFormat = date ? "epoch" : "tod";
|
|
2545
|
+
const lastWaypoint = RouteUtils.getWaypoint(last);
|
|
2546
|
+
lastWaypoint.time = lastTime;
|
|
2547
|
+
lastWaypoint.timeFormat = timeFormat;
|
|
2548
|
+
const nextWaypoint = RouteUtils.getWaypoint(next);
|
|
2549
|
+
nextWaypoint.time = nextTime;
|
|
2550
|
+
nextWaypoint.timeFormat = timeFormat;
|
|
2551
|
+
const thenWaypoint = RouteUtils.getWaypoint(then || "?");
|
|
2552
|
+
const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
|
|
2553
|
+
decodeResult.raw.route = { waypoints };
|
|
2554
|
+
decodeResult.formatted.items.push({
|
|
2555
|
+
type: "aircraft_route",
|
|
2556
|
+
code: "ROUTE",
|
|
2557
|
+
label: "Aircraft Route",
|
|
2558
|
+
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
2559
|
+
});
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2562
|
+
// lib/plugins/Label_4J_POS.ts
|
|
2563
|
+
var Label_4J_POS = class extends DecoderPlugin {
|
|
2564
|
+
name = "label-4j-pos";
|
|
2565
|
+
qualifiers() {
|
|
2566
|
+
return {
|
|
2567
|
+
labels: ["4J"],
|
|
2568
|
+
preambles: ["POS/"]
|
|
2569
|
+
};
|
|
2570
|
+
}
|
|
2571
|
+
// copied from Label_H1.ts since i don't really want to have to have
|
|
2572
|
+
// something named like that decode more than 1 type
|
|
2573
|
+
// if we figure out a good name, i'll combine them
|
|
2574
|
+
decode(message, options = {}) {
|
|
2575
|
+
let decodeResult = this.defaultResult();
|
|
2576
|
+
decodeResult.decoder.name = this.name;
|
|
2577
|
+
decodeResult.message = message;
|
|
2578
|
+
const msg = message.text.replace(/\n|\r/g, "");
|
|
2579
|
+
const decoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
2580
|
+
decodeResult.decoded = decoded;
|
|
2581
|
+
decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
|
|
2582
|
+
if (decodeResult.formatted.items.length === 0) {
|
|
2583
|
+
if (options.debug) {
|
|
2584
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2585
|
+
}
|
|
2586
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
2587
|
+
decodeResult.decoded = false;
|
|
2588
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2589
|
+
}
|
|
2590
|
+
return decodeResult;
|
|
2591
|
+
}
|
|
2592
|
+
};
|
|
2593
|
+
|
|
2594
|
+
// lib/plugins/Label_4N.ts
|
|
2595
|
+
var Label_4N = class extends DecoderPlugin {
|
|
2596
|
+
name = "label-4n";
|
|
2597
|
+
qualifiers() {
|
|
2598
|
+
return {
|
|
2599
|
+
labels: ["4N"]
|
|
2600
|
+
};
|
|
2601
|
+
}
|
|
2602
|
+
decode(message, options = {}) {
|
|
2603
|
+
const decodeResult = this.defaultResult();
|
|
2604
|
+
decodeResult.decoder.name = this.name;
|
|
2605
|
+
decodeResult.message = message;
|
|
2606
|
+
decodeResult.formatted.description = "Airline Defined";
|
|
2607
|
+
let text = message.text;
|
|
2608
|
+
if (text.match(/^M\d{2}A\w{6}/)) {
|
|
2609
|
+
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
2610
|
+
text = text.substring(10);
|
|
2611
|
+
}
|
|
2612
|
+
decodeResult.decoded = true;
|
|
2613
|
+
const fields = text.split(",");
|
|
2614
|
+
if (text.length === 51) {
|
|
2615
|
+
decodeResult.raw.day_of_month = text.substring(0, 2);
|
|
2616
|
+
ResultFormatter.departureAirport(decodeResult, text.substring(8, 11));
|
|
2617
|
+
ResultFormatter.arrivalAirport(decodeResult, text.substring(13, 16));
|
|
2618
|
+
ResultFormatter.position(decodeResult, CoordinateUtils.decodeStringCoordinatesDecimalMinutes(text.substring(30, 45).replace(/^(.)0/, "$1")));
|
|
2619
|
+
ResultFormatter.altitude(decodeResult, Number(text.substring(48, 51)) * 100);
|
|
2620
|
+
ResultFormatter.unknownArr(decodeResult, [text.substring(2, 4), text.substring(19, 29)], " ");
|
|
2621
|
+
} else if (fields.length === 33) {
|
|
2622
|
+
decodeResult.raw.date = fields[3];
|
|
2623
|
+
if (fields[1] === "B") {
|
|
2624
|
+
ResultFormatter.position(decodeResult, { latitude: Number(fields[4]), longitude: Number(fields[5]) });
|
|
2625
|
+
ResultFormatter.altitude(decodeResult, Number(fields[6]));
|
|
2626
|
+
}
|
|
2627
|
+
ResultFormatter.departureAirport(decodeResult, fields[8]);
|
|
2628
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[9]);
|
|
2629
|
+
ResultFormatter.alternateAirport(decodeResult, fields[10]);
|
|
2630
|
+
ResultFormatter.arrivalRunway(decodeResult, fields[11].split("/")[0]);
|
|
2631
|
+
if (fields[12].length > 1) {
|
|
2632
|
+
ResultFormatter.alternateRunway(decodeResult, fields[12].split("/")[0]);
|
|
2633
|
+
}
|
|
2634
|
+
ResultFormatter.checksum(decodeResult, fields[32]);
|
|
2635
|
+
ResultFormatter.unknownArr(decodeResult, [...fields.slice(1, 3), fields[7], ...fields.slice(13, 32)].filter((f) => f != ""));
|
|
2636
|
+
} else {
|
|
2637
|
+
decodeResult.decoded = false;
|
|
2638
|
+
ResultFormatter.unknown(decodeResult, text);
|
|
2639
|
+
}
|
|
2640
|
+
if (decodeResult.decoded) {
|
|
2641
|
+
if (!decodeResult.remaining.text)
|
|
2642
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2643
|
+
else
|
|
2644
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2645
|
+
} else {
|
|
2646
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2647
|
+
}
|
|
2648
|
+
return decodeResult;
|
|
2649
|
+
}
|
|
2650
|
+
};
|
|
2651
|
+
|
|
2652
|
+
// lib/plugins/Label_80.ts
|
|
2653
|
+
var Label_80 = class extends DecoderPlugin {
|
|
2654
|
+
name = "label-80";
|
|
2655
|
+
descriptions = {
|
|
2656
|
+
ALT: "Altitude",
|
|
2657
|
+
DWND: "Wind Direction",
|
|
2658
|
+
ETA: "Estimated Time of Arrival",
|
|
2659
|
+
FOB: "Fuel on Board",
|
|
2660
|
+
FL: "Flight Level",
|
|
2661
|
+
HDG: "Heading",
|
|
2662
|
+
MCH: "Aircraft Speed",
|
|
2663
|
+
NWYP: "Next Waypoint",
|
|
2664
|
+
POS: "Aircraft Position",
|
|
2665
|
+
SAT: "Static Air Temperature",
|
|
2666
|
+
SWND: "Wind Speed",
|
|
2667
|
+
TAS: "True Airspeed",
|
|
2668
|
+
WYP: "Waypoint"
|
|
2669
|
+
};
|
|
2670
|
+
qualifiers() {
|
|
2671
|
+
return {
|
|
2672
|
+
labels: ["80"],
|
|
2673
|
+
preambles: ["3N01 POSRPT"]
|
|
2674
|
+
};
|
|
2675
|
+
}
|
|
2676
|
+
decode(message, options = {}) {
|
|
2677
|
+
const decodeResult = this.defaultResult();
|
|
2678
|
+
decodeResult.decoder.name = this.name;
|
|
2679
|
+
decodeResult.formatted.description = "Airline Defined Position Report";
|
|
2680
|
+
const parts = message.text.split("\n");
|
|
2681
|
+
let posRptRegex = /^3N01 POSRPT \d\d\d\d\/\d\d (?<orig>\w+)\/(?<dest>\w+) \.(?<tail>[\w-]+)(\/(?<agate>.+) (?<sta>\w+:\w+))*/;
|
|
2682
|
+
let results = parts[0].match(posRptRegex);
|
|
2683
|
+
if (!results?.groups) {
|
|
2684
|
+
decodeResult.decoded = false;
|
|
2685
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2686
|
+
return decodeResult;
|
|
2687
|
+
}
|
|
2688
|
+
if (results && results.length > 0) {
|
|
2689
|
+
ResultFormatter.departureAirport(decodeResult, results.groups.orig);
|
|
2690
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.dest);
|
|
2691
|
+
ResultFormatter.tail(decodeResult, results.groups.tail);
|
|
2692
|
+
if (results.groups.agate) {
|
|
2693
|
+
decodeResult.raw.arrival_gate = results.groups.agate;
|
|
2624
2694
|
decodeResult.formatted.items.push({
|
|
2625
|
-
type: "
|
|
2626
|
-
code: "
|
|
2627
|
-
label: "
|
|
2628
|
-
value:
|
|
2695
|
+
type: "arrival_gate",
|
|
2696
|
+
code: "ARG",
|
|
2697
|
+
label: "Arrival Gate",
|
|
2698
|
+
value: `${results.groups.agate}`
|
|
2699
|
+
});
|
|
2700
|
+
decodeResult.raw.scheduled_time_of_arrival = results.groups.sta;
|
|
2701
|
+
decodeResult.formatted.items.push({
|
|
2702
|
+
type: "scheduled_time_of_arrival",
|
|
2703
|
+
code: "STA",
|
|
2704
|
+
label: "Scheduled Time of Arrival",
|
|
2705
|
+
value: `${results.groups.sta}`
|
|
2629
2706
|
});
|
|
2630
|
-
} else {
|
|
2631
|
-
decodeResult.remaining.text += "/" + fields[i];
|
|
2632
2707
|
}
|
|
2708
|
+
posRptRegex = /\/(?<field>\w+)\s(?<value>[\w\+\-:\.]+)\s*/gi;
|
|
2709
|
+
const remainingParts = parts.slice(1);
|
|
2710
|
+
for (const part of remainingParts) {
|
|
2711
|
+
const matches = part.matchAll(posRptRegex);
|
|
2712
|
+
for (const match of matches) {
|
|
2713
|
+
switch (match.groups?.field) {
|
|
2714
|
+
case "ALT": {
|
|
2715
|
+
ResultFormatter.altitude(decodeResult, Number(match.groups.value));
|
|
2716
|
+
break;
|
|
2717
|
+
}
|
|
2718
|
+
case "DWND": {
|
|
2719
|
+
decodeResult.raw.wind_direction = Number(match.groups.value);
|
|
2720
|
+
decodeResult.formatted.items.push({
|
|
2721
|
+
type: "wind_direction",
|
|
2722
|
+
code: "DWND",
|
|
2723
|
+
label: this.descriptions[match.groups.field],
|
|
2724
|
+
value: decodeResult.raw.wind_direction
|
|
2725
|
+
});
|
|
2726
|
+
break;
|
|
2727
|
+
}
|
|
2728
|
+
case "FL": {
|
|
2729
|
+
const flight_level = Number(match.groups.value);
|
|
2730
|
+
ResultFormatter.altitude(decodeResult, flight_level * 100);
|
|
2731
|
+
break;
|
|
2732
|
+
}
|
|
2733
|
+
case "FOB": {
|
|
2734
|
+
const fob = Number(match.groups.value);
|
|
2735
|
+
if (!isNaN(fob)) {
|
|
2736
|
+
ResultFormatter.currentFuel(decodeResult, fob);
|
|
2737
|
+
}
|
|
2738
|
+
break;
|
|
2739
|
+
}
|
|
2740
|
+
case "HDG": {
|
|
2741
|
+
ResultFormatter.heading(decodeResult, Number(match.groups.value));
|
|
2742
|
+
break;
|
|
2743
|
+
}
|
|
2744
|
+
case "MCH": {
|
|
2745
|
+
decodeResult.raw.mach = Number(match.groups.value) / 1e3;
|
|
2746
|
+
decodeResult.formatted.items.push({
|
|
2747
|
+
type: "mach",
|
|
2748
|
+
code: "MCH",
|
|
2749
|
+
label: this.descriptions[match.groups.field],
|
|
2750
|
+
value: `${decodeResult.raw.mach} Mach`
|
|
2751
|
+
});
|
|
2752
|
+
break;
|
|
2753
|
+
}
|
|
2754
|
+
case "NWYP": {
|
|
2755
|
+
decodeResult.raw.next_waypoint = match.groups.value;
|
|
2756
|
+
decodeResult.formatted.items.push({
|
|
2757
|
+
type: "next_waypoint",
|
|
2758
|
+
code: "NWYP",
|
|
2759
|
+
label: this.descriptions[match.groups.field],
|
|
2760
|
+
value: decodeResult.raw.next_waypoint
|
|
2761
|
+
});
|
|
2762
|
+
break;
|
|
2763
|
+
}
|
|
2764
|
+
case "POS": {
|
|
2765
|
+
const posRegex = /^(?<latd>[NS])(?<lat>.+)(?<lngd>[EW])(?<lng>.+)/;
|
|
2766
|
+
const posResult = match.groups.value.match(posRegex);
|
|
2767
|
+
const lat = Number(posResult?.groups?.lat) * (posResult?.groups?.lngd === "S" ? -1 : 1);
|
|
2768
|
+
const lon = Number(posResult?.groups?.lng) * (posResult?.groups?.lngd === "W" ? -1 : 1);
|
|
2769
|
+
const position = {
|
|
2770
|
+
latitude: Number.isInteger(lat) ? lat / 1e3 : lat / 100,
|
|
2771
|
+
longitude: Number.isInteger(lon) ? lon / 1e3 : lon / 100
|
|
2772
|
+
};
|
|
2773
|
+
ResultFormatter.position(decodeResult, position);
|
|
2774
|
+
break;
|
|
2775
|
+
}
|
|
2776
|
+
case "SWND": {
|
|
2777
|
+
decodeResult.raw.wind_speed = Number(match.groups.value);
|
|
2778
|
+
decodeResult.formatted.items.push({
|
|
2779
|
+
type: "wind_speed",
|
|
2780
|
+
code: "SWND",
|
|
2781
|
+
label: this.descriptions[match.groups.field],
|
|
2782
|
+
value: decodeResult.raw.wind_speed
|
|
2783
|
+
});
|
|
2784
|
+
break;
|
|
2785
|
+
}
|
|
2786
|
+
default: {
|
|
2787
|
+
if (match.groups?.field != void 0) {
|
|
2788
|
+
const description = this.descriptions[match.groups.field] ? this.descriptions[match.groups.field] : "Unknown";
|
|
2789
|
+
decodeResult.formatted.items.push({
|
|
2790
|
+
type: match.groups.field,
|
|
2791
|
+
code: match.groups.field,
|
|
2792
|
+
label: description || `Unknown (${match.groups.field})`,
|
|
2793
|
+
value: `${match.groups.value}`
|
|
2794
|
+
});
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
decodeResult.decoded = true;
|
|
2801
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2633
2802
|
}
|
|
2634
|
-
|
|
2635
|
-
ResultFormatter.checksum(decodeResult, checksum);
|
|
2636
|
-
}
|
|
2637
|
-
return true;
|
|
2803
|
+
return decodeResult;
|
|
2638
2804
|
}
|
|
2639
2805
|
};
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
}
|
|
2648
|
-
function processTimeOfDeparture(decodeResult, data) {
|
|
2649
|
-
if (data.length === 2) {
|
|
2650
|
-
decodeResult.raw.plannedDepartureTime = data[0];
|
|
2651
|
-
decodeResult.formatted.items.push({
|
|
2652
|
-
type: "ptd",
|
|
2653
|
-
code: "ptd",
|
|
2654
|
-
label: "Planned Departure Time",
|
|
2655
|
-
value: `YYYY-MM-${data[0].substring(0, 2)}T${data[0].substring(2, 4)}:${data[0].substring(4)}:00Z`
|
|
2656
|
-
});
|
|
2657
|
-
decodeResult.raw.plannedDepartureTime = data[1];
|
|
2658
|
-
decodeResult.formatted.items.push({
|
|
2659
|
-
type: "etd",
|
|
2660
|
-
code: "etd",
|
|
2661
|
-
label: "Estimated Departure Time",
|
|
2662
|
-
value: `${data[1].substring(0, 2)}:${data[1].substring(2)}`
|
|
2663
|
-
});
|
|
2664
|
-
} else {
|
|
2665
|
-
decodeResult.remaining.text += "/TD" + data.join(",");
|
|
2666
|
-
}
|
|
2667
|
-
}
|
|
2668
|
-
function processIdentification(decodeResult, data) {
|
|
2669
|
-
ResultFormatter.tail(decodeResult, data[0]);
|
|
2670
|
-
if (data.length > 1) {
|
|
2671
|
-
decodeResult.raw.flight_number = data[1];
|
|
2672
|
-
}
|
|
2673
|
-
if (data.length > 2) {
|
|
2674
|
-
decodeResult.raw.mission_number = data[2];
|
|
2675
|
-
}
|
|
2676
|
-
}
|
|
2677
|
-
function processDT(decodeResult, data) {
|
|
2678
|
-
if (!decodeResult.raw.arrival_icao) {
|
|
2679
|
-
ResultFormatter.arrivalAirport(decodeResult, data[0]);
|
|
2680
|
-
} else if (decodeResult.raw.arrival_icao != data[0]) {
|
|
2681
|
-
decodeResult.remaining.text += "/" + data;
|
|
2682
|
-
}
|
|
2683
|
-
if (data.length > 1) {
|
|
2684
|
-
ResultFormatter.arrivalRunway(decodeResult, data[1]);
|
|
2685
|
-
}
|
|
2686
|
-
if (data.length > 2) {
|
|
2687
|
-
ResultFormatter.currentFuel(decodeResult, Number(data[2]));
|
|
2688
|
-
}
|
|
2689
|
-
if (data.length > 3) {
|
|
2690
|
-
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data[3]));
|
|
2691
|
-
}
|
|
2692
|
-
if (data.length > 4) {
|
|
2693
|
-
ResultFormatter.remainingFuel(decodeResult, Number(data[4]));
|
|
2694
|
-
}
|
|
2695
|
-
if (data.length > 5) {
|
|
2696
|
-
decodeResult.remaining.text += "," + data.slice(5).join(",");
|
|
2697
|
-
}
|
|
2698
|
-
}
|
|
2699
|
-
function processLR(decodeResult, data) {
|
|
2700
|
-
if (data.length === 19) {
|
|
2701
|
-
ResultFormatter.unknown(decodeResult, data[1]);
|
|
2702
|
-
ResultFormatter.flightNumber(decodeResult, data[2]);
|
|
2703
|
-
ResultFormatter.departureAirport(decodeResult, data[3]);
|
|
2704
|
-
ResultFormatter.arrivalAirport(decodeResult, data[4]);
|
|
2705
|
-
ResultFormatter.arrivalRunway(decodeResult, data[5]);
|
|
2706
|
-
ResultFormatter.unknown(decodeResult, data.slice(6, 19).join(","));
|
|
2707
|
-
} else {
|
|
2708
|
-
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
2806
|
+
|
|
2807
|
+
// lib/plugins/Label_83.ts
|
|
2808
|
+
var Label_83 = class extends DecoderPlugin {
|
|
2809
|
+
name = "label-83";
|
|
2810
|
+
qualifiers() {
|
|
2811
|
+
return {
|
|
2812
|
+
labels: ["83"]
|
|
2813
|
+
};
|
|
2709
2814
|
}
|
|
2710
|
-
}
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2815
|
+
decode(message, options = {}) {
|
|
2816
|
+
const decodeResult = this.defaultResult();
|
|
2817
|
+
decodeResult.decoder.name = this.name;
|
|
2818
|
+
decodeResult.message = message;
|
|
2819
|
+
decodeResult.formatted.description = "Airline Defined";
|
|
2820
|
+
let text = message.text;
|
|
2821
|
+
if (text.match(/^M\d{2}A\w{6}/)) {
|
|
2822
|
+
ResultFormatter.flightNumber(decodeResult, message.text.substring(4, 10).replace(/^([A-Z]+)0*/g, "$1"));
|
|
2823
|
+
text = text.substring(10);
|
|
2717
2824
|
}
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2825
|
+
decodeResult.decoded = true;
|
|
2826
|
+
if (text.substring(0, 10) === "4DH3 ETAT2") {
|
|
2827
|
+
const fields = text.split(/\s+/);
|
|
2828
|
+
if (fields[2].length > 5) {
|
|
2829
|
+
decodeResult.raw.day_of_month = fields[2].substring(5);
|
|
2830
|
+
}
|
|
2831
|
+
ResultFormatter.unknown(decodeResult, fields[2].substring(0, 4));
|
|
2832
|
+
const subfields = fields[3].split("/");
|
|
2833
|
+
ResultFormatter.departureAirport(decodeResult, subfields[0]);
|
|
2834
|
+
ResultFormatter.arrivalAirport(decodeResult, subfields[1]);
|
|
2835
|
+
ResultFormatter.tail(decodeResult, fields[4].replace(/\./g, ""));
|
|
2836
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[6] + "00"));
|
|
2837
|
+
} else if (text.substring(0, 5) === "001PR") {
|
|
2838
|
+
decodeResult.raw.day_of_month = text.substring(5, 7);
|
|
2839
|
+
const position = CoordinateUtils.decodeStringCoordinatesDecimalMinutes(text.substring(13, 28).replace(/\./g, ""));
|
|
2840
|
+
if (position) {
|
|
2841
|
+
ResultFormatter.position(decodeResult, position);
|
|
2842
|
+
}
|
|
2843
|
+
ResultFormatter.altitude(decodeResult, Number(text.substring(28, 33)));
|
|
2844
|
+
ResultFormatter.unknown(decodeResult, text.substring(33));
|
|
2845
|
+
} else {
|
|
2846
|
+
const fields = text.replace(/\s/g, "").split(",");
|
|
2847
|
+
if (fields.length === 9) {
|
|
2848
|
+
ResultFormatter.departureAirport(decodeResult, fields[0]);
|
|
2849
|
+
ResultFormatter.arrivalAirport(decodeResult, fields[1]);
|
|
2850
|
+
decodeResult.raw.day_of_month = fields[2].substring(0, 2);
|
|
2851
|
+
decodeResult.raw.time = fields[2].substring(2);
|
|
2852
|
+
ResultFormatter.position(
|
|
2853
|
+
decodeResult,
|
|
2854
|
+
{
|
|
2855
|
+
latitude: Number(fields[3].replace(/\s/g, "")),
|
|
2856
|
+
longitude: Number(fields[4].replace(/\s/g, ""))
|
|
2857
|
+
}
|
|
2858
|
+
);
|
|
2859
|
+
ResultFormatter.altitude(decodeResult, Number(fields[5]));
|
|
2860
|
+
ResultFormatter.groundspeed(decodeResult, Number(fields[6]));
|
|
2861
|
+
ResultFormatter.heading(decodeResult, Number(fields[7]));
|
|
2862
|
+
ResultFormatter.unknown(decodeResult, fields[8]);
|
|
2863
|
+
} else {
|
|
2864
|
+
decodeResult.decoded = false;
|
|
2865
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
2866
|
+
}
|
|
2724
2867
|
}
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2868
|
+
if (decodeResult.decoded) {
|
|
2869
|
+
if (!decodeResult.remaining.text)
|
|
2870
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2871
|
+
else
|
|
2872
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
2873
|
+
} else {
|
|
2874
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2728
2875
|
}
|
|
2729
|
-
|
|
2730
|
-
} else {
|
|
2731
|
-
decodeResult.remaining.text += messageType;
|
|
2732
|
-
}
|
|
2733
|
-
}
|
|
2734
|
-
function processMessageType(decodeResult, type) {
|
|
2735
|
-
if (type === "FPN") {
|
|
2736
|
-
decodeResult.formatted.description = "Flight Plan";
|
|
2737
|
-
} else if (type === "FTX") {
|
|
2738
|
-
decodeResult.formatted.description = "Free Text";
|
|
2739
|
-
} else if (type === "INI") {
|
|
2740
|
-
decodeResult.formatted.description = "Flight Plan Initial Report";
|
|
2741
|
-
} else if (type === "POS") {
|
|
2742
|
-
decodeResult.formatted.description = "Position Report";
|
|
2743
|
-
} else if (type === "PRG") {
|
|
2744
|
-
decodeResult.formatted.description = "Progress Report";
|
|
2745
|
-
} else {
|
|
2746
|
-
decodeResult.formatted.description = "Unknown H1 Message";
|
|
2747
|
-
}
|
|
2748
|
-
}
|
|
2749
|
-
function processDC(decodeResult, data) {
|
|
2750
|
-
decodeResult.raw.message_date = data[0];
|
|
2751
|
-
if (data.length === 1) {
|
|
2752
|
-
} else if (data.length === 2) {
|
|
2753
|
-
const date = data[0].substring(2, 4) + data[0].substring(0, 2) + data[0].substring(4, 6);
|
|
2754
|
-
const time = DateTimeUtils.convertDateTimeToEpoch(data[1], data[0]);
|
|
2755
|
-
decodeResult.raw.message_timestamp = time;
|
|
2876
|
+
return decodeResult;
|
|
2756
2877
|
}
|
|
2757
|
-
}
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
value: CoordinateUtils.coordinateString(position)
|
|
2767
|
-
});
|
|
2878
|
+
};
|
|
2879
|
+
|
|
2880
|
+
// lib/plugins/Label_8E.ts
|
|
2881
|
+
var Label_8E = class extends DecoderPlugin {
|
|
2882
|
+
name = "label-8e";
|
|
2883
|
+
qualifiers() {
|
|
2884
|
+
return {
|
|
2885
|
+
labels: ["8E"]
|
|
2886
|
+
};
|
|
2768
2887
|
}
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2888
|
+
decode(message, options = {}) {
|
|
2889
|
+
const decodeResult = this.defaultResult();
|
|
2890
|
+
decodeResult.decoder.name = this.name;
|
|
2891
|
+
decodeResult.formatted.description = "ETA Report";
|
|
2892
|
+
decodeResult.message = message;
|
|
2893
|
+
const regex = /^(?<arrival_icao>\w{4}),(?<arrival_eta>\d{4})$/;
|
|
2894
|
+
const results = message.text.match(regex);
|
|
2895
|
+
if (results?.groups) {
|
|
2896
|
+
if (options.debug) {
|
|
2897
|
+
console.log(`Label 8E ETA: groups`);
|
|
2898
|
+
console.log(results.groups);
|
|
2899
|
+
}
|
|
2900
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(results.groups.arrival_eta + "00"));
|
|
2901
|
+
ResultFormatter.arrivalAirport(decodeResult, results.groups.arrival_icao);
|
|
2902
|
+
}
|
|
2903
|
+
decodeResult.decoded = true;
|
|
2904
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2905
|
+
return decodeResult;
|
|
2775
2906
|
}
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2907
|
+
};
|
|
2908
|
+
|
|
2909
|
+
// lib/plugins/Label_B6.ts
|
|
2910
|
+
var Label_B6_Forwardslash = class extends DecoderPlugin {
|
|
2911
|
+
name = "label-b6-forwardslash";
|
|
2912
|
+
qualifiers() {
|
|
2913
|
+
return {
|
|
2914
|
+
labels: ["B6"],
|
|
2915
|
+
preambles: ["/"]
|
|
2916
|
+
};
|
|
2785
2917
|
}
|
|
2786
|
-
}
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
decodeResult.
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
value: CoordinateUtils.coordinateString(position)
|
|
2796
|
-
});
|
|
2918
|
+
decode(message, options = {}) {
|
|
2919
|
+
const decodeResult = this.defaultResult();
|
|
2920
|
+
decodeResult.decoder.name = this.name;
|
|
2921
|
+
decodeResult.formatted.description = "CPDLC Message";
|
|
2922
|
+
decodeResult.message = message;
|
|
2923
|
+
if (options.debug) {
|
|
2924
|
+
console.log("CPDLC: " + message);
|
|
2925
|
+
}
|
|
2926
|
+
return decodeResult;
|
|
2797
2927
|
}
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2928
|
+
};
|
|
2929
|
+
|
|
2930
|
+
// lib/plugins/Label_ColonComma.ts
|
|
2931
|
+
var Label_ColonComma = class extends DecoderPlugin {
|
|
2932
|
+
name = "label-colon-comma";
|
|
2933
|
+
qualifiers() {
|
|
2934
|
+
return {
|
|
2935
|
+
labels: [":;"]
|
|
2936
|
+
};
|
|
2804
2937
|
}
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2938
|
+
decode(message, options = {}) {
|
|
2939
|
+
const decodeResult = this.defaultResult();
|
|
2940
|
+
decodeResult.decoder.name = this.name;
|
|
2941
|
+
decodeResult.raw.frequency = Number(message.text) / 1e3;
|
|
2942
|
+
decodeResult.formatted.description = "Aircraft Transceiver Frequency Change";
|
|
2943
|
+
decodeResult.formatted.items.push({
|
|
2944
|
+
type: "frequency",
|
|
2945
|
+
label: "Frequency",
|
|
2946
|
+
value: `${decodeResult.raw.frequency} MHz`,
|
|
2947
|
+
code: "FREQ"
|
|
2948
|
+
});
|
|
2949
|
+
decodeResult.decoded = true;
|
|
2950
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
2951
|
+
return decodeResult;
|
|
2810
2952
|
}
|
|
2811
|
-
}
|
|
2812
|
-
function processRoute(decodeResult, last, time, next, eta, then, date) {
|
|
2813
|
-
const lastTime = date ? DateTimeUtils.convertDateTimeToEpoch(time, date) : DateTimeUtils.convertHHMMSSToTod(time);
|
|
2814
|
-
const nextTime = date ? DateTimeUtils.convertDateTimeToEpoch(eta, date) : DateTimeUtils.convertHHMMSSToTod(eta);
|
|
2815
|
-
const timeFormat = date ? "epoch" : "tod";
|
|
2816
|
-
const lastWaypoint = RouteUtils.getWaypoint(last);
|
|
2817
|
-
lastWaypoint.time = lastTime;
|
|
2818
|
-
lastWaypoint.timeFormat = timeFormat;
|
|
2819
|
-
const nextWaypoint = RouteUtils.getWaypoint(next);
|
|
2820
|
-
nextWaypoint.time = nextTime;
|
|
2821
|
-
nextWaypoint.timeFormat = timeFormat;
|
|
2822
|
-
const thenWaypoint = RouteUtils.getWaypoint(then || "?");
|
|
2823
|
-
const waypoints = [lastWaypoint, nextWaypoint, thenWaypoint];
|
|
2824
|
-
decodeResult.raw.route = { waypoints };
|
|
2825
|
-
decodeResult.formatted.items.push({
|
|
2826
|
-
type: "aircraft_route",
|
|
2827
|
-
code: "ROUTE",
|
|
2828
|
-
label: "Aircraft Route",
|
|
2829
|
-
value: RouteUtils.routeToString(decodeResult.raw.route)
|
|
2830
|
-
});
|
|
2831
|
-
}
|
|
2953
|
+
};
|
|
2832
2954
|
|
|
2833
2955
|
// lib/plugins/Label_H1.ts
|
|
2834
2956
|
var Label_H1 = class extends DecoderPlugin {
|
|
@@ -2842,16 +2964,205 @@ var Label_H1 = class extends DecoderPlugin {
|
|
|
2842
2964
|
let decodeResult = this.defaultResult();
|
|
2843
2965
|
decodeResult.decoder.name = this.name;
|
|
2844
2966
|
decodeResult.message = message;
|
|
2845
|
-
decodeResult.remaining.text = "";
|
|
2846
2967
|
const msg = message.text.replace(/\n|\r/g, "");
|
|
2847
2968
|
const decoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
2848
2969
|
decodeResult.decoded = decoded;
|
|
2849
|
-
decodeResult.decoder.decodeLevel = decodeResult.remaining.text
|
|
2970
|
+
decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
|
|
2850
2971
|
if (decodeResult.formatted.items.length === 0) {
|
|
2851
2972
|
if (options.debug) {
|
|
2852
2973
|
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
2853
2974
|
}
|
|
2854
|
-
decodeResult
|
|
2975
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
2976
|
+
decodeResult.decoded = false;
|
|
2977
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
2978
|
+
}
|
|
2979
|
+
return decodeResult;
|
|
2980
|
+
}
|
|
2981
|
+
};
|
|
2982
|
+
|
|
2983
|
+
// lib/plugins/Label_H1_FLR.ts
|
|
2984
|
+
var Label_H1_FLR = class extends DecoderPlugin {
|
|
2985
|
+
name = "label-h1-flr";
|
|
2986
|
+
qualifiers() {
|
|
2987
|
+
return {
|
|
2988
|
+
labels: ["H1"],
|
|
2989
|
+
preambles: ["FLR", "#CFBFLR"]
|
|
2990
|
+
};
|
|
2991
|
+
}
|
|
2992
|
+
decode(message, options = {}) {
|
|
2993
|
+
let decodeResult = this.defaultResult();
|
|
2994
|
+
decodeResult.decoder.name = this.name;
|
|
2995
|
+
decodeResult.formatted.description = "Fault Log Report";
|
|
2996
|
+
decodeResult.message = message;
|
|
2997
|
+
const parts = message.text.split("/FR");
|
|
2998
|
+
if (parts.length > 1) {
|
|
2999
|
+
const fields = parts[0].split("/");
|
|
3000
|
+
for (let i = 1; i < fields.length; i++) {
|
|
3001
|
+
const field = fields[i];
|
|
3002
|
+
ResultFormatter.unknown(decodeResult, field, "/");
|
|
3003
|
+
}
|
|
3004
|
+
const data = parts[1].substring(0, 20);
|
|
3005
|
+
const msg = parts[1].substring(20);
|
|
3006
|
+
const datetime = data.substring(0, 12);
|
|
3007
|
+
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
3008
|
+
ResultFormatter.unknown(decodeResult, data.substring(12), "/");
|
|
3009
|
+
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
3010
|
+
decodeResult.raw.fault_message = msg;
|
|
3011
|
+
decodeResult.formatted.items.push({
|
|
3012
|
+
type: "fault",
|
|
3013
|
+
code: "FR",
|
|
3014
|
+
label: "Fault Report",
|
|
3015
|
+
value: decodeResult.raw.fault_message
|
|
3016
|
+
});
|
|
3017
|
+
decodeResult.decoded = true;
|
|
3018
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
3019
|
+
} else {
|
|
3020
|
+
if (options.debug) {
|
|
3021
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
3022
|
+
}
|
|
3023
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
3024
|
+
decodeResult.decoded = false;
|
|
3025
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
3026
|
+
}
|
|
3027
|
+
return decodeResult;
|
|
3028
|
+
}
|
|
3029
|
+
};
|
|
3030
|
+
|
|
3031
|
+
// lib/plugins/Label_H1_OHMA.ts
|
|
3032
|
+
var zlib = __toESM(require("minizlib"));
|
|
3033
|
+
var Label_H1_OHMA = class extends DecoderPlugin {
|
|
3034
|
+
name = "label-h1-ohma";
|
|
3035
|
+
qualifiers() {
|
|
3036
|
+
return {
|
|
3037
|
+
labels: ["H1"],
|
|
3038
|
+
preambles: ["OHMA", "/RTNBOCR.OHMA", "#T1B/RTNBOCR.OHMA"]
|
|
3039
|
+
};
|
|
3040
|
+
}
|
|
3041
|
+
decode(message, options = {}) {
|
|
3042
|
+
let decodeResult = this.defaultResult();
|
|
3043
|
+
decodeResult.decoder.name = this.name;
|
|
3044
|
+
decodeResult.formatted.description = "OHMA Message";
|
|
3045
|
+
decodeResult.message = message;
|
|
3046
|
+
const data = message.text.split("OHMA")[1];
|
|
3047
|
+
try {
|
|
3048
|
+
const compressedBuffer = Buffer.from(data, "base64");
|
|
3049
|
+
const decompress = new zlib.Inflate({ windowBits: 15 });
|
|
3050
|
+
decompress.write(compressedBuffer);
|
|
3051
|
+
decompress.flush(zlib.constants.Z_SYNC_FLUSH);
|
|
3052
|
+
const result = decompress.read();
|
|
3053
|
+
const jsonText = result.toString();
|
|
3054
|
+
let formattedMsg;
|
|
3055
|
+
let jsonMessage;
|
|
3056
|
+
try {
|
|
3057
|
+
jsonMessage = JSON.parse(jsonText).message;
|
|
3058
|
+
} catch {
|
|
3059
|
+
jsonMessage = jsonText;
|
|
3060
|
+
}
|
|
3061
|
+
try {
|
|
3062
|
+
const ohmaMsg = JSON.parse(jsonMessage);
|
|
3063
|
+
formattedMsg = JSON.stringify(ohmaMsg, null, 2);
|
|
3064
|
+
} catch {
|
|
3065
|
+
formattedMsg = jsonMessage;
|
|
3066
|
+
}
|
|
3067
|
+
decodeResult.decoded = true;
|
|
3068
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
3069
|
+
decodeResult.raw.ohma = jsonText;
|
|
3070
|
+
decodeResult.formatted.items.push({
|
|
3071
|
+
type: "ohma",
|
|
3072
|
+
code: "OHMA",
|
|
3073
|
+
label: "OHMA Downlink",
|
|
3074
|
+
value: formattedMsg
|
|
3075
|
+
});
|
|
3076
|
+
} catch (e) {
|
|
3077
|
+
if (options.debug) {
|
|
3078
|
+
console.log(`Decoder: Unknown H1 OHMA message: ${message.text}`, e);
|
|
3079
|
+
}
|
|
3080
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
3081
|
+
decodeResult.decoded = false;
|
|
3082
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
3083
|
+
}
|
|
3084
|
+
return decodeResult;
|
|
3085
|
+
}
|
|
3086
|
+
};
|
|
3087
|
+
|
|
3088
|
+
// lib/plugins/Label_H1_StarPOS.ts
|
|
3089
|
+
var Label_H1_StarPOS = class extends DecoderPlugin {
|
|
3090
|
+
name = "label-h1-star-pos";
|
|
3091
|
+
qualifiers() {
|
|
3092
|
+
return {
|
|
3093
|
+
labels: ["H1"],
|
|
3094
|
+
preambles: ["*POS"]
|
|
3095
|
+
};
|
|
3096
|
+
}
|
|
3097
|
+
decode(message, options = {}) {
|
|
3098
|
+
let decodeResult = this.defaultResult();
|
|
3099
|
+
decodeResult.decoder.name = this.name;
|
|
3100
|
+
decodeResult.formatted.description = "Position Report";
|
|
3101
|
+
decodeResult.message = message;
|
|
3102
|
+
const msg = message.text;
|
|
3103
|
+
if (msg.length !== 43 || !msg.startsWith("*POS")) {
|
|
3104
|
+
if (options.debug) {
|
|
3105
|
+
console.log(`Decoder: Unknown H1 message: ${msg}`);
|
|
3106
|
+
}
|
|
3107
|
+
ResultFormatter.unknown(decodeResult, msg);
|
|
3108
|
+
decodeResult.decoded = false;
|
|
3109
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
3110
|
+
return decodeResult;
|
|
3111
|
+
}
|
|
3112
|
+
decodeResult.raw.month = Number(msg.substring(4, 6));
|
|
3113
|
+
decodeResult.raw.day_of_month = Number(msg.substring(6, 8));
|
|
3114
|
+
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(msg.substring(8, 12) + "00"));
|
|
3115
|
+
ResultFormatter.position(decodeResult, {
|
|
3116
|
+
// Deg Min, no sec
|
|
3117
|
+
latitude: CoordinateUtils.getDirection(msg.substring(12, 13)) * (Number(msg.substring(13, 15)) + Number(msg.substring(15, 17)) / 60),
|
|
3118
|
+
longitude: CoordinateUtils.getDirection(msg.substring(17, 18)) * (Number(msg.substring(18, 21)) + Number(msg.substring(21, 23)) / 60)
|
|
3119
|
+
});
|
|
3120
|
+
ResultFormatter.altitude(decodeResult, Number(msg.substring(23, 28)));
|
|
3121
|
+
ResultFormatter.unknown(decodeResult, msg.substring(28));
|
|
3122
|
+
decodeResult.decoded = true;
|
|
3123
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
3124
|
+
return decodeResult;
|
|
3125
|
+
}
|
|
3126
|
+
};
|
|
3127
|
+
|
|
3128
|
+
// lib/plugins/Label_H1_WRN.ts
|
|
3129
|
+
var Label_H1_WRN = class extends DecoderPlugin {
|
|
3130
|
+
name = "label-h1-wrn";
|
|
3131
|
+
qualifiers() {
|
|
3132
|
+
return {
|
|
3133
|
+
labels: ["H1"],
|
|
3134
|
+
preambles: ["WRN", "#CFBWRN"]
|
|
3135
|
+
};
|
|
3136
|
+
}
|
|
3137
|
+
decode(message, options = {}) {
|
|
3138
|
+
let decodeResult = this.defaultResult();
|
|
3139
|
+
decodeResult.decoder.name = this.name;
|
|
3140
|
+
decodeResult.formatted.description = "Warning Message";
|
|
3141
|
+
decodeResult.message = message;
|
|
3142
|
+
const parts = message.text.split("/WN");
|
|
3143
|
+
if (parts.length > 1) {
|
|
3144
|
+
const fields = parts[0].split("/");
|
|
3145
|
+
ResultFormatter.unknownArr(decodeResult, fields.slice(1), "/");
|
|
3146
|
+
const data = parts[1].substring(0, 20);
|
|
3147
|
+
const msg = parts[1].substring(20);
|
|
3148
|
+
const datetime = data.substring(0, 12);
|
|
3149
|
+
const date = datetime.substring(4, 6) + datetime.substring(2, 4) + datetime.substring(0, 2);
|
|
3150
|
+
ResultFormatter.unknown(decodeResult, data.substring(12), "/");
|
|
3151
|
+
decodeResult.raw.message_timestamp = DateTimeUtils.convertDateTimeToEpoch(datetime.substring(6), date);
|
|
3152
|
+
decodeResult.raw.warning_message = msg;
|
|
3153
|
+
decodeResult.formatted.items.push({
|
|
3154
|
+
type: "warning",
|
|
3155
|
+
code: "WRN",
|
|
3156
|
+
label: "Warning Message",
|
|
3157
|
+
value: decodeResult.raw.warning_message
|
|
3158
|
+
});
|
|
3159
|
+
decodeResult.decoded = true;
|
|
3160
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
3161
|
+
} else {
|
|
3162
|
+
if (options.debug) {
|
|
3163
|
+
console.log(`Decoder: Unknown H1 message: ${message.text}`);
|
|
3164
|
+
}
|
|
3165
|
+
ResultFormatter.unknown(decodeResult, message.text);
|
|
2855
3166
|
decodeResult.decoded = false;
|
|
2856
3167
|
decodeResult.decoder.decodeLevel = "none";
|
|
2857
3168
|
}
|
|
@@ -2882,25 +3193,18 @@ var Label_HX = class extends DecoderPlugin {
|
|
|
2882
3193
|
let londir = parts[4].substring(0, 1);
|
|
2883
3194
|
let londeg = Number(parts[4].substring(1, 4));
|
|
2884
3195
|
let lonmin = Number(parts[4].substring(4, 8));
|
|
2885
|
-
|
|
3196
|
+
let pos = {
|
|
2886
3197
|
latitude: (latdeg + latmin / 60) * (latdir === "N" ? 1 : -1),
|
|
2887
3198
|
longitude: (londeg + lonmin / 60) * (londir === "E" ? 1 : -1)
|
|
2888
3199
|
};
|
|
2889
|
-
decodeResult
|
|
3200
|
+
ResultFormatter.unknownArr(decodeResult, parts.slice(5), " ");
|
|
3201
|
+
ResultFormatter.position(decodeResult, pos);
|
|
2890
3202
|
} else if (parts[2] === "43") {
|
|
2891
3203
|
ResultFormatter.departureAirport(decodeResult, parts[3]);
|
|
2892
|
-
decodeResult
|
|
3204
|
+
ResultFormatter.unknownArr(decodeResult, parts.slice(4), " ");
|
|
2893
3205
|
} else {
|
|
2894
3206
|
decodeResult.decoded = false;
|
|
2895
3207
|
}
|
|
2896
|
-
if (decodeResult.raw.position) {
|
|
2897
|
-
decodeResult.formatted.items.push({
|
|
2898
|
-
type: "aircraft_position",
|
|
2899
|
-
code: "POS",
|
|
2900
|
-
label: "Aircraft Position",
|
|
2901
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
2902
|
-
});
|
|
2903
|
-
}
|
|
2904
3208
|
if (decodeResult.decoded) {
|
|
2905
3209
|
if (!decodeResult.remaining.text)
|
|
2906
3210
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -2930,7 +3234,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2930
3234
|
if (decodeResult.raw.version === "2") {
|
|
2931
3235
|
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+)\/.*/;
|
|
2932
3236
|
const result = message.text.match(regex);
|
|
2933
|
-
if (result && result.length >= 8) {
|
|
3237
|
+
if (result?.groups && result.length >= 8) {
|
|
2934
3238
|
decodeResult.raw.groundStation = {
|
|
2935
3239
|
number: result.groups.station,
|
|
2936
3240
|
iataCode: result.groups.iata,
|
|
@@ -2940,7 +3244,7 @@ var Label_SQ = class extends DecoderPlugin {
|
|
|
2940
3244
|
longitude: Number(result.groups.lng) / 100 * (result.groups.lngd === "W" ? -1 : 1)
|
|
2941
3245
|
}
|
|
2942
3246
|
};
|
|
2943
|
-
decodeResult.raw.vdlFrequency = result.groups.vfreq / 1e3;
|
|
3247
|
+
decodeResult.raw.vdlFrequency = Number(result.groups.vfreq) / 1e3;
|
|
2944
3248
|
}
|
|
2945
3249
|
}
|
|
2946
3250
|
decodeResult.formatted.description = "Ground Station Squitter";
|
|
@@ -3031,31 +3335,11 @@ var Label_QR = class extends DecoderPlugin {
|
|
|
3031
3335
|
decode(message, options = {}) {
|
|
3032
3336
|
const decodeResult = this.defaultResult();
|
|
3033
3337
|
decodeResult.decoder.name = this.name;
|
|
3034
|
-
decodeResult.raw.origin = message.text.substring(0, 4);
|
|
3035
|
-
decodeResult.raw.destination = message.text.substring(4, 8);
|
|
3036
|
-
decodeResult.raw.wheels_on = message.text.substring(8, 12);
|
|
3037
|
-
decodeResult.remaining.text = message.text.substring(12);
|
|
3038
3338
|
decodeResult.formatted.description = "ON Report";
|
|
3039
|
-
decodeResult.
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
label: "Origin",
|
|
3044
|
-
value: decodeResult.raw.origin
|
|
3045
|
-
},
|
|
3046
|
-
{
|
|
3047
|
-
type: "destination",
|
|
3048
|
-
code: "DST",
|
|
3049
|
-
label: "Destination",
|
|
3050
|
-
value: decodeResult.raw.destination
|
|
3051
|
-
},
|
|
3052
|
-
{
|
|
3053
|
-
type: "wheels_on",
|
|
3054
|
-
code: "WON",
|
|
3055
|
-
label: "Wheels ON",
|
|
3056
|
-
value: decodeResult.raw.wheels_on
|
|
3057
|
-
}
|
|
3058
|
-
];
|
|
3339
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
3340
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
3341
|
+
ResultFormatter.on(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12) + "00"));
|
|
3342
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
3059
3343
|
decodeResult.decoded = true;
|
|
3060
3344
|
if (!decodeResult.remaining.text)
|
|
3061
3345
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -3076,31 +3360,11 @@ var Label_QP = class extends DecoderPlugin {
|
|
|
3076
3360
|
decode(message, options = {}) {
|
|
3077
3361
|
const decodeResult = this.defaultResult();
|
|
3078
3362
|
decodeResult.decoder.name = this.name;
|
|
3079
|
-
decodeResult.raw.origin = message.text.substring(0, 4);
|
|
3080
|
-
decodeResult.raw.destination = message.text.substring(4, 8);
|
|
3081
|
-
decodeResult.raw.gate_out = message.text.substring(8, 12);
|
|
3082
|
-
decodeResult.remaining.text = message.text.substring(12);
|
|
3083
3363
|
decodeResult.formatted.description = "OUT Report";
|
|
3084
|
-
decodeResult.
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
label: "Origin",
|
|
3089
|
-
value: decodeResult.raw.origin
|
|
3090
|
-
},
|
|
3091
|
-
{
|
|
3092
|
-
type: "destination",
|
|
3093
|
-
code: "DST",
|
|
3094
|
-
label: "Destination",
|
|
3095
|
-
value: decodeResult.raw.destination
|
|
3096
|
-
},
|
|
3097
|
-
{
|
|
3098
|
-
type: "gate_out",
|
|
3099
|
-
code: "GOUT",
|
|
3100
|
-
label: "Gate OUT",
|
|
3101
|
-
value: decodeResult.raw.gate_out
|
|
3102
|
-
}
|
|
3103
|
-
];
|
|
3364
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
3365
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
3366
|
+
ResultFormatter.out(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12) + "00"));
|
|
3367
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
3104
3368
|
decodeResult.decoded = true;
|
|
3105
3369
|
if (!decodeResult.remaining.text)
|
|
3106
3370
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -3121,31 +3385,11 @@ var Label_QS = class extends DecoderPlugin {
|
|
|
3121
3385
|
decode(message, options = {}) {
|
|
3122
3386
|
const decodeResult = this.defaultResult();
|
|
3123
3387
|
decodeResult.decoder.name = this.name;
|
|
3124
|
-
decodeResult.raw.origin = message.text.substring(0, 4);
|
|
3125
|
-
decodeResult.raw.destination = message.text.substring(4, 8);
|
|
3126
|
-
decodeResult.raw.gate_in = message.text.substring(8, 12);
|
|
3127
|
-
decodeResult.remaining.text = message.text.substring(12);
|
|
3128
3388
|
decodeResult.formatted.description = "IN Report";
|
|
3129
|
-
decodeResult.
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
label: "Origin",
|
|
3134
|
-
value: decodeResult.raw.origin
|
|
3135
|
-
},
|
|
3136
|
-
{
|
|
3137
|
-
type: "destination",
|
|
3138
|
-
code: "DST",
|
|
3139
|
-
label: "Destination",
|
|
3140
|
-
value: decodeResult.raw.destination
|
|
3141
|
-
},
|
|
3142
|
-
{
|
|
3143
|
-
type: "gate_in",
|
|
3144
|
-
code: "GIN",
|
|
3145
|
-
label: "Gate IN",
|
|
3146
|
-
value: decodeResult.raw.gate_in
|
|
3147
|
-
}
|
|
3148
|
-
];
|
|
3389
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
3390
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
3391
|
+
ResultFormatter.in(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12) + "00"));
|
|
3392
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
3149
3393
|
decodeResult.decoded = true;
|
|
3150
3394
|
if (!decodeResult.remaining.text)
|
|
3151
3395
|
decodeResult.decoder.decodeLevel = "full";
|
|
@@ -3170,43 +3414,30 @@ var Label_QQ = class extends DecoderPlugin {
|
|
|
3170
3414
|
decodeResult.formatted.description = "OFF Report";
|
|
3171
3415
|
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
3172
3416
|
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
3173
|
-
decodeResult.raw.wheels_off = message.text.substring(8, 12);
|
|
3174
3417
|
if (message.text.substring(12, 19) === "\r\n001FE") {
|
|
3175
3418
|
decodeResult.raw.day_of_month = message.text.substring(19, 21);
|
|
3176
|
-
decodeResult.
|
|
3419
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(21, 27)));
|
|
3177
3420
|
let latdir = message.text.substring(27, 28);
|
|
3178
3421
|
let latdeg = Number(message.text.substring(28, 30));
|
|
3179
3422
|
let latmin = Number(message.text.substring(30, 34));
|
|
3180
3423
|
let londir = message.text.substring(34, 35);
|
|
3181
3424
|
let londeg = Number(message.text.substring(35, 38));
|
|
3182
3425
|
let lonmin = Number(message.text.substring(38, 42));
|
|
3183
|
-
|
|
3426
|
+
let pos = {
|
|
3184
3427
|
latitude: (latdeg + latmin / 60) * (latdir === "N" ? 1 : -1),
|
|
3185
3428
|
longitude: (londeg + lonmin / 60) * (londir === "E" ? 1 : -1)
|
|
3186
3429
|
};
|
|
3187
|
-
decodeResult
|
|
3430
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(42, 45));
|
|
3431
|
+
ResultFormatter.position(decodeResult, pos);
|
|
3188
3432
|
if (decodeResult.remaining.text !== "---") {
|
|
3189
|
-
ResultFormatter.groundspeed(decodeResult, message.text.substring(45, 48));
|
|
3433
|
+
ResultFormatter.groundspeed(decodeResult, Number(message.text.substring(45, 48)));
|
|
3190
3434
|
} else {
|
|
3191
3435
|
ResultFormatter.unknown(decodeResult, message.text.substring(45, 48));
|
|
3192
3436
|
}
|
|
3193
3437
|
ResultFormatter.unknown(decodeResult, message.text.substring(48));
|
|
3194
3438
|
} else {
|
|
3195
|
-
decodeResult.
|
|
3196
|
-
|
|
3197
|
-
decodeResult.formatted.items.push({
|
|
3198
|
-
type: "wheels_off",
|
|
3199
|
-
code: "WOFF",
|
|
3200
|
-
label: "Wheels OFF",
|
|
3201
|
-
value: decodeResult.raw.wheels_off
|
|
3202
|
-
});
|
|
3203
|
-
if (decodeResult.raw.position) {
|
|
3204
|
-
decodeResult.formatted.items.push({
|
|
3205
|
-
type: "aircraft_position",
|
|
3206
|
-
code: "POS",
|
|
3207
|
-
label: "Aircraft Position",
|
|
3208
|
-
value: CoordinateUtils.coordinateString(decodeResult.raw.position)
|
|
3209
|
-
});
|
|
3439
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12) + "00"));
|
|
3440
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
3210
3441
|
}
|
|
3211
3442
|
decodeResult.decoded = true;
|
|
3212
3443
|
if (!decodeResult.remaining.text)
|
|
@@ -4038,8 +4269,14 @@ var MessageDecoder = class {
|
|
|
4038
4269
|
this.registerPlugin(new Label_15(this));
|
|
4039
4270
|
this.registerPlugin(new Label_15_FST(this));
|
|
4040
4271
|
this.registerPlugin(new Label_16_N_Space(this));
|
|
4272
|
+
this.registerPlugin(new Label_1L_3Line(this));
|
|
4273
|
+
this.registerPlugin(new Label_1L_070(this));
|
|
4274
|
+
this.registerPlugin(new Label_1L_660(this));
|
|
4275
|
+
this.registerPlugin(new Label_1L_Slash(this));
|
|
4041
4276
|
this.registerPlugin(new Label_20_POS(this));
|
|
4042
4277
|
this.registerPlugin(new Label_21_POS(this));
|
|
4278
|
+
this.registerPlugin(new Label_22_OFF(this));
|
|
4279
|
+
this.registerPlugin(new Label_22_POS(this));
|
|
4043
4280
|
this.registerPlugin(new Label_24_Slash(this));
|
|
4044
4281
|
this.registerPlugin(new Label_30_Slash_EA(this));
|
|
4045
4282
|
this.registerPlugin(new Label_44_ETA(this));
|
|
@@ -4052,12 +4289,14 @@ var MessageDecoder = class {
|
|
|
4052
4289
|
this.registerPlugin(new Label_4A_DIS(this));
|
|
4053
4290
|
this.registerPlugin(new Label_4A_DOOR(this));
|
|
4054
4291
|
this.registerPlugin(new Label_4A_Slash_01(this));
|
|
4292
|
+
this.registerPlugin(new Label_4J_POS(this));
|
|
4055
4293
|
this.registerPlugin(new Label_4N(this));
|
|
4056
4294
|
this.registerPlugin(new Label_B6_Forwardslash(this));
|
|
4057
4295
|
this.registerPlugin(new Label_H1_FLR(this));
|
|
4058
4296
|
this.registerPlugin(new Label_H1_OHMA(this));
|
|
4059
4297
|
this.registerPlugin(new Label_H1_WRN(this));
|
|
4060
4298
|
this.registerPlugin(new Label_H1(this));
|
|
4299
|
+
this.registerPlugin(new Label_H1_StarPOS(this));
|
|
4061
4300
|
this.registerPlugin(new Label_HX(this));
|
|
4062
4301
|
this.registerPlugin(new Label_80(this));
|
|
4063
4302
|
this.registerPlugin(new Label_83(this));
|