@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.mjs
CHANGED
|
@@ -140,7 +140,6 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
140
140
|
* @returns An object with latitude and longitude properties
|
|
141
141
|
*/
|
|
142
142
|
static decodeStringCoordinates(stringCoords) {
|
|
143
|
-
var results = {};
|
|
144
143
|
const firstChar = stringCoords.substring(0, 1);
|
|
145
144
|
let middleChar = stringCoords.substring(6, 7);
|
|
146
145
|
let longitudeChars = stringCoords.substring(7, 13);
|
|
@@ -149,12 +148,12 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
149
148
|
longitudeChars = stringCoords.substring(8, 14);
|
|
150
149
|
}
|
|
151
150
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
return {
|
|
152
|
+
latitude: Number(stringCoords.substring(1, 6)) / 1e3 * _CoordinateUtils.getDirection(firstChar),
|
|
153
|
+
longitude: Number(longitudeChars) / 1e3 * _CoordinateUtils.getDirection(middleChar)
|
|
154
|
+
};
|
|
156
155
|
}
|
|
157
|
-
return
|
|
156
|
+
return void 0;
|
|
158
157
|
}
|
|
159
158
|
/**
|
|
160
159
|
* Decode a string of coordinates into an object with latitude and longitude in degrees and decimal minutes
|
|
@@ -163,7 +162,6 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
163
162
|
* @returns An object with latitude and longitude properties
|
|
164
163
|
*/
|
|
165
164
|
static decodeStringCoordinatesDecimalMinutes(stringCoords) {
|
|
166
|
-
var results = {};
|
|
167
165
|
const firstChar = stringCoords.substring(0, 1);
|
|
168
166
|
let middleChar = stringCoords.substring(6, 7);
|
|
169
167
|
let longitudeChars = stringCoords.substring(7, 13);
|
|
@@ -176,12 +174,12 @@ var CoordinateUtils = class _CoordinateUtils {
|
|
|
176
174
|
const lonDeg = Math.trunc(Number(longitudeChars) / 1e3);
|
|
177
175
|
const lonMin = Number(longitudeChars) % 1e3 / 10;
|
|
178
176
|
if ((firstChar === "N" || firstChar === "S") && (middleChar === "W" || middleChar === "E")) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
177
|
+
return {
|
|
178
|
+
latitude: (latDeg + latMin / 60) * _CoordinateUtils.getDirection(firstChar),
|
|
179
|
+
longitude: (lonDeg + lonMin / 60) * _CoordinateUtils.getDirection(middleChar)
|
|
180
|
+
};
|
|
183
181
|
}
|
|
184
|
-
return
|
|
182
|
+
return void 0;
|
|
185
183
|
}
|
|
186
184
|
static coordinateString(coords) {
|
|
187
185
|
const latDir = coords.latitude > 0 ? "N" : "S";
|
|
@@ -475,6 +473,15 @@ var ResultFormatter = class {
|
|
|
475
473
|
value: decodeResult.raw.fuel_on_board.toString()
|
|
476
474
|
});
|
|
477
475
|
}
|
|
476
|
+
static burnedFuel(decodeResult, value) {
|
|
477
|
+
decodeResult.raw.fuel_burned = value;
|
|
478
|
+
decodeResult.formatted.items.push({
|
|
479
|
+
type: "fuel_burned",
|
|
480
|
+
code: "FB",
|
|
481
|
+
label: "Fuel Burned",
|
|
482
|
+
value: decodeResult.raw.fuel_burned.toString()
|
|
483
|
+
});
|
|
484
|
+
}
|
|
478
485
|
static remainingFuel(decodeResult, value) {
|
|
479
486
|
decodeResult.raw.fuel_remaining = value;
|
|
480
487
|
decodeResult.formatted.items.push({
|
|
@@ -650,6 +657,24 @@ var ResultFormatter = class {
|
|
|
650
657
|
value: text
|
|
651
658
|
});
|
|
652
659
|
}
|
|
660
|
+
static mac(decodeResult, mac) {
|
|
661
|
+
decodeResult.raw.mac = mac;
|
|
662
|
+
decodeResult.formatted.items.push({
|
|
663
|
+
type: "mac",
|
|
664
|
+
code: "MAC",
|
|
665
|
+
label: "Mean Aerodynamic Chord",
|
|
666
|
+
value: `${mac} %`
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
static trim(decodeResult, trim) {
|
|
670
|
+
decodeResult.raw.trim = trim;
|
|
671
|
+
decodeResult.formatted.items.push({
|
|
672
|
+
type: "trim",
|
|
673
|
+
code: "TRIM",
|
|
674
|
+
label: "Trim",
|
|
675
|
+
value: `${trim} units`
|
|
676
|
+
});
|
|
677
|
+
}
|
|
653
678
|
static windData(decodeResult, windData) {
|
|
654
679
|
decodeResult.raw.wind_data = windData;
|
|
655
680
|
for (const wind of windData) {
|
|
@@ -665,6 +690,64 @@ var ResultFormatter = class {
|
|
|
665
690
|
});
|
|
666
691
|
}
|
|
667
692
|
}
|
|
693
|
+
static cg(decodeResult, value, type = "center") {
|
|
694
|
+
switch (type) {
|
|
695
|
+
case "center":
|
|
696
|
+
decodeResult.raw.center_of_gravity = value;
|
|
697
|
+
decodeResult.formatted.items.push({
|
|
698
|
+
type: "center_of_gravity",
|
|
699
|
+
code: "CG",
|
|
700
|
+
label: "Center of Gravity",
|
|
701
|
+
value: `${decodeResult.raw.center_of_gravity} %`
|
|
702
|
+
});
|
|
703
|
+
break;
|
|
704
|
+
case "lower":
|
|
705
|
+
decodeResult.raw.cg_lower_limit = value;
|
|
706
|
+
decodeResult.formatted.items.push({
|
|
707
|
+
type: "cg_lower_limit",
|
|
708
|
+
code: "CG_LOWER",
|
|
709
|
+
label: "Center of Gravity Lower Limit",
|
|
710
|
+
value: `${decodeResult.raw.cg_lower_limit} %`
|
|
711
|
+
});
|
|
712
|
+
break;
|
|
713
|
+
case "upper":
|
|
714
|
+
decodeResult.raw.cg_upper_limit = value;
|
|
715
|
+
decodeResult.formatted.items.push({
|
|
716
|
+
type: "cg_upper_limit",
|
|
717
|
+
code: "CG_UPPER",
|
|
718
|
+
label: "Center of Gravity Upper Limit",
|
|
719
|
+
value: `${decodeResult.raw.cg_upper_limit} %`
|
|
720
|
+
});
|
|
721
|
+
break;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
static version(decodeResult, value) {
|
|
725
|
+
decodeResult.raw.version = value;
|
|
726
|
+
decodeResult.formatted.items.push({
|
|
727
|
+
type: "version",
|
|
728
|
+
code: "VERSION",
|
|
729
|
+
label: "Message Version",
|
|
730
|
+
value: `v${decodeResult.raw.version.toFixed(1)}`
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
static label(decodeResult, value) {
|
|
734
|
+
decodeResult.raw.label = value;
|
|
735
|
+
decodeResult.formatted.items.push({
|
|
736
|
+
type: "label",
|
|
737
|
+
code: "LABEL",
|
|
738
|
+
label: "Message Label",
|
|
739
|
+
value: `${decodeResult.raw.label}`
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
static sublabel(decodeResult, value) {
|
|
743
|
+
decodeResult.raw.sublabel = value;
|
|
744
|
+
decodeResult.formatted.items.push({
|
|
745
|
+
type: "sublabel",
|
|
746
|
+
code: "SUBLABEL",
|
|
747
|
+
label: "Message Sublabel",
|
|
748
|
+
value: `${decodeResult.raw.sublabel}`
|
|
749
|
+
});
|
|
750
|
+
}
|
|
668
751
|
static unknown(decodeResult, value, sep = ",") {
|
|
669
752
|
if (!decodeResult.remaining.text)
|
|
670
753
|
decodeResult.remaining.text = value;
|
|
@@ -1498,6 +1581,14 @@ var FlightPlanUtils = class _FlightPlanUtils {
|
|
|
1498
1581
|
label: "Route Status",
|
|
1499
1582
|
value: "Route Inactive"
|
|
1500
1583
|
});
|
|
1584
|
+
} else if (header.startsWith("RM")) {
|
|
1585
|
+
decodeResult.raw.route_status = "RM";
|
|
1586
|
+
decodeResult.formatted.items.push({
|
|
1587
|
+
type: "status",
|
|
1588
|
+
code: "ROUTE_STATUS",
|
|
1589
|
+
label: "Route Status",
|
|
1590
|
+
value: "Route Mapped"
|
|
1591
|
+
});
|
|
1501
1592
|
} else {
|
|
1502
1593
|
decodeResult.remaining.text += header;
|
|
1503
1594
|
allKnownFields = false;
|
|
@@ -1573,6 +1664,11 @@ var H1Helper = class _H1Helper {
|
|
|
1573
1664
|
static decodeH1Message(decodeResult, message) {
|
|
1574
1665
|
const checksum = message.slice(-4);
|
|
1575
1666
|
const data = message.slice(0, message.length - 4);
|
|
1667
|
+
if (calculateChecksum(data) !== checksum) {
|
|
1668
|
+
decodeResult.decoded = false;
|
|
1669
|
+
decodeResult.decoder.decodeLevel = "none";
|
|
1670
|
+
return false;
|
|
1671
|
+
}
|
|
1576
1672
|
const fields = data.split("/");
|
|
1577
1673
|
const canDecode = parseMessageType(decodeResult, fields[0]);
|
|
1578
1674
|
if (!canDecode) {
|
|
@@ -1581,53 +1677,71 @@ var H1Helper = class _H1Helper {
|
|
|
1581
1677
|
return false;
|
|
1582
1678
|
}
|
|
1583
1679
|
for (let i = 1; i < fields.length; ++i) {
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
ResultFormatter.
|
|
1619
|
-
|
|
1680
|
+
const key = fields[i].substring(0, 2);
|
|
1681
|
+
const data2 = fields[i].substring(2);
|
|
1682
|
+
switch (key) {
|
|
1683
|
+
case "AF":
|
|
1684
|
+
processAirField(decodeResult, data2.split(","));
|
|
1685
|
+
break;
|
|
1686
|
+
case "CG":
|
|
1687
|
+
processCenterOfGravity(decodeResult, data2.split(","));
|
|
1688
|
+
break;
|
|
1689
|
+
case "DC":
|
|
1690
|
+
processDateCode(decodeResult, data2.split(","));
|
|
1691
|
+
break;
|
|
1692
|
+
case "DT":
|
|
1693
|
+
processDT(decodeResult, data2.split(","));
|
|
1694
|
+
break;
|
|
1695
|
+
case "ET":
|
|
1696
|
+
processETA(data2, decodeResult, fields, i);
|
|
1697
|
+
break;
|
|
1698
|
+
case "FB":
|
|
1699
|
+
ResultFormatter.currentFuel(decodeResult, parseInt(data2, 10));
|
|
1700
|
+
break;
|
|
1701
|
+
case "FN":
|
|
1702
|
+
decodeResult.raw.flight_number = data2;
|
|
1703
|
+
break;
|
|
1704
|
+
case "FX":
|
|
1705
|
+
ResultFormatter.freetext(decodeResult, data2);
|
|
1706
|
+
break;
|
|
1707
|
+
case "ID":
|
|
1708
|
+
processIdentification(decodeResult, data2.split(","));
|
|
1709
|
+
break;
|
|
1710
|
+
case "LR":
|
|
1711
|
+
processLandingReport(decodeResult, data2.split(","));
|
|
1712
|
+
break;
|
|
1713
|
+
case "PR":
|
|
1714
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
1715
|
+
break;
|
|
1716
|
+
case "PS":
|
|
1717
|
+
_H1Helper.processPS(decodeResult, data2.split(","));
|
|
1718
|
+
break;
|
|
1719
|
+
case "RF":
|
|
1720
|
+
case "RI":
|
|
1721
|
+
case "RM":
|
|
1722
|
+
case "RP":
|
|
1723
|
+
FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
|
|
1724
|
+
break;
|
|
1725
|
+
case "SN":
|
|
1726
|
+
decodeResult.raw.serial_number = data2;
|
|
1727
|
+
break;
|
|
1728
|
+
case "TD":
|
|
1729
|
+
processTimeOfDeparture(decodeResult, data2.split(","));
|
|
1730
|
+
break;
|
|
1731
|
+
case "TS":
|
|
1732
|
+
_H1Helper.processTimeStamp(decodeResult, data2.split(","));
|
|
1733
|
+
break;
|
|
1734
|
+
case "VR":
|
|
1735
|
+
ResultFormatter.version(decodeResult, parseInt(data2, 10) / 10);
|
|
1736
|
+
break;
|
|
1737
|
+
case "WD":
|
|
1738
|
+
processWindData(decodeResult, data2);
|
|
1739
|
+
break;
|
|
1740
|
+
default:
|
|
1620
1741
|
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
1621
|
-
}
|
|
1622
|
-
} else if (fields[i].startsWith("WD")) {
|
|
1623
|
-
processWindData(decodeResult, fields[i].substring(2));
|
|
1624
|
-
} else {
|
|
1625
|
-
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
1626
1742
|
}
|
|
1627
1743
|
}
|
|
1628
|
-
|
|
1629
|
-
ResultFormatter.checksum(decodeResult, checksum);
|
|
1630
|
-
}
|
|
1744
|
+
ResultFormatter.checksum(decodeResult, checksum);
|
|
1631
1745
|
return true;
|
|
1632
1746
|
}
|
|
1633
1747
|
static processPS(decodeResult, data) {
|
|
@@ -1671,16 +1785,26 @@ var H1Helper = class _H1Helper {
|
|
|
1671
1785
|
ResultFormatter.unknownArr(decodeResult, data.slice(10));
|
|
1672
1786
|
}
|
|
1673
1787
|
}
|
|
1674
|
-
static
|
|
1788
|
+
static processTimeStamp(decodeResult, data) {
|
|
1675
1789
|
let time = DateTimeUtils.convertDateTimeToEpoch(data[0], data[1]);
|
|
1676
1790
|
if (Number.isNaN(time)) {
|
|
1677
1791
|
const date = data[1].substring(2, 4) + data[1].substring(0, 2) + data[1].substring(4, 6);
|
|
1678
1792
|
time = DateTimeUtils.convertDateTimeToEpoch(data[0], date);
|
|
1679
1793
|
}
|
|
1680
|
-
decodeResult.raw.message_date = data[1];
|
|
1681
1794
|
decodeResult.raw.message_timestamp = time;
|
|
1682
1795
|
}
|
|
1683
1796
|
};
|
|
1797
|
+
function processETA(data, decodeResult, fields, i) {
|
|
1798
|
+
if (data.length === 5) {
|
|
1799
|
+
ResultFormatter.day(decodeResult, Number(data.substring(0, 1)));
|
|
1800
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data.substring(1)));
|
|
1801
|
+
} else if (data.length === 6) {
|
|
1802
|
+
ResultFormatter.day(decodeResult, Number(data.substring(0, 2)));
|
|
1803
|
+
ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(data.substring(2)));
|
|
1804
|
+
} else {
|
|
1805
|
+
ResultFormatter.unknown(decodeResult, fields[i], "/");
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1684
1808
|
function processAirField(decodeResult, data) {
|
|
1685
1809
|
if (data.length === 2) {
|
|
1686
1810
|
ResultFormatter.departureAirport(decodeResult, data[0]);
|
|
@@ -1740,7 +1864,7 @@ function processDT(decodeResult, data) {
|
|
|
1740
1864
|
ResultFormatter.unknownArr(decodeResult, data);
|
|
1741
1865
|
}
|
|
1742
1866
|
}
|
|
1743
|
-
function
|
|
1867
|
+
function processLandingReport(decodeResult, data) {
|
|
1744
1868
|
if (data.length === 19) {
|
|
1745
1869
|
ResultFormatter.unknown(decodeResult, data[1]);
|
|
1746
1870
|
ResultFormatter.flightNumber(decodeResult, data[2]);
|
|
@@ -1752,35 +1876,37 @@ function processLR(decodeResult, data) {
|
|
|
1752
1876
|
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
1753
1877
|
}
|
|
1754
1878
|
}
|
|
1755
|
-
function
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
if (parts[0].length > 0) {
|
|
1771
|
-
ResultFormatter.unknown(decodeResult, parts[0].substring(0, 4));
|
|
1772
|
-
ResultFormatter.flightNumber(decodeResult, parts[0].substring(4));
|
|
1773
|
-
ResultFormatter.unknown(decodeResult, parts[1].length == 5 ? parts[1].substring(0, 2) : parts[1].substring(0, 3), "#");
|
|
1774
|
-
}
|
|
1775
|
-
const type = parts[1].length == 5 ? parts[1].substring(2, 5) : parts[1].substring(3, 6);
|
|
1776
|
-
if (parts[1].substring(3, 6) === "POS" && parts[1].length > 6) {
|
|
1777
|
-
H1Helper.processPosition(decodeResult, parts[1].substring(6).split(","));
|
|
1778
|
-
}
|
|
1779
|
-
return processMessageType(decodeResult, type);
|
|
1879
|
+
function processCenterOfGravity(decodeResult, data) {
|
|
1880
|
+
if (data.length === 1) {
|
|
1881
|
+
if (data[0] !== void 0 && data[0] !== "") {
|
|
1882
|
+
ResultFormatter.cg(decodeResult, parseInt(data[0], 10) / 10);
|
|
1883
|
+
}
|
|
1884
|
+
} else if (data.length === 3) {
|
|
1885
|
+
if (data[0] !== void 0 && data[0] !== "") {
|
|
1886
|
+
ResultFormatter.cg(decodeResult, parseInt(data[0], 10) / 10, "center");
|
|
1887
|
+
}
|
|
1888
|
+
if (data[1] !== void 0 && data[1] !== "") {
|
|
1889
|
+
ResultFormatter.cg(decodeResult, parseInt(data[1], 10) / 10, "lower");
|
|
1890
|
+
}
|
|
1891
|
+
if (data[2] !== void 0 && data[2] !== "") {
|
|
1892
|
+
ResultFormatter.cg(decodeResult, parseInt(data[2], 10) / 10, "upper");
|
|
1893
|
+
}
|
|
1780
1894
|
} else {
|
|
1781
|
-
ResultFormatter.unknown(decodeResult,
|
|
1782
|
-
|
|
1895
|
+
ResultFormatter.unknown(decodeResult, data.join(","));
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
function parseMessageType(decodeResult, messageType) {
|
|
1899
|
+
if (messageType.startsWith("POS")) {
|
|
1900
|
+
H1Helper.processPosition(decodeResult, messageType.substring(3).split(","));
|
|
1901
|
+
return processMessageType(decodeResult, "POS");
|
|
1902
|
+
} else if (messageType.length === 13) {
|
|
1903
|
+
if (processMessageType(decodeResult, messageType.substring(10))) {
|
|
1904
|
+
ResultFormatter.unknown(decodeResult, messageType.substring(0, 4));
|
|
1905
|
+
ResultFormatter.flightNumber(decodeResult, messageType.slice(4, 10));
|
|
1906
|
+
return true;
|
|
1907
|
+
}
|
|
1783
1908
|
}
|
|
1909
|
+
return processMessageType(decodeResult, messageType.substring(0, 3));
|
|
1784
1910
|
}
|
|
1785
1911
|
function processMessageType(decodeResult, type) {
|
|
1786
1912
|
if (type === "FPN") {
|
|
@@ -1789,19 +1915,21 @@ function processMessageType(decodeResult, type) {
|
|
|
1789
1915
|
decodeResult.formatted.description = "Free Text";
|
|
1790
1916
|
} else if (type === "INI") {
|
|
1791
1917
|
decodeResult.formatted.description = "Flight Plan Initial Report";
|
|
1918
|
+
} else if (type === "PER") {
|
|
1919
|
+
decodeResult.formatted.description = "Performance Report";
|
|
1792
1920
|
} else if (type === "POS") {
|
|
1793
1921
|
decodeResult.formatted.description = "Position Report";
|
|
1794
1922
|
} else if (type === "PRG") {
|
|
1795
1923
|
decodeResult.formatted.description = "Progress Report";
|
|
1796
1924
|
} else if (type === "PWI") {
|
|
1797
|
-
decodeResult.formatted.description = "Weather
|
|
1925
|
+
decodeResult.formatted.description = "Pilot Weather Information";
|
|
1798
1926
|
} else {
|
|
1799
1927
|
decodeResult.formatted.description = "Unknown H1 Message";
|
|
1800
1928
|
return false;
|
|
1801
1929
|
}
|
|
1802
1930
|
return true;
|
|
1803
1931
|
}
|
|
1804
|
-
function
|
|
1932
|
+
function processDateCode(decodeResult, data) {
|
|
1805
1933
|
decodeResult.raw.message_date = data[0];
|
|
1806
1934
|
if (data.length === 1) {
|
|
1807
1935
|
} else if (data.length === 2) {
|
|
@@ -1866,6 +1994,26 @@ function processWindData(decodeResult, message) {
|
|
|
1866
1994
|
});
|
|
1867
1995
|
ResultFormatter.windData(decodeResult, wind);
|
|
1868
1996
|
}
|
|
1997
|
+
function calculateChecksum(data) {
|
|
1998
|
+
let crc = 65535;
|
|
1999
|
+
const bytes = Buffer.from(data, "ascii");
|
|
2000
|
+
for (const byte of bytes) {
|
|
2001
|
+
crc ^= byte;
|
|
2002
|
+
for (let i = 0; i < 8; i++) {
|
|
2003
|
+
if ((crc & 1) !== 0) {
|
|
2004
|
+
crc = crc >>> 1 ^ 33800;
|
|
2005
|
+
} else {
|
|
2006
|
+
crc = crc >>> 1;
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
crc = (crc ^ 65535) & 65535;
|
|
2011
|
+
const nibble1 = crc >> 12 & 15;
|
|
2012
|
+
const nibble2 = crc >> 8 & 15;
|
|
2013
|
+
const nibble3 = crc >> 4 & 15;
|
|
2014
|
+
const nibble4 = crc & 15;
|
|
2015
|
+
return `${nibble4.toString(16)}${nibble3.toString(16)}${nibble2.toString(16)}${nibble1.toString(16)}`.toUpperCase();
|
|
2016
|
+
}
|
|
1869
2017
|
|
|
1870
2018
|
// lib/plugins/Label_1J_2J_FTX.ts
|
|
1871
2019
|
var Label_1J_2J_FTX = class extends DecoderPlugin {
|
|
@@ -1880,7 +2028,14 @@ var Label_1J_2J_FTX = class extends DecoderPlugin {
|
|
|
1880
2028
|
decodeResult.decoder.name = this.name;
|
|
1881
2029
|
decodeResult.message = message;
|
|
1882
2030
|
const msg = message.text.replace(/\n|\r/g, "");
|
|
1883
|
-
const
|
|
2031
|
+
const parts = msg.split("/");
|
|
2032
|
+
let decoded = false;
|
|
2033
|
+
if (parts[0].length > 3) {
|
|
2034
|
+
decoded = H1Helper.decodeH1Message(decodeResult, msg.slice(parts[0].length - 3));
|
|
2035
|
+
decodeResult.remaining.text = parts[0].slice(0, 3) + "/" + decodeResult.remaining.text;
|
|
2036
|
+
} else {
|
|
2037
|
+
decoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
2038
|
+
}
|
|
1884
2039
|
decodeResult.decoded = decoded;
|
|
1885
2040
|
decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
|
|
1886
2041
|
if (decodeResult.formatted.items.length === 0) {
|
|
@@ -2425,7 +2580,6 @@ var Label_2P_FM3 = class extends DecoderPlugin {
|
|
|
2425
2580
|
ResultFormatter.unknown(decodeResult, header[0].substring(0, 4));
|
|
2426
2581
|
ResultFormatter.flightNumber(decodeResult, header[0].substring(4));
|
|
2427
2582
|
}
|
|
2428
|
-
console.log(header[1]);
|
|
2429
2583
|
if (header[1].length === 4) {
|
|
2430
2584
|
ResultFormatter.time_of_day(decodeResult, DateTimeUtils.convertHHMMSSToTod(header[1]));
|
|
2431
2585
|
} else {
|
|
@@ -2569,7 +2723,14 @@ var Label_2P_POS = class extends DecoderPlugin {
|
|
|
2569
2723
|
decodeResult.decoder.name = this.name;
|
|
2570
2724
|
decodeResult.message = message;
|
|
2571
2725
|
const msg = message.text.replace(/\n|\r/g, "");
|
|
2572
|
-
const
|
|
2726
|
+
const parts = msg.split("/");
|
|
2727
|
+
let decoded = false;
|
|
2728
|
+
if (parts[0].length > 3) {
|
|
2729
|
+
decoded = H1Helper.decodeH1Message(decodeResult, msg.slice(parts[0].length - 3));
|
|
2730
|
+
decodeResult.remaining.text = parts[0].slice(0, 3) + "/" + decodeResult.remaining.text;
|
|
2731
|
+
} else {
|
|
2732
|
+
decoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
2733
|
+
}
|
|
2573
2734
|
decodeResult.decoded = decoded;
|
|
2574
2735
|
decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
|
|
2575
2736
|
if (decodeResult.formatted.items.length === 0) {
|
|
@@ -3702,7 +3863,18 @@ var Label_H1 = class extends DecoderPlugin {
|
|
|
3702
3863
|
decodeResult.decoder.name = this.name;
|
|
3703
3864
|
decodeResult.message = message;
|
|
3704
3865
|
const msg = message.text.replace(/\n|\r/g, "");
|
|
3705
|
-
const
|
|
3866
|
+
const parts = msg.split("#");
|
|
3867
|
+
let decoded = false;
|
|
3868
|
+
if (parts.length === 1) {
|
|
3869
|
+
decoded = H1Helper.decodeH1Message(decodeResult, msg);
|
|
3870
|
+
} else if (parts.length == 2) {
|
|
3871
|
+
const offset = isNaN(parseInt(parts[1][1])) ? 3 : 4;
|
|
3872
|
+
decoded = H1Helper.decodeH1Message(decodeResult, msg.slice(parts[0].length + offset));
|
|
3873
|
+
if (decoded && parts[0].length > 0) {
|
|
3874
|
+
ResultFormatter.flightNumber(decodeResult, parts[0].substring(4));
|
|
3875
|
+
decodeResult.remaining.text = parts[0].substring(0, 4) + "#" + parts[1].substring(0, offset - 1) + "/" + decodeResult.remaining.text;
|
|
3876
|
+
}
|
|
3877
|
+
}
|
|
3706
3878
|
decodeResult.decoded = decoded;
|
|
3707
3879
|
decodeResult.decoder.decodeLevel = !decodeResult.remaining.text ? "full" : "partial";
|
|
3708
3880
|
if (decodeResult.formatted.items.length === 0) {
|
|
@@ -3855,7 +4027,7 @@ var Label_H1_FLR = class extends DecoderPlugin {
|
|
|
3855
4027
|
|
|
3856
4028
|
// lib/plugins/Label_H1_OHMA.ts
|
|
3857
4029
|
import * as zlib from "minizlib";
|
|
3858
|
-
import { Buffer } from "buffer";
|
|
4030
|
+
import { Buffer as Buffer2 } from "buffer";
|
|
3859
4031
|
var Label_H1_OHMA = class extends DecoderPlugin {
|
|
3860
4032
|
name = "label-h1-ohma";
|
|
3861
4033
|
qualifiers() {
|
|
@@ -3871,12 +4043,12 @@ var Label_H1_OHMA = class extends DecoderPlugin {
|
|
|
3871
4043
|
decodeResult.message = message;
|
|
3872
4044
|
const data = message.text.split("OHMA")[1];
|
|
3873
4045
|
try {
|
|
3874
|
-
const compressedBuffer =
|
|
3875
|
-
const decompress = new zlib.Inflate({
|
|
4046
|
+
const compressedBuffer = Buffer2.from(data, "base64");
|
|
4047
|
+
const decompress = new zlib.Inflate({});
|
|
3876
4048
|
decompress.write(compressedBuffer);
|
|
3877
4049
|
decompress.flush(zlib.constants.Z_SYNC_FLUSH);
|
|
3878
4050
|
const result = decompress.read();
|
|
3879
|
-
const jsonText = result
|
|
4051
|
+
const jsonText = result?.toString() || "";
|
|
3880
4052
|
let formattedMsg;
|
|
3881
4053
|
let jsonMessage;
|
|
3882
4054
|
try {
|
|
@@ -3947,7 +4119,7 @@ var Label_H1_Slash = class extends DecoderPlugin {
|
|
|
3947
4119
|
for (let i = 2; i < fields.length; i++) {
|
|
3948
4120
|
const field = fields[i];
|
|
3949
4121
|
if (field.startsWith("TS")) {
|
|
3950
|
-
H1Helper.
|
|
4122
|
+
H1Helper.processTimeStamp(decodeResult, field.substring(2, 15).split(","));
|
|
3951
4123
|
} else if (field.startsWith("PS")) {
|
|
3952
4124
|
H1Helper.processPS(decodeResult, field.substring(2).split(","));
|
|
3953
4125
|
} else {
|
|
@@ -4102,332 +4274,147 @@ var Label_HX = class extends DecoderPlugin {
|
|
|
4102
4274
|
}
|
|
4103
4275
|
};
|
|
4104
4276
|
|
|
4105
|
-
// lib/
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4277
|
+
// lib/utils/miam.ts
|
|
4278
|
+
import * as Base85 from "base85";
|
|
4279
|
+
import * as zlib2 from "minizlib";
|
|
4280
|
+
import { Buffer as Buffer3 } from "buffer";
|
|
4281
|
+
var MIAMVersion = /* @__PURE__ */ ((MIAMVersion2) => {
|
|
4282
|
+
MIAMVersion2[MIAMVersion2["V1"] = 1] = "V1";
|
|
4283
|
+
MIAMVersion2[MIAMVersion2["V2"] = 2] = "V2";
|
|
4284
|
+
return MIAMVersion2;
|
|
4285
|
+
})(MIAMVersion || {});
|
|
4286
|
+
var MIAMFid = /* @__PURE__ */ ((MIAMFid2) => {
|
|
4287
|
+
MIAMFid2["SingleTransfer"] = "T";
|
|
4288
|
+
MIAMFid2["FileTransferRequest"] = "F";
|
|
4289
|
+
MIAMFid2["FileTransferAccept"] = "K";
|
|
4290
|
+
MIAMFid2["FileSegment"] = "S";
|
|
4291
|
+
MIAMFid2["FileTransferAbort"] = "A";
|
|
4292
|
+
MIAMFid2["XOFFIndication"] = "Y";
|
|
4293
|
+
MIAMFid2["XONIndication"] = "X";
|
|
4294
|
+
return MIAMFid2;
|
|
4295
|
+
})(MIAMFid || {});
|
|
4296
|
+
var MIAMCorePdu = /* @__PURE__ */ ((MIAMCorePdu2) => {
|
|
4297
|
+
MIAMCorePdu2[MIAMCorePdu2["Data"] = 0] = "Data";
|
|
4298
|
+
MIAMCorePdu2[MIAMCorePdu2["Ack"] = 1] = "Ack";
|
|
4299
|
+
MIAMCorePdu2[MIAMCorePdu2["Aloha"] = 2] = "Aloha";
|
|
4300
|
+
MIAMCorePdu2[MIAMCorePdu2["AlohaReply"] = 3] = "AlohaReply";
|
|
4301
|
+
return MIAMCorePdu2;
|
|
4302
|
+
})(MIAMCorePdu || {});
|
|
4303
|
+
var MIAMCoreApp = /* @__PURE__ */ ((MIAMCoreApp2) => {
|
|
4304
|
+
MIAMCoreApp2[MIAMCoreApp2["ACARS2Char"] = 0] = "ACARS2Char";
|
|
4305
|
+
MIAMCoreApp2[MIAMCoreApp2["ACARS4Char"] = 1] = "ACARS4Char";
|
|
4306
|
+
MIAMCoreApp2[MIAMCoreApp2["ACARS6Char"] = 2] = "ACARS6Char";
|
|
4307
|
+
MIAMCoreApp2[MIAMCoreApp2["NonACARS6Char"] = 3] = "NonACARS6Char";
|
|
4308
|
+
return MIAMCoreApp2;
|
|
4309
|
+
})(MIAMCoreApp || {});
|
|
4310
|
+
var MIAMCoreV1CRCLength = 4;
|
|
4311
|
+
var MIAMCoreV2CRCLength = 2;
|
|
4312
|
+
var isMIAMVersion = (x) => Object.values(MIAMVersion).includes(x);
|
|
4313
|
+
var isMIAMFid = (x) => Object.values(MIAMFid).includes(x);
|
|
4314
|
+
var isMIAMCoreApp = (x) => Object.values(MIAMCoreApp).includes(x);
|
|
4315
|
+
var isMIAMCorePdu = (x) => Object.values(MIAMCorePdu).includes(x);
|
|
4316
|
+
var MIAMCoreUtils = class {
|
|
4317
|
+
static AppTypeToAppIdLenTable = {
|
|
4318
|
+
[1 /* V1 */]: {
|
|
4319
|
+
[0 /* ACARS2Char */]: 2,
|
|
4320
|
+
[1 /* ACARS4Char */]: 4,
|
|
4321
|
+
[2 /* ACARS6Char */]: 6,
|
|
4322
|
+
[3 /* NonACARS6Char */]: 6
|
|
4323
|
+
},
|
|
4324
|
+
[2 /* V2 */]: {
|
|
4325
|
+
[0 /* ACARS2Char */]: 2,
|
|
4326
|
+
[1 /* ACARS4Char */]: 4,
|
|
4327
|
+
[2 /* ACARS6Char */]: 6,
|
|
4328
|
+
[3 /* NonACARS6Char */]: 6
|
|
4329
|
+
}
|
|
4330
|
+
};
|
|
4331
|
+
static FidHandlerTable = {
|
|
4332
|
+
["T" /* SingleTransfer */]: (txt) => {
|
|
4333
|
+
if (txt.length < 3) {
|
|
4334
|
+
return {
|
|
4335
|
+
decoded: false,
|
|
4336
|
+
error: "Raw MIAM message too short (" + txt.length + " < 3) "
|
|
4131
4337
|
};
|
|
4132
|
-
decodeResult.raw.vdlFrequency = Number(result.groups.vfreq) / 1e3;
|
|
4133
4338
|
}
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
formattedNetwork = "SITA";
|
|
4141
|
-
}
|
|
4142
|
-
decodeResult.formatted.items = [
|
|
4143
|
-
{
|
|
4144
|
-
type: "network",
|
|
4145
|
-
code: "NETT",
|
|
4146
|
-
label: "Network",
|
|
4147
|
-
value: formattedNetwork
|
|
4148
|
-
},
|
|
4149
|
-
{
|
|
4150
|
-
type: "version",
|
|
4151
|
-
code: "VER",
|
|
4152
|
-
label: "Version",
|
|
4153
|
-
value: decodeResult.raw.version
|
|
4339
|
+
let bpad = txt[0];
|
|
4340
|
+
if ("0123-.".indexOf(bpad) === -1) {
|
|
4341
|
+
return {
|
|
4342
|
+
decoded: false,
|
|
4343
|
+
error: "Invalid body padding value: '" + bpad + "'"
|
|
4344
|
+
};
|
|
4154
4345
|
}
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
code: "GNDSTN",
|
|
4161
|
-
label: "Ground Station",
|
|
4162
|
-
value: `${decodeResult.raw.groundStation.icaoCode}${decodeResult.raw.groundStation.number}`
|
|
4163
|
-
});
|
|
4346
|
+
if ("0123".indexOf(txt[1]) === -1) {
|
|
4347
|
+
return {
|
|
4348
|
+
decoded: false,
|
|
4349
|
+
error: "Invalid header padding value: '" + txt[1] + "'"
|
|
4350
|
+
};
|
|
4164
4351
|
}
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
}
|
|
4352
|
+
const hpad = parseInt(txt[1]);
|
|
4353
|
+
const delimIdx = txt.indexOf("|");
|
|
4354
|
+
if (delimIdx === -1) {
|
|
4355
|
+
return {
|
|
4356
|
+
decoded: false,
|
|
4357
|
+
error: "Raw MIAM message missing header-body delimiter"
|
|
4358
|
+
};
|
|
4172
4359
|
}
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
});
|
|
4360
|
+
const rawHdr = txt.substring(2, delimIdx);
|
|
4361
|
+
if (rawHdr.length === 0) {
|
|
4362
|
+
return {
|
|
4363
|
+
decoded: false,
|
|
4364
|
+
error: "Empty MIAM message header"
|
|
4365
|
+
};
|
|
4180
4366
|
}
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
});
|
|
4367
|
+
let hdr = Base85.decode("<~" + rawHdr + "~>", "ascii85");
|
|
4368
|
+
if (!hdr || hdr.length < hpad) {
|
|
4369
|
+
return {
|
|
4370
|
+
decoded: false,
|
|
4371
|
+
error: "Ascii85 decode failed for MIAM message header"
|
|
4372
|
+
};
|
|
4188
4373
|
}
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
code: "VDLFRQ",
|
|
4202
|
-
label: "VDL Frequency",
|
|
4203
|
-
value: `${decodeResult.raw.vdlFrequency} MHz`
|
|
4204
|
-
});
|
|
4205
|
-
}
|
|
4206
|
-
decodeResult.decoded = true;
|
|
4207
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4208
|
-
return decodeResult;
|
|
4209
|
-
}
|
|
4210
|
-
};
|
|
4211
|
-
|
|
4212
|
-
// lib/plugins/Label_QR.ts
|
|
4213
|
-
var Label_QR = class extends DecoderPlugin {
|
|
4214
|
-
name = "label-qr";
|
|
4215
|
-
qualifiers() {
|
|
4216
|
-
return {
|
|
4217
|
-
labels: ["QR"]
|
|
4218
|
-
};
|
|
4219
|
-
}
|
|
4220
|
-
decode(message, options = {}) {
|
|
4221
|
-
const decodeResult = this.defaultResult();
|
|
4222
|
-
decodeResult.decoder.name = this.name;
|
|
4223
|
-
decodeResult.formatted.description = "ON Report";
|
|
4224
|
-
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
4225
|
-
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
4226
|
-
ResultFormatter.on(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12)));
|
|
4227
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
4228
|
-
decodeResult.decoded = true;
|
|
4229
|
-
if (!decodeResult.remaining.text)
|
|
4230
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4231
|
-
else
|
|
4232
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
4233
|
-
return decodeResult;
|
|
4234
|
-
}
|
|
4235
|
-
};
|
|
4236
|
-
|
|
4237
|
-
// lib/plugins/Label_QP.ts
|
|
4238
|
-
var Label_QP = class extends DecoderPlugin {
|
|
4239
|
-
name = "label-qp";
|
|
4240
|
-
qualifiers() {
|
|
4241
|
-
return {
|
|
4242
|
-
labels: ["QP"]
|
|
4243
|
-
};
|
|
4244
|
-
}
|
|
4245
|
-
decode(message, options = {}) {
|
|
4246
|
-
const decodeResult = this.defaultResult();
|
|
4247
|
-
decodeResult.decoder.name = this.name;
|
|
4248
|
-
decodeResult.formatted.description = "OUT Report";
|
|
4249
|
-
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
4250
|
-
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
4251
|
-
ResultFormatter.out(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12)));
|
|
4252
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
4253
|
-
decodeResult.decoded = true;
|
|
4254
|
-
if (!decodeResult.remaining.text)
|
|
4255
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4256
|
-
else
|
|
4257
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
4258
|
-
return decodeResult;
|
|
4259
|
-
}
|
|
4260
|
-
};
|
|
4261
|
-
|
|
4262
|
-
// lib/plugins/Label_QS.ts
|
|
4263
|
-
var Label_QS = class extends DecoderPlugin {
|
|
4264
|
-
name = "label-qs";
|
|
4265
|
-
qualifiers() {
|
|
4266
|
-
return {
|
|
4267
|
-
labels: ["QS"]
|
|
4268
|
-
};
|
|
4269
|
-
}
|
|
4270
|
-
decode(message, options = {}) {
|
|
4271
|
-
const decodeResult = this.defaultResult();
|
|
4272
|
-
decodeResult.decoder.name = this.name;
|
|
4273
|
-
decodeResult.formatted.description = "IN Report";
|
|
4274
|
-
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
4275
|
-
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
4276
|
-
ResultFormatter.in(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12)));
|
|
4277
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
4278
|
-
decodeResult.decoded = true;
|
|
4279
|
-
if (!decodeResult.remaining.text)
|
|
4280
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4281
|
-
else
|
|
4282
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
4283
|
-
return decodeResult;
|
|
4284
|
-
}
|
|
4285
|
-
};
|
|
4286
|
-
|
|
4287
|
-
// lib/plugins/Label_QQ.ts
|
|
4288
|
-
var Label_QQ = class extends DecoderPlugin {
|
|
4289
|
-
name = "label-qq";
|
|
4290
|
-
qualifiers() {
|
|
4291
|
-
return {
|
|
4292
|
-
labels: ["QQ"]
|
|
4293
|
-
};
|
|
4294
|
-
}
|
|
4295
|
-
decode(message, options = {}) {
|
|
4296
|
-
const decodeResult = this.defaultResult();
|
|
4297
|
-
decodeResult.decoder.name = this.name;
|
|
4298
|
-
decodeResult.message = message;
|
|
4299
|
-
decodeResult.formatted.description = "OFF Report";
|
|
4300
|
-
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
4301
|
-
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
4302
|
-
if (message.text.substring(12, 19) === "\r\n001FE") {
|
|
4303
|
-
decodeResult.raw.day = message.text.substring(19, 21);
|
|
4304
|
-
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(21, 27)));
|
|
4305
|
-
let latdir = message.text.substring(27, 28);
|
|
4306
|
-
let latdeg = Number(message.text.substring(28, 30));
|
|
4307
|
-
let latmin = Number(message.text.substring(30, 34));
|
|
4308
|
-
let londir = message.text.substring(34, 35);
|
|
4309
|
-
let londeg = Number(message.text.substring(35, 38));
|
|
4310
|
-
let lonmin = Number(message.text.substring(38, 42));
|
|
4311
|
-
let pos = {
|
|
4312
|
-
latitude: (latdeg + latmin / 60) * (latdir === "N" ? 1 : -1),
|
|
4313
|
-
longitude: (londeg + lonmin / 60) * (londir === "E" ? 1 : -1)
|
|
4314
|
-
};
|
|
4315
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(42, 45));
|
|
4316
|
-
ResultFormatter.position(decodeResult, pos);
|
|
4317
|
-
if (decodeResult.remaining.text !== "---") {
|
|
4318
|
-
ResultFormatter.groundspeed(decodeResult, Number(message.text.substring(45, 48)));
|
|
4319
|
-
} else {
|
|
4320
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(45, 48));
|
|
4321
|
-
}
|
|
4322
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(48));
|
|
4323
|
-
} else {
|
|
4324
|
-
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12) + "00"));
|
|
4325
|
-
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
4326
|
-
}
|
|
4327
|
-
decodeResult.decoded = true;
|
|
4328
|
-
if (!decodeResult.remaining.text)
|
|
4329
|
-
decodeResult.decoder.decodeLevel = "full";
|
|
4330
|
-
else
|
|
4331
|
-
decodeResult.decoder.decodeLevel = "partial";
|
|
4332
|
-
return decodeResult;
|
|
4333
|
-
}
|
|
4334
|
-
};
|
|
4335
|
-
|
|
4336
|
-
// lib/utils/miam.ts
|
|
4337
|
-
import * as Base85 from "base85";
|
|
4338
|
-
import * as zlib2 from "minizlib";
|
|
4339
|
-
import { Buffer as Buffer2 } from "buffer";
|
|
4340
|
-
var MIAMCoreV1CRCLength = 4;
|
|
4341
|
-
var MIAMCoreV2CRCLength = 2;
|
|
4342
|
-
var MIAMCoreUtils = class {
|
|
4343
|
-
static AppTypeToAppIdLenTable = {
|
|
4344
|
-
1: {
|
|
4345
|
-
[0 /* ACARS2Char */]: 2,
|
|
4346
|
-
[1 /* ACARS4Char */]: 4,
|
|
4347
|
-
[2 /* ACARS6Char */]: 6,
|
|
4348
|
-
[3 /* NonACARS6Char */]: 6
|
|
4349
|
-
},
|
|
4350
|
-
2: {
|
|
4351
|
-
[0 /* ACARS2Char */]: 2,
|
|
4352
|
-
[1 /* ACARS4Char */]: 4,
|
|
4353
|
-
[2 /* ACARS6Char */]: 6,
|
|
4354
|
-
[3 /* NonACARS6Char */]: 6
|
|
4355
|
-
}
|
|
4356
|
-
};
|
|
4357
|
-
static FidHandlerTable = {
|
|
4358
|
-
["T" /* SingleTransfer */]: (txt) => {
|
|
4359
|
-
if (txt.length < 3) {
|
|
4360
|
-
return {
|
|
4361
|
-
decoded: false,
|
|
4362
|
-
error: "Raw MIAM message too short (" + txt.length + " < 3) "
|
|
4363
|
-
};
|
|
4364
|
-
}
|
|
4365
|
-
let bpad = txt[0];
|
|
4366
|
-
if ("0123-.".indexOf(bpad) === -1) {
|
|
4367
|
-
return {
|
|
4368
|
-
decoded: false,
|
|
4369
|
-
error: "Invalid body padding value: '" + bpad + "'"
|
|
4370
|
-
};
|
|
4371
|
-
}
|
|
4372
|
-
if ("0123".indexOf(txt[1]) === -1) {
|
|
4373
|
-
return {
|
|
4374
|
-
decoded: false,
|
|
4375
|
-
error: "Invalid header padding value: '" + txt[1] + "'"
|
|
4376
|
-
};
|
|
4377
|
-
}
|
|
4378
|
-
const hpad = parseInt(txt[1]);
|
|
4379
|
-
const delimIdx = txt.indexOf("|");
|
|
4380
|
-
if (delimIdx === -1) {
|
|
4381
|
-
return {
|
|
4382
|
-
decoded: false,
|
|
4383
|
-
error: "Raw MIAM message missing header-body delimiter"
|
|
4384
|
-
};
|
|
4385
|
-
}
|
|
4386
|
-
const rawHdr = txt.substring(2, delimIdx);
|
|
4387
|
-
if (rawHdr.length === 0) {
|
|
4388
|
-
return {
|
|
4389
|
-
decoded: false,
|
|
4390
|
-
error: "Empty MIAM message header"
|
|
4391
|
-
};
|
|
4392
|
-
}
|
|
4393
|
-
let hdr = Base85.decode("<~" + rawHdr + "~>", "ascii85");
|
|
4394
|
-
if (!hdr || hdr.length < hpad) {
|
|
4395
|
-
return {
|
|
4396
|
-
decoded: false,
|
|
4397
|
-
error: "Ascii85 decode failed for MIAM message header"
|
|
4398
|
-
};
|
|
4399
|
-
}
|
|
4400
|
-
let body = void 0;
|
|
4401
|
-
const rawBody = txt.substring(delimIdx + 1);
|
|
4402
|
-
if (rawBody.length > 0) {
|
|
4403
|
-
if ("0123".indexOf(bpad) >= 0) {
|
|
4404
|
-
const bpadValue = parseInt(bpad);
|
|
4405
|
-
body = Base85.decode("<~" + rawBody + "~>", "ascii85") || void 0;
|
|
4406
|
-
if (body && body.length >= bpadValue) {
|
|
4407
|
-
body = body.subarray(0, body.length - bpadValue);
|
|
4408
|
-
}
|
|
4409
|
-
} else if (bpad === "-") {
|
|
4410
|
-
body = Buffer2.from(rawBody);
|
|
4411
|
-
}
|
|
4374
|
+
let body = void 0;
|
|
4375
|
+
const rawBody = txt.substring(delimIdx + 1);
|
|
4376
|
+
if (rawBody.length > 0) {
|
|
4377
|
+
if ("0123".indexOf(bpad) >= 0) {
|
|
4378
|
+
const bpadValue = parseInt(bpad);
|
|
4379
|
+
body = Base85.decode("<~" + rawBody + "~>", "ascii85") || void 0;
|
|
4380
|
+
if (body && body.length >= bpadValue) {
|
|
4381
|
+
body = body.subarray(0, body.length - bpadValue);
|
|
4382
|
+
}
|
|
4383
|
+
} else if (bpad === "-") {
|
|
4384
|
+
body = Buffer3.from(rawBody);
|
|
4385
|
+
}
|
|
4412
4386
|
}
|
|
4413
4387
|
hdr = hdr.subarray(0, hdr.length - hpad);
|
|
4414
4388
|
const version = hdr.readUInt8(0) & 15;
|
|
4415
4389
|
const pduType = hdr.readUInt8(0) >> 4 & 15;
|
|
4416
|
-
|
|
4417
|
-
|
|
4390
|
+
if (isMIAMVersion(version) && isMIAMCorePdu(pduType)) {
|
|
4391
|
+
const versionPduHandler = this.VersionPduHandlerTable[version][pduType];
|
|
4392
|
+
return versionPduHandler(hdr, body);
|
|
4393
|
+
} else {
|
|
4418
4394
|
return {
|
|
4419
4395
|
decoded: false,
|
|
4420
4396
|
error: "Invalid version and PDU type combination: v=" + version + ", pdu=" + pduType
|
|
4421
4397
|
};
|
|
4422
4398
|
}
|
|
4423
|
-
return versionPduHandler(hdr, body);
|
|
4424
4399
|
},
|
|
4425
|
-
["F" /* FileTransferRequest */]:
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
["
|
|
4429
|
-
|
|
4430
|
-
|
|
4400
|
+
["F" /* FileTransferRequest */]: () => {
|
|
4401
|
+
return { decoded: false, error: "File Transfer Request not implemented" };
|
|
4402
|
+
},
|
|
4403
|
+
["K" /* FileTransferAccept */]: () => {
|
|
4404
|
+
return { decoded: false, error: "File Transfer Accept not implemented" };
|
|
4405
|
+
},
|
|
4406
|
+
["S" /* FileSegment */]: () => {
|
|
4407
|
+
return { decoded: false, error: "File Segment not implemented" };
|
|
4408
|
+
},
|
|
4409
|
+
["A" /* FileTransferAbort */]: () => {
|
|
4410
|
+
return { decoded: false, error: "File Transfer Abort not implemented" };
|
|
4411
|
+
},
|
|
4412
|
+
["Y" /* XOFFIndication */]: () => {
|
|
4413
|
+
return { decoded: false, error: "XOFF Indication not implemented" };
|
|
4414
|
+
},
|
|
4415
|
+
["X" /* XONIndication */]: () => {
|
|
4416
|
+
return { decoded: false, error: "XON Indication not implemented" };
|
|
4417
|
+
}
|
|
4431
4418
|
};
|
|
4432
4419
|
static arincCrc16(buf, seed) {
|
|
4433
4420
|
const crctable = [
|
|
@@ -4961,14 +4948,15 @@ var MIAMCoreUtils = class {
|
|
|
4961
4948
|
}
|
|
4962
4949
|
static parse(txt) {
|
|
4963
4950
|
const fidType = txt[0];
|
|
4964
|
-
|
|
4965
|
-
|
|
4951
|
+
if (isMIAMFid(fidType)) {
|
|
4952
|
+
const handler = this.FidHandlerTable[fidType];
|
|
4953
|
+
return handler(txt.substring(1));
|
|
4954
|
+
} else {
|
|
4966
4955
|
return {
|
|
4967
4956
|
decoded: false,
|
|
4968
4957
|
error: "Unsupported FID type: " + fidType
|
|
4969
4958
|
};
|
|
4970
4959
|
}
|
|
4971
|
-
return handler(txt.substring(1));
|
|
4972
4960
|
}
|
|
4973
4961
|
static corePduDataHandler(version, minHdrSize, crcLen, hdr, body) {
|
|
4974
4962
|
if (hdr.length < minHdrSize) {
|
|
@@ -4983,14 +4971,14 @@ var MIAMCoreUtils = class {
|
|
|
4983
4971
|
let pduAppType = 0;
|
|
4984
4972
|
let pduAppId = "";
|
|
4985
4973
|
let pduCrc = 0;
|
|
4986
|
-
let pduData =
|
|
4974
|
+
let pduData = null;
|
|
4987
4975
|
let pduCrcIsOk = false;
|
|
4988
4976
|
let pduIsComplete = true;
|
|
4989
4977
|
let pduErrors = [];
|
|
4990
4978
|
let tail = void 0;
|
|
4991
4979
|
let msgNum = 0;
|
|
4992
4980
|
let ackOptions = 0;
|
|
4993
|
-
if (version === 1) {
|
|
4981
|
+
if (version === 1 /* V1 */) {
|
|
4994
4982
|
pduSize = hdr.readUInt8(1) << 16 | hdr.readUInt8(2) << 8 | hdr.readUInt8(3);
|
|
4995
4983
|
const msgSize = hdr.length + (body === void 0 ? 0 : body.length);
|
|
4996
4984
|
if (pduSize > msgSize) {
|
|
@@ -5000,7 +4988,7 @@ var MIAMCoreUtils = class {
|
|
|
5000
4988
|
hdr = hdr.subarray(4);
|
|
5001
4989
|
tail = hdr.subarray(0, 7).toString("ascii");
|
|
5002
4990
|
hdr = hdr.subarray(7);
|
|
5003
|
-
} else if (version === 2) {
|
|
4991
|
+
} else if (version === 2 /* V2 */) {
|
|
5004
4992
|
hdr = hdr.subarray(1);
|
|
5005
4993
|
}
|
|
5006
4994
|
msgNum = hdr.readUInt8(0) >> 1 & 127;
|
|
@@ -5010,9 +4998,11 @@ var MIAMCoreUtils = class {
|
|
|
5010
4998
|
pduEncoding = hdr.readUInt8(1) >> 4 & 3;
|
|
5011
4999
|
pduAppType = hdr.readUInt8(1) & 15;
|
|
5012
5000
|
hdr = hdr.subarray(2);
|
|
5013
|
-
let appIdLen
|
|
5014
|
-
if (
|
|
5015
|
-
|
|
5001
|
+
let appIdLen;
|
|
5002
|
+
if (isMIAMCoreApp(pduAppType)) {
|
|
5003
|
+
appIdLen = this.AppTypeToAppIdLenTable[version][pduAppType];
|
|
5004
|
+
} else {
|
|
5005
|
+
if (version === 2 /* V2 */ && (pduAppType & 8) !== 0 && pduAppType !== 13) {
|
|
5016
5006
|
appIdLen = (pduAppType & 7) + 1;
|
|
5017
5007
|
} else {
|
|
5018
5008
|
return {
|
|
@@ -5022,9 +5012,6 @@ var MIAMCoreUtils = class {
|
|
|
5022
5012
|
}
|
|
5023
5013
|
}
|
|
5024
5014
|
const pduIsACARS = [
|
|
5025
|
-
0 /* ACARS2Char */,
|
|
5026
|
-
1 /* ACARS4Char */,
|
|
5027
|
-
2 /* ACARS6Char */,
|
|
5028
5015
|
0 /* ACARS2Char */,
|
|
5029
5016
|
1 /* ACARS4Char */,
|
|
5030
5017
|
2 /* ACARS6Char */
|
|
@@ -5046,7 +5033,7 @@ var MIAMCoreUtils = class {
|
|
|
5046
5033
|
if (body !== void 0 && body.length > 0) {
|
|
5047
5034
|
if ([1 /* Deflate */, 1 /* Deflate */].indexOf(pduCompression) >= 0) {
|
|
5048
5035
|
try {
|
|
5049
|
-
const decompress = new zlib2.InflateRaw({
|
|
5036
|
+
const decompress = new zlib2.InflateRaw({});
|
|
5050
5037
|
decompress.write(body);
|
|
5051
5038
|
decompress.flush(zlib2.constants.Z_SYNC_FLUSH);
|
|
5052
5039
|
pduData = decompress.read();
|
|
@@ -5058,18 +5045,18 @@ var MIAMCoreUtils = class {
|
|
|
5058
5045
|
} else {
|
|
5059
5046
|
pduErrors.push("Unsupported v" + version + " compression type: " + pduCompression);
|
|
5060
5047
|
}
|
|
5061
|
-
if (pduData !==
|
|
5048
|
+
if (pduData !== null) {
|
|
5062
5049
|
const crcAlgoHandlerByVersion = {
|
|
5063
|
-
1: (buf, seed) => {
|
|
5050
|
+
[1 /* V1 */]: (buf, seed) => {
|
|
5064
5051
|
return ~this.arinc665Crc32(buf, seed);
|
|
5065
5052
|
},
|
|
5066
|
-
2: this.arincCrc16
|
|
5053
|
+
[2 /* V2 */]: this.arincCrc16
|
|
5067
5054
|
};
|
|
5068
5055
|
const crcAlgoHandler = crcAlgoHandlerByVersion[version];
|
|
5069
5056
|
if (crcAlgoHandler === void 0) {
|
|
5070
5057
|
return {
|
|
5071
5058
|
decoded: false,
|
|
5072
|
-
|
|
5059
|
+
error: "No CRC handler for v" + version
|
|
5073
5060
|
};
|
|
5074
5061
|
}
|
|
5075
5062
|
const crcCheck = crcAlgoHandler(pduData, 4294967295);
|
|
@@ -5117,25 +5104,315 @@ var MIAMCoreUtils = class {
|
|
|
5117
5104
|
};
|
|
5118
5105
|
}
|
|
5119
5106
|
static VersionPduHandlerTable = {
|
|
5120
|
-
1: {
|
|
5107
|
+
[1 /* V1 */]: {
|
|
5121
5108
|
[0 /* Data */]: (hdr, body) => {
|
|
5122
|
-
return this.corePduDataHandler(1
|
|
5109
|
+
return this.corePduDataHandler(1 /* V1 */, 20, MIAMCoreV1CRCLength, hdr, body);
|
|
5110
|
+
},
|
|
5111
|
+
[1 /* Ack */]: () => {
|
|
5112
|
+
return { decoded: false, error: "v1 Ack PDU not implemented" };
|
|
5113
|
+
},
|
|
5114
|
+
[2 /* Aloha */]: () => {
|
|
5115
|
+
return { decoded: false, error: "v1 Aloha PDU not implemented" };
|
|
5123
5116
|
},
|
|
5124
|
-
[
|
|
5125
|
-
|
|
5126
|
-
|
|
5117
|
+
[3 /* AlohaReply */]: () => {
|
|
5118
|
+
return { decoded: false, error: "v1 AlohaReply PDU not implemented" };
|
|
5119
|
+
}
|
|
5127
5120
|
},
|
|
5128
|
-
2: {
|
|
5121
|
+
[2 /* V2 */]: {
|
|
5129
5122
|
[0 /* Data */]: (hdr, body) => {
|
|
5130
|
-
return this.corePduDataHandler(2
|
|
5123
|
+
return this.corePduDataHandler(2 /* V2 */, 7, MIAMCoreV2CRCLength, hdr, body);
|
|
5124
|
+
},
|
|
5125
|
+
[1 /* Ack */]: () => {
|
|
5126
|
+
return { decoded: false, error: "v2 Ack PDU not implemented" };
|
|
5127
|
+
},
|
|
5128
|
+
[2 /* Aloha */]: () => {
|
|
5129
|
+
return { decoded: false, error: "v2 Aloha PDU not implemented" };
|
|
5131
5130
|
},
|
|
5132
|
-
[
|
|
5133
|
-
|
|
5134
|
-
|
|
5131
|
+
[3 /* AlohaReply */]: () => {
|
|
5132
|
+
return { decoded: false, error: "v2 Aloha reply PDU not implemented" };
|
|
5133
|
+
}
|
|
5135
5134
|
}
|
|
5136
5135
|
};
|
|
5137
5136
|
};
|
|
5138
5137
|
|
|
5138
|
+
// lib/plugins/Label_MA.ts
|
|
5139
|
+
var Label_MA = class extends DecoderPlugin {
|
|
5140
|
+
name = "label-ma";
|
|
5141
|
+
qualifiers() {
|
|
5142
|
+
return {
|
|
5143
|
+
labels: ["MA"]
|
|
5144
|
+
};
|
|
5145
|
+
}
|
|
5146
|
+
decode(message, options = {}) {
|
|
5147
|
+
let decodeResult = this.defaultResult();
|
|
5148
|
+
decodeResult.decoder.name = this.name;
|
|
5149
|
+
decodeResult.message = message;
|
|
5150
|
+
const miamResult = MIAMCoreUtils.parse(message.text);
|
|
5151
|
+
if (miamResult.decoded && miamResult.message.data !== void 0 && miamResult.message.data.crcOk && miamResult.message.data.complete && miamResult.message.data.acars !== void 0) {
|
|
5152
|
+
decodeResult.decoded = true;
|
|
5153
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5154
|
+
ResultFormatter.label(decodeResult, miamResult.message.data.acars.label);
|
|
5155
|
+
if (miamResult.message.data.acars.sublabel) {
|
|
5156
|
+
ResultFormatter.sublabel(decodeResult, miamResult.message.data.acars.sublabel);
|
|
5157
|
+
}
|
|
5158
|
+
if (miamResult.message.data.acars.tail) {
|
|
5159
|
+
ResultFormatter.tail(decodeResult, miamResult.message.data.acars.tail);
|
|
5160
|
+
}
|
|
5161
|
+
const messageText = miamResult.message.data.acars.text;
|
|
5162
|
+
if (messageText) {
|
|
5163
|
+
const decoded = this.decoder.decode({
|
|
5164
|
+
label: miamResult.message.data.acars.label,
|
|
5165
|
+
sublabel: miamResult.message.data.acars.sublabel,
|
|
5166
|
+
text: messageText
|
|
5167
|
+
}, options);
|
|
5168
|
+
if (decoded.decoded) {
|
|
5169
|
+
decodeResult.decoder.decodeLevel = decoded.decoder.decodeLevel;
|
|
5170
|
+
decodeResult.raw = { ...decodeResult.raw, ...decoded.raw };
|
|
5171
|
+
decodeResult.formatted.items.push(...decoded.formatted.items);
|
|
5172
|
+
} else {
|
|
5173
|
+
ResultFormatter.text(decodeResult, messageText);
|
|
5174
|
+
}
|
|
5175
|
+
message.text = messageText;
|
|
5176
|
+
}
|
|
5177
|
+
message.label = miamResult.message.data.acars.label;
|
|
5178
|
+
message.sublabel = miamResult.message.data.acars.sublabel;
|
|
5179
|
+
return decodeResult;
|
|
5180
|
+
}
|
|
5181
|
+
return decodeResult;
|
|
5182
|
+
}
|
|
5183
|
+
};
|
|
5184
|
+
|
|
5185
|
+
// lib/plugins/Label_SQ.ts
|
|
5186
|
+
var Label_SQ = class extends DecoderPlugin {
|
|
5187
|
+
name = "label-sq";
|
|
5188
|
+
qualifiers() {
|
|
5189
|
+
return {
|
|
5190
|
+
labels: ["SQ"]
|
|
5191
|
+
};
|
|
5192
|
+
}
|
|
5193
|
+
decode(message, options = {}) {
|
|
5194
|
+
const decodeResult = this.defaultResult();
|
|
5195
|
+
decodeResult.decoder.name = this.name;
|
|
5196
|
+
decodeResult.raw.preamble = message.text.substring(0, 4);
|
|
5197
|
+
decodeResult.raw.version = message.text.substring(1, 2);
|
|
5198
|
+
decodeResult.raw.network = message.text.substring(3, 4);
|
|
5199
|
+
if (decodeResult.raw.version === "2") {
|
|
5200
|
+
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+)\/.*/;
|
|
5201
|
+
const result = message.text.match(regex);
|
|
5202
|
+
if (result?.groups && result.length >= 8) {
|
|
5203
|
+
decodeResult.raw.groundStation = {
|
|
5204
|
+
number: result.groups.station,
|
|
5205
|
+
iataCode: result.groups.iata,
|
|
5206
|
+
icaoCode: result.groups.icao,
|
|
5207
|
+
coordinates: {
|
|
5208
|
+
latitude: Number(result.groups.lat) / 100 * (result.groups.latd === "S" ? -1 : 1),
|
|
5209
|
+
longitude: Number(result.groups.lng) / 100 * (result.groups.lngd === "W" ? -1 : 1)
|
|
5210
|
+
}
|
|
5211
|
+
};
|
|
5212
|
+
decodeResult.raw.vdlFrequency = Number(result.groups.vfreq) / 1e3;
|
|
5213
|
+
}
|
|
5214
|
+
}
|
|
5215
|
+
decodeResult.formatted.description = "Ground Station Squitter";
|
|
5216
|
+
var formattedNetwork = "Unknown";
|
|
5217
|
+
if (decodeResult.raw.network == "A") {
|
|
5218
|
+
formattedNetwork = "ARINC";
|
|
5219
|
+
} else if (decodeResult.raw.network == "S") {
|
|
5220
|
+
formattedNetwork = "SITA";
|
|
5221
|
+
}
|
|
5222
|
+
decodeResult.formatted.items = [
|
|
5223
|
+
{
|
|
5224
|
+
type: "network",
|
|
5225
|
+
code: "NETT",
|
|
5226
|
+
label: "Network",
|
|
5227
|
+
value: formattedNetwork
|
|
5228
|
+
},
|
|
5229
|
+
{
|
|
5230
|
+
type: "version",
|
|
5231
|
+
code: "VER",
|
|
5232
|
+
label: "Version",
|
|
5233
|
+
value: decodeResult.raw.version
|
|
5234
|
+
}
|
|
5235
|
+
];
|
|
5236
|
+
if (decodeResult.raw.groundStation) {
|
|
5237
|
+
if (decodeResult.raw.groundStation.icaoCode && decodeResult.raw.groundStation.number) {
|
|
5238
|
+
decodeResult.formatted.items.push({
|
|
5239
|
+
type: "ground_station",
|
|
5240
|
+
code: "GNDSTN",
|
|
5241
|
+
label: "Ground Station",
|
|
5242
|
+
value: `${decodeResult.raw.groundStation.icaoCode}${decodeResult.raw.groundStation.number}`
|
|
5243
|
+
});
|
|
5244
|
+
}
|
|
5245
|
+
if (decodeResult.raw.groundStation.iataCode) {
|
|
5246
|
+
decodeResult.formatted.items.push({
|
|
5247
|
+
type: "iataCode",
|
|
5248
|
+
code: "IATA",
|
|
5249
|
+
label: "IATA",
|
|
5250
|
+
value: decodeResult.raw.groundStation.iataCode
|
|
5251
|
+
});
|
|
5252
|
+
}
|
|
5253
|
+
if (decodeResult.raw.groundStation.icaoCode) {
|
|
5254
|
+
decodeResult.formatted.items.push({
|
|
5255
|
+
type: "icaoCode",
|
|
5256
|
+
code: "ICAO",
|
|
5257
|
+
label: "ICAO",
|
|
5258
|
+
value: decodeResult.raw.groundStation.icaoCode
|
|
5259
|
+
});
|
|
5260
|
+
}
|
|
5261
|
+
if (decodeResult.raw.groundStation.coordinates.latitude) {
|
|
5262
|
+
decodeResult.formatted.items.push({
|
|
5263
|
+
type: "coordinates",
|
|
5264
|
+
code: "COORD",
|
|
5265
|
+
label: "Ground Station Location",
|
|
5266
|
+
value: `${decodeResult.raw.groundStation.coordinates.latitude}, ${decodeResult.raw.groundStation.coordinates.longitude}`
|
|
5267
|
+
});
|
|
5268
|
+
}
|
|
5269
|
+
if (decodeResult.raw.groundStation.airport) {
|
|
5270
|
+
decodeResult.formatted.items.push({
|
|
5271
|
+
type: "airport",
|
|
5272
|
+
code: "APT",
|
|
5273
|
+
label: "Airport",
|
|
5274
|
+
value: `${decodeResult.raw.groundStation.airport.name} (${decodeResult.raw.groundStation.airport.icao}) in ${decodeResult.raw.groundStation.airport.location}`
|
|
5275
|
+
});
|
|
5276
|
+
}
|
|
5277
|
+
}
|
|
5278
|
+
if (decodeResult.raw.vdlFrequency) {
|
|
5279
|
+
decodeResult.formatted.items.push({
|
|
5280
|
+
type: "vdlFrequency",
|
|
5281
|
+
code: "VDLFRQ",
|
|
5282
|
+
label: "VDL Frequency",
|
|
5283
|
+
value: `${decodeResult.raw.vdlFrequency} MHz`
|
|
5284
|
+
});
|
|
5285
|
+
}
|
|
5286
|
+
decodeResult.decoded = true;
|
|
5287
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5288
|
+
return decodeResult;
|
|
5289
|
+
}
|
|
5290
|
+
};
|
|
5291
|
+
|
|
5292
|
+
// lib/plugins/Label_QR.ts
|
|
5293
|
+
var Label_QR = class extends DecoderPlugin {
|
|
5294
|
+
name = "label-qr";
|
|
5295
|
+
qualifiers() {
|
|
5296
|
+
return {
|
|
5297
|
+
labels: ["QR"]
|
|
5298
|
+
};
|
|
5299
|
+
}
|
|
5300
|
+
decode(message, options = {}) {
|
|
5301
|
+
const decodeResult = this.defaultResult();
|
|
5302
|
+
decodeResult.decoder.name = this.name;
|
|
5303
|
+
decodeResult.formatted.description = "ON Report";
|
|
5304
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
5305
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
5306
|
+
ResultFormatter.on(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12)));
|
|
5307
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
5308
|
+
decodeResult.decoded = true;
|
|
5309
|
+
if (!decodeResult.remaining.text)
|
|
5310
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5311
|
+
else
|
|
5312
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5313
|
+
return decodeResult;
|
|
5314
|
+
}
|
|
5315
|
+
};
|
|
5316
|
+
|
|
5317
|
+
// lib/plugins/Label_QP.ts
|
|
5318
|
+
var Label_QP = class extends DecoderPlugin {
|
|
5319
|
+
name = "label-qp";
|
|
5320
|
+
qualifiers() {
|
|
5321
|
+
return {
|
|
5322
|
+
labels: ["QP"]
|
|
5323
|
+
};
|
|
5324
|
+
}
|
|
5325
|
+
decode(message, options = {}) {
|
|
5326
|
+
const decodeResult = this.defaultResult();
|
|
5327
|
+
decodeResult.decoder.name = this.name;
|
|
5328
|
+
decodeResult.formatted.description = "OUT Report";
|
|
5329
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
5330
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
5331
|
+
ResultFormatter.out(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12)));
|
|
5332
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
5333
|
+
decodeResult.decoded = true;
|
|
5334
|
+
if (!decodeResult.remaining.text)
|
|
5335
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5336
|
+
else
|
|
5337
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5338
|
+
return decodeResult;
|
|
5339
|
+
}
|
|
5340
|
+
};
|
|
5341
|
+
|
|
5342
|
+
// lib/plugins/Label_QS.ts
|
|
5343
|
+
var Label_QS = class extends DecoderPlugin {
|
|
5344
|
+
name = "label-qs";
|
|
5345
|
+
qualifiers() {
|
|
5346
|
+
return {
|
|
5347
|
+
labels: ["QS"]
|
|
5348
|
+
};
|
|
5349
|
+
}
|
|
5350
|
+
decode(message, options = {}) {
|
|
5351
|
+
const decodeResult = this.defaultResult();
|
|
5352
|
+
decodeResult.decoder.name = this.name;
|
|
5353
|
+
decodeResult.formatted.description = "IN Report";
|
|
5354
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
5355
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
5356
|
+
ResultFormatter.in(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12)));
|
|
5357
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
5358
|
+
decodeResult.decoded = true;
|
|
5359
|
+
if (!decodeResult.remaining.text)
|
|
5360
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5361
|
+
else
|
|
5362
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5363
|
+
return decodeResult;
|
|
5364
|
+
}
|
|
5365
|
+
};
|
|
5366
|
+
|
|
5367
|
+
// lib/plugins/Label_QQ.ts
|
|
5368
|
+
var Label_QQ = class extends DecoderPlugin {
|
|
5369
|
+
name = "label-qq";
|
|
5370
|
+
qualifiers() {
|
|
5371
|
+
return {
|
|
5372
|
+
labels: ["QQ"]
|
|
5373
|
+
};
|
|
5374
|
+
}
|
|
5375
|
+
decode(message, options = {}) {
|
|
5376
|
+
const decodeResult = this.defaultResult();
|
|
5377
|
+
decodeResult.decoder.name = this.name;
|
|
5378
|
+
decodeResult.message = message;
|
|
5379
|
+
decodeResult.formatted.description = "OFF Report";
|
|
5380
|
+
ResultFormatter.departureAirport(decodeResult, message.text.substring(0, 4));
|
|
5381
|
+
ResultFormatter.arrivalAirport(decodeResult, message.text.substring(4, 8));
|
|
5382
|
+
if (message.text.substring(12, 19) === "\r\n001FE") {
|
|
5383
|
+
decodeResult.raw.day = message.text.substring(19, 21);
|
|
5384
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(21, 27)));
|
|
5385
|
+
let latdir = message.text.substring(27, 28);
|
|
5386
|
+
let latdeg = Number(message.text.substring(28, 30));
|
|
5387
|
+
let latmin = Number(message.text.substring(30, 34));
|
|
5388
|
+
let londir = message.text.substring(34, 35);
|
|
5389
|
+
let londeg = Number(message.text.substring(35, 38));
|
|
5390
|
+
let lonmin = Number(message.text.substring(38, 42));
|
|
5391
|
+
let pos = {
|
|
5392
|
+
latitude: (latdeg + latmin / 60) * (latdir === "N" ? 1 : -1),
|
|
5393
|
+
longitude: (londeg + lonmin / 60) * (londir === "E" ? 1 : -1)
|
|
5394
|
+
};
|
|
5395
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(42, 45));
|
|
5396
|
+
ResultFormatter.position(decodeResult, pos);
|
|
5397
|
+
if (decodeResult.remaining.text !== "---") {
|
|
5398
|
+
ResultFormatter.groundspeed(decodeResult, Number(message.text.substring(45, 48)));
|
|
5399
|
+
} else {
|
|
5400
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(45, 48));
|
|
5401
|
+
}
|
|
5402
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(48));
|
|
5403
|
+
} else {
|
|
5404
|
+
ResultFormatter.off(decodeResult, DateTimeUtils.convertHHMMSSToTod(message.text.substring(8, 12) + "00"));
|
|
5405
|
+
ResultFormatter.unknown(decodeResult, message.text.substring(12));
|
|
5406
|
+
}
|
|
5407
|
+
decodeResult.decoded = true;
|
|
5408
|
+
if (!decodeResult.remaining.text)
|
|
5409
|
+
decodeResult.decoder.decodeLevel = "full";
|
|
5410
|
+
else
|
|
5411
|
+
decodeResult.decoder.decodeLevel = "partial";
|
|
5412
|
+
return decodeResult;
|
|
5413
|
+
}
|
|
5414
|
+
};
|
|
5415
|
+
|
|
5139
5416
|
// lib/MessageDecoder.ts
|
|
5140
5417
|
var MessageDecoder = class {
|
|
5141
5418
|
name;
|
|
@@ -5203,6 +5480,7 @@ var MessageDecoder = class {
|
|
|
5203
5480
|
this.registerPlugin(new Label_83(this));
|
|
5204
5481
|
this.registerPlugin(new Label_8E(this));
|
|
5205
5482
|
this.registerPlugin(new Label_1M_Slash(this));
|
|
5483
|
+
this.registerPlugin(new Label_MA(this));
|
|
5206
5484
|
this.registerPlugin(new Label_SQ(this));
|
|
5207
5485
|
this.registerPlugin(new Label_QP(this));
|
|
5208
5486
|
this.registerPlugin(new Label_QQ(this));
|
|
@@ -5215,18 +5493,6 @@ var MessageDecoder = class {
|
|
|
5215
5493
|
return true;
|
|
5216
5494
|
}
|
|
5217
5495
|
decode(message, options = {}) {
|
|
5218
|
-
if (message.label === "MA") {
|
|
5219
|
-
const decodeResult = MIAMCoreUtils.parse(message.text);
|
|
5220
|
-
if (decodeResult.decoded && decodeResult.message.data !== void 0 && decodeResult.message.data.crcOk && decodeResult.message.data.complete && decodeResult.message.data.acars !== void 0) {
|
|
5221
|
-
message = {
|
|
5222
|
-
...message,
|
|
5223
|
-
label: decodeResult.message.data.acars.label,
|
|
5224
|
-
...decodeResult.message.data.acars.sublabel ? { sublabel: decodeResult.message.data.acars.sublabel } : {},
|
|
5225
|
-
...decodeResult.message.data.acars.mfi ? { mfi: decodeResult.message.data.acars.mfi } : {},
|
|
5226
|
-
...decodeResult.message.data.acars.text ? { text: decodeResult.message.data.acars.text } : {}
|
|
5227
|
-
};
|
|
5228
|
-
}
|
|
5229
|
-
}
|
|
5230
5496
|
const usablePlugins = this.plugins.filter((plugin) => {
|
|
5231
5497
|
const qualifiers = plugin.qualifiers();
|
|
5232
5498
|
if (qualifiers.labels.includes(message.label)) {
|
|
@@ -5276,11 +5542,6 @@ var MessageDecoder = class {
|
|
|
5276
5542
|
}
|
|
5277
5543
|
return result;
|
|
5278
5544
|
}
|
|
5279
|
-
lookupAirportByIata(iata) {
|
|
5280
|
-
const airportsArray = [];
|
|
5281
|
-
const airport = airportsArray.filter((e) => e.iata === iata);
|
|
5282
|
-
return airport;
|
|
5283
|
-
}
|
|
5284
5545
|
};
|
|
5285
5546
|
export {
|
|
5286
5547
|
IcaoDecoder,
|