@airframes/acars-decoder 1.8.2 → 1.8.4
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.d.mts +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +709 -448
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +711 -450
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -177,7 +177,6 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
177
177
|
* @returns An object with latitude and longitude properties
|
|
178
178
|
*/
|
|
179
179
|
static decodeStringCoordinates(stringCoords) {
|
|
180
|
-
var results = {};
|
|
181
180
|
const firstChar = stringCoords.substring(0, 1);
|
|
182
181
|
let middleChar = stringCoords.substring(6, 7);
|
|
183
182
|
let longitudeChars = stringCoords.substring(7, 13);
|
|
@@ -186,12 +185,12 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
186
185
|
longitudeChars = stringCoords.substring(8, 14);
|
|
187
186
|
}
|
|
188
187
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
188
|
+
return {
|
|
189
|
+
latitude: Number(stringCoords.substring(1, 6)) / 1e3 * _CoordinateUtils.getDirection(firstChar),
|
|
190
|
+
longitude: Number(longitudeChars) / 1e3 * _CoordinateUtils.getDirection(middleChar)
|
|
191
|
+
};
|
|
193
192
|
}
|
|
194
|
-
return
|
|
193
|
+
return void 0;
|
|
195
194
|
}
|
|
196
195
|
/**
|
|
197
196
|
* Decode a string of coordinates into an object with latitude and longitude in degrees and decimal minutes
|
|
@@ -200,7 +199,6 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
200
199
|
* @returns An object with latitude and longitude properties
|
|
201
200
|
*/
|
|
202
201
|
static decodeStringCoordinatesDecimalMinutes(stringCoords) {
|
|
203
|
-
var results = {};
|
|
204
202
|
const firstChar = stringCoords.substring(0, 1);
|
|
205
203
|
let middleChar = stringCoords.substring(6, 7);
|
|
206
204
|
let longitudeChars = stringCoords.substring(7, 13);
|
|
@@ -213,12 +211,12 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
213
211
|
const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
|
|
214
212
|
const lonMin = Number(longitudeChars) % 1e3 / 10;
|
|
215
213
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
214
|
+
return {
|
|
215
|
+
latitude: (latDeg + latMin / 60) * _CoordinateUtils.getDirection(firstChar),
|
|
216
|
+
longitude: (lonDeg + lonMin / 60) * _CoordinateUtils.getDirection(middleChar)
|
|
217
|
+
};
|
|
220
218
|
}
|
|
221
|
-
return
|
|
219
|
+
return void 0;
|
|
222
220
|
}
|
|
223
221
|
static coordinateString(coords) {
|
|
224
222
|
const latDir = coords.latitude > 0 ? "N" : "S";
|
|
@@ -512,6 +510,15 @@ var ResultFormatter = class {
|
|
|
512
510
|
value: decodeResult.raw.fuel_on_board.toString()
|
|
513
511
|
});
|
|
514
512
|
}
|
|
513
|
+
static burnedFuel(decodeResult, value) {
|
|
514
|
+
decodeResult.raw.fuel_burned = value;
|
|
515
|
+
decodeResult.formatted.items.push({
|
|
516
|
+
type: "fuel_burned",
|
|
517
|
+
code: "FB",
|
|
518
|
+
label: "Fuel Burned",
|
|
519
|
+
value: decodeResult.raw.fuel_burned.toString()
|
|
520
|
+
});
|
|
521
|
+
}
|
|
515
522
|
static remainingFuel(decodeResult, value) {
|
|
516
523
|
decodeResult.raw.fuel_remaining = value;
|
|
517
524
|
decodeResult.formatted.items.push({
|
|
@@ -687,6 +694,24 @@ var ResultFormatter = class {
|
|
|
687
694
|
value: text
|
|
688
695
|
});
|
|
689
696
|
}
|
|
697
|
+
static mac(decodeResult, mac) {
|
|
698
|
+
decodeResult.raw.mac = mac;
|
|
699
|
+
decodeResult.formatted.items.push({
|
|
700
|
+
type: "mac",
|
|
701
|
+
code: "MAC",
|
|
702
|
+
label: "Mean Aerodynamic Chord",
|
|
703
|
+
value: `${mac} %`
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
static trim(decodeResult, trim) {
|
|
707
|
+
decodeResult.raw.trim = trim;
|
|
708
|
+
decodeResult.formatted.items.push({
|
|
709
|
+
type: "trim",
|
|
710
|
+
code: "TRIM",
|
|
711
|
+
label: "Trim",
|
|
712
|
+
value: `${trim} units`
|
|
713
|
+
});
|
|
714
|
+
}
|
|
690
715
|
static windData(decodeResult, windData) {
|
|
691
716
|
decodeResult.raw.wind_data = windData;
|
|
692
717
|
for (const wind of windData) {
|
|
@@ -702,6 +727,64 @@ var ResultFormatter = class {
|
|
|
702
727
|
});
|
|
703
728
|
}
|
|
704
729
|
}
|
|
730
|
+
static cg(decodeResult, value, type = "center") {
|
|
731
|
+
switch (type) {
|
|
732
|
+
case "center":
|
|
733
|
+
decodeResult.raw.center_of_gravity = value;
|
|
734
|
+
decodeResult.formatted.items.push({
|
|
735
|
+
type: "center_of_gravity",
|
|
736
|
+
code: "CG",
|
|
737
|
+
label: "Center of Gravity",
|
|
738
|
+
value: `${decodeResult.raw.center_of_gravity} %`
|
|
739
|
+
});
|
|
740
|
+
break;
|
|
741
|
+
case "lower":
|
|
742
|
+
decodeResult.raw.cg_lower_limit = value;
|
|
743
|
+
decodeResult.formatted.items.push({
|
|
744
|
+
type: "cg_lower_limit",
|
|
745
|
+
code: "CG_LOWER",
|
|
746
|
+
label: "Center of Gravity Lower Limit",
|
|
747
|
+
value: `${decodeResult.raw.cg_lower_limit} %`
|
|
748
|
+
});
|
|
749
|
+
break;
|
|
750
|
+
case "upper":
|
|
751
|
+
decodeResult.raw.cg_upper_limit = value;
|
|
752
|
+
decodeResult.formatted.items.push({
|
|
753
|
+
type: "cg_upper_limit",
|
|
754
|
+
code: "CG_UPPER",
|
|
755
|
+
label: "Center of Gravity Upper Limit",
|
|
756
|
+
value: `${decodeResult.raw.cg_upper_limit} %`
|
|
757
|
+
});
|
|
758
|
+
break;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
static version(decodeResult, value) {
|
|
762
|
+
decodeResult.raw.version = value;
|
|
763
|
+
decodeResult.formatted.items.push({
|
|
764
|
+
type: "version",
|
|
765
|
+
code: "VERSION",
|
|
766
|
+
label: "Message Version",
|
|
767
|
+
value: `v${decodeResult.raw.version.toFixed(1)}`
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
static label(decodeResult, value) {
|
|
771
|
+
decodeResult.raw.label = value;
|
|
772
|
+
decodeResult.formatted.items.push({
|
|
773
|
+
type: "label",
|
|
774
|
+
code: "LABEL",
|
|
775
|
+
label: "Message Label",
|
|
776
|
+
value: `${decodeResult.raw.label}`
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
static sublabel(decodeResult, value) {
|
|
780
|
+
decodeResult.raw.sublabel = value;
|
|
781
|
+
decodeResult.formatted.items.push({
|
|
782
|
+
type: "sublabel",
|
|
783
|
+
code: "SUBLABEL",
|
|
784
|
+
label: "Message Sublabel",
|
|
785
|
+
value: `${decodeResult.raw.sublabel}`
|
|
786
|
+
});
|
|
787
|
+
}
|
|
705
788
|
static unknown(decodeResult, value, sep = ",") {
|
|
706
789
|
if (!decodeResult.remaining.text)
|
|
707
790
|
decodeResult.remaining.text = value;
|
|
@@ -1535,6 +1618,14 @@ var FlightPlanUtils = class _FlightPlanUtils {
|
|
|
1535
1618
|
label: "Route Status",
|
|
1536
1619
|
value: "Route Inactive"
|
|
1537
1620
|
});
|
|
1621
|
+
} else if (header.startsWith("RM")) {
|
|
1622
|
+
decodeResult.raw.route_status = "RM";
|
|
1623
|
+
decodeResult.formatted.items.push({
|
|
1624
|
+
type: "status",
|
|
1625
|
+
code: "ROUTE_STATUS",
|
|
1626
|
+
label: "Route Status",
|
|
1627
|
+
value: "Route Mapped"
|
|
1628
|
+
});
|
|
1538
1629
|
} else {
|
|
1539
1630
|
decodeResult.remaining.text += header;
|
|
1540
1631
|
allKnownFields = false;
|
|
@@ -1610,6 +1701,11 @@ var H1Helper = class _H1Helper {
|
|
|
1610
1701
|
static decodeH1Message(decodeResult, message) {
|
|
1611
1702
|
const checksum = message.slice(-4);
|
|
1612
1703
|
const data = message.slice(0, message.length - 4);
|
|
1704
|
+
if (calculateChecksum(data) !== checksum) {
|
|
1705
|
+
decodeResult.decoded = false;
|
|
1706
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1707
|
+
return false;
|
|
1708
|
+
}
|
|
1613
1709
|
const fields = data.split("/");
|
|
1614
1710
|
const canDecode = parseMessageType(decodeResult, fields[0]);
|
|
1615
1711
|
if (!canDecode) {
|
|
@@ -1618,53 +1714,71 @@ var H1Helper = class _H1Helper {
|
|
|
1618
1714
|
return false;
|
|
1619
1715
|
}
|
|
1620
1716
|
for (let i = 1; i < fields.length; ++i) {
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
ResultFormatter.
|
|
1656
|
-
|
|
1717
|
+
const key = fields[i].substring(0, 2);
|
|
1718
|
+
const data2 = fields[i].substring(2);
|
|
1719
|
+
switch (key) {
|
|
1720
|
+
case "AF":
|
|
1721
|
+
processAirField(decodeResult, data2.split(","));
|
|
1722
|
+
break;
|
|
1723
|
+
case "CG":
|
|
1724
|
+
processCenterOfGravity(decodeResult, data2.split(","));
|
|
1725
|
+
break;
|
|
1726
|
+
case "DC":
|
|
1727
|
+
processDateCode(decodeResult, data2.split(","));
|
|
1728
|
+
break;
|
|
1729
|
+
case "DT":
|
|
1730
|
+
processDT(decodeResult, data2.split(","));
|
|
1731
|
+
break;
|
|
1732
|
+
case "ET":
|
|
1733
|
+
processETA(data2, decodeResult, fields, i);
|
|
1734
|
+
break;
|
|
1735
|
+
case "FB":
|
|
1736
|
+
ResultFormatter.currentFuel(decodeResult, parseInt(data2, 10));
|
|
1737
|
+
break;
|
|
1738
|
+
case "FN":
|
|
1739
|
+
decodeResult.raw.flight_number = data2;
|
|
1740
|
+
break;
|
|
1741
|
+
case "FX":
|
|
1742
|
+
ResultFormatter.freetext(decodeResult, data2);
|
|
1743
|
+
break;
|
|
1744
|
+
case "ID":
|
|
1745
|
+
processIdentification(decodeResult, data2.split(","));
|
|
1746
|
+
break;
|
|
1747
|
+
case "LR":
|
|
1748
|
+
processLandingReport(decodeResult, data2.split(","));
|
|
1749
|
+
break;
|
|
1750
|
+
case "PR":
|
|
1751
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
1752
|
+
break;
|
|
1753
|
+
case "PS":
|
|
1754
|
+
_H1Helper.processPS(decodeResult, data2.split(","));
|
|
1755
|
+
break;
|
|
1756
|
+
case "RF":
|
|
1757
|
+
case "RI":
|
|
1758
|
+
case "RM":
|
|
1759
|
+
case "RP":
|
|
1760
|
+
FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
|
|
1761
|
+
break;
|
|
1762
|
+
case "SN":
|
|
1763
|
+
decodeResult.raw.serial_number = data2;
|
|
1764
|
+
break;
|
|
1765
|
+
case "TD":
|
|
1766
|
+
processTimeOfDeparture(decodeResult, data2.split(","));
|
|
1767
|
+
break;
|
|
1768
|
+
case "TS":
|
|
1769
|
+
_H1Helper.processTimeStamp(decodeResult, data2.split(","));
|
|
1770
|
+
break;
|
|
1771
|
+
case "VR":
|
|
1772
|
+
ResultFormatter.version(decodeResult, parseInt(data2, 10) / 10);
|
|
1773
|
+
break;
|
|
1774
|
+
case "WD":
|
|
1775
|
+
processWindData(decodeResult, data2);
|
|
1776
|
+
break;
|
|
1777
|
+
default:
|
|
1657
1778
|
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
1658
|
-
}
|
|
1659
|
-
} else if (fields[i].startsWith("WD")) {
|
|
1660
|
-
processWindData(decodeResult, fields[i].substring(2));
|
|
1661
|
-
} else {
|
|
1662
|
-
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
1663
1779
|
}
|
|
1664
1780
|
}
|
|
1665
|
-
|
|
1666
|
-
ResultFormatter.checksum(decodeResult, checksum);
|
|
1667
|
-
}
|
|
1781
|
+
ResultFormatter.checksum(decodeResult, checksum);
|
|
1668
1782
|
return true;
|
|
1669
1783
|
}
|
|
1670
1784
|
static processPS(decodeResult, data) {
|
|
@@ -1708,16 +1822,26 @@ var H1Helper = class _H1Helper {
|
|
|
1708
1822
|
ResultFormatter.unknownArr(decodeResult, data.slice(10));
|
|
1709
1823
|
}
|
|
1710
1824
|
}
|
|
1711
|
-
static
|
|
1825
|
+
static processTimeStamp(decodeResult, data) {
|
|
1712
1826
|
let time = DateTimeUtils.convertDateTimeToEpoch(data[0], data[1]);
|
|
1713
1827
|
if (Number.isNaN(time)) {
|
|
1714
1828
|
const date = data[1].substring(2, 4) + data[1].substring(0, 2) + data[1].substring(4, 6);
|
|
1715
1829
|
time = DateTimeUtils.convertDateTimeToEpoch(data[0], date);
|
|
1716
1830
|
}
|
|
1717
|
-
decodeResult.raw.message_date = data[1];
|
|
1718
1831
|
decodeResult.raw.message_timestamp = time;
|
|
1719
1832
|
}
|
|
1720
1833
|
};
|
|
1834
|
+
function processETA(data, decodeResult, fields, i) {
|
|
1835
|
+
if (data.length === 5) {
|
|
1836
|
+
ResultFormatter.day(decodeResult, Number(data.substring(0, 1)));
|
|
1837
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data.substring(1)));
|
|
1838
|
+
} else if (data.length === 6) {
|
|
1839
|
+
ResultFormatter.day(decodeResult, Number(data.substring(0, 2)));
|
|
1840
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data.substring(2)));
|
|
1841
|
+
} else {
|
|
1842
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1721
1845
|
function processAirField(decodeResult, data) {
|
|
1722
1846
|
if (data.length === 2) {
|
|
1723
1847
|
ResultFormatter.departureAirport(decodeResult, data[0]);
|
|
@@ -1777,7 +1901,7 @@ function processDT(decodeResult, data) {
|
|
|
1777
1901
|
ResultFormatter.unknownArr(decodeResult, data);
|
|
1778
1902
|
}
|
|
1779
1903
|
}
|
|
1780
|
-
function
|
|
1904
|
+
function processLandingReport(decodeResult, data) {
|
|
1781
1905
|
if (data.length === 19) {
|
|
1782
1906
|
ResultFormatter.unknown(decodeResult, data[1]);
|
|
1783
1907
|
ResultFormatter.flightNumber(decodeResult, data[2]);
|
|
@@ -1789,35 +1913,37 @@ function processLR(decodeResult, data) {
|
|
|
1789
1913
|
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
1790
1914
|
}
|
|
1791
1915
|
}
|
|
1792
|
-
function
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
if (parts[0].length > 0) {
|
|
1808
|
-
ResultFormatter.unknown(decodeResult, parts[0].substring(0, 4));
|
|
1809
|
-
ResultFormatter.flightNumber(decodeResult, parts[0].substring(4));
|
|
1810
|
-
ResultFormatter.unknown(decodeResult, parts[1].length == 5 ? parts[1].substring(0, 2) : parts[1].substring(0, 3), "#");
|
|
1811
|
-
}
|
|
1812
|
-
const type = parts[1].length == 5 ? parts[1].substring(2, 5) : parts[1].substring(3, 6);
|
|
1813
|
-
if (parts[1].substring(3, 6) === "POS" && parts[1].length > 6) {
|
|
1814
|
-
H1Helper.processPosition(decodeResult, parts[1].substring(6).split(","));
|
|
1815
|
-
}
|
|
1816
|
-
return processMessageType(decodeResult, type);
|
|
1916
|
+
function processCenterOfGravity(decodeResult, data) {
|
|
1917
|
+
if (data.length === 1) {
|
|
1918
|
+
if (data[0] !== void 0 && data[0] !== "") {
|
|
1919
|
+
ResultFormatter.cg(decodeResult, parseInt(data[0], 10) / 10);
|
|
1920
|
+
}
|
|
1921
|
+
} else if (data.length === 3) {
|
|
1922
|
+
if (data[0] !== void 0 && data[0] !== "") {
|
|
1923
|
+
ResultFormatter.cg(decodeResult, parseInt(data[0], 10) / 10, "center");
|
|
1924
|
+
}
|
|
1925
|
+
if (data[1] !== void 0 && data[1] !== "") {
|
|
1926
|
+
ResultFormatter.cg(decodeResult, parseInt(data[1], 10) / 10, "lower");
|
|
1927
|
+
}
|
|
1928
|
+
if (data[2] !== void 0 && data[2] !== "") {
|
|
1929
|
+
ResultFormatter.cg(decodeResult, parseInt(data[2], 10) / 10, "upper");
|
|
1930
|
+
}
|
|
1817
1931
|
} else {
|
|
1818
|
-
ResultFormatter.unknown(decodeResult,
|
|
1819
|
-
|
|
1932
|
+
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
function parseMessageType(decodeResult, messageType) {
|
|
1936
|
+
if (messageType.startsWith("POS")) {
|
|
1937
|
+
H1Helper.processPosition(decodeResult, messageType.substring(3).split(","));
|
|
1938
|
+
return processMessageType(decodeResult, "POS");
|
|
1939
|
+
} else if (messageType.length === 13) {
|
|
1940
|
+
if (processMessageType(decodeResult, messageType.substring(10))) {
|
|
1941
|
+
ResultFormatter.unknown(decodeResult, messageType.substring(0, 4));
|
|
1942
|
+
ResultFormatter.flightNumber(decodeResult, messageType.slice(4, 10));
|
|
1943
|
+
return true;
|
|
1944
|
+
}
|
|
1820
1945
|
}
|
|
1946
|
+
return processMessageType(decodeResult, messageType.substring(0, 3));
|
|
1821
1947
|
}
|
|
1822
1948
|
function processMessageType(decodeResult, type) {
|
|
1823
1949
|
if (type === "FPN") {
|
|
@@ -1826,19 +1952,21 @@ function processMessageType(decodeResult, type) {
|
|
|
1826
1952
|
decodeResult.formatted.description = "Free Text";
|
|
1827
1953
|
} else if (type === "INI") {
|
|
1828
1954
|
decodeResult.formatted.description = "Flight Plan Initial Report";
|
|
1955
|
+
} else if (type === "PER") {
|
|
1956
|
+
decodeResult.formatted.description = "Performance Report";
|
|
1829
1957
|
} else if (type === "POS") {
|
|
1830
1958
|
decodeResult.formatted.description = "Position Report";
|
|
1831
1959
|
} else if (type === "PRG") {
|
|
1832
1960
|
decodeResult.formatted.description = "Progress Report";
|
|
1833
1961
|
} else if (type === "PWI") {
|
|
1834
|
-
decodeResult.formatted.description = "Weather
|
|
1962
|
+
decodeResult.formatted.description = "Pilot Weather Information";
|
|
1835
1963
|
} else {
|
|
1836
1964
|
decodeResult.formatted.description = "Unknown H1 Message";
|
|
1837
1965
|
return false;
|
|
1838
1966
|
}
|
|
1839
1967
|
return true;
|
|
1840
1968
|
}
|
|
1841
|
-
function
|
|
1969
|
+
function processDateCode(decodeResult, data) {
|
|
1842
1970
|
decodeResult.raw.message_date = data[0];
|
|
1843
1971
|
if (data.length === 1) {
|
|
1844
1972
|
} else if (data.length === 2) {
|
|
@@ -1903,6 +2031,26 @@ function processWindData(decodeResult, message) {
|
|
|
1903
2031
|
});
|
|
1904
2032
|
ResultFormatter.windData(decodeResult, wind);
|
|
1905
2033
|
}
|
|
2034
|
+
function calculateChecksum(data) {
|
|
2035
|
+
let crc = 65535;
|
|
2036
|
+
const bytes = Buffer.from(data, "ascii");
|
|
2037
|
+
for (const byte of bytes) {
|
|
2038
|
+
crc ^= byte;
|
|
2039
|
+
for (let i = 0; i < 8; i++) {
|
|
2040
|
+
if ((crc & 1) !== 0) {
|
|
2041
|
+
crc = crc >>> 1 ^ 33800;
|
|
2042
|
+
} else {
|
|
2043
|
+
crc = crc >>> 1;
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
crc = (crc ^ 65535) & 65535;
|
|
2048
|
+
const nibble1 = crc >> 12 & 15;
|
|
2049
|
+
const nibble2 = crc >> 8 & 15;
|
|
2050
|
+
const nibble3 = crc >> 4 & 15;
|
|
2051
|
+
const nibble4 = crc & 15;
|
|
2052
|
+
return `${nibble4.toString(16)}${nibble3.toString(16)}${nibble2.toString(16)}${nibble1.toString(16)}`.toUpperCase();
|
|
2053
|
+
}
|
|
1906
2054
|
|
|
1907
2055
|
// lib/plugins/Label_1J_2J_FTX.ts
|
|
1908
2056
|
var Label_1J_2J_FTX = class extends DecoderPlugin {
|
|
@@ -1917,7 +2065,14 @@ var Label_1J_2J_FTX = class extends DecoderPlugin {
|
|
|
1917
2065
|
decodeResult.decoder.name = this.name;
|
|
1918
2066
|
decodeResult.message = message;
|
|
1919
2067
|
const msg = message.text.replace(/\n|\r/g, "");
|
|
1920
|
-
const
|
|
2068
|
+
const parts = msg.split("/");
|
|
2069
|
+
let decoded = false;
|
|
2070
|
+
if (parts[0].length > 3) {
|
|
2071
|
+
decoded = H1Helper.decodeH1Message(decodeResult, msg.slice(parts[0].length - 3));
|
|
2072
|
+
decodeResult.remaining.text = parts[0].slice(0, 3) + "/" + decodeResult.remaining.text;
|
|
2073
|
+
} else {
|
|
2074
|
+
decoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
2075
|
+
}
|
|
1921
2076
|
decodeResult.decoded = decoded;
|
|
1922
2077
|
decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
|
|
1923
2078
|
if (decodeResult.formatted.items.length === 0) {
|
|
@@ -2462,7 +2617,6 @@ var Label_2P_FM3 = class extends DecoderPlugin {
|
|
|
2462
2617
|
ResultFormatter.unknown(decodeResult, header[0].substring(0, 4));
|
|
2463
2618
|
ResultFormatter.flightNumber(decodeResult, header[0].substring(4));
|
|
2464
2619
|
}
|
|
2465
|
-
console.log(header[1]);
|
|
2466
2620
|
if (header[1].length === 4) {
|
|
2467
2621
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(header[1]));
|
|
2468
2622
|
} else {
|
|
@@ -2606,7 +2760,14 @@ var Label_2P_POS = class extends DecoderPlugin {
|
|
|
2606
2760
|
decodeResult.decoder.name = this.name;
|
|
2607
2761
|
decodeResult.message = message;
|
|
2608
2762
|
const msg = message.text.replace(/\n|\r/g, "");
|
|
2609
|
-
const
|
|
2763
|
+
const parts = msg.split("/");
|
|
2764
|
+
let decoded = false;
|
|
2765
|
+
if (parts[0].length > 3) {
|
|
2766
|
+
decoded = H1Helper.decodeH1Message(decodeResult, msg.slice(parts[0].length - 3));
|
|
2767
|
+
decodeResult.remaining.text = parts[0].slice(0, 3) + "/" + decodeResult.remaining.text;
|
|
2768
|
+
} else {
|
|
2769
|
+
decoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
2770
|
+
}
|
|
2610
2771
|
decodeResult.decoded = decoded;
|
|
2611
2772
|
decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
|
|
2612
2773
|
if (decodeResult.formatted.items.length === 0) {
|
|
@@ -3739,7 +3900,18 @@ var Label_H1 = class extends DecoderPlugin {
|
|
|
3739
3900
|
decodeResult.decoder.name = this.name;
|
|
3740
3901
|
decodeResult.message = message;
|
|
3741
3902
|
const msg = message.text.replace(/\n|\r/g, "");
|
|
3742
|
-
const
|
|
3903
|
+
const parts = msg.split("#");
|
|
3904
|
+
let decoded = false;
|
|
3905
|
+
if (parts.length === 1) {
|
|
3906
|
+
decoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
3907
|
+
} else if (parts.length == 2) {
|
|
3908
|
+
const offset = isNaN(parseInt(parts[1][1])) ? 3 : 4;
|
|
3909
|
+
decoded = H1Helper.decodeH1Message(decodeResult, msg.slice(parts[0].length + offset));
|
|
3910
|
+
if (decoded && parts[0].length > 0) {
|
|
3911
|
+
ResultFormatter.flightNumber(decodeResult, parts[0].substring(4));
|
|
3912
|
+
decodeResult.remaining.text = parts[0].substring(0, 4) + "#" + parts[1].substring(0, offset - 1) + "/" + decodeResult.remaining.text;
|
|
3913
|
+
}
|
|
3914
|
+
}
|
|
3743
3915
|
decodeResult.decoded = decoded;
|
|
3744
3916
|
decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
|
|
3745
3917
|
if (decodeResult.formatted.items.length === 0) {
|
|
@@ -3909,11 +4081,11 @@ var Label_H1_OHMA = class extends DecoderPlugin {
|
|
|
3909
4081
|
const data = message.text.split("OHMA")[1];
|
|
3910
4082
|
try {
|
|
3911
4083
|
const compressedBuffer = import_node_buffer.Buffer.from(data, "base64");
|
|
3912
|
-
const decompress = new zlib.Inflate({
|
|
4084
|
+
const decompress = new zlib.Inflate({});
|
|
3913
4085
|
decompress.write(compressedBuffer);
|
|
3914
4086
|
decompress.flush(zlib.constants.Z_SYNC_FLUSH);
|
|
3915
4087
|
const result = decompress.read();
|
|
3916
|
-
const jsonText = result
|
|
4088
|
+
const jsonText = result?.toString() || "";
|
|
3917
4089
|
let formattedMsg;
|
|
3918
4090
|
let jsonMessage;
|
|
3919
4091
|
try {
|
|
@@ -3984,7 +4156,7 @@ var Label_H1_Slash = class extends DecoderPlugin {
|
|
|
3984
4156
|
for (let i = 2; i < fields.length; i++) {
|
|
3985
4157
|
const field = fields[i];
|
|
3986
4158
|
if (field.startsWith("TS")) {
|
|
3987
|
-
H1Helper.
|
|
4159
|
+
H1Helper.processTimeStamp(decodeResult, field.substring(2, 15).split(","));
|
|
3988
4160
|
} else if (field.startsWith("PS")) {
|
|
3989
4161
|
H1Helper.processPS(decodeResult, field.substring(2).split(","));
|
|
3990
4162
|
} else {
|
|
@@ -4139,332 +4311,147 @@ var Label_HX = class extends DecoderPlugin {
|
|
|
4139
4311
|
}
|
|
4140
4312
|
};
|
|
4141
4313
|
|
|
4142
|
-
// lib/
|
|
4143
|
-
var
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4314
|
+
// lib/utils/miam.ts
|
|
4315
|
+
var Base85 = __toESM(require("base85"));
|
|
4316
|
+
var zlib2 = __toESM(require("minizlib"));
|
|
4317
|
+
var import_node_buffer2 = require("buffer");
|
|
4318
|
+
var MIAMVersion = /* @__PURE__ */ ((MIAMVersion2) => {
|
|
4319
|
+
MIAMVersion2[MIAMVersion2["V1"] = 1] = "V1";
|
|
4320
|
+
MIAMVersion2[MIAMVersion2["V2"] = 2] = "V2";
|
|
4321
|
+
return MIAMVersion2;
|
|
4322
|
+
})(MIAMVersion || {});
|
|
4323
|
+
var MIAMFid = /* @__PURE__ */ ((MIAMFid2) => {
|
|
4324
|
+
MIAMFid2["SingleTransfer"] = "T";
|
|
4325
|
+
MIAMFid2["FileTransferRequest"] = "F";
|
|
4326
|
+
MIAMFid2["FileTransferAccept"] = "K";
|
|
4327
|
+
MIAMFid2["FileSegment"] = "S";
|
|
4328
|
+
MIAMFid2["FileTransferAbort"] = "A";
|
|
4329
|
+
MIAMFid2["XOFFIndication"] = "Y";
|
|
4330
|
+
MIAMFid2["XONIndication"] = "X";
|
|
4331
|
+
return MIAMFid2;
|
|
4332
|
+
})(MIAMFid || {});
|
|
4333
|
+
var MIAMCorePdu = /* @__PURE__ */ ((MIAMCorePdu2) => {
|
|
4334
|
+
MIAMCorePdu2[MIAMCorePdu2["Data"] = 0] = "Data";
|
|
4335
|
+
MIAMCorePdu2[MIAMCorePdu2["Ack"] = 1] = "Ack";
|
|
4336
|
+
MIAMCorePdu2[MIAMCorePdu2["Aloha"] = 2] = "Aloha";
|
|
4337
|
+
MIAMCorePdu2[MIAMCorePdu2["AlohaReply"] = 3] = "AlohaReply";
|
|
4338
|
+
return MIAMCorePdu2;
|
|
4339
|
+
})(MIAMCorePdu || {});
|
|
4340
|
+
var MIAMCoreApp = /* @__PURE__ */ ((MIAMCoreApp2) => {
|
|
4341
|
+
MIAMCoreApp2[MIAMCoreApp2["ACARS2Char"] = 0] = "ACARS2Char";
|
|
4342
|
+
MIAMCoreApp2[MIAMCoreApp2["ACARS4Char"] = 1] = "ACARS4Char";
|
|
4343
|
+
MIAMCoreApp2[MIAMCoreApp2["ACARS6Char"] = 2] = "ACARS6Char";
|
|
4344
|
+
MIAMCoreApp2[MIAMCoreApp2["NonACARS6Char"] = 3] = "NonACARS6Char";
|
|
4345
|
+
return MIAMCoreApp2;
|
|
4346
|
+
})(MIAMCoreApp || {});
|
|
4347
|
+
var MIAMCoreV1CRCLength = 4;
|
|
4348
|
+
var MIAMCoreV2CRCLength = 2;
|
|
4349
|
+
var isMIAMVersion = (x) => Object.values(MIAMVersion).includes(x);
|
|
4350
|
+
var isMIAMFid = (x) => Object.values(MIAMFid).includes(x);
|
|
4351
|
+
var isMIAMCoreApp = (x) => Object.values(MIAMCoreApp).includes(x);
|
|
4352
|
+
var isMIAMCorePdu = (x) => Object.values(MIAMCorePdu).includes(x);
|
|
4353
|
+
var MIAMCoreUtils = class {
|
|
4354
|
+
static AppTypeToAppIdLenTable = {
|
|
4355
|
+
[1 /* V1 */]: {
|
|
4356
|
+
[0 /* ACARS2Char */]: 2,
|
|
4357
|
+
[1 /* ACARS4Char */]: 4,
|
|
4358
|
+
[2 /* ACARS6Char */]: 6,
|
|
4359
|
+
[3 /* NonACARS6Char */]: 6
|
|
4360
|
+
},
|
|
4361
|
+
[2 /* V2 */]: {
|
|
4362
|
+
[0 /* ACARS2Char */]: 2,
|
|
4363
|
+
[1 /* ACARS4Char */]: 4,
|
|
4364
|
+
[2 /* ACARS6Char */]: 6,
|
|
4365
|
+
[3 /* NonACARS6Char */]: 6
|
|
4366
|
+
}
|
|
4367
|
+
};
|
|
4368
|
+
static FidHandlerTable = {
|
|
4369
|
+
["T" /* SingleTransfer */]: (txt) => {
|
|
4370
|
+
if (txt.length < 3) {
|
|
4371
|
+
return {
|
|
4372
|
+
decoded: false,
|
|
4373
|
+
error: "Raw MIAM message too short (" + txt.length + " < 3) "
|
|
4168
4374
|
};
|
|
4169
|
-
decodeResult.raw.vdlFrequency = Number(result.groups.vfreq) / 1e3;
|
|
4170
4375
|
}
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
formattedNetwork = "SITA";
|
|
4178
|
-
}
|
|
4179
|
-
decodeResult.formatted.items = [
|
|
4180
|
-
{
|
|
4181
|
-
type: "network",
|
|
4182
|
-
code: "NETT",
|
|
4183
|
-
label: "Network",
|
|
4184
|
-
value: formattedNetwork
|
|
4185
|
-
},
|
|
4186
|
-
{
|
|
4187
|
-
type: "version",
|
|
4188
|
-
code: "VER",
|
|
4189
|
-
label: "Version",
|
|
4190
|
-
value: decodeResult.raw.version
|
|
4376
|
+
let bpad = txt[0];
|
|
4377
|
+
if ("0123-.".indexOf(bpad) === -1) {
|
|
4378
|
+
return {
|
|
4379
|
+
decoded: false,
|
|
4380
|
+
error: "Invalid body padding value: '" + bpad + "'"
|
|
4381
|
+
};
|
|
4191
4382
|
}
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
code: "GNDSTN",
|
|
4198
|
-
label: "Ground Station",
|
|
4199
|
-
value: `${decodeResult.raw.groundStation.icaoCode}${decodeResult.raw.groundStation.number}`
|
|
4200
|
-
});
|
|
4383
|
+
if ("0123".indexOf(txt[1]) === -1) {
|
|
4384
|
+
return {
|
|
4385
|
+
decoded: false,
|
|
4386
|
+
error: "Invalid header padding value: '" + txt[1] + "'"
|
|
4387
|
+
};
|
|
4201
4388
|
}
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
}
|
|
4389
|
+
const hpad = parseInt(txt[1]);
|
|
4390
|
+
const delimIdx = txt.indexOf("|");
|
|
4391
|
+
if (delimIdx === -1) {
|
|
4392
|
+
return {
|
|
4393
|
+
decoded: false,
|
|
4394
|
+
error: "Raw MIAM message missing header-body delimiter"
|
|
4395
|
+
};
|
|
4209
4396
|
}
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
});
|
|
4397
|
+
const rawHdr = txt.substring(2, delimIdx);
|
|
4398
|
+
if (rawHdr.length === 0) {
|
|
4399
|
+
return {
|
|
4400
|
+
decoded: false,
|
|
4401
|
+
error: "Empty MIAM message header"
|
|
4402
|
+
};
|
|
4217
4403
|
}
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
});
|
|
4404
|
+
let hdr = Base85.decode("<~" + rawHdr + "~>", "ascii85");
|
|
4405
|
+
if (!hdr || hdr.length < hpad) {
|
|
4406
|
+
return {
|
|
4407
|
+
decoded: false,
|
|
4408
|
+
error: "Ascii85 decode failed for MIAM message header"
|
|
4409
|
+
};
|
|
4225
4410
|
}
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
code: "VDLFRQ",
|
|
4239
|
-
label: "VDL Frequency",
|
|
4240
|
-
value: `${decodeResult.raw.vdlFrequency} MHz`
|
|
4241
|
-
});
|
|
4242
|
-
}
|
|
4243
|
-
decodeResult.decoded = true;
|
|
4244
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4245
|
-
return decodeResult;
|
|
4246
|
-
}
|
|
4247
|
-
};
|
|
4248
|
-
|
|
4249
|
-
// lib/plugins/Label_QR.ts
|
|
4250
|
-
var Label_QR = class extends DecoderPlugin {
|
|
4251
|
-
name = "label-qr";
|
|
4252
|
-
qualifiers() {
|
|
4253
|
-
return {
|
|
4254
|
-
labels: ["QR"]
|
|
4255
|
-
};
|
|
4256
|
-
}
|
|
4257
|
-
decode(message, options = {}) {
|
|
4258
|
-
const decodeResult = this.defaultResult();
|
|
4259
|
-
decodeResult.decoder.name = this.name;
|
|
4260
|
-
decodeResult.formatted.description = "ON Report";
|
|
4261
|
-
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
4262
|
-
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
4263
|
-
ResultFormatter.on(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12)));
|
|
4264
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
4265
|
-
decodeResult.decoded = true;
|
|
4266
|
-
if (!decodeResult.remaining.text)
|
|
4267
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4268
|
-
else
|
|
4269
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
4270
|
-
return decodeResult;
|
|
4271
|
-
}
|
|
4272
|
-
};
|
|
4273
|
-
|
|
4274
|
-
// lib/plugins/Label_QP.ts
|
|
4275
|
-
var Label_QP = class extends DecoderPlugin {
|
|
4276
|
-
name = "label-qp";
|
|
4277
|
-
qualifiers() {
|
|
4278
|
-
return {
|
|
4279
|
-
labels: ["QP"]
|
|
4280
|
-
};
|
|
4281
|
-
}
|
|
4282
|
-
decode(message, options = {}) {
|
|
4283
|
-
const decodeResult = this.defaultResult();
|
|
4284
|
-
decodeResult.decoder.name = this.name;
|
|
4285
|
-
decodeResult.formatted.description = "OUT Report";
|
|
4286
|
-
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
4287
|
-
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
4288
|
-
ResultFormatter.out(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12)));
|
|
4289
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
4290
|
-
decodeResult.decoded = true;
|
|
4291
|
-
if (!decodeResult.remaining.text)
|
|
4292
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4293
|
-
else
|
|
4294
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
4295
|
-
return decodeResult;
|
|
4296
|
-
}
|
|
4297
|
-
};
|
|
4298
|
-
|
|
4299
|
-
// lib/plugins/Label_QS.ts
|
|
4300
|
-
var Label_QS = class extends DecoderPlugin {
|
|
4301
|
-
name = "label-qs";
|
|
4302
|
-
qualifiers() {
|
|
4303
|
-
return {
|
|
4304
|
-
labels: ["QS"]
|
|
4305
|
-
};
|
|
4306
|
-
}
|
|
4307
|
-
decode(message, options = {}) {
|
|
4308
|
-
const decodeResult = this.defaultResult();
|
|
4309
|
-
decodeResult.decoder.name = this.name;
|
|
4310
|
-
decodeResult.formatted.description = "IN Report";
|
|
4311
|
-
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
4312
|
-
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
4313
|
-
ResultFormatter.in(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12)));
|
|
4314
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
4315
|
-
decodeResult.decoded = true;
|
|
4316
|
-
if (!decodeResult.remaining.text)
|
|
4317
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4318
|
-
else
|
|
4319
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
4320
|
-
return decodeResult;
|
|
4321
|
-
}
|
|
4322
|
-
};
|
|
4323
|
-
|
|
4324
|
-
// lib/plugins/Label_QQ.ts
|
|
4325
|
-
var Label_QQ = class extends DecoderPlugin {
|
|
4326
|
-
name = "label-qq";
|
|
4327
|
-
qualifiers() {
|
|
4328
|
-
return {
|
|
4329
|
-
labels: ["QQ"]
|
|
4330
|
-
};
|
|
4331
|
-
}
|
|
4332
|
-
decode(message, options = {}) {
|
|
4333
|
-
const decodeResult = this.defaultResult();
|
|
4334
|
-
decodeResult.decoder.name = this.name;
|
|
4335
|
-
decodeResult.message = message;
|
|
4336
|
-
decodeResult.formatted.description = "OFF Report";
|
|
4337
|
-
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
4338
|
-
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
4339
|
-
if (message.text.substring(12, 19) === "\r\n001FE") {
|
|
4340
|
-
decodeResult.raw.day = message.text.substring(19, 21);
|
|
4341
|
-
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(21, 27)));
|
|
4342
|
-
let latdir = message.text.substring(27, 28);
|
|
4343
|
-
let latdeg = Number(message.text.substring(28, 30));
|
|
4344
|
-
let latmin = Number(message.text.substring(30, 34));
|
|
4345
|
-
let londir = message.text.substring(34, 35);
|
|
4346
|
-
let londeg = Number(message.text.substring(35, 38));
|
|
4347
|
-
let lonmin = Number(message.text.substring(38, 42));
|
|
4348
|
-
let pos = {
|
|
4349
|
-
latitude: (latdeg + latmin / 60) * (latdir === "N" ? 1 : -1),
|
|
4350
|
-
longitude: (londeg + lonmin / 60) * (londir === "E" ? 1 : -1)
|
|
4351
|
-
};
|
|
4352
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(42, 45));
|
|
4353
|
-
ResultFormatter.position(decodeResult, pos);
|
|
4354
|
-
if (decodeResult.remaining.text !== "---") {
|
|
4355
|
-
ResultFormatter.groundspeed(decodeResult, Number(message.text.substring(45, 48)));
|
|
4356
|
-
} else {
|
|
4357
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(45, 48));
|
|
4358
|
-
}
|
|
4359
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(48));
|
|
4360
|
-
} else {
|
|
4361
|
-
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12) + "00"));
|
|
4362
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
4363
|
-
}
|
|
4364
|
-
decodeResult.decoded = true;
|
|
4365
|
-
if (!decodeResult.remaining.text)
|
|
4366
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4367
|
-
else
|
|
4368
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
4369
|
-
return decodeResult;
|
|
4370
|
-
}
|
|
4371
|
-
};
|
|
4372
|
-
|
|
4373
|
-
// lib/utils/miam.ts
|
|
4374
|
-
var Base85 = __toESM(require("base85"));
|
|
4375
|
-
var zlib2 = __toESM(require("minizlib"));
|
|
4376
|
-
var import_node_buffer2 = require("buffer");
|
|
4377
|
-
var MIAMCoreV1CRCLength = 4;
|
|
4378
|
-
var MIAMCoreV2CRCLength = 2;
|
|
4379
|
-
var MIAMCoreUtils = class {
|
|
4380
|
-
static AppTypeToAppIdLenTable = {
|
|
4381
|
-
1: {
|
|
4382
|
-
[0 /* ACARS2Char */]: 2,
|
|
4383
|
-
[1 /* ACARS4Char */]: 4,
|
|
4384
|
-
[2 /* ACARS6Char */]: 6,
|
|
4385
|
-
[3 /* NonACARS6Char */]: 6
|
|
4386
|
-
},
|
|
4387
|
-
2: {
|
|
4388
|
-
[0 /* ACARS2Char */]: 2,
|
|
4389
|
-
[1 /* ACARS4Char */]: 4,
|
|
4390
|
-
[2 /* ACARS6Char */]: 6,
|
|
4391
|
-
[3 /* NonACARS6Char */]: 6
|
|
4392
|
-
}
|
|
4393
|
-
};
|
|
4394
|
-
static FidHandlerTable = {
|
|
4395
|
-
["T" /* SingleTransfer */]: (txt) => {
|
|
4396
|
-
if (txt.length < 3) {
|
|
4397
|
-
return {
|
|
4398
|
-
decoded: false,
|
|
4399
|
-
error: "Raw MIAM message too short (" + txt.length + " < 3) "
|
|
4400
|
-
};
|
|
4401
|
-
}
|
|
4402
|
-
let bpad = txt[0];
|
|
4403
|
-
if ("0123-.".indexOf(bpad) === -1) {
|
|
4404
|
-
return {
|
|
4405
|
-
decoded: false,
|
|
4406
|
-
error: "Invalid body padding value: '" + bpad + "'"
|
|
4407
|
-
};
|
|
4408
|
-
}
|
|
4409
|
-
if ("0123".indexOf(txt[1]) === -1) {
|
|
4410
|
-
return {
|
|
4411
|
-
decoded: false,
|
|
4412
|
-
error: "Invalid header padding value: '" + txt[1] + "'"
|
|
4413
|
-
};
|
|
4414
|
-
}
|
|
4415
|
-
const hpad = parseInt(txt[1]);
|
|
4416
|
-
const delimIdx = txt.indexOf("|");
|
|
4417
|
-
if (delimIdx === -1) {
|
|
4418
|
-
return {
|
|
4419
|
-
decoded: false,
|
|
4420
|
-
error: "Raw MIAM message missing header-body delimiter"
|
|
4421
|
-
};
|
|
4422
|
-
}
|
|
4423
|
-
const rawHdr = txt.substring(2, delimIdx);
|
|
4424
|
-
if (rawHdr.length === 0) {
|
|
4425
|
-
return {
|
|
4426
|
-
decoded: false,
|
|
4427
|
-
error: "Empty MIAM message header"
|
|
4428
|
-
};
|
|
4429
|
-
}
|
|
4430
|
-
let hdr = Base85.decode("<~" + rawHdr + "~>", "ascii85");
|
|
4431
|
-
if (!hdr || hdr.length < hpad) {
|
|
4432
|
-
return {
|
|
4433
|
-
decoded: false,
|
|
4434
|
-
error: "Ascii85 decode failed for MIAM message header"
|
|
4435
|
-
};
|
|
4436
|
-
}
|
|
4437
|
-
let body = void 0;
|
|
4438
|
-
const rawBody = txt.substring(delimIdx + 1);
|
|
4439
|
-
if (rawBody.length > 0) {
|
|
4440
|
-
if ("0123".indexOf(bpad) >= 0) {
|
|
4441
|
-
const bpadValue = parseInt(bpad);
|
|
4442
|
-
body = Base85.decode("<~" + rawBody + "~>", "ascii85") || void 0;
|
|
4443
|
-
if (body && body.length >= bpadValue) {
|
|
4444
|
-
body = body.subarray(0, body.length - bpadValue);
|
|
4445
|
-
}
|
|
4446
|
-
} else if (bpad === "-") {
|
|
4447
|
-
body = import_node_buffer2.Buffer.from(rawBody);
|
|
4448
|
-
}
|
|
4411
|
+
let body = void 0;
|
|
4412
|
+
const rawBody = txt.substring(delimIdx + 1);
|
|
4413
|
+
if (rawBody.length > 0) {
|
|
4414
|
+
if ("0123".indexOf(bpad) >= 0) {
|
|
4415
|
+
const bpadValue = parseInt(bpad);
|
|
4416
|
+
body = Base85.decode("<~" + rawBody + "~>", "ascii85") || void 0;
|
|
4417
|
+
if (body && body.length >= bpadValue) {
|
|
4418
|
+
body = body.subarray(0, body.length - bpadValue);
|
|
4419
|
+
}
|
|
4420
|
+
} else if (bpad === "-") {
|
|
4421
|
+
body = import_node_buffer2.Buffer.from(rawBody);
|
|
4422
|
+
}
|
|
4449
4423
|
}
|
|
4450
4424
|
hdr = hdr.subarray(0, hdr.length - hpad);
|
|
4451
4425
|
const version = hdr.readUInt8(0) & 15;
|
|
4452
4426
|
const pduType = hdr.readUInt8(0) >> 4 & 15;
|
|
4453
|
-
|
|
4454
|
-
|
|
4427
|
+
if (isMIAMVersion(version) && isMIAMCorePdu(pduType)) {
|
|
4428
|
+
const versionPduHandler = this.VersionPduHandlerTable[version][pduType];
|
|
4429
|
+
return versionPduHandler(hdr, body);
|
|
4430
|
+
} else {
|
|
4455
4431
|
return {
|
|
4456
4432
|
decoded: false,
|
|
4457
4433
|
error: "Invalid version and PDU type combination: v=" + version + ", pdu=" + pduType
|
|
4458
4434
|
};
|
|
4459
4435
|
}
|
|
4460
|
-
return versionPduHandler(hdr, body);
|
|
4461
4436
|
},
|
|
4462
|
-
["F" /* FileTransferRequest */]:
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
["
|
|
4466
|
-
|
|
4467
|
-
|
|
4437
|
+
["F" /* FileTransferRequest */]: () => {
|
|
4438
|
+
return { decoded: false, error: "File Transfer Request not implemented" };
|
|
4439
|
+
},
|
|
4440
|
+
["K" /* FileTransferAccept */]: () => {
|
|
4441
|
+
return { decoded: false, error: "File Transfer Accept not implemented" };
|
|
4442
|
+
},
|
|
4443
|
+
["S" /* FileSegment */]: () => {
|
|
4444
|
+
return { decoded: false, error: "File Segment not implemented" };
|
|
4445
|
+
},
|
|
4446
|
+
["A" /* FileTransferAbort */]: () => {
|
|
4447
|
+
return { decoded: false, error: "File Transfer Abort not implemented" };
|
|
4448
|
+
},
|
|
4449
|
+
["Y" /* XOFFIndication */]: () => {
|
|
4450
|
+
return { decoded: false, error: "XOFF Indication not implemented" };
|
|
4451
|
+
},
|
|
4452
|
+
["X" /* XONIndication */]: () => {
|
|
4453
|
+
return { decoded: false, error: "XON Indication not implemented" };
|
|
4454
|
+
}
|
|
4468
4455
|
};
|
|
4469
4456
|
static arincCrc16(buf, seed) {
|
|
4470
4457
|
const crctable = [
|
|
@@ -4998,14 +4985,15 @@ var MIAMCoreUtils = class {
|
|
|
4998
4985
|
}
|
|
4999
4986
|
static parse(txt) {
|
|
5000
4987
|
const fidType = txt[0];
|
|
5001
|
-
|
|
5002
|
-
|
|
4988
|
+
if (isMIAMFid(fidType)) {
|
|
4989
|
+
const handler = this.FidHandlerTable[fidType];
|
|
4990
|
+
return handler(txt.substring(1));
|
|
4991
|
+
} else {
|
|
5003
4992
|
return {
|
|
5004
4993
|
decoded: false,
|
|
5005
4994
|
error: "Unsupported FID type: " + fidType
|
|
5006
4995
|
};
|
|
5007
4996
|
}
|
|
5008
|
-
return handler(txt.substring(1));
|
|
5009
4997
|
}
|
|
5010
4998
|
static corePduDataHandler(version, minHdrSize, crcLen, hdr, body) {
|
|
5011
4999
|
if (hdr.length < minHdrSize) {
|
|
@@ -5020,14 +5008,14 @@ var MIAMCoreUtils = class {
|
|
|
5020
5008
|
let pduAppType = 0;
|
|
5021
5009
|
let pduAppId = "";
|
|
5022
5010
|
let pduCrc = 0;
|
|
5023
|
-
let pduData =
|
|
5011
|
+
let pduData = null;
|
|
5024
5012
|
let pduCrcIsOk = false;
|
|
5025
5013
|
let pduIsComplete = true;
|
|
5026
5014
|
let pduErrors = [];
|
|
5027
5015
|
let tail = void 0;
|
|
5028
5016
|
let msgNum = 0;
|
|
5029
5017
|
let ackOptions = 0;
|
|
5030
|
-
if (version === 1) {
|
|
5018
|
+
if (version === 1 /* V1 */) {
|
|
5031
5019
|
pduSize = hdr.readUInt8(1) << 16 | hdr.readUInt8(2) << 8 | hdr.readUInt8(3);
|
|
5032
5020
|
const msgSize = hdr.length + (body === void 0 ? 0 : body.length);
|
|
5033
5021
|
if (pduSize > msgSize) {
|
|
@@ -5037,7 +5025,7 @@ var MIAMCoreUtils = class {
|
|
|
5037
5025
|
hdr = hdr.subarray(4);
|
|
5038
5026
|
tail = hdr.subarray(0, 7).toString("ascii");
|
|
5039
5027
|
hdr = hdr.subarray(7);
|
|
5040
|
-
} else if (version === 2) {
|
|
5028
|
+
} else if (version === 2 /* V2 */) {
|
|
5041
5029
|
hdr = hdr.subarray(1);
|
|
5042
5030
|
}
|
|
5043
5031
|
msgNum = hdr.readUInt8(0) >> 1 & 127;
|
|
@@ -5047,9 +5035,11 @@ var MIAMCoreUtils = class {
|
|
|
5047
5035
|
pduEncoding = hdr.readUInt8(1) >> 4 & 3;
|
|
5048
5036
|
pduAppType = hdr.readUInt8(1) & 15;
|
|
5049
5037
|
hdr = hdr.subarray(2);
|
|
5050
|
-
let appIdLen
|
|
5051
|
-
if (
|
|
5052
|
-
|
|
5038
|
+
let appIdLen;
|
|
5039
|
+
if (isMIAMCoreApp(pduAppType)) {
|
|
5040
|
+
appIdLen = this.AppTypeToAppIdLenTable[version][pduAppType];
|
|
5041
|
+
} else {
|
|
5042
|
+
if (version === 2 /* V2 */ && (pduAppType & 8) !== 0 && pduAppType !== 13) {
|
|
5053
5043
|
appIdLen = (pduAppType & 7) + 1;
|
|
5054
5044
|
} else {
|
|
5055
5045
|
return {
|
|
@@ -5059,9 +5049,6 @@ var MIAMCoreUtils = class {
|
|
|
5059
5049
|
}
|
|
5060
5050
|
}
|
|
5061
5051
|
const pduIsACARS = [
|
|
5062
|
-
0 /* ACARS2Char */,
|
|
5063
|
-
1 /* ACARS4Char */,
|
|
5064
|
-
2 /* ACARS6Char */,
|
|
5065
5052
|
0 /* ACARS2Char */,
|
|
5066
5053
|
1 /* ACARS4Char */,
|
|
5067
5054
|
2 /* ACARS6Char */
|
|
@@ -5083,7 +5070,7 @@ var MIAMCoreUtils = class {
|
|
|
5083
5070
|
if (body !== void 0 && body.length > 0) {
|
|
5084
5071
|
if ([1 /* Deflate */, 1 /* Deflate */].indexOf(pduCompression) >= 0) {
|
|
5085
5072
|
try {
|
|
5086
|
-
const decompress = new zlib2.InflateRaw({
|
|
5073
|
+
const decompress = new zlib2.InflateRaw({});
|
|
5087
5074
|
decompress.write(body);
|
|
5088
5075
|
decompress.flush(zlib2.constants.Z_SYNC_FLUSH);
|
|
5089
5076
|
pduData = decompress.read();
|
|
@@ -5095,18 +5082,18 @@ var MIAMCoreUtils = class {
|
|
|
5095
5082
|
} else {
|
|
5096
5083
|
pduErrors.push("Unsupported v" + version + " compression type: " + pduCompression);
|
|
5097
5084
|
}
|
|
5098
|
-
if (pduData !==
|
|
5085
|
+
if (pduData !== null) {
|
|
5099
5086
|
const crcAlgoHandlerByVersion = {
|
|
5100
|
-
1: (buf, seed) => {
|
|
5087
|
+
[1 /* V1 */]: (buf, seed) => {
|
|
5101
5088
|
return ~this.arinc665Crc32(buf, seed);
|
|
5102
5089
|
},
|
|
5103
|
-
2: this.arincCrc16
|
|
5090
|
+
[2 /* V2 */]: this.arincCrc16
|
|
5104
5091
|
};
|
|
5105
5092
|
const crcAlgoHandler = crcAlgoHandlerByVersion[version];
|
|
5106
5093
|
if (crcAlgoHandler === void 0) {
|
|
5107
5094
|
return {
|
|
5108
5095
|
decoded: false,
|
|
5109
|
-
|
|
5096
|
+
error: "No CRC handler for v" + version
|
|
5110
5097
|
};
|
|
5111
5098
|
}
|
|
5112
5099
|
const crcCheck = crcAlgoHandler(pduData, 4294967295);
|
|
@@ -5154,25 +5141,315 @@ var MIAMCoreUtils = class {
|
|
|
5154
5141
|
};
|
|
5155
5142
|
}
|
|
5156
5143
|
static VersionPduHandlerTable = {
|
|
5157
|
-
1: {
|
|
5144
|
+
[1 /* V1 */]: {
|
|
5158
5145
|
[0 /* Data */]: (hdr, body) => {
|
|
5159
|
-
return this.corePduDataHandler(1
|
|
5146
|
+
return this.corePduDataHandler(1 /* V1 */, 20, MIAMCoreV1CRCLength, hdr, body);
|
|
5147
|
+
},
|
|
5148
|
+
[1 /* Ack */]: () => {
|
|
5149
|
+
return { decoded: false, error: "v1 Ack PDU not implemented" };
|
|
5160
5150
|
},
|
|
5161
|
-
[
|
|
5162
|
-
|
|
5163
|
-
|
|
5151
|
+
[2 /* Aloha */]: () => {
|
|
5152
|
+
return { decoded: false, error: "v1 Aloha PDU not implemented" };
|
|
5153
|
+
},
|
|
5154
|
+
[3 /* AlohaReply */]: () => {
|
|
5155
|
+
return { decoded: false, error: "v1 AlohaReply PDU not implemented" };
|
|
5156
|
+
}
|
|
5164
5157
|
},
|
|
5165
|
-
2: {
|
|
5158
|
+
[2 /* V2 */]: {
|
|
5166
5159
|
[0 /* Data */]: (hdr, body) => {
|
|
5167
|
-
return this.corePduDataHandler(2
|
|
5160
|
+
return this.corePduDataHandler(2 /* V2 */, 7, MIAMCoreV2CRCLength, hdr, body);
|
|
5161
|
+
},
|
|
5162
|
+
[1 /* Ack */]: () => {
|
|
5163
|
+
return { decoded: false, error: "v2 Ack PDU not implemented" };
|
|
5168
5164
|
},
|
|
5169
|
-
[
|
|
5170
|
-
|
|
5171
|
-
|
|
5165
|
+
[2 /* Aloha */]: () => {
|
|
5166
|
+
return { decoded: false, error: "v2 Aloha PDU not implemented" };
|
|
5167
|
+
},
|
|
5168
|
+
[3 /* AlohaReply */]: () => {
|
|
5169
|
+
return { decoded: false, error: "v2 Aloha reply PDU not implemented" };
|
|
5170
|
+
}
|
|
5172
5171
|
}
|
|
5173
5172
|
};
|
|
5174
5173
|
};
|
|
5175
5174
|
|
|
5175
|
+
// lib/plugins/Label_MA.ts
|
|
5176
|
+
var Label_MA = class extends DecoderPlugin {
|
|
5177
|
+
name = "label-ma";
|
|
5178
|
+
qualifiers() {
|
|
5179
|
+
return {
|
|
5180
|
+
labels: ["MA"]
|
|
5181
|
+
};
|
|
5182
|
+
}
|
|
5183
|
+
decode(message, options = {}) {
|
|
5184
|
+
let decodeResult = this.defaultResult();
|
|
5185
|
+
decodeResult.decoder.name = this.name;
|
|
5186
|
+
decodeResult.message = message;
|
|
5187
|
+
const miamResult = MIAMCoreUtils.parse(message.text);
|
|
5188
|
+
if (miamResult.decoded && miamResult.message.data !== void 0 && miamResult.message.data.crcOk && miamResult.message.data.complete && miamResult.message.data.acars !== void 0) {
|
|
5189
|
+
decodeResult.decoded = true;
|
|
5190
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5191
|
+
ResultFormatter.label(decodeResult, miamResult.message.data.acars.label);
|
|
5192
|
+
if (miamResult.message.data.acars.sublabel) {
|
|
5193
|
+
ResultFormatter.sublabel(decodeResult, miamResult.message.data.acars.sublabel);
|
|
5194
|
+
}
|
|
5195
|
+
if (miamResult.message.data.acars.tail) {
|
|
5196
|
+
ResultFormatter.tail(decodeResult, miamResult.message.data.acars.tail);
|
|
5197
|
+
}
|
|
5198
|
+
const messageText = miamResult.message.data.acars.text;
|
|
5199
|
+
if (messageText) {
|
|
5200
|
+
const decoded = this.decoder.decode({
|
|
5201
|
+
label: miamResult.message.data.acars.label,
|
|
5202
|
+
sublabel: miamResult.message.data.acars.sublabel,
|
|
5203
|
+
text: messageText
|
|
5204
|
+
}, options);
|
|
5205
|
+
if (decoded.decoded) {
|
|
5206
|
+
decodeResult.decoder.decodeLevel = decoded.decoder.decodeLevel;
|
|
5207
|
+
decodeResult.raw = { ...decodeResult.raw, ...decoded.raw };
|
|
5208
|
+
decodeResult.formatted.items.push(...decoded.formatted.items);
|
|
5209
|
+
} else {
|
|
5210
|
+
ResultFormatter.text(decodeResult, messageText);
|
|
5211
|
+
}
|
|
5212
|
+
message.text = messageText;
|
|
5213
|
+
}
|
|
5214
|
+
message.label = miamResult.message.data.acars.label;
|
|
5215
|
+
message.sublabel = miamResult.message.data.acars.sublabel;
|
|
5216
|
+
return decodeResult;
|
|
5217
|
+
}
|
|
5218
|
+
return decodeResult;
|
|
5219
|
+
}
|
|
5220
|
+
};
|
|
5221
|
+
|
|
5222
|
+
// lib/plugins/Label_SQ.ts
|
|
5223
|
+
var Label_SQ = class extends DecoderPlugin {
|
|
5224
|
+
name = "label-sq";
|
|
5225
|
+
qualifiers() {
|
|
5226
|
+
return {
|
|
5227
|
+
labels: ["SQ"]
|
|
5228
|
+
};
|
|
5229
|
+
}
|
|
5230
|
+
decode(message, options = {}) {
|
|
5231
|
+
const decodeResult = this.defaultResult();
|
|
5232
|
+
decodeResult.decoder.name = this.name;
|
|
5233
|
+
decodeResult.raw.preamble = message.text.substring(0, 4);
|
|
5234
|
+
decodeResult.raw.version = message.text.substring(1, 2);
|
|
5235
|
+
decodeResult.raw.network = message.text.substring(3, 4);
|
|
5236
|
+
if (decodeResult.raw.version === "2") {
|
|
5237
|
+
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+)\/.*/;
|
|
5238
|
+
const result = message.text.match(regex);
|
|
5239
|
+
if (result?.groups && result.length >= 8) {
|
|
5240
|
+
decodeResult.raw.groundStation = {
|
|
5241
|
+
number: result.groups.station,
|
|
5242
|
+
iataCode: result.groups.iata,
|
|
5243
|
+
icaoCode: result.groups.icao,
|
|
5244
|
+
coordinates: {
|
|
5245
|
+
latitude: Number(result.groups.lat) / 100 * (result.groups.latd === "S" ? -1 : 1),
|
|
5246
|
+
longitude: Number(result.groups.lng) / 100 * (result.groups.lngd === "W" ? -1 : 1)
|
|
5247
|
+
}
|
|
5248
|
+
};
|
|
5249
|
+
decodeResult.raw.vdlFrequency = Number(result.groups.vfreq) / 1e3;
|
|
5250
|
+
}
|
|
5251
|
+
}
|
|
5252
|
+
decodeResult.formatted.description = "Ground Station Squitter";
|
|
5253
|
+
var formattedNetwork = "Unknown";
|
|
5254
|
+
if (decodeResult.raw.network == "A") {
|
|
5255
|
+
formattedNetwork = "ARINC";
|
|
5256
|
+
} else if (decodeResult.raw.network == "S") {
|
|
5257
|
+
formattedNetwork = "SITA";
|
|
5258
|
+
}
|
|
5259
|
+
decodeResult.formatted.items = [
|
|
5260
|
+
{
|
|
5261
|
+
type: "network",
|
|
5262
|
+
code: "NETT",
|
|
5263
|
+
label: "Network",
|
|
5264
|
+
value: formattedNetwork
|
|
5265
|
+
},
|
|
5266
|
+
{
|
|
5267
|
+
type: "version",
|
|
5268
|
+
code: "VER",
|
|
5269
|
+
label: "Version",
|
|
5270
|
+
value: decodeResult.raw.version
|
|
5271
|
+
}
|
|
5272
|
+
];
|
|
5273
|
+
if (decodeResult.raw.groundStation) {
|
|
5274
|
+
if (decodeResult.raw.groundStation.icaoCode && decodeResult.raw.groundStation.number) {
|
|
5275
|
+
decodeResult.formatted.items.push({
|
|
5276
|
+
type: "ground_station",
|
|
5277
|
+
code: "GNDSTN",
|
|
5278
|
+
label: "Ground Station",
|
|
5279
|
+
value: `${decodeResult.raw.groundStation.icaoCode}${decodeResult.raw.groundStation.number}`
|
|
5280
|
+
});
|
|
5281
|
+
}
|
|
5282
|
+
if (decodeResult.raw.groundStation.iataCode) {
|
|
5283
|
+
decodeResult.formatted.items.push({
|
|
5284
|
+
type: "iataCode",
|
|
5285
|
+
code: "IATA",
|
|
5286
|
+
label: "IATA",
|
|
5287
|
+
value: decodeResult.raw.groundStation.iataCode
|
|
5288
|
+
});
|
|
5289
|
+
}
|
|
5290
|
+
if (decodeResult.raw.groundStation.icaoCode) {
|
|
5291
|
+
decodeResult.formatted.items.push({
|
|
5292
|
+
type: "icaoCode",
|
|
5293
|
+
code: "ICAO",
|
|
5294
|
+
label: "ICAO",
|
|
5295
|
+
value: decodeResult.raw.groundStation.icaoCode
|
|
5296
|
+
});
|
|
5297
|
+
}
|
|
5298
|
+
if (decodeResult.raw.groundStation.coordinates.latitude) {
|
|
5299
|
+
decodeResult.formatted.items.push({
|
|
5300
|
+
type: "coordinates",
|
|
5301
|
+
code: "COORD",
|
|
5302
|
+
label: "Ground Station Location",
|
|
5303
|
+
value: `${decodeResult.raw.groundStation.coordinates.latitude}, ${decodeResult.raw.groundStation.coordinates.longitude}`
|
|
5304
|
+
});
|
|
5305
|
+
}
|
|
5306
|
+
if (decodeResult.raw.groundStation.airport) {
|
|
5307
|
+
decodeResult.formatted.items.push({
|
|
5308
|
+
type: "airport",
|
|
5309
|
+
code: "APT",
|
|
5310
|
+
label: "Airport",
|
|
5311
|
+
value: `${decodeResult.raw.groundStation.airport.name} (${decodeResult.raw.groundStation.airport.icao}) in ${decodeResult.raw.groundStation.airport.location}`
|
|
5312
|
+
});
|
|
5313
|
+
}
|
|
5314
|
+
}
|
|
5315
|
+
if (decodeResult.raw.vdlFrequency) {
|
|
5316
|
+
decodeResult.formatted.items.push({
|
|
5317
|
+
type: "vdlFrequency",
|
|
5318
|
+
code: "VDLFRQ",
|
|
5319
|
+
label: "VDL Frequency",
|
|
5320
|
+
value: `${decodeResult.raw.vdlFrequency} MHz`
|
|
5321
|
+
});
|
|
5322
|
+
}
|
|
5323
|
+
decodeResult.decoded = true;
|
|
5324
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5325
|
+
return decodeResult;
|
|
5326
|
+
}
|
|
5327
|
+
};
|
|
5328
|
+
|
|
5329
|
+
// lib/plugins/Label_QR.ts
|
|
5330
|
+
var Label_QR = class extends DecoderPlugin {
|
|
5331
|
+
name = "label-qr";
|
|
5332
|
+
qualifiers() {
|
|
5333
|
+
return {
|
|
5334
|
+
labels: ["QR"]
|
|
5335
|
+
};
|
|
5336
|
+
}
|
|
5337
|
+
decode(message, options = {}) {
|
|
5338
|
+
const decodeResult = this.defaultResult();
|
|
5339
|
+
decodeResult.decoder.name = this.name;
|
|
5340
|
+
decodeResult.formatted.description = "ON Report";
|
|
5341
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
5342
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
5343
|
+
ResultFormatter.on(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12)));
|
|
5344
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
5345
|
+
decodeResult.decoded = true;
|
|
5346
|
+
if (!decodeResult.remaining.text)
|
|
5347
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5348
|
+
else
|
|
5349
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5350
|
+
return decodeResult;
|
|
5351
|
+
}
|
|
5352
|
+
};
|
|
5353
|
+
|
|
5354
|
+
// lib/plugins/Label_QP.ts
|
|
5355
|
+
var Label_QP = class extends DecoderPlugin {
|
|
5356
|
+
name = "label-qp";
|
|
5357
|
+
qualifiers() {
|
|
5358
|
+
return {
|
|
5359
|
+
labels: ["QP"]
|
|
5360
|
+
};
|
|
5361
|
+
}
|
|
5362
|
+
decode(message, options = {}) {
|
|
5363
|
+
const decodeResult = this.defaultResult();
|
|
5364
|
+
decodeResult.decoder.name = this.name;
|
|
5365
|
+
decodeResult.formatted.description = "OUT Report";
|
|
5366
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
5367
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
5368
|
+
ResultFormatter.out(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12)));
|
|
5369
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
5370
|
+
decodeResult.decoded = true;
|
|
5371
|
+
if (!decodeResult.remaining.text)
|
|
5372
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5373
|
+
else
|
|
5374
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5375
|
+
return decodeResult;
|
|
5376
|
+
}
|
|
5377
|
+
};
|
|
5378
|
+
|
|
5379
|
+
// lib/plugins/Label_QS.ts
|
|
5380
|
+
var Label_QS = class extends DecoderPlugin {
|
|
5381
|
+
name = "label-qs";
|
|
5382
|
+
qualifiers() {
|
|
5383
|
+
return {
|
|
5384
|
+
labels: ["QS"]
|
|
5385
|
+
};
|
|
5386
|
+
}
|
|
5387
|
+
decode(message, options = {}) {
|
|
5388
|
+
const decodeResult = this.defaultResult();
|
|
5389
|
+
decodeResult.decoder.name = this.name;
|
|
5390
|
+
decodeResult.formatted.description = "IN Report";
|
|
5391
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
5392
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
5393
|
+
ResultFormatter.in(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12)));
|
|
5394
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
5395
|
+
decodeResult.decoded = true;
|
|
5396
|
+
if (!decodeResult.remaining.text)
|
|
5397
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5398
|
+
else
|
|
5399
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5400
|
+
return decodeResult;
|
|
5401
|
+
}
|
|
5402
|
+
};
|
|
5403
|
+
|
|
5404
|
+
// lib/plugins/Label_QQ.ts
|
|
5405
|
+
var Label_QQ = class extends DecoderPlugin {
|
|
5406
|
+
name = "label-qq";
|
|
5407
|
+
qualifiers() {
|
|
5408
|
+
return {
|
|
5409
|
+
labels: ["QQ"]
|
|
5410
|
+
};
|
|
5411
|
+
}
|
|
5412
|
+
decode(message, options = {}) {
|
|
5413
|
+
const decodeResult = this.defaultResult();
|
|
5414
|
+
decodeResult.decoder.name = this.name;
|
|
5415
|
+
decodeResult.message = message;
|
|
5416
|
+
decodeResult.formatted.description = "OFF Report";
|
|
5417
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
5418
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
5419
|
+
if (message.text.substring(12, 19) === "\r\n001FE") {
|
|
5420
|
+
decodeResult.raw.day = message.text.substring(19, 21);
|
|
5421
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(21, 27)));
|
|
5422
|
+
let latdir = message.text.substring(27, 28);
|
|
5423
|
+
let latdeg = Number(message.text.substring(28, 30));
|
|
5424
|
+
let latmin = Number(message.text.substring(30, 34));
|
|
5425
|
+
let londir = message.text.substring(34, 35);
|
|
5426
|
+
let londeg = Number(message.text.substring(35, 38));
|
|
5427
|
+
let lonmin = Number(message.text.substring(38, 42));
|
|
5428
|
+
let pos = {
|
|
5429
|
+
latitude: (latdeg + latmin / 60) * (latdir === "N" ? 1 : -1),
|
|
5430
|
+
longitude: (londeg + lonmin / 60) * (londir === "E" ? 1 : -1)
|
|
5431
|
+
};
|
|
5432
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(42, 45));
|
|
5433
|
+
ResultFormatter.position(decodeResult, pos);
|
|
5434
|
+
if (decodeResult.remaining.text !== "---") {
|
|
5435
|
+
ResultFormatter.groundspeed(decodeResult, Number(message.text.substring(45, 48)));
|
|
5436
|
+
} else {
|
|
5437
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(45, 48));
|
|
5438
|
+
}
|
|
5439
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(48));
|
|
5440
|
+
} else {
|
|
5441
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12) + "00"));
|
|
5442
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
5443
|
+
}
|
|
5444
|
+
decodeResult.decoded = true;
|
|
5445
|
+
if (!decodeResult.remaining.text)
|
|
5446
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5447
|
+
else
|
|
5448
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5449
|
+
return decodeResult;
|
|
5450
|
+
}
|
|
5451
|
+
};
|
|
5452
|
+
|
|
5176
5453
|
// lib/MessageDecoder.ts
|
|
5177
5454
|
var MessageDecoder = class {
|
|
5178
5455
|
name;
|
|
@@ -5240,6 +5517,7 @@ var MessageDecoder = class {
|
|
|
5240
5517
|
this.registerPlugin(new Label_83(this));
|
|
5241
5518
|
this.registerPlugin(new Label_8E(this));
|
|
5242
5519
|
this.registerPlugin(new Label_1M_Slash(this));
|
|
5520
|
+
this.registerPlugin(new Label_MA(this));
|
|
5243
5521
|
this.registerPlugin(new Label_SQ(this));
|
|
5244
5522
|
this.registerPlugin(new Label_QP(this));
|
|
5245
5523
|
this.registerPlugin(new Label_QQ(this));
|
|
@@ -5252,18 +5530,6 @@ var MessageDecoder = class {
|
|
|
5252
5530
|
return true;
|
|
5253
5531
|
}
|
|
5254
5532
|
decode(message, options = {}) {
|
|
5255
|
-
if (message.label === "MA") {
|
|
5256
|
-
const decodeResult = MIAMCoreUtils.parse(message.text);
|
|
5257
|
-
if (decodeResult.decoded && decodeResult.message.data !== void 0 && decodeResult.message.data.crcOk && decodeResult.message.data.complete && decodeResult.message.data.acars !== void 0) {
|
|
5258
|
-
message = {
|
|
5259
|
-
...message,
|
|
5260
|
-
label: decodeResult.message.data.acars.label,
|
|
5261
|
-
...decodeResult.message.data.acars.sublabel ? { sublabel: decodeResult.message.data.acars.sublabel } : {},
|
|
5262
|
-
...decodeResult.message.data.acars.mfi ? { mfi: decodeResult.message.data.acars.mfi } : {},
|
|
5263
|
-
...decodeResult.message.data.acars.text ? { text: decodeResult.message.data.acars.text } : {}
|
|
5264
|
-
};
|
|
5265
|
-
}
|
|
5266
|
-
}
|
|
5267
5533
|
const usablePlugins = this.plugins.filter((plugin) => {
|
|
5268
5534
|
const qualifiers = plugin.qualifiers();
|
|
5269
5535
|
if (qualifiers.labels.includes(message.label)) {
|
|
@@ -5313,11 +5579,6 @@ var MessageDecoder = class {
|
|
|
5313
5579
|
}
|
|
5314
5580
|
return result;
|
|
5315
5581
|
}
|
|
5316
|
-
lookupAirportByIata(iata) {
|
|
5317
|
-
const airportsArray = [];
|
|
5318
|
-
const airport = airportsArray.filter((e) => e.iata === iata);
|
|
5319
|
-
return airport;
|
|
5320
|
-
}
|
|
5321
5582
|
};
|
|
5322
5583
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5323
5584
|
0 && (module.exports = {
|