@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.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
- results.latitude = Number(stringCoords.substring(1, 6)) / 1e3 * _CoordinateUtils.getDirection(firstChar);
190
- results.longitude = Number(longitudeChars) / 1e3 * _CoordinateUtils.getDirection(middleChar);
191
- } else {
192
- return;
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 results;
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
- results.latitude = (latDeg + latMin / 60) * _CoordinateUtils.getDirection(firstChar);
217
- results.longitude = (lonDeg + lonMin / 60) * _CoordinateUtils.getDirection(middleChar);
218
- } else {
219
- return;
214
+ return {
215
+ latitude: (latDeg + latMin / 60) * _CoordinateUtils.getDirection(firstChar),
216
+ longitude: (lonDeg + lonMin / 60) * _CoordinateUtils.getDirection(middleChar)
217
+ };
220
218
  }
221
- return results;
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
- if (fields[i].startsWith("FN")) {
1622
- decodeResult.raw.flight_number = fields[i].substring(2);
1623
- } else if (fields[i].startsWith("SN")) {
1624
- decodeResult.raw.serial_number = fields[i].substring(2);
1625
- } else if (fields[i].startsWith("DC")) {
1626
- processDC(decodeResult, fields[i].substring(2).split(","));
1627
- } else if (fields[i].startsWith("TS")) {
1628
- _H1Helper.processTS(decodeResult, fields[i].substring(2).split(","));
1629
- } else if (fields[i].startsWith("PS")) {
1630
- _H1Helper.processPS(decodeResult, fields[i].substring(2).split(","));
1631
- } else if (fields[i].startsWith("DT")) {
1632
- const data2 = fields[i].substring(2).split(",");
1633
- processDT(decodeResult, data2);
1634
- } else if (fields[i].startsWith("ID")) {
1635
- processIdentification(decodeResult, fields[i].substring(2).split(","));
1636
- } else if (fields[i].startsWith("LR")) {
1637
- const data2 = fields[i].substring(2).split(",");
1638
- processLR(decodeResult, data2);
1639
- } else if (fields[i].startsWith("RI") || fields[i].startsWith("RF") || fields[i].startsWith("RP")) {
1640
- FlightPlanUtils.processFlightPlan(decodeResult, fields[i].split(":"));
1641
- } else if (fields[i].startsWith("PR")) {
1642
- ResultFormatter.unknown(decodeResult, fields[i], "/");
1643
- } else if (fields[i].startsWith("AF")) {
1644
- processAirField(decodeResult, fields[i].substring(2).split(","));
1645
- } else if (fields[i].startsWith("TD")) {
1646
- processTimeOfDeparture(decodeResult, fields[i].substring(2).split(","));
1647
- } else if (fields[i].startsWith("FX")) {
1648
- ResultFormatter.freetext(decodeResult, fields[i].substring(2));
1649
- } else if (fields[i].startsWith("ET")) {
1650
- if (fields[i].length === 7) {
1651
- ResultFormatter.day(decodeResult, Number(fields[i].substring(2, 3)));
1652
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(3)));
1653
- } else if (fields[i].length === 8) {
1654
- ResultFormatter.day(decodeResult, Number(fields[i].substring(2, 4)));
1655
- ResultFormatter.eta(decodeResult, DateTimeUtils.convertHHMMSSToTod(fields[i].substring(4)));
1656
- } else {
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
- if (decodeResult.formatted.items.length > 0) {
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 processTS(decodeResult, data) {
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 processLR(decodeResult, data) {
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 parseMessageType(decodeResult, messageType) {
1793
- const parts = messageType.split("#");
1794
- if (parts.length == 1) {
1795
- if (parts[0].startsWith("POS")) {
1796
- H1Helper.processPosition(decodeResult, parts[0].substring(3).split(","));
1797
- return processMessageType(decodeResult, "POS");
1798
- } else if (parts[0].length === 13) {
1799
- if (processMessageType(decodeResult, parts[0].substring(10))) {
1800
- ResultFormatter.unknown(decodeResult, parts[0].substring(0, 4));
1801
- ResultFormatter.flightNumber(decodeResult, parts[0].slice(4, 10));
1802
- return true;
1803
- }
1804
- }
1805
- return processMessageType(decodeResult, parts[0].substring(0, 3));
1806
- } else if (parts.length == 2) {
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, messageType);
1819
- return false;
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 Report";
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 processDC(decodeResult, data) {
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 decoded = H1Helper.decodeH1Message(decodeResult, msg);
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 decoded = H1Helper.decodeH1Message(decodeResult, msg);
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 decoded = H1Helper.decodeH1Message(decodeResult, msg);
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({ windowBits: 15 });
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.toString();
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.processTS(decodeResult, field.substring(2, 15).split(","));
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/plugins/Label_SQ.ts
4143
- var Label_SQ = class extends DecoderPlugin {
4144
- name = "label-sq";
4145
- qualifiers() {
4146
- return {
4147
- labels: ["SQ"]
4148
- };
4149
- }
4150
- decode(message, options = {}) {
4151
- const decodeResult = this.defaultResult();
4152
- decodeResult.decoder.name = this.name;
4153
- decodeResult.raw.preamble = message.text.substring(0, 4);
4154
- decodeResult.raw.version = message.text.substring(1, 2);
4155
- decodeResult.raw.network = message.text.substring(3, 4);
4156
- if (decodeResult.raw.version === "2") {
4157
- 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+)\/.*/;
4158
- const result = message.text.match(regex);
4159
- if (result?.groups && result.length >= 8) {
4160
- decodeResult.raw.groundStation = {
4161
- number: result.groups.station,
4162
- iataCode: result.groups.iata,
4163
- icaoCode: result.groups.icao,
4164
- coordinates: {
4165
- latitude: Number(result.groups.lat) / 100 * (result.groups.latd === "S" ? -1 : 1),
4166
- longitude: Number(result.groups.lng) / 100 * (result.groups.lngd === "W" ? -1 : 1)
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
- decodeResult.formatted.description = "Ground Station Squitter";
4173
- var formattedNetwork = "Unknown";
4174
- if (decodeResult.raw.network == "A") {
4175
- formattedNetwork = "ARINC";
4176
- } else if (decodeResult.raw.network == "S") {
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
- if (decodeResult.raw.groundStation) {
4194
- if (decodeResult.raw.groundStation.icaoCode && decodeResult.raw.groundStation.number) {
4195
- decodeResult.formatted.items.push({
4196
- type: "ground_station",
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
- if (decodeResult.raw.groundStation.iataCode) {
4203
- decodeResult.formatted.items.push({
4204
- type: "iataCode",
4205
- code: "IATA",
4206
- label: "IATA",
4207
- value: decodeResult.raw.groundStation.iataCode
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
- if (decodeResult.raw.groundStation.icaoCode) {
4211
- decodeResult.formatted.items.push({
4212
- type: "icaoCode",
4213
- code: "ICAO",
4214
- label: "ICAO",
4215
- value: decodeResult.raw.groundStation.icaoCode
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
- if (decodeResult.raw.groundStation.coordinates.latitude) {
4219
- decodeResult.formatted.items.push({
4220
- type: "coordinates",
4221
- code: "COORD",
4222
- label: "Ground Station Location",
4223
- value: `${decodeResult.raw.groundStation.coordinates.latitude}, ${decodeResult.raw.groundStation.coordinates.longitude}`
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
- if (decodeResult.raw.groundStation.airport) {
4227
- decodeResult.formatted.items.push({
4228
- type: "airport",
4229
- code: "APT",
4230
- label: "Airport",
4231
- value: `${decodeResult.raw.groundStation.airport.name} (${decodeResult.raw.groundStation.airport.icao}) in ${decodeResult.raw.groundStation.airport.location}`
4232
- });
4233
- }
4234
- }
4235
- if (decodeResult.raw.vdlFrequency) {
4236
- decodeResult.formatted.items.push({
4237
- type: "vdlFrequency",
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
- const versionPduHandler = this.VersionPduHandlerTable[version][pduType];
4454
- if (versionPduHandler === void 0) {
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 */]: void 0,
4463
- ["K" /* FileTransferAccept */]: void 0,
4464
- ["S" /* FileSegment */]: void 0,
4465
- ["A" /* FileTransferAbort */]: void 0,
4466
- ["Y" /* XOFFIndication */]: void 0,
4467
- ["X" /* XONIndication */]: void 0
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
- const handler = this.FidHandlerTable[fidType];
5002
- if (handler === void 0) {
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 = void 0;
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 = this.AppTypeToAppIdLenTable[version][pduAppType];
5051
- if (appIdLen === void 0) {
5052
- if (version === 2 && (pduAppType & 8) !== 0 && pduAppType !== 13) {
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({ windowBits: 15 });
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 !== void 0) {
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
- errors: "No CRC handler for v" + version
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, 20, MIAMCoreV1CRCLength, hdr, body);
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
- [1 /* Ack */]: void 0,
5162
- [2 /* Aloha */]: void 0,
5163
- [3 /* AlohaReply */]: void 0
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, 7, MIAMCoreV2CRCLength, hdr, body);
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
- [1 /* Ack */]: void 0,
5170
- [2 /* Aloha */]: void 0,
5171
- [3 /* AlohaReply */]: void 0
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 = {